]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/file.cpp
apply patch from Martin Gerhardy - more quake2 related modules compiled and misc...
[xonotic/netradiant.git] / radiant / 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 "stdafx.h"
39
40 #include <stdio.h>
41 #include <memory.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45
46 IDataStream::IDataStream()
47 { }
48   
49 IDataStream::~IDataStream()
50 { }
51
52 /////////////////////////////////////////////////////////////////////////////
53 // File construction/destruction
54
55 MemStream::MemStream()
56 {
57   m_nGrowBytes = 1024;
58   m_nPosition = 0;
59   m_nBufferSize = 0;
60   m_nFileSize = 0;
61   m_pBuffer = NULL;
62   m_bAutoDelete = true;
63 }
64
65 MemStream::MemStream(unsigned long nLen)
66 {
67   m_nGrowBytes = 1024;
68   m_nPosition = 0;
69   m_nBufferSize = 0;
70   m_nFileSize = 0;
71   m_pBuffer = NULL;
72   m_bAutoDelete = true;
73
74   GrowFile (nLen);
75 }
76
77 FileStream::FileStream()
78 {
79   m_hFile = NULL;
80   m_bCloseOnDelete = false;
81 }
82
83 MemStream::~MemStream()
84 {
85   if (m_pBuffer)
86     Close();
87
88   m_nGrowBytes = 0;
89   m_nPosition = 0;
90   m_nBufferSize = 0;
91   m_nFileSize = 0;
92 }
93
94 FileStream::~FileStream()
95 {
96   if (m_hFile != NULL && m_bCloseOnDelete)
97     Close();
98 }
99
100 /////////////////////////////////////////////////////////////////////////////
101 // File operations
102
103 char* MemStream::ReadString(char* pBuf, unsigned long nMax)
104 {
105   int nRead = 0;
106   unsigned char ch;
107
108   if (nMax <= 0)
109     return NULL;
110   if (m_nPosition >= m_nFileSize)
111     return NULL;
112
113   while ((--nMax))
114   {
115     if (m_nPosition == m_nFileSize)
116       break;
117
118     ch = m_pBuffer[m_nPosition];
119     m_nPosition++;
120     pBuf[nRead++] = ch;
121
122     if (ch == '\n')
123       break;
124   }
125
126   pBuf[nRead] = '\0';
127   return pBuf;
128 }
129
130 char* FileStream::ReadString(char* pBuf, unsigned long nMax)
131 {
132   return fgets(pBuf, nMax, m_hFile);
133 }
134
135 unsigned long MemStream::Read(void* pBuf, unsigned long nCount)
136 {
137   if (nCount == 0)
138     return 0;
139
140   if (m_nPosition > m_nFileSize)
141     return 0;
142
143   unsigned long nRead;
144   if (m_nPosition + nCount > m_nFileSize)
145     nRead = (unsigned long)(m_nFileSize - m_nPosition);
146   else
147     nRead = nCount;
148
149   memcpy((unsigned char*)pBuf, (unsigned char*)m_pBuffer + m_nPosition, nRead);
150   m_nPosition += nRead;
151
152   return nRead;
153 }
154
155 unsigned long FileStream::Read(void* pBuf, unsigned long nCount)
156 {
157   return fread(pBuf, 1, nCount, m_hFile);
158 }
159
160 int MemStream::GetChar()
161 {
162   if (m_nPosition > m_nFileSize)
163     return 0;
164
165   unsigned char* ret = (unsigned char*)m_pBuffer + m_nPosition;
166   m_nPosition++;
167
168   return *ret;
169 }
170
171 int FileStream::GetChar()
172 {
173   return fgetc(m_hFile);
174 }
175
176 unsigned long MemStream::Write(const void* pBuf, unsigned long nCount)
177 {
178   if (nCount == 0)
179     return 0;
180
181   if (m_nPosition + nCount > m_nBufferSize)
182     GrowFile(m_nPosition + nCount);
183
184   memcpy((unsigned char*)m_pBuffer + m_nPosition, (unsigned char*)pBuf, nCount);
185
186   m_nPosition += nCount;
187
188   if (m_nPosition > m_nFileSize)
189     m_nFileSize = m_nPosition;
190
191   return nCount;
192 }
193
194 unsigned long FileStream::Write(const void* pBuf, unsigned long nCount)
195 {
196   return fwrite(pBuf, 1, nCount, m_hFile);
197 }
198
199 int MemStream::PutChar(int c)
200 {
201   if (m_nPosition + 1 > m_nBufferSize)
202     GrowFile(m_nPosition + 1);
203
204   unsigned char* bt = (unsigned char*)m_pBuffer + m_nPosition;
205   *bt = c;
206
207   m_nPosition++;
208
209   if (m_nPosition > m_nFileSize)
210     m_nFileSize = m_nPosition;
211
212   return 1;
213 }
214
215 /*!\todo SPoG suggestion: replace printf with operator >> using c++ iostream and strstream */
216 void FileStream::printf(const char* s, ...)
217 {
218   va_list args;
219
220   va_start (args, s);
221   vfprintf(m_hFile, s, args);
222   va_end (args);
223 }
224
225 /*!\todo SPoG suggestion: replace printf with operator >> using c++ iostream and strstream */
226 void MemStream::printf(const char* s, ...)
227 {
228   va_list args;
229
230   char buffer[4096];
231   va_start (args, s);
232   vsprintf(buffer, s, args);
233   va_end (args);
234   Write(buffer, strlen(buffer));
235 }
236
237 int FileStream::PutChar(int c)
238 {
239   return fputc(c, m_hFile);
240 }
241
242 bool FileStream::Open(const char *filename, const char *mode)
243 {
244   m_hFile = fopen(filename, mode);
245   m_bCloseOnDelete = true;
246
247   return (m_hFile != NULL);
248 }
249
250 void MemStream::Close()
251 {
252   m_nGrowBytes = 0;
253   m_nPosition = 0;
254   m_nBufferSize = 0;
255   m_nFileSize = 0;
256   if (m_pBuffer && m_bAutoDelete)
257     free(m_pBuffer);
258   m_pBuffer = NULL;
259 }
260
261 void FileStream::Close()
262 {
263   if (m_hFile != NULL)
264     fclose(m_hFile);
265
266   m_hFile = NULL;
267   m_bCloseOnDelete = false;
268 }
269
270 unsigned long MemStream::Seek(long lOff, int nFrom)
271 {
272   unsigned long lNewPos = m_nPosition;
273
274   if (nFrom == SEEK_SET)
275     lNewPos = lOff;
276   else if (nFrom == SEEK_CUR)
277     lNewPos += lOff;
278   else if (nFrom == SEEK_END)
279     lNewPos = m_nFileSize + lOff;
280   else
281     return (unsigned long)-1;
282
283   m_nPosition = lNewPos;
284
285   return m_nPosition;
286 }
287
288 unsigned long FileStream::Seek(long lOff, int nFrom)
289 {
290   fseek (m_hFile, lOff, nFrom);
291
292   return ftell(m_hFile);
293 }
294
295 unsigned long MemStream::GetPosition() const
296 {
297     return m_nPosition;
298 }
299
300 unsigned long FileStream::GetPosition() const
301 {
302   return ftell(m_hFile);
303 }
304
305 void MemStream::GrowFile(unsigned long nNewLen)
306 {
307   if (nNewLen > m_nBufferSize)
308   {
309     // grow the buffer
310     unsigned long nNewBufferSize = m_nBufferSize;
311
312     // determine new buffer size
313     while (nNewBufferSize < nNewLen)
314       nNewBufferSize += m_nGrowBytes;
315
316     // allocate new buffer
317     unsigned char* lpNew;
318     if (m_pBuffer == NULL)
319       lpNew = static_cast<unsigned char*>(malloc(nNewBufferSize));
320     else
321       lpNew = static_cast<unsigned char*>(realloc(m_pBuffer, nNewBufferSize));
322
323     m_pBuffer = lpNew;
324     m_nBufferSize = nNewBufferSize;
325   }
326 }
327
328 void MemStream::Flush()
329 {
330   // Nothing to be done
331 }
332
333 void FileStream::Flush()
334 {
335   if (m_hFile == NULL)
336     return;
337
338   fflush(m_hFile);
339 }
340
341 void MemStream::Abort()
342 {
343   Close();
344 }
345
346 void FileStream::Abort()
347 {
348   if (m_hFile != NULL)
349   {
350     // close but ignore errors
351     if (m_bCloseOnDelete)
352       fclose(m_hFile);
353     m_hFile = NULL;
354     m_bCloseOnDelete = false;
355   }
356 }
357
358 void MemStream::SetLength(unsigned long nNewLen)
359 {
360   if (nNewLen > m_nBufferSize)
361     GrowFile(nNewLen);
362
363   if (nNewLen < m_nPosition)
364     m_nPosition = nNewLen;
365
366   m_nFileSize = nNewLen;
367 }
368
369 void FileStream::SetLength(unsigned long nNewLen)
370 {
371   fseek(m_hFile, nNewLen, SEEK_SET);
372 }
373
374 unsigned long MemStream::GetLength() const
375 {
376   return m_nFileSize;
377 }
378
379 unsigned long FileStream::GetLength() const
380 {
381   unsigned long nLen, nCur;
382
383   // Seek is a non const operation
384   nCur = ftell(m_hFile);
385   fseek(m_hFile, 0, SEEK_END);
386   nLen = ftell(m_hFile);
387   fseek(m_hFile, nCur, SEEK_SET);
388
389   return nLen;
390 }