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