1 // 2 // Copyright (C) 2017 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef PROPERTY_INFO_SERIALIZER_TRIE_NODE_ARENA_H 18 #define PROPERTY_INFO_SERIALIZER_TRIE_NODE_ARENA_H 19 20 #include <string> 21 #include <vector> 22 23 namespace android { 24 namespace properties { 25 26 template <typename T> 27 class ArenaObjectPointer { 28 public: ArenaObjectPointer(std::string & arena_data,uint32_t offset)29 ArenaObjectPointer(std::string& arena_data, uint32_t offset) 30 : arena_data_(arena_data), offset_(offset) {} 31 32 T* operator->() { return reinterpret_cast<T*>(arena_data_.data() + offset_); } 33 34 private: 35 std::string& arena_data_; 36 uint32_t offset_; 37 }; 38 39 class TrieNodeArena { 40 public: TrieNodeArena()41 TrieNodeArena() : current_data_pointer_(0) {} 42 43 // We can't return pointers to objects since data_ may move when reallocated, thus invalidating 44 // any pointers. Therefore we return an ArenaObjectPointer, which always accesses elements via 45 // data_ + offset. 46 template <typename T> AllocateObject(uint32_t * return_offset)47 ArenaObjectPointer<T> AllocateObject(uint32_t* return_offset) { 48 uint32_t offset; 49 AllocateData(sizeof(T), &offset); 50 if (return_offset) *return_offset = offset; 51 return ArenaObjectPointer<T>(data_, offset); 52 } 53 AllocateUint32Array(int length)54 uint32_t AllocateUint32Array(int length) { 55 uint32_t offset; 56 AllocateData(sizeof(uint32_t) * length, &offset); 57 return offset; 58 } 59 uint32_array(uint32_t offset)60 uint32_t* uint32_array(uint32_t offset) { 61 return reinterpret_cast<uint32_t*>(data_.data() + offset); 62 } 63 AllocateAndWriteString(const std::string & string)64 uint32_t AllocateAndWriteString(const std::string& string) { 65 uint32_t offset; 66 char* data = static_cast<char*>(AllocateData(string.size() + 1, &offset)); 67 strcpy(data, string.c_str()); 68 return offset; 69 } 70 AllocateAndWriteUint32(uint32_t value)71 void AllocateAndWriteUint32(uint32_t value) { 72 auto location = static_cast<uint32_t*>(AllocateData(sizeof(uint32_t), nullptr)); 73 *location = value; 74 } 75 AllocateData(size_t size,uint32_t * offset)76 void* AllocateData(size_t size, uint32_t* offset) { 77 size_t aligned_size = size + (sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1); 78 79 if (current_data_pointer_ + aligned_size > data_.size()) { 80 auto new_size = (current_data_pointer_ + aligned_size + data_.size()) * 2; 81 data_.resize(new_size, '\0'); 82 } 83 if (offset) *offset = current_data_pointer_; 84 85 uint32_t return_offset = current_data_pointer_; 86 current_data_pointer_ += aligned_size; 87 return &data_[0] + return_offset; 88 } 89 size()90 uint32_t size() const { return current_data_pointer_; } 91 data()92 const std::string& data() const { return data_; } 93 truncated_data()94 std::string truncated_data() const { 95 auto result = data_; 96 result.resize(current_data_pointer_); 97 return result; 98 } 99 100 private: 101 std::string data_; 102 uint32_t current_data_pointer_; 103 }; 104 105 } // namespace properties 106 } // namespace android 107 108 #endif 109