]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/profile/file.cpp
ok
[xonotic/netradiant.git] / libs / profile / file.cpp
1 /*
2 Copyright (c) 2001, Loki software, inc.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, 
6 are permitted provided that the following conditions are met:
7
8 Redistributions of source code must retain the above copyright notice, this list 
9 of conditions and the following disclaimer.
10
11 Redistributions in binary form must reproduce the above copyright notice, this
12 list of conditions and the following disclaimer in the documentation and/or
13 other materials provided with the distribution.
14
15 Neither the name of Loki software nor the names of its contributors may be used 
16 to endorse or promote products derived from this software without specific prior 
17 written permission. 
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
22 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
23 DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
29 */
30
31 //
32 // File class, can be a memory file or a regular disk file.
33 // Originally from LeoCAD, used with permission from the author. :)
34 //
35 // Leonardo Zide (leo@lokigames.com)
36 //
37
38 #include "file.h"
39
40 #include <memory.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <stdarg.h>
44
45 /////////////////////////////////////////////////////////////////////////////
46 // File construction/destruction
47
48 MemStream::MemStream()
49 {
50   m_nGrowBytes = 1024;
51   m_nPosition = 0;
52   m_nBufferSize = 0;
53   m_nFileSize = 0;
54   m_pBuffer = NULL;
55   m_bAutoDelete = true;
56 }
57
58 MemStream::MemStream(size_type nLen)
59 {
60   m_nGrowBytes = 1024;
61   m_nPosition = 0;
62   m_nBufferSize = 0;
63   m_nFileSize = 0;
64   m_pBuffer = NULL;
65   m_bAutoDelete = true;
66
67   GrowFile (nLen);
68 }
69
70 FileStream::FileStream()
71 {
72   m_hFile = NULL;
73   m_bCloseOnDelete = false;
74 }
75
76 MemStream::~MemStream()
77 {
78   if (m_pBuffer)
79     Close();
80
81   m_nGrowBytes = 0;
82   m_nPosition = 0;
83   m_nBufferSize = 0;
84   m_nFileSize = 0;
85 }
86
87 FileStream::~FileStream()
88 {
89   if (m_hFile != NULL && m_bCloseOnDelete)
90     Close();
91 }
92
93 /////////////////////////////////////////////////////////////////////////////
94 // File operations
95
96 char* MemStream::ReadString(char* pBuf, size_type nMax)
97 {
98   int nRead = 0;
99   unsigned char ch;
100
101   if (nMax <= 0)
102     return NULL;
103   if (m_nPosition >= m_nFileSize)
104     return NULL;
105
106   while ((--nMax))
107   {
108     if (m_nPosition == m_nFileSize)
109       break;
110
111     ch = m_pBuffer[m_nPosition];
112     m_nPosition++;
113     pBuf[nRead++] = ch;
114
115     if (ch == '\n')
116       break;
117   }
118
119   pBuf[nRead] = '\0';
120   return pBuf;
121 }
122
123 char* FileStream::ReadString(char* pBuf, size_type nMax)
124 {
125   return fgets(pBuf, static_cast<int>(nMax), m_hFile);
126 }
127
128 MemStream::size_type MemStream::read(byte_type* buffer, size_type length)
129 {
130   if (length == 0)
131     return 0;
132
133   if (m_nPosition > m_nFileSize)
134     return 0;
135
136   size_type nRead;
137   if (m_nPosition + length > m_nFileSize)
138     nRead = m_nFileSize - m_nPosition;
139   else
140     nRead = length;
141
142   memcpy((unsigned char*)buffer, (unsigned char*)m_pBuffer + m_nPosition, nRead);
143   m_nPosition += nRead;
144
145   return nRead;
146 }
147
148 FileStream::size_type FileStream::read(byte_type* buffer, size_type length)
149 {
150   return fread(buffer, 1, length, m_hFile);
151 }
152
153 int MemStream::GetChar()
154 {
155   if (m_nPosition > m_nFileSize)
156     return 0;
157
158   unsigned char* ret = (unsigned char*)m_pBuffer + m_nPosition;
159   m_nPosition++;
160
161   return *ret;
162 }
163
164 int FileStream::GetChar()
165 {
166   return fgetc(m_hFile);
167 }
168
169 MemStream::size_type MemStream::write(const byte_type* buffer, size_type length)
170 {
171   if (length == 0)
172     return 0;
173
174   if (m_nPosition + length > m_nBufferSize)
175     GrowFile(m_nPosition + length);
176
177   memcpy((unsigned char*)m_pBuffer + m_nPosition, (unsigned char*)buffer, length);
178
179   m_nPosition += size_type(length);
180
181   if (m_nPosition > m_nFileSize)
182     m_nFileSize = m_nPosition;
183
184   return length;
185 }
186
187 FileStream::size_type FileStream::write(const byte_type* buffer, size_type length)
188 {
189   return fwrite(buffer, 1, length, m_hFile);
190 }
191
192 int MemStream::PutChar(int c)
193 {
194   if (m_nPosition + 1 > m_nBufferSize)
195     GrowFile(m_nPosition + 1);
196
197   unsigned char* bt = (unsigned char*)m_pBuffer + m_nPosition;
198   *bt = c;
199
200   m_nPosition++;
201
202   if (m_nPosition > m_nFileSize)
203     m_nFileSize = m_nPosition;
204
205   return 1;
206 }
207
208 /*!\todo SPoG suggestion: replace printf with operator >> using c++ iostream and strstream */
209 void FileStream::printf(const char* s, ...)
210 {
211   va_list args;
212
213   va_start (args, s);
214   vfprintf(m_hFile, s, args);
215   va_end (args);
216 }
217
218 /*!\todo SPoG suggestion: replace printf with operator >> using c++ iostream and strstream */
219 void MemStream::printf(const char* s, ...)
220 {
221   va_list args;
222
223   char buffer[4096];
224   va_start (args, s);
225   vsprintf(buffer, s, args);
226   va_end (args);
227   write(reinterpret_cast<byte_type*>(buffer), strlen(buffer));
228 }
229
230 int FileStream::PutChar(int c)
231 {
232   return fputc(c, m_hFile);
233 }
234
235 bool FileStream::Open(const char *filename, const char *mode)
236 {
237   m_hFile = fopen(filename, mode);
238   m_bCloseOnDelete = true;
239
240   return (m_hFile != NULL);
241 }
242
243 void MemStream::Close()
244 {
245   m_nGrowBytes = 0;
246   m_nPosition = 0;
247   m_nBufferSize = 0;
248   m_nFileSize = 0;
249   if (m_pBuffer && m_bAutoDelete)
250     free(m_pBuffer);
251   m_pBuffer = NULL;
252 }
253
254 void FileStream::Close()
255 {
256   if (m_hFile != NULL)
257     fclose(m_hFile);
258
259   m_hFile = NULL;
260   m_bCloseOnDelete = false;
261 }
262
263 int MemStream::Seek(offset_type lOff, int nFrom)
264 {
265   size_type lNewPos = m_nPosition;
266
267   if (nFrom == SEEK_SET)
268     lNewPos = lOff;
269   else if (nFrom == SEEK_CUR)
270     lNewPos += lOff;
271   else if (nFrom == SEEK_END)
272     lNewPos = m_nFileSize + lOff;
273   else
274     return (position_type)-1;
275
276   m_nPosition = lNewPos;
277
278   return static_cast<int>(m_nPosition);
279 }
280
281 int FileStream::Seek(offset_type lOff, int nFrom)
282 {
283   fseek (m_hFile, lOff, nFrom);
284
285   return ftell(m_hFile);
286 }
287
288 MemStream::position_type MemStream::GetPosition() const
289 {
290     return m_nPosition;
291 }
292
293 FileStream::position_type FileStream::GetPosition() const
294 {
295   return ftell(m_hFile);
296 }
297
298 void MemStream::GrowFile(size_type nNewLen)
299 {
300   if (nNewLen > m_nBufferSize)
301   {
302     // grow the buffer
303     size_type nNewBufferSize = m_nBufferSize;
304
305     // determine new buffer size
306     while (nNewBufferSize < nNewLen)
307       nNewBufferSize += m_nGrowBytes;
308
309     // allocate new buffer
310     unsigned char* lpNew;
311     if (m_pBuffer == NULL)
312       lpNew = static_cast<unsigned char*>(malloc(nNewBufferSize));
313     else
314       lpNew = static_cast<unsigned char*>(realloc(m_pBuffer, nNewBufferSize));
315
316     m_pBuffer = lpNew;
317     m_nBufferSize = nNewBufferSize;
318   }
319 }
320
321 void MemStream::Flush()
322 {
323   // Nothing to be done
324 }
325
326 void FileStream::Flush()
327 {
328   if (m_hFile == NULL)
329     return;
330
331   fflush(m_hFile);
332 }
333
334 void MemStream::Abort()
335 {
336   Close();
337 }
338
339 void FileStream::Abort()
340 {
341   if (m_hFile != NULL)
342   {
343     // close but ignore errors
344     if (m_bCloseOnDelete)
345       fclose(m_hFile);
346     m_hFile = NULL;
347     m_bCloseOnDelete = false;
348   }
349 }
350
351 void MemStream::SetLength(size_type nNewLen)
352 {
353   if (nNewLen > m_nBufferSize)
354     GrowFile(nNewLen);
355
356   if (nNewLen < m_nPosition)
357     m_nPosition = nNewLen;
358
359   m_nFileSize = nNewLen;
360 }
361
362 void FileStream::SetLength(size_type nNewLen)
363 {
364   fseek(m_hFile, static_cast<long>(nNewLen), SEEK_SET);
365 }
366
367 MemStream::size_type MemStream::GetLength() const
368 {
369   return m_nFileSize;
370 }
371
372 FileStream::size_type FileStream::GetLength() const
373 {
374   size_type nLen, nCur;
375
376   // Seek is a non const operation
377   nCur = ftell(m_hFile);
378   fseek(m_hFile, 0, SEEK_END);
379   nLen = ftell(m_hFile);
380   fseek(m_hFile, static_cast<long>(nCur), SEEK_SET);
381
382   return nLen;
383 }