2 Copyright 2004-2005 Chris Tallon, Andreas Vogel
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "serialize.h"
24 #include <arpa/inet.h>
31 #define SNPRINTF snprintf
34 #define BUFFERINCREASE 1024
36 int SerializeBuffer::seek(int amount) {
37 UCHAR *np=current+amount;
38 if (np < start || np > end) return -1;
43 void SerializeBuffer::rewind() {
47 int SerializeBuffer::checkSpace(int amount) {
48 if ((current+amount) <= end) return 0;
49 if (owning && autoincrease) {
50 if (start+size > current+amount) {
54 UCHAR *ns=new UCHAR[size+BUFFERINCREASE];
56 memcpy(ns,start,end-start);
57 size=size+BUFFERINCREASE;
59 if (useMalloc) free( start);
67 SerializeBuffer::~SerializeBuffer() {
69 if (useMalloc) free(start);
74 SerializeBuffer::SerializeBuffer(ULONG sz,bool isMalloc,bool ai){
78 start=(UCHAR *)malloc(sz);
88 //constructor for SerializeBuffers with external buffers
89 SerializeBuffer::SerializeBuffer(UCHAR *buffer,ULONG sz,bool ow,bool isMalloc,bool ai) {
99 * helper for serialize and deserialize
100 * always return != if no space
101 * advance buffer pointer
104 int SerializeBuffer::encodeLong(ULONG data) {
105 if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
106 *((ULONG *)(current))=htonl(data);
107 current+=sizeof(ULONG);
110 int SerializeBuffer::encodeShort(USHORT data) {
111 if (checkSpace( (int)sizeof(USHORT))!=0) return -1;
112 *((USHORT *)(current))=htons(data);
113 current+=sizeof(USHORT);
116 int SerializeBuffer::encodeByte(UCHAR data) {
117 if (checkSpace( (int)sizeof(UCHAR))!=0) return -1;
118 *((UCHAR *)(current))=data;
119 current+=sizeof(UCHAR);
122 int SerializeBuffer::encodeLongLong(ULLONG data) {
123 if (checkSpace( (int)sizeof(ULLONG))!=0) return -1;
124 *((ULONG *)(current))=htonl((data>>32) & 0xffffffff);
125 current+=sizeof(ULONG);
126 *((ULONG *)(current))=htonl(data & 0xffffffff);
127 current+=sizeof(ULONG);
130 //string: 4 len, string with 0
131 int SerializeBuffer::encodeString(const char *str) {
132 if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
134 if (str) len=strlen(str)+1;
135 *((ULONG *)(current))=htonl(len);
136 current+=sizeof(ULONG);
137 if (len == 0) return 0;
138 if (checkSpace((int)len)!=0) return -1;
139 strcpy((char *) current,str);
143 int SerializeBuffer::decodeLong( int &data) {
144 if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
145 data=(int)ntohl(*((ULONG *)(current)));
146 current+=sizeof(ULONG);
149 int SerializeBuffer::decodeLong(ULONG &data) {
150 if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
151 data=ntohl(*((ULONG *)(current)));
152 current+=sizeof(ULONG);
155 int SerializeBuffer::decodeShort(USHORT &data) {
156 if (checkSpace( (int)sizeof(USHORT))!=0) return -1;
157 data=ntohs(*((USHORT *)(current)));
158 current+=sizeof(USHORT);
161 int SerializeBuffer::decodeByte(UCHAR &data) {
162 if (checkSpace( (int)sizeof(UCHAR))!=0) return -1;
163 data=*((UCHAR *)current);
164 current+=sizeof(UCHAR);
167 int SerializeBuffer::decodeLongLong(ULLONG &data) {
168 if (checkSpace( (int)sizeof(ULLONG))!=0) return -1;
169 ULLONG hd=ntohl(*((ULONG *)(current)));
170 current+=sizeof(ULONG);
171 ULLONG ld=ntohl(*((ULONG *)(current)));
172 current+=sizeof(ULONG);
173 data=(hd << 32) | ld;
176 //string: 4 len, string with 0
177 int SerializeBuffer::decodeString(ULONG &len, char *&strbuf) {
180 if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
181 len=ntohl(*((ULONG *)(current)));
182 current+=sizeof(ULONG);
183 if (len == 0) return 0;
184 if (checkSpace((int)len)!=0) return -1;
185 strbuf=new char[len];
186 strncpy(strbuf,(char *)current,len);
193 UCHAR * SerializeBuffer::steelBuffer() {
200 int Serializable::getSerializedStringLen(const char * str) {
202 if (str) rt+=strlen(str)+1;
206 USHORT Serializable::getVersion() {
211 Serializable::Serializable() {
214 Serializable::~Serializable(){}
216 int Serializable::getSerializedLen() {
218 return 6 + getSerializedLenImpl();
220 int Serializable::serialize(SerializeBuffer *b) {
221 UCHAR *ptr=b->getCurrent();
222 if (b->encodeShort(version) != 0) return -1;
223 if (b->encodeLong(0) != 0) return -1; //dummy len
224 if (serializeImpl(b) != 0) return -1;
225 UCHAR *ep=b->getCurrent();
228 if (len < 0) return -1 ; //internal error
229 b->seek(ptr-ep+2); //to len field
230 if (b->encodeLong(len) != 0) return -1;
231 b->seek(ep-b->getCurrent()); //back to end
235 int Serializable::deserialize(SerializeBuffer *b) {
237 if (b->decodeShort(vers) != 0) return -1;
239 if (b->decodeLong(len) != 0) return -1;
240 UCHAR *data=b->getCurrent();
241 if (data+len > b->getEnd()) return -1;
242 //TODO: set end temp. to current+len
243 //for better error handling in deserializeImpl
244 if (deserializeImpl(b) != 0) return -1;
245 //ensure we go to end of this element regardless of the things we know
246 b->seek(data+len-b->getCurrent());
250 SerializableList::SerializableList() {
254 SerializableList::~SerializableList(){}
256 int SerializableList::addParam(Serializable *p,USHORT v) {
257 if (v < version || p == NULL) return -1;
262 list.push_back(entry);
266 int SerializableList::addParam(USHORT *p,USHORT v) {
267 if (v < version || p == NULL) return -1;
272 list.push_back(entry);
276 int SerializableList::addParam(ULONG *p,USHORT v) {
277 if (v < version || p == NULL) return -1;
282 list.push_back(entry);
286 int SerializableList::addParam(ULLONG *p,USHORT v) {
287 if (v < version || p == NULL) return -1;
292 list.push_back(entry);
296 int SerializableList::addParam(char **p,USHORT v) {
297 if (v < version || p == NULL) return -1;
302 list.push_back(entry);
307 bool SerializableList::Pentry::isEqual(void *p,SerializableList::Ptypes t) {
311 cmp=(void *)ptr.pshort;
314 cmp=(void *)ptr.plong;
317 cmp=(void *)ptr.pllong;
320 cmp=(void *)ptr.pser;
323 cmp=(void *)ptr.pchar;
331 SerializableList::Pentry *SerializableList::findEntry(void *p,SerializableList::Ptypes t) {
332 for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
333 if ( (*it).isEqual(p,t)) return &(*it);
337 bool SerializableList::isDeserialized(Serializable *p){
338 SerializableList::Pentry *e=findEntry(p,TSER);
339 if (!e) return false;
340 return e->isDeserialized;
342 bool SerializableList::isDeserialized(USHORT *p){
343 SerializableList::Pentry *e=findEntry(p,TUSHORT);
344 if (!e) return false;
345 return e->isDeserialized;
347 bool SerializableList::isDeserialized(ULONG *p){
348 SerializableList::Pentry *e=findEntry(p,TULONG);
349 if (!e) return false;
350 return e->isDeserialized;
353 bool SerializableList::isDeserialized(ULLONG *p){
354 SerializableList::Pentry *e=findEntry(p,TULLONG);
355 if (!e) return false;
356 return e->isDeserialized;
359 bool SerializableList::isDeserialized(char **p){
360 SerializableList::Pentry *e=findEntry(p,TCHAR);
361 if (!e) return false;
362 return e->isDeserialized;
365 int SerializableList::getSerializedLenImpl(){
367 for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
379 rt+=getSerializedStringLen(*((*it).ptr.pchar));
382 rt+=(*it).ptr.pser->getSerializedLen();
391 int SerializableList::serializeImpl(SerializeBuffer *b){
392 for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
395 if (b->encodeShort(*(*it).ptr.pshort) != 0) return -1;
398 if (b->encodeLong(*(*it).ptr.plong) != 0) return -1;
401 if (b->encodeLongLong(*(*it).ptr.pllong) != 0) return -1;
404 if (b->encodeString(*(*it).ptr.pchar) != 0) return -1;
407 if ((*it).ptr.pser->serialize(b) != 0) return -1;
416 int SerializableList::deserializeImpl(SerializeBuffer *b){
418 for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
419 if ((*it).version > version) {
420 //OK - we received an older version - stop here
425 if (b->decodeShort(*(*it).ptr.pshort) != 0) return -1;
428 if (b->decodeLong(*(*it).ptr.plong) != 0) return -1;
431 if (b->decodeLongLong(*(*it).ptr.pllong) != 0) return -1;
434 if (b->decodeString(dlen,*(*it).ptr.pchar) != 0) return -1;
437 if ((*it).ptr.pser->deserialize(b) != 0) return -1;
442 (*it).isDeserialized=true;