1 /*
2 * Copyright 2019 Google
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "aemu/base/files/Stream.h"
7
8 #include <assert.h>
9 #include <string.h>
10
11 namespace android {
12 namespace base {
13
putByte(uint8_t value)14 void Stream::putByte(uint8_t value) {
15 write(&value, 1U);
16 }
17
getByte()18 uint8_t Stream::getByte() {
19 uint8_t value[1] = { 0 };
20 read(value, 1U);
21 return value[0];
22 }
23
putBe16(uint16_t value)24 void Stream::putBe16(uint16_t value) {
25 uint8_t b[2] = { (uint8_t)(value >> 8), (uint8_t)value };
26 write(b, 2U);
27 }
28
getBe16()29 uint16_t Stream::getBe16() {
30 uint8_t b[2] = { 0, 0 };
31 read(b, 2U);
32 return ((uint16_t)b[0] << 8) | (uint16_t)b[1];
33 }
34
putBe32(uint32_t value)35 void Stream::putBe32(uint32_t value) {
36 uint8_t b[4] = {
37 (uint8_t)(value >> 24),
38 (uint8_t)(value >> 16),
39 (uint8_t)(value >> 8),
40 (uint8_t)value };
41 write(b, 4U);
42 }
43
getBe32()44 uint32_t Stream::getBe32() {
45 uint8_t b[4] = { 0, 0, 0, 0 };
46 read(b, 4U);
47 return ((uint32_t)b[0] << 24) |
48 ((uint32_t)b[1] << 16) |
49 ((uint32_t)b[2] << 8) |
50 (uint32_t)b[3];
51 }
52
putBe64(uint64_t value)53 void Stream::putBe64(uint64_t value) {
54 uint8_t b[8] = {
55 (uint8_t)(value >> 56),
56 (uint8_t)(value >> 48),
57 (uint8_t)(value >> 40),
58 (uint8_t)(value >> 32),
59 (uint8_t)(value >> 24),
60 (uint8_t)(value >> 16),
61 (uint8_t)(value >> 8),
62 (uint8_t)value };
63 write(b, 8U);
64 }
65
getBe64()66 uint64_t Stream::getBe64() {
67 uint8_t b[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
68 read(b, 8U);
69 return ((uint64_t)b[0] << 56) |
70 ((uint64_t)b[1] << 48) |
71 ((uint64_t)b[2] << 40) |
72 ((uint64_t)b[3] << 32) |
73 ((uint64_t)b[4] << 24) |
74 ((uint64_t)b[5] << 16) |
75 ((uint64_t)b[6] << 8) |
76 (uint64_t)b[7];
77 }
78
putFloat(float v)79 void Stream::putFloat(float v) {
80 union {
81 float f;
82 uint8_t bytes[sizeof(float)];
83 } u;
84 u.f = v;
85 this->write(u.bytes, sizeof(u.bytes));
86 }
87
getFloat()88 float Stream::getFloat() {
89 union {
90 float f;
91 uint8_t bytes[sizeof(float)];
92 } u;
93 this->read(u.bytes, sizeof(u.bytes));
94 return u.f;
95 }
96
putString(const char * str)97 void Stream::putString(const char* str) {
98 putString(str, strlen(str));
99 }
100
putString(const char * str,size_t len)101 void Stream::putString(const char* str, size_t len) {
102 this->putBe32(len);
103 this->write(str, len);
104 }
105
putString(const std::string & str)106 void Stream::putString(const std::string& str) {
107 putString(str.c_str());
108 }
109
getString()110 std::string Stream::getString() {
111 std::string result;
112 size_t len = this->getBe32();
113 if (len > 0) {
114 result.resize(len);
115 if (this->read(&result[0], len) != static_cast<ssize_t>(len)) {
116 result.clear();
117 }
118 }
119 #ifdef _WIN32
120 else {
121 // std::string in GCC's STL still uses copy on write implementation
122 // with a single shared buffer for an empty string. Its dtor has
123 // a check for that shared buffer, and it deallocates memory only if
124 // the current string's instance address != shared empty string address
125 // Unfortunately, in Windows DLLs each DLL has its own copy of this
126 // empty string (that's just the way Windows DLLs work), so if this
127 // code creates an empty string and passes it over into another module,
128 // that module's std::string::~string() will compare address with its
129 // empty string object, find that they are different and will try to
130 // free() a static object.
131 // To mitigate it we make sure the string allocates something, so it
132 // isn't empty internally and dtor is OK to delete the storage.
133 result.reserve(1);
134 }
135 #endif
136 return result;
137 }
138
putPackedNum(uint64_t num)139 void Stream::putPackedNum(uint64_t num) {
140 do {
141 auto byte = uint8_t(num & 0x7f);
142 num >>= 7;
143 if (num) {
144 byte |= 0x80;
145 }
146 putByte(byte);
147 } while (num != 0);
148 }
149
getPackedNum()150 uint64_t Stream::getPackedNum() {
151 uint64_t res = 0;
152 uint8_t byte;
153 int i = 0;
154 do {
155 byte = getByte();
156 res |= uint64_t(byte & 0x7f) << (i++ * 7);
157 } while (byte & 0x80 && i < 10);
158 return res;
159 }
160
putPackedSignedNum(int64_t num)161 void Stream::putPackedSignedNum(int64_t num) {
162 if (num >= 0) {
163 assert((uint64_t(num) & (1ULL << 63)) == 0);
164 putPackedNum(uint64_t(num) << 1);
165 } else {
166 assert((uint64_t(-num) & (1ULL << 63)) == 0);
167 putPackedNum((uint64_t(-num) << 1) | 1);
168 }
169 }
170
getPackedSignedNum()171 int64_t Stream::getPackedSignedNum() {
172 auto num = getPackedNum();
173 auto sign = num & 1;
174 return sign ? -int64_t(num >> 1) : (num >> 1);
175 }
176
177 // Static big-endian conversions
178
179 // the |v| pointer is unlikely to be aligned---use memcpy throughout
180
toByte(uint8_t *)181 void Stream::toByte(uint8_t*) { } // no conversion
182
toBe16(uint8_t * v)183 void Stream::toBe16(uint8_t* v) {
184 uint16_t value;
185 memcpy(&value, v, sizeof(uint16_t));
186 uint8_t b[2] = { (uint8_t)(value >> 8), (uint8_t)value };
187 memcpy(v, b, sizeof(uint16_t));
188 }
189
toBe32(uint8_t * v)190 void Stream::toBe32(uint8_t* v) {
191 uint32_t value;
192 memcpy(&value, v, sizeof(uint32_t));
193 uint8_t b[4] = {
194 (uint8_t)(value >> 24),
195 (uint8_t)(value >> 16),
196 (uint8_t)(value >> 8),
197 (uint8_t)value };
198 memcpy(v, b, sizeof(uint32_t));
199 }
200
toBe64(uint8_t * v)201 void Stream::toBe64(uint8_t* v) {
202 uint64_t value;
203 memcpy(&value, v, sizeof(uint64_t));
204 uint8_t b[8] = {
205 (uint8_t)(value >> 56),
206 (uint8_t)(value >> 48),
207 (uint8_t)(value >> 40),
208 (uint8_t)(value >> 32),
209 (uint8_t)(value >> 24),
210 (uint8_t)(value >> 16),
211 (uint8_t)(value >> 8),
212 (uint8_t)value };
213 memcpy(v, b, sizeof(uint64_t));
214 }
215
fromByte(uint8_t *)216 void Stream::fromByte(uint8_t*) { } // no conversion
217
fromBe16(uint8_t * v)218 void Stream::fromBe16(uint8_t* v) {
219 uint8_t b[2];
220 memcpy(b, v, sizeof(uint16_t));
221 uint16_t value = ((uint16_t)b[0] << 8) | (uint16_t)b[1];
222 memcpy(v, &value, sizeof(uint16_t));
223 }
224
fromBe32(uint8_t * v)225 void Stream::fromBe32(uint8_t* v) {
226 uint8_t b[4];
227 memcpy(b, v, sizeof(uint32_t));
228 uint32_t value =
229 ((uint32_t)b[0] << 24) |
230 ((uint32_t)b[1] << 16) |
231 ((uint32_t)b[2] << 8) |
232 (uint32_t)b[3];
233 memcpy(v, &value, sizeof(uint32_t));
234 }
235
fromBe64(uint8_t * v)236 void Stream::fromBe64(uint8_t* v) {
237 uint8_t b[8];
238 memcpy(b, v, sizeof(uint64_t));
239 uint64_t value =
240 ((uint64_t)b[0] << 56) |
241 ((uint64_t)b[1] << 48) |
242 ((uint64_t)b[2] << 40) |
243 ((uint64_t)b[3] << 32) |
244 ((uint64_t)b[4] << 24) |
245 ((uint64_t)b[5] << 16) |
246 ((uint64_t)b[6] << 8) |
247 (uint64_t)b[7];
248 memcpy(v, &value, sizeof(uint64_t));
249 }
250
251 } // namespace base
252 } // namespace android
253