WvStreams
wvbufstore.h
00001 /* -*- Mode: C++ -*-
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  *
00005  * Defines basic buffer storage classes.
00006  * These are not intended for use directly by clients.
00007  * See "wvbufbase.h" for the public API.
00008  */
00009 #ifndef __WVBUFFERSTORE_H
00010 #define __WVBUFFERSTORE_H
00011 
00012 #include "wvlinklist.h"
00013 #include <assert.h>
00014 #include <limits.h>
00015 #include <assert.h>
00016 
00023 #define UNLIMITED_FREE_SPACE (INT_MAX/2)
00024 
00026 class WvBufStore
00027 {
00028     // discourage copying
00029     explicit WvBufStore(const WvBufStore &other) { }
00030 
00031 protected:
00032     // the suggested granularity
00033     int granularity;
00034 
00040     explicit WvBufStore(int _granularity);
00041     
00042 public:
00043     virtual ~WvBufStore() { }
00044 
00045     /*** Buffer Reading ***/
00046     
00047     virtual bool isreadable() const
00048         { return true; }
00049     virtual size_t used() const = 0;
00050     virtual size_t optgettable() const
00051         { return used(); }
00052     virtual const void *get(size_t count) = 0;
00053     virtual void skip(size_t count)
00054         { get(count); }
00055     virtual void unget(size_t count) = 0;
00056     virtual size_t ungettable() const = 0;
00057     virtual size_t peekable(int offset) const;
00058     virtual size_t optpeekable(int offset) const
00059         { return peekable(offset); }
00060     virtual const void *peek(int offset, size_t count)
00061         { return mutablepeek(offset, count); }
00062     virtual void zap() = 0;
00063     
00064     // helpers
00065     void move(void *buf, size_t count);
00066     void copy(void *buf, int offset, size_t count);
00067     
00068     /*** Buffer Writing ***/
00069     
00070     virtual bool iswritable() const
00071         { return true; }
00072     virtual size_t free() const = 0;
00073     virtual size_t optallocable() const
00074         { return free(); }
00075     virtual void *alloc(size_t count) = 0;
00076     virtual void unalloc(size_t count) = 0;
00077     virtual size_t unallocable() const = 0;
00078     virtual void *mutablepeek(int offset, size_t count) = 0;
00079     
00080     // helpers
00081     void put(const void *data, size_t count);
00082     void fastput(const void *data, size_t count);
00083     void poke(const void *data, int offset, size_t count);
00084 
00085     /*** Buffer to Buffer Transfers ***/
00086 
00087     virtual void merge(WvBufStore &instore, size_t count);
00088 
00089     // default implementation
00090     void basicmerge(WvBufStore &instore, size_t count);
00091 
00092 protected:
00093     /*** Support for buffers with subbuffers ***/
00094 
00096     virtual bool usessubbuffers() const
00097         { return false; }
00098 
00100     virtual size_t numsubbuffers() const
00101         { return 0; }
00102 
00107     virtual WvBufStore *firstsubbuffer() const
00108         { return NULL; }
00109 
00111     virtual void appendsubbuffer(WvBufStore *buffer, bool autofree)
00112         { /*assert(! "not supported");*/ }
00113 
00115     virtual void prependsubbuffer(WvBufStore *buffer, bool autofree)
00116         { /*assert(! "not supported");*/ }
00117 
00123     virtual bool unlinksubbuffer(WvBufStore *buffer,
00124         bool allowautofree)
00125         { /*assert(! "not supported");*/ return true; }
00126 };
00127 
00128 // lists of buffer stores are sometimes useful
00129 DeclareWvList(WvBufStore);
00130 
00131 
00132 
00138 template<class Super>
00139 class WvReadOnlyBufferStoreMixin : public Super
00140 {
00141 public:
00142     explicit WvReadOnlyBufferStoreMixin(int _granularity) :
00143         Super(_granularity) { }
00144     virtual bool iswritable() const
00145     {
00146         return false;
00147     }
00148     virtual size_t free() const
00149     {
00150         return 0;
00151     }
00152     virtual size_t optallocable() const
00153     {
00154         return 0;
00155     }
00156     virtual void *alloc(size_t count)
00157     {
00158         assert(count == 0 ||
00159             ! "non-zero alloc() called on non-writable buffer");
00160         return NULL;
00161     }
00162     virtual void unalloc(size_t count)
00163     {
00164         assert(count == 0 ||
00165             ! "non-zero unalloc() called on non-writable buffer");
00166     }
00167     virtual size_t unallocable() const
00168     {
00169         return 0;
00170     }
00171     virtual void *mutablepeek(int offset, size_t count)
00172     {
00173         assert(count == 0 ||
00174             ! "mutablepeek() called on non-writable buffer");
00175         return NULL;
00176     }
00177     virtual void merge(WvBufStore &instore, size_t count)
00178     {
00179         assert(count == 0 ||
00180             ! "non-zero merge() called on non-writable buffer");
00181     }
00182 };
00183 
00184 
00185 
00190 template<class Super>
00191 class WvWriteOnlyBufferStoreMixin : public Super
00192 {
00193 public:
00194     explicit WvWriteOnlyBufferStoreMixin(int _granularity) :
00195         Super(_granularity) { }
00196     virtual bool isreadable() const
00197     {
00198         return false;
00199     }
00200     virtual size_t used() const
00201     {
00202         return 0;
00203     }
00204     virtual size_t optgettable() const
00205     {
00206         return 0;
00207     }
00208     virtual size_t peekable(int offset) const
00209     {
00210         return 0;
00211     }
00212     virtual size_t optpeekable(int offset) const
00213     {
00214         return 0;
00215     }
00216     virtual const void *get(size_t count)
00217     {
00218         assert(count == 0 ||
00219             ! "non-zero get() called on non-readable buffer");
00220         return NULL;
00221     }
00222     virtual void skip(size_t count)
00223     {
00224         assert(count == 0 ||
00225             ! "non-zero skip() called on non-readable buffer");
00226     }
00227     virtual void unget(size_t count)
00228     {
00229         assert(count == 0 ||
00230             ! "non-zero unget() called on non-readable buffer");
00231     }
00232     virtual size_t ungettable() const
00233     {
00234         return 0;
00235     }
00236     virtual const void *peek(int offset, size_t count)
00237     {
00238         assert(count == 0 ||
00239             ! "peek() called on non-readable buffer");
00240         return NULL;
00241     }
00242     virtual void zap()
00243     {
00244         // nothing to zap
00245     }
00246 };
00247 
00248 
00249 
00251 class WvInPlaceBufStore : public WvBufStore
00252 {
00253 protected:
00254     void *data;
00255     size_t xsize;
00256     size_t readidx;
00257     size_t writeidx;
00258     bool xautofree;
00259 
00260 public:
00261     WvInPlaceBufStore(int _granularity,
00262         void *_data, size_t _avail, size_t _size, bool _autofree);
00263     WvInPlaceBufStore(int _granularity, size_t _size);
00264     virtual ~WvInPlaceBufStore();
00265     void *ptr() const
00266         { return data; }
00267     size_t size() const
00268         { return xsize; }
00269     bool get_autofree() const
00270         { return xautofree; }
00271     void set_autofree(bool _autofree)
00272         { xautofree = _autofree; }
00273     void reset(void *_data, size_t _avail, size_t _size, bool _autofree);
00274     void setavail(size_t _avail);
00275     
00276     /*** Overridden Members ***/
00277     virtual size_t used() const;
00278     virtual const void *get(size_t count);
00279     virtual void unget(size_t count);
00280     virtual size_t ungettable() const;
00281     virtual void zap();
00282     virtual size_t free() const;
00283     virtual void *alloc(size_t count);
00284     virtual void unalloc(size_t count);
00285     virtual size_t unallocable() const;
00286     virtual void *mutablepeek(int offset, size_t count);
00287 };
00288 
00289 
00290 
00292 class WvConstInPlaceBufStore :
00293     public WvReadOnlyBufferStoreMixin<WvBufStore>
00294 {
00295 protected:
00296     const void *data;
00297     size_t avail;
00298     size_t readidx;
00299 
00300 public:
00301     WvConstInPlaceBufStore(int _granularity,
00302         const void *_data, size_t _avail);
00303     const void *ptr() const
00304         { return data; }
00305     void reset(const void *_data, size_t _avail);
00306     void setavail(size_t _avail);
00307 
00308     /*** Overridden Members ***/
00309     virtual size_t used() const;
00310     virtual const void *get(size_t count);
00311     virtual void unget(size_t count);
00312     virtual size_t ungettable() const;
00313     virtual const void *peek(int offset, size_t count);
00314     virtual void zap();
00315 };
00316 
00317 
00318 
00320 class WvCircularBufStore : public WvBufStore
00321 {
00322 protected:
00323     void *data;
00324     size_t xsize;
00325     size_t head;
00326     size_t totalused;
00327     size_t totalinit;
00328     bool xautofree;
00329 
00330 public:
00331     WvCircularBufStore(int _granularity,
00332         void *_data, size_t _avail, size_t _size, bool _autofree);
00333     WvCircularBufStore(int _granularity, size_t _size);
00334     virtual ~WvCircularBufStore();
00335     void *ptr() const
00336         { return data; }
00337     size_t size() const
00338         { return xsize; }
00339     bool get_autofree() const
00340         { return xautofree; }
00341     void set_autofree(bool _autofree)
00342         { xautofree = _autofree; }
00343     void reset(void *_data, size_t _avail, size_t _size, bool _autofree);
00344     void setavail(size_t _avail);
00345     void normalize();
00346     
00347     /*** Overridden Members ***/
00348     virtual size_t used() const;
00349     virtual size_t optgettable() const;
00350     virtual const void *get(size_t count);
00351     virtual void unget(size_t count);
00352     virtual size_t ungettable() const;
00353     virtual void zap();
00354     virtual size_t free() const;
00355     virtual size_t optallocable() const;
00356     virtual void *alloc(size_t count);
00357     virtual void unalloc(size_t count);
00358     virtual size_t unallocable() const;
00359     virtual void *mutablepeek(int offset, size_t count);
00360 
00361 protected:
00372     size_t ensurecontiguous(int offset, size_t count, bool keephistory);
00373 
00383     static void compact(void *data, size_t size,
00384         size_t head, size_t count);
00385 };
00386 
00387 
00388 
00401 class WvLinkedBufferStore : public WvBufStore
00402 {
00403 protected:
00404     WvBufStoreList list;
00405     size_t totalused;
00406     size_t maxungettable;
00407 
00408 public:
00409     explicit WvLinkedBufferStore(int _granularity);
00410 
00411     /*** Overridden Members ***/
00412     virtual size_t used() const;
00413     virtual size_t optgettable() const;
00414     virtual const void *get(size_t count);
00415     virtual void unget(size_t count);
00416     virtual size_t ungettable() const;
00417     virtual void zap();
00418     virtual size_t free() const;
00419     virtual size_t optallocable() const;
00420     virtual void *alloc(size_t count);
00421     virtual void unalloc(size_t count);
00422     virtual size_t unallocable() const;
00423     virtual size_t optpeekable(int offset) const;
00424     virtual void *mutablepeek(int offset, size_t count);
00425 
00426 protected:
00427     virtual bool usessubbuffers() const;
00428     virtual size_t numsubbuffers() const;
00429     virtual WvBufStore *firstsubbuffer() const;
00430     virtual void appendsubbuffer(WvBufStore *buffer, bool autofree);
00431     virtual void prependsubbuffer(WvBufStore *buffer, bool autofree);
00432     virtual bool unlinksubbuffer(WvBufStore *buffer,
00433         bool allowautofree);
00434 
00435 protected:
00442     virtual WvBufStore *newbuffer(size_t minsize);
00443 
00450     virtual void recyclebuffer(WvBufStore *buffer);
00451 
00460     int search(WvBufStoreList::Iter &it, int offset) const;
00461 
00469     WvBufStore *coalesce(WvBufStoreList::Iter &it,
00470         size_t count);
00471 
00472 private:
00473     // unlinks and recycles the buffer pointed at by the iterator
00474     void do_xunlink(WvBufStoreList::Iter &it);
00475 };
00476 
00477 
00478 
00480 class WvDynBufStore : public WvLinkedBufferStore
00481 {
00482     size_t minalloc;
00483     size_t maxalloc;
00484     
00485 public:
00486     WvDynBufStore(size_t _granularity,
00487         size_t _minalloc, size_t _maxalloc);
00488 
00489     /*** Overridden Members ***/
00490     virtual size_t free() const;
00491     virtual size_t optallocable() const;
00492     virtual void *alloc(size_t count);
00493 
00494 protected:
00495     virtual WvBufStore *newbuffer(size_t minsize);
00496 };
00497 
00498 
00499 
00501 class WvNullBufStore : public WvWriteOnlyBufferStoreMixin<
00502     WvReadOnlyBufferStoreMixin<WvBufStore> >
00503 {
00504 public:
00505     explicit WvNullBufStore(size_t _granularity);
00506 };
00507 
00508 
00509 
00511 class WvBufCursorStore :
00512     public WvReadOnlyBufferStoreMixin<WvBufStore>
00513 {
00514 protected:
00515     WvBufStore *buf;
00516     int start;
00517     size_t length;
00518     size_t shift;
00519 
00520 public:
00521     WvBufCursorStore(size_t _granularity, WvBufStore *_buf,
00522         int _start, size_t _length);
00523 
00524     /*** Overridden Members ***/
00525     virtual bool isreadable() const;
00526     virtual size_t used() const;
00527     virtual size_t optgettable() const;
00528     virtual const void *get(size_t count);
00529     virtual void skip(size_t count);
00530     virtual void unget(size_t count);
00531     virtual size_t ungettable() const;
00532     virtual size_t peekable(int offset) const;
00533     virtual size_t optpeekable(int offset) const;
00534     virtual const void *peek(int offset, size_t count);
00535     virtual void zap();
00536     virtual bool iswritable() const;
00537     virtual void *mutablepeek(int offset, size_t count);
00538 };
00539 
00540 #endif // __WVBUFFERSTORE_H