Saner handling if config.mk doesn't exist: use a default config.defaults.mk.
[wvstreams.git] / include / wvbufbase.h
blob3a2eade83ef02c767c0b7dbb67d0e9be9efc8547
1 /* -*- Mode: C++ -*-
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
5 * A generic buffering API.
6 * Please declare specializations in a separate header file,
7 * See "wvbuf.h".
8 */
9 #ifndef __WVBUFFERBASE_H
10 #define __WVBUFFERBASE_H
12 #include "wvbufstore.h"
14 template<class T>
15 class WvBufBase;
17 /**
18 * An abstract generic buffer template.
19 * Buffers are simple data queues designed to ease the construction of
20 * functions that must generate, consume, or transform large amount of
21 * data in pipeline fashion. Concrete buffer subclases define the actual
22 * storage mechanism and queuing machinery. In addition they may provide
23 * additional functionality for accomplishing particular tasks.
25 * The base component is split into two parts, WvBufBaseCommonImpl
26 * that defines the common API for all buffer types, and WvBufBase
27 * that allows specializations to be defined to add functionality
28 * to the base type. When passing around buffer objects, you should
29 * use the WvBufBase<T> type rather than WvBufBaseCommonImpl<T>.
31 * See WvBufBase<T>
32 * "T" is the type of object to store, must be a primitive or a struct
33 * without special initialization, copy, or assignment semantics
35 template<class T>
36 class WvBufBaseCommonImpl
38 protected:
39 typedef T Elem;
40 typedef WvBufBase<T> Buffer;
42 WvBufStore *store;
44 // discourage copying
45 explicit WvBufBaseCommonImpl(
46 const WvBufBaseCommonImpl &other) { }
48 protected:
49 /**
50 * Initializes the buffer.
52 * Note: Does not take ownership of the storage object.
55 * "store" is the low-level storage object
57 explicit WvBufBaseCommonImpl(WvBufStore *store) :
58 store(store) { }
60 public:
61 /** Destroys the buffer. */
62 virtual ~WvBufBaseCommonImpl() { }
64 /**
65 * Returns a pointer to the underlying storage class object.
67 * Returns: the low-level storage class object pointer, non-null
69 WvBufStore *getstore()
71 return store;
74 /*** Buffer Reading ***/
76 /**
77 * Returns true if the buffer supports reading.
79 * Returns: true if reading is supported
81 bool isreadable() const
83 return store->isreadable();
86 /**
87 * Returns the number of elements in the buffer currently
88 * available for reading.
90 * This function could also be called gettable().
92 size_t used() const
94 return store->used() / sizeof(Elem);
97 /**
98 * Reads exactly the specified number of elements and returns
99 * a pointer to a storage location owned by the buffer.
101 * The pointer is only valid until the next non-const buffer
102 * member is called. eg. alloc(size_t)
104 * If count == 0, a NULL pointer may be returned.
106 * It is an error for count to be greater than the number of
107 * available elements in the buffer.
109 * For maximum efficiency, call this function multiple times
110 * with count no greater than optgettable() each time.
112 * After this operation, at least count elements may be ungotten.
114 const T *get(size_t count)
116 if (count > used())
117 return NULL;
119 return static_cast<const T*>(
120 store->get(count * sizeof(Elem)));
124 * Skips exactly the specified number of elements.
126 * This is equivalent to invoking get(size_t) with the count
127 * and discarding the result, but may be faster for certain
128 * types of buffers. As with get(size_t), the call may be
129 * followed up by an unget(size_t).
131 * It is an error for count to be greater than the number of
132 * available elements in the buffer.
134 * "count" is the number of elements
136 void skip(size_t count)
138 store->skip(count * sizeof(Elem));
142 * Returns the optimal maximum number of elements in the
143 * buffer currently available for reading without incurring
144 * significant overhead.
146 * Invariants:
148 * - optgettable() <= used()
149 * - optgettable() != 0 if used() != 0
152 * Returns: the number of elements
154 size_t optgettable() const
156 size_t avail = store->optgettable();
157 size_t elems = avail / sizeof(Elem);
158 if (elems != 0) return elems;
159 return avail != 0 && store->used() >= sizeof(Elem) ? 1 : 0;
163 * Ungets exactly the specified number of elements by returning
164 * them to the buffer for subsequent reads.
166 * This operation may always be safely performed with count
167 * less than or equal to that specified in the last get(size_t)
168 * if no non-const buffer members have been called since then.
170 * If count == 0, nothing happens.
172 * It is an error for count to be greater than ungettable().
175 * "count" is the number of elements
177 void unget(size_t count)
179 store->unget(count * sizeof(Elem));
183 * Returns the maximum number of elements that may be ungotten
184 * at this time.
186 * Returns: the number of elements
188 size_t ungettable() const
190 return store->ungettable() / sizeof(Elem);
194 * Returns a const pointer into the buffer at the specified
195 * offset to the specified number of elements without actually
196 * adjusting the current get() index.
198 * The pointer is only valid until the next non-const buffer
199 * member is called. eg. alloc(size_t)
201 * If count == 0, a NULL pointer may be returned.
203 * If offset is greater than zero, then elements will be returned
204 * beginning with the with the offset'th element that would be
205 * returned by get(size_t).
207 * If offset equals zero, then elements will be returned beginning
208 * with the next one available for get(size_t).
210 * If offset is less than zero, then elements will be returned
211 * beginning with the first one that would be returned on a
212 * get(size_t) following an unget(-offset).
214 * It is an error for count to be greater than peekable(offset).
216 * For maximum efficiency, call this function multiple times
217 * with count no greater than that returned by optpeekable(size_t)
218 * at incremental offsets.
221 * "offset" is the buffer offset
222 * "count" is the number of elements
223 * Returns: the element storage pointer
225 const T *peek(int offset, size_t count)
227 return static_cast<const T*>(store->peek(
228 offset * sizeof(Elem), count * sizeof(Elem)));
231 size_t peekable(int offset)
233 return store->peekable(offset * sizeof(Elem)) / sizeof(Elem);
236 size_t optpeekable(int offset)
238 offset *= sizeof(Elem);
239 size_t avail = store->optpeekable(offset);
240 size_t elems = avail / sizeof(Elem);
241 if (elems != 0) return elems;
242 return avail != 0 &&
243 store->peekable(offset) >= sizeof(Elem) ? 1 : 0;
247 * Clears the buffer.
249 * For many types of buffers, calling zap() will increased the
250 * amount of free space available for writing (see below) by
251 * an amount greater than used(). Hence it is wise to zap()
252 * a buffer just before writing to it to maximize free space.
254 * After this operation, used() == 0, and often ungettable() == 0.
257 void zap()
259 store->zap();
263 * Reads the next element from the buffer.
265 * It is an error to invoke this method if used() == 0.
267 * After this operation, at least 1 element may be ungotten.
270 * Returns: the element
272 T get()
274 return *get(1);
278 * Returns the element at the specified offset in the buffer.
280 * It is an error to invoke this method if used() == 0.
283 * "offset" is the offset, default 0
284 * Returns: the element
286 T peek(int offset = 0)
288 return *peek(offset * sizeof(Elem), sizeof(Elem));
292 * Efficiently copies the specified number of elements from the
293 * buffer to the specified UNINITIALIZED storage location
294 * and removes the elements from the buffer.
296 * It is an error for count to be greater than used().
298 * For maximum efficiency, choose as large a count as possible.
300 * The pointer buf may be NULL only if count == 0.
302 * After this operation, an indeterminate number of elements
303 * may be ungotten.
306 * "buf" is the buffer that will receive the elements
307 * "count" is the number of elements
309 void move(T *buf, size_t count)
311 store->move(buf, count * sizeof(Elem));
315 * Efficiently copies the specified number of elements from the
316 * buffer to the specified UNINITIALIZED storage location
317 * but does not remove the elements from the buffer.
319 * It is an error for count to be greater than peekable(offset).
321 * For maximum efficiency, choose as large a count as possible.
323 * The pointer buf may be NULL only if count == 0.
326 * "buf" is the buffer that will receive the elements
327 * "offset" is the buffer offset
328 * "count" is the number of elements
330 void copy(T *buf, int offset, size_t count)
332 store->copy(buf, offset * sizeof(Elem), count * sizeof(Elem));
335 /*** Buffer Writing ***/
338 * Returns true if the buffer supports writing.
340 * Returns: true if writing is supported
342 bool iswritable() const
344 return true;
348 * Returns the number of elements that the buffer can currently
349 * accept for writing.
351 * Returns: the number of elements
353 size_t free() const
355 return store->free() / sizeof(Elem);
359 * Allocates exactly the specified number of elements and returns
360 * a pointer to an UNINITIALIZED storage location owned by the
361 * buffer.
363 * The pointer is only valid until the next non-const buffer
364 * member is called. eg. alloc(size_t)
366 * If count == 0, a NULL pointer may be returned.
368 * It is an error for count to be greater than free().
370 * For best results, call this function multiple times with
371 * count no greater than optallocable() each time.
373 * After this operation, at least count elements may be unallocated.
376 * "count" is the number of elements
377 * Returns: the element storage pointer
379 T *alloc(size_t count)
381 return static_cast<T*>(store->alloc(count * sizeof(Elem)));
385 * Returns the optimal maximum number of elements that the
386 * buffer can currently accept for writing without incurring
387 * significant overhead.
389 * Invariants:
391 * - optallocable() <= free()
392 * - optallocable() != 0 if free() != 0
395 * Returns: the number of elements
397 size_t optallocable() const
399 size_t avail = store->optallocable();
400 size_t elems = avail / sizeof(Elem);
401 if (elems != 0) return elems;
402 return avail != 0 && store->free() >= sizeof(Elem) ? 1 : 0;
406 * Unallocates exactly the specified number of elements by removing
407 * them from the buffer and releasing their storage.
409 * This operation may always be safely performed with count
410 * less than or equal to that specified in the last alloc(size_t)
411 * or put(const T*, size_t) if no non-const buffer members have
412 * been called since then.
414 * If count == 0, nothing happens.
416 * It is an error for count to be greater than unallocable().
419 * "count" is the number of elements
421 void unalloc(size_t count)
423 return store->unalloc(count * sizeof(Elem));
427 * Returns the maximum number of elements that may be unallocated
428 * at this time.
430 * For all practical purposes, this number will always be at least
431 * as large as the amount currently in use. It is provided
432 * primarily for symmetry, but also to handle cases where
433 * buffer reading (hence used()) is not supported by the
434 * implementation.
436 * Invariants:
438 * - unallocable() >= used()
441 * Returns: the number of elements
443 size_t unallocable() const
445 return store->unallocable() / sizeof(Elem);
449 * Returns a non-const pointer info the buffer at the specified
450 * offset to the specified number of elements without actually
451 * adjusting the current get() index.
453 * Other than the fact that the returned storage is mutable,
454 * operates identically to peek(int, size_t).
457 * "offset" is the buffer offset
458 * "count" is the number of elements
459 * Returns: the element storage pointer
461 T *mutablepeek(int offset, size_t count)
463 return static_cast<T*>(store->mutablepeek(
464 offset * sizeof(Elem), count * sizeof(Elem)));
468 * Writes the specified number of elements from the specified
469 * storage location into the buffer at its tail.
471 * It is an error for count to be greater than free().
473 * For maximum efficiency, choose as large a count as possible.
475 * The pointer buf may be NULL only if count == 0.
477 * After this operation, at least count elements may be unallocated.
480 * "data" is the buffer that contains the elements
481 * "count" is the number of elements
483 void put(const T *data, size_t count)
485 store->put(data, count * sizeof(Elem));
489 * Efficiently copies the specified number of elements from the
490 * specified storage location into the buffer at a particular
491 * offset.
493 * If offset <= used() and offset + count > used(), the
494 * remaining data is simply tacked onto the end of the buffer
495 * with put().
497 * It is an error for count to be greater than free() - offset.
500 * "data" is the buffer that contains the elements
501 * "count" is the number of elements
502 * "offset" is the buffer offset, default 0
504 void poke(const T *data, int offset, size_t count)
506 store->poke(data, offset * sizeof(Elem), count * sizeof(Elem));
510 * Writes the element into the buffer at its tail.
512 * It is an error to invoke this method if free() == 0.
514 * After this operation, at least 1 element may be unallocated.
517 * "valid" is the element
519 void put(T &value)
521 store->fastput(& value, sizeof(Elem));
525 * Writes the element into the buffer at the specified offset.
527 * It is an error to invoke this method if free() == 0.
529 * After this operation, at least 1 element may be unallocated.
532 * "value" is the element
533 * "offset" is the buffer offset
535 void poke(T &value, int offset)
537 poke(& value, offset, 1);
541 /*** Buffer to Buffer Transfers ***/
544 * Efficiently moves count bytes from the specified buffer into
545 * this one. In some cases, this may be a zero-copy operation.
547 * It is an error for count to be greater than inbuf.used().
549 * For maximum efficiency, choose as large a count as possible.
551 * After this operation, an indeterminate number of elements
552 * may be ungotten from inbuf.
555 * "inbuf" is the buffer from which to read
556 * "count" is the number of elements
558 void merge(Buffer &inbuf, size_t count)
560 store->merge(*inbuf.store, count * sizeof(Elem));
564 * Efficiently merges the entire contents of a buffer into this one.
566 * "inbuf" is the buffer from which to read
568 void merge(Buffer &inbuf)
570 merge(inbuf, inbuf.used());
577 * The generic buffer base type.
578 * To specialize buffers to add new functionality, declare a template
579 * specialization of this type that derives from WvBufBaseCommonImpl.
581 * See WvBufBaseCommonImpl<T>
582 * "T" is the type of object to store, must be a primitive or a struct
583 * without special initialization, copy, or assignment semantics
585 template<class T>
586 class WvBufBase : public WvBufBaseCommonImpl<T>
588 public:
589 explicit WvBufBase(WvBufStore *store) :
590 WvBufBaseCommonImpl<T>(store) { }
596 * A buffer that wraps a pre-allocated array and provides
597 * read-write access to its elements.
599 * "T" is the type of object to store, must be a primitive or a struct
600 * without special initialization, copy, or assignment semantics
602 template<class T>
603 class WvInPlaceBufBase : public WvBufBase<T>
605 protected:
606 typedef T Elem;
608 WvInPlaceBufStore mystore;
610 public:
612 * Creates a new buffer backed by the supplied array.
614 * "_data" is the array of data to wrap
615 * "_avail" is the amount of data available for reading
616 * "_size" is the size of the array
617 * "_autofree" is if true, the array will be freed when discarded
619 WvInPlaceBufBase(T *_data, size_t _avail, size_t _size,
620 bool _autofree = false) :
621 WvBufBase<T>(& mystore),
622 mystore(sizeof(Elem), _data, _avail * sizeof(Elem),
623 _size * sizeof(Elem), _autofree) { }
626 * Creates a new empty buffer backed by a new array.
628 * "_size" is the size of the array
630 explicit WvInPlaceBufBase(size_t _size) :
631 WvBufBase<T>(& mystore),
632 mystore(sizeof(Elem), _size * sizeof(Elem)) { }
634 /** Creates a new empty buffer with no backing array. */
635 WvInPlaceBufBase() :
636 WvBufBase<T>(& mystore),
637 mystore(sizeof(Elem), NULL, 0, 0, false) { }
640 * Destroys the buffer.
642 * Frees the underlying array if autofree().
645 virtual ~WvInPlaceBufBase() { }
648 * Returns the underlying array pointer.
650 * Returns: the element pointer
652 T *ptr() const
654 return static_cast<T*>(mystore.ptr());
658 * Returns the total size of the buffer.
660 * Returns: the number of elements
662 size_t size() const
664 return mystore.size() / sizeof(Elem);
668 * Returns the autofree flag.
670 * Returns: the autofree flag
672 bool get_autofree() const
674 return mystore.get_autofree();
678 * Sets or clears the autofree flag.
680 * "_autofree" is if true, the array will be freed when discarded
682 void set_autofree(bool _autofree)
684 mystore.set_autofree(_autofree);
688 * Resets the underlying buffer pointer and properties.
690 * If the old and new buffer pointers differ and the old buffer
691 * was specified as autofree, the old buffer is destroyed.
693 * "_data" is the array of data to wrap
694 * "_avail" is the amount of data available for reading
695 * "_size" is the size of the array
696 * "_autofree" is if true, the array will be freed when discarded
698 void reset(T *_data, size_t _avail, size_t _size,
699 bool _autofree = false)
701 mystore.reset(_data, _avail * sizeof(Elem),
702 _size * sizeof(Elem), _autofree);
706 * Sets the amount of available data using the current buffer
707 * and resets the read index to the beginning of the buffer.
709 * "_avail" is the amount of data available for reading
711 void setavail(size_t _avail)
713 mystore.setavail(_avail * sizeof(Elem));
720 * A buffer that wraps a pre-allocated array and provides
721 * read-only access to its elements.
723 * "T" is the type of object to store, must be a primitive or a struct
724 * without special initialization, copy, or assignment semantics
726 template<class T>
727 class WvConstInPlaceBufBase : public WvBufBase<T>
729 protected:
730 typedef T Elem;
732 WvConstInPlaceBufStore mystore;
734 public:
736 * Creates a new buffer backed by the supplied array.
738 * "_data" is the array of data to wrap
739 * "_avail" is the amount of data available for reading
741 WvConstInPlaceBufBase(const T *_data, size_t _avail) :
742 WvBufBase<T>(& mystore),
743 mystore(sizeof(Elem), _data, _avail * sizeof(Elem)) { }
745 /** Creates a new empty buffer with no backing array. */
746 WvConstInPlaceBufBase() :
747 WvBufBase<T>(& mystore),
748 mystore(sizeof(Elem), NULL, 0) { }
751 * Destroys the buffer.
753 * Never frees the underlying array.
756 virtual ~WvConstInPlaceBufBase() { }
759 * Returns the underlying array pointer.
761 * Returns: the element pointer
763 const T *ptr() const
765 return static_cast<const T*>(mystore.ptr());
769 * Resets the underlying buffer pointer and properties.
771 * Never frees the old buffer.
774 * "_data" is the array of data to wrap
775 * "_avail" is the amount of data available for reading
777 void reset(const T *_data, size_t _avail)
779 mystore.reset(_data, _avail * sizeof(Elem));
783 * Sets the amount of available data using the current buffer
784 * and resets the read index to the beginning of the buffer.
786 * "_avail" is the amount of data available for reading
788 void setavail(size_t _avail)
790 mystore.setavail(_avail * sizeof(Elem));
797 * A buffer that wraps a pre-allocated array and provides
798 * read-write access to its elements using a circular buffering
799 * scheme rather than a purely linear one, as used by
800 * WvInPlaceBuf.
802 * When there is insufficient contigous free/used space to
803 * satisfy a read or write request, the data is automatically
804 * reordered in-place to coalesce the free/used spaces into
805 * sufficiently large chunks. The process may also be manually
806 * triggered to explicitly renormalize the array and shift its
807 * contents to the front.
809 * "T" is the type of object to store, must be a primitive or a struct
810 * without special initialization, copy, or assignment semantics
812 template<class T>
813 class WvCircularBufBase : public WvBufBase<T>
815 protected:
816 typedef T Elem;
818 WvCircularBufStore mystore;
820 public:
822 * Creates a new circular buffer backed by the supplied array.
824 * "_data" is the array of data to wrap
825 * "_avail" is the amount of data available for reading
826 * at the beginning of the buffer
827 * "_size" is the size of the array
828 * "_autofree" is if true, the array will be freed when discarded
830 WvCircularBufBase(T *_data, size_t _avail, size_t _size,
831 bool _autofree = false) :
832 WvBufBase<T>(& mystore),
833 mystore(sizeof(Elem), _data, _avail * sizeof(Elem),
834 _size * sizeof(Elem), _autofree) { }
837 * Creates a new empty circular buffer backed by a new array.
839 * "_size" is the size of the array
841 explicit WvCircularBufBase(size_t _size) :
842 WvBufBase<T>(& mystore),
843 mystore(sizeof(Elem), _size * sizeof(Elem)) { }
845 /** Creates a new empty buffer with no backing array. */
846 WvCircularBufBase() :
847 WvBufBase<T>(& mystore),
848 mystore(sizeof(Elem), NULL, 0, 0, false) { }
851 * Destroys the buffer.
853 * Frees the underlying array if autofree().
856 virtual ~WvCircularBufBase() { }
859 * Returns the underlying array pointer.
861 * Returns: the element pointer
863 T *ptr() const
865 return static_cast<T*>(mystore.ptr());
869 * Returns the total size of the buffer.
871 * Returns: the number of elements
873 size_t size() const
875 return mystore.size() / sizeof(Elem);
879 * Returns the autofree flag.
881 * Returns: the autofree flag
883 bool get_autofree() const
885 return mystore.get_autofree();
889 * Sets or clears the autofree flag.
891 * "_autofree" is if true, the array will be freed when discarded
893 void set_autofree(bool _autofree)
895 mystore.set_autofree(_autofree);
899 * Resets the underlying buffer pointer and properties.
901 * If the old and new buffer pointers differ and the old buffer
902 * was specified as autofree, the old buffer is destroyed.
904 * "_data" is the array of data to wrap
905 * "_avail" is the amount of data available for reading
906 * at the beginning of the buffer
907 * "_size" is the size of the array
908 * "_autofree" is if true, the array will be freed when discarded
910 void reset(T *_data, size_t _avail, size_t _size,
911 bool _autofree = false)
913 mystore.reset(_data, _avail * sizeof(Elem),
914 _size * sizeof(Elem), _autofree);
918 * Sets the amount of available data using the current buffer
919 * and resets the read index to the beginning of the buffer.
921 * "_avail" is the amount of data available for reading
922 * at the beginning of the buffer
924 void setavail(size_t _avail)
926 mystore.setavail(_avail * sizeof(Elem));
930 * Normalizes the arrangement of the data such that the
931 * contents of the buffer are stored at the beginning of
932 * the array starting with the next element that would be
933 * returned by get(size_t).
935 * After invocation, ungettable() may equal 0.
938 void normalize()
940 mystore.normalize();
947 * A buffer that dynamically grows and shrinks based on demand.
949 * "T" is the type of object to store, must be a primitive or a struct
950 * without special initialization, copy, or assignment semantics
952 template<class T>
953 class WvDynBufBase : public WvBufBase<T>
955 protected:
956 typedef T Elem;
958 WvDynBufStore mystore;
960 public:
962 * Creates a new buffer.
964 * Provides some parameters for tuning response to buffer
965 * growth.
967 * "_minalloc" is the minimum number of elements to allocate
968 * at once when creating a new internal buffer segment
969 * "_maxalloc" is the maximum number of elements to allocate
970 * at once when creating a new internal buffer segment
971 * before before reverting to a linear growth pattern
973 explicit WvDynBufBase(size_t _minalloc = 1024,
974 size_t _maxalloc = 1048576) :
975 WvBufBase<T>(& mystore),
976 mystore(sizeof(Elem), _minalloc * sizeof(Elem),
977 _maxalloc * sizeof(Elem)) { }
983 * A buffer that is always empty.
985 * "T" is the type of object to store, must be a primitive or a struct
986 * without special initialization, copy, or assignment semantics
988 template<class T>
989 class WvNullBufBase : public WvBufBase<T>
991 protected:
992 typedef T Elem;
994 WvNullBufStore mystore;
996 public:
997 /** Creates a new buffer. */
998 WvNullBufBase() :
999 WvBufBase<T>(& mystore),
1000 mystore(sizeof(Elem)) { }
1006 * A buffer that acts like a cursor over a portion of another buffer.
1007 * The underlying buffer's get() position is not affected by
1008 * reading from this buffer.
1010 * "T" is the type of object to store, must be a primitive or a struct
1011 * without special initialization, copy, or assignment semantics
1013 template<class T>
1014 class WvBufCursorBase : public WvBufBase<T>
1016 protected:
1017 typedef T Elem;
1019 WvBufCursorStore mystore;
1021 public:
1023 * Creates a new buffer.
1025 * Does not take ownership of the supplied buffer.
1028 * "_buf" is a pointer to the buffer to be wrapped
1029 * "_start" is the buffer offset of the window start position
1030 * "_length" is the length of the window
1032 WvBufCursorBase(WvBufBase<T> &_buf, int _start,
1033 size_t _length) :
1034 WvBufBase<T>(& mystore),
1035 mystore(sizeof(Elem), _buf.getstore(),
1036 _start * sizeof(Elem), _length * sizeof(Elem)) { }
1041 * A buffer that provides a read-write view over another buffer
1042 * with a different datatype. Reading and writing through this
1043 * buffer implicitly performs the equivalent of reinterpret_cast
1044 * on each element.
1046 * Most useful for manipulating data backed by a raw memory buffer.
1048 * "T" is the type of object to store, must be a primitive or a struct
1049 * without special initialization, copy, or assignment semantics
1051 template<class T>
1052 class WvBufViewBase : public WvBufBase<T>
1054 public:
1056 * Creates a new buffer.
1058 * Does not take ownership of the supplied buffer.
1061 * "_buf" is a pointer to the buffer to be wrapped
1063 template<typename S>
1064 WvBufViewBase(WvBufBase<S> &_buf) :
1065 WvBufBase<T>(_buf.getstore()) { }
1068 #endif // __WVBUFFERBASE_H