Commit 7f14c8de authored by darin@chromium.org's avatar darin@chromium.org

Mojo: Simplify object serialization

Eliminate ObjectTraits<T> classes in favor of putting these methods directly on
the generated *_Data classes. ObjectTraits<T> was added to hide these methods
from public classes, but now that *_Data classes are internal, there is no
longer any need for ObjectTraits<T>.

Review URL: https://codereview.chromium.org/131033002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@244071 0039d316-1c4b-4281-b951-d872f2087c98
parent 2863a6c2
...@@ -23,8 +23,8 @@ void {{proxy_name}}::{{method.name}}({{params_list(method)}}) { ...@@ -23,8 +23,8 @@ void {{proxy_name}}::{{method.name}}({{params_list(method)}}) {
{#--- Computes #} {#--- Computes #}
{%- for param in method.parameters %} {%- for param in method.parameters %}
{%- if param.kind|is_object_kind %} {%- if param.kind|is_object_kind %}
payload_size += mojo::internal::ComputeSizeOf( if (!{{param.name}}.is_null())
mojo::internal::Unwrap({{param.name}})); payload_size += mojo::internal::Unwrap({{param.name}})->ComputeSize();
{%- endif %} {%- endif %}
{%- endfor %} {%- endfor %}
...@@ -36,9 +36,9 @@ void {{proxy_name}}::{{method.name}}({{params_list(method)}}) { ...@@ -36,9 +36,9 @@ void {{proxy_name}}::{{method.name}}({{params_list(method)}}) {
{#--- Sets #} {#--- Sets #}
{% for param in method.parameters %} {% for param in method.parameters %}
{%- if param.kind|is_object_kind %} {%- if param.kind|is_object_kind %}
if (!{{param.name}}.is_null())
params->set_{{param.name}}( params->set_{{param.name}}(
mojo::internal::Clone(mojo::internal::Unwrap({{param.name}}), mojo::internal::Unwrap({{param.name}})->Clone(builder.buffer()));
builder.buffer()));
{%- elif param.kind|is_handle_kind %} {%- elif param.kind|is_handle_kind %}
params->set_{{param.name}}({{param.name}}.release()); params->set_{{param.name}}({{param.name}}.release());
{%- else %} {%- else %}
...@@ -47,7 +47,7 @@ void {{proxy_name}}::{{method.name}}({{params_list(method)}}) { ...@@ -47,7 +47,7 @@ void {{proxy_name}}::{{method.name}}({{params_list(method)}}) {
{%- endfor %} {%- endfor %}
mojo::Message message; mojo::Message message;
mojo::internal::EncodePointersAndHandles(params, &message.handles); params->EncodePointersAndHandles(&message.handles);
message.data = builder.Finish(); message.data = builder.Finish();
...@@ -81,10 +81,10 @@ bool {{class_name}}Stub::Accept(mojo::Message* message) { ...@@ -81,10 +81,10 @@ bool {{class_name}}Stub::Accept(mojo::Message* message) {
reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>( reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>(
message->data->payload); message->data->payload);
if (!mojo::internal::DecodePointersAndHandles(params, message)) if (!params->DecodePointersAndHandles(message))
return false; return false;
sink_->{{method.name}}({{params(method)}}); sink_->{{method.name}}({{params(method)}});
mojo::internal::CloseHandles(params); params->CloseHandles();
break; break;
} }
{%- endfor %} {%- endfor %}
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "./{{module_name|camel_to_underscores}}.h" #include "./{{module_name|camel_to_underscores}}.h"
#include "mojo/public/bindings/lib/bindings_serialization.h"
#include "mojo/public/bindings/lib/message_builder.h" #include "mojo/public/bindings/lib/message_builder.h"
namespace {{namespace}} { namespace {{namespace}} {
...@@ -29,16 +30,16 @@ namespace { ...@@ -29,16 +30,16 @@ namespace {
} // namespace } // namespace
{#--- Struct definitions #}
{% for struct in structs %}
{%- include "struct_definition.tmpl" %}
{%- endfor %}
{#--- Struct destructors #} {#--- Struct destructors #}
{%- for struct in structs %} {%- for struct in structs %}
{%- include "struct_destructor.tmpl" %} {%- include "struct_destructor.tmpl" %}
{%- endfor %} {%- endfor %}
{#--- Struct definitions #}
{% for struct in structs %}
{%- include "struct_definition.tmpl" %}
{%- endfor %}
} // namespace internal } // namespace internal
{#--- Struct builder definitions #} {#--- Struct builder definitions #}
...@@ -51,22 +52,3 @@ namespace { ...@@ -51,22 +52,3 @@ namespace {
{%- include "interface_definition.tmpl" %} {%- include "interface_definition.tmpl" %}
{%- endfor %} {%- endfor %}
} // namespace {{namespace}} } // namespace {{namespace}}
namespace mojo {
namespace internal {
{#--- Struct serialization definitions #}
{%- for struct in structs %}
{%- include "struct_serialization_definition.tmpl" %}
{%- endfor %}
{#--- Interface serialization definitions #}
{%- for interface in interfaces %}
{%- for method in interface.methods %}
{%- set struct = interface|struct_from_method(method) %}
{%- include "params_serialization.tmpl" %}
{%- endfor %}
{%- endfor %}
} // namespace internal
} // namespace mojo
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#ifndef {{header_guard}} #ifndef {{header_guard}}
#define {{header_guard}} #define {{header_guard}}
#include "mojo/public/bindings/lib/bindings_serialization.h" #include "mojo/public/bindings/lib/bindings_internal.h"
namespace {{namespace}} { namespace {{namespace}} {
...@@ -31,15 +31,4 @@ namespace internal { ...@@ -31,15 +31,4 @@ namespace internal {
} // namespace internal } // namespace internal
} // namespace {{namespace}} } // namespace {{namespace}}
namespace mojo {
namespace internal {
{#--- Serialization traits #}
{% for struct in structs %}
{% include "struct_serialization_traits.tmpl" %}
{%- endfor %}
} // namespace internal
} // namespace mojo
#endif // {{header_guard}} #endif // {{header_guard}}
...@@ -15,9 +15,23 @@ class {{class_name}} { ...@@ -15,9 +15,23 @@ class {{class_name}} {
{#--- Getters -#} {#--- Getters -#}
{{ struct_macros.getters(struct) }} {{ struct_macros.getters(struct) }}
private: void CloseHandles() {
friend class mojo::internal::ObjectTraits<{{class_name}}>; {%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind %}
if ({{pf.field.name}}_.ptr)
{{pf.field.name}}_.ptr->CloseHandles();
{%- endfor %}
}
void EncodePointersAndHandles(std::vector<mojo::Handle>* handles) {
{{ struct_macros.encodes(struct)|indent(4) }}
}
bool DecodePointersAndHandles(mojo::Message* message) {
{{ struct_macros.decodes(struct)|indent(4) }}
return true;
}
private:
{{class_name}}() { {{class_name}}() {
_header_.num_bytes = sizeof(*this); _header_.num_bytes = sizeof(*this);
_header_.num_fields = 3; _header_.num_fields = 3;
......
{%- import "struct_macros.tmpl" as struct_macros %}
{%- set class_name = "%s::internal::%s_Data"|format(namespace, struct.name) %}
{%- set param_name = "params" %}
template <>
class ObjectTraits<{{class_name}}> {
public:
static void CloseHandles({{class_name}}* {{param_name}}) {
{%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind %}
mojo::internal::CloseHandles({{param_name}}->{{pf.field.name}}_.ptr);
{%- endfor %}
}
static void EncodePointersAndHandles(
{{class_name}}* {{param_name}},
std::vector<Handle>* handles) {
{{ struct_macros.encodes(struct, param_name)|indent(4) }}
}
static bool DecodePointersAndHandles(
{{class_name}}* {{param_name}},
Message* message) {
{{ struct_macros.decodes(struct, param_name)|indent(4) }}
return true;
}
};
...@@ -18,9 +18,13 @@ class {{class_name}} { ...@@ -18,9 +18,13 @@ class {{class_name}} {
{#--- Getters -#} {#--- Getters -#}
{{ struct_macros.getters(struct) }} {{ struct_macros.getters(struct) }}
private: size_t ComputeSize() const;
friend class mojo::internal::ObjectTraits<{{class_name}}>; {{class_name}}* Clone(mojo::Buffer* buf) const;
void CloseHandles();
void EncodePointersAndHandles(std::vector<mojo::Handle>* handles);
bool DecodePointersAndHandles(mojo::Message* message);
private:
{{class_name}}(); {{class_name}}();
~{{class_name}}(); // NOT IMPLEMENTED ~{{class_name}}(); // NOT IMPLEMENTED
......
{%- import "struct_macros.tmpl" as struct_macros %}
{%- set class_name = struct.name ~ "_Data" %} {%- set class_name = struct.name ~ "_Data" %}
// static // static
{{class_name}}* {{class_name}}::New(mojo::Buffer* buf, mojo::Buffer::Destructor dtor) { {{class_name}}* {{class_name}}::New(mojo::Buffer* buf, mojo::Buffer::Destructor dtor) {
...@@ -8,3 +9,45 @@ ...@@ -8,3 +9,45 @@
_header_.num_bytes = sizeof(*this); _header_.num_bytes = sizeof(*this);
_header_.num_fields = {{struct.packed.packed_fields|length}}; _header_.num_fields = {{struct.packed.packed_fields|length}};
} }
size_t {{class_name}}::ComputeSize() const {
size_t result = sizeof(*this);
{%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind %}
if ({{pf.field.name}}_.ptr)
result += {{pf.field.name}}_.ptr->ComputeSize();
{%- endfor %}
return result;
}
{{class_name}}* {{class_name}}::Clone(mojo::Buffer* buf) const {
{{class_name}}* clone = New(buf);
memcpy(clone, this, sizeof(*this));
{%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind %}
if ({{pf.field.name}}_.ptr)
clone->set_{{pf.field.name}}({{pf.field.name}}_.ptr->Clone(buf));
{%- endfor %}
{%- for pf in struct.packed.packed_fields if pf.field.kind|is_handle_kind %}
mojo::internal::ResetIfNonNull({{pf.field.name}}());
{%- endfor %}
return clone;
}
void {{class_name}}::CloseHandles() {
{%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind %}
if ({{pf.field.name}}_.ptr)
{{pf.field.name}}_.ptr->CloseHandles();
{%- endfor %}
{%- if struct|is_struct_with_handles %}
{{struct.name}}_Data_Destructor(this);
{%- endif %}
}
void {{class_name}}::EncodePointersAndHandles(
std::vector<mojo::Handle>* handles) {
{{ struct_macros.encodes(struct)|indent(2) }}
}
bool {{class_name}}::DecodePointersAndHandles(mojo::Message* message) {
{{ struct_macros.decodes(struct)|indent(2) }}
return true;
}
...@@ -61,22 +61,22 @@ ...@@ -61,22 +61,22 @@
{%- endif %} {%- endif %}
{%- endmacro %} {%- endmacro %}
{%- macro encodes(struct, param_name) -%} {%- macro encodes(struct) -%}
{%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind -%} {%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind -%}
Encode(&{{param_name}}->{{pf.field.name}}_, handles); mojo::internal::Encode(&{{pf.field.name}}_, handles);
{% endfor %} {% endfor %}
{%- for pf in struct.packed.packed_fields if pf.field.kind|is_handle_kind -%} {%- for pf in struct.packed.packed_fields if pf.field.kind|is_handle_kind -%}
EncodeHandle(&{{param_name}}->{{pf.field.name}}_, handles); mojo::internal::EncodeHandle(&{{pf.field.name}}_, handles);
{% endfor %} {% endfor %}
{%- endmacro -%} {%- endmacro -%}
{%- macro decodes(struct, param_name) -%} {%- macro decodes(struct) -%}
{%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind -%} {%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind -%}
if (!Decode(&{{param_name}}->{{pf.field.name}}_, message)) if (!mojo::internal::Decode(&{{pf.field.name}}_, message))
return false; return false;
{% endfor %} {% endfor %}
{%- for pf in struct.packed.packed_fields if pf.field.kind|is_handle_kind -%} {%- for pf in struct.packed.packed_fields if pf.field.kind|is_handle_kind -%}
if (!DecodeHandle(&{{param_name}}->{{pf.field.name}}_, &message->handles)) if (!mojo::internal::DecodeHandle(&{{pf.field.name}}_, &message->handles))
return false; return false;
{% endfor %} {% endfor %}
{%- endmacro -%} {%- endmacro -%}
{%- import "struct_macros.tmpl" as struct_macros %}
{%- set class_name = "%s::internal::%s_Data"|format(namespace, struct.name) -%}
{%- set param_name = struct.name|camel_to_underscores %}
// static
size_t ObjectTraits<{{class_name}}>::ComputeSizeOf(
const {{class_name}}* {{param_name}}) {
return sizeof(*{{param_name}})
{%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind %} +
mojo::internal::ComputeSizeOf({{param_name}}->{{pf.field.name}}())
{%- endfor %};
}
// static
{{class_name}}* ObjectTraits<{{class_name}}>::Clone(
const {{class_name}}* {{param_name}}, Buffer* buf) {
{{class_name}}* clone = {{class_name}}::New(buf);
memcpy(clone, {{param_name}}, sizeof(*{{param_name}}));
{%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind %}
clone->set_{{pf.field.name}}(mojo::internal::Clone({#
#}{{param_name}}->{{pf.field.name}}(), buf));
{%- endfor %}
{%- for pf in struct.packed.packed_fields if pf.field.kind|is_handle_kind %}
mojo::internal::ResetIfNonNull({{param_name}}->{{pf.field.name}}());
{%- endfor %}
return clone;
}
// static
void ObjectTraits<{{class_name}}>::CloseHandles(
{{class_name}}* {{param_name}}) {
{%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind %}
mojo::internal::CloseHandles({{param_name}}->{{pf.field.name}}_.ptr);
{%- endfor %}
{%- if struct|is_struct_with_handles %}
{{struct.name}}_Data_Destructor({{param_name}});
{%- endif %}
}
// static
void ObjectTraits<{{class_name}}>::EncodePointersAndHandles(
{{class_name}}* {{param_name}}, std::vector<mojo::Handle>* handles) {
{{ struct_macros.encodes(struct, param_name)|indent(2) }}
}
// static
bool ObjectTraits<{{class_name}}>::DecodePointersAndHandles(
{{class_name}}* {{param_name}}, mojo::Message* message) {
{{ struct_macros.decodes(struct, param_name)|indent(2) }}
return true;
}
{%- set full_class = "%s::internal::%s_Data"|format(namespace, struct.name) %}
{%- set name = struct.name|camel_to_underscores -%}
template <>
class ObjectTraits<{{full_class}}> {
public:
static size_t ComputeSizeOf(const {{full_class}}* {{name}});
static {{full_class}}* Clone(const {{full_class}}* {{name}}, Buffer* buf);
static void CloseHandles({{full_class}}* {{name}});
static void EncodePointersAndHandles({{full_class}}* {{name}},
std::vector<mojo::Handle>* handles);
static bool DecodePointersAndHandles({{full_class}}* {{name}},
mojo::Message* message);
};
...@@ -34,5 +34,26 @@ ArrayDataTraits<bool>::BitRef::operator bool() const { ...@@ -34,5 +34,26 @@ ArrayDataTraits<bool>::BitRef::operator bool() const {
return (*storage_ & mask_) != 0; return (*storage_ & mask_) != 0;
} }
// static
void ArraySerializationHelper<Handle>::EncodePointersAndHandles(
const ArrayHeader* header,
ElementType* elements,
std::vector<Handle>* handles) {
for (uint32_t i = 0; i < header->num_elements; ++i)
EncodeHandle(&elements[i], handles);
}
// static
bool ArraySerializationHelper<Handle>::DecodePointersAndHandles(
const ArrayHeader* header,
ElementType* elements,
Message* message) {
for (uint32_t i = 0; i < header->num_elements; ++i) {
if (!DecodeHandle(&elements[i], &message->handles))
return false;
}
return true;
}
} // namespace internal } // namespace internal
} // namespace mojo } // namespace mojo
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <new> #include <new>
#include "mojo/public/bindings/lib/bindings_internal.h" #include "mojo/public/bindings/lib/bindings_internal.h"
#include "mojo/public/bindings/lib/bindings_serialization.h"
#include "mojo/public/bindings/lib/buffer.h" #include "mojo/public/bindings/lib/buffer.h"
#include "mojo/public/bindings/lib/passable.h" #include "mojo/public/bindings/lib/passable.h"
#include "mojo/public/system/core_cpp.h" #include "mojo/public/system/core_cpp.h"
...@@ -92,6 +93,100 @@ struct ArrayDataTraits<bool> { ...@@ -92,6 +93,100 @@ struct ArrayDataTraits<bool> {
} }
}; };
// What follows is code to support the serialization of Array_Data<T>. There
// are two interesting cases: arrays of primitives and arrays of objects.
// Arrays of objects are represented as arrays of pointers to objects.
template <typename T>
struct ArraySerializationHelper {
typedef T ElementType;
static size_t ComputeSizeOfElements(const ArrayHeader* header,
const ElementType* elements) {
return 0;
}
static void CloneElements(const ArrayHeader* header,
ElementType* elements,
Buffer* buf) {
}
static void EncodePointersAndHandles(const ArrayHeader* header,
ElementType* elements,
std::vector<Handle>* handles) {
}
static bool DecodePointersAndHandles(const ArrayHeader* header,
ElementType* elements,
Message* message) {
return true;
}
};
template <>
struct ArraySerializationHelper<Handle> {
typedef Handle ElementType;
static size_t ComputeSizeOfElements(const ArrayHeader* header,
const ElementType* elements) {
return 0;
}
static void CloneElements(const ArrayHeader* header,
ElementType* elements,
Buffer* buf) {
}
static void EncodePointersAndHandles(const ArrayHeader* header,
ElementType* elements,
std::vector<Handle>* handles);
static bool DecodePointersAndHandles(const ArrayHeader* header,
ElementType* elements,
Message* message);
};
template <typename P>
struct ArraySerializationHelper<P*> {
typedef StructPointer<P> ElementType;
static size_t ComputeSizeOfElements(const ArrayHeader* header,
const ElementType* elements) {
size_t result = 0;
for (uint32_t i = 0; i < header->num_elements; ++i) {
if (elements[i].ptr)
result += elements[i].ptr->ComputeSize();
}
return result;
}
static void CloneElements(const ArrayHeader* header,
ElementType* elements,
Buffer* buf) {
for (uint32_t i = 0; i < header->num_elements; ++i) {
if (elements[i].ptr)
elements[i].ptr = elements[i].ptr->Clone(buf);
}
}
static void EncodePointersAndHandles(const ArrayHeader* header,
ElementType* elements,
std::vector<Handle>* handles) {
for (uint32_t i = 0; i < header->num_elements; ++i)
Encode(&elements[i], handles);
}
static bool DecodePointersAndHandles(const ArrayHeader* header,
ElementType* elements,
Message* message) {
for (uint32_t i = 0; i < header->num_elements; ++i) {
if (!Decode(&elements[i], message))
return false;
}
return true;
}
};
template <typename T> template <typename T>
class Array_Data { class Array_Data {
public: public:
...@@ -130,9 +225,38 @@ class Array_Data { ...@@ -130,9 +225,38 @@ class Array_Data {
reinterpret_cast<const char*>(this) + sizeof(*this)); reinterpret_cast<const char*>(this) + sizeof(*this));
} }
private: size_t ComputeSize() const {
friend class internal::ObjectTraits<Array_Data<T> >; return Align(header_.num_bytes) +
ArraySerializationHelper<T>::ComputeSizeOfElements(&header_, storage());
}
Array_Data<T>* Clone(Buffer* buf) const {
Array_Data<T>* clone = New(header_.num_elements, buf);
memcpy(clone->storage(),
storage(),
header_.num_bytes - sizeof(Array_Data<T>));
ArraySerializationHelper<T>::CloneElements(&clone->header_,
clone->storage(), buf);
return clone;
}
void CloseHandles() {
// TODO(darin): Implement!
}
void EncodePointersAndHandles(std::vector<Handle>* handles) {
ArraySerializationHelper<T>::EncodePointersAndHandles(&header_, storage(),
handles);
}
bool DecodePointersAndHandles(Message* message) {
return ArraySerializationHelper<T>::DecodePointersAndHandles(&header_,
storage(),
message);
}
private:
Array_Data(size_t num_bytes, size_t num_elements) { Array_Data(size_t num_bytes, size_t num_elements) {
header_.num_bytes = static_cast<uint32_t>(num_bytes); header_.num_bytes = static_cast<uint32_t>(num_bytes);
header_.num_elements = static_cast<uint32_t>(num_elements); header_.num_elements = static_cast<uint32_t>(num_elements);
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include <assert.h> #include <assert.h>
#include "mojo/public/bindings/lib/bindings_internal.h"
namespace mojo { namespace mojo {
namespace internal { namespace internal {
...@@ -67,26 +69,5 @@ bool DecodeHandle(Handle* handle, std::vector<Handle>* handles) { ...@@ -67,26 +69,5 @@ bool DecodeHandle(Handle* handle, std::vector<Handle>* handles) {
return true; return true;
} }
// static
void ArrayHelper<Handle>::EncodePointersAndHandles(
const ArrayHeader* header,
ElementType* elements,
std::vector<Handle>* handles) {
for (uint32_t i = 0; i < header->num_elements; ++i)
EncodeHandle(&elements[i], handles);
}
// static
bool ArrayHelper<Handle>::DecodePointersAndHandles(
const ArrayHeader* header,
ElementType* elements,
Message* message) {
for (uint32_t i = 0; i < header->num_elements; ++i) {
if (!DecodeHandle(&elements[i], &message->handles))
return false;
}
return true;
}
} // namespace internal } // namespace internal
} // namespace mojo } // namespace mojo
...@@ -5,11 +5,9 @@ ...@@ -5,11 +5,9 @@
#ifndef MOJO_PUBLIC_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_ #ifndef MOJO_PUBLIC_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_
#define MOJO_PUBLIC_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_ #define MOJO_PUBLIC_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_
#include <string.h>
#include <vector> #include <vector>
#include "mojo/public/bindings/lib/bindings.h" #include "mojo/public/bindings/lib/buffer.h"
#include "mojo/public/bindings/lib/message.h" #include "mojo/public/bindings/lib/message.h"
namespace mojo { namespace mojo {
...@@ -41,49 +39,13 @@ bool ValidatePointer(const void* ptr, const Message& message); ...@@ -41,49 +39,13 @@ bool ValidatePointer(const void* ptr, const Message& message);
void EncodeHandle(Handle* handle, std::vector<Handle>* handles); void EncodeHandle(Handle* handle, std::vector<Handle>* handles);
bool DecodeHandle(Handle* handle, std::vector<Handle>* handles); bool DecodeHandle(Handle* handle, std::vector<Handle>* handles);
// All objects (structs and arrays) support the following operations:
// - computing size
// - cloning
// - encoding pointers and handles
// - decoding pointers and handles
//
// The following functions are used to select the proper ObjectTraits<>
// specialization.
template <typename T>
inline size_t ComputeSizeOf(const T* obj) {
return obj ? ObjectTraits<T>::ComputeSizeOf(obj) : 0;
}
template <typename T>
inline T* Clone(const T* obj, Buffer* buf) {
return obj ? ObjectTraits<T>::Clone(obj, buf) : NULL;
}
template <typename T>
inline void CloseHandles(T* obj) {
if (obj)
ObjectTraits<T>::CloseHandles(obj);
}
template <typename T>
inline void EncodePointersAndHandles(T* obj,
std::vector<Handle>* handles) {
ObjectTraits<T>::EncodePointersAndHandles(obj, handles);
}
template <typename T>
inline bool DecodePointersAndHandles(T* obj, Message* message) {
return ObjectTraits<T>::DecodePointersAndHandles(obj, message);
}
// The following 2 functions are used to encode/decode all objects (structs and // The following 2 functions are used to encode/decode all objects (structs and
// arrays) in a consistent manner. // arrays) in a consistent manner.
template <typename T> template <typename T>
inline void Encode(T* obj, std::vector<Handle>* handles) { inline void Encode(T* obj, std::vector<Handle>* handles) {
if (obj->ptr) if (obj->ptr)
EncodePointersAndHandles(obj->ptr, handles); obj->ptr->EncodePointersAndHandles(handles);
EncodePointer(obj->ptr, &obj->offset); EncodePointer(obj->ptr, &obj->offset);
} }
...@@ -93,137 +55,12 @@ inline bool Decode(T* obj, Message* message) { ...@@ -93,137 +55,12 @@ inline bool Decode(T* obj, Message* message) {
if (obj->ptr) { if (obj->ptr) {
if (!ValidatePointer(obj->ptr, *message)) if (!ValidatePointer(obj->ptr, *message))
return false; return false;
if (!DecodePointersAndHandles(obj->ptr, message)) if (!obj->ptr->DecodePointersAndHandles(message))
return false; return false;
} }
return true; return true;
} }
// What follows is code to support the ObjectTraits<> specialization of
// Array_Data<T>. There are two interesting cases: arrays of primitives and
// arrays of objects. Arrays of objects are represented as arrays of pointers
// to objects.
template <typename T>
struct ArrayHelper {
typedef T ElementType;
static size_t ComputeSizeOfElements(const ArrayHeader* header,
const ElementType* elements) {
return 0;
}
static void CloneElements(const ArrayHeader* header,
ElementType* elements,
Buffer* buf) {
}
static void EncodePointersAndHandles(const ArrayHeader* header,
ElementType* elements,
std::vector<Handle>* handles) {
}
static bool DecodePointersAndHandles(const ArrayHeader* header,
ElementType* elements,
Message* message) {
return true;
}
};
template <>
struct ArrayHelper<Handle> {
typedef Handle ElementType;
static size_t ComputeSizeOfElements(const ArrayHeader* header,
const ElementType* elements) {
return 0;
}
static void CloneElements(const ArrayHeader* header,
ElementType* elements,
Buffer* buf) {
}
static void EncodePointersAndHandles(const ArrayHeader* header,
ElementType* elements,
std::vector<Handle>* handles);
static bool DecodePointersAndHandles(const ArrayHeader* header,
ElementType* elements,
Message* message);
};
template <typename P>
struct ArrayHelper<P*> {
typedef StructPointer<P> ElementType;
static size_t ComputeSizeOfElements(const ArrayHeader* header,
const ElementType* elements) {
size_t result = 0;
for (uint32_t i = 0; i < header->num_elements; ++i)
result += ComputeSizeOf(elements[i].ptr);
return result;
}
static void CloneElements(const ArrayHeader* header,
ElementType* elements,
Buffer* buf) {
for (uint32_t i = 0; i < header->num_elements; ++i)
elements[i].ptr = Clone(elements[i].ptr, buf);
}
static void EncodePointersAndHandles(const ArrayHeader* header,
ElementType* elements,
std::vector<Handle>* handles) {
for (uint32_t i = 0; i < header->num_elements; ++i)
Encode(&elements[i], handles);
}
static bool DecodePointersAndHandles(const ArrayHeader* header,
ElementType* elements,
Message* message) {
for (uint32_t i = 0; i < header->num_elements; ++i) {
if (!Decode(&elements[i], message))
return false;
}
return true;
}
};
template <typename T>
class ObjectTraits<Array_Data<T> > {
public:
static size_t ComputeSizeOf(const Array_Data<T>* array) {
return Align(array->header_.num_bytes) +
ArrayHelper<T>::ComputeSizeOfElements(&array->header_,
array->storage());
}
static Array_Data<T>* Clone(const Array_Data<T>* array, Buffer* buf) {
Array_Data<T>* clone = Array_Data<T>::New(array->header_.num_elements, buf);
memcpy(clone->storage(),
array->storage(),
array->header_.num_bytes - sizeof(Array_Data<T>));
ArrayHelper<T>::CloneElements(&clone->header_, clone->storage(), buf);
return clone;
}
static void CloseHandles(Array_Data<T>* array) {
// TODO(darin): Implement!
}
static void EncodePointersAndHandles(Array_Data<T>* array,
std::vector<Handle>* handles) {
ArrayHelper<T>::EncodePointersAndHandles(&array->header_, array->storage(),
handles);
}
static bool DecodePointersAndHandles(Array_Data<T>* array,
Message* message) {
return ArrayHelper<T>::DecodePointersAndHandles(&array->header_,
array->storage(),
message);
}
};
} // namespace internal } // namespace internal
} // namespace mojo } // namespace mojo
......
...@@ -26,14 +26,11 @@ ...@@ -26,14 +26,11 @@
'<(DEPTH)/mojo/public/bindings/generators/cpp_templates/module.h.tmpl', '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/module.h.tmpl',
'<(DEPTH)/mojo/public/bindings/generators/cpp_templates/module_internal.h.tmpl', '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/module_internal.h.tmpl',
'<(DEPTH)/mojo/public/bindings/generators/cpp_templates/params_definition.tmpl', '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/params_definition.tmpl',
'<(DEPTH)/mojo/public/bindings/generators/cpp_templates/params_serialization.tmpl',
'<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_builder_definition.tmpl',
'<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_declaration.tmpl', '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_declaration.tmpl',
'<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_definition.tmpl', '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_definition.tmpl',
'<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_destructor.tmpl', '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_destructor.tmpl',
'<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_macros.tmpl', '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_macros.tmpl',
'<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_serialization_definition.tmpl',
'<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_serialization_traits.tmpl',
'<(DEPTH)/mojo/public/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl',
'<(DEPTH)/mojo/public/bindings/generators/js_templates/interface_definition.tmpl', '<(DEPTH)/mojo/public/bindings/generators/js_templates/interface_definition.tmpl',
'<(DEPTH)/mojo/public/bindings/generators/js_templates/module.js.tmpl', '<(DEPTH)/mojo/public/bindings/generators/js_templates/module.js.tmpl',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment