/* * Copyright (c) 2002-2006 Samit Basu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "Serialize.hpp" #include "Exception.hpp" #include "Malloc.hpp" #include #ifdef WIN32 #include #else #include #endif Serialize::Serialize(Stream *sck) { endianSwap = false; s = sck; } Serialize::~Serialize() { } void Serialize::handshakeServer() { try { char hand = 'A'; s->writeBytes(&hand,sizeof(char)); hand = 'Y'; s->writeBytes(&hand,sizeof(char)); hand = 'B'; s->writeBytes(&hand,sizeof(char)); hand = 'S'; s->writeBytes(&hand,sizeof(char)); unsigned short t; t = 1; s->writeBytes(&t,sizeof(short)); } catch (Exception& e) { throw; } } void Serialize::handshakeClient() { try { char hand; s->readBytes(&hand,sizeof(char)); if (hand != 'A') throw Exception("Handshaking error! Unable to establish serialization"); s->readBytes(&hand,sizeof(char)); if (hand != 'Y') throw Exception("Handshaking error! Unable to establish serialization"); s->readBytes(&hand,sizeof(char)); if (hand != 'B') throw Exception("Handshaking error! Unable to establish serialization"); s->readBytes(&hand,sizeof(char)); if (hand != 'S') throw Exception("Handshaking error! Unable to establish serialization"); unsigned short t = 1; s->readBytes(&t,sizeof(short)); if (t == 1) endianSwap = false; else if (t == 256) endianSwap = true; else throw Exception("Handshaking error! Unable to resolve byte ordering between server/client"); } catch (Exception &e) { throw ; } } void Serialize::sendSignature(char type, int count) { s->writeBytes(&type,1); long netcount; netcount = htonl(count); s->writeBytes(&netcount,sizeof(long)); } void Serialize::checkSignature(char type, int count) { char rtype; long rcount; s->readBytes(&rtype,1); s->readBytes(&rcount,sizeof(long)); rcount = ntohl(rcount); if (!((type == rtype) && (count == rcount))) { char buffer[1000]; sprintf(buffer,"Serialization Mismatch: expected <%c,%d>, got <%c,%d>", type,count,rtype,rcount); throw Exception(buffer); } } // Send a stream of base objects void Serialize::putBytes(const char *ptr, int count) { sendSignature('c',count); s->writeBytes(ptr,count*sizeof(char)); } void Serialize::putShorts(const short *ptr, int count) { sendSignature('s',count); s->writeBytes(ptr,count*sizeof(short)); } void Serialize::putInts(const int *ptr, int count) { sendSignature('i',count); s->writeBytes(ptr,count*sizeof(int)); } void Serialize::putFloats(const float *ptr, int count) { sendSignature('f',count); s->writeBytes(ptr,count*sizeof(float)); } void Serialize::putDoubles(const double *ptr, int count) { sendSignature('d',count); s->writeBytes(ptr,count*sizeof(double)); } void Serialize::putString(string p) { unsigned int len; sendSignature('x',0); len = p.size()+1; putInts((int*)&len,1); putBytes(p.c_str(),len); } void Serialize::putBool(bool b) { if (b) putByte(1); else putByte(0); } bool Serialize::getBool() { char b; b = getByte(); return (b == 1); } void Serialize::putByte(char t) { putBytes(&t,1); } void Serialize::putStringVector(stringVector t) { sendSignature('S',1); putInt(t.size()); int i; for (i=0;ireadBytes(ptr,count*sizeof(char)); } #define SWAP(a,b) {tmp = a; a = b; b = tmp;} void Serialize::getShorts(short *ptr, int count) { checkSignature('s',count); s->readBytes(ptr,count*sizeof(short)); if (endianSwap) { char *cptr = (char *) ptr; char tmp; for (int i=0;i<2*count;i+=2) SWAP(cptr[i],cptr[i+1]); } } void Serialize::getInts(int *ptr, int count) { checkSignature('i',count); s->readBytes(ptr,count*sizeof(int)); if (endianSwap) { char *cptr = (char *) ptr; char tmp; for (int i=0;i<4*count;i+=4) { SWAP(cptr[i],cptr[i+3]); SWAP(cptr[i+1],cptr[i+2]); } } } void Serialize::getFloats(float *ptr, int count) { checkSignature('f',count); s->readBytes(ptr,count*sizeof(float)); if (endianSwap) { char *cptr = (char *) ptr; char tmp; for (int i=0;i<4*count;i+=4) { SWAP(cptr[i],cptr[i+3]); SWAP(cptr[i+1],cptr[i+2]); } } } void Serialize::getDoubles(double *ptr, int count) { checkSignature('d',count); s->readBytes(ptr,count*sizeof(double)); if (endianSwap) { char *cptr = (char *) ptr; char tmp; for (int i=0;i<8*count;i+=8) { SWAP(cptr[i],cptr[i+7]); SWAP(cptr[i+1],cptr[i+6]); SWAP(cptr[i+2],cptr[i+5]); SWAP(cptr[i+3],cptr[i+4]); } } } string Serialize::getString() { checkSignature('x',0); unsigned int len; getInts((int*) &len,1); if (len == 0) return string(); char *cp = (char*) malloc(len*sizeof(char)); getBytes(cp,len); string ret(cp); free(cp); return ret; } char Serialize::getByte() { char t; getBytes(&t,1); return t; } short Serialize::getShort() { short t; getShorts(&t,1); return t; } int Serialize::getInt() { int t; getInts(&t,1); return t; } float Serialize::getFloat() { float t; getFloats(&t,1); return t; } double Serialize::getDouble() { double t; getDoubles(&t,1); return t; } Class Serialize::getDataClass(bool& sparseflag, rvstring& className) { checkSignature('a',1); char a = getByte(); sparseflag = (a & 16) > 0; // For compatibility reasons, the sparse flag is stuck at // 16. Which is binary: // 0001 0000 // To mask out this bit, we need the following number: // 1110 1111 = 255 - 16 = 239 a = a & 239; switch (a) { case 1: return FM_CELL_ARRAY; case 2: return FM_STRUCT_ARRAY; case 3: return FM_LOGICAL; case 4: return FM_UINT8; case 5: return FM_INT8; case 6: return FM_UINT16; case 7: return FM_INT16; case 8: return FM_UINT32; case 9: return FM_INT32; case 32: return FM_UINT64; case 33: return FM_INT64; case 10: return FM_FLOAT; case 11: return FM_DOUBLE; case 12: return FM_COMPLEX; case 13: return FM_DCOMPLEX; case 14: return FM_STRING; case 128: { int cnt(getInt()); for (int i=0;i