• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 MINIKIN_BUFFER_H
18 #define MINIKIN_BUFFER_H
19 
20 #include <cstring>
21 #include <string_view>
22 #include <type_traits>
23 #include <utility>
24 
25 namespace minikin {
26 
27 // This is a helper class to read data from a memory buffer.
28 // This class does not copy memory, and may return pointers to parts of the memory buffer.
29 // Thus the memory buffer should outlive objects created using this class.
30 class BufferReader {
31 public:
BufferReader(const void * buffer)32     BufferReader(const void* buffer) : BufferReader(buffer, 0) {}
BufferReader(const void * buffer,uint32_t pos)33     BufferReader(const void* buffer, uint32_t pos)
34             : mData(reinterpret_cast<const uint8_t*>(buffer)), mPos(pos) {}
35 
36     template <typename T>
align(uint32_t pos)37     static uint32_t align(uint32_t pos) {
38         // This should be true for all types, unless custom alignment attributes are set.
39         static_assert(sizeof(T) % alignof(T) == 0, "sizeof(T) must be a multiple of alignof(T)");
40         // We align to sizeof(T) instead of alignof(T), because the buffer may be shared between
41         // 32-bit processes and 64-bit processes. alignof(T) may change between the two.
42         // We assume that T is a type whose size is fixed (e.g. uint32_t).
43         return (pos + sizeof(T) - 1) / sizeof(T) * sizeof(T);
44     }
45 
46     template <typename T>
read()47     const T& read() {
48         static_assert(std::is_pod<T>::value, "T must be a POD");
49         mPos = BufferReader::align<T>(mPos);
50         const T* data = reinterpret_cast<const T*>(mData + mPos);
51         mPos += sizeof(T);
52         return *data;
53     }
54 
55     template <typename T>
skip()56     void skip() {
57         static_assert(std::is_pod<T>::value, "T must be a POD");
58         mPos = BufferReader::align<T>(mPos);
59         mPos += sizeof(T);
60     }
61 
62     // Return a pointer to an array and its number of elements.
63     template <typename T>
readArray()64     std::pair<const T*, uint32_t> readArray() {
65         static_assert(std::is_pod<T>::value, "T must be a POD");
66         uint32_t size = read<uint32_t>();
67         mPos = BufferReader::align<T>(mPos);
68         const T* data = reinterpret_cast<const T*>(mData + mPos);
69         mPos += size * sizeof(T);
70         return std::make_pair(data, size);
71     }
72 
73     template <typename T>
skipArray()74     void skipArray() {
75         static_assert(std::is_pod<T>::value, "T must be a POD");
76         uint32_t size = read<uint32_t>();
77         mPos = BufferReader::align<T>(mPos);
78         mPos += size * sizeof(T);
79     }
80 
readString()81     std::string_view readString() {
82         auto [data, size] = readArray<char>();
83         return std::string_view(data, size);
84     }
85 
skipString()86     void skipString() { skipArray<char>(); }
87 
data()88     const void* data() const { return mData; }
pos()89     size_t pos() const { return mPos; }
90 
91 private:
92     const uint8_t* mData;
93     size_t mPos;
94 };
95 
96 // This is a helper class to write data to a memory buffer.
97 class BufferWriter {
98 public:
99     // Create a buffer writer. Passing nullptr creates a fake writer,
100     // which can be used to measure the buffer size needed.
BufferWriter(void * buffer)101     BufferWriter(void* buffer) : mData(reinterpret_cast<uint8_t*>(buffer)), mPos(0) {}
102 
103     BufferWriter(BufferWriter&&) = default;
104     BufferWriter& operator=(BufferWriter&&) = default;
105 
106     // Write a single data of type T.
107     // Please always specify T explicitly using <>. std::common_type_t<T> resolves to T, but
108     // disables template argument deduction.
109     // TODO: use std::type_identity_t when C++20 is available.
110     template <typename T>
write(const std::common_type_t<T> & data)111     void write(const std::common_type_t<T>& data) {
112         static_assert(std::is_pod<T>::value, "T must be a POD");
113         mPos = BufferReader::align<T>(mPos);
114         if (mData != nullptr) {
115             memcpy(mData + mPos, &data, sizeof(T));
116         }
117         mPos += sizeof(T);
118     }
119 
120     // Write an array of type T.
121     // Please always specify T explicitly using <>. std::common_type_t<T> resolves to T, but
122     // disables template argument deduction.
123     // TODO: use std::type_identity_t when C++20 is available.
124     template <typename T>
writeArray(const std::common_type_t<T> * data,uint32_t size)125     void writeArray(const std::common_type_t<T>* data, uint32_t size) {
126         static_assert(std::is_pod<T>::value, "T must be a POD");
127         write<uint32_t>(size);
128         mPos = BufferReader::align<T>(mPos);
129         if (mData != nullptr) {
130             memcpy(mData + mPos, data, size * sizeof(T));
131         }
132         mPos += size * sizeof(T);
133     }
134 
writeString(std::string_view string)135     void writeString(std::string_view string) { writeArray<char>(string.data(), string.size()); }
136 
137     // Return the number of bytes written.
size()138     size_t size() const { return mPos; }
139 
140 private:
141     uint8_t* mData;
142     size_t mPos;
143 
144     // Forbid copy and assign.
145     BufferWriter(const BufferWriter&) = delete;
146     void operator=(const BufferWriter&) = delete;
147 };
148 
149 }  // namespace minikin
150 
151 #endif  // MINIKIN_BUFFER_H
152