Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/BinarySerializer.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: BinarySerializer.cpp 1029 2004-02-11 20:45:54Z jungd $
00019   $Revision: 1.8 $
00020   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #include <base/BinarySerializer>
00026 
00027 #include <base/Serializable>
00028 
00029 using base::BinarySerializer;
00030 using base::Serializer;
00031 using base::Serializable;
00032 using base::Referenced;
00033 using base::VFile;
00034 using base::ref;
00035 
00036 using std::iostream;
00037 using std::istream;
00038 using std::ostream;
00039 using std::ios;
00040 using std::streambuf;
00041 
00042 
00043 #ifdef DEBUG
00044 
00045 // comment out to inhibit serialization debugging
00046 //#define SDEBUG
00047 
00048 #endif
00049 
00050 
00051 BinarySerializer::BinarySerializer(SerializerType type, ref<VFile> archive)
00052   : Serializer(type,archive),
00053     stream(output?archive->iostream(iostream::binary|iostream::out)
00054                  :archive->iostream(iostream::binary|iostream::in)),
00055     buf(*stream.rdbuf())
00056 {
00057 #ifdef SDEBUG
00058   Debugln(Ser,"Constructed:" << (isOutput()?String("Output"):String("Input")) );
00059 #endif
00060 }
00061 
00062 BinarySerializer::BinarySerializer(SerializerType type, std::ios& stream)
00063     : Serializer(type,stream), 
00064       stream(stream),
00065       buf(*stream.rdbuf())
00066 {
00067   Assert(output?instanceof(stream, ostream)
00068                :instanceof(stream, istream));
00069 #ifdef SDEBUG
00070   Debugln(Ser,"Constructed:" << (isOutput()?String("Output"):String("Input")) );
00071 #endif
00072 }
00073 
00074 BinarySerializer::~BinarySerializer()
00075 {
00076 }
00077 
00078 
00079 bool BinarySerializer::followReferences(bool follow)
00080 {
00081 #ifdef SDEBUG
00082   Debugln(Ser,"Reference following " << (follow?String("enabled"):String("disabled")));
00083 #endif
00084   return Serializer::followReferences(follow);
00085 }
00086 
00087 
00088 Serializer& BinarySerializer::serialize(char& c, const String& memberName)
00089 {
00090   if (output) 
00091     buf.sputc(c); 
00092   else 
00093     c = char(buf.sbumpc()); 
00094 #ifdef SDEBUG
00095   //Debugln(Ser,"serialized char:" << c);
00096 #endif
00097   return *this;
00098 }
00099 
00100 Serializer& BinarySerializer::serialize(Byte& b, const String& memberName)
00101 {
00102   if (output) 
00103     buf.sputc(char(b)); 
00104   else 
00105     b = Byte(buf.sbumpc()); 
00106 #ifdef SDEBUG
00107   Debugln(Ser,"serialized Byte:" << b);
00108 #endif
00109   return *this;
00110 }
00111 
00112 Serializer& BinarySerializer::serialize(bool& b, const String& memberName)
00113 {
00114   if (output) 
00115     buf.sputc(char(b)); 
00116   else 
00117     b = Byte(buf.sbumpc()); 
00118 #ifdef SDEBUG
00119   Debugln(Ser,"serialized bool:" << b);
00120 #endif
00121   return *this;
00122 }
00123 
00124 Serializer& BinarySerializer::serialize(SInt& i, const String& memberName)
00125 {
00126   if (output) 
00127     buf.sputn((const char*)(&i),sizeof(SInt)); 
00128   else 
00129     buf.sgetn((char*)(&i),sizeof(SInt)); 
00130 #ifdef SDEBUG
00131   Debugln(Ser,"serialized SInt:" << i);
00132 #endif
00133   return *this;
00134 }
00135 
00136 Serializer& BinarySerializer::serialize(Int& i, const String& memberName)
00137 {
00138   if (output) 
00139     buf.sputn((const char*)(&i),sizeof(Int)); 
00140   else 
00141     buf.sgetn((char*)(&i),sizeof(Int)); 
00142 #ifdef SDEBUG
00143   Debugln(Ser,"serialized Int:" << i);
00144 #endif
00145   return *this;
00146 }
00147 
00148 Serializer& BinarySerializer::serialize(LInt& i, const String& memberName)
00149 {
00150   if (output) 
00151     buf.sputn((const char*)(&i),sizeof(LInt)); 
00152   else 
00153     buf.sgetn((char*)(&i),sizeof(LInt)); 
00154 #ifdef SDEBUG
00155   Debugln(Ser,"serialized LInt:" << i);
00156 #endif
00157   return *this;
00158 }
00159 
00160 Serializer& BinarySerializer::serialize(String& s, const String& memberName)
00161 {
00162   if (output) {  
00163     Int len = s.length();
00164     operator()(len); // write length first
00165     if (len>0)
00166       buf.sputn((const char*)(s.c_str()),len); 
00167   }
00168   else { 
00169     Int len;
00170     operator()(len); // read length first
00171     if (len>0) {
00172       char* sbuf = new char[len+1];
00173       buf.sgetn(sbuf,len);
00174       sbuf[len]=char(0);
00175       s = String(sbuf);
00176       delete[] sbuf;
00177     }
00178   }
00179 #ifdef SDEBUG
00180   Debugln(Ser,"serialized String:" << s);
00181 #endif
00182   return *this;
00183 }
00184 
00185 Serializer& BinarySerializer::serialize(Real& r, const String& memberName)
00186 {
00187   if (output) 
00188     buf.sputn((const char*)(&r),sizeof(Real)); 
00189   else 
00190     buf.sgetn((char*)(&r),sizeof(Real)); 
00191 #ifdef SDEBUG
00192   Debugln(Ser,"serialized Real:" << r);
00193 #endif
00194   return *this;
00195 }
00196 
00197 void BinarySerializer::flush()
00198 {
00199   if (output) {
00200     if (instanceof(stream,std::ostream)) {
00201       std::ostream* out = dynamic_cast<std::ostream*>(&stream);
00202       (*out) << std::flush;
00203     }
00204   } 
00205 }
00206 
00207 
00208 /// \todo optimize type name storage so it doesn't store repeated name strings
00209 Serializer::TypeModifier BinarySerializer::preSerializeObject(String& typeName, TypeModifier typeModifier, const String& memberName, bool forceTypeSerialization)
00210 {
00211   if (output) {
00212     switch (typeModifier) {
00213     case ObjectType: break;
00214     case ReferencedObjectType: 
00215       operator()(char(ReferencedObjectType)); break;
00216     case ObjectReferenceType: 
00217       operator()(char(ObjectReferenceType)); break;
00218     default:
00219       abort(String("unknown/invalid typeModifier passed for output. Member:")+memberName);
00220     }
00221     operator()(forceTypeSerialization);
00222 
00223     if (forceTypeSerialization) { // binary format doesn't contain type information unless necessary
00224       String typeString;
00225       try {
00226         typeString = base::demangleTypeidName(typeName);
00227       } catch (std::exception& e) {
00228         abort(String("error demangling typeName:")+typeName+" for member "+memberName+" - "+e.what());
00229       }
00230 
00231       operator()(typeString);
00232     }
00233     return typeModifier;
00234   }
00235   else { // input
00236 
00237     TypeModifier readTypeModifier = ObjectType;
00238     if (typeModifier != ObjectType) {    // only the type modifier of referenced objects is serialized
00239 
00240 
00241       // read type indicator (object or just ref)
00242       char c;
00243       operator()(c);
00244       readTypeModifier = TypeModifier(Int(c));
00245 
00246       if ((readTypeModifier == UnknownType) || (readTypeModifier >= InvalidType)) 
00247         abort("unknown serialized object type read");
00248     
00249       // check we read what, if anything, was expected
00250       if (typeModifier != UnknownType) {
00251         if (readTypeModifier != typeModifier)
00252           abort("unexpected serialized referenced object type read");
00253       }
00254     }
00255 
00256     bool typeSerialized(false);
00257     operator()(typeSerialized);
00258     if (typeSerialized) {
00259       String readTypeName;
00260       operator()(readTypeName);
00261       if (typeName.empty())
00262         typeName = readTypeName;
00263       else 
00264         if (typeName != readTypeName)
00265           abort(String("read type "+readTypeName+" but expected "+typeName));
00266     }
00267     else
00268       typeName.clear();      
00269 
00270     return readTypeModifier;
00271   }
00272 }

Generated on Thu Jul 29 15:56:04 2004 for OpenSim by doxygen 1.3.6