1 /* 2 * Copyright 2006-2008 The FLWOR Foundation. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 #ifndef ZORBA_BINARY_PLAN_ITERATOR_SERIALIZATION 18 #define ZORBA_BINARY_PLAN_ITERATOR_SERIALIZATION 19 20 #include <time.h> 21 22 #include "zorbamisc/config/platform.h" 23 24 #include <string> 25 #include <list> 26 #include <vector> 27 #include <assert.h> 28 #include <iostream> 29 #include <typeinfo> 30 #include <string.h> 31 32 #include "zorbaserialization/archiver_consts.h" 33 34 namespace zorba 35 { 36 37 class XQPCollator; 38 39 namespace serialization 40 { 41 42 class SerializeBaseClass; 43 class Archiver; 44 class MemArchiver; 45 class ClassDeserializer; 46 47 48 /******************************************************************************* 49 50 The classes and macros defined in this file provide a generic infrastructure 51 for making an arbitrary c++ class serializable. This infrastructure is provided 52 for convenience; not every c++ type has to adopt this inftrasture. Class that 53 do follow this infrastructure can be serialized via the template operators: 54 55 void operator&(Archiver& ar, T& obj) and 56 void operator&(Archiver& ar, T*& obj), 57 58 which are defined in serialize_template_types.h. These operators assume that 59 T is a class that has the following 2 methods: 60 61 get_class_name_str() and serialize_internal() 62 ********************************************************************************/ 63 64 65 /******************************************************************************* 66 There is only one global instance of this class. 67 68 theClassFactories: 69 ------------------ 70 This map associates the name of a class C with a pointer to the ClassDeserializer 71 obj associated with C (if any such obj actually exists). The map is populated 72 "automatically", during the instantiation of each ClassDeserializer obj; the 73 constructor of each such obj places an entry into the map. 74 75 harcoded_objects_archive: 76 ------------------------- 77 78 ********************************************************************************/ 79 class ClassSerializer 80 { 81 friend class Archiver; 82 83 typedef std::vector<ClassDeserializer*> ClassFactoriesMap; 84 85 public: 86 static const unsigned long g_zorba_classes_version; 87 88 private: 89 ClassFactoriesMap theClassFactories; 90 91 MemArchiver * harcoded_objects_archive; 92 93 public: 94 clock_t t0; 95 clock_t t1; 96 97 public: 98 static ClassSerializer* getInstance(); 99 100 public: 101 ClassSerializer(); 102 103 ~ClassSerializer(); 104 105 void register_class_factory(TypeCode code, ClassDeserializer* d); 106 107 ClassDeserializer* get_class_factory(TypeCode code); 108 109 Archiver* getArchiverForHardcodedObjects(); 110 111 void destroyArchiverForHardcodedObjects(); 112 get_registration_time()113 clock_t get_registration_time() { return t1 - t0; } 114 }; 115 116 117 /******************************************************************************* 118 A class that may be used as the base for other c++ classes that need to be 119 serialized. 120 121 The serialize_internal() method is called by the template operators: 122 void operator&(Archiver& ar, T& obj) and 123 void operator&(Archiver& ar, T*& obj). 124 125 ********************************************************************************/ 126 class ZORBA_DLL_PUBLIC SerializeBaseClass 127 { 128 public: ~SerializeBaseClass()129 virtual ~SerializeBaseClass() {} 130 131 virtual serialization::TypeCode get_serializer_type_code() const = 0; 132 133 virtual void serialize_internal(Archiver& ar) = 0; 134 }; 135 136 137 /******************************************************************************* 138 Every serializable class C has a nested member class D that is a subclass of 139 ClassDeserializer. Furthermore, every serializable class has a static data 140 member of type D, whose initilization (via its default constructor) causes 141 class C to be registered in the global ClassSerializer instance. 142 ********************************************************************************/ 143 class ClassDeserializer 144 { 145 public: ~ClassDeserializer()146 virtual ~ClassDeserializer() { } 147 148 virtual SerializeBaseClass* create_new(Archiver& ar) = 0; 149 }; 150 151 152 #define SERIALIZABLE_CLASS_FACTORY_DECL(class_name, creator) \ 153 template<class T_serialized_class> \ 154 class class_factory : public ::zorba::serialization::ClassDeserializer \ 155 { \ 156 public: \ 157 class_factory() \ 158 { \ 159 serialization::ClassSerializer::getInstance()-> \ 160 register_class_factory(T_serialized_class::get_serializer_type_code_static(), this); \ 161 } \ 162 \ 163 virtual serialization::SerializeBaseClass* create_new(serialization::Archiver& ar) \ 164 { \ 165 return creator; \ 166 } \ 167 }; 168 169 170 /******************************************************************************* 171 172 ********************************************************************************/ 173 #define SERIALIZABLE_CLASS(class_name) \ 174 virtual void serialize_internal(::zorba::serialization::Archiver& ar); \ 175 \ 176 static serialization::TypeCode theTypeCode; \ 177 \ 178 virtual serialization::TypeCode get_serializer_type_code() const \ 179 { \ 180 return theTypeCode; \ 181 } \ 182 \ 183 static serialization::TypeCode get_serializer_type_code_static() \ 184 { \ 185 return theTypeCode; \ 186 } \ 187 \ 188 SERIALIZABLE_CLASS_FACTORY_DECL(class_name, new class_name(ar)) \ 189 static class_factory<class_name> g_class_factory; \ 190 191 192 #define SERIALIZABLE_ABSTRACT_CLASS(class_name) \ 193 virtual void serialize_internal(::zorba::serialization::Archiver& ar); \ 194 \ 195 virtual serialization::TypeCode get_serializer_type_code() const \ 196 { \ 197 return serialization::TYPE_LAST; \ 198 } 199 200 201 #define SERIALIZE_INTERNAL_METHOD(class_name) \ 202 void class_name::serialize_internal(::zorba::serialization::Archiver& ar) \ 203 { \ 204 if (ar.is_serialize_base_class()) \ 205 ar.set_serialize_base_class(false); \ 206 \ 207 class_name::serialize(ar); \ 208 } 209 210 211 #define SERIALIZABLE_CLASS_VERSIONS(class_name) \ 212 serialization::TypeCode class_name::theTypeCode = \ 213 serialization::TYPE_##class_name; \ 214 \ 215 class_name::class_factory<class_name> class_name::g_class_factory; \ 216 \ 217 SERIALIZE_INTERNAL_METHOD(class_name) 218 219 220 #define SERIALIZABLE_CLASS_VERSIONS_2(class_name, type_code) \ 221 serialization::TypeCode class_name::theTypeCode = \ 222 serialization::type_code; \ 223 \ 224 class_name::class_factory<class_name> class_name::g_class_factory; \ 225 \ 226 SERIALIZE_INTERNAL_METHOD(class_name) 227 228 229 /******************************************************************************* 230 231 ********************************************************************************/ 232 233 #define SERIALIZABLE_TEMPLATE_CLASS(class_name) \ 234 virtual void serialize_internal(::zorba::serialization::Archiver& ar) \ 235 { \ 236 if (ar.is_serialize_base_class()) \ 237 ar.set_serialize_base_class(false); \ 238 \ 239 class_name::serialize(ar); \ 240 } \ 241 \ 242 static serialization::TypeCode theTypeCode; \ 243 \ 244 virtual serialization::TypeCode get_serializer_type_code() const \ 245 { \ 246 return theTypeCode; \ 247 } \ 248 \ 249 static serialization::TypeCode get_serializer_type_code_static() \ 250 { \ 251 return theTypeCode; \ 252 } \ 253 \ 254 SERIALIZABLE_CLASS_FACTORY_DECL(class_name, new class_name(ar)) 255 256 257 #define SERIALIZABLE_TEMPLATE_ABSTRACT_CLASS(class_name) \ 258 virtual void serialize_internal(::zorba::serialization::Archiver& ar) \ 259 { \ 260 if (ar.is_serialize_base_class()) \ 261 ar.set_serialize_base_class(false); \ 262 \ 263 class_name::serialize(ar); \ 264 } \ 265 \ 266 virtual serialization::TypeCode get_serializer_type_code() const \ 267 { \ 268 return serialization::TYPE_LAST; \ 269 } 270 271 272 // 273 // Static members of template classes with one template param. 274 // 275 // The "index" param of the macro is used as a unique id for each specific 276 // instantiation of the template class. 277 // 278 // Example: 279 // 280 // SERIALIZABLE_TEMPLATE_INSTANCE_VERSIONS( 281 // TypedValueCompareIterator, 282 // TypedValueCompareIterator<store::XS_DOUBLE>, 283 // 1) 284 // 285 #define SERIALIZABLE_TEMPLATE_INSTANCE(template_name, instance_name, index) \ 286 \ 287 instance_name::class_factory<instance_name> \ 288 g_class_factory_##template_name##_##index; \ 289 \ 290 template<> serialization::TypeCode instance_name::theTypeCode = \ 291 serialization::TYPE_##template_name##_##index; 292 293 // 294 // If the template class has more than one template params, e.g. Foo<T1, T2>, 295 // then we need this macro because we cannot pass Foo<T1, T2> as the instance_name 296 // param of the SERIALIZABLE_TEMPLATE_INSTANCE_VERSIONS macro. This is because 297 // the "," inside Foo<T1, T2> will make it appear as two params. 298 // 299 // Example: 300 // 301 // SERIALIZABLE_TEMPLATE_INSTANCE_VERSIONS2( 302 // serializable_HashEntry, 303 // serializable_HashEntry<store::Item*, 304 // StaticallyKnownCollection_t>, 305 // 1) 306 // 307 #define SERIALIZABLE_TEMPLATE_INSTANCE_2(template_name, instance_name, second_T, index) \ 308 \ 309 instance_name, second_T::class_factory<instance_name,second_T> \ 310 g_class_factory_##template_name##_##index; \ 311 \ 312 template<> serialization::TypeCode instance_name, second_T::theTypeCode = \ 313 serialization::TYPE_##template_name##_##index; 314 315 316 /******************************************************************************* 317 Constructors to be used during deserialization 318 ********************************************************************************/ 319 320 #define SERIALIZABLE_CLASS_CONSTRUCTOR(class_name) \ 321 class_name(::zorba::serialization::Archiver& ar) \ 322 : \ 323 ::zorba::serialization::SerializeBaseClass() \ 324 { \ 325 } 326 327 #define SERIALIZABLE_CLASS_CONSTRUCTOR2(class_name, base_class) \ 328 class_name(::zorba::serialization::Archiver& ar) \ 329 : \ 330 base_class(ar) \ 331 { \ 332 } 333 334 #define SERIALIZABLE_CLASS_CONSTRUCTOR2_NULL_PARAM1(class_name, base_class, param1) \ 335 class_name(::zorba::serialization::Archiver& ar) \ 336 : \ 337 base_class(ar), \ 338 param1(NULL) \ 339 { \ 340 } 341 342 #define SERIALIZABLE_CLASS_CONSTRUCTOR2_NULL_PARAM2(class_name, base_class, param1, param2) \ 343 class_name(::zorba::serialization::Archiver& ar) \ 344 : \ 345 base_class(ar), \ 346 param1(NULL), \ 347 param2(NULL) \ 348 { \ 349 } 350 351 352 #define SERIALIZABLE_CLASS_CONSTRUCTOR3(class_name, base_class1, base_class2) \ 353 class_name(::zorba::serialization::Archiver& ar) \ 354 : \ 355 base_class1(ar), \ 356 base_class2(ar) \ 357 { \ 358 } 359 360 // 361 // Example: 362 // 363 // SERIALIZABLE_CLASS_CONSTRUCTOR2T(SequentialIterator, 364 // NaryBaseIterator<SequentialIterator, PlanIteratorState>); 365 // 366 #define SERIALIZABLE_CLASS_CONSTRUCTOR2T(class_name, base_class, templ2) \ 367 class_name(::zorba::serialization::Archiver& ar) \ 368 : \ 369 base_class , templ2(ar) \ 370 { \ 371 } 372 373 374 // 375 // Example: 376 // 377 // SERIALIZABLE_CLASS_CONSTRUCTOR3T(SpecificNumArithIterator, 378 // BinaryBaseIterator<SpecificNumArithIterator<Operation, Type>, PlanIteratorState>); 379 // 380 #define SERIALIZABLE_CLASS_CONSTRUCTOR3T(class_name, base_class, templ2, templ3) \ 381 class_name(::zorba::serialization::Archiver& ar) \ 382 : \ 383 base_class , templ2, templ3(ar) \ 384 { \ 385 } 386 387 } // namespace serialization 388 } // namespace zorba 389 390 #endif 391 /* 392 * Local variables: 393 * mode: c++ 394 * End: 395 */ 396 /* vim:set et sw=2 ts=2: */ 397