WvStreams
|
00001 /* -*- Mode: C++ -*- 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * Code to serialize objects into WvBufs, and more code to read WvBufs and 00006 * construct objects from them. 00007 */ 00008 #ifndef __WVSERIALIZE_H 00009 #define __WVSERIALIZE_H 00010 00011 #include "wvbuf.h" 00012 #include "wvstringlist.h" 00013 00014 #ifndef _WIN32 00015 # if HAVE_INTTYPES_H 00016 # include <inttypes.h> 00017 # else 00018 # if HAVE_STDINT_H 00019 # include <stdint.h> 00020 # endif 00021 # endif 00022 #include <netinet/in.h> 00023 #else 00024 #if _MSC_VER 00025 typedef __int8 int8_t; 00026 typedef unsigned __int8 uint8_t; 00027 typedef __int16 int16_t; 00028 typedef unsigned __int16 uint16_t; 00029 typedef __int32 int32_t; 00030 typedef unsigned __int32 uint32_t; 00031 typedef __int64 int64_t; 00032 typedef unsigned __int64 uint64_t; 00033 #endif 00034 #include <winsock2.h> 00035 #endif 00036 00043 template <typename T> 00044 inline void wv_serialize(WvBuf &buf, const T &t) 00045 { 00046 _wv_serialize(buf, t); 00047 } 00048 00049 00054 inline int32_t _wv_htonl(int32_t i) 00055 { 00056 return htonl(i); 00057 } 00058 inline int16_t _wv_htons(int16_t i) 00059 { 00060 return htons(i); 00061 } 00062 00066 inline uint64_t ntohll(uint64_t n) 00067 { 00068 #ifdef WORDS_BIGENDIAN 00069 return n; 00070 #else 00071 return (((uint64_t)ntohl(n)) << 32) | ntohl(n >> 32); 00072 #endif 00073 } 00074 00075 inline uint64_t htonll(uint64_t n) 00076 { 00077 #ifdef WORDS_BIGENDIAN 00078 return n; 00079 #else 00080 return (((uint64_t)htonl(n)) << 32) | htonl(n >> 32); 00081 #endif 00082 } 00083 00093 template <typename T> 00094 void wv_serialize_scalar(WvBuf &buf, const T t) 00095 { 00096 if (sizeof(T) == 8) 00097 { 00098 int64_t i = htonll(t); 00099 buf.put(&i, 8); 00100 } 00101 else if (sizeof(T) == 4) 00102 { 00103 int32_t i = _wv_htonl(t); 00104 buf.put(&i, 4); 00105 } 00106 else if (sizeof(T) == 2) 00107 { 00108 int32_t i = _wv_htons(t); 00109 buf.put(&i, 2); 00110 } 00111 else if (sizeof(T) == 1) 00112 buf.put(&t, 1); 00113 else 00114 assert(0); 00115 } 00116 00117 inline void _wv_serialize(WvBuf &buf, long long i) 00118 { wv_serialize_scalar(buf, i); } 00119 inline void _wv_serialize(WvBuf &buf, unsigned long long i) 00120 { wv_serialize_scalar(buf, i); } 00121 inline void _wv_serialize(WvBuf &buf, long i) 00122 { wv_serialize_scalar(buf, i); } 00123 inline void _wv_serialize(WvBuf &buf, unsigned long i) 00124 { wv_serialize_scalar(buf, i); } 00125 inline void _wv_serialize(WvBuf &buf, int i) 00126 { wv_serialize_scalar(buf, i); } 00127 inline void _wv_serialize(WvBuf &buf, unsigned int i) 00128 { wv_serialize_scalar(buf, i); } 00129 inline void _wv_serialize(WvBuf &buf, short i) 00130 { wv_serialize_scalar(buf, i); } 00131 inline void _wv_serialize(WvBuf &buf, unsigned short i) 00132 { wv_serialize_scalar(buf, i); } 00133 inline void _wv_serialize(WvBuf &buf, bool i) 00134 { wv_serialize_scalar(buf, i); } 00135 00137 inline void _wv_serialize(WvBuf &buf, char i) 00138 { wv_serialize_scalar(buf, i); } 00139 inline void _wv_serialize(WvBuf &buf, signed char i) 00140 { wv_serialize_scalar(buf, i); } 00141 inline void _wv_serialize(WvBuf &buf, unsigned char i) 00142 { wv_serialize_scalar(buf, i); } 00143 00144 00151 inline void _wv_serialize(WvBuf &buf, WvStringParm s) 00152 { 00153 if (!s.isnull()) 00154 buf.putstr(s); 00155 buf.put("", 1); // terminating nul 00156 } 00157 00159 inline void wv_serialize(WvBuf &buf, const char *t) 00160 { 00161 _wv_serialize(buf, t); 00162 } 00163 00164 00169 inline void _wv_serialize(WvBuf &buf, const WvBuf &inbuf) 00170 { 00171 wv_serialize(buf, inbuf.used()); 00172 buf.put(const_cast<WvBuf *>(&inbuf)->peek(0, inbuf.used()), inbuf.used()); 00173 } 00174 00175 00181 template <typename T> 00182 void _wv_serialize(WvBuf &buf, const WvList<T> &list) 00183 { 00184 // save the number of elements 00185 _wv_serialize(buf, (size_t)list.count()); 00186 00187 // save the elements 00188 typename WvList<T>::Iter i(list); 00189 for (i.rewind(); i.next(); ) 00190 _wv_serialize(buf, *i); 00191 } 00192 00193 00194 00196 template <typename T> 00197 T _wv_deserialize(WvBuf &buf); 00198 00199 00207 template <typename T> 00208 class WvDeserialize 00209 { 00210 public: 00211 static T go(WvBuf &buf) 00212 { return _wv_deserialize<T>(buf); } 00213 }; 00214 00215 00228 // note: this has to be a class because we use partial template 00229 // specialization, which doesn't work on functions. 00230 template <typename T> 00231 class WvDeserialize<T *> 00232 { 00233 public: 00234 static T *go(WvBuf &buf) 00235 { return new T(_wv_deserialize<T>(buf)); } 00236 }; 00237 00238 00239 00259 template <typename T> 00260 inline T wv_deserialize(WvBuf &buf) 00261 { 00262 return WvDeserialize<T>::go(buf); 00263 } 00264 00265 00270 inline int32_t _wv_ntohl(int32_t i) 00271 { 00272 return ntohl(i); 00273 } 00274 inline int16_t _wv_ntohs(int16_t i) 00275 { 00276 return ntohs(i); 00277 } 00278 00279 00285 template <typename T> 00286 inline T wv_deserialize_scalar(WvBuf &buf) 00287 { 00288 if (buf.used() < sizeof(T)) 00289 return 0; 00290 00291 if (sizeof(T) == 8) 00292 return (T) ntohll(*(int64_t *)buf.get(8)); 00293 else if (sizeof(T) == 4) 00294 return (T) _wv_ntohl(*(int32_t *)buf.get(4)); 00295 else if (sizeof(T) == 2) 00296 return (T) _wv_ntohs(*(int16_t *)buf.get(2)); 00297 else if (sizeof(T) == 1) 00298 return (T) *(int8_t *)buf.get(1); 00299 else 00300 assert(0); 00301 } 00302 00303 template <typename T> 00304 inline T xwv_deserialize_scalar(WvBuf &buf) 00305 { 00306 return 0; 00307 } 00308 00309 template <> 00310 inline long long _wv_deserialize<long long>(WvBuf &buf) 00311 { return wv_deserialize_scalar<long long>(buf); } 00312 template <> 00313 inline unsigned long long _wv_deserialize<unsigned long long>(WvBuf &buf) 00314 { return wv_deserialize_scalar<unsigned long long>(buf); } 00315 template <> 00316 inline long _wv_deserialize<long>(WvBuf &buf) 00317 { return wv_deserialize_scalar<long>(buf); } 00318 template <> 00319 inline unsigned long _wv_deserialize<unsigned long>(WvBuf &buf) 00320 { return wv_deserialize_scalar<unsigned long>(buf); } 00321 template <> 00322 inline int _wv_deserialize<int>(WvBuf &buf) 00323 { return wv_deserialize_scalar<int>(buf); } 00324 template <> 00325 inline unsigned int _wv_deserialize<unsigned int>(WvBuf &buf) 00326 { return wv_deserialize_scalar<unsigned int>(buf); } 00327 template <> 00328 inline short _wv_deserialize<short>(WvBuf &buf) 00329 { return wv_deserialize_scalar<short>(buf); } 00330 template <> 00331 inline unsigned short _wv_deserialize<unsigned short>(WvBuf &buf) 00332 { return wv_deserialize_scalar<unsigned short>(buf); } 00333 template <> 00334 inline bool _wv_deserialize<bool>(WvBuf &buf) 00335 { return wv_deserialize_scalar<bool>(buf); } 00336 template <> 00337 inline char _wv_deserialize<char>(WvBuf &buf) 00338 { return wv_deserialize_scalar<char>(buf); } 00339 template <> 00340 inline signed char _wv_deserialize<signed char>(WvBuf &buf) 00341 { return wv_deserialize_scalar<signed char>(buf); } 00342 template <> 00343 inline unsigned char _wv_deserialize<unsigned char>(WvBuf &buf) 00344 { return wv_deserialize_scalar<unsigned char>(buf); } 00345 00351 template <> 00352 WvString _wv_deserialize<WvString>(WvBuf &buf); 00353 00354 00356 // FIXME: it should be possible to do this without using a class! 00357 template <> 00358 class WvDeserialize<WvBuf *> 00359 { 00360 public: 00361 static WvBuf *go(WvBuf &buf) 00362 { 00363 size_t len = wv_deserialize<size_t>(buf); 00364 WvBuf *outbuf = new WvInPlaceBuf(new char[len], 0, len, true); 00365 outbuf->merge(buf, len); 00366 return outbuf; 00367 } 00368 }; 00369 00370 00372 template <typename T> 00373 class WvDeserialize<WvList<T> *> 00374 { 00375 public: 00376 static WvList<T> *go(WvBuf &buf) 00377 { 00378 WvList<T> *list = new WvList<T>; 00379 size_t nelems = wv_deserialize<size_t>(buf); 00380 00381 for (size_t count = 0; count < nelems; count++) 00382 { 00383 T t = wv_deserialize<T>(buf); 00384 list->append(new T(t), true); 00385 } 00386 00387 return list; 00388 } 00389 }; 00390 00391 template <> 00392 class WvDeserialize<WvStringList*> 00393 { 00394 public: 00395 static WvStringList *go(WvBuf &buf) 00396 { 00397 WvStringList *list = new WvStringList(); 00398 size_t nelems = wv_deserialize<size_t>(buf); 00399 00400 for (size_t count = 0; count < nelems; count++) 00401 { 00402 WvString str = wv_deserialize<WvString>(buf); 00403 list->append(str); 00404 } 00405 00406 return list; 00407 } 00408 }; 00409 00410 #endif // __WVSERIALIZE_H