00001
00039 #ifndef CRL_MULTISENSE_BUFFERSTREAM_HH
00040 #define CRL_MULTISENSE_BUFFERSTREAM_HH
00041
00042 #include "Exception.hh"
00043 #include "TimeStamp.hh"
00044 #include "ReferenceCount.hh"
00045 #include "Portability.hh"
00046
00047 #include <stdint.h>
00048 #include <cstddef>
00049 #include <vector>
00050
00051 namespace crl {
00052 namespace multisense {
00053 namespace details {
00054 namespace utility {
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 class BufferStream {
00067 public:
00068
00069 void clear () { m_tell = 0; };
00070 std::size_t tell () const { return m_tell; };
00071 std::size_t size () const { return m_size; };
00072 void *data () const { return m_bufferP; };
00073 void *peek () const { return &(m_bufferP[m_tell]); };
00074
00075 #ifndef SENSORPOD_FIRMWARE
00076 bool shared() const { return m_ref.isShared(); };
00077 #endif // SENSORPOD_FIRMWARE
00078
00079 virtual void read (void *bufferP, std::size_t length) {
00080 CRL_EXCEPTION("not implemented");
00081 };
00082 virtual void write(const void *bufferP, std::size_t length) {
00083 CRL_EXCEPTION("not implemented");
00084 };
00085
00086
00087
00088
00089 void seek(std::size_t idx) {
00090
00091 if (idx > m_size)
00092 CRL_EXCEPTION("invalid seek location %d, [0, %d] valid\n",
00093 idx, m_size);
00094 m_tell = idx;
00095 };
00096
00097
00098
00099
00100 BufferStream() :
00101 m_alloced(false),
00102 m_size(0),
00103 m_tell(0),
00104 m_bufferP(NULL) {};
00105
00106
00107
00108
00109 BufferStream(std::size_t size) :
00110 m_alloced(false),
00111 m_size(size),
00112 m_tell(0),
00113 m_bufferP(NULL) {
00114
00115 m_bufferP = new (std::nothrow) uint8_t[size];
00116 if (NULL == m_bufferP)
00117 CRL_EXCEPTION("unable to allocate %d bytes", size);
00118 m_alloced = true;
00119 };
00120
00121
00122
00123
00124 BufferStream(uint8_t *bufP, std::size_t size) :
00125 m_alloced(false),
00126 m_size(size),
00127 m_tell(0),
00128 m_bufferP(bufP) {};
00129
00130
00131
00132
00133 virtual ~BufferStream() {
00134 #ifdef SENSORPOD_FIRMWARE
00135 if (m_alloced)
00136 #else
00137 if (m_alloced && false == m_ref.isShared())
00138 #endif
00139 delete[] m_bufferP;
00140 };
00141
00142
00143
00144
00145 BufferStream(const BufferStream& source) {
00146 m_alloced = source.m_alloced;
00147 m_size = source.m_size;
00148 m_tell = 0;
00149 m_bufferP = source.m_bufferP;
00150
00151 #ifndef SENSORPOD_FIRMWARE
00152 m_ref = source.m_ref;
00153 #endif // SENSORPOD_FIRMWARE
00154 };
00155
00156 protected:
00157
00158 bool m_alloced;
00159 std::size_t m_size;
00160 std::size_t m_tell;
00161 uint8_t *m_bufferP;
00162
00163 #ifndef SENSORPOD_FIRMWARE
00164 ReferenceCount m_ref;
00165 #endif // SENSORPOD_FIRMWARE
00166 };
00167
00168
00169
00170
00171
00172 class BufferStreamReader : public BufferStream {
00173 public:
00174
00175 BufferStreamReader() : BufferStream() {};
00176 BufferStreamReader(BufferStream& s) : BufferStream(s) {};
00177 BufferStreamReader(const uint8_t *p, std::size_t s) : BufferStream(const_cast<uint8_t*>(p), s) {};
00178 BufferStreamReader(std::size_t s) : BufferStream(s) {};
00179
00180 virtual void read (void *bufferP, std::size_t length) {
00181
00182 if (length > (m_size - m_tell))
00183 CRL_EXCEPTION("read overflow: tell=%d, size=%d, length=%d\n",
00184 m_tell, m_size, length);
00185
00186 memcpy(bufferP, &(m_bufferP[m_tell]), length);
00187 m_tell += length;
00188 };
00189
00190 template <typename T> BufferStreamReader& operator&(T &value) {
00191 this->read(&value, sizeof(T));
00192 return *this;
00193 };
00194
00195 template <typename T> BufferStreamReader& operator&(std::vector<T>& v) {
00196 uint16_t version;
00197 uint32_t num;
00198 *this & version;
00199 *this & num;
00200 v.resize(num);
00201 for(uint32_t i=0; i<num; i++)
00202 v[i].serialize(*this, version);
00203 return *this;
00204 }
00205
00206 BufferStreamReader& operator&(std::string& value) {
00207 uint16_t length;
00208
00209 this->read(&length, sizeof(length));
00210 if (length > 512)
00211 CRL_EXCEPTION("unusually large string: %d bytes",
00212 length);
00213 else if (length > 0) {
00214 char buffer[512+1];
00215 buffer[length] = '\0';
00216 this->read(buffer, length);
00217 value = std::string(buffer);
00218 }
00219 return *this;
00220 };
00221
00222 BufferStreamReader& operator&(TimeStamp& value) {
00223 uint32_t seconds;
00224 uint32_t microseconds;
00225
00226 this->read(&seconds, sizeof(seconds));
00227 this->read(µseconds, sizeof(microseconds));
00228
00229 value = seconds + 1e-6 * microseconds;
00230
00231 return *this;
00232 };
00233 };
00234
00235
00236
00237
00238
00239 class BufferStreamWriter : public BufferStream {
00240 public:
00241
00242 BufferStreamWriter() : BufferStream() {};
00243 BufferStreamWriter(BufferStream& s) : BufferStream(s) {};
00244 BufferStreamWriter(uint8_t *b, std::size_t s) : BufferStream(b, s) {};
00245 BufferStreamWriter(std::size_t s) : BufferStream(s) {};
00246
00247 virtual void write(const void *bufferP, std::size_t length) {
00248
00249 if ((length + m_tell) > m_size)
00250 CRL_EXCEPTION("write overflow: tell=%d, size=%d, length=%d\n",
00251 m_tell, m_size, length);
00252
00253 memcpy(&(m_bufferP[m_tell]), bufferP, length);
00254 m_tell += length;
00255 };
00256
00257 template <typename T> BufferStreamWriter& operator&(const T& value) {
00258 this->write(&value, sizeof(T));
00259 return *this;
00260 };
00261
00262 template <typename T> BufferStreamWriter& operator&(const std::vector<T>& v) {
00263 uint16_t version = T::VERSION;
00264 uint32_t num = v.size();
00265 *this & version;
00266 *this & num;
00267 for(uint32_t i=0; i<num; i++)
00268 const_cast<T*>(&v[i])->serialize(*this, version);
00269 return *this;
00270 }
00271
00272 BufferStreamWriter& operator&(const std::string& value) {
00273 uint16_t length = value.size();
00274
00275 if (length > 512)
00276 CRL_EXCEPTION("unusually large string: %d bytes", length);
00277
00278 this->write(&length, sizeof(length));
00279 if (length > 0)
00280 this->write(value.c_str(), length);
00281 return *this;
00282 };
00283
00284 BufferStreamWriter& operator&(const TimeStamp& value) {
00285 const uint32_t seconds = value.getSeconds();
00286 const uint32_t microseconds = value.getMicroSeconds();
00287
00288 this->write(&seconds, sizeof(seconds));
00289 this->write(µseconds, sizeof(microseconds));
00290
00291 return *this;
00292 };
00293 };
00294
00295 }}}}
00296
00297 #endif