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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "serialize.h"
23 #include <arpa/inet.h>
25 #define SNPRINTF snprintf
28 #define BUFFERINCREASE 1024
30 int SerializeBuffer::seek(int amount) {
31 UCHAR *np=current+amount;
32 if (np < start || np > end) return -1;
37 void SerializeBuffer::rewind() {
41 int SerializeBuffer::checkSpace(int amount) {
42 if ((current+amount) <= end) return 0;
43 if (owning && autoincrease) {
44 if (start+size > current+amount) {
48 UCHAR *ns=new UCHAR[size+BUFFERINCREASE];
50 memcpy(ns,start,end-start);
51 size=size+BUFFERINCREASE;
53 if (useMalloc) free( start);
61 SerializeBuffer::~SerializeBuffer() {
63 if (useMalloc) free(start);
68 SerializeBuffer::SerializeBuffer(ULONG sz,bool isMalloc,bool ai){
72 start=(UCHAR *)malloc(sz);
82 //constructor for SerializeBuffers with external buffers
83 SerializeBuffer::SerializeBuffer(UCHAR *buffer,ULONG sz,bool ow,bool isMalloc,bool ai) {
93 * helper for serialize and deserialize
94 * always return != if no space
95 * advance buffer pointer
98 int SerializeBuffer::encodeLong(ULONG data) {
99 if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
100 *((ULONG *)(current))=htonl(data);
101 current+=sizeof(ULONG);
104 int SerializeBuffer::encodeShort(USHORT data) {
105 if (checkSpace( (int)sizeof(USHORT))!=0) return -1;
106 *((USHORT *)(current))=htons(data);
107 current+=sizeof(USHORT);
110 int SerializeBuffer::encodeByte(UCHAR data) {
111 if (checkSpace( (int)sizeof(UCHAR))!=0) return -1;
112 *((UCHAR *)(current))=data;
113 current+=sizeof(UCHAR);
116 int SerializeBuffer::encodeLongLong(ULLONG data) {
117 if (checkSpace( (int)sizeof(ULLONG))!=0) return -1;
118 *((ULONG *)(current))=htonl((data>>32) & 0xffffffff);
119 current+=sizeof(ULONG);
120 *((ULONG *)(current))=htonl(data & 0xffffffff);
121 current+=sizeof(ULONG);
124 //string: 4 len, string with 0
125 int SerializeBuffer::encodeString(const char *str) {
126 if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
128 if (str) len=strlen(str)+1;
129 *((ULONG *)(current))=htonl(len);
130 current+=sizeof(ULONG);
131 if (len == 0) return 0;
132 if (checkSpace((int)len)!=0) return -1;
133 strcpy((char *) current,str);
137 int SerializeBuffer::decodeLong( int &data) {
138 if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
139 data=(int)ntohl(*((ULONG *)(current)));
140 current+=sizeof(ULONG);
143 int SerializeBuffer::decodeLong(ULONG &data) {
144 if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
145 data=ntohl(*((ULONG *)(current)));
146 current+=sizeof(ULONG);
149 int SerializeBuffer::decodeShort(USHORT &data) {
150 if (checkSpace( (int)sizeof(USHORT))!=0) return -1;
151 data=ntohs(*((USHORT *)(current)));
152 current+=sizeof(USHORT);
155 int SerializeBuffer::decodeByte(UCHAR &data) {
156 if (checkSpace( (int)sizeof(UCHAR))!=0) return -1;
157 data=*((UCHAR *)current);
158 current+=sizeof(UCHAR);
161 int SerializeBuffer::decodeLongLong(ULLONG &data) {
162 if (checkSpace( (int)sizeof(ULLONG))!=0) return -1;
163 ULLONG hd=ntohl(*((ULONG *)(current)));
164 current+=sizeof(ULONG);
165 ULLONG ld=ntohl(*((ULONG *)(current)));
166 current+=sizeof(ULONG);
167 data=(hd << 32) | ld;
170 //string: 4 len, string with 0
171 int SerializeBuffer::decodeString(ULONG &len, char *&strbuf) {
174 if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
175 len=ntohl(*((ULONG *)(current)));
176 current+=sizeof(ULONG);
177 if (len == 0) return 0;
178 if (checkSpace((int)len)!=0) return -1;
179 strbuf=new char[len];
180 strncpy(strbuf,(char *)current,len);
187 UCHAR * SerializeBuffer::steelBuffer() {
194 int Serializable::getSerializedStringLen(const char * str) {
196 if (str) rt+=strlen(str)+1;
200 USHORT Serializable::getVersion() {
205 Serializable::Serializable() {
208 Serializable::~Serializable(){}
210 int Serializable::getSerializedLen() {
212 return 6 + getSerializedLenImpl();
214 int Serializable::serialize(SerializeBuffer *b) {
215 UCHAR *ptr=b->getCurrent();
216 if (b->encodeShort(version) != 0) return -1;
217 if (b->encodeLong(0) != 0) return -1; //dummy len
218 if (serializeImpl(b) != 0) return -1;
219 UCHAR *ep=b->getCurrent();
222 if (len < 0) return -1 ; //internal error
223 b->seek(ptr-ep+2); //to len field
224 if (b->encodeLong(len) != 0) return -1;
225 b->seek(ep-b->getCurrent()); //back to end
229 int Serializable::deserialize(SerializeBuffer *b) {
231 if (b->decodeShort(vers) != 0) return -1;
233 if (b->decodeLong(len) != 0) return -1;
234 UCHAR *data=b->getCurrent();
235 if (data+len > b->getEnd()) return -1;
236 //TODO: set end temp. to current+len
237 //for better error handling in deserializeImpl
238 if (deserializeImpl(b) != 0) return -1;
239 //ensure we go to end of this element regardless of the things we know
240 b->seek(data+len-b->getCurrent());
244 SerializableList::SerializableList() {
248 SerializableList::~SerializableList(){}
250 int SerializableList::addParam(Serializable *p,USHORT v) {
251 if (v < version || p == NULL) return -1;
256 list.push_back(entry);
260 int SerializableList::addParam(USHORT *p,USHORT v) {
261 if (v < version || p == NULL) return -1;
266 list.push_back(entry);
270 int SerializableList::addParam(ULONG *p,USHORT v) {
271 if (v < version || p == NULL) return -1;
276 list.push_back(entry);
280 int SerializableList::addParam(ULLONG *p,USHORT v) {
281 if (v < version || p == NULL) return -1;
286 list.push_back(entry);
290 int SerializableList::addParam(char **p,USHORT v) {
291 if (v < version || p == NULL) return -1;
296 list.push_back(entry);
301 bool SerializableList::Pentry::isEqual(void *p,SerializableList::Ptypes t) {
305 cmp=(void *)ptr.pshort;
308 cmp=(void *)ptr.plong;
311 cmp=(void *)ptr.pllong;
314 cmp=(void *)ptr.pser;
317 cmp=(void *)ptr.pchar;
325 SerializableList::Pentry *SerializableList::findEntry(void *p,SerializableList::Ptypes t) {
326 for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
327 if ( (*it).isEqual(p,t)) return &(*it);
331 bool SerializableList::isDeserialized(Serializable *p){
332 SerializableList::Pentry *e=findEntry(p,TSER);
333 if (!e) return false;
334 return e->isDeserialized;
336 bool SerializableList::isDeserialized(USHORT *p){
337 SerializableList::Pentry *e=findEntry(p,TUSHORT);
338 if (!e) return false;
339 return e->isDeserialized;
341 bool SerializableList::isDeserialized(ULONG *p){
342 SerializableList::Pentry *e=findEntry(p,TULONG);
343 if (!e) return false;
344 return e->isDeserialized;
347 bool SerializableList::isDeserialized(ULLONG *p){
348 SerializableList::Pentry *e=findEntry(p,TULLONG);
349 if (!e) return false;
350 return e->isDeserialized;
353 bool SerializableList::isDeserialized(char **p){
354 SerializableList::Pentry *e=findEntry(p,TCHAR);
355 if (!e) return false;
356 return e->isDeserialized;
359 int SerializableList::getSerializedLenImpl(){
361 for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
373 rt+=getSerializedStringLen(*((*it).ptr.pchar));
376 rt+=(*it).ptr.pser->getSerializedLen();
385 int SerializableList::serializeImpl(SerializeBuffer *b){
386 for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
389 if (b->encodeShort(*(*it).ptr.pshort) != 0) return -1;
392 if (b->encodeLong(*(*it).ptr.plong) != 0) return -1;
395 if (b->encodeLongLong(*(*it).ptr.pllong) != 0) return -1;
398 if (b->encodeString(*(*it).ptr.pchar) != 0) return -1;
401 if ((*it).ptr.pser->serialize(b) != 0) return -1;
410 int SerializableList::deserializeImpl(SerializeBuffer *b){
412 for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
413 if ((*it).version > version) {
414 //OK - we received an older version - stop here
419 if (b->decodeShort(*(*it).ptr.pshort) != 0) return -1;
422 if (b->decodeLong(*(*it).ptr.plong) != 0) return -1;
425 if (b->decodeLongLong(*(*it).ptr.pllong) != 0) return -1;
428 if (b->decodeString(dlen,*(*it).ptr.pchar) != 0) return -1;
431 if ((*it).ptr.pser->deserialize(b) != 0) return -1;
436 (*it).isDeserialized=true;