summaryrefslogtreecommitdiff
path: root/indra/llmessage/llbuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/llbuffer.cpp')
-rw-r--r--indra/llmessage/llbuffer.cpp1352
1 files changed, 676 insertions, 676 deletions
diff --git a/indra/llmessage/llbuffer.cpp b/indra/llmessage/llbuffer.cpp
index cfe38605ad..dc7115b167 100644
--- a/indra/llmessage/llbuffer.cpp
+++ b/indra/llmessage/llbuffer.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llbuffer.cpp
* @author Phoenix
* @date 2005-09-20
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, 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$
*/
@@ -37,20 +37,20 @@
#define ASSERT_LLBUFFERARRAY_MUTEX_LOCKED() llassert(!mMutexp || mMutexp->isSelfLocked())
-/**
+/**
* LLSegment
*/
LLSegment::LLSegment() :
- mChannel(0),
- mData(NULL),
- mSize(0)
+ mChannel(0),
+ mData(NULL),
+ mSize(0)
{
}
LLSegment::LLSegment(S32 channel, U8* data, S32 data_len) :
- mChannel(channel),
- mData(data),
- mSize(data_len)
+ mChannel(channel),
+ mData(data),
+ mSize(data_len)
{
}
@@ -60,849 +60,849 @@ LLSegment::~LLSegment()
bool LLSegment::isOnChannel(S32 channel) const
{
- return (mChannel == channel);
+ return (mChannel == channel);
}
S32 LLSegment::getChannel() const
{
- return mChannel;
+ return mChannel;
}
void LLSegment::setChannel(S32 channel)
{
- mChannel = channel;
+ mChannel = channel;
}
U8* LLSegment::data() const
{
- return mData;
+ return mData;
}
S32 LLSegment::size() const
{
- return mSize;
+ return mSize;
}
bool LLSegment::operator==(const LLSegment& rhs) const
{
- if((mData != rhs.mData)||(mSize != rhs.mSize)||(mChannel != rhs.mChannel))
- {
- return false;
- }
- return true;
+ if((mData != rhs.mData)||(mSize != rhs.mSize)||(mChannel != rhs.mChannel))
+ {
+ return false;
+ }
+ return true;
}
-/**
+/**
* LLHeapBuffer
*/
LLHeapBuffer::LLHeapBuffer() :
- mBuffer(NULL),
- mSize(0),
- mNextFree(NULL),
- mReclaimedBytes(0)
+ mBuffer(NULL),
+ mSize(0),
+ mNextFree(NULL),
+ mReclaimedBytes(0)
{
- const S32 DEFAULT_HEAP_BUFFER_SIZE = 16384;
- allocate(DEFAULT_HEAP_BUFFER_SIZE);
+ const S32 DEFAULT_HEAP_BUFFER_SIZE = 16384;
+ allocate(DEFAULT_HEAP_BUFFER_SIZE);
}
LLHeapBuffer::LLHeapBuffer(S32 size) :
- mBuffer(NULL),
- mSize(0),
- mNextFree(NULL),
- mReclaimedBytes(0)
+ mBuffer(NULL),
+ mSize(0),
+ mNextFree(NULL),
+ mReclaimedBytes(0)
{
- allocate(size);
+ allocate(size);
}
LLHeapBuffer::LLHeapBuffer(const U8* src, S32 len) :
- mBuffer(NULL),
- mSize(0),
- mNextFree(NULL),
- mReclaimedBytes(0)
+ mBuffer(NULL),
+ mSize(0),
+ mNextFree(NULL),
+ mReclaimedBytes(0)
{
- if((len > 0) && src)
- {
- allocate(len);
- if(mBuffer)
- {
- memcpy(mBuffer, src, len); /*Flawfinder: ignore*/
- }
- }
+ if((len > 0) && src)
+ {
+ allocate(len);
+ if(mBuffer)
+ {
+ memcpy(mBuffer, src, len); /*Flawfinder: ignore*/
+ }
+ }
}
// virtual
LLHeapBuffer::~LLHeapBuffer()
{
- delete[] mBuffer;
- mBuffer = NULL;
- mSize = 0;
- mNextFree = NULL;
+ delete[] mBuffer;
+ mBuffer = NULL;
+ mSize = 0;
+ mNextFree = NULL;
}
S32 LLHeapBuffer::bytesLeft() const
{
- return (mSize - (mNextFree - mBuffer));
+ return (mSize - (mNextFree - mBuffer));
}
// virtual
bool LLHeapBuffer::createSegment(
- S32 channel,
- S32 size,
- LLSegment& segment)
+ S32 channel,
+ S32 size,
+ LLSegment& segment)
{
- // get actual size of the segment.
- S32 actual_size = llmin(size, (mSize - S32(mNextFree - mBuffer)));
+ // get actual size of the segment.
+ S32 actual_size = llmin(size, (mSize - S32(mNextFree - mBuffer)));
- // bail if we cannot build a valid segment
- if(actual_size <= 0)
- {
- return false;
- }
+ // bail if we cannot build a valid segment
+ if(actual_size <= 0)
+ {
+ return false;
+ }
- // Yay, we're done.
- segment = LLSegment(channel, mNextFree, actual_size);
- mNextFree += actual_size;
- return true;
+ // Yay, we're done.
+ segment = LLSegment(channel, mNextFree, actual_size);
+ mNextFree += actual_size;
+ return true;
}
// virtual
bool LLHeapBuffer::reclaimSegment(const LLSegment& segment)
{
- if(containsSegment(segment))
- {
- mReclaimedBytes += segment.size();
- if(mReclaimedBytes == mSize)
- {
- // We have reclaimed all of the memory from this
- // buffer. Therefore, we can reset the mNextFree to the
- // start of the buffer, and reset the reclaimed bytes.
- mReclaimedBytes = 0;
- mNextFree = mBuffer;
- }
- else if(mReclaimedBytes > mSize)
- {
- LL_WARNS() << "LLHeapBuffer reclaimed more memory than allocated."
- << " This is probably programmer error." << LL_ENDL;
- }
- return true;
- }
- return false;
+ if(containsSegment(segment))
+ {
+ mReclaimedBytes += segment.size();
+ if(mReclaimedBytes == mSize)
+ {
+ // We have reclaimed all of the memory from this
+ // buffer. Therefore, we can reset the mNextFree to the
+ // start of the buffer, and reset the reclaimed bytes.
+ mReclaimedBytes = 0;
+ mNextFree = mBuffer;
+ }
+ else if(mReclaimedBytes > mSize)
+ {
+ LL_WARNS() << "LLHeapBuffer reclaimed more memory than allocated."
+ << " This is probably programmer error." << LL_ENDL;
+ }
+ return true;
+ }
+ return false;
}
// virtual
bool LLHeapBuffer::containsSegment(const LLSegment& segment) const
{
- // *NOTE: this check is fairly simple because heap buffers are
- // simple contiguous chunks of heap memory.
- if((mBuffer > segment.data())
- || ((mBuffer + mSize) < (segment.data() + segment.size())))
- {
- return false;
- }
- return true;
+ // *NOTE: this check is fairly simple because heap buffers are
+ // simple contiguous chunks of heap memory.
+ if((mBuffer > segment.data())
+ || ((mBuffer + mSize) < (segment.data() + segment.size())))
+ {
+ return false;
+ }
+ return true;
}
void LLHeapBuffer::allocate(S32 size)
{
- mReclaimedBytes = 0;
- mBuffer = new U8[size];
- if(mBuffer)
- {
- mSize = size;
- mNextFree = mBuffer;
- }
+ mReclaimedBytes = 0;
+ mBuffer = new U8[size];
+ if(mBuffer)
+ {
+ mSize = size;
+ mNextFree = mBuffer;
+ }
}
-/**
+/**
* LLBufferArray
*/
LLBufferArray::LLBufferArray() :
- mNextBaseChannel(0),
- mMutexp(NULL)
+ mNextBaseChannel(0),
+ mMutexp(NULL)
{
}
LLBufferArray::~LLBufferArray()
{
- std::for_each(mBuffers.begin(), mBuffers.end(), DeletePointer());
- mBuffers.clear();
- delete mMutexp;
+ std::for_each(mBuffers.begin(), mBuffers.end(), DeletePointer());
+ mBuffers.clear();
+ delete mMutexp;
}
// static
LLChannelDescriptors LLBufferArray::makeChannelConsumer(
- const LLChannelDescriptors& channels)
+ const LLChannelDescriptors& channels)
{
- LLChannelDescriptors rv(channels.out());
- return rv;
+ LLChannelDescriptors rv(channels.out());
+ return rv;
}
void LLBufferArray::lock()
{
- if(mMutexp)
- {
- mMutexp->lock() ;
- }
+ if(mMutexp)
+ {
+ mMutexp->lock() ;
+ }
}
void LLBufferArray::unlock()
{
- if(mMutexp)
- {
- mMutexp->unlock() ;
- }
+ if(mMutexp)
+ {
+ mMutexp->unlock() ;
+ }
}
LLMutex* LLBufferArray::getMutex()
{
- return mMutexp ;
+ return mMutexp ;
}
void LLBufferArray::setThreaded(bool threaded)
{
- if(threaded)
- {
- if(!mMutexp)
- {
- mMutexp = new LLMutex();
- }
- }
- else
- {
- if(mMutexp)
- {
- delete mMutexp ;
- mMutexp = NULL ;
- }
- }
+ if(threaded)
+ {
+ if(!mMutexp)
+ {
+ mMutexp = new LLMutex();
+ }
+ }
+ else
+ {
+ if(mMutexp)
+ {
+ delete mMutexp ;
+ mMutexp = NULL ;
+ }
+ }
}
LLChannelDescriptors LLBufferArray::nextChannel()
{
- LLChannelDescriptors rv(mNextBaseChannel++);
- return rv;
+ LLChannelDescriptors rv(mNextBaseChannel++);
+ return rv;
}
//mMutexp should be locked before calling this.
S32 LLBufferArray::capacity() const
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- S32 total = 0;
- const_buffer_iterator_t iter = mBuffers.begin();
- const_buffer_iterator_t end = mBuffers.end();
- for(; iter != end; ++iter)
- {
- total += (*iter)->capacity();
- }
- return total;
+ S32 total = 0;
+ const_buffer_iterator_t iter = mBuffers.begin();
+ const_buffer_iterator_t end = mBuffers.end();
+ for(; iter != end; ++iter)
+ {
+ total += (*iter)->capacity();
+ }
+ return total;
}
bool LLBufferArray::append(S32 channel, const U8* src, S32 len)
{
- LLMutexLock lock(mMutexp) ;
+ LLMutexLock lock(mMutexp) ;
- std::vector<LLSegment> segments;
- if(copyIntoBuffers(channel, src, len, segments))
- {
- mSegments.insert(mSegments.end(), segments.begin(), segments.end());
- return true;
- }
- return false;
+ std::vector<LLSegment> segments;
+ if(copyIntoBuffers(channel, src, len, segments))
+ {
+ mSegments.insert(mSegments.end(), segments.begin(), segments.end());
+ return true;
+ }
+ return false;
}
//mMutexp should be locked before calling this.
bool LLBufferArray::prepend(S32 channel, const U8* src, S32 len)
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- std::vector<LLSegment> segments;
- if(copyIntoBuffers(channel, src, len, segments))
- {
- mSegments.insert(mSegments.begin(), segments.begin(), segments.end());
- return true;
- }
- return false;
+ std::vector<LLSegment> segments;
+ if(copyIntoBuffers(channel, src, len, segments))
+ {
+ mSegments.insert(mSegments.begin(), segments.begin(), segments.end());
+ return true;
+ }
+ return false;
}
bool LLBufferArray::insertAfter(
- segment_iterator_t segment,
- S32 channel,
- const U8* src,
- S32 len)
-{
- std::vector<LLSegment> segments;
-
- LLMutexLock lock(mMutexp) ;
- if(mSegments.end() != segment)
- {
- ++segment;
- }
- if(copyIntoBuffers(channel, src, len, segments))
- {
- mSegments.insert(segment, segments.begin(), segments.end());
- return true;
- }
- return false;
+ segment_iterator_t segment,
+ S32 channel,
+ const U8* src,
+ S32 len)
+{
+ std::vector<LLSegment> segments;
+
+ LLMutexLock lock(mMutexp) ;
+ if(mSegments.end() != segment)
+ {
+ ++segment;
+ }
+ if(copyIntoBuffers(channel, src, len, segments))
+ {
+ mSegments.insert(segment, segments.begin(), segments.end());
+ return true;
+ }
+ return false;
}
//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address)
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
-
- segment_iterator_t end = mSegments.end();
- segment_iterator_t it = getSegment(address);
- if(it == end)
- {
- return end;
- }
-
- // We have the location and the segment.
- U8* base = (*it).data();
- S32 size = (*it).size();
- if(address == (base + size))
- {
- // No need to split, since this is the last byte of the
- // segment. We do not want to have zero length segments, since
- // that will only incur processing overhead with no advantage.
- return it;
- }
- S32 channel = (*it).getChannel();
- LLSegment segment1(channel, base, (address - base) + 1);
- *it = segment1;
- segment_iterator_t rv = it;
- ++it;
- LLSegment segment2(channel, address + 1, size - (address - base) - 1);
- mSegments.insert(it, segment2);
- return rv;
-}
-
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+
+ segment_iterator_t end = mSegments.end();
+ segment_iterator_t it = getSegment(address);
+ if(it == end)
+ {
+ return end;
+ }
+
+ // We have the location and the segment.
+ U8* base = (*it).data();
+ S32 size = (*it).size();
+ if(address == (base + size))
+ {
+ // No need to split, since this is the last byte of the
+ // segment. We do not want to have zero length segments, since
+ // that will only incur processing overhead with no advantage.
+ return it;
+ }
+ S32 channel = (*it).getChannel();
+ LLSegment segment1(channel, base, (address - base) + 1);
+ *it = segment1;
+ segment_iterator_t rv = it;
+ ++it;
+ LLSegment segment2(channel, address + 1, size - (address - base) - 1);
+ mSegments.insert(it, segment2);
+ return rv;
+}
+
//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::beginSegment()
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- return mSegments.begin();
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ return mSegments.begin();
}
//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::endSegment()
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- return mSegments.end();
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ return mSegments.end();
}
//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter(
- U8* address,
- LLSegment& segment)
-{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- segment_iterator_t rv = mSegments.begin();
- segment_iterator_t end = mSegments.end();
- if(!address)
- {
- if(rv != end)
- {
- segment = (*rv);
- }
- }
- else
- {
- // we have an address - find the segment it is in.
- for( ; rv != end; ++rv)
- {
- if((address >= (*rv).data())
- && (address < ((*rv).data() + (*rv).size())))
- {
- if((++address) < ((*rv).data() + (*rv).size()))
- {
- // it's in this segment - construct an appropriate
- // sub-segment.
- segment = LLSegment(
- (*rv).getChannel(),
- address,
- (*rv).size() - (address - (*rv).data()));
- }
- else
- {
- ++rv;
- if(rv != end)
- {
- segment = (*rv);
- }
- }
- break;
- }
- }
- }
- if(rv == end)
- {
- segment = LLSegment();
- }
- return rv;
+ U8* address,
+ LLSegment& segment)
+{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ segment_iterator_t rv = mSegments.begin();
+ segment_iterator_t end = mSegments.end();
+ if(!address)
+ {
+ if(rv != end)
+ {
+ segment = (*rv);
+ }
+ }
+ else
+ {
+ // we have an address - find the segment it is in.
+ for( ; rv != end; ++rv)
+ {
+ if((address >= (*rv).data())
+ && (address < ((*rv).data() + (*rv).size())))
+ {
+ if((++address) < ((*rv).data() + (*rv).size()))
+ {
+ // it's in this segment - construct an appropriate
+ // sub-segment.
+ segment = LLSegment(
+ (*rv).getChannel(),
+ address,
+ (*rv).size() - (address - (*rv).data()));
+ }
+ else
+ {
+ ++rv;
+ if(rv != end)
+ {
+ segment = (*rv);
+ }
+ }
+ break;
+ }
+ }
+ }
+ if(rv == end)
+ {
+ segment = LLSegment();
+ }
+ return rv;
}
//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address)
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- segment_iterator_t end = mSegments.end();
- if(!address)
- {
- return end;
- }
- segment_iterator_t it = mSegments.begin();
- for( ; it != end; ++it)
- {
- if((address >= (*it).data())&&(address < (*it).data() + (*it).size()))
- {
- // found it.
- return it;
- }
- }
- return end;
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ segment_iterator_t end = mSegments.end();
+ if(!address)
+ {
+ return end;
+ }
+ segment_iterator_t it = mSegments.begin();
+ for( ; it != end; ++it)
+ {
+ if((address >= (*it).data())&&(address < (*it).data() + (*it).size()))
+ {
+ // found it.
+ return it;
+ }
+ }
+ return end;
}
//mMutexp should be locked before calling this.
LLBufferArray::const_segment_iterator_t LLBufferArray::getSegment(
- U8* address) const
-{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- const_segment_iterator_t end = mSegments.end();
- if(!address)
- {
- return end;
- }
- const_segment_iterator_t it = mSegments.begin();
- for( ; it != end; ++it)
- {
- if((address >= (*it).data())
- && (address < (*it).data() + (*it).size()))
- {
- // found it.
- return it;
- }
- }
- return end;
+ U8* address) const
+{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ const_segment_iterator_t end = mSegments.end();
+ if(!address)
+ {
+ return end;
+ }
+ const_segment_iterator_t it = mSegments.begin();
+ for( ; it != end; ++it)
+ {
+ if((address >= (*it).data())
+ && (address < (*it).data() + (*it).size()))
+ {
+ // found it.
+ return it;
+ }
+ }
+ return end;
}
/*
-U8* LLBufferArray::getAddressAfter(U8* address)
-{
- U8* rv = NULL;
- segment_iterator_t it = getSegment(address);
- segment_iterator_t end = mSegments.end();
- if(it != end)
- {
- if(++address < ((*it).data() + (*it).size()))
- {
- // it's in the same segment
- rv = address;
- }
- else
- {
- // it's in the next segment
- if(++it != end)
- {
- rv = (*it).data();
- }
- }
- }
- return rv;
+U8* LLBufferArray::getAddressAfter(U8* address)
+{
+ U8* rv = NULL;
+ segment_iterator_t it = getSegment(address);
+ segment_iterator_t end = mSegments.end();
+ if(it != end)
+ {
+ if(++address < ((*it).data() + (*it).size()))
+ {
+ // it's in the same segment
+ rv = address;
+ }
+ else
+ {
+ // it's in the next segment
+ if(++it != end)
+ {
+ rv = (*it).data();
+ }
+ }
+ }
+ return rv;
}
*/
S32 LLBufferArray::countAfter(S32 channel, U8* start) const
{
- S32 count = 0;
- S32 offset = 0;
- const_segment_iterator_t it;
-
- LLMutexLock lock(mMutexp) ;
- const_segment_iterator_t end = mSegments.end();
- if(start)
- {
- it = getSegment(start);
- if(it == end)
- {
- return count;
- }
- if(++start < ((*it).data() + (*it).size()))
- {
- // it's in the same segment
- offset = start - (*it).data();
- }
- else if(++it == end)
- {
- // it's in the next segment
- return count;
- }
- }
- else
- {
- it = mSegments.begin();
- }
- while(it != end)
- {
- if((*it).isOnChannel(channel))
- {
- count += (*it).size() - offset;
- }
- offset = 0;
- ++it;
- }
- return count;
+ S32 count = 0;
+ S32 offset = 0;
+ const_segment_iterator_t it;
+
+ LLMutexLock lock(mMutexp) ;
+ const_segment_iterator_t end = mSegments.end();
+ if(start)
+ {
+ it = getSegment(start);
+ if(it == end)
+ {
+ return count;
+ }
+ if(++start < ((*it).data() + (*it).size()))
+ {
+ // it's in the same segment
+ offset = start - (*it).data();
+ }
+ else if(++it == end)
+ {
+ // it's in the next segment
+ return count;
+ }
+ }
+ else
+ {
+ it = mSegments.begin();
+ }
+ while(it != end)
+ {
+ if((*it).isOnChannel(channel))
+ {
+ count += (*it).size() - offset;
+ }
+ offset = 0;
+ ++it;
+ }
+ return count;
}
U8* LLBufferArray::readAfter(
- S32 channel,
- U8* start,
- U8* dest,
- S32& len) const
-{
- U8* rv = start;
- if(!dest || len <= 0)
- {
- return rv;
- }
- S32 bytes_left = len;
- len = 0;
- S32 bytes_to_copy = 0;
- const_segment_iterator_t it;
-
- LLMutexLock lock(mMutexp) ;
- const_segment_iterator_t end = mSegments.end();
- if(start)
- {
- it = getSegment(start);
- if(it == end)
- {
- return rv;
- }
- if((++start < ((*it).data() + (*it).size()))
- && (*it).isOnChannel(channel))
- {
- // copy the data out of this segment
- S32 bytes_in_segment = (*it).size() - (start - (*it).data());
- bytes_to_copy = llmin(bytes_left, bytes_in_segment);
- memcpy(dest, start, bytes_to_copy); /*Flawfinder: ignore*/
- len += bytes_to_copy;
- bytes_left -= bytes_to_copy;
- rv = start + bytes_to_copy - 1;
- ++it;
- }
- else
- {
- ++it;
- }
- }
- else
- {
- it = mSegments.begin();
- }
- while(bytes_left && (it != end))
- {
- if(!((*it).isOnChannel(channel)))
- {
- ++it;
- continue;
- }
- bytes_to_copy = llmin(bytes_left, (*it).size());
- memcpy(dest + len, (*it).data(), bytes_to_copy); /*Flawfinder: ignore*/
- len += bytes_to_copy;
- bytes_left -= bytes_to_copy;
- rv = (*it).data() + bytes_to_copy - 1;
- ++it;
- }
- return rv;
+ S32 channel,
+ U8* start,
+ U8* dest,
+ S32& len) const
+{
+ U8* rv = start;
+ if(!dest || len <= 0)
+ {
+ return rv;
+ }
+ S32 bytes_left = len;
+ len = 0;
+ S32 bytes_to_copy = 0;
+ const_segment_iterator_t it;
+
+ LLMutexLock lock(mMutexp) ;
+ const_segment_iterator_t end = mSegments.end();
+ if(start)
+ {
+ it = getSegment(start);
+ if(it == end)
+ {
+ return rv;
+ }
+ if((++start < ((*it).data() + (*it).size()))
+ && (*it).isOnChannel(channel))
+ {
+ // copy the data out of this segment
+ S32 bytes_in_segment = (*it).size() - (start - (*it).data());
+ bytes_to_copy = llmin(bytes_left, bytes_in_segment);
+ memcpy(dest, start, bytes_to_copy); /*Flawfinder: ignore*/
+ len += bytes_to_copy;
+ bytes_left -= bytes_to_copy;
+ rv = start + bytes_to_copy - 1;
+ ++it;
+ }
+ else
+ {
+ ++it;
+ }
+ }
+ else
+ {
+ it = mSegments.begin();
+ }
+ while(bytes_left && (it != end))
+ {
+ if(!((*it).isOnChannel(channel)))
+ {
+ ++it;
+ continue;
+ }
+ bytes_to_copy = llmin(bytes_left, (*it).size());
+ memcpy(dest + len, (*it).data(), bytes_to_copy); /*Flawfinder: ignore*/
+ len += bytes_to_copy;
+ bytes_left -= bytes_to_copy;
+ rv = (*it).data() + bytes_to_copy - 1;
+ ++it;
+ }
+ return rv;
}
U8* LLBufferArray::seek(
- S32 channel,
- U8* start,
- S32 delta) const
-{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- const_segment_iterator_t it;
- const_segment_iterator_t end = mSegments.end();
- U8* rv = start;
- if(0 == delta)
- {
- if((U8*)npos == start)
- {
- // someone is looking for end of data.
- segment_list_t::const_reverse_iterator rit = mSegments.rbegin();
- segment_list_t::const_reverse_iterator rend = mSegments.rend();
- while(rit != rend)
- {
- if(!((*rit).isOnChannel(channel)))
- {
- ++rit;
- continue;
- }
- rv = (*rit).data() + (*rit).size();
- break;
- }
- }
- else if(start)
- {
- // This is sort of a weird case - check if zero bytes away
- // from current position is on channel and return start if
- // that is true. Otherwise, return NULL.
- it = getSegment(start);
- if((it == end) || !(*it).isOnChannel(channel))
- {
- rv = NULL;
- }
- }
- else
- {
- // Start is NULL, so return the very first byte on the
- // channel, or NULL.
- it = mSegments.begin();
- while((it != end) && !(*it).isOnChannel(channel))
- {
- ++it;
- }
- if(it != end)
- {
- rv = (*it).data();
- }
- }
- return rv;
- }
- if(start)
- {
- it = getSegment(start);
- if((it != end) && (*it).isOnChannel(channel))
- {
- if(delta > 0)
- {
- S32 bytes_in_segment = (*it).size() - (start - (*it).data());
- S32 local_delta = llmin(delta, bytes_in_segment);
- rv += local_delta;
- delta -= local_delta;
- ++it;
- }
- else
- {
- S32 bytes_in_segment = start - (*it).data();
- S32 local_delta = llmin(llabs(delta), bytes_in_segment);
- rv -= local_delta;
- delta += local_delta;
- }
- }
- }
- else if(delta < 0)
- {
- // start is NULL, and delta indicates seeking backwards -
- // return NULL.
- return NULL;
- }
- else
- {
- // start is NULL and delta > 0
- it = mSegments.begin();
- }
- if(delta > 0)
- {
- // At this point, we have an iterator into the segments, and
- // are seeking forward until delta is zero or we run out
- while(delta && (it != end))
- {
- if(!((*it).isOnChannel(channel)))
- {
- ++it;
- continue;
- }
- if(delta <= (*it).size())
- {
- // it's in this segment
- rv = (*it).data() + delta;
- }
- delta -= (*it).size();
- ++it;
- }
- if(delta && (it == end))
- {
- // Whoops - sought past end.
- rv = NULL;
- }
- }
- else //if(delta < 0)
- {
- // We are at the beginning of a segment, and need to search
- // backwards.
- segment_list_t::const_reverse_iterator rit(it);
- segment_list_t::const_reverse_iterator rend = mSegments.rend();
- while(delta && (rit != rend))
- {
- if(!((*rit).isOnChannel(channel)))
- {
- ++rit;
- continue;
- }
- if(llabs(delta) <= (*rit).size())
- {
- // it's in this segment.
- rv = (*rit).data() + (*rit).size() + delta;
- delta = 0;
- }
- else
- {
- delta += (*rit).size();
- }
- ++rit;
- }
- if(delta && (rit == rend))
- {
- // sought past the beginning.
- rv = NULL;
- }
- }
- return rv;
+ S32 channel,
+ U8* start,
+ S32 delta) const
+{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ const_segment_iterator_t it;
+ const_segment_iterator_t end = mSegments.end();
+ U8* rv = start;
+ if(0 == delta)
+ {
+ if((U8*)npos == start)
+ {
+ // someone is looking for end of data.
+ segment_list_t::const_reverse_iterator rit = mSegments.rbegin();
+ segment_list_t::const_reverse_iterator rend = mSegments.rend();
+ while(rit != rend)
+ {
+ if(!((*rit).isOnChannel(channel)))
+ {
+ ++rit;
+ continue;
+ }
+ rv = (*rit).data() + (*rit).size();
+ break;
+ }
+ }
+ else if(start)
+ {
+ // This is sort of a weird case - check if zero bytes away
+ // from current position is on channel and return start if
+ // that is true. Otherwise, return NULL.
+ it = getSegment(start);
+ if((it == end) || !(*it).isOnChannel(channel))
+ {
+ rv = NULL;
+ }
+ }
+ else
+ {
+ // Start is NULL, so return the very first byte on the
+ // channel, or NULL.
+ it = mSegments.begin();
+ while((it != end) && !(*it).isOnChannel(channel))
+ {
+ ++it;
+ }
+ if(it != end)
+ {
+ rv = (*it).data();
+ }
+ }
+ return rv;
+ }
+ if(start)
+ {
+ it = getSegment(start);
+ if((it != end) && (*it).isOnChannel(channel))
+ {
+ if(delta > 0)
+ {
+ S32 bytes_in_segment = (*it).size() - (start - (*it).data());
+ S32 local_delta = llmin(delta, bytes_in_segment);
+ rv += local_delta;
+ delta -= local_delta;
+ ++it;
+ }
+ else
+ {
+ S32 bytes_in_segment = start - (*it).data();
+ S32 local_delta = llmin(llabs(delta), bytes_in_segment);
+ rv -= local_delta;
+ delta += local_delta;
+ }
+ }
+ }
+ else if(delta < 0)
+ {
+ // start is NULL, and delta indicates seeking backwards -
+ // return NULL.
+ return NULL;
+ }
+ else
+ {
+ // start is NULL and delta > 0
+ it = mSegments.begin();
+ }
+ if(delta > 0)
+ {
+ // At this point, we have an iterator into the segments, and
+ // are seeking forward until delta is zero or we run out
+ while(delta && (it != end))
+ {
+ if(!((*it).isOnChannel(channel)))
+ {
+ ++it;
+ continue;
+ }
+ if(delta <= (*it).size())
+ {
+ // it's in this segment
+ rv = (*it).data() + delta;
+ }
+ delta -= (*it).size();
+ ++it;
+ }
+ if(delta && (it == end))
+ {
+ // Whoops - sought past end.
+ rv = NULL;
+ }
+ }
+ else //if(delta < 0)
+ {
+ // We are at the beginning of a segment, and need to search
+ // backwards.
+ segment_list_t::const_reverse_iterator rit(it);
+ segment_list_t::const_reverse_iterator rend = mSegments.rend();
+ while(delta && (rit != rend))
+ {
+ if(!((*rit).isOnChannel(channel)))
+ {
+ ++rit;
+ continue;
+ }
+ if(llabs(delta) <= (*rit).size())
+ {
+ // it's in this segment.
+ rv = (*rit).data() + (*rit).size() + delta;
+ delta = 0;
+ }
+ else
+ {
+ delta += (*rit).size();
+ }
+ ++rit;
+ }
+ if(delta && (rit == rend))
+ {
+ // sought past the beginning.
+ rv = NULL;
+ }
+ }
+ return rv;
}
//test use only
bool LLBufferArray::takeContents(LLBufferArray& source)
{
- LLMutexLock lock(mMutexp);
- source.lock();
+ LLMutexLock lock(mMutexp);
+ source.lock();
- std::copy(
- source.mBuffers.begin(),
- source.mBuffers.end(),
- std::back_insert_iterator<buffer_list_t>(mBuffers));
- source.mBuffers.clear();
- std::copy(
- source.mSegments.begin(),
- source.mSegments.end(),
- std::back_insert_iterator<segment_list_t>(mSegments));
- source.mSegments.clear();
- source.mNextBaseChannel = 0;
- source.unlock();
+ std::copy(
+ source.mBuffers.begin(),
+ source.mBuffers.end(),
+ std::back_insert_iterator<buffer_list_t>(mBuffers));
+ source.mBuffers.clear();
+ std::copy(
+ source.mSegments.begin(),
+ source.mSegments.end(),
+ std::back_insert_iterator<segment_list_t>(mSegments));
+ source.mSegments.clear();
+ source.mNextBaseChannel = 0;
+ source.unlock();
- return true;
+ return true;
}
//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::makeSegment(
- S32 channel,
- S32 len)
-{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- // start at the end of the buffers, because it is the most likely
- // to have free space.
- LLSegment segment;
- buffer_list_t::reverse_iterator it = mBuffers.rbegin();
- buffer_list_t::reverse_iterator end = mBuffers.rend();
- bool made_segment = false;
- for(; it != end; ++it)
- {
- if((*it)->createSegment(channel, len, segment))
- {
- made_segment = true;
- break;
- }
- }
- segment_iterator_t send = mSegments.end();
- if(!made_segment)
- {
- LLBuffer* buf = new LLHeapBuffer;
- mBuffers.push_back(buf);
- if(!buf->createSegment(channel, len, segment))
- {
- // failed. this should never happen.
- return send;
- }
- }
-
- // store and return the newly made segment
- mSegments.insert(send, segment);
- std::list<LLSegment>::reverse_iterator rv = mSegments.rbegin();
- ++rv;
- send = rv.base();
- return send;
+ S32 channel,
+ S32 len)
+{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ // start at the end of the buffers, because it is the most likely
+ // to have free space.
+ LLSegment segment;
+ buffer_list_t::reverse_iterator it = mBuffers.rbegin();
+ buffer_list_t::reverse_iterator end = mBuffers.rend();
+ bool made_segment = false;
+ for(; it != end; ++it)
+ {
+ if((*it)->createSegment(channel, len, segment))
+ {
+ made_segment = true;
+ break;
+ }
+ }
+ segment_iterator_t send = mSegments.end();
+ if(!made_segment)
+ {
+ LLBuffer* buf = new LLHeapBuffer;
+ mBuffers.push_back(buf);
+ if(!buf->createSegment(channel, len, segment))
+ {
+ // failed. this should never happen.
+ return send;
+ }
+ }
+
+ // store and return the newly made segment
+ mSegments.insert(send, segment);
+ std::list<LLSegment>::reverse_iterator rv = mSegments.rbegin();
+ ++rv;
+ send = rv.base();
+ return send;
}
//mMutexp should be locked before calling this.
bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter)
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
-
- // Find out which buffer contains the segment, and if it is found,
- // ask it to reclaim the memory.
- bool rv = false;
- LLSegment segment(*erase_iter);
- buffer_iterator_t iter = mBuffers.begin();
- buffer_iterator_t end = mBuffers.end();
- for(; iter != end; ++iter)
- {
- // We can safely call reclaimSegment on every buffer, and once
- // it returns true, the segment was found.
- if((*iter)->reclaimSegment(segment))
- {
- rv = true;
- break;
- }
- }
-
- // No need to get the return value since we are not interested in
- // the interator retured by the call.
- (void)mSegments.erase(erase_iter);
- return rv;
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+
+ // Find out which buffer contains the segment, and if it is found,
+ // ask it to reclaim the memory.
+ bool rv = false;
+ LLSegment segment(*erase_iter);
+ buffer_iterator_t iter = mBuffers.begin();
+ buffer_iterator_t end = mBuffers.end();
+ for(; iter != end; ++iter)
+ {
+ // We can safely call reclaimSegment on every buffer, and once
+ // it returns true, the segment was found.
+ if((*iter)->reclaimSegment(segment))
+ {
+ rv = true;
+ break;
+ }
+ }
+
+ // No need to get the return value since we are not interested in
+ // the interator retured by the call.
+ (void)mSegments.erase(erase_iter);
+ return rv;
}
//mMutexp should be locked before calling this.
bool LLBufferArray::copyIntoBuffers(
- S32 channel,
- const U8* src,
- S32 len,
- std::vector<LLSegment>& segments)
-{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- if(!src || !len) return false;
- S32 copied = 0;
- LLSegment segment;
- buffer_iterator_t it = mBuffers.begin();
- buffer_iterator_t end = mBuffers.end();
- for(; it != end;)
- {
- if(!(*it)->createSegment(channel, len, segment))
- {
- ++it;
- continue;
- }
- segments.push_back(segment);
- S32 bytes = llmin(segment.size(), len);
- memcpy(segment.data(), src + copied, bytes); /* Flawfinder: Ignore */
- copied += bytes;
- len -= bytes;
- if(0 == len)
- {
- break;
- }
- }
- while(len)
- {
- LLBuffer* buf = new LLHeapBuffer;
- mBuffers.push_back(buf);
- if(!buf->createSegment(channel, len, segment))
- {
- // this totally failed - bail. This is the weird corner
- // case were we 'leak' memory. No worries about an actual
- // leak - we will still reclaim the memory later, but this
- // particular buffer array is hosed for some reason.
- // This should never happen.
- return false;
- }
- segments.push_back(segment);
- memcpy(segment.data(), src + copied, segment.size()); /*Flawfinder: ignore*/
- copied += segment.size();
- len -= segment.size();
- }
- return true;
+ S32 channel,
+ const U8* src,
+ S32 len,
+ std::vector<LLSegment>& segments)
+{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ if(!src || !len) return false;
+ S32 copied = 0;
+ LLSegment segment;
+ buffer_iterator_t it = mBuffers.begin();
+ buffer_iterator_t end = mBuffers.end();
+ for(; it != end;)
+ {
+ if(!(*it)->createSegment(channel, len, segment))
+ {
+ ++it;
+ continue;
+ }
+ segments.push_back(segment);
+ S32 bytes = llmin(segment.size(), len);
+ memcpy(segment.data(), src + copied, bytes); /* Flawfinder: Ignore */
+ copied += bytes;
+ len -= bytes;
+ if(0 == len)
+ {
+ break;
+ }
+ }
+ while(len)
+ {
+ LLBuffer* buf = new LLHeapBuffer;
+ mBuffers.push_back(buf);
+ if(!buf->createSegment(channel, len, segment))
+ {
+ // this totally failed - bail. This is the weird corner
+ // case were we 'leak' memory. No worries about an actual
+ // leak - we will still reclaim the memory later, but this
+ // particular buffer array is hosed for some reason.
+ // This should never happen.
+ return false;
+ }
+ segments.push_back(segment);
+ memcpy(segment.data(), src + copied, segment.size()); /*Flawfinder: ignore*/
+ copied += segment.size();
+ len -= segment.size();
+ }
+ return true;
}