Forgot a fix.
[asdcplib.git] / src / KM_fileio.h
1 /*
2 Copyright (c) 2004-2007, 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 #ifndef KM_WIN32
145  class PathMatchRegex : public IPathMatch
146   {
147     regex_t m_regex;
148     PathMatchRegex();
149     const PathMatchRegex& operator=(const PathMatchRegex&);
150
151   public:
152     PathMatchRegex(const std::string& Pattern);
153     PathMatchRegex(const PathMatchRegex&);
154     virtual ~PathMatchRegex();
155     bool Match(const std::string& s) const;
156   };
157
158  class PathMatchGlob : public IPathMatch
159   {
160     regex_t m_regex;
161     PathMatchGlob();
162     const PathMatchGlob& operator=(const PathMatchGlob&);
163
164   public:
165     PathMatchGlob(const std::string& Pattern);
166     PathMatchGlob(const PathMatchGlob&);
167     virtual ~PathMatchGlob();
168     bool Match(const std::string& s) const;
169   };
170 #endif /* !KM_WIN32 */
171
172   // Search all paths in SearchPaths for filenames matching Pattern (no directories are returned).
173   // Put results in FoundPaths. Returns after first find if one_shot is true.
174   PathList_t& FindInPath(const IPathMatch& Pattern, const std::string& SearchDir,
175                          PathList_t& FoundPaths, bool one_shot = false, char separator = '/');
176
177   PathList_t& FindInPaths(const IPathMatch& Pattern, const PathList_t& SearchPaths,
178                           PathList_t& FoundPaths, bool one_shot = false, char separator = '/');
179
180
181   // Instant IO for strings
182   //
183   // Reads an entire file into a string.
184   Result_t ReadFileIntoString(const char* filename, std::string& outString, ui32_t max_size = 8 * Megabyte);
185
186   // Writes a string to a file, overwrites the existing file if present.
187   Result_t WriteStringIntoFile(const char* filename, const std::string& inString);
188
189   //
190   class FileReader
191     {
192       KM_NO_COPY_CONSTRUCT(FileReader);
193
194     protected:
195       std::string m_Filename;
196       HANDLE      m_Handle;
197
198     public:
199       FileReader() : m_Handle(INVALID_HANDLE_VALUE) {}
200       virtual ~FileReader() { Close(); }
201
202       Result_t OpenRead(const char*) const;                          // open the file for reading
203       Result_t Close() const;                                        // close the file
204       fsize_t  Size() const;                                         // returns the file's current size
205       Result_t Seek(Kumu::fpos_t = 0, SeekPos_t = SP_BEGIN) const;   // move the file pointer
206       Result_t Tell(Kumu::fpos_t* pos) const;                        // report the file pointer's location
207       Result_t Read(byte_t*, ui32_t, ui32_t* = 0) const;             // read a buffer of data
208
209       inline Kumu::fpos_t Tell() const                               // report the file pointer's location
210         {
211           Kumu::fpos_t tmp_pos;
212           Tell(&tmp_pos);
213           return tmp_pos;
214         }
215
216       inline bool IsOpen() {                                         // returns true if the file is open
217         return (m_Handle != INVALID_HANDLE_VALUE);
218       }
219     };
220
221   //
222   class FileWriter : public FileReader
223     {
224       class h__iovec;
225       mem_ptr<h__iovec>  m_IOVec;
226       KM_NO_COPY_CONSTRUCT(FileWriter);
227
228     public:
229       FileWriter();
230       virtual ~FileWriter();
231
232       Result_t OpenWrite(const char*);                               // open a new file, overwrites existing
233       Result_t OpenModify(const char*);                              // open a file for read/write
234
235       // this part of the interface takes advantage of the iovec structure on
236       // platforms that support it. For each call to Writev(const byte_t*, ui32_t, ui32_t*),
237       // the given buffer is added to an internal iovec struct. All items on the list
238       // are written to disk by a call to Writev();
239       Result_t Writev(const byte_t*, ui32_t);                       // queue buffer for "gather" write
240       Result_t Writev(ui32_t* = 0);                                 // write all queued buffers
241
242       // if you call this while there are unwritten items on the iovec list,
243       // the iovec list will be written to disk before the given buffer,as though
244       // you had called Writev() first.
245       Result_t Write(const byte_t*, ui32_t, ui32_t* = 0);            // write buffer to disk
246    };
247
248 } // namespace Kumu
249
250
251 #endif // _KM_FILEIO_H_
252
253
254 //
255 // end KM_fileio.h
256 //