llbuffer.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:19k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llbuffer.h
  3.  * @author Phoenix
  4.  * @date 2005-09-20
  5.  * @brief Declaration of buffer and buffer arrays primarily used in I/O.
  6.  *
  7.  * $LicenseInfo:firstyear=2005&license=viewergpl$
  8.  * 
  9.  * Copyright (c) 2005-2010, Linden Research, Inc.
  10.  * 
  11.  * Second Life Viewer Source Code
  12.  * The source code in this file ("Source Code") is provided by Linden Lab
  13.  * to you under the terms of the GNU General Public License, version 2.0
  14.  * ("GPL"), unless you have obtained a separate licensing agreement
  15.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  16.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18.  * 
  19.  * There are special exceptions to the terms and conditions of the GPL as
  20.  * it is applied to this Source Code. View the full text of the exception
  21.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  22.  * online at
  23.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24.  * 
  25.  * By copying, modifying or distributing this software, you acknowledge
  26.  * that you have read and understood your obligations described above,
  27.  * and agree to abide by those obligations.
  28.  * 
  29.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31.  * COMPLETENESS OR PERFORMANCE.
  32.  * $/LicenseInfo$
  33.  */
  34. #ifndef LL_LLBUFFER_H
  35. #define LL_LLBUFFER_H
  36. /**
  37.  * Declaration of classes used for minimizing calls to new[],
  38.  * memcpy(), and delete[]. Typically, you would create an LLBufferArray,
  39.  * feed it data, modify and add segments as you process it, and feed
  40.  * it to a sink.
  41.  */
  42. #include <list>
  43. #include <vector>
  44. /** 
  45.  * @class LLChannelDescriptors
  46.  * @brief A way simple interface to accesss channels inside a buffer
  47.  */
  48. class LLChannelDescriptors
  49. {
  50. public:
  51. // enumeration for segmenting the channel information
  52. enum { E_CHANNEL_COUNT = 3 };
  53. LLChannelDescriptors() : mBaseChannel(0) {}
  54. explicit LLChannelDescriptors(S32 base) : mBaseChannel(base) {}
  55. S32 in() const { return mBaseChannel; }
  56. S32 out() const { return mBaseChannel + 1; }
  57. //S32 err() const { return mBaseChannel + 2; }
  58. protected:
  59. S32 mBaseChannel;
  60. };
  61. /** 
  62.  * @class LLSegment
  63.  * @brief A segment is a single, contiguous chunk of memory in a buffer
  64.  *
  65.  * Each segment represents a contiguous addressable piece of memory
  66.  * which is located inside a buffer. The segment is not responsible
  67.  * for allocation or deallcoation of the data. Each segment is a light
  68.  * weight object, and simple enough to copy around, use, and generate
  69.  * as necessary.
  70.  * This is the preferred interface for working with memory blocks,
  71.  * since it is the only way to safely, inexpensively, and directly
  72.  * access linear blocks of memory. 
  73.  */
  74. class LLSegment
  75. {
  76. public:
  77. LLSegment();
  78. LLSegment(S32 channel, U8* data, S32 data_len);
  79. ~LLSegment();
  80. /**
  81.  * @brief Check if this segment is on the given channel.
  82.  *
  83.  */
  84. bool isOnChannel(S32 channel) const;
  85. /**
  86.  * @brief Get the channel
  87.  */
  88. S32 getChannel() const;
  89. /**
  90.  * @brief Set the channel
  91.  */
  92. void setChannel(S32 channel);
  93. /** 
  94.  * @brief Return a raw pointer to the current data set.
  95.  *
  96.  * The pointer returned can be used for reading or even adjustment
  97.  * if you are a bit crazy up to size() bytes into memory.
  98.  * @return A potentially NULL pointer to the raw buffer data
  99.  */
  100. U8* data() const;
  101. /** 
  102.  * @brief Return the size of the segment
  103.  */
  104. S32 size() const;
  105. /** 
  106.  * @brief Check if two segments are the same.
  107.  *
  108.  * Two segments are considered equal if they are on the same
  109.  * channel and cover the exact same address range.
  110.  * @param rhs the segment to compare with this segment.
  111.  * @return Returns true if they are equal.
  112.  */
  113. bool operator==(const LLSegment& rhs) const;
  114. protected:
  115. S32 mChannel;
  116. U8* mData;
  117. S32 mSize;
  118. };
  119. /** 
  120.  * @class LLBuffer
  121.  * @brief Abstract base class for buffers
  122.  *
  123.  * This class declares the interface necessary for buffer arrays. A
  124.  * buffer is not necessarily a single contiguous memory chunk, so
  125.  * please do not circumvent the segment API.
  126.  */
  127. class LLBuffer
  128. {
  129. public:
  130. /** 
  131.  * @brief The buffer base class should have no responsibilities
  132.  * other than an interface.
  133.  */ 
  134. virtual ~LLBuffer() {}
  135. /** 
  136.  * @brief Generate a segment for this buffer.
  137.  *
  138.  * The segment returned is always contiguous memory. This call can
  139.  * fail if no contiguous memory is available, eg, offset is past
  140.  * the end. The segment returned may be smaller than the requested
  141.  * size. The segment will never be larger than the requested size.
  142.  * @param channel The channel for the segment.
  143.  * @param offset The offset from zero in the buffer.
  144.  * @param size The requested size of the segment.
  145.  * @param segment[out] The out-value from the operation
  146.  * @return Returns true if a segment was found.
  147.  */
  148. virtual bool createSegment(S32 channel, S32 size, LLSegment& segment) = 0;
  149. /** 
  150.  * @brief Reclaim a segment from this buffer. 
  151.  *
  152.  * This method is called on a buffer object when a caller is done
  153.  * with a contiguous segment of memory inside this buffer. Since
  154.  * segments can be cut arbitrarily outside of the control of the
  155.  * buffer, this segment may not match any segment returned from
  156.  * <code>createSegment()</code>.  
  157.  * @param segment The contiguous buffer segment to reclaim.
  158.  * @return Returns true if the call was successful.
  159.  */
  160. virtual bool reclaimSegment(const LLSegment& segment) = 0;
  161. /** 
  162.  * @brief Test if a segment is inside this buffer.
  163.  *
  164.  * @param segment The contiguous buffer segment to test.
  165.  * @return Returns true if the segment is in the bufffer.
  166.  */
  167. virtual bool containsSegment(const LLSegment& segment) const = 0;
  168. /** 
  169.  * @brief Return the current number of bytes allocated.
  170.  *
  171.  * This was implemented as a debugging tool, and it is not
  172.  * necessarily a good idea to use it for anything else.
  173.  */
  174. virtual S32 capacity() const = 0;
  175. };
  176. /** 
  177.  * @class LLHeapBuffer
  178.  * @brief A large contiguous buffer allocated on the heap with new[].
  179.  *
  180.  * This class is a simple buffer implementation which allocates chunks
  181.  * off the heap. Once a buffer is constructed, it's buffer has a fixed
  182.  * length.
  183.  */
  184. class LLHeapBuffer : public LLBuffer
  185. {
  186. public:
  187. /** 
  188.  * @brief Construct a heap buffer with a reasonable default size.
  189.  */
  190. LLHeapBuffer();
  191. /** 
  192.  * @brief Construct a heap buffer with a specified size.
  193.  *
  194.  * @param size The minimum size of the buffer.
  195.  */
  196. explicit LLHeapBuffer(S32 size);
  197. /** 
  198.  * @brief Construct a heap buffer of minimum size len, and copy from src.
  199.  *
  200.  * @param src The source of the data to be copied.
  201.  * @param len The minimum size of the buffer.
  202.  */
  203. LLHeapBuffer(const U8* src, S32 len);
  204. /** 
  205.  * @brief Simple destruction.
  206.  */
  207. virtual ~LLHeapBuffer();
  208. /** 
  209.  * @brief Get the number of bytes left in the buffer.
  210.  *
  211.  * Note that this is not a virtual function, and only available in
  212.  * the LLHeapBuffer as a debugging aid.
  213.  * @return Returns the number of bytes left.
  214.  */
  215. S32 bytesLeft() const;
  216. /** 
  217.  * @brief Generate a segment for this buffer.
  218.  *
  219.  * The segment returned is always contiguous memory. This call can
  220.  * fail if no contiguous memory is available, eg, offset is past
  221.  * the end. The segment returned may be smaller than the requested
  222.  * size. It is up to the caller to delete the segment returned.
  223.  * @param channel The channel for the segment.
  224.  * @param offset The offset from zero in the buffer
  225.  * @param size The requested size of the segment
  226.  * @param segment[out] The out-value from the operation
  227.  * @return Returns true if a segment was found.
  228.  */
  229. virtual bool createSegment(S32 channel, S32 size, LLSegment& segment);
  230. /** 
  231.  * @brief reclaim a segment from this buffer. 
  232.  *
  233.  * This method is called on a buffer object when a caller is done
  234.  * with a contiguous segment of memory inside this buffer. Since
  235.  * segments can be cut arbitrarily outside of the control of the
  236.  * buffer, this segment may not match any segment returned from
  237.  * <code>createSegment()</code>.  
  238.  * This call will fail if the segment passed in is note completely
  239.  * inside the buffer, eg, if the segment starts before this buffer
  240.  * in memory or ends after it.
  241.  * @param segment The contiguous buffer segment to reclaim.
  242.  * @return Returns true if the call was successful.
  243.  */
  244. virtual bool reclaimSegment(const LLSegment& segment);
  245. /** 
  246.  * @brief Test if a segment is inside this buffer.
  247.  *
  248.  * @param segment The contiguous buffer segment to test.
  249.  * @return Returns true if the segment is in the bufffer.
  250.  */
  251. virtual bool containsSegment(const LLSegment& segment) const;
  252. /** 
  253.  * @brief Return the current number of bytes allocated.
  254.  */
  255. virtual S32 capacity() const { return mSize; }
  256. protected:
  257. U8* mBuffer;
  258. S32 mSize;
  259. U8* mNextFree;
  260. S32 mReclaimedBytes;
  261. private:
  262. /** 
  263.  * @brief Helper method to allocate a buffer and correctly set
  264.  * intertnal state of this buffer.
  265.  */ 
  266. void allocate(S32 size);
  267. };
  268. /** 
  269.  * @class LLBufferArray
  270.  * @brief Class to represent scattered memory buffers and in-order segments
  271.  * of that buffered data.
  272.  *
  273.  * *NOTE: This class needs to have an iovec interface
  274.  */
  275. class LLBufferArray
  276. {
  277. public:
  278. typedef std::vector<LLBuffer*> buffer_list_t;
  279. typedef buffer_list_t::iterator buffer_iterator_t;
  280. typedef buffer_list_t::const_iterator const_buffer_iterator_t;
  281. typedef std::list<LLSegment> segment_list_t;
  282. typedef segment_list_t::const_iterator const_segment_iterator_t;
  283. typedef segment_list_t::iterator segment_iterator_t;
  284. enum { npos = 0xffffffff };
  285. LLBufferArray();
  286. ~LLBufferArray();
  287. /* @name Channel methods
  288.  */
  289. //@{
  290. /** 
  291.  * @brief Generate the a channel descriptor which consumes the
  292.  * output for the channel passed in.
  293.  */
  294. static LLChannelDescriptors makeChannelConsumer(
  295. const LLChannelDescriptors& channels);
  296. /** 
  297.  * @brief Generate the next channel descriptor for this buffer array.
  298.  * 
  299.  * The channel descriptor interface is how the buffer array
  300.  * clients can know where to read and write data. Use this
  301.  * interface to get the 'next' channel set for usage. This is a
  302.  * bit of a simple hack until it's utility indicates it should be
  303.  * extended.
  304.  * @return Returns a valid channel descriptor set for input and output.
  305.  */
  306. LLChannelDescriptors nextChannel();
  307. //@}
  308. /* @name Data methods
  309.  */
  310. //@{
  311. /** 
  312.  * @brief Return the sum of all allocated bytes.
  313.  */
  314. S32 capacity() const;
  315. // These methods will be useful once there is any kind of buffer
  316. // besides a heap buffer.
  317. //bool append(EBufferChannel channel, LLBuffer* data);
  318. //bool prepend(EBufferChannel channel, LLBuffer* data);
  319. //bool insertAfter(
  320. // segment_iterator_t segment,
  321. // EBufferChannel channel,
  322. // LLBuffer* data);
  323. /** 
  324.  * @brief Put data on a channel at the end of this buffer array.
  325.  *
  326.  * The data is copied from src into the buffer array. At least one
  327.  * new segment is created and put on the end of the array. This
  328.  * object will internally allocate new buffers if necessary.
  329.  * @param channel The channel for this data
  330.  * @param src The start of memory for the data to be copied
  331.  * @param len The number of bytes of data to copy
  332.  * @return Returns true if the method worked.
  333.  */
  334. bool append(S32 channel, const U8* src, S32 len);
  335. /** 
  336.  * @brief Put data on a channel at the front of this buffer array.
  337.  *
  338.  * The data is copied from src into the buffer array. At least one
  339.  * new segment is created and put in the front of the array. This
  340.  * object will internally allocate new buffers if necessary.
  341.  * @param channel The channel for this data
  342.  * @param src The start of memory for the data to be copied
  343.  * @param len The number of bytes of data to copy
  344.  * @return Returns true if the method worked.
  345.  */
  346. bool prepend(S32 channel, const U8* src, S32 len);
  347. /** 
  348.  * @brief Insert data into a buffer array after a particular segment.
  349.  *
  350.  * The data is copied from src into the buffer array. At least one
  351.  * new segment is created and put in the array. This object will
  352.  * internally allocate new buffers if necessary.
  353.  * @param segment The segment in front of the new segments location
  354.  * @param channel The channel for this data
  355.  * @param src The start of memory for the data to be copied
  356.  * @param len The number of bytes of data to copy
  357.  * @return Returns true if the method worked.
  358.  */
  359. bool insertAfter(
  360. segment_iterator_t segment,
  361. S32 channel,
  362. const U8* src,
  363. S32 len);
  364. /** 
  365.  * @brief Count bytes in the buffer array on the specified channel
  366.  *
  367.  * @param channel The channel to count.
  368.  * @param start The start address in the array for counting. You
  369.  * can specify NULL to start at the beginning.
  370.  * @return Returns the number of bytes in the channel after start
  371.  */
  372. S32 countAfter(S32 channel, U8* start) const;
  373. /** 
  374.  * @brief Count all bytes on channel.
  375.  *
  376.  * Helper method which just calls countAfter().
  377.  * @param channel The channel to count.
  378.  * @return Returns the number of bytes in the channel.
  379.  */
  380. S32 count(S32 channel) const
  381. {
  382. return countAfter(channel, NULL);
  383. }
  384. /** 
  385.  * @brief Read bytes in the buffer array on the specified channel
  386.  *
  387.  * You should prefer iterating over segments is possible since
  388.  * this method requires you to allocate large buffers - precisely
  389.  * what this class is trying to prevent.  This method will skip
  390.  * any segments which are not on the given channel, so this method
  391.  * would usually be used to read a channel and copy that to a log
  392.  * or a socket buffer or something.
  393.  * @param channel The channel to read.
  394.  * @param start The start address in the array for reading. You
  395.  * can specify NULL to start at the beginning.
  396.  * @param dest The destination of the data read. This must be at
  397.  * least len bytes long.
  398.  * @param len[in,out] <b>in</b> How many bytes to read. <b>out</b> How 
  399.  * many bytes were read.
  400.  * @return Returns the address of the last read byte.
  401.  */
  402. U8* readAfter(S32 channel, U8* start, U8* dest, S32& len) const;
  403.  
  404. /** 
  405.  * @brief Find an address in a buffer array
  406.  *
  407.  * @param channel The channel to seek in.
  408.  * @param start The start address in the array for the seek
  409.  * operation. You can specify NULL to start the seek at the
  410.  * beginning, or pass in npos to start at the end.
  411.  * @param delta How many bytes to seek through the array.
  412.  * @return Returns the address of the last read byte.
  413.  */
  414. U8* seek(S32 channel, U8* start, S32 delta) const;
  415. //@}
  416. /* @name Buffer interaction
  417.  */
  418. //@{
  419. /** 
  420.  * @brief Take the contents of another buffer array
  421.  *
  422.  * This method simply strips the contents out of the source
  423.  * buffery array - segments, buffers, etc, and appends them to
  424.  * this instance. After this operation, the source is empty and
  425.  * ready for reuse.
  426.  * @param source The source buffer
  427.  * @return Returns true if the operation succeeded.
  428.  */
  429. bool takeContents(LLBufferArray& source);
  430. //@}
  431. /* @name Segment methods
  432.  */
  433. //@{
  434. /** 
  435.  * @brief Split a segments so that address is the last address of
  436.  * one segment, and the rest of the original segment becomes
  437.  * another segment on the same channel.
  438.  *
  439.  * After this method call,
  440.  * <code>getLastSegmentAddress(*getSegment(address)) ==
  441.  * address</code> should be true. This call will only create a new
  442.  * segment if the statement above is false before the call. Since
  443.  * you usually call splitAfter() to change a segment property, use
  444.  * getSegment() to perform those operations.
  445.  * @param address The address which will become the last address
  446.  * of the segment it is in.
  447.  * @return Returns an iterator to the segment which contains
  448.  * <code>address</code> which is <code>endSegment()</code> on
  449.  * failure.
  450.  */
  451. segment_iterator_t splitAfter(U8* address);
  452. /** 
  453.  * @brief Get the first segment in the buffer array.
  454.  *
  455.  * @return Returns the segment if there is one.
  456.  */
  457. segment_iterator_t beginSegment();
  458. /** 
  459.  * @brief Get the one-past-the-end segment in the buffer array
  460.  *
  461.  * @return Returns the iterator for an invalid segment location.
  462.  */
  463. segment_iterator_t endSegment();
  464. /** 
  465.  * @brief Get the segment which holds the given address.
  466.  *
  467.  * As opposed to some methods, passing a NULL will result in
  468.  * returning the end segment.
  469.  * @param address An address in the middle of the sought segment.
  470.  * @return Returns the iterator for the segment or endSegment() on
  471.  * failure.
  472.  */
  473. const_segment_iterator_t getSegment(U8* address) const;
  474. /** 
  475.  * @brief Get the segment which holds the given address.
  476.  *
  477.  * As opposed to some methods, passing a NULL will result in
  478.  * returning the end segment.
  479.  * @param address An address in the middle of the sought segment.
  480.  * @return Returns the iterator for the segment or endSegment() on
  481.  * failure.
  482.  */
  483. segment_iterator_t getSegment(U8* address);
  484. /** 
  485.  * @brief Get a segment iterator after address, and a constructed
  486.  * segment to represent the next linear block of memory.
  487.  *
  488.  * This method is a helper by giving you the largest segment
  489.  * possible in the out-value param after the address provided. The
  490.  * iterator will be useful for iteration, while the segment can be
  491.  * used for direct access to memory after address if the return
  492.  * values isnot end. Passing in NULL will return beginSegment()
  493.  * which may be endSegment(). The segment returned will only be
  494.  * zero length if the return value equals end.
  495.  * This is really just a helper method, since all the information
  496.  * returned could be constructed through other methods.
  497.  * @param address An address in the middle of the sought segment.
  498.  * @param segment[out] segment to be used for reading or writing
  499.  * @return Returns an iterator which contains at least segment or
  500.  * endSegment() on failure.
  501.  */
  502. segment_iterator_t constructSegmentAfter(U8* address, LLSegment& segment);
  503. /** 
  504.  * @brief Make a new segment at the end of buffer array
  505.  *
  506.  * This method will attempt to create a new and empty segment of
  507.  * the specified length. The segment created may be shorter than
  508.  * requested.
  509.  * @param channel[in] The channel for the newly created segment.
  510.  * @param length[in] The requested length of the segment.
  511.  * @return Returns an iterator which contains at least segment or
  512.  * endSegment() on failure.
  513.  */
  514. segment_iterator_t makeSegment(S32 channel, S32 length);
  515. /** 
  516.  * @brief Erase the segment if it is in the buffer array.
  517.  *
  518.  * @param iter An iterator referring to the segment to erase.
  519.  * @return Returns true on success.
  520.  */
  521. bool eraseSegment(const segment_iterator_t& iter);
  522. //@}
  523. protected:
  524. /** 
  525.  * @brief Optimally put data in buffers, and reutrn segments.
  526.  *
  527.  * This is an internal function used to create buffers as
  528.  * necessary, and sequence the segments appropriately for the
  529.  * various ways to copy data from src into this. 
  530.  * If this method fails, it may actually leak some space inside
  531.  * buffers, but I am not too worried about the slim possibility
  532.  * that we may have some 'dead' space which will be recovered when
  533.  * the buffer (which we will not lose) is deleted. Addressing this
  534.  * weakness will make the buffers almost as complex as a general
  535.  * memory management system.
  536.  * @param channel The channel for this data
  537.  * @param src The start of memory for the data to be copied
  538.  * @param len The number of bytes of data to copy
  539.  * @param segments Out-value for the segments created.
  540.  * @return Returns true if the method worked.
  541.  */
  542. bool copyIntoBuffers(
  543. S32 channel,
  544. const U8* src,
  545. S32 len,
  546. std::vector<LLSegment>& segments);
  547. protected:
  548. S32 mNextBaseChannel;
  549. buffer_list_t mBuffers;
  550. segment_list_t mSegments;
  551. };
  552. #endif // LL_LLBUFFER_H