Update license.
[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   //
96 #ifndef KM_SMALL_FILES_OK
97   template <bool sizecheck>    void compile_time_size_checker();
98   template <> inline void compile_time_size_checker<false>() {}
99   //
100   // READ THIS if your compiler is complaining about a previously declared implementation of
101   // compile_time_size_checker(). For example, GCC 4.0.1 looks like this:
102   //
103   // error: 'void Kumu::compile_time_size_checker() [with bool sizecheck = false]' previously declared here
104   //
105   // This is happeining because the equality being tested below is false. The reason for this 
106   // will depend on your OS, but on Linux it is probably because you have not used -D_FILE_OFFSET_BITS=64
107   // Adding this magic macro to your CFLAGS will get you going again. If you are on a system that
108   // does not support 64-bit files, you can disable this check by using -DKM_SMALL_FILES_OK. You
109   // will then of course be limited to file sizes < 4GB.
110   //
111   template <> inline void compile_time_size_checker<sizeof(Kumu::fsize_t)==sizeof(ui64_t)>() {}
112 #endif
113   //
114
115   const ui32_t Kilobyte = 1024;
116   const ui32_t Megabyte = Kilobyte * Kilobyte;
117   const ui32_t Gigabyte = Megabyte * Kilobyte;
118
119   const ui32_t MaxFilePath = Kilobyte;
120
121   // Path Manglers
122   //
123   typedef std::list<std::string> PathCompList_t; // a list of path components
124   typedef std::list<std::string> PathList_t; // a list of paths
125
126   bool        PathExists(const std::string& Path); // true if the path exists in the filesystem
127   bool        PathIsFile(const std::string& Path); // true if the path exists in the filesystem and is a file
128   bool        PathIsDirectory(const std::string& Path); // true if the path exists in the filesystem and is a directory
129   fsize_t     FileSize(const std::string& Path); // returns the size of a regular file, 0 for a directory or device
130   bool        PathsAreEquivalent(const std::string& lhs, const std::string& rhs); // true if paths point to the same filesystem entry
131
132   // split and reassemble pats as lists of path components
133   PathCompList_t& PathToComponents(const std::string& Path, PathCompList_t& CList, char separator = '/'); // removes '//'
134   std::string ComponentsToPath(const PathCompList_t& CList, char separator = '/');
135   std::string ComponentsToAbsolutePath(const PathCompList_t& CList, char separator = '/'); // add separator to the front
136   bool        PathHasComponents(const std::string& Path, char separator = '/'); // true if paths starts with separator
137
138   bool        PathIsAbsolute(const std::string& Path, char separator = '/'); // true if path begins with separator
139   std::string PathMakeAbsolute(const std::string& Path, char separator = '/'); // compute position of relative path using getcwd()
140   std::string PathMakeLocal(const std::string& Path, const std::string& Parent); // remove Parent from front of Path, if it exists
141   std::string PathMakeCanonical(const std::string& Path, char separator = '/'); // remove '.' and '..'
142
143   std::string PathBasename(const std::string& Path, char separator = '/'); // returns right-most path element (list back())
144   std::string PathDirname(const std::string& Path, char separator = '/'); // returns everything but the right-most element
145   std::string PathGetExtension(const std::string& Path); // returns everything in the right-most element following the right-most '.'
146   std::string PathSetExtension(const std::string& Path, const std::string& Extension); // empty extension removes '.' as well
147
148   //
149   //
150   class IPathMatch
151   {
152   public:
153     virtual ~IPathMatch() {}
154     virtual bool Match(const std::string& s) const = 0;
155   };
156
157  class PathMatchAny : public IPathMatch
158   {
159   public:
160     virtual ~PathMatchAny() {}
161     inline bool Match(const std::string& s) const { return true; }
162   };
163
164 #ifndef KM_WIN32
165  class PathMatchRegex : public IPathMatch
166   {
167     regex_t m_regex;
168     PathMatchRegex();
169     const PathMatchRegex& operator=(const PathMatchRegex&);
170
171   public:
172     PathMatchRegex(const std::string& Pattern);
173     PathMatchRegex(const PathMatchRegex&);
174     virtual ~PathMatchRegex();
175     bool Match(const std::string& s) const;
176   };
177
178  class PathMatchGlob : public IPathMatch
179   {
180     regex_t m_regex;
181     PathMatchGlob();
182     const PathMatchGlob& operator=(const PathMatchGlob&);
183
184   public:
185     PathMatchGlob(const std::string& Pattern);
186     PathMatchGlob(const PathMatchGlob&);
187     virtual ~PathMatchGlob();
188     bool Match(const std::string& s) const;
189   };
190 #endif /* !KM_WIN32 */
191
192   // Search all paths in SearchPaths for filenames matching Pattern (no directories are returned).
193   // Put results in FoundPaths. Returns after first find if one_shot is true.
194   PathList_t& FindInPath(const IPathMatch& Pattern, const std::string& SearchDir,
195                          PathList_t& FoundPaths, bool one_shot = false, char separator = '/');
196
197   PathList_t& FindInPaths(const IPathMatch& Pattern, const PathList_t& SearchPaths,
198                           PathList_t& FoundPaths, bool one_shot = false, char separator = '/');
199
200
201   // Instant IO for strings
202   //
203   // Reads an entire file into a string.
204   Result_t ReadFileIntoString(const char* filename, std::string& outString, ui32_t max_size = 8 * Megabyte);
205
206   // Writes a string to a file, overwrites the existing file if present.
207   Result_t WriteStringIntoFile(const char* filename, const std::string& inString);
208
209   //
210   class FileReader
211     {
212       KM_NO_COPY_CONSTRUCT(FileReader);
213
214     protected:
215       std::string m_Filename;
216       HANDLE      m_Handle;
217
218     public:
219       FileReader() : m_Handle(INVALID_HANDLE_VALUE) {}
220       virtual ~FileReader() { Close(); }
221
222       Result_t OpenRead(const char*) const;                          // open the file for reading
223       Result_t Close() const;                                        // close the file
224       fsize_t  Size() const;                                         // returns the file's current size
225       Result_t Seek(Kumu::fpos_t = 0, SeekPos_t = SP_BEGIN) const;   // move the file pointer
226       Result_t Tell(Kumu::fpos_t* pos) const;                        // report the file pointer's location
227       Result_t Read(byte_t*, ui32_t, ui32_t* = 0) const;             // read a buffer of data
228
229       inline Kumu::fpos_t Tell() const                               // report the file pointer's location
230         {
231           Kumu::fpos_t tmp_pos;
232           Tell(&tmp_pos);
233           return tmp_pos;
234         }
235
236       inline bool IsOpen() {                                         // returns true if the file is open
237         return (m_Handle != INVALID_HANDLE_VALUE);
238       }
239     };
240
241   //
242   class FileWriter : public FileReader
243     {
244       class h__iovec;
245       mem_ptr<h__iovec>  m_IOVec;
246       KM_NO_COPY_CONSTRUCT(FileWriter);
247
248     public:
249       FileWriter();
250       virtual ~FileWriter();
251
252       Result_t OpenWrite(const char*);                               // open a new file, overwrites existing
253       Result_t OpenModify(const char*);                              // open a file for read/write
254
255       // this part of the interface takes advantage of the iovec structure on
256       // platforms that support it. For each call to Writev(const byte_t*, ui32_t, ui32_t*),
257       // the given buffer is added to an internal iovec struct. All items on the list
258       // are written to disk by a call to Writev();
259       Result_t Writev(const byte_t*, ui32_t);                       // queue buffer for "gather" write
260       Result_t Writev(ui32_t* = 0);                                 // write all queued buffers
261
262       // if you call this while there are unwritten items on the iovec list,
263       // the iovec list will be written to disk before the given buffer,as though
264       // you had called Writev() first.
265       Result_t Write(const byte_t*, ui32_t, ui32_t* = 0);            // write buffer to disk
266    };
267
268 } // namespace Kumu
269
270
271 #endif // _KM_FILEIO_H_
272
273
274 //
275 // end KM_fileio.h
276 //