2 Copyright (c) 2001, Loki software, inc.
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
8 Redistributions of source code must retain the above copyright notice, this list
9 of conditions and the following disclaimer.
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.
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
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.
32 // File class, can be a memory file or a regular disk file.
33 // Originally from LeoCAD, used with permission from the author. :)
35 // Leonardo Zide (leo@lokigames.com)
46 IDataStream::IDataStream()
49 IDataStream::~IDataStream()
52 /////////////////////////////////////////////////////////////////////////////
53 // File construction/destruction
55 MemStream::MemStream()
65 MemStream::MemStream(unsigned long nLen)
77 FileStream::FileStream()
80 m_bCloseOnDelete = false;
83 MemStream::~MemStream()
94 FileStream::~FileStream()
96 if (m_hFile != NULL && m_bCloseOnDelete)
100 /////////////////////////////////////////////////////////////////////////////
103 char* MemStream::ReadString(char* pBuf, unsigned long nMax)
110 if (m_nPosition >= m_nFileSize)
115 if (m_nPosition == m_nFileSize)
118 ch = m_pBuffer[m_nPosition];
130 char* FileStream::ReadString(char* pBuf, unsigned long nMax)
132 return fgets(pBuf, nMax, m_hFile);
135 unsigned long MemStream::Read(void* pBuf, unsigned long nCount)
140 if (m_nPosition > m_nFileSize)
144 if (m_nPosition + nCount > m_nFileSize)
145 nRead = (unsigned long)(m_nFileSize - m_nPosition);
149 memcpy((unsigned char*)pBuf, (unsigned char*)m_pBuffer + m_nPosition, nRead);
150 m_nPosition += nRead;
155 unsigned long FileStream::Read(void* pBuf, unsigned long nCount)
157 return fread(pBuf, 1, nCount, m_hFile);
160 int MemStream::GetChar()
162 if (m_nPosition > m_nFileSize)
165 unsigned char* ret = (unsigned char*)m_pBuffer + m_nPosition;
171 int FileStream::GetChar()
173 return fgetc(m_hFile);
176 unsigned long MemStream::Write(const void* pBuf, unsigned long nCount)
181 if (m_nPosition + nCount > m_nBufferSize)
182 GrowFile(m_nPosition + nCount);
184 memcpy((unsigned char*)m_pBuffer + m_nPosition, (unsigned char*)pBuf, nCount);
186 m_nPosition += nCount;
188 if (m_nPosition > m_nFileSize)
189 m_nFileSize = m_nPosition;
194 unsigned long FileStream::Write(const void* pBuf, unsigned long nCount)
196 return fwrite(pBuf, 1, nCount, m_hFile);
199 int MemStream::PutChar(int c)
201 if (m_nPosition + 1 > m_nBufferSize)
202 GrowFile(m_nPosition + 1);
204 unsigned char* bt = (unsigned char*)m_pBuffer + m_nPosition;
209 if (m_nPosition > m_nFileSize)
210 m_nFileSize = m_nPosition;
215 /*!\todo SPoG suggestion: replace printf with operator >> using c++ iostream and strstream */
216 void FileStream::printf(const char* s, ...)
221 vfprintf(m_hFile, s, args);
225 /*!\todo SPoG suggestion: replace printf with operator >> using c++ iostream and strstream */
226 void MemStream::printf(const char* s, ...)
232 vsprintf(buffer, s, args);
234 Write(buffer, strlen(buffer));
237 int FileStream::PutChar(int c)
239 return fputc(c, m_hFile);
242 bool FileStream::Open(const char *filename, const char *mode)
244 m_hFile = fopen(filename, mode);
245 m_bCloseOnDelete = true;
247 return (m_hFile != NULL);
250 void MemStream::Close()
256 if (m_pBuffer && m_bAutoDelete)
261 void FileStream::Close()
267 m_bCloseOnDelete = false;
270 unsigned long MemStream::Seek(long lOff, int nFrom)
272 unsigned long lNewPos = m_nPosition;
274 if (nFrom == SEEK_SET)
276 else if (nFrom == SEEK_CUR)
278 else if (nFrom == SEEK_END)
279 lNewPos = m_nFileSize + lOff;
281 return (unsigned long)-1;
283 m_nPosition = lNewPos;
288 unsigned long FileStream::Seek(long lOff, int nFrom)
290 fseek (m_hFile, lOff, nFrom);
292 return ftell(m_hFile);
295 unsigned long MemStream::GetPosition() const
300 unsigned long FileStream::GetPosition() const
302 return ftell(m_hFile);
305 void MemStream::GrowFile(unsigned long nNewLen)
307 if (nNewLen > m_nBufferSize)
310 unsigned long nNewBufferSize = m_nBufferSize;
312 // determine new buffer size
313 while (nNewBufferSize < nNewLen)
314 nNewBufferSize += m_nGrowBytes;
316 // allocate new buffer
317 unsigned char* lpNew;
318 if (m_pBuffer == NULL)
319 lpNew = static_cast<unsigned char*>(malloc(nNewBufferSize));
321 lpNew = static_cast<unsigned char*>(realloc(m_pBuffer, nNewBufferSize));
324 m_nBufferSize = nNewBufferSize;
328 void MemStream::Flush()
330 // Nothing to be done
333 void FileStream::Flush()
341 void MemStream::Abort()
346 void FileStream::Abort()
350 // close but ignore errors
351 if (m_bCloseOnDelete)
354 m_bCloseOnDelete = false;
358 void MemStream::SetLength(unsigned long nNewLen)
360 if (nNewLen > m_nBufferSize)
363 if (nNewLen < m_nPosition)
364 m_nPosition = nNewLen;
366 m_nFileSize = nNewLen;
369 void FileStream::SetLength(unsigned long nNewLen)
371 fseek(m_hFile, nNewLen, SEEK_SET);
374 unsigned long MemStream::GetLength() const
379 unsigned long FileStream::GetLength() const
381 unsigned long nLen, nCur;
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);