00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <base/Serializer>
00026
00027 #include <base/Serializable>
00028
00029 using base::Serializer;
00030 using base::Serializable;
00031
00032
00033 #ifdef DEBUG
00034
00035
00036
00037
00038 #endif
00039
00040
00041 Serializer::Serializer(SerializerType type)
00042 : output(type==Output), follow(true), aborted(false),
00043 serializePointerRecursionDepth(0)
00044 {
00045 ptrs.push_back(0);
00046 serialized.push_back(true);
00047 }
00048
00049 Serializer::Serializer(SerializerType type, ref<VFile> archive)
00050 : output(type==Output), follow(true), aborted(false),
00051 serializePointerRecursionDepth(0)
00052 {
00053 ptrs.push_back(0);
00054 serialized.push_back(true);
00055 }
00056
00057 Serializer::Serializer(SerializerType type, std::ios& stream)
00058 : output(type==Output), follow(true), aborted(false),
00059 serializePointerRecursionDepth(0)
00060 {
00061 ptrs.push_back(0);
00062 serialized.push_back(true);
00063 }
00064
00065 Serializer::~Serializer()
00066 {
00067 if (isOutput() && !aborted) {
00068
00069
00070 Int outstandingSerializationCount = 0;
00071 for(Int pi=0; pi<serialized.size(); pi++)
00072 if (!serialized[pi])
00073 outstandingSerializationCount++;
00074 if (outstandingSerializationCount>0) {
00075 Logln("Serializer destruction with outstanding object serializations (objects referenced in the Output stream, but not serialized) - " << outstandingSerializationCount << " objects.");
00076 }
00077 }
00078 }
00079
00080
00081 bool Serializer::followReferences(bool follow)
00082 {
00083 if (!follow)
00084 depthAtFollowDisable = serializePointerRecursionDepth;
00085 bool oldfollow = this->follow;
00086 this->follow = follow;
00087 return oldfollow;
00088 }
00089
00090
00091
00092 const String Serializer::inputToConstErrorString("cannot input to a const variable");
00093
00094
00095 Serializer& Serializer::serialize(Serializable& r, const String& memberName)
00096 {
00097 String typeName(typeid(r).name());
00098 preSerializeObject(typeName, ObjectType, memberName);
00099 r.serialize(*this);
00100 postSerializeObject(memberName);
00101 return *this;
00102 }
00103
00104
00105
00106 Serializer& Serializer::operator()(Vector& v, const String& memberName)
00107 {
00108 comment(memberName);
00109 if(isOutput()) {
00110 operator()(v.size(),"dim");
00111 }
00112 else {
00113 Int dim;
00114 operator()(dim,"dim");
00115 v.resize(dim);
00116 }
00117
00118 for(Int i=0; i<v.size(); i++)
00119 operator()(v[i]);
00120
00121 return *this;
00122 }
00123
00124
00125 Serializer& Serializer::operator()(Matrix& m, const String& memberName)
00126 {
00127 comment(memberName);
00128 if(isOutput()) {
00129 operator()(m.size1(),"rows");
00130 operator()(m.size2(),"cols");
00131 }
00132 else {
00133 Int rows, cols;
00134 operator()(rows,"rows");
00135 operator()(cols,"cols");
00136 m.resize(rows,cols);
00137 }
00138
00139 for(Int r=0; r<m.size1(); r++)
00140 for(Int c=0; c<m.size2(); c++)
00141 operator()(m(r,c));
00142
00143 return *this;
00144 }
00145
00146
00147
00148 inline Int Serializer::ptrIndex(Serializable* p)
00149 {
00150 for(Int i=ptrs.size()-1; i>0; i--)
00151 if (ptrs[i] == p) return i;
00152 if (ptrs[0] == p) return 0;
00153 return ptrs.size();
00154 }
00155
00156
00157
00158 void Serializer::serializePointer(Serializable*& p, Serializable::SerializableInstantiator* i, const String& memberName, bool forceTypeSerialization)
00159 {
00160 serializePointerRecursionDepth++;
00161
00162 if (output) {
00163
00164 Int pi = ptrIndex(p);
00165 if (pi == ptrs.size()) {
00166
00167
00168 if (follow || (!follow && (serializePointerRecursionDepth==depthAtFollowDisable+1)) ) {
00169 #ifdef SDEBUG
00170 Debugln(Ser,String(serializePointerRecursionDepth,' ') << "serializing(out) obj(" << (p?String(instanceof(*p,Object)?dynamic_cast<Object*>(p)->className():"unknown"):"null") << ") [" << pi << "] first encounter");
00171 #endif
00172
00173 String typeName(typeid(*p).name());
00174 preSerializeObject(typeName,ReferencedObjectType, memberName, forceTypeSerialization);
00175 serializeReferenceIndex(pi);
00176 ptrs.at(pi) = p;
00177 serialized.at(pi) = true;
00178 p->serialize(*this);
00179 postSerializeObject(memberName);
00180 }
00181 else {
00182 #ifdef SDEBUG
00183 Debugln(Ser,String(serializePointerRecursionDepth,' ') << "serializing(out) ptr(" << (p?String(instanceof(*p,Object)?dynamic_cast<Object*>(p)->className():"unknown"):"null") << ") [" << pi << "] first encounter");
00184 #endif
00185
00186 String typeName(typeid(*p).name());
00187 preSerializeObject(typeName,ObjectReferenceType, memberName, forceTypeSerialization);
00188 serializeReferenceIndex(pi);
00189 ptrs.at(pi) = p;
00190 serialized.at(pi) = false;
00191 postSerializeObject(memberName);
00192 }
00193
00194 }
00195 else {
00196
00197 if ( (follow || (!follow && (serializePointerRecursionDepth==depthAtFollowDisable+1)))
00198 && !serialized[pi]) {
00199 #ifdef SDEBUG
00200 Debugln(Ser,String(serializePointerRecursionDepth,' ') << "serializing(out) obj(" << (p?String(instanceof(*p,Object)?dynamic_cast<Object*>(p)->className():"unknown"):"null") << ") [" << pi << "]");
00201 #endif
00202
00203
00204 String typeName(typeid(*p).name());
00205 preSerializeObject(typeName,ReferencedObjectType, memberName, forceTypeSerialization);
00206 serializeReferenceIndex(pi);
00207 serialized[pi] = true;
00208 p->serialize(*this);
00209 postSerializeObject(memberName);
00210 }
00211 else {
00212 #ifdef SDEBUG
00213 Debugln(Ser,String(serializePointerRecursionDepth,' ') << "serializing(out) ptr(" << (p?String(instanceof(*p,Object)?dynamic_cast<Object*>(p)->className():"unknown"):"null") << ") [" << pi << "]");
00214 #endif
00215
00216
00217 String typeName(typeid(*p).name());
00218 preSerializeObject(typeName,ObjectReferenceType, memberName, forceTypeSerialization);
00219 serializeReferenceIndex(pi);
00220 postSerializeObject(memberName);
00221 }
00222 }
00223 }
00224 else {
00225
00226 String typeName;
00227 TypeModifier readTypeModifier = preSerializeObject(typeName,UnknownType, memberName, forceTypeSerialization);
00228
00229 if (readTypeModifier == ReferencedObjectType) {
00230
00231
00232 Int pi;
00233 serializeReferenceIndex(pi);
00234
00235 if (pi > ptrs.size())
00236 throw serialization_error(Exception("serialization input stream corrupted (object out of sequence)"));
00237 else {
00238 if (pi == ptrs.size()) {
00239
00240 if (p==0) {
00241 if (i != 0)
00242 p = i->newSerializable();
00243 else {
00244 try{
00245 const Serializable::SerializableInstantiator& i(Serializable::getSerializableInstantiator(String(), typeName));
00246 p = i.newSerializable();
00247 } catch (std::exception& e) { abort(e.what()); }
00248 }
00249 }
00250 Assert(p);
00251
00252 if (!typeName.empty()) {
00253 if (typeName != base::className(typeid(*p)))
00254 throw serialization_error(Exception(String("read unexpected object type: ")+typeName+" expected "+base::className(typeid(*p))));
00255 }
00256
00257 #ifdef SDEBUG
00258 Debugln(Ser,String(serializePointerRecursionDepth,' ') << "serializing(in) obj(" << (p?String(instanceof(*p,Object)?dynamic_cast<Object*>(p)->className():"unknown"):"null") << ") [" << pi << "]" << ((pi == ptrs.size())?" instantiated":"") );
00259 #endif
00260 ptrs.at(pi) = p;
00261 }
00262 else {
00263
00264
00265 p = ptrs[pi];
00266 }
00267
00268 p->serialize(*this);
00269
00270 postSerializeObject(memberName);
00271 }
00272 }
00273 else if (readTypeModifier == ObjectReferenceType) {
00274
00275 Int pi;
00276 serializeReferenceIndex(pi);
00277
00278 if (pi>ptrs.size())
00279 throw serialization_error(Exception("serialization input stream corrupted (reference to object not yet encountered)"));
00280 else {
00281 if (pi == ptrs.size()) {
00282
00283
00284 if (p==0) {
00285 if (i != 0)
00286 p = i->newSerializable();
00287 else {
00288 try {
00289 const Serializable::SerializableInstantiator& i(Serializable::getSerializableInstantiator(String(), typeName));
00290 p = i.newSerializable();
00291 } catch (std::exception& e) { abort(e.what()); }
00292 }
00293 }
00294 Assert(p);
00295
00296 if (!typeName.empty()) {
00297 if (typeName != base::className(typeid(*p)))
00298 throw serialization_error(Exception(String("read unexpected object reference type: ")+typeName+" expected "+base::className(typeid(*p))));
00299 }
00300 #ifdef SDEBUG
00301 Debugln(Ser,String(serializePointerRecursionDepth,' ') << "serializing(in) ptr(" << (p?String(instanceof(*p,Object)?dynamic_cast<Object*>(p)->className():"unknown"):"null") << ") [" << pi << "] instantiated" );
00302 #endif
00303 ptrs.at(pi) = p;
00304 }
00305 else {
00306 p = ptrs[pi];
00307 Assert(p);
00308 #ifdef SDEBUG
00309 Debugln(Ser,String(serializePointerRecursionDepth,' ') << "serializing(in) ptr(" << (p?String(instanceof(*p,Object)?dynamic_cast<Object*>(p)->className():"unknown"):"null") << ") [" << pi << "]" );
00310 #endif
00311
00312 }
00313 }
00314
00315 postSerializeObject(memberName);
00316
00317 }
00318 else
00319 throw serialization_error(Exception("serialization input stream corrupted (unknown reference type)"));
00320 }
00321
00322 serializePointerRecursionDepth--;
00323
00324 }
00325
00326
00327 void Serializer::abort(const String& exceptionString)
00328 {
00329 if (!aborted) {
00330 aborted=true;
00331 Logln(exceptionString);
00332 throw serialization_error(Exception(exceptionString));
00333 }
00334 }