WvStreams
wvserialize.h
1 /* -*- Mode: C++ -*-
2  * Worldvisions Weaver Software:
3  * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4  *
5  * Code to serialize objects into WvBufs, and more code to read WvBufs and
6  * construct objects from them.
7  */
8 #ifndef __WVSERIALIZE_H
9 #define __WVSERIALIZE_H
10 
11 #include "wvbuf.h"
12 #include "wvstringlist.h"
13 
14 #ifndef _WIN32
15 # if HAVE_INTTYPES_H
16 # include <inttypes.h>
17 # else
18 # if HAVE_STDINT_H
19 # include <stdint.h>
20 # endif
21 # endif
22 #include <netinet/in.h>
23 #else
24 #if _MSC_VER
25 typedef __int8 int8_t;
26 typedef unsigned __int8 uint8_t;
27 typedef __int16 int16_t;
28 typedef unsigned __int16 uint16_t;
29 typedef __int32 int32_t;
30 typedef unsigned __int32 uint32_t;
31 typedef __int64 int64_t;
32 typedef unsigned __int64 uint64_t;
33 #endif
34 #include <winsock2.h>
35 #endif
36 
43 template <typename T>
44 inline void wv_serialize(WvBuf &buf, const T &t)
45 {
46  _wv_serialize(buf, t);
47 }
48 
49 
54 inline int32_t _wv_htonl(int32_t i)
55 {
56  return htonl(i);
57 }
58 inline int16_t _wv_htons(int16_t i)
59 {
60  return htons(i);
61 }
62 
66 inline uint64_t ntohll(uint64_t n)
67 {
68 #ifdef WORDS_BIGENDIAN
69  return n;
70 #else
71  return (((uint64_t)ntohl(n)) << 32) | ntohl(n >> 32);
72 #endif
73 }
74 
75 inline uint64_t htonll(uint64_t n)
76 {
77 #ifdef WORDS_BIGENDIAN
78  return n;
79 #else
80  return (((uint64_t)htonl(n)) << 32) | htonl(n >> 32);
81 #endif
82 }
83 
93 template <typename T>
94 void wv_serialize_scalar(WvBuf &buf, const T t)
95 {
96  if (sizeof(T) == 8)
97  {
98  int64_t i = htonll(t);
99  buf.put(&i, 8);
100  }
101  else if (sizeof(T) == 4)
102  {
103  int32_t i = _wv_htonl(t);
104  buf.put(&i, 4);
105  }
106  else if (sizeof(T) == 2)
107  {
108  int32_t i = _wv_htons(t);
109  buf.put(&i, 2);
110  }
111  else if (sizeof(T) == 1)
112  buf.put(&t, 1);
113  else
114  assert(0);
115 }
116 
117 inline void _wv_serialize(WvBuf &buf, long long i)
118  { wv_serialize_scalar(buf, i); }
119 inline void _wv_serialize(WvBuf &buf, unsigned long long i)
120  { wv_serialize_scalar(buf, i); }
121 inline void _wv_serialize(WvBuf &buf, long i)
122  { wv_serialize_scalar(buf, i); }
123 inline void _wv_serialize(WvBuf &buf, unsigned long i)
124  { wv_serialize_scalar(buf, i); }
125 inline void _wv_serialize(WvBuf &buf, int i)
126  { wv_serialize_scalar(buf, i); }
127 inline void _wv_serialize(WvBuf &buf, unsigned int i)
128  { wv_serialize_scalar(buf, i); }
129 inline void _wv_serialize(WvBuf &buf, short i)
130  { wv_serialize_scalar(buf, i); }
131 inline void _wv_serialize(WvBuf &buf, unsigned short i)
132  { wv_serialize_scalar(buf, i); }
133 inline void _wv_serialize(WvBuf &buf, bool i)
134  { wv_serialize_scalar(buf, i); }
135 
137 inline void _wv_serialize(WvBuf &buf, char i)
138  { wv_serialize_scalar(buf, i); }
139 inline void _wv_serialize(WvBuf &buf, signed char i)
140  { wv_serialize_scalar(buf, i); }
141 inline void _wv_serialize(WvBuf &buf, unsigned char i)
142  { wv_serialize_scalar(buf, i); }
143 
144 
151 inline void _wv_serialize(WvBuf &buf, WvStringParm s)
152 {
153  if (!s.isnull())
154  buf.putstr(s);
155  buf.put("", 1); // terminating nul
156 }
157 
159 inline void wv_serialize(WvBuf &buf, const char *t)
160 {
161  _wv_serialize(buf, t);
162 }
163 
164 
169 inline void _wv_serialize(WvBuf &buf, const WvBuf &inbuf)
170 {
171  wv_serialize(buf, inbuf.used());
172  buf.put(const_cast<WvBuf *>(&inbuf)->peek(0, inbuf.used()), inbuf.used());
173 }
174 
175 
181 template <typename T>
182 void _wv_serialize(WvBuf &buf, const WvList<T> &list)
183 {
184  // save the number of elements
185  _wv_serialize(buf, (size_t)list.count());
186 
187  // save the elements
188  typename WvList<T>::Iter i(list);
189  for (i.rewind(); i.next(); )
190  _wv_serialize(buf, *i);
191 }
192 
193 
194 
196 template <typename T>
197  T _wv_deserialize(WvBuf &buf);
198 
199 
207 template <typename T>
209 {
210 public:
211  static T go(WvBuf &buf)
212  { return _wv_deserialize<T>(buf); }
213 };
214 
215 
228 // note: this has to be a class because we use partial template
229 // specialization, which doesn't work on functions.
230 template <typename T>
231 class WvDeserialize<T *>
232 {
233 public:
234  static T *go(WvBuf &buf)
235  { return new T(_wv_deserialize<T>(buf)); }
236 };
237 
238 
239 
259 template <typename T>
260 inline T wv_deserialize(WvBuf &buf)
261 {
262  return WvDeserialize<T>::go(buf);
263 }
264 
265 
270 inline int32_t _wv_ntohl(int32_t i)
271 {
272  return ntohl(i);
273 }
274 inline int16_t _wv_ntohs(int16_t i)
275 {
276  return ntohs(i);
277 }
278 
279 
285 template <typename T>
286 inline T wv_deserialize_scalar(WvBuf &buf)
287 {
288  if (buf.used() < sizeof(T))
289  return 0;
290 
291  if (sizeof(T) == 8)
292  return (T) ntohll(*(int64_t *)buf.get(8));
293  else if (sizeof(T) == 4)
294  return (T) _wv_ntohl(*(int32_t *)buf.get(4));
295  else if (sizeof(T) == 2)
296  return (T) _wv_ntohs(*(int16_t *)buf.get(2));
297  else if (sizeof(T) == 1)
298  return (T) *(int8_t *)buf.get(1);
299  else
300  assert(0);
301 }
302 
303 template <typename T>
304 inline T xwv_deserialize_scalar(WvBuf &buf)
305 {
306  return 0;
307 }
308 
309 template <>
310  inline long long _wv_deserialize<long long>(WvBuf &buf)
311  { return wv_deserialize_scalar<long long>(buf); }
312 template <>
313  inline unsigned long long _wv_deserialize<unsigned long long>(WvBuf &buf)
314  { return wv_deserialize_scalar<unsigned long long>(buf); }
315 template <>
316  inline long _wv_deserialize<long>(WvBuf &buf)
317  { return wv_deserialize_scalar<long>(buf); }
318 template <>
319  inline unsigned long _wv_deserialize<unsigned long>(WvBuf &buf)
320  { return wv_deserialize_scalar<unsigned long>(buf); }
321 template <>
322  inline int _wv_deserialize<int>(WvBuf &buf)
323  { return wv_deserialize_scalar<int>(buf); }
324 template <>
325  inline unsigned int _wv_deserialize<unsigned int>(WvBuf &buf)
326  { return wv_deserialize_scalar<unsigned int>(buf); }
327 template <>
328  inline short _wv_deserialize<short>(WvBuf &buf)
329  { return wv_deserialize_scalar<short>(buf); }
330 template <>
331  inline unsigned short _wv_deserialize<unsigned short>(WvBuf &buf)
332  { return wv_deserialize_scalar<unsigned short>(buf); }
333 template <>
334  inline bool _wv_deserialize<bool>(WvBuf &buf)
335  { return wv_deserialize_scalar<bool>(buf); }
336 template <>
337  inline char _wv_deserialize<char>(WvBuf &buf)
338  { return wv_deserialize_scalar<char>(buf); }
339 template <>
340  inline signed char _wv_deserialize<signed char>(WvBuf &buf)
341  { return wv_deserialize_scalar<signed char>(buf); }
342 template <>
343  inline unsigned char _wv_deserialize<unsigned char>(WvBuf &buf)
344  { return wv_deserialize_scalar<unsigned char>(buf); }
345 
351 template <>
352 WvString _wv_deserialize<WvString>(WvBuf &buf);
353 
354 
356 // FIXME: it should be possible to do this without using a class!
357 template <>
359 {
360 public:
361  static WvBuf *go(WvBuf &buf)
362  {
363  size_t len = wv_deserialize<size_t>(buf);
364  WvBuf *outbuf = new WvInPlaceBuf(new char[len], 0, len, true);
365  outbuf->merge(buf, len);
366  return outbuf;
367  }
368 };
369 
370 
372 template <typename T>
374 {
375 public:
376  static WvList<T> *go(WvBuf &buf)
377  {
378  WvList<T> *list = new WvList<T>;
379  size_t nelems = wv_deserialize<size_t>(buf);
380 
381  for (size_t count = 0; count < nelems; count++)
382  {
383  T t = wv_deserialize<T>(buf);
384  list->append(new T(t), true);
385  }
386 
387  return list;
388  }
389 };
390 
391 template <>
393 {
394 public:
395  static WvStringList *go(WvBuf &buf)
396  {
397  WvStringList *list = new WvStringList();
398  size_t nelems = wv_deserialize<size_t>(buf);
399 
400  for (size_t count = 0; count < nelems; count++)
401  {
402  WvString str = wv_deserialize<WvString>(buf);
403  list->append(str);
404  }
405 
406  return list;
407  }
408 };
409 
410 #endif // __WVSERIALIZE_H
WvList::append
void append(T *data, bool autofree, const char *id=NULL)
Appends the element to the end of the list.
Definition: wvlinklist.h:276
WvBufBaseCommonImpl::get
const T * get(size_t count)
Reads exactly the specified number of elements and returns a pointer to a storage location owned by t...
Definition: wvbufbase.h:114
WvBufBase< unsigned char >::putstr
void putstr(WvStringParm str)
Copies a WvString into the buffer, excluding the null-terminator.
Definition: wvbuffer.cc:11
WvList::Iter
The iterator type for linked lists.
Definition: wvlinklist.h:350
WvString
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:329
WvDeserialize
Deserialize a complex templated object.
Definition: wvserialize.h:208
WvInPlaceBuf
The in place raw memory buffer type.
Definition: wvbuf.h:164
WvBufBase< unsigned char >
Specialization of WvBufBase for unsigned char type buffers intended for use with raw memory buffers.
Definition: wvbuf.h:22
WvListBase::count
size_t count() const
Returns the number of elements in the list.
Definition: wvlinklist.cc:24
WvBufBaseCommonImpl::used
size_t used() const
Returns the number of elements in the buffer currently available for reading.
Definition: wvbufbase.h:92
WvBufBaseCommonImpl::merge
void merge(Buffer &inbuf, size_t count)
Efficiently moves count bytes from the specified buffer into this one.
Definition: wvbufbase.h:558
WvStringList
This is a WvList of WvStrings, and is a really handy way to parse strings.
Definition: wvstringlist.h:27
WvList
A linked list container class.
Definition: wvlinklist.h:197