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