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