1 /* 2 Copyright (c) 2009 NetAllied Systems GmbH 3 4 This file is part of Common libBuffer. 5 6 Licensed under the MIT Open Source License, 7 for details please see LICENSE file or the website 8 http://www.opensource.org/licenses/mit-license.php 9 */ 10 11 #ifndef __COMMON_BUFFER_H__ 12 #define __COMMON_BUFFER_H__ 13 14 #include "CommonIBufferFlusher.h" 15 #include <string.h> 16 17 namespace Common 18 { 19 class Buffer 20 { 21 private: 22 /** Pointer to the buffer.*/ 23 char* mBuffer; 24 25 /** The size of the buffer.*/ 26 size_t mBufferSize; 27 28 /** Pointer to the first unused byte in the buffer.*/ 29 char* mCurrentPos; 30 31 /** Minimum size of data that will be flushed directly without copying to the buffer. The current buffer will 32 be flushed before. */ 33 size_t mDirectFlushSize; 34 35 /** Total number of bytes already passed to the flusher.*/ 36 size_t mBytesFlushed; 37 38 /** The flusher used to flush the buffer.*/ 39 IBufferFlusher* mFlusher; 40 41 bool mMarkSet; 42 43 bool mIsOverwriting; 44 45 public: 46 Buffer(size_t bufferSize, IBufferFlusher* flusher); 47 48 virtual ~Buffer(); 49 50 /** The flusher used to flush the buffer.*/ getFlusher()51 IBufferFlusher* getFlusher() const { return mFlusher; } 52 53 /** Flushes the to using the buffer flusher. 54 @return True on success, false otherwise. 55 @note Calling this method does not force to flusher to flush its data. To force this call flushFlusher instead.*/ 56 bool flushBuffer(); 57 58 /** Flushes the flusher. Call this to ensure that the data is really been handled by the flusher. 59 This method implicitly calls flushBuffer.*/ 60 bool flushFlusher(); 61 62 /** Copies @a length bytes into the buffer, starting at @a data .*/ 63 template<class T> 64 bool copyToBuffer( const T* data, size_t length); 65 66 /** Copies null terminated @a text into the buffer.*/ 67 bool copyToBuffer( const char* text); 68 69 /** Copies @a c into the buffer.*/ 70 template<class T> 71 bool copyToBuffer( const T& c); 72 getBufferSize()73 size_t getBufferSize() const { return mBufferSize; } 74 75 /** The number of bytes currently in the buffer.*/ 76 size_t getBytesUsed() const; 77 78 /** The number of bytes currently available in the buffer.*/ 79 size_t getBytesAvailable() const; 80 81 /** The number of bytes already copied to the buffer.*/ 82 size_t getBytesCopiedToBuffer() const; 83 84 /** @return True, if the buffer does not contain any data, false otherwise.*/ 85 size_t isEmpty() const; 86 87 /** Minimum size of data that will be flushed directly without copying to the buffer. The current buffer will 88 be flushed before. */ 89 size_t getDirectFlushSize() const; 90 91 /** Minimum size of data that will be flushed directly without copying to the buffer. The current buffer will 92 be flushed before. If @a directFlushSize is larger than the buffer size, the direct flush size will be set 93 to the buffer size. */ 94 void setDirectFlushSize(size_t directFlushSize); 95 96 /** 97 * Setting the start mark. 98 * @return True if start mark could be set, otherwise false. 99 */ 100 bool startMark(); 101 102 IBufferFlusher::MarkId endMark(); 103 104 bool jumpToMark(IBufferFlusher::MarkId markId, bool keepMarkId = false); 105 106 protected: 107 108 /** Provides access to the current position of the buffer for derived classes. Might be useful for 109 implementations that want to write into the buffer directly. Use increaseCurrentPosition to tell the buffer 110 how many bytes have been added to the buffer. Before writing into the buffer directly, use 111 getBytesAvailable to ensure there is enough space available.*/ getCurrentPosition()112 char* getCurrentPosition() { return mCurrentPos; } 113 114 /** Shifts the current position in the buffer by @a addedBytes bytes. No check is performed if the 115 new position is beyond the buffers end.*/ 116 void increaseCurrentPosition( size_t addedBytes); 117 118 /** Shifts the current position in the buffer by 1 byte. No check is performed if the 119 new position is beyond the buffers end.*/ 120 void increaseCurrentPosition(); 121 122 private: 123 /** Disable default copy ctor. */ 124 Buffer( const Buffer& pre ); 125 /** Disable default assignment operator. */ 126 const Buffer& operator= ( const Buffer& pre ); 127 128 bool sendDataToFlusher( const char* buffer, size_t length); 129 }; 130 131 132 //-------------------------------------------------------------------- 133 template<class T> copyToBuffer(const T * data,size_t length)134 bool Buffer::copyToBuffer( const T* data, size_t length ) 135 { 136 static const size_t typeSize = sizeof(T); 137 size_t arraySize = length * typeSize; 138 139 if ( arraySize >= mDirectFlushSize ) 140 { 141 // the data is large enough to flush directly 142 // flush the buffer first 143 if ( !flushBuffer() ) 144 { 145 // the buffer could not be flushed 146 return false; 147 } 148 149 // flush the new data directly 150 return sendDataToFlusher( (const char *)data, arraySize ); 151 } 152 153 if ( arraySize > getBytesAvailable() ) 154 { 155 // the new data does not fit into the buffer. We need to flush first. 156 if ( !flushBuffer() ) 157 { 158 // the buffer could not be flushed 159 return false; 160 } 161 } 162 163 // copy data into buffer. 164 memcpy( mCurrentPos, data, arraySize ); 165 mCurrentPos += arraySize; 166 return true; 167 } 168 169 //-------------------------------------------------------------------- 170 template<class T> copyToBuffer(const T & c)171 bool Buffer::copyToBuffer( const T& c ) 172 { 173 static const size_t typeSize = sizeof(T); 174 if ( mDirectFlushSize <= typeSize ) 175 { 176 // the data is large enough to flush directly 177 // flush the buffer first 178 if ( !flushBuffer() ) 179 { 180 // the buffer could not be flushed 181 return false; 182 } 183 184 // flush the new data directly 185 return sendDataToFlusher( (const char *)&c, typeSize ); 186 } 187 188 if ( getBytesAvailable() < typeSize) 189 { 190 // the new data does not fit into the buffer. We need to flush first. 191 if ( !flushBuffer() ) 192 { 193 // the buffer could not be flushed 194 return false; 195 } 196 } 197 198 // copy data into buffer. 199 T* typePos = (T*)mCurrentPos; 200 *typePos = c; 201 mCurrentPos += typeSize; 202 return true; 203 } 204 205 206 207 } // namespace COMMON 208 209 #endif // __COMMON_BUFFER_H__ 210