| OLD | NEW |
| (Empty) |
| 1 // Copyright 2005-2009 Google Inc. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 // ======================================================================== | |
| 15 // | |
| 16 // Declares class SerializableObject | |
| 17 // | |
| 18 // Provides the base class framework for those objects to be serialized | |
| 19 // | |
| 20 // Currently we support the serialization for the following member type | |
| 21 // | |
| 22 // 1) Value-type object | |
| 23 // 2) CString | |
| 24 // 3) Nested serializable object | |
| 25 // 4) Vector of the value-type objects | |
| 26 // 5) Vector of CString | |
| 27 // 6) Vector of serializable objects | |
| 28 // | |
| 29 // Usage: | |
| 30 // | |
| 31 // 1) Declare the object class, which you want to serialize, to be derived | |
| 32 // from SerializableObject | |
| 33 // 2) In its constructor, call AddSerializableMember(...) to add those fields | |
| 34 // to be included in the serialization | |
| 35 // 3) If you need to serialize a vector of serializable objects, | |
| 36 // a) The inner object class has to implement copy constructor and | |
| 37 // operator = | |
| 38 // b) The outer object class has to override SerializeVectorNestedObject() | |
| 39 // and DeserializeVectorNestedObject() (see sample) | |
| 40 // | |
| 41 // Versioning support: | |
| 42 // | |
| 43 // To add new fields in the new version, call | |
| 44 // AddSerializableMember(version, &member); | |
| 45 // If "version" is not given, it is 0 by default. | |
| 46 // | |
| 47 // To deserialize the data for latest version, call | |
| 48 // Deserialize(data, size, kLatestSerializableVersion); | |
| 49 // To deserialize the data for a particular version, call | |
| 50 // Deserialize(data, size, version); | |
| 51 // | |
| 52 // Sample: | |
| 53 // | |
| 54 // class FooObject : public SerializableObject { | |
| 55 // ... | |
| 56 // }; | |
| 57 // | |
| 58 // class BarObject : public SerializableObject { | |
| 59 // public: | |
| 60 // BarObject() { | |
| 61 // AddSerializableMember(&value1_); | |
| 62 // AddSerializableMember(&value2_); | |
| 63 // AddSerializableMember(&value3_); | |
| 64 // AddSerializableMember(&value4_); | |
| 65 // AddSerializableMember(&value5_); | |
| 66 // AddSerializableMember(&value6_); | |
| 67 // AddSerializableMember(1, &value7_); // New version | |
| 68 // } | |
| 69 // | |
| 70 // protected: | |
| 71 // virtual bool SerializeVectorNestedObject(std::vector<byte>* data, | |
| 72 // const byte* ptr) const { | |
| 73 // ASSERT(data, (_T(""))); | |
| 74 // ASSERT(ptr, (_T(""))); | |
| 75 // if (ptr == reinterpret_cast<const byte*>(&value6_)) | |
| 76 // return SerializeVectorNestedObjectHelper(data, &value6_); | |
| 77 // return false; | |
| 78 // } | |
| 79 // | |
| 80 // virtual bool DeserializeVectorNestedObject(byte** data, | |
| 81 // int size, | |
| 82 // byte* ptr, | |
| 83 // uint32 version) { | |
| 84 // ASSERT(data, (_T(""))); | |
| 85 // ASSERT(*data, (_T(""))); | |
| 86 // ASSERT(ptr, (_T(""))); | |
| 87 // if (ptr == reinterpret_cast<byte*>(&value6_)) | |
| 88 // return DeserializeVectorNestedObjectHelper(data, | |
| 89 // size, | |
| 90 // &value6_, | |
| 91 // version); | |
| 92 // return false; | |
| 93 // } | |
| 94 // | |
| 95 // private: | |
| 96 // int value1_; | |
| 97 // CString value2_; | |
| 98 // FooObject value3_; | |
| 99 // std::vector<byte> value4_; | |
| 100 // std::vector<CString> value5_; | |
| 101 // std::vector<BarObject> value6_; | |
| 102 // int value7_; | |
| 103 // }; | |
| 104 // | |
| 105 // Binary format: | |
| 106 // | |
| 107 // 1) Value type: data | |
| 108 // e.g. 100 => 64 00 00 00 | |
| 109 // 2) CString: size count data | |
| 110 // e.g. "ABC" => 02 00 00 00 03 00 00 00 41 00 42 00 43 00 | |
| 111 // 3) Vector: size count data | |
| 112 // e.g. vector<int> = {1, 2} | |
| 113 // => 04 00 00 00 02 00 00 00 01 00 00 00 02 00 00 00 | |
| 114 // | |
| 115 // TODO(omaha): | |
| 116 // 1) Define struct TypeTrait for all type-related info | |
| 117 // 2) Initialize TypeTrait on per-type basis instead of per-object basis | |
| 118 | |
| 119 #ifndef OMAHA_COMMON_SERIALIZABLE_OBJECT_H_ | |
| 120 #define OMAHA_COMMON_SERIALIZABLE_OBJECT_H_ | |
| 121 | |
| 122 #include <vector> | |
| 123 #include "base/basictypes.h" | |
| 124 #include "omaha/base/debug.h" | |
| 125 #include "omaha/base/type_utils.h" | |
| 126 | |
| 127 namespace omaha { | |
| 128 | |
| 129 // Constants | |
| 130 const uint32 kLatestSerializableVersion = 0xFFFFFFFF; | |
| 131 | |
| 132 // Serializable object | |
| 133 class SerializableObject { | |
| 134 private: | |
| 135 // Define SerializableMemberType, for internal use | |
| 136 typedef uint32 SerializableMemberType; | |
| 137 | |
| 138 #define SERIALIZABLE_VALUE_TYPE 1 | |
| 139 #define SERIALIZABLE_CSTRING 2 | |
| 140 #define SERIALIZABLE_NESTED_OBJECT 3 | |
| 141 #define SERIALIZABLE_VECTOR 0x8000 | |
| 142 | |
| 143 // Serializable member info | |
| 144 struct SerializableMemberInfo { | |
| 145 byte* ptr; // Pointers to the serializable member | |
| 146 SerializableMemberType type; // Type of the serializable member | |
| 147 int size; // Size of the serializable member | |
| 148 uint32 version; // Version when the member is added | |
| 149 | |
| 150 SerializableMemberInfo() | |
| 151 : ptr(NULL), type(SERIALIZABLE_VALUE_TYPE), size(0) {} | |
| 152 }; | |
| 153 | |
| 154 public: | |
| 155 // Constructor | |
| 156 SerializableObject() {} | |
| 157 | |
| 158 // Destructor | |
| 159 virtual ~SerializableObject() {} | |
| 160 | |
| 161 // Serialize | |
| 162 bool Serialize(std::vector<byte>* data) const; | |
| 163 | |
| 164 // Deserialize the data for the latest version | |
| 165 bool Deserialize(byte* data, int size) { | |
| 166 return Deserialize(data, size, kLatestSerializableVersion); | |
| 167 } | |
| 168 | |
| 169 // Deserialize the data for a particular version | |
| 170 bool Deserialize(byte* data, int size, uint32 version); | |
| 171 | |
| 172 protected: | |
| 173 // Clear the serializable member list | |
| 174 void ClearSerializableMemberList() { | |
| 175 members_.clear(); | |
| 176 } | |
| 177 | |
| 178 // Add value-typed member to the serializable member list | |
| 179 template<typename T> | |
| 180 void AddSerializableMember(T* ptr) { | |
| 181 return AddSerializableMember(0, ptr); | |
| 182 } | |
| 183 | |
| 184 // Add value-typed member to the serializable member list | |
| 185 template<typename T> | |
| 186 void AddSerializableMember(uint32 version, T* ptr) { | |
| 187 if (SUPERSUBCLASS(SerializableObject, T)) { | |
| 188 #pragma warning(push) | |
| 189 // reinterpret_cast used between related classes | |
| 190 #pragma warning(disable : 4946) | |
| 191 return AddSerializableMember(version, | |
| 192 reinterpret_cast<SerializableObject*>(ptr), | |
| 193 sizeof(T)); | |
| 194 #pragma warning(pop) | |
| 195 } | |
| 196 SerializableMemberInfo member; | |
| 197 member.ptr = reinterpret_cast<byte*>(ptr); | |
| 198 member.type = SERIALIZABLE_VALUE_TYPE; | |
| 199 member.size = sizeof(T); | |
| 200 member.version = version; | |
| 201 members_.push_back(member); | |
| 202 } | |
| 203 | |
| 204 // Add CString-typed member to the serializable member list | |
| 205 void AddSerializableMember(CString* ptr) { | |
| 206 AddSerializableMember(0, ptr); | |
| 207 } | |
| 208 | |
| 209 // Add CString-typed member to the serializable member list | |
| 210 void AddSerializableMember(uint32 version, CString* ptr) { | |
| 211 SerializableMemberInfo member; | |
| 212 member.ptr = reinterpret_cast<byte*>(ptr); | |
| 213 member.type = SERIALIZABLE_CSTRING; | |
| 214 member.size = sizeof(TCHAR); | |
| 215 member.version = version; | |
| 216 members_.push_back(member); | |
| 217 } | |
| 218 | |
| 219 // Add nested serializable member to the serializable member list | |
| 220 void AddSerializableMember(SerializableObject* ptr, int size) { | |
| 221 AddSerializableMember(0, ptr, size); | |
| 222 } | |
| 223 | |
| 224 // Add nested serializable member to the serializable member list | |
| 225 void AddSerializableMember(uint32 version, | |
| 226 SerializableObject* ptr, | |
| 227 int size) { | |
| 228 SerializableMemberInfo member; | |
| 229 member.ptr = reinterpret_cast<byte*>(ptr); | |
| 230 member.type = SERIALIZABLE_NESTED_OBJECT; | |
| 231 member.size = size; | |
| 232 member.version = version; | |
| 233 members_.push_back(member); | |
| 234 } | |
| 235 | |
| 236 // Add vector-typed member to the serializable member list | |
| 237 template<typename T> | |
| 238 void AddSerializableMember(std::vector<T>* ptr) { | |
| 239 AddSerializableMember(0, ptr); | |
| 240 } | |
| 241 | |
| 242 // Add vector-typed member to the serializable member list | |
| 243 template<typename T> | |
| 244 void AddSerializableMember(uint32 version, std::vector<T>* ptr) { | |
| 245 SerializableMemberInfo member; | |
| 246 member.ptr = reinterpret_cast<byte*>(ptr); | |
| 247 member.version = version; | |
| 248 | |
| 249 if (SUPERSUBCLASS(CString, T)) { | |
| 250 member.type = | |
| 251 static_cast<SerializableMemberType>(SERIALIZABLE_VECTOR | | |
| 252 SERIALIZABLE_CSTRING); | |
| 253 member.size = sizeof(TCHAR); | |
| 254 } else if (SUPERSUBCLASS(SerializableObject, T)) { | |
| 255 member.type = | |
| 256 static_cast<SerializableMemberType>(SERIALIZABLE_VECTOR | | |
| 257 SERIALIZABLE_NESTED_OBJECT); | |
| 258 member.size = sizeof(T); | |
| 259 } else { | |
| 260 member.type = | |
| 261 static_cast<SerializableMemberType>(SERIALIZABLE_VECTOR | | |
| 262 SERIALIZABLE_VALUE_TYPE); | |
| 263 member.size = sizeof(T); | |
| 264 } | |
| 265 | |
| 266 members_.push_back(member); | |
| 267 } | |
| 268 | |
| 269 // If there is a vector of SerializableObject to be serialized, the derived | |
| 270 // class need to provide the implementation | |
| 271 virtual bool SerializeVectorNestedObject(std::vector<byte>*, | |
| 272 const byte*) const { | |
| 273 ASSERT(false, (_T("Provide the implementation in the derived class."))); | |
| 274 return false; | |
| 275 } | |
| 276 | |
| 277 // Helper method to serialize a vector of SerializableObject | |
| 278 template<typename T> | |
| 279 bool SerializeVectorNestedObjectHelper(std::vector<byte>* data, | |
| 280 const std::vector<T>* list) const { | |
| 281 ASSERT(data, (_T(""))); | |
| 282 ASSERT(list, (_T(""))); | |
| 283 ASSERT(SUPERSUBCLASS(SerializableObject, T), (_T(""))); | |
| 284 | |
| 285 // Size of SerializableObject is unknown | |
| 286 SerializeSizeAndCount(data, 0, list->size()); | |
| 287 for (size_t i = 0; i < list->size(); ++i) { | |
| 288 // To work around compiler complaint while using dynamic_cast | |
| 289 SerializableObject* so = | |
| 290 const_cast<SerializableObject*>( | |
| 291 static_cast<const SerializableObject*>(&(*list)[i])); | |
| 292 bool res = so->Serialize(data); | |
| 293 if (!res) | |
| 294 return false; | |
| 295 } | |
| 296 return true; | |
| 297 } | |
| 298 | |
| 299 // If there is a vector of SerializableObject to be serialized, the derived | |
| 300 // class need to provide the implementation | |
| 301 virtual bool DeserializeVectorNestedObject(byte**, int, byte*, uint32) { | |
| 302 ASSERT(false, (_T("provide the implementation in the derived class."))); | |
| 303 return false; | |
| 304 } | |
| 305 | |
| 306 // Helper method to deserialize a vector of SerializableObject | |
| 307 template<typename T> | |
| 308 bool DeserializeVectorNestedObjectHelper(byte** data, | |
| 309 int size, | |
| 310 std::vector<T>* list, | |
| 311 uint32 version) { | |
| 312 ASSERT(data, (_T(""))); | |
| 313 ASSERT(*data, (_T(""))); | |
| 314 ASSERT(size, (_T(""))); | |
| 315 ASSERT(list, (_T(""))); | |
| 316 ASSERT(SUPERSUBCLASS(SerializableObject, T), (_T(""))); | |
| 317 | |
| 318 byte* tail = *data + size; | |
| 319 | |
| 320 // Size of SerializableObject is unknown | |
| 321 int count = 0; | |
| 322 bool res = DeserializeSizeAndCount(&count, 0, data, size); | |
| 323 if (!res) | |
| 324 return false; | |
| 325 | |
| 326 for (int i = 0; i < count; ++i) { | |
| 327 T obj; | |
| 328 bool res = obj.DeserializeHelper(data, tail - *data, version); | |
| 329 if (!res) | |
| 330 return false; | |
| 331 list->push_back(obj); | |
| 332 } | |
| 333 return true; | |
| 334 } | |
| 335 | |
| 336 private: | |
| 337 // Serialize the size and count values | |
| 338 void SerializeSizeAndCount(std::vector<byte>* data, | |
| 339 int size, | |
| 340 int count) const; | |
| 341 | |
| 342 // Serialize a list of value-typed elements | |
| 343 void SerializeValueList(std::vector<byte>* ser_data, | |
| 344 const byte* raw_data, | |
| 345 int size, | |
| 346 int count) const; | |
| 347 | |
| 348 // Deserialize helper | |
| 349 bool DeserializeHelper(byte** data, int size, uint32 version); | |
| 350 | |
| 351 // Deserialize the size and count values | |
| 352 bool DeserializeSizeAndCount(int* count, | |
| 353 int size, | |
| 354 byte** ser_data, | |
| 355 int ser_size) const; | |
| 356 | |
| 357 // Deserialize a list of value-typed elements | |
| 358 bool DeserializeValueList(std::vector<byte>* raw_data, | |
| 359 int size, | |
| 360 byte** ser_data, | |
| 361 int ser_size); | |
| 362 | |
| 363 // List of serializable members | |
| 364 std::vector<SerializableMemberInfo> members_; | |
| 365 | |
| 366 // We need to initialize TypeTrait on per-type basis instead of per-object | |
| 367 // basis and remove the following use of macro. | |
| 368 DISALLOW_EVIL_CONSTRUCTORS(SerializableObject); | |
| 369 }; | |
| 370 | |
| 371 } // namespace omaha | |
| 372 | |
| 373 #endif // OMAHA_COMMON_SERIALIZABLE_OBJECT_H_ | |
| OLD | NEW |