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