Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreDataStream.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 19.9 KB
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-2006 Torus Knot Software Ltd
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
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreStableHeaders.h"
30#include "OgreDataStream.h"
31#include "OgreLogManager.h"
32#include "OgreException.h"
33
34namespace Ogre {
35
36    //-----------------------------------------------------------------------
37    //-----------------------------------------------------------------------
38    template <typename T> DataStream& DataStream::operator >>(T& val)
39    {
40        read(static_cast<void*>(&val), sizeof(T));
41        return *this;
42    }
43    //-----------------------------------------------------------------------
44    String DataStream::getLine(bool trimAfter)
45    {
46        char tmpBuf[OGRE_STREAM_TEMP_SIZE];
47        String retString;
48        size_t readCount;
49        // Keep looping while not hitting delimiter
50        while ((readCount = read(tmpBuf, OGRE_STREAM_TEMP_SIZE-1)) != 0)
51        {
52            // Terminate string
53            tmpBuf[readCount] = '\0';
54
55            char* p = strchr(tmpBuf, '\n');
56            if (p != 0)
57            {
58                // Reposition backwards
59                skip((long)(p + 1 - tmpBuf - readCount));
60                *p = '\0';
61            }
62
63            retString += tmpBuf;
64
65            if (p != 0)
66            {
67                // Trim off trailing CR if this was a CR/LF entry
68                if (retString.length() && retString[retString.length()-1] == '\r')
69                {
70                    retString.erase(retString.length()-1, 1);
71                }
72
73                // Found terminator, break out
74                break;
75            }
76        }
77
78        if (trimAfter)
79        {
80            StringUtil::trim(retString);
81        }
82
83        return retString;
84    }
85    //-----------------------------------------------------------------------
86    size_t DataStream::readLine(char* buf, size_t maxCount, const String& delim)
87    {
88                // Deal with both Unix & Windows LFs
89                bool trimCR = false;
90                if (delim.find_first_of('\n') != String::npos)
91                {
92                        trimCR = true;
93                }
94
95        char tmpBuf[OGRE_STREAM_TEMP_SIZE];
96        size_t chunkSize = std::min(maxCount, (size_t)OGRE_STREAM_TEMP_SIZE-1);
97        size_t totalCount = 0;
98        size_t readCount; 
99        while (chunkSize && (readCount = read(tmpBuf, chunkSize)))
100        {
101            // Terminate
102            tmpBuf[readCount] = '\0';
103
104            // Find first delimiter
105            size_t pos = strcspn(tmpBuf, delim.c_str());
106
107            if (pos < readCount)
108            {
109                // Found terminator, reposition backwards
110                skip((long)(pos + 1 - readCount));
111            }
112
113            // Are we genuinely copying?
114            if (buf)
115            {
116                memcpy(buf+totalCount, tmpBuf, pos);
117            }
118            totalCount += pos;
119
120            if (pos < readCount)
121            {
122                // Trim off trailing CR if this was a CR/LF entry
123                if (trimCR && totalCount && buf[totalCount-1] == '\r')
124                {
125                    --totalCount;
126                }
127
128                // Found terminator, break out
129                break;
130            }
131
132            // Adjust chunkSize for next time
133            chunkSize = std::min(maxCount-totalCount, (size_t)OGRE_STREAM_TEMP_SIZE-1);
134        }
135
136        // Terminate
137        buf[totalCount] = '\0';
138
139        return totalCount;
140    }
141    //-----------------------------------------------------------------------
142    size_t DataStream::skipLine(const String& delim)
143    {
144        char tmpBuf[OGRE_STREAM_TEMP_SIZE];
145        size_t total = 0;
146        size_t readCount;
147        // Keep looping while not hitting delimiter
148        while ((readCount = read(tmpBuf, OGRE_STREAM_TEMP_SIZE-1)) != 0)
149        {
150            // Terminate string
151            tmpBuf[readCount] = '\0';
152
153            // Find first delimiter
154            size_t pos = strcspn(tmpBuf, delim.c_str());
155
156            if (pos < readCount)
157            {
158                // Found terminator, reposition backwards
159                skip((long)(pos + 1 - readCount));
160
161                total += pos + 1;
162
163                // break out
164                break;
165            }
166
167            total += readCount;
168        }
169
170        return total;
171    }
172    //-----------------------------------------------------------------------
173    String DataStream::getAsString(void)
174    {
175        // Read the entire buffer
176        char* pBuf = new char[mSize+1];
177        // Ensure read from begin of stream
178        seek(0);
179        read(pBuf, mSize);
180        pBuf[mSize] = '\0';
181        String str;
182        str.insert(0, pBuf, mSize);
183        delete [] pBuf;
184        return str;
185    }
186    //-----------------------------------------------------------------------
187    //-----------------------------------------------------------------------
188    MemoryDataStream::MemoryDataStream(void* pMem, size_t size, bool freeOnClose)
189        : DataStream()
190    {
191        mData = mPos = static_cast<uchar*>(pMem);
192        mSize = size;
193        mEnd = mData + mSize;
194        mFreeOnClose = freeOnClose;
195    }
196    //-----------------------------------------------------------------------
197    MemoryDataStream::MemoryDataStream(const String& name, void* pMem, size_t size, 
198        bool freeOnClose)
199        : DataStream(name)
200    {
201        mData = mPos = static_cast<uchar*>(pMem);
202        mSize = size;
203        mEnd = mData + mSize;
204        mFreeOnClose = freeOnClose;
205    }
206    //-----------------------------------------------------------------------
207    MemoryDataStream::MemoryDataStream(DataStream& sourceStream, 
208        bool freeOnClose)
209        : DataStream()
210    {
211        // Copy data from incoming stream
212        mSize = sourceStream.size();
213        mData = new uchar[mSize];
214        sourceStream.read(mData, mSize);
215        mPos = mData;
216        mEnd = mData + mSize;
217        mFreeOnClose = freeOnClose;
218    }
219    //-----------------------------------------------------------------------
220    MemoryDataStream::MemoryDataStream(DataStreamPtr& sourceStream, 
221        bool freeOnClose)
222        : DataStream()
223    {
224        // Copy data from incoming stream
225        mSize = sourceStream->size();
226        mData = new uchar[mSize];
227        sourceStream->read(mData, mSize);
228        mPos = mData;
229        mEnd = mData + mSize;
230        mFreeOnClose = freeOnClose;
231    }
232    //-----------------------------------------------------------------------
233    MemoryDataStream::MemoryDataStream(const String& name, DataStream& sourceStream, 
234        bool freeOnClose)
235        : DataStream(name)
236    {
237        // Copy data from incoming stream
238        mSize = sourceStream.size();
239        mData = new uchar[mSize];
240        sourceStream.read(mData, mSize);
241        mPos = mData;
242        mEnd = mData + mSize;
243        mFreeOnClose = freeOnClose;
244    }
245    //-----------------------------------------------------------------------
246    MemoryDataStream::MemoryDataStream(const String& name, const DataStreamPtr& sourceStream, 
247        bool freeOnClose)
248        : DataStream(name)
249    {
250        // Copy data from incoming stream
251        mSize = sourceStream->size();
252        mData = new uchar[mSize];
253        sourceStream->read(mData, mSize);
254        mPos = mData;
255        mEnd = mData + mSize;
256        mFreeOnClose = freeOnClose;
257    }
258    //-----------------------------------------------------------------------
259    MemoryDataStream::MemoryDataStream(size_t size, bool freeOnClose)
260        : DataStream()
261    {
262        mSize = size;
263        mFreeOnClose = freeOnClose;
264        mData = new uchar[size];
265        mPos = mData;
266        mEnd = mData + mSize;
267    }
268    //-----------------------------------------------------------------------
269    MemoryDataStream::MemoryDataStream(const String& name, size_t size, 
270        bool freeOnClose)
271        : DataStream(name)
272    {
273        mSize = size;
274        mFreeOnClose = freeOnClose;
275        mData = new uchar[size];
276        mPos = mData;
277        mEnd = mData + mSize;
278    }
279    //-----------------------------------------------------------------------
280    MemoryDataStream::~MemoryDataStream()
281    {
282        close();
283    }
284    //-----------------------------------------------------------------------
285    size_t MemoryDataStream::read(void* buf, size_t count)
286    {
287        size_t cnt = count;
288        // Read over end of memory?
289        if (mPos + cnt > mEnd)
290            cnt = mEnd - mPos;
291        if (cnt == 0)
292            return 0;
293
294        memcpy(buf, mPos, cnt);
295        mPos += cnt;
296        return cnt;
297    }
298    //-----------------------------------------------------------------------
299    size_t MemoryDataStream::readLine(char* buf, size_t maxCount, 
300        const String& delim)
301    {
302        // Deal with both Unix & Windows LFs
303                bool trimCR = false;
304                if (delim.find_first_of('\n') != String::npos)
305                {
306                        trimCR = true;
307                }
308
309        size_t pos = 0;
310
311        // Make sure pos can never go past the end of the data
312        while (pos < maxCount && mPos < mEnd)
313        {
314            if (delim.find(*mPos) != String::npos)
315            {
316                // Trim off trailing CR if this was a CR/LF entry
317                if (trimCR && pos && buf[pos-1] == '\r')
318                {
319                    // terminate 1 character early
320                    --pos;
321                }
322
323                // Found terminator, skip and break out
324                ++mPos;
325                break;
326            }
327
328            buf[pos++] = *mPos++;
329        }
330
331        // terminate
332        buf[pos] = '\0';
333
334        return pos;
335    }
336    //-----------------------------------------------------------------------
337    size_t MemoryDataStream::skipLine(const String& delim)
338    {
339        size_t pos = 0;
340
341        // Make sure pos can never go past the end of the data
342        while (mPos < mEnd)
343        {
344            ++pos;
345            if (delim.find(*mPos++) != String::npos)
346            {
347                // Found terminator, break out
348                break;
349            }
350        }
351
352        return pos;
353
354    }
355    //-----------------------------------------------------------------------
356    void MemoryDataStream::skip(long count)
357    {
358        size_t newpos = (size_t)( ( mPos - mData ) + count );
359        assert( mData + newpos <= mEnd );       
360
361        mPos = mData + newpos;
362    }
363    //-----------------------------------------------------------------------
364    void MemoryDataStream::seek( size_t pos )
365    {
366        assert( mData + pos <= mEnd );
367        mPos = mData + pos;
368    }
369    //-----------------------------------------------------------------------
370    size_t MemoryDataStream::tell(void) const
371        {
372                //mData is start, mPos is current location
373                return mPos - mData;
374        }
375        //-----------------------------------------------------------------------
376    bool MemoryDataStream::eof(void) const
377    {
378        return mPos >= mEnd;
379    }
380    //-----------------------------------------------------------------------
381    void MemoryDataStream::close(void)   
382    {
383        if (mFreeOnClose && mData)
384        {
385            delete [] mData;
386            mData = 0;
387        }
388
389    }
390    //-----------------------------------------------------------------------
391    //-----------------------------------------------------------------------
392    FileStreamDataStream::FileStreamDataStream(std::ifstream* s, bool freeOnClose)
393        : DataStream(), mpStream(s), mFreeOnClose(freeOnClose)
394    {
395        // calculate the size
396        mpStream->seekg(0, std::ios_base::end);
397        mSize = mpStream->tellg();
398        mpStream->seekg(0, std::ios_base::beg);
399
400    }
401    //-----------------------------------------------------------------------
402    FileStreamDataStream::FileStreamDataStream(const String& name, 
403        std::ifstream* s, bool freeOnClose)
404        : DataStream(name), mpStream(s), mFreeOnClose(freeOnClose)
405    {
406        // calculate the size
407        mpStream->seekg(0, std::ios_base::end);
408        mSize = mpStream->tellg();
409        mpStream->seekg(0, std::ios_base::beg);
410    }
411    //-----------------------------------------------------------------------
412    FileStreamDataStream::FileStreamDataStream(const String& name, 
413        std::ifstream* s, size_t size, bool freeOnClose)
414        : DataStream(name), mpStream(s), mFreeOnClose(freeOnClose)
415    {
416        // Size is passed in
417        mSize = size;
418    }
419    //-----------------------------------------------------------------------
420    FileStreamDataStream::~FileStreamDataStream()
421    {
422        close();
423    }
424    //-----------------------------------------------------------------------
425    size_t FileStreamDataStream::read(void* buf, size_t count)
426    {
427                mpStream->read(static_cast<char*>(buf), static_cast<std::streamsize>(count));
428        return mpStream->gcount();
429    }
430    //-----------------------------------------------------------------------
431    size_t FileStreamDataStream::readLine(char* buf, size_t maxCount, 
432        const String& delim)
433    {
434                if (delim.empty())
435                {
436                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "No delimiter provided",
437                                "FileStreamDataStream::readLine");
438                }
439                if (delim.size() > 1)
440                {
441                        LogManager::getSingleton().logMessage(
442                                "WARNING: FileStreamDataStream::readLine - using only first delimeter");
443                }
444                // Deal with both Unix & Windows LFs
445                bool trimCR = false;
446                if (delim.at(0) == '\n') 
447                {
448                        trimCR = true;
449                }
450                // maxCount + 1 since count excludes terminator in getline
451                mpStream->getline(buf, static_cast<std::streamsize>(maxCount+1), delim.at(0));
452                size_t ret = mpStream->gcount();
453                // three options
454                // 1) we had an eof before we read a whole line
455                // 2) we ran out of buffer space
456                // 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
457                // in all cases the buffer will be null terminated for us
458
459                if (mpStream->eof()) 
460                {
461                        // no problem
462                }
463                else if (mpStream->fail())
464                {
465                        // Did we fail because of maxCount hit? No - no terminating character
466                        // in included in the count in this case
467                        if (ret == maxCount)
468                        {
469                                // clear failbit for next time
470                                mpStream->clear();
471                        }
472                        else
473                        {
474                                OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
475                                        "Streaming error occurred", 
476                                        "FileStreamDataStream::readLine");
477                        }
478                }
479                else 
480                {
481                        // we need to adjust ret because we want to use it as a
482                        // pointer to the terminating null character and it is
483                        // currently the length of the data read from the stream
484                        // i.e. 1 more than the length of the data in the buffer and
485                        // hence 1 more than the _index_ of the NULL character
486                        --ret;
487                }
488
489                // trim off CR if we found CR/LF
490                if (trimCR && buf[ret-1] == '\r')
491                {
492                        --ret;
493                        buf[ret] = '\0';
494                }
495                return ret;
496        }
497    //-----------------------------------------------------------------------
498    void FileStreamDataStream::skip(long count)
499    {
500#if defined(STLPORT)
501                // Workaround for STLport issues: After reached eof of file stream,
502                // it's seems the stream was putted in intermediate state, and will be
503                // fail if try to repositioning relative to current position.
504                // Note: tellg() fail in this case too.
505                if (mpStream->eof())
506                {
507                        mpStream->clear();
508                        // Use seek relative to either begin or end to bring the stream
509                        // back to normal state.
510                        mpStream->seekg(0, std::ios::end);
511                }
512#endif         
513                mpStream->clear(); //Clear fail status in case eof was set
514                mpStream->seekg(static_cast<std::ifstream::pos_type>(count), std::ios::cur);
515    }
516    //-----------------------------------------------------------------------
517    void FileStreamDataStream::seek( size_t pos )
518    {
519                mpStream->clear(); //Clear fail status in case eof was set
520        mpStream->seekg(static_cast<std::streamoff>(pos), std::ios::beg);
521    }
522        //-----------------------------------------------------------------------
523    size_t FileStreamDataStream::tell(void) const
524        {
525                mpStream->clear(); //Clear fail status in case eof was set
526                return mpStream->tellg();
527        }
528        //-----------------------------------------------------------------------
529    bool FileStreamDataStream::eof(void) const
530    {
531        return mpStream->eof();
532    }
533    //-----------------------------------------------------------------------
534    void FileStreamDataStream::close(void)
535    {
536        if (mpStream)
537        {
538            mpStream->close();
539            if (mFreeOnClose)
540            {
541                // delete the stream too
542                delete mpStream;
543                mpStream = 0;
544            }
545        }
546    }
547    //-----------------------------------------------------------------------
548    //-----------------------------------------------------------------------
549    FileHandleDataStream::FileHandleDataStream(FILE* handle)
550        : DataStream(), mFileHandle(handle)
551    {
552                // Determine size
553                fseek(mFileHandle, 0, SEEK_END);
554                mSize = ftell(mFileHandle);
555                fseek(mFileHandle, 0, SEEK_SET);
556    }
557    //-----------------------------------------------------------------------
558    FileHandleDataStream::FileHandleDataStream(const String& name, FILE* handle)
559        : DataStream(name), mFileHandle(handle)
560    {
561                // Determine size
562                fseek(mFileHandle, 0, SEEK_END);
563                mSize = ftell(mFileHandle);
564                fseek(mFileHandle, 0, SEEK_SET);
565    }
566    //-----------------------------------------------------------------------
567    FileHandleDataStream::~FileHandleDataStream()
568    {
569        close();
570    }
571    //-----------------------------------------------------------------------
572    size_t FileHandleDataStream::read(void* buf, size_t count)
573    {
574        return fread(buf, 1, count, mFileHandle);
575    }
576    //-----------------------------------------------------------------------
577    void FileHandleDataStream::skip(long count)
578    {
579        fseek(mFileHandle, count, SEEK_CUR);
580    }
581    //-----------------------------------------------------------------------
582    void FileHandleDataStream::seek( size_t pos )
583    {
584        fseek(mFileHandle, static_cast<long>(pos), SEEK_SET);
585    }
586    //-----------------------------------------------------------------------
587    size_t FileHandleDataStream::tell(void) const
588        {
589                return ftell( mFileHandle );
590        }
591        //-----------------------------------------------------------------------
592    bool FileHandleDataStream::eof(void) const
593    {
594        return feof(mFileHandle) != 0;
595    }
596    //-----------------------------------------------------------------------
597    void FileHandleDataStream::close(void)
598    {
599        fclose(mFileHandle);
600        mFileHandle = 0;
601    }
602    //-----------------------------------------------------------------------
603
604}
Note: See TracBrowser for help on using the repository browser.