43b164df2c5fc58681dfdf12222712717a5ba228
[asdcplib.git] / src / KM_fileio.h
1 /*
2 Copyright (c) 2004-2006, John Hurst
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9    notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11    notice, this list of conditions and the following disclaimer in the
12    documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14    derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27   /*! \file    KM_fileio.h
28     \version $Id$
29     \brief   portable file i/o
30   */
31
32 #ifndef _KM_FILEIO_H_
33 #define _KM_FILEIO_H_
34
35 #include <KM_util.h>
36 #include <string>
37
38 #ifdef KM_WIN32
39 # include <io.h>
40 #else
41 # include <dirent.h>
42 # include <unistd.h>
43 # include <time.h>
44 # include <sys/types.h>
45 #include <regex.h>
46 #endif
47
48 #include <sys/stat.h>
49
50
51
52 namespace Kumu
53 {
54   //
55   class DirScanner
56     {
57     public:
58 #ifdef KM_WIN32
59       __int64               m_Handle;
60       struct _finddatai64_t m_FileInfo;
61 #else
62       DIR*       m_Handle;
63 #endif
64
65       DirScanner()  {};
66       ~DirScanner() { Close(); }
67
68       Result_t Open(const char*);
69       Result_t Close();
70       Result_t GetNext(char*);
71     };
72
73 #ifdef KM_WIN32
74   typedef __int64  fsize_t;
75   typedef __int64  fpos_t;
76
77   enum SeekPos_t {
78     SP_BEGIN = FILE_BEGIN,
79     SP_POS   = FILE_CURRENT,
80     SP_END   = FILE_END
81   };
82 #else
83   typedef off_t    fsize_t;
84   typedef off_t    fpos_t;
85   typedef int      HANDLE;
86   const HANDLE INVALID_HANDLE_VALUE = -1L;
87
88   enum SeekPos_t {
89     SP_BEGIN = SEEK_SET,
90     SP_POS   = SEEK_CUR,
91     SP_END   = SEEK_END
92   };
93 #endif
94
95   const ui32_t Kilobyte = 1024;
96   const ui32_t Megabyte = Kilobyte * Kilobyte;
97   const ui32_t Gigabyte = Megabyte * Kilobyte;
98
99   const ui32_t MaxFilePath = Kilobyte;
100
101   // Path Manglers
102   //
103   typedef std::list<std::string> PathCompList_t; // a list of path components
104   typedef std::list<std::string> PathList_t; // a list of paths
105
106   bool        PathExists(const std::string& Path); // true if the path exists in the filesystem
107   bool        PathIsFile(const std::string& Path); // true if the path exists in the filesystem and is a file
108   bool        PathIsDirectory(const std::string& Path); // true if the path exists in the filesystem and is a directory
109   fsize_t     FileSize(const std::string& Path); // returns the size of a regular file, 0 for a directory or device
110   bool        PathsAreEquivalent(const std::string& lhs, const std::string& rhs); // true if paths point to the same filesystem entry
111
112   // split and reassemble pats as lists of path components
113   PathCompList_t& PathToComponents(const std::string& Path, PathCompList_t& CList, char separator = '/'); // removes '//'
114   std::string ComponentsToPath(const PathCompList_t& CList, char separator = '/');
115   std::string ComponentsToAbsolutePath(const PathCompList_t& CList, char separator = '/'); // add separator to the front
116   bool        PathHasComponents(const std::string& Path, char separator = '/'); // true if paths starts with separator
117
118   bool        PathIsAbsolute(const std::string& Path, char separator = '/'); // true if path begins with separator
119   std::string PathMakeAbsolute(const std::string& Path, char separator = '/'); // compute position of relative path using getcwd()
120   std::string PathMakeLocal(const std::string& Path, const std::string& Parent); // remove Parent from front of Path, if it exists
121   std::string PathMakeCanonical(const std::string& Path, char separator = '/'); // remove '.' and '..'
122
123   std::string PathBasename(const std::string& Path, char separator = '/'); // returns right-most path element (list back())
124   std::string PathDirname(const std::string& Path, char separator = '/'); // returns everything but the right-most element
125   std::string PathGetExtension(const std::string& Path); // returns everything in the right-most element following the right-most '.'
126   std::string PathSetExtension(const std::string& Path, const std::string& Extension); // empty extension removes '.' as well
127
128   //
129   //
130   class IPathMatch
131   {
132   public:
133     virtual ~IPathMatch() {}
134     virtual bool Match(const std::string& s) const = 0;
135   };
136
137  class PathMatchAny : public IPathMatch
138   {
139   public:
140     virtual ~PathMatchAny() {}
141     inline bool Match(const std::string& s) const { return true; }
142   };
143
144  class PathMatchRegex : public IPathMatch
145   {
146     regex_t m_regex;
147     PathMatchRegex();
148     const PathMatchRegex& operator=(const PathMatchRegex&);
149
150   public:
151     PathMatchRegex(const std::string& Pattern);
152     PathMatchRegex(const PathMatchRegex&);
153     virtual ~PathMatchRegex();
154     bool Match(const std::string& s) const;
155   };
156
157  class PathMatchGlob : public IPathMatch
158   {
159     regex_t m_regex;
160     PathMatchGlob();
161     const PathMatchGlob& operator=(const PathMatchGlob&);
162
163   public:
164     PathMatchGlob(const std::string& Pattern);
165     PathMatchGlob(const PathMatchGlob&);
166     virtual ~PathMatchGlob();
167     bool Match(const std::string& s) const;
168   };
169
170   // Search all paths in SearchPaths for filenames matching Pattern (no directories are returned).
171   // Put results in FoundPaths. Returns after first find if one_shot is true.
172   PathList_t& FindInPath(const IPathMatch& Pattern, const std::string& SearchDir,
173                          PathList_t& FoundPaths, bool one_shot, char separator);
174
175   PathList_t& FindInPaths(const IPathMatch& Pattern, const PathList_t& SearchPaths,
176                           PathList_t& FoundPaths, bool one_shot = false, char separator = '/');
177
178
179   // Instant IO for strings
180   //
181   // Reads an entire file into a string.
182   Result_t ReadFileIntoString(const char* filename, std::string& outString, ui32_t max_size = 8 * Megabyte);
183
184   // Writes a string to a file, overwrites the existing file if present.
185   Result_t WriteStringIntoFile(const char* filename, const std::string& inString);
186
187   //
188   class FileReader
189     {
190       KM_NO_COPY_CONSTRUCT(FileReader);
191
192     protected:
193       std::string m_Filename;
194       HANDLE      m_Handle;
195
196     public:
197       FileReader() : m_Handle(INVALID_HANDLE_VALUE) {}
198       virtual ~FileReader() { Close(); }
199
200       Result_t OpenRead(const char*) const;                          // open the file for reading
201       Result_t Close() const;                                        // close the file
202       fsize_t  Size() const;                                         // returns the file's current size
203       Result_t Seek(Kumu::fpos_t = 0, SeekPos_t = SP_BEGIN) const;   // move the file pointer
204       Result_t Tell(Kumu::fpos_t* pos) const;                        // report the file pointer's location
205       Result_t Read(byte_t*, ui32_t, ui32_t* = 0) const;             // read a buffer of data
206
207       inline Kumu::fpos_t Tell() const                               // report the file pointer's location
208         {
209           Kumu::fpos_t tmp_pos;
210           Tell(&tmp_pos);
211           return tmp_pos;
212         }
213
214       inline bool IsOpen() {                                         // returns true if the file is open
215         return (m_Handle != INVALID_HANDLE_VALUE);
216       }
217     };
218
219   //
220   class FileWriter : public FileReader
221     {
222       class h__iovec;
223       mem_ptr<h__iovec>  m_IOVec;
224       KM_NO_COPY_CONSTRUCT(FileWriter);
225
226     public:
227       FileWriter();
228       virtual ~FileWriter();
229
230       Result_t OpenWrite(const char*);                               // open a new file, overwrites existing
231       Result_t OpenModify(const char*);                              // open a file for read/write
232
233       // this part of the interface takes advantage of the iovec structure on
234       // platforms that support it. For each call to Writev(const byte_t*, ui32_t, ui32_t*),
235       // the given buffer is added to an internal iovec struct. All items on the list
236       // are written to disk by a call to Writev();
237       Result_t Writev(const byte_t*, ui32_t);                       // queue buffer for "gather" write
238       Result_t Writev(ui32_t* = 0);                                 // write all queued buffers
239
240       // if you call this while there are unwritten items on the iovec list,
241       // the iovec list will be written to disk before the given buffer,as though
242       // you had called Writev() first.
243       Result_t Write(const byte_t*, ui32_t, ui32_t* = 0);            // write buffer to disk
244    };
245
246 } // namespace Kumu
247
248
249 #endif // _KM_FILEIO_H_
250
251
252 //
253 // end KM_fileio.h
254 //