source: OGRE/trunk/ogrenew/OgreMain/src/OgreDataStream.cpp @ 692

Revision 692, 18.1 KB checked in by mattausch, 19 years ago (diff)

adding ogre 1.2 and dependencies

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreStableHeaders.h"
26#include "OgreDataStream.h"
27#include "OgreLogManager.h"
28#include "OgreException.h"
29
30namespace Ogre {
31
32    //-----------------------------------------------------------------------
33    //-----------------------------------------------------------------------
34    template <typename T> DataStream& DataStream::operator >>(T& val)
35    {
36        read(static_cast<void*>(&val), sizeof(T));
37    }
38    //-----------------------------------------------------------------------
39    String DataStream::getLine(bool trimAfter)
40    {
41        StringUtil::StrStreamType str;
42        size_t c = OGRE_STREAM_TEMP_SIZE-1;
43        // Keep looping while not hitting delimiter
44        while (c == OGRE_STREAM_TEMP_SIZE-1)
45        {
46            c = readLine(mTmpArea, OGRE_STREAM_TEMP_SIZE-1);
47            str << mTmpArea;
48        }
49
50        String retString(str.str());
51        if (trimAfter)
52        {
53            StringUtil::trim(retString);
54        }
55
56        return retString;
57    }
58    //-----------------------------------------------------------------------
59    String DataStream::getAsString(void)
60    {
61        // Read the entire buffer
62        char* pBuf = new char[mSize+1];
63        read(pBuf, mSize);
64        pBuf[mSize] = '\0';
65        String str;
66        str.insert(0, pBuf, mSize);
67        delete [] pBuf;
68        return str;
69    }
70    //-----------------------------------------------------------------------
71    //-----------------------------------------------------------------------
72    MemoryDataStream::MemoryDataStream(void* pMem, size_t size, bool freeOnClose)
73        : DataStream()
74    {
75        mData = mPos = static_cast<uchar*>(pMem);
76        mSize = size;
77        mEnd = mData + mSize;
78        mFreeOnClose = freeOnClose;
79    }
80    //-----------------------------------------------------------------------
81    MemoryDataStream::MemoryDataStream(const String& name, void* pMem, size_t size,
82        bool freeOnClose)
83        : DataStream(name)
84    {
85        mData = mPos = static_cast<uchar*>(pMem);
86        mSize = size;
87        mEnd = mData + mSize;
88        mFreeOnClose = freeOnClose;
89    }
90    //-----------------------------------------------------------------------
91    MemoryDataStream::MemoryDataStream(DataStream& sourceStream,
92        bool freeOnClose)
93        : DataStream()
94    {
95        // Copy data from incoming stream
96        mSize = sourceStream.size();
97        mData = new uchar[mSize];
98        sourceStream.read(mData, mSize);
99        mPos = mData;
100        mEnd = mData + mSize;
101        mFreeOnClose = freeOnClose;
102    }
103    //-----------------------------------------------------------------------
104    MemoryDataStream::MemoryDataStream(DataStreamPtr& sourceStream,
105        bool freeOnClose)
106        : DataStream()
107    {
108        // Copy data from incoming stream
109        mSize = sourceStream->size();
110        mData = new uchar[mSize];
111        sourceStream->read(mData, mSize);
112        mPos = mData;
113        mEnd = mData + mSize;
114        mFreeOnClose = freeOnClose;
115    }
116    //-----------------------------------------------------------------------
117    MemoryDataStream::MemoryDataStream(const String& name, DataStream& sourceStream,
118        bool freeOnClose)
119        : DataStream(name)
120    {
121        // Copy data from incoming stream
122        mSize = sourceStream.size();
123        mData = new uchar[mSize];
124        sourceStream.read(mData, mSize);
125        mPos = mData;
126        mEnd = mData + mSize;
127        mFreeOnClose = freeOnClose;
128    }
129    //-----------------------------------------------------------------------
130    MemoryDataStream::MemoryDataStream(const String& name, const DataStreamPtr& sourceStream,
131        bool freeOnClose)
132        : DataStream(name)
133    {
134        // Copy data from incoming stream
135        mSize = sourceStream->size();
136        mData = new uchar[mSize];
137        sourceStream->read(mData, mSize);
138        mPos = mData;
139        mEnd = mData + mSize;
140        mFreeOnClose = freeOnClose;
141    }
142    //-----------------------------------------------------------------------
143    MemoryDataStream::MemoryDataStream(size_t size, bool freeOnClose)
144        : DataStream()
145    {
146        mSize = size;
147        mFreeOnClose = freeOnClose;
148        mData = new uchar[size];
149        mPos = mData;
150        mEnd = mData + mSize;
151    }
152    //-----------------------------------------------------------------------
153    MemoryDataStream::MemoryDataStream(const String& name, size_t size,
154        bool freeOnClose)
155        : DataStream(name)
156    {
157        mSize = size;
158        mFreeOnClose = freeOnClose;
159        mData = new uchar[size];
160        mPos = mData;
161        mEnd = mData + mSize;
162    }
163    //-----------------------------------------------------------------------
164    MemoryDataStream::~MemoryDataStream()
165    {
166        close();
167    }
168    //-----------------------------------------------------------------------
169    size_t MemoryDataStream::read(void* buf, size_t count)
170    {
171        size_t cnt = count;
172        // Read over end of memory?
173        if (mPos + cnt > mEnd)
174            cnt = mEnd - mPos;
175        if (cnt == 0)
176            return 0;
177
178        memcpy(buf, mPos, cnt);
179        mPos += cnt;
180        return cnt;
181    }
182    //-----------------------------------------------------------------------
183    size_t MemoryDataStream::readLine(char* buf, size_t maxCount,
184        const String& delim)
185    {
186        // Deal with both Unix & Windows LFs
187                bool trimCR = false;
188                if (delim.find_first_of('\n') != String::npos)
189                {
190                        trimCR = true;
191                }
192
193        size_t pos = strcspn((const char*)mPos, delim.c_str());
194        if (pos > maxCount)
195            pos = maxCount;
196
197        // Make sure pos can never go past the end of the data
198        if(mPos + pos > mEnd) pos = mEnd - mPos;
199
200        if (pos > 0)
201        {
202            memcpy(buf, (const void*)mPos, pos);
203        }
204
205                // reposition pointer
206                mPos += pos + 1;
207
208                // Trim off trailing CR if this was a CR/LF entry
209                if (trimCR && buf[pos-1] == '\r')
210                {
211                        // terminate 1 character early
212                        --pos;
213                }
214                // terminate
215                buf[pos] = '\0';
216
217
218        return pos;
219    }
220    //-----------------------------------------------------------------------
221    size_t MemoryDataStream::skipLine(const String& delim)
222    {
223        size_t pos = strcspn( (const char*)mPos, delim.c_str() );
224
225        // Make sure pos can never go past the end of the data
226        if(mPos + pos > mEnd) pos = mEnd - mPos;
227
228        mPos += pos + 1;
229
230        return pos;
231
232    }
233    //-----------------------------------------------------------------------
234    void MemoryDataStream::skip(long count)
235    {
236        size_t newpos = (size_t)( ( mPos - mData ) + count );
237        assert( mData + newpos <= mEnd );       
238
239        mPos = mData + newpos;
240    }
241    //-----------------------------------------------------------------------
242    void MemoryDataStream::seek( size_t pos )
243    {
244        assert( mData + pos <= mEnd );
245        mPos = mData + pos;
246    }
247    //-----------------------------------------------------------------------
248    size_t MemoryDataStream::tell(void) const
249        {
250                //mData is start, mPos is current location
251                return mPos - mData;
252        }
253        //-----------------------------------------------------------------------
254    bool MemoryDataStream::eof(void) const
255    {
256        return mPos >= mEnd;
257    }
258    //-----------------------------------------------------------------------
259    void MemoryDataStream::close(void)   
260    {
261        if (mFreeOnClose && mData)
262        {
263            delete [] mData;
264            mData = 0;
265        }
266
267    }
268    //-----------------------------------------------------------------------
269    //-----------------------------------------------------------------------
270    FileStreamDataStream::FileStreamDataStream(std::ifstream* s, bool freeOnClose)
271        : DataStream(), mpStream(s), mFreeOnClose(freeOnClose)
272    {
273        // calculate the size
274        mpStream->seekg(0, std::ios_base::end);
275        mSize = mpStream->tellg();
276        mpStream->seekg(0, std::ios_base::beg);
277
278    }
279    //-----------------------------------------------------------------------
280    FileStreamDataStream::FileStreamDataStream(const String& name,
281        std::ifstream* s, bool freeOnClose)
282        : DataStream(name), mpStream(s), mFreeOnClose(freeOnClose)
283    {
284        // calculate the size
285        mpStream->seekg(0, std::ios_base::end);
286        mSize = mpStream->tellg();
287        mpStream->seekg(0, std::ios_base::beg);
288    }
289    //-----------------------------------------------------------------------
290    FileStreamDataStream::FileStreamDataStream(const String& name,
291        std::ifstream* s, size_t size, bool freeOnClose)
292        : DataStream(name), mpStream(s), mFreeOnClose(freeOnClose)
293    {
294        // Size is passed in
295        mSize = size;
296    }
297    //-----------------------------------------------------------------------
298    FileStreamDataStream::~FileStreamDataStream()
299    {
300        close();
301    }
302    //-----------------------------------------------------------------------
303    size_t FileStreamDataStream::read(void* buf, size_t count)
304    {
305        mpStream->read(static_cast<char*>(buf), count);
306        return mpStream->gcount();
307    }
308    //-----------------------------------------------------------------------
309    size_t FileStreamDataStream::readLine(char* buf, size_t maxCount,
310        const String& delim)
311    {
312                if (delim.empty())
313                {
314                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "No delimiter provided",
315                                "FileStreamDataStream::readLine");
316                }
317                if (delim.size() > 1)
318                {
319                        LogManager::getSingleton().logMessage(
320                                "WARNING: FileStreamDataStream::readLine - using only first delimeter");
321                }
322                // Deal with both Unix & Windows LFs
323                bool trimCR = false;
324                if (delim.at(0) == '\n')
325                {
326                        trimCR = true;
327                }
328                // maxCount + 1 since count excludes terminator in getline
329                mpStream->getline(buf, maxCount+1, delim.at(0));
330                size_t ret = mpStream->gcount();
331                // three options
332                // 1) we had an eof before we read a whole line
333                // 2) we ran out of buffer space
334                // 3) we read a whole line - in this case the delim character is taken from the stream but not written in the buffer so the read data is of length ret-1 and thus ends at index ret-2
335                // in all cases the buffer will be null terminated for us
336
337                if (mpStream->eof())
338                {
339                        // no problem
340                }
341                else if (mpStream->fail())
342                {
343                        // Did we fail because of maxCount hit? No - no terminating character
344                        // in included in the count in this case
345                        if (ret == maxCount)
346                        {
347                                // clear failbit for next time
348                                mpStream->clear();
349                        }
350                        else
351                        {
352                                OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
353                                        "Streaming error occurred",
354                                        "FileStreamDataStream::readLine");
355                        }
356                }
357                else
358                {
359                        // we need to adjust ret because we want to use it as a
360                        // pointer to the terminating null character and it is
361                        // currently the length of the data read from the stream
362                        // i.e. 1 more than the length of the data in the buffer and
363                        // hence 1 more than the _index_ of the NULL character
364                        --ret;
365                }
366
367                // trim off CR if we found CR/LF
368                if (trimCR && buf[ret-1] == '\r')
369                {
370                        --ret;
371                        buf[ret] = '\0';
372                }
373                return ret;
374        }
375    //-----------------------------------------------------------------------
376    size_t FileStreamDataStream::skipLine(const String& delim)
377    {
378        size_t c = OGRE_STREAM_TEMP_SIZE-1;
379        size_t total = 0;
380        while (c == OGRE_STREAM_TEMP_SIZE-1)
381        {
382            c = readLine(mTmpArea, OGRE_STREAM_TEMP_SIZE-1);
383            total += c;
384        }
385        return total;
386    }
387    //-----------------------------------------------------------------------
388    void FileStreamDataStream::skip(long count)
389    {
390                mpStream->clear(); //Clear fail status in case eof was set
391                mpStream->seekg(static_cast<std::ifstream::pos_type>(count), std::ios::cur);
392    }
393    //-----------------------------------------------------------------------
394    void FileStreamDataStream::seek( size_t pos )
395    {
396                mpStream->clear(); //Clear fail status in case eof was set
397        mpStream->seekg(static_cast<std::ifstream::pos_type>(pos), std::ios::beg);
398    }
399        //-----------------------------------------------------------------------
400    size_t FileStreamDataStream::tell(void) const
401        {
402                mpStream->clear(); //Clear fail status in case eof was set
403                return mpStream->tellg();
404        }
405        //-----------------------------------------------------------------------
406    bool FileStreamDataStream::eof(void) const
407    {
408        return mpStream->eof();
409    }
410    //-----------------------------------------------------------------------
411    void FileStreamDataStream::close(void)
412    {
413        if (mpStream)
414        {
415            mpStream->close();
416            if (mFreeOnClose)
417            {
418                // delete the stream too
419                delete mpStream;
420                mpStream = 0;
421            }
422        }
423    }
424    //-----------------------------------------------------------------------
425    //-----------------------------------------------------------------------
426    FileHandleDataStream::FileHandleDataStream(FILE* handle)
427        : DataStream(), mFileHandle(handle)
428    {
429                // Determine size
430                fseek(mFileHandle, 0, SEEK_END);
431                mSize = ftell(mFileHandle);
432                fseek(mFileHandle, 0, SEEK_SET);
433    }
434    //-----------------------------------------------------------------------
435    FileHandleDataStream::FileHandleDataStream(const String& name, FILE* handle)
436        : DataStream(name), mFileHandle(handle)
437    {
438                // Determine size
439                fseek(mFileHandle, 0, SEEK_END);
440                mSize = ftell(mFileHandle);
441                fseek(mFileHandle, 0, SEEK_SET);
442    }
443    //-----------------------------------------------------------------------
444    FileHandleDataStream::~FileHandleDataStream()
445    {
446        close();
447    }
448    //-----------------------------------------------------------------------
449    size_t FileHandleDataStream::read(void* buf, size_t count)
450    {
451        return fread(buf, count, 1, mFileHandle);
452    }
453    //-----------------------------------------------------------------------
454    size_t FileHandleDataStream::readLine(char* buf, size_t maxCount, const String& delim)
455    {
456        // Have to buffer the data
457        // since we have no read up to delimeter method
458
459                // Deal with both Unix & Windows LFs
460                bool trimCR = false;
461                if (delim.find_first_of('\n') != String::npos)
462                {
463                        trimCR = true;
464                }
465
466        size_t chunkSize = std::min(maxCount, (size_t)OGRE_STREAM_TEMP_SIZE-1);
467        size_t totalCount = 0;
468        size_t readCount;
469        while (chunkSize && (readCount = fread(mTmpArea, chunkSize, 1, mFileHandle)))
470        {
471            // Terminate
472            mTmpArea[readCount] = '\0';
473            // Find first delimiter
474            size_t pos = strcspn(mTmpArea, delim.c_str());
475
476            if (pos < readCount)
477            {
478                // found terminator
479                // reposition backwards
480                fseek(mFileHandle, pos - readCount + 1, SEEK_CUR);
481            }
482
483                        if (pos > 0)
484            {
485                                // terminate early if CR found
486                                if (trimCR && mTmpArea[pos-1] == '\r')
487                                {
488                                        --pos;
489                                }
490
491                // Are we genuinely copying?
492                if (buf)
493                {
494                    memcpy(buf, (const void*)mTmpArea, pos);
495                                        buf[pos] = '\0';
496                }
497                totalCount += pos;
498            }
499
500            if (pos < readCount)
501            {
502                break;
503            }
504            // Adjust chunkSize for next time
505            chunkSize = std::min(maxCount-totalCount, (size_t)OGRE_STREAM_TEMP_SIZE-1);
506
507        }
508        return totalCount;
509
510
511    }
512    //-----------------------------------------------------------------------
513    size_t FileHandleDataStream::skipLine(const String& delim)
514    {
515        // Re-use readLine, but don't copy data
516        char* nullBuf = 0;
517        return readLine(nullBuf, 1024, delim);
518    }
519    //-----------------------------------------------------------------------
520    void FileHandleDataStream::skip(long count)
521    {
522        fseek(mFileHandle, count, SEEK_CUR);
523    }
524    //-----------------------------------------------------------------------
525    void FileHandleDataStream::seek( size_t pos )
526    {
527        fseek(mFileHandle, pos, SEEK_SET);
528    }
529    //-----------------------------------------------------------------------
530    size_t FileHandleDataStream::tell(void) const
531        {
532                return ftell( mFileHandle );
533        }
534        //-----------------------------------------------------------------------
535    bool FileHandleDataStream::eof(void) const
536    {
537        return feof(mFileHandle) != 0;
538    }
539    //-----------------------------------------------------------------------
540    void FileHandleDataStream::close(void)
541    {
542        fclose(mFileHandle);
543        mFileHandle = 0;
544    }
545    //-----------------------------------------------------------------------
546
547}
Note: See TracBrowser for help on using the repository browser.