00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef Fennel_ByteBuffer_Included
00024 #define Fennel_ByteBuffer_Included
00025
00026 #include "fennel/common/CommonPreamble.h"
00027
00028 #include <boost/shared_array.hpp>
00029
00030 FENNEL_BEGIN_NAMESPACE
00031
00032 typedef uint8_t UnsignedByte;
00033
00048 class FENNEL_COMMON_EXPORT ByteBuffer
00049 {
00050 boost::shared_array<PBuffer> ppBuffers;
00051 uint nBuffers;
00052 uint bufferSize;
00053 uint bufferMask;
00054 uint bufferShift;
00055
00059 inline uint getI(uint pos)
00060 {
00061 uint i = pos >> bufferShift;
00062 assert(i < nBuffers);
00063 return i;
00064 }
00065
00069 inline uint getJ(uint pos)
00070 {
00071 uint j = pos & bufferMask;
00072 assert(j < bufferSize);
00073 return j;
00074 }
00075
00079 static void memmerge(PBuffer dest, PConstBuffer src, uint len)
00080 {
00081 PBuffer end = dest + len;
00082 while (dest < end) {
00083 *dest++ |= *src++;
00084 }
00085 }
00086
00087 public:
00088 explicit ByteBuffer();
00089
00093 void init(
00094 boost::shared_array<PBuffer> ppBuffers, uint nBuffers, uint bufSize);
00095
00099 uint getSize();
00100
00104 inline UnsignedByte getByte(uint pos)
00105 {
00106 return ppBuffers[getI(pos)][getJ(pos)];
00107 }
00108
00112 inline void setByte(uint pos, UnsignedByte b)
00113 {
00114 ppBuffers[getI(pos)][getJ(pos)] = b;
00115 }
00116
00120 inline void mergeByte(uint pos, UnsignedByte b)
00121 {
00122 ppBuffers[getI(pos)][getJ(pos)] |= b;
00123 }
00124
00131 inline PBuffer getMem(uint pos, uint &size)
00132 {
00133 size = bufferSize - getJ(pos);
00134 return &ppBuffers[getI(pos)][getJ(pos)];
00135 }
00136
00140 void setMem(uint pos, UnsignedByte value, uint len);
00141
00145 void copyMem(uint pos, PConstBuffer mem, uint len);
00146
00150 void mergeMem(uint pos, PConstBuffer mem, uint len);
00151 };
00152
00165 template <class IndexT>
00166 class ByteWindow
00167 {
00171 SharedByteBuffer pBuffer;
00172
00176 uint windowSize;
00177
00181 uint startOffset;
00182
00186 IndexT start;
00187
00191 IndexT end;
00192
00197 inline uint getOffset(IndexT index) const
00198 {
00199 assert(index >= start);
00200 assert(index < start + windowSize);
00201 uint pos = index - start + startOffset;
00202 if (pos >= windowSize) {
00203 pos -= windowSize;
00204 }
00205 return pos;
00206 }
00207
00212 inline uint getUnwrappedMemSize(IndexT index)
00213 {
00214 assert(start <= index && index <= start + windowSize);
00215 return windowSize - getOffset(index);
00216 }
00217
00218 public:
00222 void init(SharedByteBuffer pBuffer)
00223 {
00224 this->pBuffer = pBuffer;
00225 windowSize = pBuffer->getSize();
00226 reset();
00227 }
00228
00232 void reset()
00233 {
00234 startOffset = 0;
00235 start = end = 0;
00236 }
00237
00241 inline uint getCapacity() const
00242 {
00243 return windowSize;
00244 }
00245
00249 inline IndexT getStart() const
00250 {
00251 return start;
00252 }
00253
00257 inline IndexT getEnd() const
00258 {
00259 return end;
00260 }
00261
00265 inline IndexT getLimit()
00266 {
00267 return start + windowSize;
00268 }
00269
00273 PBuffer getMem(IndexT index, uint &size)
00274 {
00275 return pBuffer->getMem(getOffset(index), size);
00276 }
00277
00282 void advance(IndexT pos)
00283 {
00284 assert (pos >= start);
00285
00286
00287
00288 if (pos >= end) {
00289 startOffset = 0;
00290 end = pos;
00291 } else {
00292 startOffset = getOffset(pos);
00293 }
00294 start = pos;
00295 }
00296
00300 void advanceEnd(IndexT pos)
00301 {
00302 assert(pos > end);
00303 assert(pos <= getLimit());
00304
00305 uint len = pos - end;
00306 uint chunkSize = std::min(len, getUnwrappedMemSize(end));
00307 pBuffer->setMem(getOffset(end), 0, chunkSize);
00308 if (len > chunkSize) {
00309 pBuffer->setMem(0, 0, len - chunkSize);
00310 }
00311 end = pos;
00312 }
00313
00317 inline UnsignedByte getByte(IndexT index) const
00318 {
00319 assert(index >= start && index < end);
00320 return pBuffer->getByte(getOffset(index));
00321 }
00322
00326 void mergeByte(IndexT index, UnsignedByte val)
00327 {
00328 assert(index >= start);
00329 assert(index < getLimit());
00330 if (index >= end) {
00331 advanceEnd(index + 1);
00332 }
00333 pBuffer->mergeByte(getOffset(index), val);
00334 }
00335
00339 void mergeMem(IndexT index, PConstBuffer byteSeg, uint len)
00340 {
00341 assert(index >= start);
00342 assert(len < windowSize);
00343 assert(index + len <= getLimit());
00344 assert(len > 0);
00345
00346
00347 IndexT writeEnd = index + len;
00348 if (writeEnd > end) {
00349 advanceEnd(writeEnd);
00350 }
00351
00352 uint chunkSize = std::min(len, getUnwrappedMemSize(index));
00353 pBuffer->mergeMem(getOffset(index), byteSeg, chunkSize);
00354 if (len > chunkSize) {
00355 pBuffer->mergeMem(0, byteSeg + chunkSize, len - chunkSize);
00356 }
00357 }
00358 };
00359
00360 FENNEL_END_NAMESPACE
00361
00362 #endif
00363
00364