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