1 /* 2 * Copyright (C) 2006-2020 by the Widelands Development Team 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 * 18 */ 19 20 #ifndef WL_IO_FILEREAD_H 21 #define WL_IO_FILEREAD_H 22 23 #include <limits> 24 25 #ifndef _WIN32 26 #include <sys/mman.h> 27 #endif 28 29 #include "io/filesystem/filesystem.h" 30 #include "io/streamread.h" 31 32 /// Can be used to read a file. It works quite naively by reading the entire 33 /// file into memory. Convenience functions are available for endian-safe 34 /// access of common data types. 35 class FileRead : public StreamRead { 36 public: 37 struct Pos { posPos38 Pos(size_t const p = 0) : pos(p) { 39 } 40 /// Returns a special value indicating invalidity. nullPos41 static Pos null() { 42 return std::numeric_limits<size_t>::max(); 43 } 44 is_nullPos45 bool is_null() const { 46 return *this == null(); 47 } size_tPos48 operator size_t() const { 49 return pos; 50 } 51 Pos operator++() { 52 return ++pos; 53 } 54 55 Pos operator+=(Pos const other) { 56 return pos += other.pos; 57 } 58 59 private: 60 size_t pos; 61 }; 62 63 struct FileBoundaryExceeded : public StreamRead::DataError { FileBoundaryExceededFileBoundaryExceeded64 FileBoundaryExceeded() : StreamRead::DataError("end of file") { 65 } 66 }; 67 68 /// Create the object with nothing to read. 69 FileRead(); 70 71 ~FileRead() override; 72 73 // See base class. 74 size_t data(void* dst, size_t bufsize) override; 75 bool end_of_file() const override; 76 char const* c_string() override; 77 78 /// Loads a file into memory. Reserves one additional byte which is zeroed, 79 /// so that text files can be handled like a null-terminated string. 80 /// \throws an exception if the file couldn't be loaded for whatever reason. 81 82 // TODO(unknown): error handling 83 void open(FileSystem& fs, const std::string& filename); 84 85 /// Works just like open, but returns false when the load fails. 86 // TODO(sirver): This method can be expressed through open() and should not 87 // be part of the public API, rather a stand alone function. 88 bool try_open(FileSystem& fs, const std::string& filename); 89 90 /// Frees allocated memory. 91 void close(); 92 93 // Returns the size of the file in bytes; 94 size_t get_size() const; 95 96 /// Set the file pointer to the given location. 97 /// \throws File_Boundary_Exceeded if the pointer is out of bound. 98 void set_file_pos(const Pos& pos); 99 100 /// Get the position that will be read from in the next read operation that 101 /// does not specify a position. 102 Pos get_pos() const; 103 104 // Returns the next 'bytes' starting at 'pos' in the file. Can throw 105 // File_Boundary_Exceeded. 106 char* data(uint32_t bytes, const Pos& pos = Pos::null()); 107 108 // Returns the whole file as a string starting from 'pos'. 109 char* c_string(const Pos& pos); 110 111 // Returns the next line. 112 char* read_line(); 113 114 private: 115 char* data_; 116 size_t length_; 117 Pos filepos_; 118 }; 119 120 #endif // end of include guard: WL_IO_FILEREAD_H 121