| 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 <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; | 51 return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; |
| 52 } | 52 } |
| 53 static Ref ToRef(StorageType* storage, size_t offset) { | 53 static Ref ToRef(StorageType* storage, size_t offset) { |
| 54 return storage[offset]; | 54 return storage[offset]; |
| 55 } | 55 } |
| 56 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { | 56 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { |
| 57 return storage[offset]; | 57 return storage[offset]; |
| 58 } | 58 } |
| 59 }; | 59 }; |
| 60 | 60 |
| 61 template <typename P> | |
| 62 struct ArrayDataTraits<P*> { | |
| 63 using StorageType = Pointer<P>; | |
| 64 using Ref = P*&; | |
| 65 using ConstRef = P* const&; | |
| 66 | |
| 67 static const uint32_t kMaxNumElements = | |
| 68 (std::numeric_limits<uint32_t>::max() - sizeof(ArrayHeader)) / | |
| 69 sizeof(StorageType); | |
| 70 | |
| 71 static uint32_t GetStorageSize(uint32_t num_elements) { | |
| 72 DCHECK(num_elements <= kMaxNumElements); | |
| 73 return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; | |
| 74 } | |
| 75 static Ref ToRef(StorageType* storage, size_t offset) { | |
| 76 return storage[offset].ptr; | |
| 77 } | |
| 78 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { | |
| 79 return storage[offset].ptr; | |
| 80 } | |
| 81 }; | |
| 82 | |
| 83 // Specialization of Arrays for bools, optimized for space. It has the | 61 // Specialization of Arrays for bools, optimized for space. It has the |
| 84 // following differences from a generalized Array: | 62 // following differences from a generalized Array: |
| 85 // * Each element takes up a single bit of memory. | 63 // * Each element takes up a single bit of memory. |
| 86 // * Accessing a non-const single element uses a helper class |BitRef|, which | 64 // * Accessing a non-const single element uses a helper class |BitRef|, which |
| 87 // emulates a reference to a bool. | 65 // emulates a reference to a bool. |
| 88 template <> | 66 template <> |
| 89 struct ArrayDataTraits<bool> { | 67 struct ArrayDataTraits<bool> { |
| 90 // Helper class to emulate a reference to a bool, used for direct element | 68 // Helper class to emulate a reference to a bool, used for direct element |
| 91 // access. | 69 // access. |
| 92 class BitRef { | 70 class BitRef { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 // wrapper type instead of the data type, that way we can use MojomTypeTraits | 112 // wrapper type instead of the data type, that way we can use MojomTypeTraits |
| 135 // to determine the categories. | 113 // to determine the categories. |
| 136 | 114 |
| 137 template <typename T, bool is_union, bool is_handle_or_interface> | 115 template <typename T, bool is_union, bool is_handle_or_interface> |
| 138 struct ArraySerializationHelper; | 116 struct ArraySerializationHelper; |
| 139 | 117 |
| 140 template <typename T> | 118 template <typename T> |
| 141 struct ArraySerializationHelper<T, false, false> { | 119 struct ArraySerializationHelper<T, false, false> { |
| 142 using ElementType = typename ArrayDataTraits<T>::StorageType; | 120 using ElementType = typename ArrayDataTraits<T>::StorageType; |
| 143 | 121 |
| 144 static void EncodePointers(const ArrayHeader* header, | |
| 145 ElementType* elements) {} | |
| 146 | |
| 147 static void DecodePointers(const ArrayHeader* header, | |
| 148 ElementType* elements) {} | |
| 149 | |
| 150 static bool ValidateElements(const ArrayHeader* header, | 122 static bool ValidateElements(const ArrayHeader* header, |
| 151 const ElementType* elements, | 123 const ElementType* elements, |
| 152 ValidationContext* validation_context, | 124 ValidationContext* validation_context, |
| 153 const ContainerValidateParams* validate_params) { | 125 const ContainerValidateParams* validate_params) { |
| 154 DCHECK(!validate_params->element_is_nullable) | 126 DCHECK(!validate_params->element_is_nullable) |
| 155 << "Primitive type should be non-nullable"; | 127 << "Primitive type should be non-nullable"; |
| 156 DCHECK(!validate_params->element_validate_params) | 128 DCHECK(!validate_params->element_validate_params) |
| 157 << "Primitive type should not have array validate params"; | 129 << "Primitive type should not have array validate params"; |
| 158 | 130 |
| 159 if (!validate_params->validate_enum_func) | 131 if (!validate_params->validate_enum_func) |
| 160 return true; | 132 return true; |
| 161 | 133 |
| 162 // Enum validation. | 134 // Enum validation. |
| 163 for (uint32_t i = 0; i < header->num_elements; ++i) { | 135 for (uint32_t i = 0; i < header->num_elements; ++i) { |
| 164 if (!validate_params->validate_enum_func(elements[i], validation_context)) | 136 if (!validate_params->validate_enum_func(elements[i], validation_context)) |
| 165 return false; | 137 return false; |
| 166 } | 138 } |
| 167 return true; | 139 return true; |
| 168 } | 140 } |
| 169 }; | 141 }; |
| 170 | 142 |
| 171 template <typename T> | 143 template <typename T> |
| 172 struct ArraySerializationHelper<T, false, true> { | 144 struct ArraySerializationHelper<T, false, true> { |
| 173 using ElementType = typename ArrayDataTraits<T>::StorageType; | 145 using ElementType = typename ArrayDataTraits<T>::StorageType; |
| 174 | 146 |
| 175 static void EncodePointers(const ArrayHeader* header, | |
| 176 ElementType* elements) {} | |
| 177 | |
| 178 static void DecodePointers(const ArrayHeader* header, | |
| 179 ElementType* elements) {} | |
| 180 | |
| 181 static bool ValidateElements(const ArrayHeader* header, | 147 static bool ValidateElements(const ArrayHeader* header, |
| 182 const ElementType* elements, | 148 const ElementType* elements, |
| 183 ValidationContext* validation_context, | 149 ValidationContext* validation_context, |
| 184 const ContainerValidateParams* validate_params) { | 150 const ContainerValidateParams* validate_params) { |
| 185 DCHECK(!validate_params->element_validate_params) | 151 DCHECK(!validate_params->element_validate_params) |
| 186 << "Handle or interface type should not have array validate params"; | 152 << "Handle or interface type should not have array validate params"; |
| 187 | 153 |
| 188 for (uint32_t i = 0; i < header->num_elements; ++i) { | 154 for (uint32_t i = 0; i < header->num_elements; ++i) { |
| 189 if (!validate_params->element_is_nullable && | 155 if (!validate_params->element_is_nullable && |
| 190 !IsHandleOrInterfaceValid(elements[i])) { | 156 !IsHandleOrInterfaceValid(elements[i])) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 202 .c_str()); | 168 .c_str()); |
| 203 return false; | 169 return false; |
| 204 } | 170 } |
| 205 if (!ValidateHandleOrInterface(elements[i], validation_context)) | 171 if (!ValidateHandleOrInterface(elements[i], validation_context)) |
| 206 return false; | 172 return false; |
| 207 } | 173 } |
| 208 return true; | 174 return true; |
| 209 } | 175 } |
| 210 }; | 176 }; |
| 211 | 177 |
| 212 template <typename P> | 178 template <typename T> |
| 213 struct ArraySerializationHelper<P*, false, false> { | 179 struct ArraySerializationHelper<Pointer<T>, false, false> { |
| 214 using ElementType = typename ArrayDataTraits<P*>::StorageType; | 180 using ElementType = typename ArrayDataTraits<Pointer<T>>::StorageType; |
| 215 | |
| 216 static void EncodePointers(const ArrayHeader* header, ElementType* elements) { | |
| 217 for (uint32_t i = 0; i < header->num_elements; ++i) | |
| 218 Encode(&elements[i]); | |
| 219 } | |
| 220 | |
| 221 static void DecodePointers(const ArrayHeader* header, ElementType* elements) { | |
| 222 for (uint32_t i = 0; i < header->num_elements; ++i) | |
| 223 Decode(&elements[i]); | |
| 224 } | |
| 225 | 181 |
| 226 static bool ValidateElements(const ArrayHeader* header, | 182 static bool ValidateElements(const ArrayHeader* header, |
| 227 const ElementType* elements, | 183 const ElementType* elements, |
| 228 ValidationContext* validation_context, | 184 ValidationContext* validation_context, |
| 229 const ContainerValidateParams* validate_params) { | 185 const ContainerValidateParams* validate_params) { |
| 230 for (uint32_t i = 0; i < header->num_elements; ++i) { | 186 for (uint32_t i = 0; i < header->num_elements; ++i) { |
| 231 if (!validate_params->element_is_nullable && !elements[i].offset) { | 187 if (!validate_params->element_is_nullable && !elements[i].offset) { |
| 232 ReportValidationError( | 188 ReportValidationError( |
| 233 validation_context, | 189 validation_context, |
| 234 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | 190 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, |
| 235 MakeMessageWithArrayIndex("null in array expecting valid pointers", | 191 MakeMessageWithArrayIndex("null in array expecting valid pointers", |
| 236 header->num_elements, | 192 header->num_elements, |
| 237 i).c_str()); | 193 i).c_str()); |
| 238 return false; | 194 return false; |
| 239 } | 195 } |
| 240 if (!ValidateCaller<P>::Run(elements[i], validation_context, | 196 if (!ValidateCaller<T>::Run(elements[i], validation_context, |
| 241 validate_params->element_validate_params)) { | 197 validate_params->element_validate_params)) { |
| 242 return false; | 198 return false; |
| 243 } | 199 } |
| 244 } | 200 } |
| 245 return true; | 201 return true; |
| 246 } | 202 } |
| 247 | 203 |
| 248 private: | 204 private: |
| 249 template <typename T> | 205 template <typename U, |
| 206 bool is_array_or_map = IsSpecializationOf<Array_Data, U>::value || |
| 207 IsSpecializationOf<Map_Data, U>::value> |
| 250 struct ValidateCaller { | 208 struct ValidateCaller { |
| 251 static bool Run(const Pointer<T>& data, | 209 static bool Run(const Pointer<U>& data, |
| 252 ValidationContext* validation_context, | 210 ValidationContext* validation_context, |
| 253 const ContainerValidateParams* validate_params) { | 211 const ContainerValidateParams* validate_params) { |
| 254 DCHECK(!validate_params) | 212 DCHECK(!validate_params) |
| 255 << "Struct type should not have array validate params"; | 213 << "Struct type should not have array validate params"; |
| 256 | 214 |
| 257 return ValidateStruct(data, validation_context); | 215 return ValidateStruct(data, validation_context); |
| 258 } | 216 } |
| 259 }; | 217 }; |
| 260 | 218 |
| 261 template <typename Key, typename Value> | 219 template <typename U> |
| 262 struct ValidateCaller<Map_Data<Key, Value>> { | 220 struct ValidateCaller<U, true> { |
| 263 static bool Run(const Pointer<Map_Data<Key, Value>>& data, | 221 static bool Run(const Pointer<U>& data, |
| 264 ValidationContext* validation_context, | 222 ValidationContext* validation_context, |
| 265 const ContainerValidateParams* validate_params) { | 223 const ContainerValidateParams* validate_params) { |
| 266 return ValidateMap(data, validation_context, validate_params); | 224 return ValidateContainer(data, validation_context, validate_params); |
| 267 } | |
| 268 }; | |
| 269 | |
| 270 template <typename T> | |
| 271 struct ValidateCaller<Array_Data<T>> { | |
| 272 static bool Run(const Pointer<Array_Data<T>>& data, | |
| 273 ValidationContext* validation_context, | |
| 274 const ContainerValidateParams* validate_params) { | |
| 275 return ValidateArray(data, validation_context, validate_params); | |
| 276 } | 225 } |
| 277 }; | 226 }; |
| 278 }; | 227 }; |
| 279 | 228 |
| 280 template <typename U> | 229 template <typename U> |
| 281 struct ArraySerializationHelper<U, true, false> { | 230 struct ArraySerializationHelper<U, true, false> { |
| 282 using ElementType = typename ArrayDataTraits<U>::StorageType; | 231 using ElementType = typename ArrayDataTraits<U>::StorageType; |
| 283 | 232 |
| 284 static void EncodePointers(const ArrayHeader* header, ElementType* elements) { | |
| 285 for (uint32_t i = 0; i < header->num_elements; ++i) | |
| 286 elements[i].EncodePointers(); | |
| 287 } | |
| 288 | |
| 289 static void DecodePointers(const ArrayHeader* header, ElementType* elements) { | |
| 290 for (uint32_t i = 0; i < header->num_elements; ++i) | |
| 291 elements[i].DecodePointers(); | |
| 292 } | |
| 293 | |
| 294 static bool ValidateElements(const ArrayHeader* header, | 233 static bool ValidateElements(const ArrayHeader* header, |
| 295 const ElementType* elements, | 234 const ElementType* elements, |
| 296 ValidationContext* validation_context, | 235 ValidationContext* validation_context, |
| 297 const ContainerValidateParams* validate_params) { | 236 const ContainerValidateParams* validate_params) { |
| 298 for (uint32_t i = 0; i < header->num_elements; ++i) { | 237 for (uint32_t i = 0; i < header->num_elements; ++i) { |
| 299 if (!validate_params->element_is_nullable && elements[i].is_null()) { | 238 if (!validate_params->element_is_nullable && elements[i].is_null()) { |
| 300 ReportValidationError( | 239 ReportValidationError( |
| 301 validation_context, | 240 validation_context, |
| 302 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | 241 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, |
| 303 MakeMessageWithArrayIndex("null in array expecting valid unions", | 242 MakeMessageWithArrayIndex("null in array expecting valid unions", |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 StorageType* storage() { | 338 StorageType* storage() { |
| 400 return reinterpret_cast<StorageType*>(reinterpret_cast<char*>(this) + | 339 return reinterpret_cast<StorageType*>(reinterpret_cast<char*>(this) + |
| 401 sizeof(*this)); | 340 sizeof(*this)); |
| 402 } | 341 } |
| 403 | 342 |
| 404 const StorageType* storage() const { | 343 const StorageType* storage() const { |
| 405 return reinterpret_cast<const StorageType*>( | 344 return reinterpret_cast<const StorageType*>( |
| 406 reinterpret_cast<const char*>(this) + sizeof(*this)); | 345 reinterpret_cast<const char*>(this) + sizeof(*this)); |
| 407 } | 346 } |
| 408 | 347 |
| 409 void EncodePointers() { Helper::EncodePointers(&header_, storage()); } | |
| 410 void DecodePointers() { Helper::DecodePointers(&header_, storage()); } | |
| 411 | |
| 412 private: | 348 private: |
| 413 Array_Data(uint32_t num_bytes, uint32_t num_elements) { | 349 Array_Data(uint32_t num_bytes, uint32_t num_elements) { |
| 414 header_.num_bytes = num_bytes; | 350 header_.num_bytes = num_bytes; |
| 415 header_.num_elements = num_elements; | 351 header_.num_elements = num_elements; |
| 416 } | 352 } |
| 417 ~Array_Data() = delete; | 353 ~Array_Data() = delete; |
| 418 | 354 |
| 419 internal::ArrayHeader header_; | 355 internal::ArrayHeader header_; |
| 420 | 356 |
| 421 // Elements of type internal::ArrayDataTraits<T>::StorageType follow. | 357 // Elements of type internal::ArrayDataTraits<T>::StorageType follow. |
| 422 }; | 358 }; |
| 423 static_assert(sizeof(Array_Data<char>) == 8, "Bad sizeof(Array_Data)"); | 359 static_assert(sizeof(Array_Data<char>) == 8, "Bad sizeof(Array_Data)"); |
| 424 | 360 |
| 425 // UTF-8 encoded | 361 // UTF-8 encoded |
| 426 using String_Data = Array_Data<char>; | 362 using String_Data = Array_Data<char>; |
| 427 | 363 |
| 428 } // namespace internal | 364 } // namespace internal |
| 429 } // namespace mojo | 365 } // namespace mojo |
| 430 | 366 |
| 431 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ | 367 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ |
| OLD | NEW |