00001 /* -*- Mode: C++ -*- 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * A generic buffering API. 00006 * Please declare specializations in a separate header file, 00007 * See "wvbuf.h". 00008 */ 00009 #ifndef __WVBUFFERBASE_H 00010 #define __WVBUFFERBASE_H 00011 00012 #include "wvbufstore.h" 00013 00014 template<class T> 00015 class WvBufBase; 00016 00017 /** 00018 * An abstract generic buffer template. 00019 * Buffers are simple data queues designed to ease the construction of 00020 * functions that must generate, consume, or transform large amount of 00021 * data in pipeline fashion. Concrete buffer subclases define the actual 00022 * storage mechanism and queuing machinery. In addition they may provide 00023 * additional functionality for accomplishing particular tasks. 00024 * 00025 * The base component is split into two parts, WvBufBaseCommonImpl 00026 * that defines the common API for all buffer types, and WvBufBase 00027 * that allows specializations to be defined to add functionality 00028 * to the base type. When passing around buffer objects, you should 00029 * use the WvBufBase<T> type rather than WvBufBaseCommonImpl<T>. 00030 * 00031 * See WvBufBase<T> 00032 * "T" is the type of object to store, must be a primitive or a struct 00033 * without special initialization, copy, or assignment semantics 00034 */ 00035 template<class T> 00036 class WvBufBaseCommonImpl 00037 { 00038 protected: 00039 typedef T Elem; 00040 typedef WvBufBase<T> Buffer; 00041 00042 WvBufStore *store; 00043 00044 // discourage copying 00045 explicit WvBufBaseCommonImpl( 00046 const WvBufBaseCommonImpl &other) { } 00047 00048 protected: 00049 /** 00050 * Initializes the buffer. 00051 * 00052 * Note: Does not take ownership of the storage object. 00053 * 00054 * 00055 * "store" is the low-level storage object 00056 */ 00057 explicit WvBufBaseCommonImpl(WvBufStore *store) : 00058 store(store) { } 00059 00060 public: 00061 /** Destroys the buffer. */ 00062 virtual ~WvBufBaseCommonImpl() { } 00063 00064 /** 00065 * Returns a pointer to the underlying storage class object. 00066 * 00067 * Returns: the low-level storage class object pointer, non-null 00068 */ 00069 WvBufStore *getstore() 00070 { 00071 return store; 00072 } 00073 00074 /*** Buffer Reading ***/ 00075 00076 /** 00077 * Returns true if the buffer supports reading. 00078 * 00079 * Returns: true if reading is supported 00080 */ 00081 bool isreadable() const 00082 { 00083 return store->isreadable(); 00084 } 00085 00086 /** 00087 * Returns the number of elements in the buffer currently 00088 * available for reading. 00089 * 00090 * This function could also be called gettable(). 00091 */ 00092 size_t used() const 00093 { 00094 return store->used() / sizeof(Elem); 00095 } 00096 00097 /** 00098 * Reads exactly the specified number of elements and returns 00099 * a pointer to a storage location owned by the buffer. 00100 * 00101 * The pointer is only valid until the next non-const buffer 00102 * member is called. eg. alloc(size_t) 00103 * 00104 * If count == 0, a NULL pointer may be returned. 00105 * 00106 * It is an error for count to be greater than used(). 00107 * 00108 * For maximum efficiency, call this function multiple times 00109 * with count no greater than optgettable() each time. 00110 * 00111 * After this operation, at least count elements may be ungotten. 00112 */ 00113 const T *get(size_t count) 00114 { 00115 if (count > used()) 00116 return NULL; 00117 00118 return static_cast<const T*>( 00119 store->get(count * sizeof(Elem))); 00120 } 00121 00122 /** 00123 * Skips exactly the specified number of elements. 00124 * 00125 * This is equivalent to invoking get(size_t) with the count 00126 * and discarding the result, but may be faster for certain 00127 * types of buffers. As with get(size_t), the call may be 00128 * followed up by an unget(size_t). 00129 * 00130 * 00131 * "count" is the number of elements 00132 */ 00133 void skip(size_t count) 00134 { 00135 store->skip(count * sizeof(Elem)); 00136 } 00137 00138 /** 00139 * Returns the optimal maximum number of elements in the 00140 * buffer currently available for reading without incurring 00141 * significant overhead. 00142 * 00143 * Invariants: 00144 * 00145 * - optgettable() <= used() 00146 * - optgettable() != 0 if used() != 0 00147 * 00148 * 00149 * Returns: the number of elements 00150 */ 00151 size_t optgettable() const 00152 { 00153 size_t avail = store->optgettable(); 00154 size_t elems = avail / sizeof(Elem); 00155 if (elems != 0) return elems; 00156 return avail != 0 && store->used() >= sizeof(Elem) ? 1 : 0; 00157 } 00158 00159 /** 00160 * Ungets exactly the specified number of elements by returning 00161 * them to the buffer for subsequent reads. 00162 * 00163 * This operation may always be safely performed with count 00164 * less than or equal to that specified in the last get(size_t) 00165 * if no non-const buffer members have been called since then. 00166 * 00167 * If count == 0, nothing happens. 00168 * 00169 * It is an error for count to be greater than ungettable(). 00170 * 00171 * 00172 * "count" is the number of elements 00173 */ 00174 void unget(size_t count) 00175 { 00176 store->unget(count * sizeof(Elem)); 00177 } 00178 00179 /** 00180 * Returns the maximum number of elements that may be ungotten 00181 * at this time. 00182 * 00183 * Returns: the number of elements 00184 */ 00185 size_t ungettable() const 00186 { 00187 return store->ungettable() / sizeof(Elem); 00188 } 00189 00190 /** 00191 * Returns a const pointer into the buffer at the specified 00192 * offset to the specified number of elements without actually 00193 * adjusting the current get() index. 00194 * 00195 * The pointer is only valid until the next non-const buffer 00196 * member is called. eg. alloc(size_t) 00197 * 00198 * If count == 0, a NULL pointer may be returned. 00199 * 00200 * If offset is greater than zero, then elements will be returned 00201 * beginning with the with the offset'th element that would be 00202 * returned by get(size_t). 00203 * 00204 * If offset equals zero, then elements will be returned beginning 00205 * with the next one available for get(size_t). 00206 * 00207 * If offset is less than zero, then elements will be returned 00208 * beginning with the first one that would be returned on a 00209 * get(size_t) following an unget(-offset). 00210 * 00211 * It is an error for count to be greater than peekable(offset). 00212 * 00213 * For maximum efficiency, call this function multiple times 00214 * with count no greater than that returned by optpeekable(size_t) 00215 * at incremental offsets. 00216 * 00217 * 00218 * "offset" is the buffer offset 00219 * "count" is the number of elements 00220 * Returns: the element storage pointer 00221 */ 00222 const T *peek(int offset, size_t count) 00223 { 00224 return static_cast<const T*>(store->peek( 00225 offset * sizeof(Elem), count * sizeof(Elem))); 00226 } 00227 00228 size_t peekable(int offset) 00229 { 00230 return store->peekable(offset * sizeof(Elem)) / sizeof(Elem); 00231 } 00232 00233 size_t optpeekable(int offset) 00234 { 00235 offset *= sizeof(Elem); 00236 size_t avail = store->optpeekable(offset); 00237 size_t elems = avail / sizeof(Elem); 00238 if (elems != 0) return elems; 00239 return avail != 0 && 00240 store->peekable(offset) >= sizeof(Elem) ? 1 : 0; 00241 } 00242 00243 /** 00244 * Clears the buffer. 00245 * 00246 * For many types of buffers, calling zap() will increased the 00247 * amount of free space available for writing (see below) by 00248 * an amount greater than used(). Hence it is wise to zap() 00249 * a buffer just before writing to it to maximize free space. 00250 * 00251 * After this operation, used() == 0, and often ungettable() == 0. 00252 * 00253 */ 00254 void zap() 00255 { 00256 store->zap(); 00257 } 00258 00259 /** 00260 * Reads the next element from the buffer. 00261 * 00262 * It is an error to invoke this method if used() == 0. 00263 * 00264 * After this operation, at least 1 element may be ungotten. 00265 * 00266 * 00267 * Returns: the element 00268 */ 00269 T get() 00270 { 00271 return *get(1); 00272 } 00273 00274 /** 00275 * Returns the element at the specified offset in the buffer. 00276 * 00277 * It is an error to invoke this method if used() == 0. 00278 * 00279 * 00280 * "offset" is the offset, default 0 00281 * Returns: the element 00282 */ 00283 T peek(int offset = 0) 00284 { 00285 return *peek(offset * sizeof(Elem), sizeof(Elem)); 00286 } 00287 00288 /** 00289 * Efficiently copies the specified number of elements from the 00290 * buffer to the specified UNINITIALIZED storage location 00291 * and removes the elements from the buffer. 00292 * 00293 * It is an error for count to be greater than used(). 00294 * 00295 * For maximum efficiency, choose as large a count as possible. 00296 * 00297 * The pointer buf may be NULL only if count == 0. 00298 * 00299 * After this operation, an indeterminate number of elements 00300 * may be ungotten. 00301 * 00302 * 00303 * "buf" is the buffer that will receive the elements 00304 * "count" is the number of elements 00305 */ 00306 void move(T *buf, size_t count) 00307 { 00308 store->move(buf, count * sizeof(Elem)); 00309 } 00310 00311 /** 00312 * Efficiently copies the specified number of elements from the 00313 * buffer to the specified UNINITIALIZED storage location 00314 * but does not remove the elements from the buffer. 00315 * 00316 * It is an error for count to be greater than peekable(offset). 00317 * 00318 * For maximum efficiency, choose as large a count as possible. 00319 * 00320 * The pointer buf may be NULL only if count == 0. 00321 * 00322 * 00323 * "buf" is the buffer that will receive the elements 00324 * "offset" is the buffer offset 00325 * "count" is the number of elements 00326 */ 00327 void copy(T *buf, int offset, size_t count) 00328 { 00329 store->copy(buf, offset * sizeof(Elem), count * sizeof(Elem)); 00330 } 00331 00332 /*** Buffer Writing ***/ 00333 00334 /** 00335 * Returns true if the buffer supports writing. 00336 * 00337 * Returns: true if writing is supported 00338 */ 00339 bool iswritable() const 00340 { 00341 return true; 00342 } 00343 00344 /** 00345 * Returns the number of elements that the buffer can currently 00346 * accept for writing. 00347 * 00348 * Returns: the number of elements 00349 */ 00350 size_t free() const 00351 { 00352 return store->free() / sizeof(Elem); 00353 } 00354 00355 /** 00356 * Allocates exactly the specified number of elements and returns 00357 * a pointer to an UNINITIALIZED storage location owned by the 00358 * buffer. 00359 * 00360 * The pointer is only valid until the next non-const buffer 00361 * member is called. eg. alloc(size_t) 00362 * 00363 * If count == 0, a NULL pointer may be returned. 00364 * 00365 * It is an error for count to be greater than free(). 00366 * 00367 * For best results, call this function multiple times with 00368 * count no greater than optallocable() each time. 00369 * 00370 * After this operation, at least count elements may be unallocated. 00371 * 00372 * 00373 * "count" is the number of elements 00374 * Returns: the element storage pointer 00375 */ 00376 T *alloc(size_t count) 00377 { 00378 return static_cast<T*>(store->alloc(count * sizeof(Elem))); 00379 } 00380 00381 /** 00382 * Returns the optimal maximum number of elements that the 00383 * buffer can currently accept for writing without incurring 00384 * significant overhead. 00385 * 00386 * Invariants: 00387 * 00388 * - optallocable() <= free() 00389 * - optallocable() != 0 if free() != 0 00390 * 00391 * 00392 * Returns: the number of elements 00393 */ 00394 size_t optallocable() const 00395 { 00396 size_t avail = store->optallocable(); 00397 size_t elems = avail / sizeof(Elem); 00398 if (elems != 0) return elems; 00399 return avail != 0 && store->free() >= sizeof(Elem) ? 1 : 0; 00400 } 00401 00402 /** 00403 * Unallocates exactly the specified number of elements by removing 00404 * them from the buffer and releasing their storage. 00405 * 00406 * This operation may always be safely performed with count 00407 * less than or equal to that specified in the last alloc(size_t) 00408 * or put(const T*, size_t) if no non-const buffer members have 00409 * been called since then. 00410 * 00411 * If count == 0, nothing happens. 00412 * 00413 * It is an error for count to be greater than unallocable(). 00414 * 00415 * 00416 * "count" is the number of elements 00417 */ 00418 void unalloc(size_t count) 00419 { 00420 return store->unalloc(count * sizeof(Elem)); 00421 } 00422 00423 /** 00424 * Returns the maximum number of elements that may be unallocated 00425 * at this time. 00426 * 00427 * For all practical purposes, this number will always be at least 00428 * as large as the amount currently in use. It is provided 00429 * primarily for symmetry, but also to handle cases where 00430 * buffer reading (hence used()) is not supported by the 00431 * implementation. 00432 * 00433 * Invariants: 00434 * 00435 * - unallocable() >= used() 00436 * 00437 * 00438 * Returns: the number of elements 00439 */ 00440 size_t unallocable() const 00441 { 00442 return store->unallocable() / sizeof(Elem); 00443 } 00444 00445 /** 00446 * Returns a non-const pointer info the buffer at the specified 00447 * offset to the specified number of elements without actually 00448 * adjusting the current get() index. 00449 * 00450 * Other than the fact that the returned storage is mutable, 00451 * operates identically to peek(int, size_t). 00452 * 00453 * 00454 * "offset" is the buffer offset 00455 * "count" is the number of elements 00456 * Returns: the element storage pointer 00457 */ 00458 T *mutablepeek(int offset, size_t count) 00459 { 00460 return static_cast<T*>(store->mutablepeek( 00461 offset * sizeof(Elem), count * sizeof(Elem))); 00462 } 00463 00464 /** 00465 * Writes the specified number of elements from the specified 00466 * storage location into the buffer at its tail. 00467 * 00468 * It is an error for count to be greater than free(). 00469 * 00470 * For maximum efficiency, choose as large a count as possible. 00471 * 00472 * The pointer buf may be NULL only if count == 0. 00473 * 00474 * After this operation, at least count elements may be unallocated. 00475 * 00476 * 00477 * "data" is the buffer that contains the elements 00478 * "count" is the number of elements 00479 */ 00480 void put(const T *data, size_t count) 00481 { 00482 store->put(data, count * sizeof(Elem)); 00483 } 00484 00485 /** 00486 * Efficiently copies the specified number of elements from the 00487 * specified storage location into the buffer at a particular 00488 * offset. 00489 * 00490 * If offset <= used() and offset + count > used(), the 00491 * remaining data is simply tacked onto the end of the buffer 00492 * with put(). 00493 * 00494 * It is an error for count to be greater than free() - offset. 00495 * 00496 * 00497 * "data" is the buffer that contains the elements 00498 * "count" is the number of elements 00499 * "offset" is the buffer offset, default 0 00500 */ 00501 void poke(const T *data, int offset, size_t count) 00502 { 00503 store->poke(data, offset * sizeof(Elem), count * sizeof(Elem)); 00504 } 00505 00506 /** 00507 * Writes the element into the buffer at its tail. 00508 * 00509 * It is an error to invoke this method if free() == 0. 00510 * 00511 * After this operation, at least 1 element may be unallocated. 00512 * 00513 * 00514 * "valid" is the element 00515 */ 00516 void put(T &value) 00517 { 00518 store->fastput(& value, sizeof(Elem)); 00519 } 00520 00521 /** 00522 * Writes the element into the buffer at the specified offset. 00523 * 00524 * It is an error to invoke this method if free() == 0. 00525 * 00526 * After this operation, at least 1 element may be unallocated. 00527 * 00528 * 00529 * "value" is the element 00530 * "offset" is the buffer offset 00531 */ 00532 void poke(T &value, int offset) 00533 { 00534 poke(& value, offset, 1); 00535 } 00536 00537 00538 /*** Buffer to Buffer Transfers ***/ 00539 00540 /** 00541 * Efficiently moves count bytes from the specified buffer into 00542 * this one. In some cases, this may be a zero-copy operation. 00543 * 00544 * It is an error for count to be greater than inbuf.used(). 00545 * 00546 * For maximum efficiency, choose as large a count as possible. 00547 * 00548 * After this operation, an indeterminate number of elements 00549 * may be ungotten from inbuf. 00550 * 00551 * 00552 * "inbuf" is the buffer from which to read 00553 * "count" is the number of elements 00554 */ 00555 void merge(Buffer &inbuf, size_t count) 00556 { 00557 store->merge(*inbuf.store, count * sizeof(Elem)); 00558 } 00559 00560 /** 00561 * Efficiently merges the entire contents of a buffer into this one. 00562 * 00563 * "inbuf" is the buffer from which to read 00564 */ 00565 void merge(Buffer &inbuf) 00566 { 00567 merge(inbuf, inbuf.used()); 00568 } 00569 }; 00570 00571 00572 00573 /** 00574 * The generic buffer base type. 00575 * To specialize buffers to add new functionality, declare a template 00576 * specialization of this type that derives from WvBufBaseCommonImpl. 00577 * 00578 * See WvBufBaseCommonImpl<T> 00579 * "T" is the type of object to store, must be a primitive or a struct 00580 * without special initialization, copy, or assignment semantics 00581 */ 00582 template<class T> 00583 class WvBufBase : public WvBufBaseCommonImpl<T> 00584 { 00585 public: 00586 explicit WvBufBase(WvBufStore *store) : 00587 WvBufBaseCommonImpl<T>(store) { } 00588 }; 00589 00590 00591 00592 /** 00593 * A buffer that wraps a pre-allocated array and provides 00594 * read-write access to its elements. 00595 * 00596 * "T" is the type of object to store, must be a primitive or a struct 00597 * without special initialization, copy, or assignment semantics 00598 */ 00599 template<class T> 00600 class WvInPlaceBufBase : public WvBufBase<T> 00601 { 00602 protected: 00603 typedef T Elem; 00604 00605 WvInPlaceBufStore mystore; 00606 00607 public: 00608 /** 00609 * Creates a new buffer backed by the supplied array. 00610 * 00611 * "_data" is the array of data to wrap 00612 * "_avail" is the amount of data available for reading 00613 * "_size" is the size of the array 00614 * "_autofree" is if true, the array will be freed when discarded 00615 */ 00616 WvInPlaceBufBase(T *_data, size_t _avail, size_t _size, 00617 bool _autofree = false) : 00618 WvBufBase<T>(& mystore), 00619 mystore(sizeof(Elem), _data, _avail * sizeof(Elem), 00620 _size * sizeof(Elem), _autofree) { } 00621 00622 /** 00623 * Creates a new empty buffer backed by a new array. 00624 * 00625 * "_size" is the size of the array 00626 */ 00627 explicit WvInPlaceBufBase(size_t _size) : 00628 WvBufBase<T>(& mystore), 00629 mystore(sizeof(Elem), _size * sizeof(Elem)) { } 00630 00631 /** Creates a new empty buffer with no backing array. */ 00632 WvInPlaceBufBase() : 00633 WvBufBase<T>(& mystore), 00634 mystore(sizeof(Elem), NULL, 0, 0, false) { } 00635 00636 /** 00637 * Destroys the buffer. 00638 * 00639 * Frees the underlying array if autofree(). 00640 * 00641 */ 00642 virtual ~WvInPlaceBufBase() { } 00643 00644 /** 00645 * Returns the underlying array pointer. 00646 * 00647 * Returns: the element pointer 00648 */ 00649 T *ptr() const 00650 { 00651 return static_cast<T*>(mystore.ptr()); 00652 } 00653 00654 /** 00655 * Returns the total size of the buffer. 00656 * 00657 * Returns: the number of elements 00658 */ 00659 size_t size() const 00660 { 00661 return mystore.size() / sizeof(Elem); 00662 } 00663 00664 /** 00665 * Returns the autofree flag. 00666 * 00667 * Returns: the autofree flag 00668 */ 00669 bool autofree() const 00670 { 00671 return mystore.autofree(); 00672 } 00673 00674 /** 00675 * Sets or clears the auto_free flag. 00676 * 00677 * "_autofree" is if true, the array will be freed when discarded 00678 */ 00679 void setautofree(bool _autofree) 00680 { 00681 mystore.setautofree(_autofree); 00682 } 00683 00684 /** 00685 * Resets the underlying buffer pointer and properties. 00686 * 00687 * If the old and new buffer pointers differ and the old buffer 00688 * was specified as auto_free, the old buffer is destroyed. 00689 * 00690 * "_data" is the array of data to wrap 00691 * "_avail" is the amount of data available for reading 00692 * "_size" is the size of the array 00693 * "_autofree" is if true, the array will be freed when discarded 00694 */ 00695 void reset(T *_data, size_t _avail, size_t _size, 00696 bool _autofree = false) 00697 { 00698 mystore.reset(_data, _avail * sizeof(Elem), 00699 _size * sizeof(Elem), _autofree); 00700 } 00701 00702 /** 00703 * Sets the amount of available data using the current buffer 00704 * and resets the read index to the beginning of the buffer. 00705 * 00706 * "_avail" is the amount of data available for reading 00707 */ 00708 void setavail(size_t _avail) 00709 { 00710 mystore.setavail(_avail * sizeof(Elem)); 00711 } 00712 }; 00713 00714 00715 00716 /** 00717 * A buffer that wraps a pre-allocated array and provides 00718 * read-only access to its elements. 00719 * 00720 * "T" is the type of object to store, must be a primitive or a struct 00721 * without special initialization, copy, or assignment semantics 00722 */ 00723 template<class T> 00724 class WvConstInPlaceBufBase : public WvBufBase<T> 00725 { 00726 protected: 00727 typedef T Elem; 00728 00729 WvConstInPlaceBufStore mystore; 00730 00731 public: 00732 /** 00733 * Creates a new buffer backed by the supplied array. 00734 * 00735 * "_data" is the array of data to wrap 00736 * "_avail" is the amount of data available for reading 00737 */ 00738 WvConstInPlaceBufBase(const T *_data, size_t _avail) : 00739 WvBufBase<T>(& mystore), 00740 mystore(sizeof(Elem), _data, _avail * sizeof(Elem)) { } 00741 00742 /** Creates a new empty buffer with no backing array. */ 00743 WvConstInPlaceBufBase() : 00744 WvBufBase<T>(& mystore), 00745 mystore(sizeof(Elem), NULL, 0) { } 00746 00747 /** 00748 * Destroys the buffer. 00749 * 00750 * Never frees the underlying array. 00751 * 00752 */ 00753 virtual ~WvConstInPlaceBufBase() { } 00754 00755 /** 00756 * Returns the underlying array pointer. 00757 * 00758 * Returns: the element pointer 00759 */ 00760 const T *ptr() const 00761 { 00762 return static_cast<const T*>(mystore.ptr()); 00763 } 00764 00765 /** 00766 * Resets the underlying buffer pointer and properties. 00767 * 00768 * Never frees the old buffer. 00769 * 00770 * 00771 * "_data" is the array of data to wrap 00772 * "_avail" is the amount of data available for reading 00773 */ 00774 void reset(const T *_data, size_t _avail) 00775 { 00776 mystore.reset(_data, _avail * sizeof(Elem)); 00777 } 00778 00779 /** 00780 * Sets the amount of available data using the current buffer 00781 * and resets the read index to the beginning of the buffer. 00782 * 00783 * "_avail" is the amount of data available for reading 00784 */ 00785 void setavail(size_t _avail) 00786 { 00787 mystore.setavail(_avail * sizeof(Elem)); 00788 } 00789 }; 00790 00791 00792 00793 /** 00794 * A buffer that wraps a pre-allocated array and provides 00795 * read-write access to its elements using a circular buffering 00796 * scheme rather than a purely linear one, as used by 00797 * WvInPlaceBuf. 00798 * 00799 * When there is insufficient contigous free/used space to 00800 * satisfy a read or write request, the data is automatically 00801 * reordered in-place to coalesce the free/used spaces into 00802 * sufficiently large chunks. The process may also be manually 00803 * triggered to explicitly renormalize the array and shift its 00804 * contents to the front. 00805 * 00806 * "T" is the type of object to store, must be a primitive or a struct 00807 * without special initialization, copy, or assignment semantics 00808 */ 00809 template<class T> 00810 class WvCircularBufBase : public WvBufBase<T> 00811 { 00812 protected: 00813 typedef T Elem; 00814 00815 WvCircularBufStore mystore; 00816 00817 public: 00818 /** 00819 * Creates a new circular buffer backed by the supplied array. 00820 * 00821 * "_data" is the array of data to wrap 00822 * "_avail" is the amount of data available for reading 00823 * at the beginning of the buffer 00824 * "_size" is the size of the array 00825 * "_autofree" is if true, the array will be freed when discarded 00826 */ 00827 WvCircularBufBase(T *_data, size_t _avail, size_t _size, 00828 bool _autofree = false) : 00829 WvBufBase<T>(& mystore), 00830 mystore(sizeof(Elem), _data, _avail * sizeof(Elem), 00831 _size * sizeof(Elem), _autofree) { } 00832 00833 /** 00834 * Creates a new empty circular buffer backed by a new array. 00835 * 00836 * "_size" is the size of the array 00837 */ 00838 explicit WvCircularBufBase(size_t _size) : 00839 WvBufBase<T>(& mystore), 00840 mystore(sizeof(Elem), _size * sizeof(Elem)) { } 00841 00842 /** Creates a new empty buffer with no backing array. */ 00843 WvCircularBufBase() : 00844 WvBufBase<T>(& mystore), 00845 mystore(sizeof(Elem), NULL, 0, 0, false) { } 00846 00847 /** 00848 * Destroys the buffer. 00849 * 00850 * Frees the underlying array if autofree(). 00851 * 00852 */ 00853 virtual ~WvCircularBufBase() { } 00854 00855 /** 00856 * Returns the underlying array pointer. 00857 * 00858 * Returns: the element pointer 00859 */ 00860 T *ptr() const 00861 { 00862 return static_cast<T*>(mystore.ptr()); 00863 } 00864 00865 /** 00866 * Returns the total size of the buffer. 00867 * 00868 * Returns: the number of elements 00869 */ 00870 size_t size() const 00871 { 00872 return mystore.size() / sizeof(Elem); 00873 } 00874 00875 /** 00876 * Returns the autofree flag. 00877 * 00878 * Returns: the autofree flag 00879 */ 00880 bool autofree() const 00881 { 00882 return mystore.autofree(); 00883 } 00884 00885 /** 00886 * Sets or clears the auto_free flag. 00887 * 00888 * "_autofree" is if true, the array will be freed when discarded 00889 */ 00890 void setautofree(bool _autofree) 00891 { 00892 mystore.setautofree(_autofree); 00893 } 00894 00895 /** 00896 * Resets the underlying buffer pointer and properties. 00897 * 00898 * If the old and new buffer pointers differ and the old buffer 00899 * was specified as auto_free, the old buffer is destroyed. 00900 * 00901 * "_data" is the array of data to wrap 00902 * "_avail" is the amount of data available for reading 00903 * at the beginning of the buffer 00904 * "_size" is the size of the array 00905 * "_autofree" is if true, the array will be freed when discarded 00906 */ 00907 void reset(T *_data, size_t _avail, size_t _size, 00908 bool _autofree = false) 00909 { 00910 mystore.reset(_data, _avail * sizeof(Elem), 00911 _size * sizeof(Elem), _autofree); 00912 } 00913 00914 /** 00915 * Sets the amount of available data using the current buffer 00916 * and resets the read index to the beginning of the buffer. 00917 * 00918 * "_avail" is the amount of data available for reading 00919 * at the beginning of the buffer 00920 */ 00921 void setavail(size_t _avail) 00922 { 00923 mystore.setavail(_avail * sizeof(Elem)); 00924 } 00925 00926 /** 00927 * Normalizes the arrangement of the data such that the 00928 * contents of the buffer are stored at the beginning of 00929 * the array starting with the next element that would be 00930 * returned by get(size_t). 00931 * 00932 * After invocation, ungettable() may equal 0. 00933 * 00934 */ 00935 void normalize() 00936 { 00937 mystore.normalize(); 00938 } 00939 }; 00940 00941 00942 00943 /** 00944 * A buffer that dynamically grows and shrinks based on demand. 00945 * 00946 * "T" is the type of object to store, must be a primitive or a struct 00947 * without special initialization, copy, or assignment semantics 00948 */ 00949 template<class T> 00950 class WvDynBufBase : public WvBufBase<T> 00951 { 00952 protected: 00953 typedef T Elem; 00954 00955 WvDynBufStore mystore; 00956 00957 public: 00958 /** 00959 * Creates a new buffer. 00960 * 00961 * Provides some parameters for tuning response to buffer 00962 * growth. 00963 * 00964 * "_minalloc" is the minimum number of elements to allocate 00965 * at once when creating a new internal buffer segment 00966 * "_maxalloc" is the maximum number of elements to allocate 00967 * at once when creating a new internal buffer segment 00968 * before before reverting to a linear growth pattern 00969 */ 00970 explicit WvDynBufBase(size_t _minalloc = 1024, 00971 size_t _maxalloc = 1048576) : 00972 WvBufBase<T>(& mystore), 00973 mystore(sizeof(Elem), _minalloc * sizeof(Elem), 00974 _maxalloc * sizeof(Elem)) { } 00975 }; 00976 00977 00978 00979 /** 00980 * A buffer that is always empty. 00981 * 00982 * "T" is the type of object to store, must be a primitive or a struct 00983 * without special initialization, copy, or assignment semantics 00984 */ 00985 template<class T> 00986 class WvNullBufBase : public WvBufBase<T> 00987 { 00988 protected: 00989 typedef T Elem; 00990 00991 WvNullBufStore mystore; 00992 00993 public: 00994 /** Creates a new buffer. */ 00995 WvNullBufBase() : 00996 WvBufBase<T>(& mystore), 00997 mystore(sizeof(Elem)) { } 00998 }; 00999 01000 01001 01002 /** 01003 * A buffer that acts like a cursor over a portion of another buffer. 01004 * The underlying buffer's get() position is not affected by 01005 * reading from this buffer. 01006 * 01007 * "T" is the type of object to store, must be a primitive or a struct 01008 * without special initialization, copy, or assignment semantics 01009 */ 01010 template<class T> 01011 class WvBufCursorBase : public WvBufBase<T> 01012 { 01013 protected: 01014 typedef T Elem; 01015 01016 WvBufCursorStore mystore; 01017 01018 public: 01019 /** 01020 * Creates a new buffer. 01021 * 01022 * Does not take ownership of the supplied buffer. 01023 * 01024 * 01025 * "_buf" is a pointer to the buffer to be wrapped 01026 * "_start" is the buffer offset of the window start position 01027 * "_length" is the length of the window 01028 */ 01029 WvBufCursorBase(WvBufBase<T> &_buf, int _start, 01030 size_t _length) : 01031 WvBufBase<T>(& mystore), 01032 mystore(sizeof(Elem), _buf.getstore(), 01033 _start * sizeof(Elem), _length * sizeof(Elem)) { } 01034 }; 01035 01036 01037 /** 01038 * A buffer that provides a read-write view over another buffer 01039 * with a different datatype. Reading and writing through this 01040 * buffer implicitly performs the equivalent of reinterpret_cast 01041 * on each element. 01042 * 01043 * Most useful for manipulating data backed by a raw memory buffer. 01044 * 01045 * "T" is the type of object to store, must be a primitive or a struct 01046 * without special initialization, copy, or assignment semantics 01047 */ 01048 template<class T> 01049 class WvBufViewBase : public WvBufBase<T> 01050 { 01051 public: 01052 /** 01053 * Creates a new buffer. 01054 * 01055 * Does not take ownership of the supplied buffer. 01056 * 01057 * 01058 * "_buf" is a pointer to the buffer to be wrapped 01059 */ 01060 template<typename S> 01061 WvBufViewBase(WvBufBase<S> &_buf) : 01062 WvBufBase<T>(_buf.getstore()) { } 01063 }; 01064 01065 #endif // __WVBUFFERBASE_H