123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /**
- * @file llcorebufferstream.cpp
- * @brief Implements the BufferStream adapter class
- *
- * $LicenseInfo:firstyear=2012&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
- #include "linden_common.h"
- #include "llcorebufferstream.h"
- namespace LLCore
- {
- BufferArrayStreamBuf::BufferArrayStreamBuf(BufferArray* array)
- : mBufferArray(array),
- mReadCurPos(0),
- mReadCurBlock(-1),
- mReadBegin(NULL),
- mReadCur(NULL),
- mReadEnd(NULL),
- mWriteCurPos(0)
- {
- if (array)
- {
- array->addRef();
- mWriteCurPos = array->mLen;
- }
- }
- BufferArrayStreamBuf::~BufferArrayStreamBuf()
- {
- if (mBufferArray)
- {
- mBufferArray->release();
- mBufferArray = NULL;
- }
- }
- BufferArrayStreamBuf::int_type BufferArrayStreamBuf::underflow()
- {
- if (!mBufferArray)
- {
- return traits_type::eof();
- }
- if (mReadCur == mReadEnd)
- {
- // Find the next block with actual data or leave mCurBlock/mCur/mEnd
- // unchanged if we're at the end of any block chain.
- const char* new_begin = NULL;
- const char* new_end = NULL;
- S32 new_cur_block = mReadCurBlock + 1;
- while (mBufferArray->getBlockStartEnd(new_cur_block, &new_begin,
- &new_end))
- {
- if (new_begin != new_end)
- {
- break;
- }
- ++new_cur_block;
- }
- if (new_begin == new_end)
- {
- return traits_type::eof();
- }
- mReadCurBlock = new_cur_block;
- mReadBegin = mReadCur = new_begin;
- mReadEnd = new_end;
- }
- return traits_type::to_int_type(*mReadCur);
- }
- BufferArrayStreamBuf::int_type BufferArrayStreamBuf::uflow()
- {
- const int_type ret(underflow());
- if (traits_type::eof() != ret)
- {
- ++mReadCur;
- ++mReadCurPos;
- }
- return ret;
- }
- BufferArrayStreamBuf::int_type BufferArrayStreamBuf::pbackfail(int_type ch)
- {
- if (!mBufferArray)
- {
- return traits_type::eof();
- }
- if (mReadCur == mReadBegin)
- {
- // Find the previous block with actual data or leave mCurBlock/mBegin/
- // mCur/mEnd unchanged if we're at the beginning of any block chain.
- const char* new_begin = NULL;
- const char* new_end = NULL;
- S32 new_cur_block = mReadCurBlock - 1;
- while (mBufferArray->getBlockStartEnd(new_cur_block, &new_begin,
- &new_end))
- {
- if (new_begin != new_end)
- {
- break;
- }
- --new_cur_block;
- }
- if (new_begin == new_end)
- {
- return traits_type::eof();
- }
- mReadCurBlock = new_cur_block;
- mReadBegin = new_begin;
- mReadEnd = mReadCur = new_end;
- }
- if (traits_type::eof() != ch && mReadCur[-1] != ch)
- {
- return traits_type::eof();
- }
- --mReadCurPos;
- return traits_type::to_int_type(*--mReadCur);
- }
- std::streamsize BufferArrayStreamBuf::showmanyc()
- {
- return mBufferArray ? mBufferArray->mLen - mReadCurPos : -1;
- }
- BufferArrayStreamBuf::int_type BufferArrayStreamBuf::overflow(int c)
- {
- if (!mBufferArray || mWriteCurPos > mBufferArray->mLen)
- {
- return traits_type::eof();
- }
- const size_t wrote(mBufferArray->write(mWriteCurPos, &c, 1));
- mWriteCurPos += wrote;
- return wrote ? c : traits_type::eof();
- }
- std::streamsize BufferArrayStreamBuf::xsputn(const char* src,
- std::streamsize count)
- {
- if (!mBufferArray || mWriteCurPos > mBufferArray->mLen)
- {
- return 0;
- }
- const size_t wrote(mBufferArray->write(mWriteCurPos, src, count));
- mWriteCurPos += wrote;
- return wrote;
- }
- std::streampos BufferArrayStreamBuf::seekoff(std::streamoff off,
- std::ios_base::seekdir way,
- std::ios_base::openmode which)
- {
- std::streampos ret = -1;
- if (!mBufferArray)
- {
- return ret;
- }
- if (std::ios_base::in == which)
- {
- size_t pos = 0;
- switch (way)
- {
- case std::ios_base::beg:
- pos = off;
- break;
- case std::ios_base::cur:
- pos = mReadCurPos += off;
- break;
- case std::ios_base::end:
- pos = mBufferArray->mLen - off;
- break;
- default:
- return ret;
- }
- size_t buff_size = mBufferArray->size();
- if (pos >= buff_size)
- {
- if (buff_size)
- {
- pos = buff_size - 1;
- }
- else
- {
- pos = 0;
- }
- }
- size_t ba_offset = 0;
- S32 block = mBufferArray->findBlock(pos, ba_offset);
- if (block < 0)
- {
- return ret;
- }
- const char* start = NULL;
- const char* end = NULL;
- if (!mBufferArray->getBlockStartEnd(block, &start, &end))
- {
- return ret;
- }
- mReadCurBlock = block;
- mReadBegin = start;
- mReadCur = start + ba_offset;
- mReadEnd = end;
- ret = mReadCurPos = pos;
- }
- else if (std::ios_base::out == which)
- {
- int pos = 0;
- switch (way)
- {
- case std::ios_base::beg:
- pos = off;
- break;
- case std::ios_base::cur:
- pos = mWriteCurPos += off;
- break;
- case std::ios_base::end:
- pos = mBufferArray->mLen - off;
- break;
- default:
- return ret;
- }
- if (pos < 0)
- {
- return ret;
- }
- if (pos > (int)mBufferArray->size())
- {
- pos = mBufferArray->size();
- }
- ret = mWriteCurPos = pos;
- }
- return ret;
- }
- BufferArrayStream::BufferArrayStream(BufferArray* ba)
- : std::iostream(&mStreamBuf),
- mStreamBuf(ba)
- {
- }
- } // End namespace LLCore
|