revised comment
[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 happening 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   // Instant IO for archivable objects
210   //
211   // Unarchives a file into an object
212   Result_t ReadFileIntoObject(const std::string& Filename, IArchive& Object, ui32_t max_size = 8 * Kumu::Megabyte);
213
214   // Archives an object into a file
215   Result_t WriteObjectIntoFile(const IArchive& Object, const std::string& Filename);
216
217   //
218   class FileReader
219     {
220       KM_NO_COPY_CONSTRUCT(FileReader);
221
222     protected:
223       std::string m_Filename;
224       HANDLE      m_Handle;
225
226     public:
227       FileReader() : m_Handle(INVALID_HANDLE_VALUE) {}
228       virtual ~FileReader() { Close(); }
229
230       Result_t OpenRead(const char*) const;                          // open the file for reading
231       Result_t Close() const;                                        // close the file
232       fsize_t  Size() const;                                         // returns the file's current size
233       Result_t Seek(Kumu::fpos_t = 0, SeekPos_t = SP_BEGIN) const;   // move the file pointer
234       Result_t Tell(Kumu::fpos_t* pos) const;                        // report the file pointer's location
235       Result_t Read(byte_t*, ui32_t, ui32_t* = 0) const;             // read a buffer of data
236
237       inline Kumu::fpos_t Tell() const                               // report the file pointer's location
238         {
239           Kumu::fpos_t tmp_pos;
240           Tell(&tmp_pos);
241           return tmp_pos;
242         }
243
244       inline bool IsOpen() {                                         // returns true if the file is open
245         return (m_Handle != INVALID_HANDLE_VALUE);
246       }
247     };
248
249   //
250   class FileWriter : public FileReader
251     {
252       class h__iovec;
253       mem_ptr<h__iovec>  m_IOVec;
254       KM_NO_COPY_CONSTRUCT(FileWriter);
255
256     public:
257       FileWriter();
258       virtual ~FileWriter();
259
260       Result_t OpenWrite(const char*);                               // open a new file, overwrites existing
261       Result_t OpenModify(const char*);                              // open a file for read/write
262
263       // this part of the interface takes advantage of the iovec structure on
264       // platforms that support it. For each call to Writev(const byte_t*, ui32_t, ui32_t*),
265       // the given buffer is added to an internal iovec struct. All items on the list
266       // are written to disk by a call to Writev();
267       Result_t Writev(const byte_t*, ui32_t);                       // queue buffer for "gather" write
268       Result_t Writev(ui32_t* = 0);                                 // write all queued buffers
269
270       // if you call this while there are unwritten items on the iovec list,
271       // the iovec list will be written to disk before the given buffer,as though
272       // you had called Writev() first.
273       Result_t Write(const byte_t*, ui32_t, ui32_t* = 0);            // write buffer to disk
274    };
275
276 } // namespace Kumu
277
278
279 #endif // _KM_FILEIO_H_
280
281
282 //
283 // end KM_fileio.h
284 //