00001 #ifndef CASTOR_ENCODING_CNER_H
00002 #define CASTOR_ENCODING_CNER_H 1
00003
00004 #include <sstream>
00005 #include <iostream>
00006
00007 #include "Encoding.h"
00008 #include "EncodingException.h"
00009
00010 namespace castor { namespace encoding {
00011
00012 class CNER : public Encoder, public Decoder {
00013
00014 private:
00015
00016 std::stringstream buffer;
00017
00018 bool doSwitchEndian;
00019
00020 bool marked;
00021 size_t marker;
00022
00023 size_t length;
00024
00025 inline void writeInternal(const char *data, size_t length, bool ignoreEndian = false) {
00026
00027 if (this->mode != encode) return;
00028
00029 if ((this->doSwitchEndian) && (!ignoreEndian)) {
00030
00031 if (length > 0) {
00032 char temp[length];
00033 for (int i = length - 1; i >= 0; i--) {
00034 temp[i] = data[(length - 1) - i];
00035 }
00036 this->buffer.write(temp, length);
00037
00038
00039 }
00040
00041 } else {
00042 this->buffer.write(data, length);
00043
00044
00045
00046
00047 }
00048 }
00049
00050 inline void readInternal(char *data, size_t length, bool ignoreEndian = false) {
00051
00052 if (this->mode != decode) return;
00053
00054 if ((this->doSwitchEndian) && (!ignoreEndian)) {
00055
00056 if (length > 0) {
00057 char temp[length];
00058 this->buffer.read(temp, length);
00059
00060 for (int i = length - 1; i >= 0; i--) {
00061 data[i] = temp[(length - 1) - i];
00062
00063 }
00064 }
00065
00066 } else {
00067 this->buffer.read(data, length);
00068
00069
00070
00071
00072 }
00073 }
00074
00075 enum { encode, decode } mode;
00076
00077 public:
00078
00079 CNER() :
00080 buffer(std::ios_base::out), doSwitchEndian(false),
00081 marked(false), marker(0), length(0), mode(encode)
00082 {
00083 }
00084
00085 CNER(const BytesPtr x, size_t offset) :
00086 buffer(std::string(x->begin() + offset, x->end()), std::ios_base::in),
00087 doSwitchEndian(false), marked(false), marker(0), length(x->size()), mode(decode)
00088 {
00089 }
00090
00091 CNER(const char *x, size_t length) :
00092 buffer(std::string(x, length), std::ios_base::in),
00093 doSwitchEndian(false), marked(false), marker(0), length(length), mode(decode)
00094 {
00095 }
00096
00097 CNER(const char *x, size_t offset, size_t length) :
00098 buffer(std::string(std::string(x, length), offset),
00099 std::ios_base::in),
00100 doSwitchEndian(false), marked(false), marker(0), length(length), mode(decode)
00101 {
00102 }
00103
00104 ~CNER() { }
00105
00106 inline EncoderPtr createEncoder() {
00107 return EncoderPtr(new CNER());
00108 }
00109
00110 inline DecoderPtr createDecoder(const BytesPtr x, size_t offset = 0) {
00111 return DecoderPtr(new CNER(x, offset));
00112 }
00113
00114 inline DecoderPtr createDecoder(const char *x, size_t length) {
00115 return DecoderPtr(new CNER(x, length));
00116 }
00117
00118 DecoderPtr createDecoder(const char *x, size_t offset, size_t length) {
00119 return DecoderPtr(new CNER(x, offset, length));
00120 }
00121
00122 inline void switchEndianness(bool yes) {
00123 this->doSwitchEndian = yes;
00124 }
00125
00126 inline size_t getLength() {
00127
00128 size_t length = 0;
00129
00130 if (this->mode == encode) {
00131
00132 size_t pos = this->buffer.tellp();
00133
00134 this->buffer.seekp(0, std::ios::end);
00135 length = this->buffer.tellp();
00136 this->buffer.seekp(pos, std::ios::beg);
00137
00138 } else {
00139
00140 size_t pos = this->buffer.tellg();
00141
00142 this->buffer.seekg(0, std::ios::end);
00143 length = this->buffer.tellg();
00144 this->buffer.seekg(pos, std::ios::beg);
00145 }
00146
00147 return length;
00148 }
00149
00150 inline size_t getPosition() {
00151 return (this->mode == encode ?
00152 this->buffer.tellp() :
00153 this->buffer.tellg());
00154 }
00155
00156 inline const char *getBuffer() {
00157 return this->buffer.str().c_str();
00158 }
00159
00160 inline BytesPtr getBytes() {
00161 std::string x = this->buffer.str();
00162 return BytesPtr(new Bytes(x.begin(), x.end()));
00163 }
00164
00165 inline void mark() {
00166 this->marked = true;
00167 this->marker = getPosition();
00168 }
00169
00170 inline void commit() {
00171 this->marked = false;
00172 this->marker = 0;
00173 }
00174
00175 inline void rollback() {
00176
00177 if (this->mode == encode) {
00178 this->buffer.seekp(this->marker, std::ios_base::beg);
00179 } else {
00180 this->buffer.seekg(this->marker, std::ios_base::beg);
00181 }
00182 this->marked = false;
00183 this->marker = 0;
00184 }
00185
00186 inline void reset() {
00187 if (this->mode == encode) {
00188 this->buffer.str("");
00189 } else {
00190 this->buffer.seekg(0, std::ios_base::beg);
00191 }
00192
00193 this->buffer.clear();
00194 this->marked = false;
00195 this->marker = 0;
00196 }
00197
00198 inline void seek(long offset) {
00199 if (this->mode == encode) {
00200 this->buffer.seekp(offset, std::ios_base::cur);
00201 } else {
00202 this->buffer.seekg(offset, std::ios_base::cur);
00203 }
00204 }
00205
00206 inline void encLength(size_t x) {
00207
00208 if (this->mode != encode) throw EncodingException("wanted to encode while being in decode mode");
00209
00210 if (x == 0) {
00211 this->buffer.put(0);
00212 return;
00213 }
00214
00215 while (x > 0) {
00216
00217
00218 char c = (char)(x & 0x7f);
00219
00220
00221 x >>= 7;
00222
00223
00224
00225
00226 this->buffer.put((x == 0 ? c : (c | 0x80)));
00227 }
00228 }
00229
00230 inline void encBool(bool x) {
00231 if (this->mode != encode) return;
00232 this->buffer.put((char)x);
00233 }
00234
00235 inline void encInt8(char x) {
00236 if (this->mode != encode) return;
00237 this->buffer.put(x);
00238 }
00239
00240 inline void encUInt8(unsigned char x) {
00241 if (this->mode != encode) return;
00242 this->buffer.put((char)x);
00243 }
00244
00245 inline void encInt16(short x) {
00246 writeInternal((char *)&x, 2);
00247 }
00248
00249 inline void encUInt16(unsigned short x) {
00250 writeInternal((char *)&x, 2);
00251 }
00252
00253 inline void encInt32(long x) {
00254 writeInternal((char *)&x, 4);
00255 }
00256
00257 inline void encUInt32(unsigned long x) {
00258 writeInternal((char *)&x, 4);
00259 }
00260
00261 inline void encInt64(long long x) {
00262 writeInternal((char *)&x, 8);
00263 }
00264
00265 inline void encUInt64(unsigned long long x) {
00266 writeInternal((char *)&x, 8);
00267 }
00268
00269 inline void encFloat(float x) {
00270 writeInternal((char *)&x, 4);
00271 }
00272
00273
00274
00275
00276 inline void encDouble(double x) {
00277 float y = (float)x;
00278 writeInternal((char *)&y, 4);
00279 }
00280
00281 inline void encString(const std::string x) {
00282 if (this->mode != encode) return;
00283 encLength(x.size());
00284 writeInternal(x.c_str(), x.size(), true);
00285 }
00286
00287 inline void encAddress(const castor::net::NetAddress &x) {
00288
00289 if (this->mode != encode) return;
00290 BytesPtr b = x.getBytes();
00291 encLength(b->size());
00292 writeInternal(&((*b)[0]), b->size(), true);
00293 }
00294
00295 inline void encBytes(const Bytes &x) {
00296 writeInternal(&x[0], x.size(), true);
00297 }
00298
00299 inline void encBytes(const Bytes &x, size_t offset, size_t length) {
00300 if (this->mode != encode) return;
00301
00302 if (length + offset > x.size()) {
00303 throw EncodingException("CNER: offset + length > x.size()");
00304 }
00305 writeInternal(&x[offset], length, true);
00306 }
00307
00308 inline void encBytes(const char *x, size_t length) {
00309 writeInternal(x, length, true);
00310 }
00311
00312 inline void encBytes(const char *x, size_t offset, size_t length) {
00313 writeInternal(&(x[offset]), length, true);
00314 }
00315
00316 inline size_t decLength() {
00317 if (this->mode != decode) return 0;
00318
00319 int bitsRead = 0;
00320 size_t result = 0;
00321 char c = 0;
00322
00323
00324 do {
00325
00326 c = this->buffer.get();
00327
00328
00329 if (bitsRead >= 64) {
00330 throw EncodingException("CNER: length field overflow (> 2^64)");
00331 }
00332
00333 result |= (static_cast<size_t>(c & 0x7f) << bitsRead);
00334 bitsRead += 7;
00335
00336
00337
00338 } while ((c & 0x80) != 0);
00339
00340 return result;
00341 }
00342
00343 inline bool decBool() {
00344 if (this->mode != decode) return false;
00345 return static_cast<bool>(this->buffer.get());
00346 }
00347
00348 inline char decInt8() {
00349 if (this->mode != decode) return 0;
00350 return this->buffer.get();
00351 }
00352
00353 inline unsigned char decUInt8() {
00354 if (this->mode != decode) return 0;
00355 return static_cast<unsigned char>(this->buffer.get());
00356 }
00357
00358 inline short decInt16() {
00359 short x = 0;
00360 readInternal((char *)&x, 2);
00361 return x;
00362 }
00363
00364 inline unsigned short decUInt16() {
00365 unsigned short x = 0;
00366 readInternal((char *)&x, 2);
00367 return x;
00368 }
00369
00370 inline long decInt32() {
00371 long x = 0;
00372 readInternal((char *)&x, 4);
00373 return x;
00374 }
00375
00376 inline unsigned long decUInt32() {
00377 unsigned long x = 0;
00378 readInternal((char *)&x, 4);
00379 return x;
00380 }
00381
00382 inline long long decInt64() {
00383 long long x = 0;
00384 readInternal((char *)&x, 8);
00385 return x;
00386 }
00387
00388 inline unsigned long long decUInt64() {
00389 unsigned long long x = 0;
00390 readInternal((char *)&x, 8);
00391 return x;
00392 }
00393
00394 inline float decFloat() {
00395 float x = 0;
00396 readInternal((char *)&x, 4);
00397 return x;
00398 }
00399
00400
00401
00402
00403
00404
00405 inline double decDouble() {
00406 float x = 0;
00407 readInternal((char *)&x, 4);
00408 return (double)x;
00409 }
00410
00411 inline std::string decString() {
00412 size_t length = decLength();
00413 char x[length];
00414 readInternal(x, length, true);
00415 return std::string(x, length);
00416 }
00417
00418 inline castor::net::NetAddress decAddress() {
00419 if (this->mode != decode) return castor::net::NetAddress();
00420
00421 size_t length = decLength();
00422 BytesPtr x(new Bytes(length, 0));
00423 readInternal(&((*x)[0]), length, true);
00424 return castor::net::NetAddress(x);
00425 }
00426
00427 inline BytesPtr decBytes(size_t length) {
00428 if (this->mode != decode) return BytesPtr();
00429 BytesPtr x(new Bytes(length, 0));
00430 readInternal(&((*x)[0]), length, true);
00431 return x;
00432 }
00433 };
00434
00435 } }
00436
00437 #endif
00438