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 u1 *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 u1 *ns=new u1[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(u4 sz,bool isMalloc,bool ai){
78 start=(u1 *)malloc(sz);
88 //constructor for SerializeBuffers with external buffers
89 SerializeBuffer::SerializeBuffer(u1 *buffer,u4 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(u4 data) {
105 if (checkSpace( (int)sizeof(u4))!=0) return -1;
106 *((u4 *)(current))=htonl(data);
110 int SerializeBuffer::encodeShort(u2 data) {
111 if (checkSpace( (int)sizeof(u2))!=0) return -1;
112 *((u2 *)(current))=htons(data);
116 int SerializeBuffer::encodeByte(u1 data) {
117 if (checkSpace( (int)sizeof(u1))!=0) return -1;
118 *((u1 *)(current))=data;
122 int SerializeBuffer::encodeLongLong(u8 data) {
123 if (checkSpace( (int)sizeof(u8))!=0) return -1;
124 *((u4 *)(current))=htonl((data>>32) & 0xffffffff);
126 *((u4 *)(current))=htonl(data & 0xffffffff);
130 //string: 4 len, string with 0
131 int SerializeBuffer::encodeString(const char *str) {
132 if (checkSpace( (int)sizeof(u4))!=0) return -1;
134 if (str) len=strlen(str)+1;
135 *((u4 *)(current))=htonl(len);
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(u4))!=0) return -1;
145 data=(int)ntohl(*((u4 *)(current)));
149 int SerializeBuffer::decodeLong(u4 &data) {
150 if (checkSpace( (int)sizeof(u4))!=0) return -1;
151 data=ntohl(*((u4 *)(current)));
155 int SerializeBuffer::decodeShort(u2 &data) {
156 if (checkSpace( (int)sizeof(u2))!=0) return -1;
157 data=ntohs(*((u2 *)(current)));
161 int SerializeBuffer::decodeByte(u1 &data) {
162 if (checkSpace( (int)sizeof(u1))!=0) return -1;
163 data=*((u1 *)current);
167 int SerializeBuffer::decodeLongLong(u8 &data) {
168 if (checkSpace( (int)sizeof(u8))!=0) return -1;
169 u8 hd=ntohl(*((u4 *)(current)));
171 u8 ld=ntohl(*((u4 *)(current)));
173 data=(hd << 32) | ld;
176 //string: 4 len, string with 0
177 int SerializeBuffer::decodeString(u4 &len, char *&strbuf) {
180 if (checkSpace( (int)sizeof(u4))!=0) return -1;
181 len=ntohl(*((u4 *)(current)));
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 u1 * SerializeBuffer::steelBuffer() {
200 int Serializable::getSerializedStringLen(const char * str) {
202 if (str) rt+=strlen(str)+1;
206 u2 Serializable::getVersion() {
211 Serializable::Serializable() {
214 Serializable::~Serializable(){}
216 int Serializable::getSerializedLen() {
218 return 6 + getSerializedLenImpl();
220 int Serializable::serialize(SerializeBuffer *b) {
221 u1 *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 u1 *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 u1 *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,u2 v) {
257 if (v < version || p == NULL) return -1;
262 list.push_back(entry);
266 int SerializableList::addParam(u2 *p,u2 v) {
267 if (v < version || p == NULL) return -1;
272 list.push_back(entry);
276 int SerializableList::addParam(u4 *p,u2 v) {
277 if (v < version || p == NULL) return -1;
282 list.push_back(entry);
286 int SerializableList::addParam(u8 *p,u2 v) {
287 if (v < version || p == NULL) return -1;
292 list.push_back(entry);
296 int SerializableList::addParam(char **p,u2 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(u2 *p){
343 SerializableList::Pentry *e=findEntry(p,Tu2);
344 if (!e) return false;
345 return e->isDeserialized;
347 bool SerializableList::isDeserialized(u4 *p){
348 SerializableList::Pentry *e=findEntry(p,TULONG);
349 if (!e) return false;
350 return e->isDeserialized;
353 bool SerializableList::isDeserialized(u8 *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;