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