26 memcpy(target, source, count);
29 inline void copy(
void *target,
const void *source,
size_t count)
32 memcpy(target, source, count);
41 memmove(target, source, count);
45 inline void swap(
void *target,
void *source,
size_t count)
47 register unsigned char *t1 = (
unsigned char*)target;
48 register unsigned char *t2 = (
unsigned char*)source;
51 register unsigned char temp;
58 inline void uninit(
void *target,
size_t count)
64 return new unsigned char[count];
69 deletev (
unsigned char*)buf;
74inline size_t roundup(
size_t value,
size_t boundary)
76 size_t mod = value % boundary;
77 return mod ? value + boundary - mod : value;
84WvBufStore::WvBufStore(
int _granularity) :
85 granularity(_granularity)
90size_t WvBufStore::peekable(
int offset)
const
98 if (
size_t(-offset) <= ungettable())
99 return size_t(-offset) + used();
103 int avail = int(used()) - offset;
111void WvBufStore::move(
void *buf,
size_t count)
115 size_t amount = count;
116 assert(amount != 0 ||
117 !
"attempted to move() more than used()");
120 const void *data = get(amount);
122 buf = (
unsigned char*)buf + amount;
128void WvBufStore::copy(
void *buf,
int offset,
size_t count)
132 size_t amount = optpeekable(offset);
133 assert(amount != 0 ||
134 !
"attempted to copy() with invalid offset");
137 const void *data = peek(offset, amount);
139 buf = (
unsigned char*)buf + amount;
146void WvBufStore::put(
const void *data,
size_t count)
150 size_t amount = optallocable();
151 assert(amount != 0 ||
152 !
"attempted to put() more than free()");
155 void *buf = alloc(amount);
157 data = (
const unsigned char*)data + amount;
163void WvBufStore::fastput(
const void *data,
size_t count)
165 void *buf = alloc(count);
170void WvBufStore::poke(
const void *data,
int offset,
size_t count)
172 int limit = int(used());
173 assert(offset <= limit ||
174 !
"attempted to poke() beyond end of buffer");
175 int end = offset + count;
178 size_t tail = end - limit;
180 put((
const unsigned char*)data + count, tail);
184 size_t amount = optpeekable(offset);
185 assert(amount != 0 ||
186 !
"attempted to poke() with invalid offset");
189 void *buf = mutablepeek(offset, amount);
190 memops.
copy(buf, data, amount);
191 data = (
const unsigned char*)data + amount;
198void WvBufStore::merge(
WvBufStore &instore,
size_t count)
212 size_t avail = buf->used();
225 basicmerge(instore, count);
229void WvBufStore::basicmerge(
WvBufStore &instore,
size_t count)
234 const void *indata = NULL;
235 void *outdata = NULL;
242 inavail = instore.optgettable();
243 assert(inavail != 0 ||
244 !
"attempted to merge() more than instore.used()");
247 indata = instore.get(inavail);
251 outavail = optallocable();
252 assert(outavail != 0 ||
253 !
"attempted to merge() more than free()");
254 if (outavail > count)
256 outdata = alloc(outavail);
258 if (inavail < outavail)
268 outdata = (
unsigned char*)outdata + inavail;
275 if (count == 0)
return;
277 indata = (
const unsigned char*)indata + outavail;
287WvInPlaceBufStore::WvInPlaceBufStore(
int _granularity,
288 void *_data,
size_t _avail,
size_t _size,
bool _autofree) :
291 reset(_data, _avail, _size, _autofree);
295WvInPlaceBufStore::WvInPlaceBufStore(
int _granularity,
size_t _size) :
298 reset(memops.
newarray(_size), 0, _size,
true);
302WvInPlaceBufStore::~WvInPlaceBufStore()
304 if (data && xautofree)
309void WvInPlaceBufStore::reset(
void *_data,
size_t _avail,
310 size_t _size,
bool _autofree =
false)
312 assert(_data != NULL || _avail == 0);
313 if (data && _data != data && xautofree)
316 xautofree = _autofree;
322void WvInPlaceBufStore::setavail(
size_t _avail)
324 assert(_avail <= xsize);
330size_t WvInPlaceBufStore::used()
const
332 return writeidx - readidx;
336const void *WvInPlaceBufStore::get(
size_t count)
338 assert(count <= writeidx - readidx ||
339 !
"attempted to get() more than used()");
340 const void *tmpptr = (
const unsigned char*)data + readidx;
346void WvInPlaceBufStore::unget(
size_t count)
348 assert(count <= readidx ||
349 !
"attempted to unget() more than ungettable()");
354size_t WvInPlaceBufStore::ungettable()
const
360void WvInPlaceBufStore::zap()
362 readidx = writeidx = 0;
366size_t WvInPlaceBufStore::free()
const
368 return xsize - writeidx;
372void *WvInPlaceBufStore::alloc(
size_t count)
374 assert(count <= xsize - writeidx ||
375 !
"attempted to alloc() more than free()");
376 void *tmpptr = (
unsigned char*)data + writeidx;
382void WvInPlaceBufStore::unalloc(
size_t count)
384 assert(count <= writeidx - readidx ||
385 !
"attempted to unalloc() more than unallocable()");
390size_t WvInPlaceBufStore::unallocable()
const
392 return writeidx - readidx;
396void *WvInPlaceBufStore::mutablepeek(
int offset,
size_t count)
400 assert(((offset <= 0) ?
401 size_t(-offset) <= readidx :
402 size_t(offset) < writeidx - readidx) ||
403 !
"attempted to peek() with invalid offset or count");
404 return (
unsigned char*)data + readidx + offset;
411WvConstInPlaceBufStore::WvConstInPlaceBufStore(
int _granularity,
412 const void *_data,
size_t _avail) :
415 reset(_data, _avail);
419void WvConstInPlaceBufStore::reset(
const void *_data,
size_t _avail)
421 assert(_data != NULL || _avail == 0);
427size_t WvConstInPlaceBufStore::used()
const
429 return avail - readidx;
433void WvConstInPlaceBufStore::setavail(
size_t _avail)
440const void *WvConstInPlaceBufStore::get(
size_t count)
442 assert(count <= avail - readidx ||
443 !
"attempted to get() more than used()");
444 const void *ptr = (
const unsigned char*)data + readidx;
450void WvConstInPlaceBufStore::unget(
size_t count)
452 assert(count <= readidx ||
453 !
"attempted to unget() more than ungettable()");
458size_t WvConstInPlaceBufStore::ungettable()
const
464const void *WvConstInPlaceBufStore::peek(
int offset,
size_t count)
468 assert(((offset <= 0) ?
469 size_t(-offset) <= readidx :
470 size_t(offset) < avail - readidx) ||
471 !
"attempted to peek() with invalid offset or count");
472 return (
const unsigned char*)data + readidx + offset;
476void WvConstInPlaceBufStore::zap()
485WvCircularBufStore::WvCircularBufStore(
int _granularity,
486 void *_data,
size_t _avail,
size_t _size,
bool _autofree) :
489 reset(_data, _avail, _size, _autofree);
493WvCircularBufStore::WvCircularBufStore(
int _granularity,
size_t _size) :
496 reset(memops.
newarray(_size), 0, _size,
true);
500WvCircularBufStore::~WvCircularBufStore()
502 if (data && xautofree)
507void WvCircularBufStore::reset(
void *_data,
size_t _avail,
508 size_t _size,
bool _autofree =
false)
510 assert(_data != NULL || _avail == 0);
511 if (data && _data != data && xautofree)
514 xautofree = _autofree;
520void WvCircularBufStore::setavail(
size_t _avail)
522 assert(_avail <= xsize);
524 totalused = totalinit = _avail;
528size_t WvCircularBufStore::used()
const
534size_t WvCircularBufStore::optgettable()
const
536 size_t avail = xsize - head;
537 if (avail > totalused)
543const void *WvCircularBufStore::get(
size_t count)
545 assert(count <= totalused ||
546 !
"attempted to get() more than used()");
548 const void *tmpptr = (
const unsigned char*)data + first;
549 head = (head + count) % xsize;
555void WvCircularBufStore::unget(
size_t count)
557 assert(count <= totalinit - totalused ||
558 !
"attempted to unget() more than ungettable()");
559 head = (head + xsize - count) % xsize;
564size_t WvCircularBufStore::ungettable()
const
566 return totalinit - totalused;
570void WvCircularBufStore::zap()
573 totalused = totalinit = 0;
577size_t WvCircularBufStore::free()
const
579 return xsize - totalused;
583size_t WvCircularBufStore::optallocable()
const
585 size_t tail = head + totalused;
587 return xsize - totalused;
592void *WvCircularBufStore::alloc(
size_t count)
594 assert(count <= xsize - totalused ||
595 !
"attempted to alloc() more than free()");
596 totalinit = totalused;
599 void *tmpptr = (
unsigned char*)data + first;
606void WvCircularBufStore::unalloc(
size_t count)
608 assert(count <= totalused ||
609 !
"attempted to unalloc() more than unallocable()");
615size_t WvCircularBufStore::unallocable()
const
621void *WvCircularBufStore::mutablepeek(
int offset,
size_t count)
625 assert(((offset <= 0) ?
626 size_t(-offset) <= totalinit - totalused :
627 size_t(offset) < totalused) ||
628 !
"attempted to peek() with invalid offset or count");
631 void *tmpptr = (
unsigned char*)data + first;
636void WvCircularBufStore::normalize()
639 totalinit = totalused;
642 compact(data, xsize, head, totalused);
648 size_t count,
bool keephistory)
651 size_t start = (head + offset + xsize) % xsize;
654 size_t end = start + count;
659 size_t keepstart = head;
663 keepstart += totalused - totalinit + xsize;
668 totalinit = totalused;
673 compact(data, xsize, keepstart, totalinit);
674 head = totalinit - totalused;
677 start = (head + offset + xsize) % xsize;
685 size_t head,
size_t count)
694 if (head + count <= size)
698 memops.
uninit_move(data, (
unsigned char*)data + head, count);
702 size_t headcount = size - head;
703 size_t tailcount = count - headcount;
704 size_t freecount = size - count;
705 if (freecount >= headcount)
709 memops.
uninit_move((
unsigned char*)data + headcount,
711 memops.
uninit_move(data, (
unsigned char*)data + head,
718 unsigned char *start = (
unsigned char*)data;
719 unsigned char *end = (
unsigned char*)data + head;
720 while (tailcount >= headcount)
722 memops.
swap(start, end, headcount);
724 tailcount -= headcount;
728 void *buf = memops.
newarray(tailcount);
731 memops.
uninit_move(start + headcount, buf, tailcount);
739WvLinkedBufferStore::WvLinkedBufferStore(
int _granularity) :
740 WvBufStore(_granularity), totalused(0), maxungettable(0)
766 list.append(buffer, autofree);
767 totalused += buffer->used();
774 list.prepend(buffer, autofree);
775 totalused += buffer->used();
783 WvBufStoreList::Iter it(list);
784 WvLink *link = it.find(buffer);
787 bool autofree = it.get_autofree();
788 totalused -= buffer->used();
789 if (buffer == list.first())
792 it.set_autofree(
false);
798size_t WvLinkedBufferStore::used()
const
800 assert(!totalused || !list.isempty());
805size_t WvLinkedBufferStore::optgettable()
const
809 WvBufStoreList::Iter it(list);
810 for (it.rewind(); it.next(); )
811 if ((count = it->optgettable()) != 0)
817const void *WvLinkedBufferStore::get(
size_t count)
819 assert(!totalused || !list.isempty());
823 assert(count <= totalused);
828 assert(totalused >= 0);
833 WvBufStoreList::Iter it(list);
836 it.rewind(); it.next();
838 assert(buf &&
"attempted to get() more than used()" &&
839 "totalused is wrong!");
841 availused = buf->used();
850 if (availused < count)
853 maxungettable += count;
854 return buf->get(count);
858void WvLinkedBufferStore::unget(
size_t count)
860 assert(!totalused || !list.isempty());
864 assert(!list.isempty());
865 assert(count <= maxungettable);
867 maxungettable -= count;
868 list.first()->unget(count);
872size_t WvLinkedBufferStore::ungettable()
const
874 assert(!totalused || !list.isempty());
877 assert(maxungettable == 0);
889 size_t avail = list.first()->ungettable();
890 if (avail > maxungettable)
891 avail = maxungettable;
896void WvLinkedBufferStore::zap()
900 WvBufStoreList::Iter it(list);
901 for (it.rewind(); it.next(); )
906size_t WvLinkedBufferStore::free()
const
909 return list.last()->free();
914size_t WvLinkedBufferStore::optallocable()
const
917 return list.last()->optallocable();
922void *WvLinkedBufferStore::alloc(
size_t count)
926 assert(!list.isempty() &&
"attempted to alloc() more than free()");
928 return list.last()->alloc(count);
932void WvLinkedBufferStore::unalloc(
size_t count)
934 assert(count <= totalused);
939 assert(!list.isempty() &&
940 "attempted to unalloc() more than unallocable()" &&
941 "totalused is wrong");
943 size_t avail = buf->unallocable();
950 WvBufStoreList::Iter it(list);
959size_t WvLinkedBufferStore::unallocable()
const
965size_t WvLinkedBufferStore::optpeekable(
int offset)
const
968 WvBufStoreList::Iter it(list);
969 int newoffset =
search(it, offset);
973 return buf->optpeekable(newoffset);
977void *WvLinkedBufferStore::mutablepeek(
int offset,
size_t count)
983 WvBufStoreList::Iter it(list);
984 offset =
search(it, offset);
986 assert(buf &&
"attempted to peek() with invalid offset or count");
989 size_t availpeek = buf->peekable(offset);
990 if (availpeek < count)
992 return buf->mutablepeek(offset, count);
998 minsize = roundup(minsize, granularity);
1020 if (
size_t(-offset) <= buf->ungettable())
1030 size_t avail = buf->used();
1031 if (
size_t(offset) < avail)
1046 size_t availused = buf->used();
1047 if (count <= availused)
1051 size_t needed = count - availused;
1052 size_t availfree = buf->free();
1053 size_t mustskip = 0;
1054 if (availfree < needed)
1059 if (buf == list.first() && totalused != 0)
1064 mustskip = ungettable();
1065 buf->unget(mustskip);
1068 needed = count + mustskip;
1072 list.add_after(it.prev, buf,
true);
1080 size_t chunk = itbuf->used();
1085 buf->merge(*itbuf, chunk);
1089 buf->skip(mustskip);
1095 assert(
false &&
"invalid count during get() or peek()");
1100void WvLinkedBufferStore::do_xunlink(WvBufStoreList::Iter &it)
1103 if (buf == list.first())
1106 bool autofree = it.get_autofree();
1107 it.set_autofree(
false);
1117WvDynBufStore::WvDynBufStore(
size_t _granularity,
1118 size_t _minalloc,
size_t _maxalloc) :
1120 minalloc(_minalloc), maxalloc(_maxalloc)
1122 assert(maxalloc >= minalloc);
1126size_t WvDynBufStore::free()
const
1128 return UNLIMITED_FREE_SPACE;
1132size_t WvDynBufStore::optallocable()
const
1134 size_t avail = WvLinkedBufferStore::optallocable();
1136 avail = UNLIMITED_FREE_SPACE;
1141void *WvDynBufStore::alloc(
size_t count)
1143 if (count > WvLinkedBufferStore::free())
1148 return WvLinkedBufferStore::alloc(count);
1157 size_t size = used();
1158 if (size < minsize * 2)
1160 if (size < minalloc)
1162 else if (size > maxalloc)
1173WvNullBufStore::WvNullBufStore(
size_t _granularity) :
1183WvBufCursorStore::WvBufCursorStore(
size_t _granularity,
1184 WvBufStore *_buf,
int _start,
size_t _length) :
1186 buf(_buf), start(_start), length(_length), shift(0)
1191bool WvBufCursorStore::isreadable()
const
1193 return buf->isreadable();
1197size_t WvBufCursorStore::used()
const
1199 return length - shift;
1203size_t WvBufCursorStore::optgettable()
const
1205 size_t avail = buf->optpeekable(start + shift);
1206 assert(avail != 0 || length == shift ||
1207 !
"buffer cursor operating over invalid region");
1214const void *WvBufCursorStore::get(
size_t count)
1216 assert(count <= length - shift ||
1217 !
"attempted to get() more than used()");
1218 const void *data = buf->peek(start + shift, count);
1224void WvBufCursorStore::skip(
size_t count)
1226 assert(count <= length - shift ||
1227 !
"attempted to skip() more than used()");
1232void WvBufCursorStore::unget(
size_t count)
1234 assert(count <= shift ||
1235 !
"attempted to unget() more than ungettable()");
1240size_t WvBufCursorStore::ungettable()
const
1246void WvBufCursorStore::zap()
1252size_t WvBufCursorStore::peekable(
int offset)
const
1256 if (offset < 0 || offset >
int(length))
1258 return length - size_t(offset);
1262size_t WvBufCursorStore::optpeekable(
int offset)
const
1264 size_t avail = buf->optpeekable(start + shift + offset);
1265 assert(avail != 0 || length == shift ||
1266 !
"buffer cursor operating over invalid region");
1267 size_t max = peekable(offset);
1274const void *WvBufCursorStore::peek(
int offset,
size_t count)
1277 assert((offset >= start && offset - start + count <= length) ||
1278 !
"attempted to peek() with invalid offset or count");
1279 return buf->peek(offset, count);
1283bool WvBufCursorStore::iswritable()
const
1286 return buf->iswritable();
1290void *WvBufCursorStore::mutablepeek(
int offset,
size_t count)
1293 assert((offset >= start && offset - start + count <= length) ||
1294 !
"attempted to peek() with invalid offset or count");
1295 return buf->mutablepeek(offset, count);
The abstract buffer storage base class.
virtual bool usessubbuffers() const
Returns true if the buffer uses subbuffers for storage.
virtual void appendsubbuffer(WvBufStore *buffer, bool autofree)
Appends a subbuffer to the buffer.
virtual WvBufStore * firstsubbuffer() const
Returns the first subbuffer.
virtual bool unlinksubbuffer(WvBufStore *buffer, bool allowautofree)
Unlinks the specified subbuffer.
The WvCircularBuf storage class.
size_t ensurecontiguous(int offset, size_t count, bool keephistory)
Ensures that count new bytes can be read from or written to the buffer beginning at the specified off...
static void compact(void *data, size_t size, size_t head, size_t count)
Compacts an array arranged as a circular buffer such that the specified region is moved to the beginn...
virtual WvBufStore * newbuffer(size_t minsize)
Called when a new buffer must be allocated to coalesce chunks.
WvLink is one element of a WvList<T>.
The WvLinkedBuffer storage class.
virtual WvBufStore * newbuffer(size_t minsize)
Called when a new buffer must be allocated to coalesce chunks.
virtual void prependsubbuffer(WvBufStore *buffer, bool autofree)
Prepends a subbuffer to the buffer.
int search(WvBufStoreList::Iter &it, int offset) const
Searches for the buffer containing the offset.
virtual bool usessubbuffers() const
Returns true if the buffer uses subbuffers for storage.
virtual void recyclebuffer(WvBufStore *buffer)
Called when a buffer with autofree is removed from the list.
virtual void appendsubbuffer(WvBufStore *buffer, bool autofree)
Appends a subbuffer to the buffer.
virtual bool unlinksubbuffer(WvBufStore *buffer, bool allowautofree)
Unlinks the specified subbuffer.
virtual size_t numsubbuffers() const
Returns the number of subbuffers in the buffer.
WvBufStore * coalesce(WvBufStoreList::Iter &it, size_t count)
Coalesces a sequence of buffers.
virtual WvBufStore * firstsubbuffer() const
Returns the first subbuffer.
A statically bound mixin template for buffer implementations that are read-only.
A statically bound mixin template for buffer implementations that are write-only.
An abstraction for memory transfer operations.
void deletearray(void *buf)
Deletes an uninitialized array.
void swap(void *target, void *source, size_t count)
Swaps initialized regions.
void copy(void *target, const void *source, size_t count)
Copies initialized region to initialized region.
void uninit(void *target, size_t count)
Uninitializes a region.
void uninit_move(void *target, void *source, size_t count)
Moves initialized region to uninitialized region.
void * newarray(size_t count)
Creates a new array.
void uninit_copy(void *target, const void *source, size_t count)
Copies initialized region to uninitialized region.