WvStreams
wvserialize.h
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