00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef __SERIALIZABLE_H
00034 #define __SERIALIZABLE_H
00035
00036 #include <inttypes.h>
00037 #include "m_net.h"
00038 #include <string>
00039 #include <sstream>
00040 #include <iostream>
00041 #include <typeinfo>
00042 #include <ctype.h>
00043
00044 #include <boost/lexical_cast.hpp>
00045 #include <boost/concept_check.hpp>
00046 #include "Exception.h"
00047 #include "massert.h"
00048
00056 static inline bool _DO_BYTE_SWAP() { return (1 != htonl(1)); }
00057
00058 #if 0
00059 #define htonll(t) \
00060 { \
00061 uint32_t low_h = t & 0xffffffff; \
00062 uint32_t low_n = htonl(low_h); \
00063 if (low_h == low_n) { t; } \
00064 else {uint32_t high_h = t >> 32; \
00065 uint32_t high_n = htonl(high_h); \
00066 uint64_t t_n = low_n; \
00067 t_n = (t_n << 32) + high_n; \
00068 } \
00069 }
00070 #endif
00071
00073 inline uint64_t htonll(const uint64_t& t) {
00074 if (!_DO_BYTE_SWAP()) {
00075 return t;
00076 }
00077 uint32_t low_h = t & 0xffffffff;
00078 uint32_t low_n = htonl(low_h);
00079 uint32_t high_h = t >> 32;
00080 uint32_t high_n = htonl(high_h);
00081 uint64_t t_n = low_n;
00082 t_n = (t_n << 32) + high_n;
00083 return t_n;
00084 }
00085
00086 #if 0
00087 #define ntohll(t) \
00088 { \
00089 uint32_t low_n = t & 0xffffffff; \
00090 uint32_t low_h = ntohl(low_n); \
00091 if (low_h == low_n) { t; } \
00092 else {uint32_t high_n = t >> 32; \
00093 uint32_t high_h = ntohl(high_n); \
00094 uint64_t t_h = low_h; \
00095 t_h = (t_h << 32) + high_h; \
00096 } \
00097 }
00098 #endif
00099
00101 inline uint64_t ntohll(const uint64_t& t) {
00102 if (!_DO_BYTE_SWAP()) {
00103 return t;
00104 }
00105 uint32_t low_n = t & 0xffffffff;
00106 uint32_t low_h = ntohl(low_n);
00107 uint32_t high_n = t >> 32;
00108 uint32_t high_h = ntohl(high_n);
00109 uint64_t t_h = low_h;
00110 t_h = (t_h << 32) + high_h;
00111 return t_h;
00112 }
00113
00114
00115 using std::istream;
00116 using std::istringstream;
00117 using std::skipws;
00118
00119
00120
00121 namespace mace {
00122
00123
00124
00126 class Serializer { };
00127
00129 class SoftState : public Serializer {};
00130
00132 class SerializationException : public Exception {
00133 public:
00134 SerializationException(const std::string& m) : Exception(m) { }
00135 virtual void rethrow() const { throw *this; }
00136 };
00137
00138
00144
00145 class SerializationUtil {
00146 public:
00148 static std::string getTag(istream& in, bool strict = true)
00149 throw(SerializationException) {
00150 std::string ret("<");
00151 char ch;
00152
00153 expect(in, '<');
00154 in.get(ch);
00155 while(in && ch != '>' && (!strict || (isalnum(ch) || ch == '/' || ch == '_'))) {
00156
00157 ret.push_back(ch);
00158 in.get(ch);
00159 }
00160 if(!in) {
00161 throw SerializationException("EOF while deserializing tag: " + ret);
00162 }
00163 if (ch != '>') {
00164 std::string err = "Invalid character in tag " + ret + ": ";
00165 err.push_back(ch);
00166 throw SerializationException(err);
00167 }
00168 ret.push_back('>');
00169
00170
00171 return ret;
00172 }
00173
00175 static void expectTag(istream& in, const char* tag)
00176 throw(SerializationException) {
00177
00178 while (in && isspace(in.peek())) {
00179 in.get();
00180 }
00181
00182 expect(in, tag);
00183 }
00184
00186 static std::string get(istream& in, char delim) throw(SerializationException) {
00187 std::string ret = "";
00188 char ch;
00189
00190 while(in) {
00191 in.get(ch);
00192 if(ch != delim)
00193 ret += ch;
00194 else {
00195 in.unget();
00196 return ret;
00197 }
00198 }
00199 throw SerializationException("EOF while looking for delimeter " + delim);
00200 }
00201
00203 static void expect(istream& in, const char* str)
00204 throw(SerializationException) {
00205 unsigned len = strlen(str);
00206
00207
00208 char* buf = new char[len];
00209 in.read(buf, len);
00210
00211
00212 if(!in || strncmp(buf, str, len) != 0) {
00213 delete [] buf;
00214 std::string errstr = "error parsing string: ";
00215 if (!in) {
00216 errstr += "could not read " + boost::lexical_cast<std::string>(len) +
00217 " bytes, expecting ";
00218 errstr.append(str);
00219 }
00220 else {
00221 errstr.append(str);
00222 errstr += " != ";
00223 errstr.append(buf, len);
00224 }
00225 throw SerializationException(errstr);
00226 }
00227 delete [] buf;
00228 }
00229
00231 static void expect(istream& in, const std::string& str)
00232 throw(SerializationException) {
00233 expect(in, str.c_str());
00234 }
00235
00237 template<typename S>
00238 static void expect(istream& in, const S& val) throw(SerializationException) {
00239 S v;
00240
00241 in >> v;
00242 if (!in || v != val) {
00243 std::string errstr = "error parsing token " +
00244 boost::lexical_cast<std::string>(val) + ": ";
00245 if (!in) {
00246 errstr += "EOF";
00247 }
00248 else {
00249 errstr += "parsed " + boost::lexical_cast<std::string>(v);
00250 }
00251
00252 throw SerializationException(errstr);
00253 }
00254 }
00255
00257 template<typename S>
00258 static void getToken(istream& in, S& val) throw(SerializationException) {
00259 in >> val;
00260 if (!in) {
00261 throw SerializationException("error parsing token " +
00262 boost::lexical_cast<std::string>(val));
00263 }
00264 }
00265
00266 };
00267
00270
00271 class Serializable : public Serializer {
00272 public:
00274 virtual int deserialize(std::istream& in) throw(SerializationException) = 0;
00276 virtual void serialize(std::string& str) const = 0;
00278
00279
00280
00281 virtual std::string serializeStr() const {
00282 std::string s;
00283 serialize(s);
00284 return s;
00285 }
00287 virtual void deserializeStr(const std::string& s) throw(SerializationException) {
00288 std::istringstream is(s);
00289 deserialize(is);
00290 }
00291
00293 virtual int deserializeXML_RPC(std::istream& in) throw(SerializationException);
00295 virtual void serializeXML_RPC(std::string& str) const throw(SerializationException);
00296
00297 virtual ~Serializable() {}
00298 };
00299
00301 inline Serializable* getSerializable(void* pitem) {
00302 return NULL;
00303 }
00305 inline Serializable* getSerializable(Serializable* pitem) {
00306 return pitem;
00307 }
00309 inline const Serializable* getSerializable(const void* pitem) {
00310 return NULL;
00311 }
00313 inline const Serializable* getSerializable(const Serializable* pitem) {
00314 return pitem;
00315 }
00316 inline const std::string* getSerializableString(const void* pitem) {
00317 return NULL;
00318 }
00319 inline const std::string* getSerializableString(const std::string* pitem) {
00320 return pitem;
00321 }
00322 inline std::string* getSerializableString(void* pitem) {
00323 return NULL;
00324 }
00325 inline std::string* getSerializableString(std::string* pitem) {
00326 return pitem;
00327 }
00328
00329
00330
00331
00332
00334 inline void serialize(std::string& str, const Serializable* pitem) {
00335 pitem->serialize(str);
00336 }
00337
00339 inline void serialize(std::string& str, const uint8_t* pitem) {
00340 str.append((char*)pitem, sizeof(uint8_t));
00341 }
00343 inline void serialize(std::string& str, const uint16_t* pitem) {
00344 uint16_t tmp = htons(*pitem);
00345 str.append((char*)&tmp, sizeof(tmp));
00346 }
00348 inline void serialize(std::string& str, const uint32_t* pitem) {
00349 uint32_t tmp = htonl(*pitem);
00350 str.append((char*)&tmp, sizeof(tmp));
00351 }
00353 inline void serialize(std::string& str, const uint64_t* pitem) {
00354 uint64_t tmp = htonll(*pitem);
00355 str.append((char*)&tmp, sizeof(tmp));
00356 }
00357
00359 inline void serialize(std::string& str, const int8_t* pitem) {
00360 str.append((char*)pitem, sizeof(int8_t));
00361 }
00363 inline void serialize(std::string& str, const int16_t* pitem) {
00364 int16_t tmp = htons(*pitem);
00365 str.append((char*)&tmp, sizeof(tmp));
00366 }
00368 inline void serialize(std::string& str, const int32_t* pitem) {
00369 int32_t tmp = htonl(*pitem);
00370 str.append((char*)&tmp, sizeof(tmp));
00371 }
00373 inline void serialize(std::string& str, const int64_t* pitem) {
00374 int64_t tmp = htonll(*pitem);
00375 str.append((char*)&tmp, sizeof(tmp));
00376 }
00377
00379 inline void serialize(std::string& str, const bool* pitem) {
00380 uint8_t tmp = *pitem;
00381 serialize(str, &tmp);
00382 }
00383
00386 inline void serialize(std::string& str, const float* pitem) {
00387 str.append((char*)pitem, sizeof(float));
00388 }
00391 inline void serialize(std::string& str, const double* pitem) {
00392 str.append((char*)pitem, sizeof(double));
00393 }
00395 inline void serialize(std::string &str, const std::string* pitem) {
00396 uint32_t sz = (uint32_t)pitem->size();
00397 mace::serialize(str, &sz);
00398 if (sz > 0) {
00399 str.append(pitem->data(), sz);
00400 }
00401 }
00402
00403
00405 inline int deserialize(std::istream& in, Serializable* pitem) throw(SerializationException) {
00406 return pitem->deserialize(in);
00407 }
00408
00410 inline int deserialize(std::istream& in, int8_t* pitem) throw(SerializationException) {
00411 in.read((char *)pitem, sizeof(int8_t));
00412 if (!in) {
00413 throw SerializationException("could not read " +
00414 boost::lexical_cast<std::string>(sizeof(int8_t)) + " bytes");
00415 }
00416 return sizeof(int8_t);
00417 }
00419 inline int deserialize(std::istream& in, int16_t* pitem) throw(SerializationException) {
00420 in.read((char *)pitem, sizeof(int16_t));
00421 if (!in) {
00422 throw SerializationException("could not read " +
00423 boost::lexical_cast<std::string>(sizeof(int16_t)) + " bytes");
00424 }
00425 *pitem = ntohs(*pitem);
00426 return sizeof(int16_t);
00427 }
00429 inline int deserialize(std::istream& in, int32_t* pitem) throw(SerializationException) {
00430 in.read((char *)pitem, sizeof(int32_t));
00431 if (!in) {
00432 throw SerializationException("could not read " +
00433 boost::lexical_cast<std::string>(sizeof(int32_t)) + " bytes");
00434 }
00435 *pitem = ntohl(*pitem);
00436 return sizeof(int32_t);
00437 }
00439 inline int deserialize(std::istream& in, int64_t* pitem) throw(SerializationException) {
00440 in.read((char *)pitem, sizeof(int64_t));
00441 if (!in) {
00442 throw SerializationException("could not read " +
00443 boost::lexical_cast<std::string>(sizeof(int64_t)) + " bytes");
00444 }
00445 *pitem = ntohll(*pitem);
00446 return sizeof(int64_t);
00447 }
00448
00450 inline int deserialize(std::istream& in, uint8_t* pitem) throw(SerializationException) {
00451 in.read((char *)pitem, sizeof(uint8_t));
00452 if (!in) {
00453 throw SerializationException("could not read " +
00454 boost::lexical_cast<std::string>(sizeof(uint8_t)) + " bytes");
00455 }
00456 return sizeof(uint8_t);
00457 }
00459 inline int deserialize(std::istream& in, uint16_t* pitem) throw(SerializationException) {
00460 in.read((char *)pitem, sizeof(uint16_t));
00461 if (!in) {
00462 throw SerializationException("could not read " +
00463 boost::lexical_cast<std::string>(sizeof(uint16_t)) + " bytes");
00464 }
00465 *pitem = ntohs(*pitem);
00466 return sizeof(uint16_t);
00467 }
00469 inline int deserialize(std::istream& in, uint32_t* pitem) throw(SerializationException) {
00470 in.read((char *)pitem, sizeof(uint32_t));
00471 if (!in) {
00472 throw SerializationException("could not read " +
00473 boost::lexical_cast<std::string>(sizeof(uint32_t)) + " bytes");
00474 }
00475 *pitem = ntohl(*pitem);
00476 return sizeof(uint32_t);
00477 }
00479 inline int deserialize(std::istream& in, uint64_t* pitem) throw(SerializationException) {
00480 in.read((char *)pitem, sizeof(uint64_t));
00481 if (!in) {
00482 throw SerializationException("could not read " +
00483 boost::lexical_cast<std::string>(sizeof(uint64_t)) + " bytes");
00484 }
00485 *pitem = ntohll(*pitem);
00486 return sizeof(uint64_t);
00487 }
00488
00490 inline int deserialize(std::istream& in, bool* pitem) throw(SerializationException) {
00491 int8_t tmp;
00492 deserialize(in, &tmp);
00493 *pitem = tmp;
00494 return sizeof(int8_t);
00495 }
00496
00499 inline int deserialize(std::istream& in, float* pitem) throw(SerializationException) {
00500 in.read((char *)pitem, sizeof(float));
00501 if (!in) {
00502 throw SerializationException("could not read " +
00503 boost::lexical_cast<std::string>(sizeof(float)) + " bytes");
00504 }
00505 return sizeof(float);
00506 }
00509 inline int deserialize(std::istream& in, double* pitem) throw(SerializationException) {
00510 in.read((char *)pitem, sizeof(double));
00511 if (!in) {
00512 throw SerializationException("could not read " +
00513 boost::lexical_cast<std::string>(sizeof(double)) + " bytes");
00514 }
00515 return sizeof(double);
00516 }
00518 inline int deserialize(std::istream& in, std::string* pitem) throw(SerializationException){
00519 uint32_t sz;
00520 char* buf;
00521 mace::deserialize(in, &sz);
00522 if (sz == 0) {
00523 pitem->clear();
00524 return sizeof(sz);
00525 }
00526 buf = new char[sz];
00527 if (buf == NULL) {
00528 throw SerializationException("Could not allocate memory to deserialize");
00529 }
00530
00531 in.read(buf, sz);
00532 if (!in) {
00533 throw SerializationException("String not long enough to deserialize");
00534 }
00535 pitem->assign(buf, sz);
00536 delete [] buf;
00537 return sizeof(sz) + sz;
00538 }
00539
00540
00542 template<typename S> int deserializeStr(const std::string& str, S* pitem) {
00543 std::istringstream in(str);
00544 return mace::deserialize(in, pitem);
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554
00556 template<typename S> std::string serialize(const S* pitem) {
00557 const std::string* sptr = getSerializableString(pitem);
00558 if (sptr != NULL) {
00559 return *sptr;
00560 }
00561 const Serializable* tmp = getSerializable(pitem);
00562 if (tmp == NULL) {
00563 std::string str;
00564 serialize(str, pitem);
00565 return str;
00566 }
00567 else {
00568 return tmp->serializeStr();
00569 }
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00588 template<typename S> void deserialize(const std::string& s, S* pitem) throw(SerializationException) {
00589 std::string* sptr = getSerializableString(pitem);
00590 if (sptr != NULL) {
00591 sptr->assign(s);
00592 return;
00593 }
00594 Serializable* tmp = getSerializable(pitem);
00595 if (tmp == NULL) {
00596 deserializeStr(s, pitem);
00597 }
00598 else {
00599 tmp->deserializeStr(s);
00600 }
00601 }
00602
00604 template<typename S> void serializeMap(std::string& str, const S& s) {
00605 uint32_t sz = (uint32_t)s.size();
00606 mace::serialize(str, &sz);
00607 for(typename S::const_iterator i=s.begin(); i!=s.end(); i++) {
00608 mace::serialize(str, &(i->first));
00609 mace::serialize(str, &(i->second));
00610 }
00611 }
00613 template<typename S> int deserializeMap(std::istream& in, S& s) throw(SerializationException) {
00614 typename S::key_type k;
00615 uint32_t sz;
00616 int bytes = sizeof(sz);
00617
00618 s.clear();
00619 mace::deserialize(in, &sz);
00620 for (uint64_t i = 0; i < sz; i++) {
00621 bytes += mace::deserialize(in, &k);
00622 bytes += mace::deserialize(in, s[k]);
00623 }
00624 return bytes;
00625 }
00626
00628 template<typename T> class SerializeConcept {
00629 public:
00630 void constraints() {
00631 std::string s;
00632 T t;
00633 serialize(s, &t);
00634 std::istringstream in(s);
00635 deserialize(in, &t);
00636 }
00637 };
00638
00639 }
00640 #endif