• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Android Open Source Project
2 //
3 // This software is licensed under the terms of the GNU General Public
4 // License version 2, as published by the Free Software Foundation, and
5 // may be copied, distributed, and modified under those terms.
6 //
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License for more details.
11 
12 #include "android/base/files/Stream.h"
13 
14 #include <assert.h>
15 #include <string.h>
16 
17 namespace android {
18 namespace base {
19 
putByte(uint8_t value)20 void Stream::putByte(uint8_t value) {
21     write(&value, 1U);
22 }
23 
getByte()24 uint8_t Stream::getByte() {
25     uint8_t value[1] = { 0 };
26     read(value, 1U);
27     return value[0];
28 }
29 
putBe16(uint16_t value)30 void Stream::putBe16(uint16_t value) {
31     uint8_t b[2] = { (uint8_t)(value >> 8), (uint8_t)value };
32     write(b, 2U);
33 }
34 
getBe16()35 uint16_t Stream::getBe16() {
36     uint8_t b[2] = { 0, 0 };
37     read(b, 2U);
38     return ((uint16_t)b[0] << 8) | (uint16_t)b[1];
39 }
40 
putBe32(uint32_t value)41 void Stream::putBe32(uint32_t value) {
42     uint8_t b[4] = {
43             (uint8_t)(value >> 24),
44             (uint8_t)(value >> 16),
45             (uint8_t)(value >> 8),
46             (uint8_t)value };
47     write(b, 4U);
48 }
49 
getBe32()50 uint32_t Stream::getBe32() {
51     uint8_t b[4] = { 0, 0, 0, 0 };
52     read(b, 4U);
53     return ((uint32_t)b[0] << 24) |
54            ((uint32_t)b[1] << 16) |
55            ((uint32_t)b[2] << 8) |
56            (uint32_t)b[3];
57 }
58 
putBe64(uint64_t value)59 void Stream::putBe64(uint64_t value) {
60     uint8_t b[8] = {
61             (uint8_t)(value >> 56),
62             (uint8_t)(value >> 48),
63             (uint8_t)(value >> 40),
64             (uint8_t)(value >> 32),
65             (uint8_t)(value >> 24),
66             (uint8_t)(value >> 16),
67             (uint8_t)(value >> 8),
68             (uint8_t)value };
69     write(b, 8U);
70 }
71 
getBe64()72 uint64_t Stream::getBe64() {
73     uint8_t b[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
74     read(b, 8U);
75     return ((uint64_t)b[0] << 56) |
76            ((uint64_t)b[1] << 48) |
77            ((uint64_t)b[2] << 40) |
78            ((uint64_t)b[3] << 32) |
79            ((uint64_t)b[4] << 24) |
80            ((uint64_t)b[5] << 16) |
81            ((uint64_t)b[6] << 8) |
82            (uint64_t)b[7];
83 }
84 
putFloat(float v)85 void Stream::putFloat(float v) {
86     union {
87         float f;
88         uint8_t bytes[sizeof(float)];
89     } u;
90     u.f = v;
91     this->write(u.bytes, sizeof(u.bytes));
92 }
93 
getFloat()94 float Stream::getFloat() {
95     union {
96         float f;
97         uint8_t bytes[sizeof(float)];
98     } u;
99     this->read(u.bytes, sizeof(u.bytes));
100     return u.f;
101 }
102 
putString(StringView str)103 void Stream::putString(StringView str) {
104     this->putBe32(str.size());
105     this->write(str.data(), str.size());
106 }
107 
putString(const char * str)108 void Stream::putString(const char* str) {
109     putString(StringView(str));
110 }
111 
putString(const char * str,size_t len)112 void Stream::putString(const char* str, size_t len) {
113     putString(StringView(str, len));
114 }
115 
getString()116 std::string Stream::getString() {
117     std::string result;
118     size_t len = this->getBe32();
119     if (len > 0) {
120         result.resize(len);
121         if (this->read(&result[0], len) != static_cast<ssize_t>(len)) {
122             result.clear();
123         }
124     }
125 #ifdef _WIN32
126     else {
127         // std::string in GCC's STL still uses copy on write implementation
128         // with a single shared buffer for an empty string. Its dtor has
129         // a check for that shared buffer, and it deallocates memory only if
130         // the current string's instance address != shared empty string address
131         // Unfortunately, in Windows DLLs each DLL has its own copy of this
132         // empty string (that's just the way Windows DLLs work), so if this
133         // code creates an empty string and passes it over into another module,
134         // that module's std::string::~string() will compare address with its
135         // empty string object, find that they are different and will try to
136         // free() a static object.
137         // To mitigate it we make sure the string allocates something, so it
138         // isn't empty internally and dtor is OK to delete the storage.
139         result.reserve(1);
140     }
141 #endif
142     return result;
143 }
144 
putPackedNum(uint64_t num)145 void Stream::putPackedNum(uint64_t num) {
146     do {
147         auto byte = uint8_t(num & 0x7f);
148         num >>= 7;
149         if (num) {
150             byte |= 0x80;
151         }
152         putByte(byte);
153     } while (num != 0);
154 }
155 
getPackedNum()156 uint64_t Stream::getPackedNum() {
157     uint64_t res = 0;
158     uint8_t byte;
159     int i = 0;
160     do {
161         byte = getByte();
162         res |= uint64_t(byte & 0x7f) << (i++ * 7);
163     } while (byte & 0x80 && i < 10);
164     return res;
165 }
166 
putPackedSignedNum(int64_t num)167 void Stream::putPackedSignedNum(int64_t num) {
168     if (num >= 0) {
169         assert((uint64_t(num) & (1ULL << 63)) == 0);
170         putPackedNum(uint64_t(num) << 1);
171     } else {
172         assert((uint64_t(-num) & (1ULL << 63)) == 0);
173         putPackedNum((uint64_t(-num) << 1) | 1);
174     }
175 }
176 
getPackedSignedNum()177 int64_t Stream::getPackedSignedNum() {
178     auto num = getPackedNum();
179     auto sign = num & 1;
180     return sign ? -int64_t(num >> 1) : (num >> 1);
181 }
182 
183 }  // namespace base
184 }  // namespace android
185