rcolyer.net
RC Lib  Version 202403231100
File.h
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////
2 //
3 // RC Library, (c) 2011-2015, Ryan A. Colyer
4 // Distributed under the Boost Software License, v1.0. (LICENSE.txt)
5 //
6 /// \file File.h
7 /// Provides file input and output, and file / directory tools.
8 /////////////////////////////////////////////////////////////////////
9 
10 #ifndef RC_FILE_H
11 #define RC_FILE_H
12 
13 #include "RCconfig.h"
14 #include "Types.h"
15 #include "Errors.h"
16 #include "Ptr.h"
17 #include "Data1D.h"
18 #include "RStr.h"
19 
20 #ifdef WIN32
21 #include <winsock2.h>
22 #include <direct.h>
23 #include <windows.h>
24 #else
25 #include <dirent.h>
26 #include <unistd.h>
27 #endif
28 
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <stdio.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
34 
35 #ifdef CPP11
36 #include <atomic>
37 #include <type_traits>
38 #endif
39 
40 /// @cond UNDOC
41 #ifndef O_BINARY
42 #ifdef _O_BINARY
43 #define O_BINARY _O_BINARY
44 #else
45 #define O_BINARY 0
46 #endif
47 #endif
48 /// @endcond
49 
50 
51 #ifdef _MSC_VER
52 inline int open(const char *pathname, int flags) {
53  return _open(pathname, flags);
54 }
55 inline int open(const char *pathname, int flags, mode_t mode) {
56  return _open(pathname, flags, mode);
57 }
58 #endif
59 
60 
61 namespace RC {
62  class FileRead;
63  class FileWrite;
64 
65  /// Overload this with a specialization to support Get on a custom type.
66  /** An implementation of this should use the FileRead's methods Get and
67  * RawGet to read other supported types or primitives, then place the
68  * result in data.
69  * @return True if the Get succeeded.
70  */
71  template<class T> inline bool FileGetWrapper(FileRead& fr, T& data);
72  /// Overload this with a specialization to support Put on a custom type.
73  /** An implementation of this should take the value of data and use the
74  * FileWrite's methods Put and RawPut to write other supported types or
75  * primitives.
76  */
77  template<class T> inline void FilePutWrapper(FileWrite& fw, const T& data);
78 
79  /// Valid write modes for a FileWrite or FileRW.
80  /** TRUNCATE sets the file size to 0. KEEP preserves the file contents,
81  * setting the initial position to the beginning of the file. APPEND
82  * starts the read position at the beginning of the file but all Write/Put
83  * operations are forced to the end of the file. NEWONLY will only
84  * succeed if the file does not already exist.
85  */
86  enum WriteMode { TRUNCATE=0, KEEP, APPEND, NEWONLY }; // Do not reorder.
87 
88  /// Provides the common methods for the FileRead/FileWrite/FileRW classes.
89  class FileBase {
90  protected:
91  /// @cond PROTECTED
92 
93  // This class gets tossed along with assignments of FileRead/FileWrite,
94  // and maintains a reference count
95  class FileHelper {
96  public:
97 
98  inline FileHelper()
99  : fp (NULL),
100  cnt (1),
101  index (0),
102  amnt_read (0),
103  do_close (true),
104  is_readable (false),
105  is_writable (false),
106  last_was_read (false),
107  last_was_write (false) {
108  }
109 
110 
111  inline void Add() {
112  ++cnt;
113  }
114 
115  inline void Del() {
116  u64 cur_cnt = --cnt;
117  if (cur_cnt == 0) {
118  Close();
119  delete(this);
120  }
121  }
122 
123  inline void Close() {
124  FILE* loc_fp;
125  #ifdef CPP11
126  loc_fp = fp.exchange(NULL);
127  #else
128  loc_fp = fp;
129  fp = NULL;
130  #endif
131  if (do_close && (loc_fp != NULL)) {
132  fclose(loc_fp);
133  }
134  }
135 
136  inline bool IsWriteBuf() const {
137  return index > amnt_read;
138  }
139 
140  inline bool IsReadBuf() const {
141  return amnt_read > index;
142  }
143 
144  #ifdef CPP11
145  std::atomic<FILE*> fp;
146  std::atomic<u64> cnt;
147  #else
148  FILE* fp;
149  u64 cnt;
150  #endif
151 
152  Data1D<u8> buf;
153  size_t index;
154  size_t amnt_read;
155 
156  bool do_close;
157  RStr filename;
158  bool is_readable;
159  bool is_writable;
160  bool last_was_read;
161  bool last_was_write;
162  };
163 
164  // Ordering coupled to Open implementations.
165  enum BaseMode { R_ONLY=0, W_TRUNC, W_KEEP, W_APP, W_NEW,
166  RW_TRUNC, RW_KEEP, RW_APP, RW_NEW };
167 
168  inline bool BaseOpen(const RStr& filename, const BaseMode mode) {
169  helper->Del();
170 
171  helper = new FileHelper();
172 
173  helper->filename = filename;
174  RStr mode_str;
175 
176  int flags = O_BINARY;
177 
178  switch (mode) {
179  case R_ONLY: mode_str = "rb";
180  flags |= O_RDONLY;
181  break;
182  case W_TRUNC: mode_str = "wb";
183  flags |= O_WRONLY | O_CREAT | O_TRUNC;
184  break;
185  case W_KEEP: mode_str = "wb";
186  flags |= O_WRONLY | O_CREAT;
187  break;
188  case W_APP: mode_str = "ab";
189  flags |= O_WRONLY | O_CREAT | O_APPEND;
190  break;
191  case W_NEW: mode_str = "wb";
192  flags |= O_WRONLY | O_CREAT | O_EXCL;
193 #ifdef unix
194  flags |= O_NOFOLLOW;
195 #endif
196  break;
197  case RW_TRUNC: mode_str = "wb+";
198  flags |= O_RDWR | O_CREAT | O_TRUNC;
199  break;
200  case RW_KEEP: mode_str = "rb+";
201  flags |= O_RDWR | O_CREAT;
202  break;
203  case RW_APP: mode_str = "ab+";
204  flags |= O_RDWR | O_CREAT | O_APPEND;
205  break;
206  case RW_NEW: mode_str = "wb+";
207  flags |= O_RDWR | O_CREAT | O_EXCL;
208 #ifdef unix
209  flags |= O_NOFOLLOW;
210 #endif
211  break;
212  default: Throw_RC_Type(File, "Invalid mode");
213  }
214 
215 #ifdef WIN32
216  int create_mode = _S_IREAD | _S_IWRITE;
217 #else
218  int create_mode = 0664;
219 #endif
220  int fd = open(filename.c_str(), flags, create_mode);
221  if (fd >= 0) {
222  helper->fp = fdopen(fd, mode_str.c_str());
223 
224  if (helper->fp == NULL) {
225  close(fd); // If fdopen fails, must close fd manually.
226  }
227  }
228 
229  if (helper->fp == NULL) {
230  return false;
231  }
232 
233  if ((mode == R_ONLY) || (mode == RW_TRUNC) ||
234  (mode == RW_APP) || (mode == RW_NEW)) {
235  helper->is_readable = true;
236  }
237 
238  if ((mode == W_TRUNC) || (mode == W_APP) || (mode == W_NEW) ||
239  (mode == RW_TRUNC) || (mode == RW_APP) || (mode == RW_NEW)) {
240  helper->is_writable = true;
241  }
242  return true;
243  }
244 
245  inline void BaseOpen(FILE *fp, bool do_close) {
246  helper->Del();
247 
248  helper = new FileHelper();
249 
250  helper->fp = fp;
251  helper->do_close = do_close;
252  }
253 
254  inline void BaseSwitchWrite() const {
255  if (helper->last_was_read) {
256  BaseRelativePosition(0);
257  helper->last_was_read = false;
258  }
259  helper->last_was_write = true;
260  }
261 
262  inline void BaseSwitchRead() const {
263  if (helper->last_was_write) {
264  BaseRelativePosition(0);
265  helper->last_was_write = false;
266  }
267  helper->last_was_read = true;
268  }
269 
270  template<class T>
271  inline void BaseWrite(const Data1D<T> &data,
272  const size_t amnt_to_write) const {
273  size_t amnt_written;
274 
275  Assert();
276 
277  if (amnt_to_write == 0) {
278  return;
279  }
280  data.Assert(amnt_to_write-1);
281 
282  BaseSwitchWrite();
283 
284  amnt_written = fwrite(data.Raw(), data.TypeSize(), amnt_to_write,
285  helper->fp);
286 
287  if (amnt_written < amnt_to_write) {
288  if (ferror(helper->fp) != 0) {
289  Throw_RC_Type(File, "File Write Error");
290  }
291  }
292  }
293 
294  inline void BaseRelativePosition(const i64 amnt) const {
295  if (fseek(helper->fp, amnt, SEEK_CUR) < 0) {
296  if (amnt != 0) {
297  Throw_RC_Type(File, "File Seek Error");
298  }
299  }
300  }
301 
302  inline void BufFlush() {
303  if (helper->IsWriteBuf()) {
304  BaseWrite(helper->buf, helper->index);
305  helper->index = 0;
306  }
307  }
308 
309 
310  FileHelper *helper;
311  static const size_t min_buf_size = 65536;
312 
313  /// @endcond
314 
315  public:
316 
317  /// Default constructor.
318  inline FileBase() {
319  helper = new FileHelper();
320  }
321 
322  /// Copy constructor.
323  inline FileBase(const FileBase& other) {
324  other.helper->Add();
325  helper = other.helper;
326  }
327 
328  /// Assignment operator.
329  inline FileBase& operator= (const FileBase& other) {
330  helper->Del();
331 
332  other.helper->Add();
333  helper = other.helper;
334 
335  return *this;
336  }
337 
338  /// Flushes the write buffer before destructing. This will close the file
339  /// if it is the last FileBase sharing it.
340  inline virtual ~FileBase() {
341  try{
342  Flush();
343  }
344  catch(...) {}
345  helper->Del();
346  }
347 
348 
349  /// Returns the filename if one was given upon opening.
350  inline RStr GetFilename() const {
351  return (helper->filename);
352  }
353 
354 
355  /// Manually changes the associated filename.
356  inline void SetFilename(const RStr& newfilename) const {
357  helper->filename = newfilename;
358  }
359 
360 
361  /// Flushes the buffers and closes the file.
362  inline void Close() {
363  Flush();
364  helper->Close();
365  }
366 
367 
368  /// True if the file is open.
369  inline bool IsOpen() const {
370  return (helper->fp != NULL);
371  }
372 
373  /// True if the file is closed.
374  inline bool IsClosed() const {
375  return (helper->fp == NULL);
376  }
377 
378  /// True if the file is open and readable.
379  inline bool IsReadable() const {
380  return (IsOpen() && (helper->is_readable));
381  }
382 
383  /// True if the file is open and writable.
384  inline bool IsWritable() const {
385  return (IsOpen() && (helper->is_writable));
386  }
387 
388 
389  /// Returns a raw FILE* which can be used with the C file functions.
390  inline FILE* Raw() const {
391  return (helper->fp);
392  }
393 
394 
395  /// Throws ErrorMsgFile if the file is closed.
396  inline void Assert() const {
397  if (IsClosed()) {
398  Throw_RC_Type(File, "File Is Closed");
399  }
400  }
401 
402 
403  /// Returns the file size in bytes.
404  inline size_t Size() const {
405  struct stat filestats;
406 
407  Assert();
408 
409  if (fstat(fileno(helper->fp), &filestats) < 0) {
410  Throw_RC_Type(File, "File Size Error");
411  }
412 
413  return (filestats.st_size);
414  }
415 
416 
417  /// Sets the reading and writing position to pos bytes into the file.
418  inline void SetPosition(const size_t pos) {
419  Assert();
420  ClearBuffer();
421 
422  if (fseek(helper->fp, pos, SEEK_SET) < 0) {
423  Throw_RC_Type(File, "File Seek Error");
424  }
425  }
426 
427 
428  /// Sets the position for the next read or write operation.
429  /** Note: This has no effect on write operations in APPEND mode.
430  */
431  inline void RelativePosition(const i64 amnt) {
432  Assert();
433  ClearBuffer();
434 
435  BaseRelativePosition(amnt);
436  }
437 
438  /// Gets the position for the next read or write operation.
439  /** @param quiet_fail If true, does not throw an error from being
440  * unable to find the position. (0 is returned.)
441  */
442  inline size_t GetPosition(bool quiet_fail=false) const {
443  Assert();
444  long pos;
445 
446  if ( (pos = ftell(helper->fp)) < 0) {
447  if (quiet_fail) { return 0; }
448  Throw_RC_Type(File, "File Position Error");
449  }
450 
451  return size_t(pos) + helper->index - helper->amnt_read;
452  }
453 
454  /// Clears the read-ahead buffer used by FileRead::Get calls.
455  inline void Rewind() {
456  if (helper->IsReadBuf()) {
457  BaseRelativePosition(i64(helper->index)-i64(helper->amnt_read));
458  helper->amnt_read = 0;
459  helper->index = 0;
460  }
461  }
462 
463  /// Flushes all unsaved data to the storage system.
464  inline void Flush() {
465  if (helper->is_writable) {
466  BufFlush();
467  if (fflush(helper->fp) != 0) {
468  Throw_RC_Type(File, "File Flush Error");
469  }
470  }
471  }
472 
473  /// Processes the remaining data in the Put/Get buffer.
474  inline void ClearBuffer() {
475  Rewind();
476  BufFlush();
477  }
478  };
479 
480 
481  /// A file reading class that provides buffered and unbuffered access to
482  /// files with support for non-POD classes.
483  class FileRead : public virtual FileBase {
484  protected:
485  /// @cond PROTECTED
486 
487  inline void FillBuff(size_t min_requested=0) {
488  if (helper->buf.size() < min_requested) {
489  if (min_requested < min_buf_size) {
490  helper->buf.Resize(min_buf_size);
491  }
492  else {
493  helper->buf.Resize(min_requested);
494  }
495  }
496  if (helper->amnt_read > helper->index) {
497  std::copy(helper->buf.Raw()+helper->index,
498  helper->buf.Raw()+helper->amnt_read,
499  helper->buf.Raw());
500  helper->buf.SetOffset(helper->amnt_read - helper->index);
501  helper->amnt_read += Read(helper->buf) - helper->index;
502  helper->buf.SetOffset(0);
503  }
504  else {
505  helper->amnt_read = Read(helper->buf);
506  }
507  helper->index = 0;
508  }
509 
510  /// @endcond
511  public:
512 
513  /// Default constructor.
514  inline FileRead() {
515  }
516 
517  /// Opens the file specified by filename for reading.
518  /** Throws ErrorMsgFile if the file could not be opened.
519  */
520  inline FileRead(const RStr& filename) {
521  if ( ! Open(filename)) {
522  Throw_RC_Type(File, "File Open Error");
523  }
524  }
525 
526  /// Wraps the FILE* fp for reading. It will close it when finished if
527  /// do_close is true.
528  inline FileRead(FILE *fp, bool do_close) {
529  Open(fp, do_close);
530  }
531 
532  /// Wraps the FILE* fp for reading. It will close it when finished
533  /// unless fp is stdin.
534  inline FileRead(FILE *fp) {
535  Open(fp);
536  }
537 
538  /// Base copy constructor.
539  inline FileRead(const FileBase& other) : FileBase(other) { }
540 
541 
542  /// Opens the file specified by filename for reading.
543  /** @return True if the file was successfully opened.
544  */
545  inline bool Open(const RStr& filename) {
546  return BaseOpen(filename, R_ONLY);
547  }
548 
549  /// Wraps the FILE* fp for reading. It will close it when finished if
550  /// do_close is true.
551  inline void Open(FILE *fp, bool do_close) {
552  BaseOpen(fp, do_close);
553  helper->is_readable = true;
554  }
555 
556  /// Wraps the FILE* fp for reading. It will close it when finished
557  /// unless fp is stdin.
558  inline void Open(FILE *fp) {
559  Open(fp, (fp != stdin));
560  }
561 
562 
563  /// Reads amnt_to_read elements of plain old data type T into data without
564  /// buffering, resizing if too small.
565  /** Throws ErrorMsgFile if there was an error reading.
566  * @return The number of elements successfully read.
567  */
568  template<class T>
569  inline size_t Read(Data1D<T> &data, const size_t amnt_to_read) {
570 #ifdef CPP11
571  // TODO - Uncomment after correct implementation broadly available.
572 // static_assert(std::is_trivially_copyable<T>::value,
573 // "Use only on trivially copyable types");
574 #endif
575  size_t amnt_read;
576 
577  Assert();
578  BaseSwitchRead();
579  Rewind();
580 
581  if (data.size() < amnt_to_read) {
582  data.Resize(amnt_to_read);
583  }
584 
585  amnt_read = fread(data.Raw(), data.TypeSize(), amnt_to_read, helper->fp);
586 
587  if (amnt_read == 0) {
588  if (ferror(helper->fp) != 0) {
589  Throw_RC_Type(File, "File Read Error");
590  }
591  }
592 
593  return amnt_read;
594  }
595 
596 
597  /// Fills data with plain old data type T without buffering.
598  /** Throws ErrorMsgFile if there was an error reading.
599  * @return The number of elements successfully read.
600  */
601  template<class T>
602  inline size_t Read(Data1D<T> &data) {
603  return Read(data, data.size());
604  }
605 
606 
607  /// Reads all data until the end of file into data as plain old data type
608  /// T.
609  template<class T>
610  inline void ReadAll(Data1D<T> &data) {
611 #ifdef CPP11
612  // TODO - Uncomment after correct implementation broadly available.
613 // static_assert(std::is_trivially_copyable<T>::value,
614 // "Use only on trivially copyable types");
615 #endif
616  size_t amnt_read;
617  size_t amnt_to_read = 1+65535/sizeof(T);
618 
619  size_t estimate = (Size()-GetPosition(true)) / sizeof(T);
620 
621  // If we can determine the filesize, read that.
622  // Otherwise, read until EOF.
623  if (estimate > 0) {
624  data.Resize(estimate);
625  data.Resize(Read(data));
626  }
627  else {
628  size_t initial_offset = data.GetOffset();
629  estimate = initial_offset + amnt_to_read;
630  data.Reserve(estimate);
631 
632  size_t total_read = 0;
633  while (1) {
634  data.Resize(amnt_to_read);
635  amnt_read = Read(data);
636  if (amnt_read == 0) {
637  break;
638  }
639  total_read += amnt_read;
640  data.SetOffset(initial_offset + total_read);
641  if ((data.reserved() - data.GetOffset()) < amnt_to_read) {
642  estimate *= 2;
643  data.Reserve(estimate);
644  }
645  }
646  data.SetOffset(initial_offset);
647  data.Resize(total_read);
648  }
649  }
650 
651 
652  /// Reads one line until newline, null, or end of file. The newline
653  /// is removed if crop_newline is true.
654  /** Throws ErrorMsgFile if there was a read error.
655  * @return True if the read was successful.
656  */
657  inline bool ReadLine(RStr &line, bool crop_newline = true) {
658  Data1D<char> str(4096);
659  char *retv;
660  size_t amnt_read;
661  bool readmore;
662  size_t partsread;
663 
664  Assert();
665  Rewind();
666  BaseSwitchRead();
667 
668  line = "";
669 
670  readmore = true;
671  for (partsread=0; readmore; partsread++) {
672  retv = fgets(str.Raw(), str.size(), helper->fp);
673  if (retv == NULL) {
674  if (ferror(helper->fp) != 0) {
675  Throw_RC_Type(File, "File Read Error");
676  }
677  else { // No error, but no more data.
678  if (partsread == 0) {
679  return false;
680  }
681  else {
682  return true;
683  }
684  }
685  }
686 
687 
688  amnt_read = strlen(str.Raw());
689  if ( (amnt_read != (str.size()-1)) || (str[amnt_read-1] == '\n') ) {
690  readmore = false;
691  }
692  if (crop_newline) {
693  while (amnt_read >= 1) {
694  if ( (str[amnt_read-1] == '\n') || (str[amnt_read-1] == '\r') ) {
695  str[amnt_read-1] = 0;
696  amnt_read--;
697  }
698  else {
699  break;
700  }
701  }
702  }
703 
704  line += str.Raw();
705 
706  }
707 
708  return true;
709  }
710 
711  /// Does ReadLine.
712  inline bool Read(RStr &line, bool crop_newline = true) {
713  return ReadLine(line, crop_newline);
714  }
715 
716 
717  /// Discards one line until newline, null, or end of file.
718  inline bool SkipLine() {
719  RStr discard;
720  return ReadLine(discard);
721  }
722 
723 
724  /// Reads all the lines found until the end of the file. If crop_newlines
725  /// is true they are removed from each line.
726  inline void ReadAllLines(Data1D<RStr> &lines, bool crop_newlines = true) {
727  RStr str;
728  size_t estimate;
729  estimate = (Size()-GetPosition(true)) / 30; // Estimate #lines in file.
730  lines.Delete();
731  lines.Reserve(estimate);
732 
733  while (ReadLine(str, crop_newlines)) {
734  lines.Append(str);
735  }
736  }
737 
738  /// Does ReadAllLines.
739  inline void ReadAll(Data1D<RStr> &lines, bool crop_newlines = true) {
740  ReadAllLines(lines, crop_newlines);
741  }
742 
743 
744  /// Performs a buffered read of sizeof(T) bytes and assigns them to data.
745  /** @return True if the read succeeded.
746  */
747  template<class T>
748  inline bool RawGet(T& data) {
749 #ifdef CPP11
750  // TODO - Uncomment after correct implementation broadly available.
751 // static_assert(std::is_trivially_copyable<T>::value,
752 // "Implement a FileGetWrapper for types with copy/move constructors");
753 #endif
754  if (helper->IsWriteBuf()) {
755  BufFlush();
756  }
757  if ( (helper->amnt_read - helper->index) < sizeof(T) ) {
758  FillBuff(sizeof(T));
759  if (helper->amnt_read < sizeof(T)) {
760  return false;
761  }
762  }
763 
764  data = *reinterpret_cast<T*>(helper->buf.Raw()+helper->index);
765  helper->index += sizeof(T);
766 
767  return true;
768  }
769 
770  /// Gets data of type T, after passing through FileGetWrapper.
771  /** @return True if the read succeeded.
772  */
773  template<class T>
774  inline bool Get(T& data) { return FileGetWrapper(*this, data); }
775 
776  /// Gets one line into data, up to the newline, null, or end of file,
777  /// removing the newline if crop_newline is true.
778  /** @return True if the read succeeded.
779  */
780  inline bool Get(RStr& data, bool crop_newline=true) {
781  Data1D<char> arr;
782  arr.Reserve(4096);
783  char ch;
784  bool retval = false;
785 
786  while (RawGet(ch)) {
787  retval = true;
788  if (ch == '\0') {
789  break;
790  }
791  if (ch == '\n') {
792  if ( ! crop_newline ) {
793  arr += ch;
794  }
795  break;
796  }
797  arr += ch;
798  }
799 
800  if (crop_newline) {
801  while (arr.size() > 0 && arr[arr.size()-1] == '\r') {
802  arr.Resize(arr.size()-1);
803  }
804  }
805 
806  arr += '\0';
807  data = arr.Raw();
808 
809  return retval;
810  }
811 
812  /// Fill data with lines from the file, removing the newlines if
813  /// crop_newlines is true.
814  /** @return True if the reads succeeded.
815  */
816  inline bool Get(Data1D<RStr>& data, bool crop_newlines=true) {
817  bool retval = false;
818  for (size_t i=0; i<data.size(); i++) {
819  retval = Get(data[i], crop_newlines);
820  if (!retval) {
821  return false;
822  }
823  }
824  return retval;
825  }
826 
827  /// Fill data with elements of type T, calling Get on each one.
828  /** @return True if the reads succeeded.
829  */
830  template<class T>
831  inline bool Get(Data1D<T>& data) {
832  bool retval = false;
833  for (size_t i=0; i<data.size(); i++) {
834  retval = Get(data[i]);
835  if (!retval) {
836  return false;
837  }
838  }
839  return retval;
840  }
841 
842  /// Fill data with elements of type T, calling Get on each one.
843  /** For data[y][x], x is the inner loop.
844  * @return True if the reads succeeded.
845  */
846  template<class T>
847  inline bool Get(Data2D<T>& data) {
848  return Get(data.RawData());
849  }
850 
851  /// Fill data with elements of type T, calling Get on each one.
852  /** For data[z][y][x], x is the inner loop.
853  * @return True if the reads succeeded.
854  */
855  template<class T>
856  inline bool Get(Data3D<T>& data) {
857  return Get(data.RawData());
858  }
859 
860  /// Fill data with all lines from the file until the end, removing the
861  /// newlines if crop_newlines is true.
862  /** @return True if the reads succeeded.
863  */
864  inline bool GetAll(Data1D<RStr>& data, bool crop_newlines=true) {
865  bool retval = false;
866  data.Resize(0);
867  RStr tmp;
868  while(Get(tmp, crop_newlines)) {
869  retval = true;
870  data += tmp;
871  }
872  return retval;
873  }
874 
875  /// Fill data with all elements of type T until the end of file, calling
876  /// Get on each one.
877  /** @return True if the reads succeeded.
878  */
879  template<class T>
880  inline bool GetAll(Data1D<T>& data) {
881  bool retval = false;
882  data.Resize(0);
883  T tmp;
884  while(Get(tmp)) {
885  retval = true;
886  data += tmp;
887  }
888  return retval;
889  }
890  };
891 
892 
893  /// A file writing class that provides buffered and unbuffered output to
894  /// files with support for non-POD classes.
895  class FileWrite : public virtual FileBase {
896  public:
897 
898  /// Default constructor.
899  inline FileWrite() {
900  }
901 
902  /// Opens the file specified by filename for writing, using the WriteMode
903  /// specified by mode.
904  /** Throws ErrorMsgFile if the file could not be opened.
905  */
906  inline FileWrite(const RStr& filename,
907  const WriteMode mode=TRUNCATE) {
908  if ( ! Open(filename, mode) ) {
909  if (errno == EEXIST) {
910  Throw_RC_Type(File, "File Exists");
911  }
912  else {
913  Throw_RC_Type(File, "File Open Error");
914  }
915  }
916  }
917 
918  /// Wraps the FILE* fp for writing. It will close it when finished if
919  /// do_close is true.
920  inline FileWrite(FILE *fp, bool do_close) {
921  Open(fp, do_close);
922  }
923 
924  /// Wraps the FILE* fp for writing. It will close it when finished
925  /// unless fp is stdout.
926  inline FileWrite(FILE *fp) {
927  Open(fp);
928  }
929 
930  /// Base copy constructor.
931  inline FileWrite(const FileBase& other) : FileBase(other) { }
932 
933 
934  /// Opens the file specified by filename for writing, using the WriteMode
935  /// specified by mode.
936  /** @return True if the file was successfully opened.
937  */
938  inline bool Open(const RStr& filename, const WriteMode mode=TRUNCATE) {
939  return BaseOpen(filename, BaseMode(int(mode)+1));
940  }
941 
942  /// Wraps the FILE* fp for writing. It will close it when finished if
943  /// do_close is true.
944  inline void Open(FILE *fp, bool do_close) {
945  BaseOpen(fp, do_close);
946  helper->is_writable = true;
947  }
948 
949  /// Wraps the FILE* fp for writing. It will close it when finished
950  /// unless fp is stdout or stderr.
951  inline void Open(FILE *fp) {
952  Open(fp, (fp != stdout) && (fp != stderr));
953  }
954 
955 
956  /// Writes amnt_to_write elements of plain old data type T from data
957  /// without buffering.
958  /** Throws ErrorMsgFile if there was an error writing.
959  */
960  template<class T>
961  inline void Write(const Data1D<T> &data, const size_t amnt_to_write) {
962  BufFlush();
963  BaseWrite(data, amnt_to_write);
964  }
965 
966  /// Writes all of data's plain old data type T without buffering.
967  /** Throws ErrorMsgFile if there was an error writing.
968  */
969  template<class T>
970  inline void Write(const Data1D<T> &data) {
971  Write(data, data.size());
972  }
973 
974 
975  /// Writes the null-terminated contents of str without buffering.
976  /** Throws ErrorMsgFile if there was a write error.
977  */
978  inline void WriteStr(const char *str) {
979  Assert();
980  BufFlush();
981 
982  BaseSwitchWrite();
983  if (fputs(str, helper->fp) < 0) {
984  if (ferror(helper->fp) != 0) {
985  Throw_RC_Type(File, "File Write Error");
986  }
987  }
988  }
989 
990 
991  /// Writes the RStr str without buffering.
992  /** Throws ErrorMsgFile if there was a write error.
993  */
994  inline void WriteStr(const RStr &str) {
995  Assert();
996 
997  WriteStr(str.c_str());
998  }
999 
1000 
1001  /// Writes all lines without buffering, adding a newline after each if
1002  /// add_newlines is true.
1003  /** Throws ErrorMsgFile if there was a write error.
1004  */
1005  inline void WriteAllStr(const Data1D<RStr> &lines,
1006  const bool add_newlines) {
1007  for (size_t i=0; i<lines.size(); i++) {
1008  WriteStr(lines[i]);
1009  if (add_newlines) {
1010  if (fputc('\n', helper->fp) == EOF) {
1011  Throw_RC_Type(File, "File Write Error");
1012  }
1013  }
1014  }
1015  }
1016 
1017 
1018  /// Performs a buffered write of sizeof(T) raw bytes extracted from data.
1019  template<class T>
1020  inline void RawPut(const T& data) {
1021 #ifdef CPP11
1022  // TODO - Uncomment after correct implementation broadly available.
1023 // static_assert(std::is_trivially_copyable<T>::value,
1024 // "Implement a FilePutWrapper for types with copy/move constructors");
1025 #endif
1026  if (helper->IsReadBuf()) {
1027  Rewind();
1028  }
1029  if ( (helper->buf.size() - helper->index) < sizeof(T) ) {
1030  BufFlush();
1031  if (helper->buf.size() < sizeof(T)) {
1032  if (sizeof(T) < min_buf_size) {
1033  helper->buf.Resize(min_buf_size);
1034  }
1035  else {
1036  helper->buf.Resize(sizeof(T));
1037  }
1038  }
1039  }
1040 
1041  memcpy(helper->buf.Raw()+helper->index, &data, sizeof(T));
1042  helper->index += sizeof(T);
1043  }
1044 
1045  /// Puts data of type T into the write buffer, after passing through
1046  /// FilePutWrapper.
1047  template<class T>
1048  inline void Put(const T& data) { FilePutWrapper(*this, data); }
1049 
1050  /// Puts the null-terminated character data str into the write buffer,
1051  /// excluding the null.
1052  inline void Put(const char* str) {
1053  const char* tmp = str;
1054  while (*tmp) {
1055  Put(*tmp);
1056  tmp++;
1057  }
1058  }
1059 
1060  /// Puts the RStr str into the write buffer.
1061  inline void Put(const RStr& str) {
1062  Put(str.c_str());
1063  }
1064 
1065  /// Calls Put for each element of data.
1066  template<class T>
1067  inline void Put(const Data1D<T>& data) {
1068  for (size_t i=0; i<data.size(); i++) {
1069  Put(data[i]);
1070  }
1071  }
1072 
1073  /// Calls Put for each element of data.
1074  /** For data[y][x], x is the inner loop.
1075  */
1076  template<class T>
1077  inline void Put(const Data2D<T>& data) {
1078  Put(data.RawData());
1079  }
1080 
1081  /// Calls Put for each element of data.
1082  /** For data[z][y][x], x is the inner loop.
1083  */
1084  template<class T>
1085  inline void Put(const Data3D<T>& data) {
1086  Put(data.RawData());
1087  }
1088 
1089  /// Puts each RStr in data into the write buffer, adding newlines to each
1090  /// if add_newline is true.
1091  inline void Put(const Data1D<RStr>& data, const bool add_newline) {
1092  for (size_t i=0; i<data.size(); i++) {
1093  Put(data[i]);
1094  if (add_newline) {
1095  Put('\n');
1096  }
1097  }
1098  }
1099 
1100 
1101  /// Get all the remaining data from the FileRead, and Put it to this
1102  /// FileWrite.
1103  inline FileWrite& operator<< (FileRead& read) {
1104 #ifdef CPP11
1105  struct { u64 a, b, c, d; } tmp;
1106 #else
1107  u64 tmp;
1108 #endif
1109  while (read.Get(tmp)) {
1110  Put(tmp);
1111  }
1112  char ch;
1113  while (read.Get(ch)) {
1114  Put(ch);
1115  }
1116 
1117  return (*this);
1118  }
1119  };
1120 
1121 
1122  /// A file class for both reading and writing that provides buffered and
1123  /// unbuffered output to files.
1124  class FileRW : public FileRead, public FileWrite {
1125  public:
1126 
1127  /// Default constructor.
1128  inline FileRW() {
1129  }
1130 
1131  /// Opens the file specified by filename for reading and writing, using
1132  /// the WriteMode specified by mode.
1133  /** Throws ErrorMsgFile if the file could not be opened.
1134  */
1135  inline FileRW(const RStr& filename,
1136  const WriteMode mode=KEEP) {
1137  if ( ! Open(filename, mode) ) {
1138  if (errno == EEXIST) {
1139  Throw_RC_Type(File, "File Exists");
1140  }
1141  else {
1142  Throw_RC_Type(File, "File Open Error");
1143  }
1144  }
1145  }
1146 
1147  /// Wraps the FILE* fp for reading and writing. It will close it when
1148  /// finished if do_close is true.
1149  inline FileRW(FILE *fp, bool do_close) {
1150  Open(fp, do_close);
1151  }
1152 
1153  /// Wraps the FILE* fp for reading and writing. It will close it when
1154  /// finished unless fp is stdin/stdout/stderr.
1155  inline FileRW(FILE *fp) {
1156  Open(fp);
1157  }
1158 
1159  /// Base copy constructor.
1160  inline FileRW(const FileBase& other) : FileBase(other) { }
1161 
1162 
1163  /// Opens the file specified by filename for reading and writing, using
1164  /// the WriteMode specified by mode.
1165  /** @return True if the file was successfully opened.
1166  */
1167  inline bool Open(const RStr& filename, const WriteMode mode=KEEP) {
1168  return BaseOpen(filename, BaseMode(int(mode)+5));
1169  }
1170 
1171  /// Wraps the FILE* fp for reading and writing. It will close it when
1172  /// finished if do_close is true.
1173  inline void Open(FILE *fp, bool do_close) {
1174  BaseOpen(fp, do_close);
1175  helper->is_readable = true;
1176  helper->is_writable = true;
1177  }
1178 
1179  /// Wraps the FILE* fp for reading and writing. It will close it when
1180  /// finished unless fp is stdin/stdout/stderr.
1181  inline void Open(FILE *fp) {
1182  Open(fp, (fp != stdin) && (fp != stdout) && (fp != stderr));
1183  }
1184  };
1185 
1186 
1187  /// The default FileGetWrapper for plain old data, which calls RawGet.
1188  template<class T> inline bool FileGetWrapper(FileRead& fr, T& data) {
1189  return fr.RawGet(data);
1190  }
1191 
1192  /// The default FilePutWrapper for plain old data, which calls RawPut.
1193  template<class T> inline void FilePutWrapper(FileWrite& fw, const T& data) {
1194  fw.RawPut(data);
1195  }
1196 
1197  /// A specialization for handling std::string objects.
1198  template<> inline bool FileGetWrapper<std::string>(FileRead& fr,
1199  std::string& data) {
1200  RStr tmp;
1201  bool retval = fr.Get(tmp);
1202  data = tmp.Raw();
1203  return retval;
1204  }
1205 
1206  /// A specialization for handling std::string objects.
1207  template<> inline void FilePutWrapper<std::string>(FileWrite& fw,
1208  const std::string& data) {
1209  fw.Put(RStr(data));
1210  }
1211 
1212 
1213  /// A class with static methods for file and directory info and manipulation.
1214  class File {
1215  public:
1216 
1217  /// The OS-specific divider between directories in a pathname.
1218 #ifdef WIN32
1219  static const char divider = '\\';
1220 #else
1221  static const char divider = '/';
1222 #endif
1223 
1224  /// Returns the file size of pathname, or 0 if the file does not exist.
1225  static inline size_t Size(const RStr& pathname) {
1226  struct stat filestats;
1227 
1228  if (stat(pathname.c_str(), &filestats) < 0) {
1229  if (errno == ENOENT) {
1230  return 0; // File does not exist
1231  }
1232  else {
1233  Throw_RC_Type(File, "File Size Error");
1234  }
1235  }
1236 
1237  return (filestats.st_size);
1238  }
1239 
1240 
1241  /// Returns true if the file pathname exists.
1242  static inline bool Exists(const RStr& pathname) {
1243  struct stat filestats;
1244 
1245  if (stat(pathname.c_str(), &filestats) < 0) {
1246  return false;
1247  }
1248  else {
1249  return true;
1250  }
1251  }
1252 
1253 
1254  /// Deletes the file pathname, returning true if it succeeded.
1255  /** If quiet_fail is false, an exception is thrown upon failure. */
1256  static inline bool Delete(const RStr& pathname, bool quiet_fail=true) {
1257  if (remove(pathname.c_str()) != 0) {
1258  if ( ! quiet_fail ) {
1259  Throw_RC_Type(File, "File Delete Error");
1260  }
1261  return false;
1262  }
1263  return true;
1264  }
1265 
1266 
1267  /// Copies the contents of srcfile to destfile. It will overwrite an
1268  /// existing file only if overwrite is true.
1269  /** Throws ErrorMsgFile if an error occurs. */
1270  static inline void Copy(const RStr& srcfile, const RStr& destfile,
1271  bool overwrite=true) {
1272  FileRead in(srcfile);
1273 
1274  WriteMode mode = overwrite ? TRUNCATE : NEWONLY;
1275  FileWrite out(destfile, mode);
1276 
1277  out << in;
1278  }
1279 
1280 
1281  /// Moves srcfile to destfile by copying the contents and then deleting
1282  /// srcfile.
1283  /** Note: This first attempts an efficient rename, but if that fails
1284  * it falls back to a copy/delete operation.
1285  * ErrorMsgFile is thrown if the move fails.
1286  */
1287  static inline void Move(const RStr& srcfile, const RStr& destfile,
1288  bool overwrite=true) {
1289  int ren_ret;
1290  if (srcfile == destfile) { return; }
1291 
1292 #ifdef WIN32
1293  ren_ret = rename(srcfile.c_str(), destfile.c_str());
1294  if (overwrite && ren_ret != 0 && errno == EACCES) {
1295  if (Delete(destfile)) {
1296  ren_ret = rename(srcfile.c_str(), destfile.c_str());
1297  }
1298  }
1299 #else
1300  if (overwrite) {
1301  ren_ret = rename(srcfile.c_str(), destfile.c_str());
1302  }
1303  else {
1304  ren_ret = link(srcfile.c_str(), destfile.c_str());
1305  if (ren_ret == 0) {
1306  unlink(srcfile.c_str());
1307  }
1308  }
1309 #endif
1310 
1311  if (ren_ret != 0) {
1312  Copy(srcfile, destfile, overwrite);
1313  Delete(srcfile);
1314  }
1315  }
1316 
1317 
1318  /// Makes a new directory dirname.
1319  /** @return True if it succeeded.
1320  * If return_true_if_exists is true, success is if the directory exists
1321  * upon return. If it's false, success is if the directory was newly
1322  * created.
1323  */
1324  static inline bool MakeDir(const RStr& dirname,
1325  bool return_true_if_exists=true) {
1326 #ifdef WIN32
1327  RStr tmpdir = dirname;
1328  if (CreateDirectory(tmpdir.ToLPCTSTR(), NULL)==0) {
1329  if (return_true_if_exists &&
1330  (GetLastError() == ERROR_ALREADY_EXISTS)) {
1331  return true;
1332  }
1333  return false;
1334  }
1335 #else
1336  if (mkdir(dirname.c_str(), 0777)) {
1337  if (return_true_if_exists && (errno == EEXIST)) {
1338  return true;
1339  }
1340  return false;
1341  }
1342 #endif
1343  return true;
1344  }
1345 
1346 
1347  /// Returns the current working directory.
1348  static inline RStr CurrentDir() {
1349  char cwd[65536];
1350  char *errchk;
1351  RStr retval;
1352 #ifdef WIN32
1353  errchk = _getcwd(cwd, 65536);
1354 #else
1355  errchk = getcwd(cwd, 65536);
1356 #endif
1357  if (errchk != NULL) {
1358  retval = cwd;
1359  }
1360  return retval;
1361  }
1362 
1363 
1364  /// Returns a list of entries in the directory path.
1365  /** If qualified is true, the returned entries are fully qualified
1366  * pathnames. Throws ErrorMsgFile if the directory cannot be read.
1367  */
1368  static inline Data1D<RStr> DirList(const RStr &path,
1369  bool qualified=false) {
1370  Data1D<RStr> dir_list;
1371  const char err_msg[] = "Could not read directory";
1372 
1373 #ifdef WIN32
1374  RStr path_appended = path + "\\*";
1375  WIN32_FIND_DATA file_data;
1376  HANDLE dir_handle;
1377 
1378  dir_handle = FindFirstFile(path_appended.ToLPCTSTR(), &file_data);
1379 
1380  if (dir_handle == INVALID_HANDLE_VALUE) {
1381  Throw_RC_Type(File, err_msg);
1382  }
1383 
1384  do {
1385  if (qualified) {
1386  dir_list += path + File::divider + RStr(file_data.cFileName);
1387  }
1388  else {
1389  dir_list += RStr(file_data.cFileName);
1390  }
1391  } while (FindNextFile(dir_handle, &file_data));
1392 #else
1393  struct dirent **namelist;
1394 
1395  int entries = scandir(path.c_str(), &namelist, NULL, NULL);
1396  if (entries < 0) {
1397  Throw_RC_Type(File, err_msg);
1398  }
1399 
1400  for (int i=0; i<entries; i++) {
1401  RStr entry = RStr(namelist[i]->d_name);
1402  if (entry != "." && entry != "..") {
1403  if (qualified) {
1404  dir_list += path + File::divider + entry;
1405  }
1406  else {
1407  dir_list += entry;
1408  }
1409  }
1410  free(namelist[i]);
1411  }
1412  free(namelist);
1413 #endif
1414 
1415  dir_list.Sort();
1416 
1417  return dir_list;
1418  }
1419 
1420  /// Extracts the directory portion of filename, or the current directory
1421  /// if filename has no directory.
1422  static inline RStr Dirname(const RStr& filename) {
1423  size_t mid;
1424  mid = filename.find_last_of("\\/");
1425  if (mid == RStr::npos) {
1426  return CurrentDir();
1427  }
1428  else {
1429  if (mid < filename.length()) {
1430  mid++;
1431  }
1432  return filename.substr(0, mid);
1433  }
1434  }
1435 
1436 
1437  /// Extracts the basename portion of filename, which excludes the
1438  /// directory.
1439  static inline RStr Basename(const RStr& filename) {
1440  Data1D<RStr> split = filename.SplitLast("\\/");
1441  if (split[1].length() == 0) {
1442  return filename;
1443  }
1444  else {
1445  return split[1];
1446  }
1447  }
1448 
1449 
1450  /// Merges path and filename into a path with a divider inserted if
1451  /// needed.
1452  static inline RStr FullPath(const RStr& path, const RStr& filename) {
1453  if (path.size()>0 && path[path.size()-1]==divider) {
1454  return path + filename;
1455  }
1456  else {
1457  return path + divider + filename;
1458  }
1459  }
1460 
1461 
1462  /// Extracts the filename's extension.
1463  static inline RStr Extension(const RStr& filename) {
1464  if (filename.size() == 0) { return ""; }
1465  for (size_t i=filename.size()-1; i<filename.size(); i--) {
1466  if (filename[i] == '.') {
1467  return filename.substr(i+1);
1468  }
1469  if (filename[i] == '\\' || filename[i] == '/') {
1470  break;
1471  }
1472  }
1473  return "";
1474  }
1475 
1476 
1477  /// Extracts the filename without the extension.
1478  static inline RStr NoExtension(const RStr& filename) {
1479  if (filename.size() == 0) { return ""; }
1480  for (size_t i=filename.size()-1; i<filename.size(); i--) {
1481  if (filename[i] == '.') {
1482  return filename.substr(0,i);
1483  }
1484  if (filename[i] == '\\' || filename[i] == '/') {
1485  break;
1486  }
1487  }
1488  return filename;
1489  }
1490  };
1491 }
1492 
1493 
1494 #endif // RC_FILE_H
1495 
Provides a one-dimensional vector-like structure.
Provides informative exception handling.
#define Throw_RC_Type(Type, err)
Use this to throw an RC:ErrorMsg subtype exception.
Definition: Errors.h:282
Provides a safe pointer class which throws exceptions.
The version information and configuration settings for RC Lib.
Provides a robust value-added wrapper for std::string.
Provides typedefs and routines for working with primitives.
uint64_t u64
64-bit unsigned integer.
Definition: Types.h:31
int64_t i64
64-bit signed integer.
Definition: Types.h:30
A bounds-safe one-dimensional vector-like structure.
Definition: Data1D.h:49
void Append(const T &newT)
Add an element to the end, expanding if necessary.
Definition: Data1D.h:811
size_t TypeSize() const
Returns the size of this Data1D's type.
Definition: Data1D.h:361
size_t GetOffset() const
Returns the current offset for index 0.
Definition: Data1D.h:372
void Delete()
Delete all the elements and free all allocated memory.
Definition: Data1D.h:188
void Sort()
Sorts the elements according to T::operator< in N*log2(N) time.
Definition: Data1D.h:707
T * Raw() const
Access a raw unprotected C-pointer to the enclosed data.
Definition: Data1D.h:356
void Reserve(const size_t reserve_size)
Reserve storage without resizing the array.
Definition: Data1D.h:271
void SetOffset(const size_t new_offset)
Set a new offset position for index 0.
Definition: Data1D.h:314
size_t size() const
Returns the current number of elements.
Definition: Data1D.h:359
void Assert(const size_t x) const
Throws an ErrorMsgBounds exception if x is out of bounds.
Definition: Data1D.h:262
void Resize(const size_t resize_size)
Resize the array, reallocating if necessary.
Definition: Data1D.h:302
size_t reserved() const
Returns the number of elements for which space is reserved.
Definition: Data1D.h:365
A bounds-safe two-dimensional resizeable structure.
Definition: Data2D.h:32
Data1D< Data1D< T > > & RawData()
Access the underlying nested Data1D structure for this object.
Definition: Data2D.h:300
A bounds-safe three-dimensional resizeable structure.
Definition: Data3D.h:31
const Data1D< Data2D< T > > & RawData() const
Access the underlying nested Data1D/Data2D structure for this object.
Definition: Data3D.h:292
Provides the common methods for the FileRead/FileWrite/FileRW classes.
Definition: File.h:89
void SetPosition(const size_t pos)
Sets the reading and writing position to pos bytes into the file.
Definition: File.h:418
FileBase()
Default constructor.
Definition: File.h:318
void Close()
Flushes the buffers and closes the file.
Definition: File.h:362
FILE * Raw() const
Returns a raw FILE* which can be used with the C file functions.
Definition: File.h:390
void Assert() const
Throws ErrorMsgFile if the file is closed.
Definition: File.h:396
FileBase & operator=(const FileBase &other)
Assignment operator.
Definition: File.h:329
void SetFilename(const RStr &newfilename) const
Manually changes the associated filename.
Definition: File.h:356
size_t GetPosition(bool quiet_fail=false) const
Gets the position for the next read or write operation.
Definition: File.h:442
FileBase(const FileBase &other)
Copy constructor.
Definition: File.h:323
bool IsReadable() const
True if the file is open and readable.
Definition: File.h:379
bool IsOpen() const
True if the file is open.
Definition: File.h:369
void RelativePosition(const i64 amnt)
Sets the position for the next read or write operation.
Definition: File.h:431
bool IsClosed() const
True if the file is closed.
Definition: File.h:374
void ClearBuffer()
Processes the remaining data in the Put/Get buffer.
Definition: File.h:474
void Flush()
Flushes all unsaved data to the storage system.
Definition: File.h:464
RStr GetFilename() const
Returns the filename if one was given upon opening.
Definition: File.h:350
void Rewind()
Clears the read-ahead buffer used by FileRead::Get calls.
Definition: File.h:455
size_t Size() const
Returns the file size in bytes.
Definition: File.h:404
virtual ~FileBase()
Flushes the write buffer before destructing. This will close the file if it is the last FileBase shar...
Definition: File.h:340
bool IsWritable() const
True if the file is open and writable.
Definition: File.h:384
A file class for both reading and writing that provides buffered and unbuffered output to files.
Definition: File.h:1124
bool Open(const RStr &filename, const WriteMode mode=KEEP)
Opens the file specified by filename for reading and writing, using the WriteMode specified by mode.
Definition: File.h:1167
FileRW(const RStr &filename, const WriteMode mode=KEEP)
Opens the file specified by filename for reading and writing, using the WriteMode specified by mode.
Definition: File.h:1135
FileRW(const FileBase &other)
Base copy constructor.
Definition: File.h:1160
FileRW(FILE *fp)
Wraps the FILE* fp for reading and writing. It will close it when finished unless fp is stdin/stdout/...
Definition: File.h:1155
FileRW(FILE *fp, bool do_close)
Wraps the FILE* fp for reading and writing. It will close it when finished if do_close is true.
Definition: File.h:1149
void Open(FILE *fp, bool do_close)
Wraps the FILE* fp for reading and writing. It will close it when finished if do_close is true.
Definition: File.h:1173
void Open(FILE *fp)
Wraps the FILE* fp for reading and writing. It will close it when finished unless fp is stdin/stdout/...
Definition: File.h:1181
FileRW()
Default constructor.
Definition: File.h:1128
A file reading class that provides buffered and unbuffered access to files with support for non-POD c...
Definition: File.h:483
FileRead(const RStr &filename)
Opens the file specified by filename for reading.
Definition: File.h:520
bool Get(Data2D< T > &data)
Fill data with elements of type T, calling Get on each one.
Definition: File.h:847
void Open(FILE *fp, bool do_close)
Wraps the FILE* fp for reading. It will close it when finished if do_close is true.
Definition: File.h:551
bool GetAll(Data1D< T > &data)
Fill data with all elements of type T until the end of file, calling Get on each one.
Definition: File.h:880
bool Get(T &data)
Gets data of type T, after passing through FileGetWrapper.
Definition: File.h:774
bool Get(Data1D< T > &data)
Fill data with elements of type T, calling Get on each one.
Definition: File.h:831
void ReadAll(Data1D< RStr > &lines, bool crop_newlines=true)
Does ReadAllLines.
Definition: File.h:739
void ReadAllLines(Data1D< RStr > &lines, bool crop_newlines=true)
Reads all the lines found until the end of the file. If crop_newlines is true they are removed from e...
Definition: File.h:726
bool Get(Data1D< RStr > &data, bool crop_newlines=true)
Fill data with lines from the file, removing the newlines if crop_newlines is true.
Definition: File.h:816
FileRead(FILE *fp)
Wraps the FILE* fp for reading. It will close it when finished unless fp is stdin.
Definition: File.h:534
FileRead(const FileBase &other)
Base copy constructor.
Definition: File.h:539
void ReadAll(Data1D< T > &data)
Reads all data until the end of file into data as plain old data type T.
Definition: File.h:610
void Open(FILE *fp)
Wraps the FILE* fp for reading. It will close it when finished unless fp is stdin.
Definition: File.h:558
bool RawGet(T &data)
Performs a buffered read of sizeof(T) bytes and assigns them to data.
Definition: File.h:748
bool SkipLine()
Discards one line until newline, null, or end of file.
Definition: File.h:718
FileRead()
Default constructor.
Definition: File.h:514
bool GetAll(Data1D< RStr > &data, bool crop_newlines=true)
Fill data with all lines from the file until the end, removing the newlines if crop_newlines is true.
Definition: File.h:864
bool Get(Data3D< T > &data)
Fill data with elements of type T, calling Get on each one.
Definition: File.h:856
FileRead(FILE *fp, bool do_close)
Wraps the FILE* fp for reading. It will close it when finished if do_close is true.
Definition: File.h:528
size_t Read(Data1D< T > &data, const size_t amnt_to_read)
Reads amnt_to_read elements of plain old data type T into data without buffering, resizing if too sma...
Definition: File.h:569
bool Read(RStr &line, bool crop_newline=true)
Does ReadLine.
Definition: File.h:712
bool Get(RStr &data, bool crop_newline=true)
Gets one line into data, up to the newline, null, or end of file, removing the newline if crop_newlin...
Definition: File.h:780
bool Open(const RStr &filename)
Opens the file specified by filename for reading.
Definition: File.h:545
size_t Read(Data1D< T > &data)
Fills data with plain old data type T without buffering.
Definition: File.h:602
bool ReadLine(RStr &line, bool crop_newline=true)
Reads one line until newline, null, or end of file. The newline is removed if crop_newline is true.
Definition: File.h:657
A file writing class that provides buffered and unbuffered output to files with support for non-POD c...
Definition: File.h:895
FileWrite & operator<<(FileRead &read)
Get all the remaining data from the FileRead, and Put it to this FileWrite.
Definition: File.h:1103
void Put(const Data1D< RStr > &data, const bool add_newline)
Puts each RStr in data into the write buffer, adding newlines to each if add_newline is true.
Definition: File.h:1091
void RawPut(const T &data)
Performs a buffered write of sizeof(T) raw bytes extracted from data.
Definition: File.h:1020
void WriteStr(const RStr &str)
Writes the RStr str without buffering.
Definition: File.h:994
void Put(const RStr &str)
Puts the RStr str into the write buffer.
Definition: File.h:1061
void Write(const Data1D< T > &data)
Writes all of data's plain old data type T without buffering.
Definition: File.h:970
FileWrite()
Default constructor.
Definition: File.h:899
void WriteAllStr(const Data1D< RStr > &lines, const bool add_newlines)
Writes all lines without buffering, adding a newline after each if add_newlines is true.
Definition: File.h:1005
void Put(const Data1D< T > &data)
Calls Put for each element of data.
Definition: File.h:1067
void Put(const char *str)
Puts the null-terminated character data str into the write buffer, excluding the null.
Definition: File.h:1052
FileWrite(const FileBase &other)
Base copy constructor.
Definition: File.h:931
void Put(const Data3D< T > &data)
Calls Put for each element of data.
Definition: File.h:1085
FileWrite(const RStr &filename, const WriteMode mode=TRUNCATE)
Opens the file specified by filename for writing, using the WriteMode specified by mode.
Definition: File.h:906
void WriteStr(const char *str)
Writes the null-terminated contents of str without buffering.
Definition: File.h:978
void Write(const Data1D< T > &data, const size_t amnt_to_write)
Writes amnt_to_write elements of plain old data type T from data without buffering.
Definition: File.h:961
bool Open(const RStr &filename, const WriteMode mode=TRUNCATE)
Opens the file specified by filename for writing, using the WriteMode specified by mode.
Definition: File.h:938
void Put(const Data2D< T > &data)
Calls Put for each element of data.
Definition: File.h:1077
void Put(const T &data)
Puts data of type T into the write buffer, after passing through FilePutWrapper.
Definition: File.h:1048
FileWrite(FILE *fp, bool do_close)
Wraps the FILE* fp for writing. It will close it when finished if do_close is true.
Definition: File.h:920
FileWrite(FILE *fp)
Wraps the FILE* fp for writing. It will close it when finished unless fp is stdout.
Definition: File.h:926
void Open(FILE *fp, bool do_close)
Wraps the FILE* fp for writing. It will close it when finished if do_close is true.
Definition: File.h:944
void Open(FILE *fp)
Wraps the FILE* fp for writing. It will close it when finished unless fp is stdout or stderr.
Definition: File.h:951
A class with static methods for file and directory info and manipulation.
Definition: File.h:1214
static void Move(const RStr &srcfile, const RStr &destfile, bool overwrite=true)
Moves srcfile to destfile by copying the contents and then deleting srcfile.
Definition: File.h:1287
static RStr CurrentDir()
Returns the current working directory.
Definition: File.h:1348
static RStr FullPath(const RStr &path, const RStr &filename)
Merges path and filename into a path with a divider inserted if needed.
Definition: File.h:1452
static size_t Size(const RStr &pathname)
Returns the file size of pathname, or 0 if the file does not exist.
Definition: File.h:1225
static Data1D< RStr > DirList(const RStr &path, bool qualified=false)
Returns a list of entries in the directory path.
Definition: File.h:1368
static bool MakeDir(const RStr &dirname, bool return_true_if_exists=true)
Makes a new directory dirname.
Definition: File.h:1324
static RStr Extension(const RStr &filename)
Extracts the filename's extension.
Definition: File.h:1463
static bool Exists(const RStr &pathname)
Returns true if the file pathname exists.
Definition: File.h:1242
static void Copy(const RStr &srcfile, const RStr &destfile, bool overwrite=true)
Copies the contents of srcfile to destfile. It will overwrite an existing file only if overwrite is t...
Definition: File.h:1270
static bool Delete(const RStr &pathname, bool quiet_fail=true)
Deletes the file pathname, returning true if it succeeded.
Definition: File.h:1256
static RStr Dirname(const RStr &filename)
Extracts the directory portion of filename, or the current directory if filename has no directory.
Definition: File.h:1422
static const char divider
The OS-specific divider between directories in a pathname.
Definition: File.h:1219
static RStr NoExtension(const RStr &filename)
Extracts the filename without the extension.
Definition: File.h:1478
static RStr Basename(const RStr &filename)
Extracts the basename portion of filename, which excludes the directory.
Definition: File.h:1439
A bounds-safe string class which provides an identical interface to std::string plus many convenience...
Definition: RStr.h:110
size_t size() const
Returns the length of the string.
Definition: RStr.h:263
const char * c_str() const
Provides a null-terminated C style string corresponding to RStr.
Definition: RStr.h:622
Data1D< RStr > SplitLast(const RStr &dividers) const
Return an array of 2 strings split at the last character from dividers.
Definition: RStr.h:1684
std::string & Raw()
Provides raw access to the std::string this RStr wraps.
Definition: RStr.h:1325
const char * ToLPCTSTR()
For Win32, provides an LPCTSTR to the string.
Definition: RStr.h:1317
size_t length() const
Returns the length of the string.
Definition: RStr.h:265
RStr substr(size_t pos=0, size_t n=npos) const
Creates a substring from n characters starting at position pos, or until the end of the string.
Definition: RStr.h:826
size_t find_last_of(const RStr &s, size_t pos=npos) const
Returns the highest index at pos or before which matches a character in s, or npos if none match.
Definition: RStr.h:739
static const size_t npos
The largest possible value of size_t.
Definition: RStr.h:2215
Definition: APtr.h:25
WriteMode
Valid write modes for a FileWrite or FileRW.
Definition: File.h:86
void FilePutWrapper(FileWrite &fw, const T &data)
Overload this with a specialization to support Put on a custom type.
Definition: File.h:1193
bool FileGetWrapper(FileRead &fr, T &data)
Overload this with a specialization to support Get on a custom type.
Definition: File.h:1188
email address
— (c) 2015