summaryrefslogtreecommitdiff
path: root/indra/llmessage/llbuffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/llbuffer.h')
-rw-r--r--indra/llmessage/llbuffer.h1032
1 files changed, 516 insertions, 516 deletions
diff --git a/indra/llmessage/llbuffer.h b/indra/llmessage/llbuffer.h
index ccdb9fa7ee..89229ea9d1 100644
--- a/indra/llmessage/llbuffer.h
+++ b/indra/llmessage/llbuffer.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llbuffer.h
* @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$
*/
@@ -40,26 +40,26 @@
#include <vector>
class LLMutex;
-/**
+/**
* @class LLChannelDescriptors
* @brief A way simple interface to accesss channels inside a buffer
*/
class LLChannelDescriptors
{
public:
- // enumeration for segmenting the channel information
- enum { E_CHANNEL_COUNT = 3 };
- LLChannelDescriptors() : mBaseChannel(0) {}
- explicit LLChannelDescriptors(S32 base) : mBaseChannel(base) {}
- S32 in() const { return mBaseChannel; }
- S32 out() const { return mBaseChannel + 1; }
- //S32 err() const { return mBaseChannel + 2; }
+ // enumeration for segmenting the channel information
+ enum { E_CHANNEL_COUNT = 3 };
+ LLChannelDescriptors() : mBaseChannel(0) {}
+ explicit LLChannelDescriptors(S32 base) : mBaseChannel(base) {}
+ S32 in() const { return mBaseChannel; }
+ S32 out() const { return mBaseChannel + 1; }
+ //S32 err() const { return mBaseChannel + 2; }
protected:
- S32 mBaseChannel;
+ S32 mBaseChannel;
};
-/**
+/**
* @class LLSegment
* @brief A segment is a single, contiguous chunk of memory in a buffer
*
@@ -70,62 +70,62 @@ protected:
* as necessary.
* This is the preferred interface for working with memory blocks,
* since it is the only way to safely, inexpensively, and directly
- * access linear blocks of memory.
+ * access linear blocks of memory.
*/
class LLSegment
{
public:
- LLSegment();
- LLSegment(S32 channel, U8* data, S32 data_len);
- ~LLSegment();
-
- /**
- * @brief Check if this segment is on the given channel.
- *
- */
- bool isOnChannel(S32 channel) const;
-
- /**
- * @brief Get the channel
- */
- S32 getChannel() const;
-
- /**
- * @brief Set the channel
- */
- void setChannel(S32 channel);
-
- /**
- * @brief Return a raw pointer to the current data set.
- *
- * The pointer returned can be used for reading or even adjustment
- * if you are a bit crazy up to size() bytes into memory.
- * @return A potentially NULL pointer to the raw buffer data
- */
- U8* data() const;
-
- /**
- * @brief Return the size of the segment
- */
- S32 size() const;
-
- /**
- * @brief Check if two segments are the same.
- *
- * Two segments are considered equal if they are on the same
- * channel and cover the exact same address range.
- * @param rhs the segment to compare with this segment.
- * @return Returns true if they are equal.
- */
- bool operator==(const LLSegment& rhs) const;
+ LLSegment();
+ LLSegment(S32 channel, U8* data, S32 data_len);
+ ~LLSegment();
+
+ /**
+ * @brief Check if this segment is on the given channel.
+ *
+ */
+ bool isOnChannel(S32 channel) const;
+
+ /**
+ * @brief Get the channel
+ */
+ S32 getChannel() const;
+
+ /**
+ * @brief Set the channel
+ */
+ void setChannel(S32 channel);
+
+ /**
+ * @brief Return a raw pointer to the current data set.
+ *
+ * The pointer returned can be used for reading or even adjustment
+ * if you are a bit crazy up to size() bytes into memory.
+ * @return A potentially NULL pointer to the raw buffer data
+ */
+ U8* data() const;
+
+ /**
+ * @brief Return the size of the segment
+ */
+ S32 size() const;
+
+ /**
+ * @brief Check if two segments are the same.
+ *
+ * Two segments are considered equal if they are on the same
+ * channel and cover the exact same address range.
+ * @param rhs the segment to compare with this segment.
+ * @return Returns true if they are equal.
+ */
+ bool operator==(const LLSegment& rhs) const;
protected:
- S32 mChannel;
- U8* mData;
- S32 mSize;
+ S32 mChannel;
+ U8* mData;
+ S32 mSize;
};
-/**
+/**
* @class LLBuffer
* @brief Abstract base class for buffers
*
@@ -136,58 +136,58 @@ protected:
class LLBuffer
{
public:
- /**
- * @brief The buffer base class should have no responsibilities
- * other than an interface.
- */
- virtual ~LLBuffer() {}
-
- /**
- * @brief Generate a segment for this buffer.
- *
- * The segment returned is always contiguous memory. This call can
- * fail if no contiguous memory is available, eg, offset is past
- * the end. The segment returned may be smaller than the requested
- * size. The segment will never be larger than the requested size.
- * @param channel The channel for the segment.
- * @param offset The offset from zero in the buffer.
- * @param size The requested size of the segment.
- * @param segment[out] The out-value from the operation
- * @return Returns true if a segment was found.
- */
- virtual bool createSegment(S32 channel, S32 size, LLSegment& segment) = 0;
-
- /**
- * @brief Reclaim a segment from this buffer.
- *
- * This method is called on a buffer object when a caller is done
- * with a contiguous segment of memory inside this buffer. Since
- * segments can be cut arbitrarily outside of the control of the
- * buffer, this segment may not match any segment returned from
- * <code>createSegment()</code>.
- * @param segment The contiguous buffer segment to reclaim.
- * @return Returns true if the call was successful.
- */
- virtual bool reclaimSegment(const LLSegment& segment) = 0;
-
- /**
- * @brief Test if a segment is inside this buffer.
- *
- * @param segment The contiguous buffer segment to test.
- * @return Returns true if the segment is in the bufffer.
- */
- virtual bool containsSegment(const LLSegment& segment) const = 0;
-
- /**
- * @brief Return the current number of bytes allocated.
- *
- * This was implemented as a debugging tool, and it is not
- * necessarily a good idea to use it for anything else.
- */
- virtual S32 capacity() const = 0;
+ /**
+ * @brief The buffer base class should have no responsibilities
+ * other than an interface.
+ */
+ virtual ~LLBuffer() {}
+
+ /**
+ * @brief Generate a segment for this buffer.
+ *
+ * The segment returned is always contiguous memory. This call can
+ * fail if no contiguous memory is available, eg, offset is past
+ * the end. The segment returned may be smaller than the requested
+ * size. The segment will never be larger than the requested size.
+ * @param channel The channel for the segment.
+ * @param offset The offset from zero in the buffer.
+ * @param size The requested size of the segment.
+ * @param segment[out] The out-value from the operation
+ * @return Returns true if a segment was found.
+ */
+ virtual bool createSegment(S32 channel, S32 size, LLSegment& segment) = 0;
+
+ /**
+ * @brief Reclaim a segment from this buffer.
+ *
+ * This method is called on a buffer object when a caller is done
+ * with a contiguous segment of memory inside this buffer. Since
+ * segments can be cut arbitrarily outside of the control of the
+ * buffer, this segment may not match any segment returned from
+ * <code>createSegment()</code>.
+ * @param segment The contiguous buffer segment to reclaim.
+ * @return Returns true if the call was successful.
+ */
+ virtual bool reclaimSegment(const LLSegment& segment) = 0;
+
+ /**
+ * @brief Test if a segment is inside this buffer.
+ *
+ * @param segment The contiguous buffer segment to test.
+ * @return Returns true if the segment is in the bufffer.
+ */
+ virtual bool containsSegment(const LLSegment& segment) const = 0;
+
+ /**
+ * @brief Return the current number of bytes allocated.
+ *
+ * This was implemented as a debugging tool, and it is not
+ * necessarily a good idea to use it for anything else.
+ */
+ virtual S32 capacity() const = 0;
};
-/**
+/**
* @class LLHeapBuffer
* @brief A large contiguous buffer allocated on the heap with new[].
*
@@ -198,99 +198,99 @@ public:
class LLHeapBuffer : public LLBuffer
{
public:
- /**
- * @brief Construct a heap buffer with a reasonable default size.
- */
- LLHeapBuffer();
-
- /**
- * @brief Construct a heap buffer with a specified size.
- *
- * @param size The minimum size of the buffer.
- */
- explicit LLHeapBuffer(S32 size);
-
- /**
- * @brief Construct a heap buffer of minimum size len, and copy from src.
- *
- * @param src The source of the data to be copied.
- * @param len The minimum size of the buffer.
- */
- LLHeapBuffer(const U8* src, S32 len);
-
- /**
- * @brief Simple destruction.
- */
- virtual ~LLHeapBuffer();
-
- /**
- * @brief Get the number of bytes left in the buffer.
- *
- * Note that this is not a virtual function, and only available in
- * the LLHeapBuffer as a debugging aid.
- * @return Returns the number of bytes left.
- */
- S32 bytesLeft() const;
-
- /**
- * @brief Generate a segment for this buffer.
- *
- * The segment returned is always contiguous memory. This call can
- * fail if no contiguous memory is available, eg, offset is past
- * the end. The segment returned may be smaller than the requested
- * size. It is up to the caller to delete the segment returned.
- * @param channel The channel for the segment.
- * @param offset The offset from zero in the buffer
- * @param size The requested size of the segment
- * @param segment[out] The out-value from the operation
- * @return Returns true if a segment was found.
- */
- virtual bool createSegment(S32 channel, S32 size, LLSegment& segment);
-
- /**
- * @brief reclaim a segment from this buffer.
- *
- * This method is called on a buffer object when a caller is done
- * with a contiguous segment of memory inside this buffer. Since
- * segments can be cut arbitrarily outside of the control of the
- * buffer, this segment may not match any segment returned from
- * <code>createSegment()</code>.
- * This call will fail if the segment passed in is note completely
- * inside the buffer, eg, if the segment starts before this buffer
- * in memory or ends after it.
- * @param segment The contiguous buffer segment to reclaim.
- * @return Returns true if the call was successful.
- */
- virtual bool reclaimSegment(const LLSegment& segment);
-
- /**
- * @brief Test if a segment is inside this buffer.
- *
- * @param segment The contiguous buffer segment to test.
- * @return Returns true if the segment is in the bufffer.
- */
- virtual bool containsSegment(const LLSegment& segment) const;
-
- /**
- * @brief Return the current number of bytes allocated.
- */
- virtual S32 capacity() const { return mSize; }
+ /**
+ * @brief Construct a heap buffer with a reasonable default size.
+ */
+ LLHeapBuffer();
+
+ /**
+ * @brief Construct a heap buffer with a specified size.
+ *
+ * @param size The minimum size of the buffer.
+ */
+ explicit LLHeapBuffer(S32 size);
+
+ /**
+ * @brief Construct a heap buffer of minimum size len, and copy from src.
+ *
+ * @param src The source of the data to be copied.
+ * @param len The minimum size of the buffer.
+ */
+ LLHeapBuffer(const U8* src, S32 len);
+
+ /**
+ * @brief Simple destruction.
+ */
+ virtual ~LLHeapBuffer();
+
+ /**
+ * @brief Get the number of bytes left in the buffer.
+ *
+ * Note that this is not a virtual function, and only available in
+ * the LLHeapBuffer as a debugging aid.
+ * @return Returns the number of bytes left.
+ */
+ S32 bytesLeft() const;
+
+ /**
+ * @brief Generate a segment for this buffer.
+ *
+ * The segment returned is always contiguous memory. This call can
+ * fail if no contiguous memory is available, eg, offset is past
+ * the end. The segment returned may be smaller than the requested
+ * size. It is up to the caller to delete the segment returned.
+ * @param channel The channel for the segment.
+ * @param offset The offset from zero in the buffer
+ * @param size The requested size of the segment
+ * @param segment[out] The out-value from the operation
+ * @return Returns true if a segment was found.
+ */
+ virtual bool createSegment(S32 channel, S32 size, LLSegment& segment);
+
+ /**
+ * @brief reclaim a segment from this buffer.
+ *
+ * This method is called on a buffer object when a caller is done
+ * with a contiguous segment of memory inside this buffer. Since
+ * segments can be cut arbitrarily outside of the control of the
+ * buffer, this segment may not match any segment returned from
+ * <code>createSegment()</code>.
+ * This call will fail if the segment passed in is note completely
+ * inside the buffer, eg, if the segment starts before this buffer
+ * in memory or ends after it.
+ * @param segment The contiguous buffer segment to reclaim.
+ * @return Returns true if the call was successful.
+ */
+ virtual bool reclaimSegment(const LLSegment& segment);
+
+ /**
+ * @brief Test if a segment is inside this buffer.
+ *
+ * @param segment The contiguous buffer segment to test.
+ * @return Returns true if the segment is in the bufffer.
+ */
+ virtual bool containsSegment(const LLSegment& segment) const;
+
+ /**
+ * @brief Return the current number of bytes allocated.
+ */
+ virtual S32 capacity() const { return mSize; }
protected:
- U8* mBuffer;
- S32 mSize;
- U8* mNextFree;
- S32 mReclaimedBytes;
+ U8* mBuffer;
+ S32 mSize;
+ U8* mNextFree;
+ S32 mReclaimedBytes;
private:
- /**
- * @brief Helper method to allocate a buffer and correctly set
- * intertnal state of this buffer.
- */
- void allocate(S32 size);
+ /**
+ * @brief Helper method to allocate a buffer and correctly set
+ * intertnal state of this buffer.
+ */
+ void allocate(S32 size);
};
-/**
+/**
* @class LLBufferArray
* @brief Class to represent scattered memory buffers and in-order segments
* of that buffered data.
@@ -300,326 +300,326 @@ private:
class LLBufferArray
{
public:
- typedef std::vector<LLBuffer*> buffer_list_t;
- typedef buffer_list_t::iterator buffer_iterator_t;
- typedef buffer_list_t::const_iterator const_buffer_iterator_t;
- typedef std::list<LLSegment> segment_list_t;
- typedef segment_list_t::const_iterator const_segment_iterator_t;
- typedef segment_list_t::iterator segment_iterator_t;
- enum { npos = 0xffffffff };
-
- LLBufferArray();
- ~LLBufferArray();
-
- /* @name Channel methods
- */
- //@{
- /**
- * @brief Generate the a channel descriptor which consumes the
- * output for the channel passed in.
- */
- static LLChannelDescriptors makeChannelConsumer(
- const LLChannelDescriptors& channels);
-
- /**
- * @brief Generate the next channel descriptor for this buffer array.
- *
- * The channel descriptor interface is how the buffer array
- * clients can know where to read and write data. Use this
- * interface to get the 'next' channel set for usage. This is a
- * bit of a simple hack until it's utility indicates it should be
- * extended.
- * @return Returns a valid channel descriptor set for input and output.
- */
- LLChannelDescriptors nextChannel();
- //@}
-
- /* @name Data methods
- */
- //@{
-
- /**
- * @brief Return the sum of all allocated bytes.
- */
- S32 capacity() const;
-
- // These methods will be useful once there is any kind of buffer
- // besides a heap buffer.
- //bool append(EBufferChannel channel, LLBuffer* data);
- //bool prepend(EBufferChannel channel, LLBuffer* data);
- //bool insertAfter(
- // segment_iterator_t segment,
- // EBufferChannel channel,
- // LLBuffer* data);
-
- /**
- * @brief Put data on a channel at the end of this buffer array.
- *
- * The data is copied from src into the buffer array. At least one
- * new segment is created and put on the end of the array. This
- * object will internally allocate new buffers if necessary.
- * @param channel The channel for this data
- * @param src The start of memory for the data to be copied
- * @param len The number of bytes of data to copy
- * @return Returns true if the method worked.
- */
- bool append(S32 channel, const U8* src, S32 len);
-
- /**
- * @brief Put data on a channel at the front of this buffer array.
- *
- * The data is copied from src into the buffer array. At least one
- * new segment is created and put in the front of the array. This
- * object will internally allocate new buffers if necessary.
- * @param channel The channel for this data
- * @param src The start of memory for the data to be copied
- * @param len The number of bytes of data to copy
- * @return Returns true if the method worked.
- */
- bool prepend(S32 channel, const U8* src, S32 len);
-
- /**
- * @brief Insert data into a buffer array after a particular segment.
- *
- * The data is copied from src into the buffer array. At least one
- * new segment is created and put in the array. This object will
- * internally allocate new buffers if necessary.
- * @param segment The segment in front of the new segments location
- * @param channel The channel for this data
- * @param src The start of memory for the data to be copied
- * @param len The number of bytes of data to copy
- * @return Returns true if the method worked.
- */
- bool insertAfter(
- segment_iterator_t segment,
- S32 channel,
- const U8* src,
- S32 len);
-
- /**
- * @brief Count bytes in the buffer array on the specified channel
- *
- * @param channel The channel to count.
- * @param start The start address in the array for counting. You
- * can specify NULL to start at the beginning.
- * @return Returns the number of bytes in the channel after start
- */
- S32 countAfter(S32 channel, U8* start) const;
-
- /**
- * @brief Count all bytes on channel.
- *
- * Helper method which just calls countAfter().
- * @param channel The channel to count.
- * @return Returns the number of bytes in the channel.
- */
- S32 count(S32 channel) const
- {
- return countAfter(channel, NULL);
- }
-
- /**
- * @brief Read bytes in the buffer array on the specified channel
- *
- * You should prefer iterating over segments is possible since
- * this method requires you to allocate large buffers - precisely
- * what this class is trying to prevent. This method will skip
- * any segments which are not on the given channel, so this method
- * would usually be used to read a channel and copy that to a log
- * or a socket buffer or something.
- * @param channel The channel to read.
- * @param start The start address in the array for reading. You
- * can specify NULL to start at the beginning.
- * @param dest The destination of the data read. This must be at
- * least len bytes long.
- * @param len[in,out] <b>in</b> How many bytes to read. <b>out</b> How
- * many bytes were read.
- * @return Returns the address of the last read byte.
- */
- U8* readAfter(S32 channel, U8* start, U8* dest, S32& len) const;
-
- /**
- * @brief Find an address in a buffer array
- *
- * @param channel The channel to seek in.
- * @param start The start address in the array for the seek
- * operation. You can specify NULL to start the seek at the
- * beginning, or pass in npos to start at the end.
- * @param delta How many bytes to seek through the array.
- * @return Returns the address of the last read byte.
- */
- U8* seek(S32 channel, U8* start, S32 delta) const;
- //@}
-
- /* @name Buffer interaction
- */
- //@{
- /**
- * @brief Take the contents of another buffer array
- *
- * This method simply strips the contents out of the source
- * buffery array - segments, buffers, etc, and appends them to
- * this instance. After this operation, the source is empty and
- * ready for reuse.
- * @param source The source buffer
- * @return Returns true if the operation succeeded.
- */
- bool takeContents(LLBufferArray& source);
- //@}
-
- /* @name Segment methods
- */
- //@{
- /**
- * @brief Split a segments so that address is the last address of
- * one segment, and the rest of the original segment becomes
- * another segment on the same channel.
- *
- * After this method call,
- * <code>getLastSegmentAddress(*getSegment(address)) ==
- * address</code> should be true. This call will only create a new
- * segment if the statement above is false before the call. Since
- * you usually call splitAfter() to change a segment property, use
- * getSegment() to perform those operations.
- * @param address The address which will become the last address
- * of the segment it is in.
- * @return Returns an iterator to the segment which contains
- * <code>address</code> which is <code>endSegment()</code> on
- * failure.
- */
- segment_iterator_t splitAfter(U8* address);
-
- /**
- * @brief Get the first segment in the buffer array.
- *
- * @return Returns the segment if there is one.
- */
- segment_iterator_t beginSegment();
-
- /**
- * @brief Get the one-past-the-end segment in the buffer array
- *
- * @return Returns the iterator for an invalid segment location.
- */
- segment_iterator_t endSegment();
-
- /**
- * @brief Get the segment which holds the given address.
- *
- * As opposed to some methods, passing a NULL will result in
- * returning the end segment.
- * @param address An address in the middle of the sought segment.
- * @return Returns the iterator for the segment or endSegment() on
- * failure.
- */
- const_segment_iterator_t getSegment(U8* address) const;
-
- /**
- * @brief Get the segment which holds the given address.
- *
- * As opposed to some methods, passing a NULL will result in
- * returning the end segment.
- * @param address An address in the middle of the sought segment.
- * @return Returns the iterator for the segment or endSegment() on
- * failure.
- */
- segment_iterator_t getSegment(U8* address);
-
- /**
- * @brief Get a segment iterator after address, and a constructed
- * segment to represent the next linear block of memory.
- *
- * This method is a helper by giving you the largest segment
- * possible in the out-value param after the address provided. The
- * iterator will be useful for iteration, while the segment can be
- * used for direct access to memory after address if the return
- * values isnot end. Passing in NULL will return beginSegment()
- * which may be endSegment(). The segment returned will only be
- * zero length if the return value equals end.
- * This is really just a helper method, since all the information
- * returned could be constructed through other methods.
- * @param address An address in the middle of the sought segment.
- * @param segment[out] segment to be used for reading or writing
- * @return Returns an iterator which contains at least segment or
- * endSegment() on failure.
- */
- segment_iterator_t constructSegmentAfter(U8* address, LLSegment& segment);
-
- /**
- * @brief Make a new segment at the end of buffer array
- *
- * This method will attempt to create a new and empty segment of
- * the specified length. The segment created may be shorter than
- * requested.
- * @param channel[in] The channel for the newly created segment.
- * @param length[in] The requested length of the segment.
- * @return Returns an iterator which contains at least segment or
- * endSegment() on failure.
- */
- segment_iterator_t makeSegment(S32 channel, S32 length);
-
- /**
- * @brief Erase the segment if it is in the buffer array.
- *
- * @param iter An iterator referring to the segment to erase.
- * @return Returns true on success.
- */
- bool eraseSegment(const segment_iterator_t& iter);
-
- /**
- * @brief Lock the mutex if it exists
- * This method locks mMutexp to make accessing LLBufferArray thread-safe
- */
- void lock();
-
- /**
- * @brief Unlock the mutex if it exists
- */
- void unlock();
-
- /**
- * @brief Return mMutexp
- */
- LLMutex* getMutex();
-
- /**
- * @brief Set LLBufferArray to be shared across threads or not
- * This method is to create mMutexp if is threaded.
- * @param threaded Indicates this LLBufferArray instance is shared across threads if true.
- */
- void setThreaded(bool threaded);
- //@}
+ typedef std::vector<LLBuffer*> buffer_list_t;
+ typedef buffer_list_t::iterator buffer_iterator_t;
+ typedef buffer_list_t::const_iterator const_buffer_iterator_t;
+ typedef std::list<LLSegment> segment_list_t;
+ typedef segment_list_t::const_iterator const_segment_iterator_t;
+ typedef segment_list_t::iterator segment_iterator_t;
+ enum { npos = 0xffffffff };
+
+ LLBufferArray();
+ ~LLBufferArray();
+
+ /* @name Channel methods
+ */
+ //@{
+ /**
+ * @brief Generate the a channel descriptor which consumes the
+ * output for the channel passed in.
+ */
+ static LLChannelDescriptors makeChannelConsumer(
+ const LLChannelDescriptors& channels);
+
+ /**
+ * @brief Generate the next channel descriptor for this buffer array.
+ *
+ * The channel descriptor interface is how the buffer array
+ * clients can know where to read and write data. Use this
+ * interface to get the 'next' channel set for usage. This is a
+ * bit of a simple hack until it's utility indicates it should be
+ * extended.
+ * @return Returns a valid channel descriptor set for input and output.
+ */
+ LLChannelDescriptors nextChannel();
+ //@}
+
+ /* @name Data methods
+ */
+ //@{
+
+ /**
+ * @brief Return the sum of all allocated bytes.
+ */
+ S32 capacity() const;
+
+ // These methods will be useful once there is any kind of buffer
+ // besides a heap buffer.
+ //bool append(EBufferChannel channel, LLBuffer* data);
+ //bool prepend(EBufferChannel channel, LLBuffer* data);
+ //bool insertAfter(
+ // segment_iterator_t segment,
+ // EBufferChannel channel,
+ // LLBuffer* data);
+
+ /**
+ * @brief Put data on a channel at the end of this buffer array.
+ *
+ * The data is copied from src into the buffer array. At least one
+ * new segment is created and put on the end of the array. This
+ * object will internally allocate new buffers if necessary.
+ * @param channel The channel for this data
+ * @param src The start of memory for the data to be copied
+ * @param len The number of bytes of data to copy
+ * @return Returns true if the method worked.
+ */
+ bool append(S32 channel, const U8* src, S32 len);
+
+ /**
+ * @brief Put data on a channel at the front of this buffer array.
+ *
+ * The data is copied from src into the buffer array. At least one
+ * new segment is created and put in the front of the array. This
+ * object will internally allocate new buffers if necessary.
+ * @param channel The channel for this data
+ * @param src The start of memory for the data to be copied
+ * @param len The number of bytes of data to copy
+ * @return Returns true if the method worked.
+ */
+ bool prepend(S32 channel, const U8* src, S32 len);
+
+ /**
+ * @brief Insert data into a buffer array after a particular segment.
+ *
+ * The data is copied from src into the buffer array. At least one
+ * new segment is created and put in the array. This object will
+ * internally allocate new buffers if necessary.
+ * @param segment The segment in front of the new segments location
+ * @param channel The channel for this data
+ * @param src The start of memory for the data to be copied
+ * @param len The number of bytes of data to copy
+ * @return Returns true if the method worked.
+ */
+ bool insertAfter(
+ segment_iterator_t segment,
+ S32 channel,
+ const U8* src,
+ S32 len);
+
+ /**
+ * @brief Count bytes in the buffer array on the specified channel
+ *
+ * @param channel The channel to count.
+ * @param start The start address in the array for counting. You
+ * can specify NULL to start at the beginning.
+ * @return Returns the number of bytes in the channel after start
+ */
+ S32 countAfter(S32 channel, U8* start) const;
+
+ /**
+ * @brief Count all bytes on channel.
+ *
+ * Helper method which just calls countAfter().
+ * @param channel The channel to count.
+ * @return Returns the number of bytes in the channel.
+ */
+ S32 count(S32 channel) const
+ {
+ return countAfter(channel, NULL);
+ }
+
+ /**
+ * @brief Read bytes in the buffer array on the specified channel
+ *
+ * You should prefer iterating over segments is possible since
+ * this method requires you to allocate large buffers - precisely
+ * what this class is trying to prevent. This method will skip
+ * any segments which are not on the given channel, so this method
+ * would usually be used to read a channel and copy that to a log
+ * or a socket buffer or something.
+ * @param channel The channel to read.
+ * @param start The start address in the array for reading. You
+ * can specify NULL to start at the beginning.
+ * @param dest The destination of the data read. This must be at
+ * least len bytes long.
+ * @param len[in,out] <b>in</b> How many bytes to read. <b>out</b> How
+ * many bytes were read.
+ * @return Returns the address of the last read byte.
+ */
+ U8* readAfter(S32 channel, U8* start, U8* dest, S32& len) const;
+
+ /**
+ * @brief Find an address in a buffer array
+ *
+ * @param channel The channel to seek in.
+ * @param start The start address in the array for the seek
+ * operation. You can specify NULL to start the seek at the
+ * beginning, or pass in npos to start at the end.
+ * @param delta How many bytes to seek through the array.
+ * @return Returns the address of the last read byte.
+ */
+ U8* seek(S32 channel, U8* start, S32 delta) const;
+ //@}
+
+ /* @name Buffer interaction
+ */
+ //@{
+ /**
+ * @brief Take the contents of another buffer array
+ *
+ * This method simply strips the contents out of the source
+ * buffery array - segments, buffers, etc, and appends them to
+ * this instance. After this operation, the source is empty and
+ * ready for reuse.
+ * @param source The source buffer
+ * @return Returns true if the operation succeeded.
+ */
+ bool takeContents(LLBufferArray& source);
+ //@}
+
+ /* @name Segment methods
+ */
+ //@{
+ /**
+ * @brief Split a segments so that address is the last address of
+ * one segment, and the rest of the original segment becomes
+ * another segment on the same channel.
+ *
+ * After this method call,
+ * <code>getLastSegmentAddress(*getSegment(address)) ==
+ * address</code> should be true. This call will only create a new
+ * segment if the statement above is false before the call. Since
+ * you usually call splitAfter() to change a segment property, use
+ * getSegment() to perform those operations.
+ * @param address The address which will become the last address
+ * of the segment it is in.
+ * @return Returns an iterator to the segment which contains
+ * <code>address</code> which is <code>endSegment()</code> on
+ * failure.
+ */
+ segment_iterator_t splitAfter(U8* address);
+
+ /**
+ * @brief Get the first segment in the buffer array.
+ *
+ * @return Returns the segment if there is one.
+ */
+ segment_iterator_t beginSegment();
+
+ /**
+ * @brief Get the one-past-the-end segment in the buffer array
+ *
+ * @return Returns the iterator for an invalid segment location.
+ */
+ segment_iterator_t endSegment();
+
+ /**
+ * @brief Get the segment which holds the given address.
+ *
+ * As opposed to some methods, passing a NULL will result in
+ * returning the end segment.
+ * @param address An address in the middle of the sought segment.
+ * @return Returns the iterator for the segment or endSegment() on
+ * failure.
+ */
+ const_segment_iterator_t getSegment(U8* address) const;
+
+ /**
+ * @brief Get the segment which holds the given address.
+ *
+ * As opposed to some methods, passing a NULL will result in
+ * returning the end segment.
+ * @param address An address in the middle of the sought segment.
+ * @return Returns the iterator for the segment or endSegment() on
+ * failure.
+ */
+ segment_iterator_t getSegment(U8* address);
+
+ /**
+ * @brief Get a segment iterator after address, and a constructed
+ * segment to represent the next linear block of memory.
+ *
+ * This method is a helper by giving you the largest segment
+ * possible in the out-value param after the address provided. The
+ * iterator will be useful for iteration, while the segment can be
+ * used for direct access to memory after address if the return
+ * values isnot end. Passing in NULL will return beginSegment()
+ * which may be endSegment(). The segment returned will only be
+ * zero length if the return value equals end.
+ * This is really just a helper method, since all the information
+ * returned could be constructed through other methods.
+ * @param address An address in the middle of the sought segment.
+ * @param segment[out] segment to be used for reading or writing
+ * @return Returns an iterator which contains at least segment or
+ * endSegment() on failure.
+ */
+ segment_iterator_t constructSegmentAfter(U8* address, LLSegment& segment);
+
+ /**
+ * @brief Make a new segment at the end of buffer array
+ *
+ * This method will attempt to create a new and empty segment of
+ * the specified length. The segment created may be shorter than
+ * requested.
+ * @param channel[in] The channel for the newly created segment.
+ * @param length[in] The requested length of the segment.
+ * @return Returns an iterator which contains at least segment or
+ * endSegment() on failure.
+ */
+ segment_iterator_t makeSegment(S32 channel, S32 length);
+
+ /**
+ * @brief Erase the segment if it is in the buffer array.
+ *
+ * @param iter An iterator referring to the segment to erase.
+ * @return Returns true on success.
+ */
+ bool eraseSegment(const segment_iterator_t& iter);
+
+ /**
+ * @brief Lock the mutex if it exists
+ * This method locks mMutexp to make accessing LLBufferArray thread-safe
+ */
+ void lock();
+
+ /**
+ * @brief Unlock the mutex if it exists
+ */
+ void unlock();
+
+ /**
+ * @brief Return mMutexp
+ */
+ LLMutex* getMutex();
+
+ /**
+ * @brief Set LLBufferArray to be shared across threads or not
+ * This method is to create mMutexp if is threaded.
+ * @param threaded Indicates this LLBufferArray instance is shared across threads if true.
+ */
+ void setThreaded(bool threaded);
+ //@}
protected:
- /**
- * @brief Optimally put data in buffers, and reutrn segments.
- *
- * This is an internal function used to create buffers as
- * necessary, and sequence the segments appropriately for the
- * various ways to copy data from src into this.
- * If this method fails, it may actually leak some space inside
- * buffers, but I am not too worried about the slim possibility
- * that we may have some 'dead' space which will be recovered when
- * the buffer (which we will not lose) is deleted. Addressing this
- * weakness will make the buffers almost as complex as a general
- * memory management system.
- * @param channel The channel for this data
- * @param src The start of memory for the data to be copied
- * @param len The number of bytes of data to copy
- * @param segments Out-value for the segments created.
- * @return Returns true if the method worked.
- */
- bool copyIntoBuffers(
- S32 channel,
- const U8* src,
- S32 len,
- std::vector<LLSegment>& segments);
+ /**
+ * @brief Optimally put data in buffers, and reutrn segments.
+ *
+ * This is an internal function used to create buffers as
+ * necessary, and sequence the segments appropriately for the
+ * various ways to copy data from src into this.
+ * If this method fails, it may actually leak some space inside
+ * buffers, but I am not too worried about the slim possibility
+ * that we may have some 'dead' space which will be recovered when
+ * the buffer (which we will not lose) is deleted. Addressing this
+ * weakness will make the buffers almost as complex as a general
+ * memory management system.
+ * @param channel The channel for this data
+ * @param src The start of memory for the data to be copied
+ * @param len The number of bytes of data to copy
+ * @param segments Out-value for the segments created.
+ * @return Returns true if the method worked.
+ */
+ bool copyIntoBuffers(
+ S32 channel,
+ const U8* src,
+ S32 len,
+ std::vector<LLSegment>& segments);
protected:
- S32 mNextBaseChannel;
- buffer_list_t mBuffers;
- segment_list_t mSegments;
- LLMutex* mMutexp;
+ S32 mNextBaseChannel;
+ buffer_list_t mBuffers;
+ segment_list_t mSegments;
+ LLMutex* mMutexp;
};
#endif // LL_LLBUFFER_H