| Index: mojo/public/cpp/bindings/lib/array_internal.h
|
| diff --git a/mojo/public/cpp/bindings/lib/array_internal.h b/mojo/public/cpp/bindings/lib/array_internal.h
|
| deleted file mode 100644
|
| index 26509b1f1f7f02367aeb938fc8e8962f8fe21ed1..0000000000000000000000000000000000000000
|
| --- a/mojo/public/cpp/bindings/lib/array_internal.h
|
| +++ /dev/null
|
| @@ -1,540 +0,0 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
|
| -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
|
| -
|
| -#include <new>
|
| -#include <string>
|
| -#include <type_traits>
|
| -#include <vector>
|
| -
|
| -#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
|
| -#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
|
| -#include "mojo/public/cpp/bindings/lib/bounds_checker.h"
|
| -#include "mojo/public/cpp/bindings/lib/buffer.h"
|
| -#include "mojo/public/cpp/bindings/lib/map_data_internal.h"
|
| -#include "mojo/public/cpp/bindings/lib/validate_params.h"
|
| -#include "mojo/public/cpp/bindings/lib/validation_errors.h"
|
| -#include "mojo/public/cpp/environment/logging.h"
|
| -
|
| -namespace mojo {
|
| -template <typename T>
|
| -class Array;
|
| -class String;
|
| -
|
| -namespace internal {
|
| -
|
| -// std::numeric_limits<uint32_t>::max() is not a compile-time constant (until
|
| -// C++11).
|
| -const uint32_t kMaxUint32 = 0xFFFFFFFF;
|
| -
|
| -// TODO(vardhan): Get rid of the following 2 functions.
|
| -std::string MakeMessageWithArrayIndex(const char* message,
|
| - size_t size,
|
| - size_t index);
|
| -
|
| -std::string MakeMessageWithExpectedArraySize(const char* message,
|
| - size_t size,
|
| - size_t expected_size);
|
| -
|
| -template <typename T>
|
| -struct ArrayDataTraits {
|
| - typedef T StorageType;
|
| - typedef T& Ref;
|
| - typedef T const& ConstRef;
|
| -
|
| - static const uint32_t kMaxNumElements =
|
| - (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType);
|
| -
|
| - static uint32_t GetStorageSize(uint32_t num_elements) {
|
| - MOJO_DCHECK(num_elements <= kMaxNumElements);
|
| - return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements;
|
| - }
|
| - static Ref ToRef(StorageType* storage, size_t offset) {
|
| - return storage[offset];
|
| - }
|
| - static ConstRef ToConstRef(const StorageType* storage, size_t offset) {
|
| - return storage[offset];
|
| - }
|
| -};
|
| -
|
| -template <typename P, bool is_union>
|
| -struct ObjectStorageType;
|
| -
|
| -template <typename P>
|
| -struct ObjectStorageType<P, true> {
|
| - typedef P Type;
|
| -};
|
| -
|
| -template <typename P>
|
| -struct ObjectStorageType<P, false> {
|
| - typedef StructPointer<P> Type;
|
| -};
|
| -
|
| -template <typename P>
|
| -struct ArrayDataTraits<P*> {
|
| - typedef typename ObjectStorageType<P, IsUnionDataType<P>::value>::Type
|
| - StorageType;
|
| - typedef P*& Ref;
|
| - typedef P* const& ConstRef;
|
| -
|
| - static const uint32_t kMaxNumElements =
|
| - (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType);
|
| -
|
| - static uint32_t GetStorageSize(uint32_t num_elements) {
|
| - MOJO_DCHECK(num_elements <= kMaxNumElements);
|
| - return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements;
|
| - }
|
| - static Ref ToRef(StorageType* storage, size_t offset) {
|
| - return storage[offset].ptr;
|
| - }
|
| - static ConstRef ToConstRef(const StorageType* storage, size_t offset) {
|
| - return storage[offset].ptr;
|
| - }
|
| -};
|
| -
|
| -template <typename T>
|
| -struct ArrayDataTraits<Array_Data<T>*> {
|
| - typedef ArrayPointer<T> StorageType;
|
| - typedef Array_Data<T>*& Ref;
|
| - typedef Array_Data<T>* const& ConstRef;
|
| -
|
| - static const uint32_t kMaxNumElements =
|
| - (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType);
|
| -
|
| - static uint32_t GetStorageSize(uint32_t num_elements) {
|
| - MOJO_DCHECK(num_elements <= kMaxNumElements);
|
| - return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements;
|
| - }
|
| - static Ref ToRef(StorageType* storage, size_t offset) {
|
| - return storage[offset].ptr;
|
| - }
|
| - static ConstRef ToConstRef(const StorageType* storage, size_t offset) {
|
| - return storage[offset].ptr;
|
| - }
|
| -};
|
| -
|
| -// Specialization of Arrays for bools, optimized for space. It has the
|
| -// following differences from a generalized Array:
|
| -// * Each element takes up a single bit of memory.
|
| -// * Accessing a non-const single element uses a helper class |BitRef|, which
|
| -// emulates a reference to a bool.
|
| -template <>
|
| -struct ArrayDataTraits<bool> {
|
| - // Helper class to emulate a reference to a bool, used for direct element
|
| - // access.
|
| - class BitRef {
|
| - public:
|
| - ~BitRef();
|
| - BitRef& operator=(bool value);
|
| - BitRef& operator=(const BitRef& value);
|
| - operator bool() const;
|
| -
|
| - private:
|
| - friend struct ArrayDataTraits<bool>;
|
| - BitRef(uint8_t* storage, uint8_t mask);
|
| - BitRef();
|
| - uint8_t* storage_;
|
| - uint8_t mask_;
|
| - };
|
| -
|
| - // Because each element consumes only 1/8 byte.
|
| - static const uint32_t kMaxNumElements = kMaxUint32;
|
| -
|
| - typedef uint8_t StorageType;
|
| - typedef BitRef Ref;
|
| - typedef bool ConstRef;
|
| -
|
| - static uint32_t GetStorageSize(uint32_t num_elements) {
|
| - return sizeof(ArrayHeader) + ((num_elements + 7) / 8);
|
| - }
|
| - static BitRef ToRef(StorageType* storage, size_t offset) {
|
| - return BitRef(&storage[offset / 8], 1 << (offset % 8));
|
| - }
|
| - static bool ToConstRef(const StorageType* storage, size_t offset) {
|
| - return (storage[offset / 8] & (1 << (offset % 8))) != 0;
|
| - }
|
| -};
|
| -
|
| -// What follows is code to support the serialization of Array_Data<T>. There
|
| -// are two interesting cases: arrays of primitives/unions, arrays of non-union
|
| -// objects (structs, arrays and maps).
|
| -// Arrays of non-union objects are represented as arrays of pointers to objects.
|
| -// Arrays of primitives or unions are represented as arrays of the values
|
| -// themselves.
|
| -
|
| -template <typename T, bool is_handle, bool is_union>
|
| -struct ArraySerializationHelper;
|
| -
|
| -template <typename T>
|
| -struct ArraySerializationHelper<T, false, false> {
|
| - typedef typename ArrayDataTraits<T>::StorageType ElementType;
|
| -
|
| - static void EncodePointersAndHandles(const ArrayHeader* header,
|
| - ElementType* elements,
|
| - std::vector<Handle>* handles) {}
|
| -
|
| - static void DecodePointersAndHandles(const ArrayHeader* header,
|
| - ElementType* elements,
|
| - std::vector<Handle>* handles) {}
|
| -
|
| - static ValidationError ValidateElements(
|
| - const ArrayHeader* header,
|
| - const ElementType* elements,
|
| - BoundsChecker* bounds_checker,
|
| - const ArrayValidateParams* validate_params,
|
| - std::string* err) {
|
| - MOJO_DCHECK(!validate_params->element_is_nullable)
|
| - << "Primitive type should be non-nullable";
|
| - MOJO_DCHECK(!validate_params->element_validate_params)
|
| - << "Primitive type should not have array validate params";
|
| - return ValidationError::NONE;
|
| - }
|
| -};
|
| -
|
| -template <>
|
| -struct ArraySerializationHelper<Handle, true, false> {
|
| - typedef ArrayDataTraits<Handle>::StorageType ElementType;
|
| -
|
| - static void EncodePointersAndHandles(const ArrayHeader* header,
|
| - ElementType* elements,
|
| - std::vector<Handle>* handles);
|
| -
|
| - static void DecodePointersAndHandles(const ArrayHeader* header,
|
| - ElementType* elements,
|
| - std::vector<Handle>* handles);
|
| -
|
| - static ValidationError ValidateElements(
|
| - const ArrayHeader* header,
|
| - const ElementType* elements,
|
| - BoundsChecker* bounds_checker,
|
| - const ArrayValidateParams* validate_params,
|
| - std::string* err) {
|
| - MOJO_DCHECK(!validate_params->element_validate_params)
|
| - << "Handle type should not have array validate params";
|
| -
|
| - for (uint32_t i = 0; i < header->num_elements; ++i) {
|
| - if (!validate_params->element_is_nullable &&
|
| - elements[i].value() == kEncodedInvalidHandleValue) {
|
| - MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err)
|
| - << "invalid handle in array expecting valid handles (array size="
|
| - << header->num_elements << ", index = " << i << ")";
|
| - return ValidationError::UNEXPECTED_INVALID_HANDLE;
|
| - }
|
| - if (!bounds_checker->ClaimHandle(elements[i])) {
|
| - MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << "";
|
| - return ValidationError::ILLEGAL_HANDLE;
|
| - }
|
| - }
|
| - return ValidationError::NONE;
|
| - }
|
| -};
|
| -
|
| -template <typename H>
|
| -struct ArraySerializationHelper<H, true, false> {
|
| - typedef typename ArrayDataTraits<H>::StorageType ElementType;
|
| -
|
| - static void EncodePointersAndHandles(const ArrayHeader* header,
|
| - ElementType* elements,
|
| - std::vector<Handle>* handles) {
|
| - ArraySerializationHelper<Handle, true, false>::EncodePointersAndHandles(
|
| - header, elements, handles);
|
| - }
|
| -
|
| - static void DecodePointersAndHandles(const ArrayHeader* header,
|
| - ElementType* elements,
|
| - std::vector<Handle>* handles) {
|
| - ArraySerializationHelper<Handle, true, false>::DecodePointersAndHandles(
|
| - header, elements, handles);
|
| - }
|
| -
|
| - static ValidationError ValidateElements(
|
| - const ArrayHeader* header,
|
| - const ElementType* elements,
|
| - BoundsChecker* bounds_checker,
|
| - const ArrayValidateParams* validate_params,
|
| - std::string* err) {
|
| - return ArraySerializationHelper<Handle, true, false>::ValidateElements(
|
| - header, elements, bounds_checker, validate_params, err);
|
| - }
|
| -};
|
| -
|
| -template <typename P>
|
| -struct ArraySerializationHelper<P*, false, false> {
|
| - typedef typename ArrayDataTraits<P*>::StorageType ElementType;
|
| -
|
| - 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 void DecodePointersAndHandles(const ArrayHeader* header,
|
| - ElementType* elements,
|
| - std::vector<Handle>* handles) {
|
| - for (uint32_t i = 0; i < header->num_elements; ++i)
|
| - Decode(&elements[i], handles);
|
| - }
|
| -
|
| - static ValidationError ValidateElements(
|
| - const ArrayHeader* header,
|
| - const ElementType* elements,
|
| - BoundsChecker* bounds_checker,
|
| - const ArrayValidateParams* validate_params,
|
| - std::string* err) {
|
| - for (uint32_t i = 0; i < header->num_elements; ++i) {
|
| - if (!validate_params->element_is_nullable && !elements[i].offset) {
|
| - MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err)
|
| - << "null in array expecting valid pointers (size="
|
| - << header->num_elements << ", index = " << i << ")";
|
| - return ValidationError::UNEXPECTED_NULL_POINTER;
|
| - }
|
| -
|
| - if (!ValidateEncodedPointer(&elements[i].offset)) {
|
| - MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << "";
|
| - return ValidationError::ILLEGAL_POINTER;
|
| - }
|
| -
|
| - auto retval = ValidateCaller<P>::Run(
|
| - DecodePointerRaw(&elements[i].offset), bounds_checker,
|
| - validate_params->element_validate_params, err);
|
| - if (retval != ValidationError::NONE)
|
| - return retval;
|
| - }
|
| - return ValidationError::NONE;
|
| - }
|
| -
|
| - private:
|
| - template <typename T>
|
| - struct ValidateCaller {
|
| - static ValidationError Run(const void* data,
|
| - BoundsChecker* bounds_checker,
|
| - const ArrayValidateParams* validate_params,
|
| - std::string* err) {
|
| - MOJO_DCHECK(!validate_params)
|
| - << "Struct type should not have array validate params";
|
| -
|
| - return T::Validate(data, bounds_checker, err);
|
| - }
|
| - };
|
| -
|
| - template <typename Key, typename Value>
|
| - struct ValidateCaller<Map_Data<Key, Value>> {
|
| - static ValidationError Run(const void* data,
|
| - BoundsChecker* bounds_checker,
|
| - const ArrayValidateParams* validate_params,
|
| - std::string* err) {
|
| - return Map_Data<Key, Value>::Validate(data, bounds_checker,
|
| - validate_params, err);
|
| - }
|
| - };
|
| -
|
| - template <typename T>
|
| - struct ValidateCaller<Array_Data<T>> {
|
| - static ValidationError Run(const void* data,
|
| - BoundsChecker* bounds_checker,
|
| - const ArrayValidateParams* validate_params,
|
| - std::string* err) {
|
| - return Array_Data<T>::Validate(data, bounds_checker, validate_params,
|
| - err);
|
| - }
|
| - };
|
| -};
|
| -
|
| -// Array Serialization Helper for unions.
|
| -template <typename P>
|
| -struct ArraySerializationHelper<P, false, true> {
|
| - typedef P ElementType;
|
| -
|
| - static void EncodePointersAndHandles(const ArrayHeader* header,
|
| - ElementType* elements,
|
| - std::vector<Handle>* handles) {
|
| - for (uint32_t i = 0; i < header->num_elements; ++i)
|
| - elements[i].EncodePointersAndHandles(handles);
|
| - }
|
| -
|
| - static void DecodePointersAndHandles(const ArrayHeader* header,
|
| - ElementType* elements,
|
| - std::vector<Handle>* handles) {
|
| - for (uint32_t i = 0; i < header->num_elements; ++i)
|
| - elements[i].DecodePointersAndHandles(handles);
|
| - }
|
| -
|
| - static ValidationError ValidateElements(
|
| - const ArrayHeader* header,
|
| - const ElementType* elements,
|
| - BoundsChecker* bounds_checker,
|
| - const ArrayValidateParams* validate_params,
|
| - std::string* err) {
|
| - MOJO_DCHECK(!validate_params->element_validate_params)
|
| - << "Union type should not have array validate params";
|
| - for (uint32_t i = 0; i < header->num_elements; ++i) {
|
| - if (!validate_params->element_is_nullable && elements[i].is_null()) {
|
| - MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err)
|
| - << "null union in array expecting non-null unions (size="
|
| - << header->num_elements << ", index = " << i << ")";
|
| - return ValidationError::UNEXPECTED_NULL_UNION;
|
| - }
|
| -
|
| - auto retval = ElementType::Validate(
|
| - static_cast<const void*>(&elements[i]), bounds_checker, true, err);
|
| - if (retval != ValidationError::NONE)
|
| - return retval;
|
| - }
|
| - return ValidationError::NONE;
|
| - }
|
| -};
|
| -
|
| -template <typename T>
|
| -class Array_Data {
|
| - public:
|
| - typedef ArrayDataTraits<T> Traits;
|
| - typedef typename Traits::StorageType StorageType;
|
| - typedef typename Traits::Ref Ref;
|
| - typedef typename Traits::ConstRef ConstRef;
|
| - typedef ArraySerializationHelper<
|
| - T,
|
| - IsHandle<T>::value,
|
| - IsUnionDataType<typename std::remove_pointer<T>::type>::value> Helper;
|
| -
|
| - // Returns null if |num_elements| or the corresponding storage size cannot be
|
| - // stored in uint32_t.
|
| - static Array_Data<T>* New(size_t num_elements, Buffer* buf) {
|
| - if (num_elements > Traits::kMaxNumElements)
|
| - return nullptr;
|
| -
|
| - uint32_t num_bytes =
|
| - Traits::GetStorageSize(static_cast<uint32_t>(num_elements));
|
| - return new (buf->Allocate(num_bytes))
|
| - Array_Data<T>(num_bytes, static_cast<uint32_t>(num_elements));
|
| - }
|
| -
|
| - static ValidationError Validate(const void* data,
|
| - BoundsChecker* bounds_checker,
|
| - const ArrayValidateParams* validate_params,
|
| - std::string* err) {
|
| - if (!data)
|
| - return ValidationError::NONE;
|
| - if (!IsAligned(data)) {
|
| - MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << "";
|
| - return ValidationError::MISALIGNED_OBJECT;
|
| - }
|
| - if (!bounds_checker->IsValidRange(data, sizeof(ArrayHeader))) {
|
| - MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << "";
|
| - return ValidationError::ILLEGAL_MEMORY_RANGE;
|
| - }
|
| -
|
| - const ArrayHeader* header = static_cast<const ArrayHeader*>(data);
|
| - if (header->num_elements > Traits::kMaxNumElements ||
|
| - header->num_bytes < Traits::GetStorageSize(header->num_elements)) {
|
| - MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << "";
|
| - return ValidationError::UNEXPECTED_ARRAY_HEADER;
|
| - }
|
| -
|
| - if (validate_params->expected_num_elements != 0 &&
|
| - header->num_elements != validate_params->expected_num_elements) {
|
| - MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err)
|
| - << "fixed-size array has wrong number of elements (size="
|
| - << header->num_elements
|
| - << ", expected size=" << validate_params->expected_num_elements
|
| - << ")";
|
| - return ValidationError::UNEXPECTED_ARRAY_HEADER;
|
| - }
|
| -
|
| - if (!bounds_checker->ClaimMemory(data, header->num_bytes)) {
|
| - MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << "";
|
| - return ValidationError::ILLEGAL_MEMORY_RANGE;
|
| - }
|
| -
|
| - const Array_Data<T>* object = static_cast<const Array_Data<T>*>(data);
|
| - return Helper::ValidateElements(&object->header_, object->storage(),
|
| - bounds_checker, validate_params, err);
|
| - }
|
| -
|
| - size_t size() const { return header_.num_elements; }
|
| -
|
| - Ref at(size_t offset) {
|
| - MOJO_DCHECK(offset < static_cast<size_t>(header_.num_elements));
|
| - return Traits::ToRef(storage(), offset);
|
| - }
|
| -
|
| - ConstRef at(size_t offset) const {
|
| - MOJO_DCHECK(offset < static_cast<size_t>(header_.num_elements));
|
| - return Traits::ToConstRef(storage(), offset);
|
| - }
|
| -
|
| - StorageType* storage() {
|
| - return reinterpret_cast<StorageType*>(reinterpret_cast<char*>(this) +
|
| - sizeof(*this));
|
| - }
|
| -
|
| - const StorageType* storage() const {
|
| - return reinterpret_cast<const StorageType*>(
|
| - reinterpret_cast<const char*>(this) + sizeof(*this));
|
| - }
|
| -
|
| - void EncodePointersAndHandles(std::vector<Handle>* handles) {
|
| - Helper::EncodePointersAndHandles(&header_, storage(), handles);
|
| - }
|
| -
|
| - void DecodePointersAndHandles(std::vector<Handle>* handles) {
|
| - Helper::DecodePointersAndHandles(&header_, storage(), handles);
|
| - }
|
| -
|
| - private:
|
| - Array_Data(uint32_t num_bytes, uint32_t num_elements) {
|
| - header_.num_bytes = num_bytes;
|
| - header_.num_elements = num_elements;
|
| - }
|
| - ~Array_Data() = delete;
|
| -
|
| - internal::ArrayHeader header_;
|
| -
|
| - // Elements of type internal::ArrayDataTraits<T>::StorageType follow.
|
| -};
|
| -static_assert(sizeof(Array_Data<char>) == 8, "Bad sizeof(Array_Data)");
|
| -
|
| -// UTF-8 encoded
|
| -typedef Array_Data<char> String_Data;
|
| -
|
| -template <typename T, bool kIsMoveOnlyType>
|
| -struct ArrayTraits {};
|
| -
|
| -template <typename T>
|
| -struct ArrayTraits<T, false> {
|
| - typedef typename std::vector<T>::const_reference ForwardType;
|
| - static inline void PushBack(std::vector<T>* vec, ForwardType value) {
|
| - vec->push_back(value);
|
| - }
|
| - static inline void Clone(const std::vector<T>& src_vec,
|
| - std::vector<T>* dest_vec) {
|
| - dest_vec->assign(src_vec.begin(), src_vec.end());
|
| - }
|
| -};
|
| -
|
| -template <typename T>
|
| -struct ArrayTraits<T, true> {
|
| - typedef T ForwardType;
|
| - static inline void PushBack(std::vector<T>* vec, T& value) {
|
| - vec->push_back(value.Pass());
|
| - }
|
| - static inline void Clone(const std::vector<T>& src_vec,
|
| - std::vector<T>* dest_vec) {
|
| - dest_vec->resize(src_vec.size());
|
| - for (size_t i = 0; i < src_vec.size(); ++i)
|
| - dest_vec->at(i) = src_vec.at(i).Clone();
|
| - }
|
| -};
|
| -
|
| -template <>
|
| -struct WrapperTraits<String, false> {
|
| - typedef String_Data* DataType;
|
| -};
|
| -
|
| -} // namespace internal
|
| -} // namespace mojo
|
| -
|
| -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
|
|
|