1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: m_fileio.cpp 4469 2014-01-03 23:38:29Z dr_sean $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Copyright (C) 2006-2014 by The Odamex Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // DESCRIPTION:
20 // File Input/Output Operations
21 //
22 //-----------------------------------------------------------------------------
23
24 #include "m_fileio.h"
25 #include "c_dispatch.h"
26 #include "z_zone.h"
27
28 // unfortunately, we still need you
29 #include "cmdlib.h"
30
31 // Simple logging
32 std::ofstream LOG;
33
34 // Simple file based console input
35 std::ifstream CON;
36
37 //
38 // M_FileLength
39 //
40 // Returns the length of a file using an open descriptor
M_FileLength(FILE * f)41 SDWORD M_FileLength (FILE *f)
42 {
43 SDWORD CurrentPosition = -1;
44 SDWORD FileSize = -1;
45
46 if (f != NULL)
47 {
48 CurrentPosition = ftell (f);
49 fseek (f, 0, SEEK_END);
50 FileSize = ftell (f);
51 fseek (f, CurrentPosition, SEEK_SET);
52 }
53
54 return FileSize;
55 }
56
57 //
58 // M_FileExists
59 //
60 // Checks to see whether a file exists or not
61 //
M_FileExists(const std::string & filename)62 bool M_FileExists(const std::string& filename)
63 {
64 FILE *f = fopen(filename.c_str(), "r");
65 if (!f)
66 return false;
67 fclose(f);
68 return true;
69 }
70
71 //
72 // M_WriteFile
73 //
74 // Writes a buffer to a new file, if it already exists, the file will be
75 // erased and recreated with the new contents
M_WriteFile(std::string filename,void * source,QWORD length)76 BOOL M_WriteFile(std::string filename, void *source, QWORD length)
77 {
78 FILE *handle;
79 QWORD count;
80
81 handle = fopen(filename.c_str(), "wb");
82
83 if (handle == NULL)
84 {
85 Printf(PRINT_HIGH, "Could not open file %s for writing\n", filename.c_str());
86 return false;
87 }
88
89 count = fwrite(source, 1, length, handle);
90 fclose(handle);
91
92 if (count != length)
93 {
94 Printf(PRINT_HIGH, "Failed while writing to file %s\n", filename.c_str());
95 return false;
96 }
97
98 return true;
99 }
100
101
102 //
103 // M_ReadFile
104 //
105 // Reads a file, it will allocate storage via Z_Malloc for it and return
106 // the buffer and the size.
M_ReadFile(std::string filename,BYTE ** buffer)107 QWORD M_ReadFile(std::string filename, BYTE **buffer)
108 {
109 FILE *handle;
110 QWORD count, length;
111 BYTE *buf;
112
113 handle = fopen(filename.c_str(), "rb");
114
115 if (handle == NULL)
116 {
117 Printf(PRINT_HIGH, "Could not open file %s for reading\n", filename.c_str());
118 return false;
119 }
120
121 length = M_FileLength(handle);
122
123 buf = (BYTE *)Z_Malloc (length, PU_STATIC, NULL);
124 count = fread(buf, 1, length, handle);
125 fclose (handle);
126
127 if (count != length)
128 {
129 Printf(PRINT_HIGH, "Failed while reading from file %s\n", filename.c_str());
130 return false;
131 }
132
133 *buffer = buf;
134 return length;
135 }
136
137 //
138 // M_AppendExtension
139 //
140 // Add an extension onto the end of a filename, returns false if it failed.
141 // if_needed detects if an extension is not present in path, if it isn't, it is
142 // added.
143 // The extension must contain a . at the beginning
M_AppendExtension(std::string & filename,std::string extension,bool if_needed)144 BOOL M_AppendExtension (std::string &filename, std::string extension, bool if_needed)
145 {
146 FixPathSeparator(filename);
147
148 size_t l = filename.find_last_of(PATHSEPCHAR);
149 if(l == filename.length())
150 return false;
151
152 size_t dot = extension.find_first_of('.');
153 if (dot == std::string::npos)
154 return false;
155
156 if (if_needed)
157 {
158 size_t dot = filename.find_last_of('.');
159
160 if (dot == std::string::npos)
161 filename.append(extension);
162
163 return true;
164 }
165
166 filename.append(extension);
167
168 return true;
169 }
170
171 //
172 // M_ExtractFilePath
173 //
174 // Extract the path from a filename that includes one
M_ExtractFilePath(const std::string & filename,std::string & dest)175 void M_ExtractFilePath(const std::string& filename, std::string &dest)
176 {
177 dest = filename;
178 FixPathSeparator(dest);
179
180 size_t l = dest.find_last_of(PATHSEPCHAR);
181 if (l == std::string::npos)
182 dest.clear();
183 else if (l < dest.length())
184 dest = dest.substr(0, l);
185 }
186
187 //
188 // M_ExtractFileExtension
189 //
190 // Extract the extension of a file, returns false if it can't find
191 // extension seperator, true if succeeded, the extension is returned in
192 // dest
M_ExtractFileExtension(const std::string & filename,std::string & dest)193 bool M_ExtractFileExtension(const std::string& filename, std::string &dest)
194 {
195 if (!filename.length())
196 return false;
197
198 // find the last dot, iterating backwards
199 size_t last_dot = filename.find_last_of('.', filename.length());
200 if (last_dot == std::string::npos)
201 dest.clear();
202 else
203 dest = filename.substr(last_dot + 1);
204
205 return (!dest.empty());
206 }
207
208 //
209 // M_ExtractFileBase
210 //
211 // Extract the base file name from a path string (basefile = filename with no extension)
212 //
213 // e.g. /asdf/qwerty.zxc -> qwerty
214 // iuyt.wad -> iuyt
215 // hgfd -> hgfd
216 //
217 // Note: On windows, text after the last . is considered the extension, so any preceding
218 // .'s won't be removed
M_ExtractFileBase(std::string filename,std::string & dest)219 void M_ExtractFileBase (std::string filename, std::string &dest)
220 {
221 FixPathSeparator(filename);
222
223 size_t l = filename.find_last_of(PATHSEPCHAR);
224 if(l == std::string::npos)
225 l = 0;
226 else
227 l++;
228
229 size_t e = filename.find_last_of('.');
230 if(e == std::string::npos)
231 e = filename.length();
232
233 if(l < filename.length())
234 dest = filename.substr(l, e - l);
235 }
236
237 //
238 // M_ExtractFileName
239 //
240 // Extract the name of a file from a path (name = filename with extension)
M_ExtractFileName(std::string filename,std::string & dest)241 void M_ExtractFileName (std::string filename, std::string &dest)
242 {
243 FixPathSeparator(filename);
244
245 size_t l = filename.find_last_of(PATHSEPCHAR);
246 if(l == std::string::npos)
247 l = 0;
248 else
249 l++;
250
251 if(l < filename.length())
252 dest = filename.substr(l);
253 }
254
M_ExtractFileName(const std::string filename)255 std::string M_ExtractFileName(const std::string filename) {
256 std::string result;
257 M_ExtractFileName(filename, result);
258 return result;
259 }
260
261 VERSION_CONTROL (m_fileio_cpp, "$Id: m_fileio.cpp 4469 2014-01-03 23:38:29Z dr_sean $")
262