Allolib  1.0
C++ Components For Interactive Multimedia
al_Serialize.h
1 #ifndef INCLUDE_AL_SERIALIZE_H
2 #define INCLUDE_AL_SERIALIZE_H
3 
4 /* Allocore --
5  Multimedia / virtual environment application class library
6 
7  Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
8  Copyright (C) 2012. The Regents of the University of California.
9  All rights reserved.
10 
11  Redistribution and use in source and binary forms, with or without
12  modification, are permitted provided that the following conditions are met:
13 
14  Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16 
17  Redistributions in binary form must reproduce the above copyright
18  notice, this list of conditions and the following disclaimer in the
19  documentation and/or other materials provided with the distribution.
20 
21  Neither the name of the University of California nor the names of its
22  contributors may be used to endorse or promote products derived from
23  this software without specific prior written permission.
24 
25  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  POSSIBILITY OF SUCH DAMAGE.
36 
37 
38  File description:
39  General serialization and deserialization for file and network i/o.
40 
41  Either single elements or arrays of elements can be read or written to a
42  buffer. Each group of elements is preceeded by a header that tells the type of
43  elements and the size of the array.
44 
45  A string is a C-style null-terminated array of characters.
46  A boolean is a single byte where a value of 0 is false and non-zero value is true.
47 
48  Byte ordering is little endian. If the target architecture is big endian,
49  then pass in the preprocessor flag -DSER_IS_BIG_ENDIAN.
50 
51  File author(s):
52  Lance Putnam, 2010, putnam.lance@gmail.com
53 */
54 
55 
56 #include <stddef.h>
57 #include <string.h>
58 #include <cstdint>
59 
60 
61 #ifdef __cplusplus
62 extern "C" {
63 #endif
64 
65 //#define SER_IS_BIG_ENDIAN
66 
67 /* Serialization data types */
68 enum{
69  SER_FLOAT32 = 'f', /* 32-bit IEEE float */
70  SER_FLOAT64 = 'd', /* 64-bit IEEE float */
71  SER_INT8 = 'h', /* 8-bit 2's-complement signed integer */
72  SER_INT16 = 'H', /* 16-bit 2's-complement signed integer */
73  SER_INT32 = 'i', /* 32-bit 2's-complement signed integer */
74  SER_INT64 = 'I', /* 64-bit 2's-complement signed integer */
75  SER_UINT8 = 't', /* 8-bit unsigned integer */
76  SER_UINT16 = 'T', /* 16-bit unsigned integer */
77  SER_UINT32 = 'u', /* 32-bit unsigned integer */
78  SER_UINT64 = 'U', /* 64-bit unsigned integer */
79  SER_SUB = '_' /* substructure */
80 };
81 
82 
83 #define SER_HEADER_SIZE 5
84 
85 /* Serialized data header */
86 struct SerHeader{
87  uint8_t type; /* type of data */
88  uint32_t num; /* number of data elements */
89 };
90 
91 
92 /* Serialized data header. Don't think this is needed... */
93 //struct SerStruct{
94 // SerHeader header;
95 // void * data;
96 //};
97 
98 
99 /* Copy 1-byte elements */
100 static uint32_t serCopy1(void * dst, const void * src, uint32_t num);
101 
102 /* Copy 2-byte elements in little endian byte order */
103 static uint32_t serCopy2(void * dst, const void * src, uint32_t num);
104 
105 /* Copy 4-byte elements in little endian byte order */
106 static uint32_t serCopy4(void * dst, const void * src, uint32_t num);
107 
108 /* Copy 8-byte elements in little endian byte order */
109 static uint32_t serCopy8(void * dst, const void * src, uint32_t num);
110 
111 /* Decode serialized data. Returns number of bytes parsed */
112 uint32_t serDecode(const char * b, void * data);
113 
114 /* */
115 struct SerHeader serGetHeader(const char * buf);
116 
117 /* Returns header size in bytes */
118 static inline int serHeaderSize(){ return SER_HEADER_SIZE; }
119 
120 /* Returns size of data type in bytes */
121 int serTypeSize(uint8_t t);
122 
123 uint32_t serElementsSize(const struct SerHeader * h);
124 
125 static void serSwap(char * a, char * b);
126 static void serSwapBytes2(void * v);
127 static void serSwapBytes4(void * v);
128 static void serSwapBytes8(void * v);
129 
130 /* Returns human-readable string of header */
131 const char * serStringifyHeader(const struct SerHeader * h);
132 
133 /* Returns human-readable string of type */
134 const char * serStringifyType(uint8_t t);
135 
136 
137 
138 
139 
140 
141 
142 
143 
144 #define SOH serHeaderSize()
145 
146 static inline void serHeaderWrite(char * b, uint8_t type, uint32_t num){
147  b[0] = type;
148  serCopy4(b+1, &num, 1);
149 }
150 
151 #define DO(B, N)\
152  serHeaderWrite(b, type, N);\
153  return SOH + serCopy##B(b+SOH, v, N)
154 static inline uint32_t serEncode1(uint8_t type, char * b, const void * v, uint32_t n){ DO(1,n); }
155 static inline uint32_t serEncode2(uint8_t type, char * b, const void * v, uint32_t n){ DO(2,n); }
156 static inline uint32_t serEncode4(uint8_t type, char * b, const void * v, uint32_t n){ DO(4,n); }
157 static inline uint32_t serEncode8(uint8_t type, char * b, const void * v, uint32_t n){ DO(8,n); }
158 #undef DO
159 
160 static inline uint32_t serEncodeFloat32(char * b, const float * v , uint32_t n){ return serEncode4(SER_FLOAT32, b,v,n); }
161 static inline uint32_t serEncodeFloat64(char * b, const double * v , uint32_t n){ return serEncode8(SER_FLOAT64, b,v,n); }
162 static inline uint32_t serEncodeInt8 (char * b, const int8_t * v , uint32_t n){ return serEncode1(SER_INT8 , b,v,n); }
163 static inline uint32_t serEncodeInt16 (char * b, const int16_t * v , uint32_t n){ return serEncode2(SER_INT16 , b,v,n); }
164 static inline uint32_t serEncodeInt32 (char * b, const int32_t * v , uint32_t n){ return serEncode4(SER_INT32 , b,v,n); }
165 static inline uint32_t serEncodeInt64 (char * b, const int64_t * v , uint32_t n){ return serEncode8(SER_INT64 , b,v,n); }
166 static inline uint32_t serEncodeUInt8 (char * b, const uint8_t * v , uint32_t n){ return serEncode1(SER_UINT8 , b,v,n); }
167 static inline uint32_t serEncodeUInt16 (char * b, const uint16_t * v, uint32_t n){ return serEncode2(SER_UINT16 , b,v,n); }
168 static inline uint32_t serEncodeUInt32 (char * b, const uint32_t * v, uint32_t n){ return serEncode4(SER_UINT32 , b,v,n); }
169 static inline uint32_t serEncodeUInt64 (char * b, const uint64_t * v, uint32_t n){ return serEncode8(SER_UINT64 , b,v,n); }
170 
171 
172 
173 
174 static inline void serSwap(char * a, char * b){ char t=*a; *a=*b; *b=t; }
175 
176 static inline void serSwapBytes2(void * v){
177  char * b = (char *)v;
178  serSwap(b , b+1);
179 }
180 
181 static inline void serSwapBytes4(void * v){
182  char * b = (char *)v;
183  serSwap(b , b+3);
184  serSwap(b+1, b+2);
185 }
186 
187 static inline void serSwapBytes8(void * v){
188  char * b = (char *)v;
189  serSwap(b , b+7);
190  serSwap(b+1, b+6);
191  serSwap(b+2, b+5);
192  serSwap(b+3, b+4);
193 }
194 
195 
196 static inline uint32_t serCopy1(void * d, const void * s, uint32_t n){
197  memcpy(d,s,n); return n;
198 }
199 
200 #define DEF_LE(B, S)\
201 static inline uint32_t serCopy##B(void * d, const void * s, uint32_t n){\
202  n = n<<S;\
203  memcpy(d,s,n);\
204  return n;\
205 }
206 
207 #define DEF_BE(p, B, S)\
208 static inline uint32_t serCopy##B(void * d, const void * s, uint32_t n){\
209  n = n<<S;\
210  memcpy(d,s,n);\
211  char * t = (char *)d;\
212  for(uint32_t i=0; i<n; i+=B) swapBytes##B(t+i);\
213  return n;\
214 }
215 
216 #ifdef SER_IS_BIG_ENDIAN
217 DEF_BE(2,1) DEF_BE(4,2) DEF_BE(8,3)
218 #else
219 DEF_LE(2,1) DEF_LE(4,2) DEF_LE(8,3)
220 #endif
221 
222 #undef DEF_BE
223 #undef DEF_LE
224 
225 #undef SOH
226 
227 #ifdef __cplusplus
228 }
229 #endif
230 
231 #endif