WvStreams
include/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
25typedef __int8 int8_t;
26typedef unsigned __int8 uint8_t;
27typedef __int16 int16_t;
28typedef unsigned __int16 uint16_t;
29typedef __int32 int32_t;
30typedef unsigned __int32 uint32_t;
31typedef __int64 int64_t;
32typedef unsigned __int64 uint64_t;
33#endif
34#include <winsock2.h>
35#endif
36
43template <typename T>
44inline void wv_serialize(WvBuf &buf, const T &t)
45{
46 _wv_serialize(buf, t);
47}
48
49
54inline int32_t _wv_htonl(int32_t i)
55{
56 return htonl(i);
57}
58inline int16_t _wv_htons(int16_t i)
59{
60 return htons(i);
61}
62
66inline 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
75inline 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
93template <typename T>
94void 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
117inline void _wv_serialize(WvBuf &buf, long long i)
118 { wv_serialize_scalar(buf, i); }
119inline void _wv_serialize(WvBuf &buf, unsigned long long i)
120 { wv_serialize_scalar(buf, i); }
121inline void _wv_serialize(WvBuf &buf, long i)
122 { wv_serialize_scalar(buf, i); }
123inline void _wv_serialize(WvBuf &buf, unsigned long i)
124 { wv_serialize_scalar(buf, i); }
125inline void _wv_serialize(WvBuf &buf, int i)
126 { wv_serialize_scalar(buf, i); }
127inline void _wv_serialize(WvBuf &buf, unsigned int i)
128 { wv_serialize_scalar(buf, i); }
129inline void _wv_serialize(WvBuf &buf, short i)
130 { wv_serialize_scalar(buf, i); }
131inline void _wv_serialize(WvBuf &buf, unsigned short i)
132 { wv_serialize_scalar(buf, i); }
133inline void _wv_serialize(WvBuf &buf, bool i)
134 { wv_serialize_scalar(buf, i); }
135
137inline void _wv_serialize(WvBuf &buf, char i)
138 { wv_serialize_scalar(buf, i); }
139inline void _wv_serialize(WvBuf &buf, signed char i)
140 { wv_serialize_scalar(buf, i); }
141inline void _wv_serialize(WvBuf &buf, unsigned char i)
142 { wv_serialize_scalar(buf, i); }
143
144
151inline void _wv_serialize(WvBuf &buf, WvStringParm s)
152{
153 if (!s.isnull())
154 buf.putstr(s);
155 buf.put("", 1); // terminating nul
156}
157
159inline void wv_serialize(WvBuf &buf, const char *t)
160{
161 _wv_serialize(buf, t);
162}
163
164
169inline 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
181template <typename T>
182void _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
196template <typename T>
197 T _wv_deserialize(WvBuf &buf);
198
199
207template <typename T>
208class WvDeserialize
209{
210public:
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.
230template <typename T>
231class WvDeserialize<T *>
232{
233public:
234 static T *go(WvBuf &buf)
235 { return new T(_wv_deserialize<T>(buf)); }
236};
237
238
239
259template <typename T>
260inline T wv_deserialize(WvBuf &buf)
261{
262 return WvDeserialize<T>::go(buf);
263}
264
265
270inline int32_t _wv_ntohl(int32_t i)
271{
272 return ntohl(i);
273}
274inline int16_t _wv_ntohs(int16_t i)
275{
276 return ntohs(i);
277}
278
279
285template <typename T>
286inline 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
303template <typename T>
304inline T xwv_deserialize_scalar(WvBuf &buf)
305{
306 return 0;
307}
308
309template <>
310 inline long long _wv_deserialize<long long>(WvBuf &buf)
311 { return wv_deserialize_scalar<long long>(buf); }
312template <>
313 inline unsigned long long _wv_deserialize<unsigned long long>(WvBuf &buf)
314 { return wv_deserialize_scalar<unsigned long long>(buf); }
315template <>
316 inline long _wv_deserialize<long>(WvBuf &buf)
317 { return wv_deserialize_scalar<long>(buf); }
318template <>
319 inline unsigned long _wv_deserialize<unsigned long>(WvBuf &buf)
320 { return wv_deserialize_scalar<unsigned long>(buf); }
321template <>
322 inline int _wv_deserialize<int>(WvBuf &buf)
323 { return wv_deserialize_scalar<int>(buf); }
324template <>
325 inline unsigned int _wv_deserialize<unsigned int>(WvBuf &buf)
326 { return wv_deserialize_scalar<unsigned int>(buf); }
327template <>
328 inline short _wv_deserialize<short>(WvBuf &buf)
329 { return wv_deserialize_scalar<short>(buf); }
330template <>
331 inline unsigned short _wv_deserialize<unsigned short>(WvBuf &buf)
332 { return wv_deserialize_scalar<unsigned short>(buf); }
333template <>
334 inline bool _wv_deserialize<bool>(WvBuf &buf)
335 { return wv_deserialize_scalar<bool>(buf); }
336template <>
337 inline char _wv_deserialize<char>(WvBuf &buf)
338 { return wv_deserialize_scalar<char>(buf); }
339template <>
340 inline signed char _wv_deserialize<signed char>(WvBuf &buf)
341 { return wv_deserialize_scalar<signed char>(buf); }
342template <>
343 inline unsigned char _wv_deserialize<unsigned char>(WvBuf &buf)
344 { return wv_deserialize_scalar<unsigned char>(buf); }
345
351template <>
352WvString _wv_deserialize<WvString>(WvBuf &buf);
353
354
356// FIXME: it should be possible to do this without using a class!
357template <>
358class WvDeserialize<WvBuf *>
359{
360public:
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
372template <typename T>
373class WvDeserialize<WvList<T> *>
374{
375public:
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
391template <>
393{
394public:
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
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
bool isnull() const
returns true if this string is null
The in place raw memory buffer type.
size_t count() const
Returns the number of elements in the list.
Definition wvlinklist.cc:24
void append(T *data, bool autofree, const char *id=NULL)
Appends the element to the end of the list.
This is a WvList of WvStrings, and is a really handy way to parse strings.
WvString is an implementation of a simple and efficient printable-string class.