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