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