blob: 5dd712dd19c70fc120d201e81acca2d97a5e7874 [file] [log] [blame]
// Copyright 2005-2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
//
// Declares class SerializableObject
//
// Provides the base class framework for those objects to be serialized
//
// Currently we support the serialization for the following member type
//
// 1) Value-type object
// 2) CString
// 3) Nested serializable object
// 4) Vector of the value-type objects
// 5) Vector of CString
// 6) Vector of serializable objects
//
// Usage:
//
// 1) Declare the object class, which you want to serialize, to be derived
// from SerializableObject
// 2) In its constructor, call AddSerializableMember(...) to add those fields
// to be included in the serialization
// 3) If you need to serialize a vector of serializable objects,
// a) The inner object class has to implement copy constructor and
// operator =
// b) The outer object class has to override SerializeVectorNestedObject()
// and DeserializeVectorNestedObject() (see sample)
//
// Versioning support:
//
// To add new fields in the new version, call
// AddSerializableMember(version, &member);
// If "version" is not given, it is 0 by default.
//
// To deserialize the data for latest version, call
// Deserialize(data, size, kLatestSerializableVersion);
// To deserialize the data for a particular version, call
// Deserialize(data, size, version);
//
// Sample:
//
// class FooObject : public SerializableObject {
// ...
// };
//
// class BarObject : public SerializableObject {
// public:
// BarObject() {
// AddSerializableMember(&value1_);
// AddSerializableMember(&value2_);
// AddSerializableMember(&value3_);
// AddSerializableMember(&value4_);
// AddSerializableMember(&value5_);
// AddSerializableMember(&value6_);
// AddSerializableMember(1, &value7_); // New version
// }
//
// protected:
// virtual bool SerializeVectorNestedObject(std::vector<byte>* data,
// const byte* ptr) const {
// ASSERT(data, (_T("")));
// ASSERT(ptr, (_T("")));
// if (ptr == reinterpret_cast<const byte*>(&value6_))
// return SerializeVectorNestedObjectHelper(data, &value6_);
// return false;
// }
//
// virtual bool DeserializeVectorNestedObject(byte** data,
// int size,
// byte* ptr,
// uint32 version) {
// ASSERT(data, (_T("")));
// ASSERT(*data, (_T("")));
// ASSERT(ptr, (_T("")));
// if (ptr == reinterpret_cast<byte*>(&value6_))
// return DeserializeVectorNestedObjectHelper(data,
// size,
// &value6_,
// version);
// return false;
// }
//
// private:
// int value1_;
// CString value2_;
// FooObject value3_;
// std::vector<byte> value4_;
// std::vector<CString> value5_;
// std::vector<BarObject> value6_;
// int value7_;
// };
//
// Binary format:
//
// 1) Value type: data
// e.g. 100 => 64 00 00 00
// 2) CString: size count data
// e.g. "ABC" => 02 00 00 00 03 00 00 00 41 00 42 00 43 00
// 3) Vector: size count data
// e.g. vector<int> = {1, 2}
// => 04 00 00 00 02 00 00 00 01 00 00 00 02 00 00 00
//
// TODO(omaha):
// 1) Define struct TypeTrait for all type-related info
// 2) Initialize TypeTrait on per-type basis instead of per-object basis
#ifndef OMAHA_COMMON_SERIALIZABLE_OBJECT_H_
#define OMAHA_COMMON_SERIALIZABLE_OBJECT_H_
#include <vector>
#include "base/basictypes.h"
#include "omaha/base/debug.h"
#include "omaha/base/type_utils.h"
namespace omaha {
// Constants
const uint32 kLatestSerializableVersion = 0xFFFFFFFF;
// Serializable object
class SerializableObject {
private:
// Define SerializableMemberType, for internal use
typedef uint32 SerializableMemberType;
#define SERIALIZABLE_VALUE_TYPE 1
#define SERIALIZABLE_CSTRING 2
#define SERIALIZABLE_NESTED_OBJECT 3
#define SERIALIZABLE_VECTOR 0x8000
// Serializable member info
struct SerializableMemberInfo {
byte* ptr; // Pointers to the serializable member
SerializableMemberType type; // Type of the serializable member
int size; // Size of the serializable member
uint32 version; // Version when the member is added
SerializableMemberInfo()
: ptr(NULL), type(SERIALIZABLE_VALUE_TYPE), size(0) {}
};
public:
// Constructor
SerializableObject() {}
// Destructor
virtual ~SerializableObject() {}
// Serialize
bool Serialize(std::vector<byte>* data) const;
// Deserialize the data for the latest version
bool Deserialize(byte* data, int size) {
return Deserialize(data, size, kLatestSerializableVersion);
}
// Deserialize the data for a particular version
bool Deserialize(byte* data, int size, uint32 version);
protected:
// Clear the serializable member list
void ClearSerializableMemberList() {
members_.clear();
}
// Add value-typed member to the serializable member list
template<typename T>
void AddSerializableMember(T* ptr) {
return AddSerializableMember(0, ptr);
}
// Add value-typed member to the serializable member list
template<typename T>
void AddSerializableMember(uint32 version, T* ptr) {
if (SUPERSUBCLASS(SerializableObject, T)) {
#pragma warning(push)
// reinterpret_cast used between related classes
#pragma warning(disable : 4946)
return AddSerializableMember(version,
reinterpret_cast<SerializableObject*>(ptr),
sizeof(T));
#pragma warning(pop)
}
SerializableMemberInfo member;
member.ptr = reinterpret_cast<byte*>(ptr);
member.type = SERIALIZABLE_VALUE_TYPE;
member.size = sizeof(T);
member.version = version;
members_.push_back(member);
}
// Add CString-typed member to the serializable member list
void AddSerializableMember(CString* ptr) {
AddSerializableMember(0, ptr);
}
// Add CString-typed member to the serializable member list
void AddSerializableMember(uint32 version, CString* ptr) {
SerializableMemberInfo member;
member.ptr = reinterpret_cast<byte*>(ptr);
member.type = SERIALIZABLE_CSTRING;
member.size = sizeof(TCHAR);
member.version = version;
members_.push_back(member);
}
// Add nested serializable member to the serializable member list
void AddSerializableMember(SerializableObject* ptr, int size) {
AddSerializableMember(0, ptr, size);
}
// Add nested serializable member to the serializable member list
void AddSerializableMember(uint32 version,
SerializableObject* ptr,
int size) {
SerializableMemberInfo member;
member.ptr = reinterpret_cast<byte*>(ptr);
member.type = SERIALIZABLE_NESTED_OBJECT;
member.size = size;
member.version = version;
members_.push_back(member);
}
// Add vector-typed member to the serializable member list
template<typename T>
void AddSerializableMember(std::vector<T>* ptr) {
AddSerializableMember(0, ptr);
}
// Add vector-typed member to the serializable member list
template<typename T>
void AddSerializableMember(uint32 version, std::vector<T>* ptr) {
SerializableMemberInfo member;
member.ptr = reinterpret_cast<byte*>(ptr);
member.version = version;
if (SUPERSUBCLASS(CString, T)) {
member.type =
static_cast<SerializableMemberType>(SERIALIZABLE_VECTOR |
SERIALIZABLE_CSTRING);
member.size = sizeof(TCHAR);
} else if (SUPERSUBCLASS(SerializableObject, T)) {
member.type =
static_cast<SerializableMemberType>(SERIALIZABLE_VECTOR |
SERIALIZABLE_NESTED_OBJECT);
member.size = sizeof(T);
} else {
member.type =
static_cast<SerializableMemberType>(SERIALIZABLE_VECTOR |
SERIALIZABLE_VALUE_TYPE);
member.size = sizeof(T);
}
members_.push_back(member);
}
// If there is a vector of SerializableObject to be serialized, the derived
// class need to provide the implementation
virtual bool SerializeVectorNestedObject(std::vector<byte>*,
const byte*) const {
ASSERT(false, (_T("Provide the implementation in the derived class.")));
return false;
}
// Helper method to serialize a vector of SerializableObject
template<typename T>
bool SerializeVectorNestedObjectHelper(std::vector<byte>* data,
const std::vector<T>* list) const {
ASSERT(data, (_T("")));
ASSERT(list, (_T("")));
ASSERT(SUPERSUBCLASS(SerializableObject, T), (_T("")));
// Size of SerializableObject is unknown
SerializeSizeAndCount(data, 0, list->size());
for (size_t i = 0; i < list->size(); ++i) {
// To work around compiler complaint while using dynamic_cast
SerializableObject* so =
const_cast<SerializableObject*>(
static_cast<const SerializableObject*>(&(*list)[i]));
bool res = so->Serialize(data);
if (!res)
return false;
}
return true;
}
// If there is a vector of SerializableObject to be serialized, the derived
// class need to provide the implementation
virtual bool DeserializeVectorNestedObject(byte**, int, byte*, uint32) {
ASSERT(false, (_T("provide the implementation in the derived class.")));
return false;
}
// Helper method to deserialize a vector of SerializableObject
template<typename T>
bool DeserializeVectorNestedObjectHelper(byte** data,
int size,
std::vector<T>* list,
uint32 version) {
ASSERT(data, (_T("")));
ASSERT(*data, (_T("")));
ASSERT(size, (_T("")));
ASSERT(list, (_T("")));
ASSERT(SUPERSUBCLASS(SerializableObject, T), (_T("")));
byte* tail = *data + size;
// Size of SerializableObject is unknown
int count = 0;
bool res = DeserializeSizeAndCount(&count, 0, data, size);
if (!res)
return false;
for (int i = 0; i < count; ++i) {
T obj;
bool res = obj.DeserializeHelper(data, tail - *data, version);
if (!res)
return false;
list->push_back(obj);
}
return true;
}
private:
// Serialize the size and count values
void SerializeSizeAndCount(std::vector<byte>* data,
int size,
int count) const;
// Serialize a list of value-typed elements
void SerializeValueList(std::vector<byte>* ser_data,
const byte* raw_data,
int size,
int count) const;
// Deserialize helper
bool DeserializeHelper(byte** data, int size, uint32 version);
// Deserialize the size and count values
bool DeserializeSizeAndCount(int* count,
int size,
byte** ser_data,
int ser_size) const;
// Deserialize a list of value-typed elements
bool DeserializeValueList(std::vector<byte>* raw_data,
int size,
byte** ser_data,
int ser_size);
// List of serializable members
std::vector<SerializableMemberInfo> members_;
// We need to initialize TypeTrait on per-type basis instead of per-object
// basis and remove the following use of macro.
DISALLOW_EVIL_CONSTRUCTORS(SerializableObject);
};
} // namespace omaha
#endif // OMAHA_COMMON_SERIALIZABLE_OBJECT_H_