| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ | 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ |
| 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ | 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ |
| 7 | 7 |
| 8 #include <new> | 8 #include <new> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "mojo/public/c/system/macros.h" | 11 #include "mojo/public/c/system/macros.h" |
| 12 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" | 12 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" |
| 13 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" | 13 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" |
| 14 #include "mojo/public/cpp/bindings/lib/bounds_checker.h" | 14 #include "mojo/public/cpp/bindings/lib/bounds_checker.h" |
| 15 #include "mojo/public/cpp/bindings/lib/buffer.h" | 15 #include "mojo/public/cpp/bindings/lib/buffer.h" |
| 16 #include "mojo/public/cpp/bindings/lib/template_util.h" | 16 #include "mojo/public/cpp/bindings/lib/template_util.h" |
| 17 #include "mojo/public/cpp/bindings/lib/validation_errors.h" | 17 #include "mojo/public/cpp/bindings/lib/validation_errors.h" |
| 18 #include "mojo/public/cpp/environment/logging.h" | 18 #include "mojo/public/cpp/environment/logging.h" |
| 19 | 19 |
| 20 namespace mojo { | 20 namespace mojo { |
| 21 template <typename T> class Array; | 21 template <typename T> class Array; |
| 22 class String; | 22 class String; |
| 23 | 23 |
| 24 namespace internal { | 24 namespace internal { |
| 25 | 25 |
| 26 // std::numeric_limits<uint32_t>::max() is not a compile-time constant (until |
| 27 // C++11). |
| 28 const uint32_t kMaxUint32 = 0xFFFFFFFF; |
| 29 |
| 26 template <typename T> | 30 template <typename T> |
| 27 struct ArrayDataTraits { | 31 struct ArrayDataTraits { |
| 28 typedef T StorageType; | 32 typedef T StorageType; |
| 29 typedef T& Ref; | 33 typedef T& Ref; |
| 30 typedef T const& ConstRef; | 34 typedef T const& ConstRef; |
| 31 | 35 |
| 32 static size_t GetStorageSize(size_t num_elements) { | 36 static const uint32_t kMaxNumElements = |
| 33 return sizeof(StorageType) * num_elements; | 37 (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType); |
| 38 |
| 39 static uint32_t GetStorageSize(uint32_t num_elements) { |
| 40 MOJO_DCHECK(num_elements <= kMaxNumElements); |
| 41 return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; |
| 34 } | 42 } |
| 35 static Ref ToRef(StorageType* storage, size_t offset) { | 43 static Ref ToRef(StorageType* storage, size_t offset) { |
| 36 return storage[offset]; | 44 return storage[offset]; |
| 37 } | 45 } |
| 38 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { | 46 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { |
| 39 return storage[offset]; | 47 return storage[offset]; |
| 40 } | 48 } |
| 41 }; | 49 }; |
| 42 | 50 |
| 43 template <typename P> | 51 template <typename P> |
| 44 struct ArrayDataTraits<P*> { | 52 struct ArrayDataTraits<P*> { |
| 45 typedef StructPointer<P> StorageType; | 53 typedef StructPointer<P> StorageType; |
| 46 typedef P*& Ref; | 54 typedef P*& Ref; |
| 47 typedef P* const& ConstRef; | 55 typedef P* const& ConstRef; |
| 48 | 56 |
| 49 static size_t GetStorageSize(size_t num_elements) { | 57 static const uint32_t kMaxNumElements = |
| 50 return sizeof(StorageType) * num_elements; | 58 (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType); |
| 59 |
| 60 static uint32_t GetStorageSize(uint32_t num_elements) { |
| 61 MOJO_DCHECK(num_elements <= kMaxNumElements); |
| 62 return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; |
| 51 } | 63 } |
| 52 static Ref ToRef(StorageType* storage, size_t offset) { | 64 static Ref ToRef(StorageType* storage, size_t offset) { |
| 53 return storage[offset].ptr; | 65 return storage[offset].ptr; |
| 54 } | 66 } |
| 55 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { | 67 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { |
| 56 return storage[offset].ptr; | 68 return storage[offset].ptr; |
| 57 } | 69 } |
| 58 }; | 70 }; |
| 59 | 71 |
| 60 template <typename T> | 72 template <typename T> |
| 61 struct ArrayDataTraits<Array_Data<T>*> { | 73 struct ArrayDataTraits<Array_Data<T>*> { |
| 62 typedef ArrayPointer<T> StorageType; | 74 typedef ArrayPointer<T> StorageType; |
| 63 typedef Array_Data<T>*& Ref; | 75 typedef Array_Data<T>*& Ref; |
| 64 typedef Array_Data<T>* const& ConstRef; | 76 typedef Array_Data<T>* const& ConstRef; |
| 65 | 77 |
| 66 static size_t GetStorageSize(size_t num_elements) { | 78 static const uint32_t kMaxNumElements = |
| 67 return sizeof(StorageType) * num_elements; | 79 (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType); |
| 80 |
| 81 static uint32_t GetStorageSize(uint32_t num_elements) { |
| 82 MOJO_DCHECK(num_elements <= kMaxNumElements); |
| 83 return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; |
| 68 } | 84 } |
| 69 static Ref ToRef(StorageType* storage, size_t offset) { | 85 static Ref ToRef(StorageType* storage, size_t offset) { |
| 70 return storage[offset].ptr; | 86 return storage[offset].ptr; |
| 71 } | 87 } |
| 72 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { | 88 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { |
| 73 return storage[offset].ptr; | 89 return storage[offset].ptr; |
| 74 } | 90 } |
| 75 }; | 91 }; |
| 76 | 92 |
| 77 // Specialization of Arrays for bools, optimized for space. It has the | 93 // Specialization of Arrays for bools, optimized for space. It has the |
| (...skipping 12 matching lines...) Expand all Loading... |
| 90 BitRef& operator=(const BitRef& value); | 106 BitRef& operator=(const BitRef& value); |
| 91 operator bool() const; | 107 operator bool() const; |
| 92 private: | 108 private: |
| 93 friend struct ArrayDataTraits<bool>; | 109 friend struct ArrayDataTraits<bool>; |
| 94 BitRef(uint8_t* storage, uint8_t mask); | 110 BitRef(uint8_t* storage, uint8_t mask); |
| 95 BitRef(); | 111 BitRef(); |
| 96 uint8_t* storage_; | 112 uint8_t* storage_; |
| 97 uint8_t mask_; | 113 uint8_t mask_; |
| 98 }; | 114 }; |
| 99 | 115 |
| 116 // Because each element consumes only 1/8 byte. |
| 117 static const uint32_t kMaxNumElements = kMaxUint32; |
| 118 |
| 100 typedef uint8_t StorageType; | 119 typedef uint8_t StorageType; |
| 101 typedef BitRef Ref; | 120 typedef BitRef Ref; |
| 102 typedef bool ConstRef; | 121 typedef bool ConstRef; |
| 103 | 122 |
| 104 static size_t GetStorageSize(size_t num_elements) { | 123 static uint32_t GetStorageSize(uint32_t num_elements) { |
| 105 return ((num_elements + 7) / 8); | 124 return sizeof(ArrayHeader) + ((num_elements + 7) / 8); |
| 106 } | 125 } |
| 107 static BitRef ToRef(StorageType* storage, size_t offset) { | 126 static BitRef ToRef(StorageType* storage, size_t offset) { |
| 108 return BitRef(&storage[offset / 8], 1 << (offset % 8)); | 127 return BitRef(&storage[offset / 8], 1 << (offset % 8)); |
| 109 } | 128 } |
| 110 static bool ToConstRef(const StorageType* storage, size_t offset) { | 129 static bool ToConstRef(const StorageType* storage, size_t offset) { |
| 111 return (storage[offset / 8] & (1 << (offset % 8))) != 0; | 130 return (storage[offset / 8] & (1 << (offset % 8))) != 0; |
| 112 } | 131 } |
| 113 }; | 132 }; |
| 114 | 133 |
| 115 // Array type information needed for valdiation. | 134 // Array type information needed for valdiation. |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 | 310 |
| 292 template <typename T> | 311 template <typename T> |
| 293 class Array_Data { | 312 class Array_Data { |
| 294 public: | 313 public: |
| 295 typedef ArrayDataTraits<T> Traits; | 314 typedef ArrayDataTraits<T> Traits; |
| 296 typedef typename Traits::StorageType StorageType; | 315 typedef typename Traits::StorageType StorageType; |
| 297 typedef typename Traits::Ref Ref; | 316 typedef typename Traits::Ref Ref; |
| 298 typedef typename Traits::ConstRef ConstRef; | 317 typedef typename Traits::ConstRef ConstRef; |
| 299 typedef ArraySerializationHelper<T, IsHandle<T>::value> Helper; | 318 typedef ArraySerializationHelper<T, IsHandle<T>::value> Helper; |
| 300 | 319 |
| 320 // Returns NULL if |num_elements| or the corresponding storage size cannot be |
| 321 // stored in uint32_t. |
| 301 static Array_Data<T>* New(size_t num_elements, Buffer* buf) { | 322 static Array_Data<T>* New(size_t num_elements, Buffer* buf) { |
| 302 size_t num_bytes = sizeof(Array_Data<T>) + | 323 if (num_elements > Traits::kMaxNumElements) |
| 303 Traits::GetStorageSize(num_elements); | 324 return NULL; |
| 304 return new (buf->Allocate(num_bytes)) Array_Data<T>(num_bytes, | 325 |
| 305 num_elements); | 326 uint32_t num_bytes = |
| 327 Traits::GetStorageSize(static_cast<uint32_t>(num_elements)); |
| 328 return new (buf->Allocate(num_bytes)) Array_Data<T>( |
| 329 num_bytes, static_cast<uint32_t>(num_elements)); |
| 306 } | 330 } |
| 307 | 331 |
| 308 template <typename Params> | 332 template <typename Params> |
| 309 static bool Validate(const void* data, BoundsChecker* bounds_checker) { | 333 static bool Validate(const void* data, BoundsChecker* bounds_checker) { |
| 310 if (!data) | 334 if (!data) |
| 311 return true; | 335 return true; |
| 312 if (!IsAligned(data)) { | 336 if (!IsAligned(data)) { |
| 313 ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); | 337 ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); |
| 314 return false; | 338 return false; |
| 315 } | 339 } |
| 316 if (!bounds_checker->IsValidRange(data, sizeof(ArrayHeader))) { | 340 if (!bounds_checker->IsValidRange(data, sizeof(ArrayHeader))) { |
| 317 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); | 341 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); |
| 318 return false; | 342 return false; |
| 319 } | 343 } |
| 320 const ArrayHeader* header = static_cast<const ArrayHeader*>(data); | 344 const ArrayHeader* header = static_cast<const ArrayHeader*>(data); |
| 321 if (header->num_bytes < (sizeof(Array_Data<T>) + | 345 if (header->num_elements > Traits::kMaxNumElements || |
| 322 Traits::GetStorageSize(header->num_elements))) { | 346 header->num_bytes < Traits::GetStorageSize(header->num_elements)) { |
| 323 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); | 347 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); |
| 324 return false; | 348 return false; |
| 325 } | 349 } |
| 326 if (Params::expected_num_elements != 0 && | 350 if (Params::expected_num_elements != 0 && |
| 327 header->num_elements != Params::expected_num_elements) { | 351 header->num_elements != Params::expected_num_elements) { |
| 328 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); | 352 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); |
| 329 return false; | 353 return false; |
| 330 } | 354 } |
| 331 if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { | 355 if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { |
| 332 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); | 356 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 363 | 387 |
| 364 void EncodePointersAndHandles(std::vector<Handle>* handles) { | 388 void EncodePointersAndHandles(std::vector<Handle>* handles) { |
| 365 Helper::EncodePointersAndHandles(&header_, storage(), handles); | 389 Helper::EncodePointersAndHandles(&header_, storage(), handles); |
| 366 } | 390 } |
| 367 | 391 |
| 368 void DecodePointersAndHandles(std::vector<Handle>* handles) { | 392 void DecodePointersAndHandles(std::vector<Handle>* handles) { |
| 369 Helper::DecodePointersAndHandles(&header_, storage(), handles); | 393 Helper::DecodePointersAndHandles(&header_, storage(), handles); |
| 370 } | 394 } |
| 371 | 395 |
| 372 private: | 396 private: |
| 373 Array_Data(size_t num_bytes, size_t num_elements) { | 397 Array_Data(uint32_t num_bytes, uint32_t num_elements) { |
| 374 header_.num_bytes = static_cast<uint32_t>(num_bytes); | 398 header_.num_bytes = num_bytes; |
| 375 header_.num_elements = static_cast<uint32_t>(num_elements); | 399 header_.num_elements = num_elements; |
| 376 } | 400 } |
| 377 ~Array_Data() {} | 401 ~Array_Data() {} |
| 378 | 402 |
| 379 internal::ArrayHeader header_; | 403 internal::ArrayHeader header_; |
| 380 | 404 |
| 381 // Elements of type internal::ArrayDataTraits<T>::StorageType follow. | 405 // Elements of type internal::ArrayDataTraits<T>::StorageType follow. |
| 382 }; | 406 }; |
| 383 MOJO_COMPILE_ASSERT(sizeof(Array_Data<char>) == 8, bad_sizeof_Array_Data); | 407 MOJO_COMPILE_ASSERT(sizeof(Array_Data<char>) == 8, bad_sizeof_Array_Data); |
| 384 | 408 |
| 385 // UTF-8 encoded | 409 // UTF-8 encoded |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 }; | 483 }; |
| 460 | 484 |
| 461 template <> struct WrapperTraits<String, false> { | 485 template <> struct WrapperTraits<String, false> { |
| 462 typedef String_Data* DataType; | 486 typedef String_Data* DataType; |
| 463 }; | 487 }; |
| 464 | 488 |
| 465 } // namespace internal | 489 } // namespace internal |
| 466 } // namespace mojo | 490 } // namespace mojo |
| 467 | 491 |
| 468 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ | 492 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ |
| OLD | NEW |