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