1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2012 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker // BinaryStream.h: Provides binary serialization of simple types.
8*8975f5c5SAndroid Build Coastguard Worker
9*8975f5c5SAndroid Build Coastguard Worker #ifndef COMMON_BINARYSTREAM_H_
10*8975f5c5SAndroid Build Coastguard Worker #define COMMON_BINARYSTREAM_H_
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker #include <stdint.h>
13*8975f5c5SAndroid Build Coastguard Worker #include <cstddef>
14*8975f5c5SAndroid Build Coastguard Worker #include <string>
15*8975f5c5SAndroid Build Coastguard Worker #include <vector>
16*8975f5c5SAndroid Build Coastguard Worker
17*8975f5c5SAndroid Build Coastguard Worker #include "common/PackedEnums.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "common/angleutils.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "common/mathutil.h"
20*8975f5c5SAndroid Build Coastguard Worker
21*8975f5c5SAndroid Build Coastguard Worker namespace gl
22*8975f5c5SAndroid Build Coastguard Worker {
23*8975f5c5SAndroid Build Coastguard Worker template <typename IntT>
24*8975f5c5SAndroid Build Coastguard Worker struct PromotedIntegerType
25*8975f5c5SAndroid Build Coastguard Worker {
26*8975f5c5SAndroid Build Coastguard Worker using type = typename std::conditional<
27*8975f5c5SAndroid Build Coastguard Worker std::is_signed<IntT>::value,
28*8975f5c5SAndroid Build Coastguard Worker typename std::conditional<sizeof(IntT) <= 4, int32_t, int64_t>::type,
29*8975f5c5SAndroid Build Coastguard Worker typename std::conditional<sizeof(IntT) <= 4, uint32_t, uint64_t>::type>::type;
30*8975f5c5SAndroid Build Coastguard Worker };
31*8975f5c5SAndroid Build Coastguard Worker
32*8975f5c5SAndroid Build Coastguard Worker class BinaryInputStream : angle::NonCopyable
33*8975f5c5SAndroid Build Coastguard Worker {
34*8975f5c5SAndroid Build Coastguard Worker public:
BinaryInputStream(const void * data,size_t length)35*8975f5c5SAndroid Build Coastguard Worker BinaryInputStream(const void *data, size_t length)
36*8975f5c5SAndroid Build Coastguard Worker {
37*8975f5c5SAndroid Build Coastguard Worker mError = false;
38*8975f5c5SAndroid Build Coastguard Worker mOffset = 0;
39*8975f5c5SAndroid Build Coastguard Worker mData = static_cast<const uint8_t *>(data);
40*8975f5c5SAndroid Build Coastguard Worker mLength = length;
41*8975f5c5SAndroid Build Coastguard Worker }
42*8975f5c5SAndroid Build Coastguard Worker
43*8975f5c5SAndroid Build Coastguard Worker // readInt will generate an error for bool types
44*8975f5c5SAndroid Build Coastguard Worker template <class IntT>
readInt()45*8975f5c5SAndroid Build Coastguard Worker IntT readInt()
46*8975f5c5SAndroid Build Coastguard Worker {
47*8975f5c5SAndroid Build Coastguard Worker static_assert(!std::is_same<bool, std::remove_cv<IntT>()>(), "Use readBool");
48*8975f5c5SAndroid Build Coastguard Worker using PromotedIntT = typename PromotedIntegerType<IntT>::type;
49*8975f5c5SAndroid Build Coastguard Worker PromotedIntT value = 0;
50*8975f5c5SAndroid Build Coastguard Worker read(&value);
51*8975f5c5SAndroid Build Coastguard Worker ASSERT(angle::IsValueInRangeForNumericType<IntT>(value));
52*8975f5c5SAndroid Build Coastguard Worker return static_cast<IntT>(value);
53*8975f5c5SAndroid Build Coastguard Worker }
54*8975f5c5SAndroid Build Coastguard Worker
55*8975f5c5SAndroid Build Coastguard Worker template <class IntT>
readInt(IntT * outValue)56*8975f5c5SAndroid Build Coastguard Worker void readInt(IntT *outValue)
57*8975f5c5SAndroid Build Coastguard Worker {
58*8975f5c5SAndroid Build Coastguard Worker *outValue = readInt<IntT>();
59*8975f5c5SAndroid Build Coastguard Worker }
60*8975f5c5SAndroid Build Coastguard Worker
61*8975f5c5SAndroid Build Coastguard Worker template <class T>
readVector(std::vector<T> * param)62*8975f5c5SAndroid Build Coastguard Worker void readVector(std::vector<T> *param)
63*8975f5c5SAndroid Build Coastguard Worker {
64*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<T>(), "must be memcpy-able");
65*8975f5c5SAndroid Build Coastguard Worker ASSERT(param->empty());
66*8975f5c5SAndroid Build Coastguard Worker size_t size = readInt<size_t>();
67*8975f5c5SAndroid Build Coastguard Worker if (size > 0)
68*8975f5c5SAndroid Build Coastguard Worker {
69*8975f5c5SAndroid Build Coastguard Worker param->resize(size);
70*8975f5c5SAndroid Build Coastguard Worker readBytes(reinterpret_cast<uint8_t *>(param->data()), param->size() * sizeof(T));
71*8975f5c5SAndroid Build Coastguard Worker }
72*8975f5c5SAndroid Build Coastguard Worker }
73*8975f5c5SAndroid Build Coastguard Worker
74*8975f5c5SAndroid Build Coastguard Worker template <typename E, typename T>
readPackedEnumMap(angle::PackedEnumMap<E,T> * param)75*8975f5c5SAndroid Build Coastguard Worker void readPackedEnumMap(angle::PackedEnumMap<E, T> *param)
76*8975f5c5SAndroid Build Coastguard Worker {
77*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<T>(), "must be memcpy-able");
78*8975f5c5SAndroid Build Coastguard Worker readBytes(reinterpret_cast<uint8_t *>(param->data()), param->size() * sizeof(T));
79*8975f5c5SAndroid Build Coastguard Worker }
80*8975f5c5SAndroid Build Coastguard Worker
81*8975f5c5SAndroid Build Coastguard Worker template <class T>
readStruct(T * param)82*8975f5c5SAndroid Build Coastguard Worker void readStruct(T *param)
83*8975f5c5SAndroid Build Coastguard Worker {
84*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<T>(), "must be memcpy-able");
85*8975f5c5SAndroid Build Coastguard Worker readBytes(reinterpret_cast<uint8_t *>(param), sizeof(T));
86*8975f5c5SAndroid Build Coastguard Worker }
87*8975f5c5SAndroid Build Coastguard Worker
88*8975f5c5SAndroid Build Coastguard Worker template <class EnumT>
readEnum()89*8975f5c5SAndroid Build Coastguard Worker EnumT readEnum()
90*8975f5c5SAndroid Build Coastguard Worker {
91*8975f5c5SAndroid Build Coastguard Worker using UnderlyingType = typename std::underlying_type<EnumT>::type;
92*8975f5c5SAndroid Build Coastguard Worker return static_cast<EnumT>(readInt<UnderlyingType>());
93*8975f5c5SAndroid Build Coastguard Worker }
94*8975f5c5SAndroid Build Coastguard Worker
95*8975f5c5SAndroid Build Coastguard Worker template <class EnumT>
readEnum(EnumT * outValue)96*8975f5c5SAndroid Build Coastguard Worker void readEnum(EnumT *outValue)
97*8975f5c5SAndroid Build Coastguard Worker {
98*8975f5c5SAndroid Build Coastguard Worker *outValue = readEnum<EnumT>();
99*8975f5c5SAndroid Build Coastguard Worker }
100*8975f5c5SAndroid Build Coastguard Worker
readBool()101*8975f5c5SAndroid Build Coastguard Worker bool readBool()
102*8975f5c5SAndroid Build Coastguard Worker {
103*8975f5c5SAndroid Build Coastguard Worker int value = 0;
104*8975f5c5SAndroid Build Coastguard Worker read(&value);
105*8975f5c5SAndroid Build Coastguard Worker return (value > 0);
106*8975f5c5SAndroid Build Coastguard Worker }
107*8975f5c5SAndroid Build Coastguard Worker
readBool(bool * outValue)108*8975f5c5SAndroid Build Coastguard Worker void readBool(bool *outValue) { *outValue = readBool(); }
109*8975f5c5SAndroid Build Coastguard Worker
readBytes(unsigned char outArray[],size_t count)110*8975f5c5SAndroid Build Coastguard Worker void readBytes(unsigned char outArray[], size_t count) { read<unsigned char>(outArray, count); }
getBytes(size_t count)111*8975f5c5SAndroid Build Coastguard Worker const unsigned char *getBytes(size_t count) { return read<unsigned char>(nullptr, count); }
112*8975f5c5SAndroid Build Coastguard Worker
readString()113*8975f5c5SAndroid Build Coastguard Worker std::string readString()
114*8975f5c5SAndroid Build Coastguard Worker {
115*8975f5c5SAndroid Build Coastguard Worker std::string outString;
116*8975f5c5SAndroid Build Coastguard Worker readString(&outString);
117*8975f5c5SAndroid Build Coastguard Worker return outString;
118*8975f5c5SAndroid Build Coastguard Worker }
119*8975f5c5SAndroid Build Coastguard Worker
readString(std::string * v)120*8975f5c5SAndroid Build Coastguard Worker void readString(std::string *v)
121*8975f5c5SAndroid Build Coastguard Worker {
122*8975f5c5SAndroid Build Coastguard Worker size_t length;
123*8975f5c5SAndroid Build Coastguard Worker readInt(&length);
124*8975f5c5SAndroid Build Coastguard Worker
125*8975f5c5SAndroid Build Coastguard Worker if (mError)
126*8975f5c5SAndroid Build Coastguard Worker {
127*8975f5c5SAndroid Build Coastguard Worker return;
128*8975f5c5SAndroid Build Coastguard Worker }
129*8975f5c5SAndroid Build Coastguard Worker
130*8975f5c5SAndroid Build Coastguard Worker angle::CheckedNumeric<size_t> checkedOffset(mOffset);
131*8975f5c5SAndroid Build Coastguard Worker checkedOffset += length;
132*8975f5c5SAndroid Build Coastguard Worker
133*8975f5c5SAndroid Build Coastguard Worker if (!checkedOffset.IsValid() || mOffset + length > mLength)
134*8975f5c5SAndroid Build Coastguard Worker {
135*8975f5c5SAndroid Build Coastguard Worker mError = true;
136*8975f5c5SAndroid Build Coastguard Worker return;
137*8975f5c5SAndroid Build Coastguard Worker }
138*8975f5c5SAndroid Build Coastguard Worker
139*8975f5c5SAndroid Build Coastguard Worker v->assign(reinterpret_cast<const char *>(mData) + mOffset, length);
140*8975f5c5SAndroid Build Coastguard Worker mOffset = checkedOffset.ValueOrDie();
141*8975f5c5SAndroid Build Coastguard Worker }
142*8975f5c5SAndroid Build Coastguard Worker
readFloat()143*8975f5c5SAndroid Build Coastguard Worker float readFloat()
144*8975f5c5SAndroid Build Coastguard Worker {
145*8975f5c5SAndroid Build Coastguard Worker float f;
146*8975f5c5SAndroid Build Coastguard Worker read(&f, 1);
147*8975f5c5SAndroid Build Coastguard Worker return f;
148*8975f5c5SAndroid Build Coastguard Worker }
149*8975f5c5SAndroid Build Coastguard Worker
skip(size_t length)150*8975f5c5SAndroid Build Coastguard Worker void skip(size_t length)
151*8975f5c5SAndroid Build Coastguard Worker {
152*8975f5c5SAndroid Build Coastguard Worker angle::CheckedNumeric<size_t> checkedOffset(mOffset);
153*8975f5c5SAndroid Build Coastguard Worker checkedOffset += length;
154*8975f5c5SAndroid Build Coastguard Worker
155*8975f5c5SAndroid Build Coastguard Worker if (!checkedOffset.IsValid() || mOffset + length > mLength)
156*8975f5c5SAndroid Build Coastguard Worker {
157*8975f5c5SAndroid Build Coastguard Worker mError = true;
158*8975f5c5SAndroid Build Coastguard Worker return;
159*8975f5c5SAndroid Build Coastguard Worker }
160*8975f5c5SAndroid Build Coastguard Worker
161*8975f5c5SAndroid Build Coastguard Worker mOffset = checkedOffset.ValueOrDie();
162*8975f5c5SAndroid Build Coastguard Worker }
163*8975f5c5SAndroid Build Coastguard Worker
offset()164*8975f5c5SAndroid Build Coastguard Worker size_t offset() const { return mOffset; }
remainingSize()165*8975f5c5SAndroid Build Coastguard Worker size_t remainingSize() const
166*8975f5c5SAndroid Build Coastguard Worker {
167*8975f5c5SAndroid Build Coastguard Worker ASSERT(mLength >= mOffset);
168*8975f5c5SAndroid Build Coastguard Worker return mLength - mOffset;
169*8975f5c5SAndroid Build Coastguard Worker }
170*8975f5c5SAndroid Build Coastguard Worker
error()171*8975f5c5SAndroid Build Coastguard Worker bool error() const { return mError; }
172*8975f5c5SAndroid Build Coastguard Worker
endOfStream()173*8975f5c5SAndroid Build Coastguard Worker bool endOfStream() const { return mOffset == mLength; }
174*8975f5c5SAndroid Build Coastguard Worker
data()175*8975f5c5SAndroid Build Coastguard Worker const uint8_t *data() { return mData; }
176*8975f5c5SAndroid Build Coastguard Worker
177*8975f5c5SAndroid Build Coastguard Worker private:
178*8975f5c5SAndroid Build Coastguard Worker bool mError;
179*8975f5c5SAndroid Build Coastguard Worker size_t mOffset;
180*8975f5c5SAndroid Build Coastguard Worker const uint8_t *mData;
181*8975f5c5SAndroid Build Coastguard Worker size_t mLength;
182*8975f5c5SAndroid Build Coastguard Worker
183*8975f5c5SAndroid Build Coastguard Worker template <typename T>
read(T * v,size_t num)184*8975f5c5SAndroid Build Coastguard Worker const uint8_t *read(T *v, size_t num)
185*8975f5c5SAndroid Build Coastguard Worker {
186*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
187*8975f5c5SAndroid Build Coastguard Worker
188*8975f5c5SAndroid Build Coastguard Worker angle::CheckedNumeric<size_t> checkedLength(num);
189*8975f5c5SAndroid Build Coastguard Worker checkedLength *= sizeof(T);
190*8975f5c5SAndroid Build Coastguard Worker if (!checkedLength.IsValid())
191*8975f5c5SAndroid Build Coastguard Worker {
192*8975f5c5SAndroid Build Coastguard Worker mError = true;
193*8975f5c5SAndroid Build Coastguard Worker return nullptr;
194*8975f5c5SAndroid Build Coastguard Worker }
195*8975f5c5SAndroid Build Coastguard Worker
196*8975f5c5SAndroid Build Coastguard Worker angle::CheckedNumeric<size_t> checkedOffset(mOffset);
197*8975f5c5SAndroid Build Coastguard Worker checkedOffset += checkedLength;
198*8975f5c5SAndroid Build Coastguard Worker
199*8975f5c5SAndroid Build Coastguard Worker if (!checkedOffset.IsValid() || checkedOffset.ValueOrDie() > mLength)
200*8975f5c5SAndroid Build Coastguard Worker {
201*8975f5c5SAndroid Build Coastguard Worker mError = true;
202*8975f5c5SAndroid Build Coastguard Worker return nullptr;
203*8975f5c5SAndroid Build Coastguard Worker }
204*8975f5c5SAndroid Build Coastguard Worker
205*8975f5c5SAndroid Build Coastguard Worker const uint8_t *srcBytes = mData + mOffset;
206*8975f5c5SAndroid Build Coastguard Worker if (v != nullptr)
207*8975f5c5SAndroid Build Coastguard Worker {
208*8975f5c5SAndroid Build Coastguard Worker memcpy(v, srcBytes, checkedLength.ValueOrDie());
209*8975f5c5SAndroid Build Coastguard Worker }
210*8975f5c5SAndroid Build Coastguard Worker mOffset = checkedOffset.ValueOrDie();
211*8975f5c5SAndroid Build Coastguard Worker
212*8975f5c5SAndroid Build Coastguard Worker return srcBytes;
213*8975f5c5SAndroid Build Coastguard Worker }
214*8975f5c5SAndroid Build Coastguard Worker
215*8975f5c5SAndroid Build Coastguard Worker template <typename T>
read(T * v)216*8975f5c5SAndroid Build Coastguard Worker void read(T *v)
217*8975f5c5SAndroid Build Coastguard Worker {
218*8975f5c5SAndroid Build Coastguard Worker read(v, 1);
219*8975f5c5SAndroid Build Coastguard Worker }
220*8975f5c5SAndroid Build Coastguard Worker };
221*8975f5c5SAndroid Build Coastguard Worker
222*8975f5c5SAndroid Build Coastguard Worker class BinaryOutputStream : angle::NonCopyable
223*8975f5c5SAndroid Build Coastguard Worker {
224*8975f5c5SAndroid Build Coastguard Worker public:
225*8975f5c5SAndroid Build Coastguard Worker BinaryOutputStream();
226*8975f5c5SAndroid Build Coastguard Worker ~BinaryOutputStream();
227*8975f5c5SAndroid Build Coastguard Worker
228*8975f5c5SAndroid Build Coastguard Worker // writeInt also handles bool types
229*8975f5c5SAndroid Build Coastguard Worker template <class IntT>
writeInt(IntT param)230*8975f5c5SAndroid Build Coastguard Worker void writeInt(IntT param)
231*8975f5c5SAndroid Build Coastguard Worker {
232*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_integral<IntT>::value, "Not an integral type");
233*8975f5c5SAndroid Build Coastguard Worker static_assert(!std::is_same<bool, std::remove_cv<IntT>()>(), "Use writeBool");
234*8975f5c5SAndroid Build Coastguard Worker using PromotedIntT = typename PromotedIntegerType<IntT>::type;
235*8975f5c5SAndroid Build Coastguard Worker ASSERT(angle::IsValueInRangeForNumericType<PromotedIntT>(param));
236*8975f5c5SAndroid Build Coastguard Worker PromotedIntT intValue = static_cast<PromotedIntT>(param);
237*8975f5c5SAndroid Build Coastguard Worker write(&intValue, 1);
238*8975f5c5SAndroid Build Coastguard Worker }
239*8975f5c5SAndroid Build Coastguard Worker
240*8975f5c5SAndroid Build Coastguard Worker // Specialized writeInt for values that can also be exactly -1.
241*8975f5c5SAndroid Build Coastguard Worker template <class UintT>
writeIntOrNegOne(UintT param)242*8975f5c5SAndroid Build Coastguard Worker void writeIntOrNegOne(UintT param)
243*8975f5c5SAndroid Build Coastguard Worker {
244*8975f5c5SAndroid Build Coastguard Worker if (param == static_cast<UintT>(-1))
245*8975f5c5SAndroid Build Coastguard Worker {
246*8975f5c5SAndroid Build Coastguard Worker writeInt(-1);
247*8975f5c5SAndroid Build Coastguard Worker }
248*8975f5c5SAndroid Build Coastguard Worker else
249*8975f5c5SAndroid Build Coastguard Worker {
250*8975f5c5SAndroid Build Coastguard Worker writeInt(param);
251*8975f5c5SAndroid Build Coastguard Worker }
252*8975f5c5SAndroid Build Coastguard Worker }
253*8975f5c5SAndroid Build Coastguard Worker
254*8975f5c5SAndroid Build Coastguard Worker template <class T>
writeVector(const std::vector<T> & param)255*8975f5c5SAndroid Build Coastguard Worker void writeVector(const std::vector<T> ¶m)
256*8975f5c5SAndroid Build Coastguard Worker {
257*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<T>(), "must be memcpy-able");
258*8975f5c5SAndroid Build Coastguard Worker writeInt(param.size());
259*8975f5c5SAndroid Build Coastguard Worker if (param.size() > 0)
260*8975f5c5SAndroid Build Coastguard Worker {
261*8975f5c5SAndroid Build Coastguard Worker writeBytes(reinterpret_cast<const uint8_t *>(param.data()), param.size() * sizeof(T));
262*8975f5c5SAndroid Build Coastguard Worker }
263*8975f5c5SAndroid Build Coastguard Worker }
264*8975f5c5SAndroid Build Coastguard Worker
265*8975f5c5SAndroid Build Coastguard Worker template <typename E, typename T>
writePackedEnumMap(const angle::PackedEnumMap<E,T> & param)266*8975f5c5SAndroid Build Coastguard Worker void writePackedEnumMap(const angle::PackedEnumMap<E, T> ¶m)
267*8975f5c5SAndroid Build Coastguard Worker {
268*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<T>(), "must be memcpy-able");
269*8975f5c5SAndroid Build Coastguard Worker writeBytes(reinterpret_cast<const uint8_t *>(param.data()), param.size() * sizeof(T));
270*8975f5c5SAndroid Build Coastguard Worker }
271*8975f5c5SAndroid Build Coastguard Worker
272*8975f5c5SAndroid Build Coastguard Worker template <class T>
writeStruct(const T & param)273*8975f5c5SAndroid Build Coastguard Worker void writeStruct(const T ¶m)
274*8975f5c5SAndroid Build Coastguard Worker {
275*8975f5c5SAndroid Build Coastguard Worker static_assert(!std::is_pointer<T>::value,
276*8975f5c5SAndroid Build Coastguard Worker "Must pass in a struct, not the pointer to struct");
277*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<T>(), "must be memcpy-able");
278*8975f5c5SAndroid Build Coastguard Worker writeBytes(reinterpret_cast<const uint8_t *>(¶m), sizeof(T));
279*8975f5c5SAndroid Build Coastguard Worker }
280*8975f5c5SAndroid Build Coastguard Worker
281*8975f5c5SAndroid Build Coastguard Worker template <class EnumT>
writeEnum(EnumT param)282*8975f5c5SAndroid Build Coastguard Worker void writeEnum(EnumT param)
283*8975f5c5SAndroid Build Coastguard Worker {
284*8975f5c5SAndroid Build Coastguard Worker using UnderlyingType = typename std::underlying_type<EnumT>::type;
285*8975f5c5SAndroid Build Coastguard Worker writeInt<UnderlyingType>(static_cast<UnderlyingType>(param));
286*8975f5c5SAndroid Build Coastguard Worker }
287*8975f5c5SAndroid Build Coastguard Worker
writeString(const std::string & v)288*8975f5c5SAndroid Build Coastguard Worker void writeString(const std::string &v)
289*8975f5c5SAndroid Build Coastguard Worker {
290*8975f5c5SAndroid Build Coastguard Worker writeInt(v.length());
291*8975f5c5SAndroid Build Coastguard Worker write(v.c_str(), v.length());
292*8975f5c5SAndroid Build Coastguard Worker }
293*8975f5c5SAndroid Build Coastguard Worker
writeString(const char * v)294*8975f5c5SAndroid Build Coastguard Worker void writeString(const char *v)
295*8975f5c5SAndroid Build Coastguard Worker {
296*8975f5c5SAndroid Build Coastguard Worker size_t len = strlen(v);
297*8975f5c5SAndroid Build Coastguard Worker writeInt(len);
298*8975f5c5SAndroid Build Coastguard Worker write(v, len);
299*8975f5c5SAndroid Build Coastguard Worker }
300*8975f5c5SAndroid Build Coastguard Worker
writeBytes(const unsigned char * bytes,size_t count)301*8975f5c5SAndroid Build Coastguard Worker void writeBytes(const unsigned char *bytes, size_t count) { write(bytes, count); }
302*8975f5c5SAndroid Build Coastguard Worker
writeBool(bool value)303*8975f5c5SAndroid Build Coastguard Worker void writeBool(bool value)
304*8975f5c5SAndroid Build Coastguard Worker {
305*8975f5c5SAndroid Build Coastguard Worker int intValue = value ? 1 : 0;
306*8975f5c5SAndroid Build Coastguard Worker write(&intValue, 1);
307*8975f5c5SAndroid Build Coastguard Worker }
308*8975f5c5SAndroid Build Coastguard Worker
writeFloat(float value)309*8975f5c5SAndroid Build Coastguard Worker void writeFloat(float value) { write(&value, 1); }
310*8975f5c5SAndroid Build Coastguard Worker
length()311*8975f5c5SAndroid Build Coastguard Worker size_t length() const { return mData.size(); }
312*8975f5c5SAndroid Build Coastguard Worker
data()313*8975f5c5SAndroid Build Coastguard Worker const void *data() const { return mData.size() ? &mData[0] : nullptr; }
314*8975f5c5SAndroid Build Coastguard Worker
getData()315*8975f5c5SAndroid Build Coastguard Worker const std::vector<uint8_t> &getData() const { return mData; }
316*8975f5c5SAndroid Build Coastguard Worker
317*8975f5c5SAndroid Build Coastguard Worker private:
318*8975f5c5SAndroid Build Coastguard Worker template <typename T>
write(const T * v,size_t num)319*8975f5c5SAndroid Build Coastguard Worker void write(const T *v, size_t num)
320*8975f5c5SAndroid Build Coastguard Worker {
321*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
322*8975f5c5SAndroid Build Coastguard Worker const char *asBytes = reinterpret_cast<const char *>(v);
323*8975f5c5SAndroid Build Coastguard Worker mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T));
324*8975f5c5SAndroid Build Coastguard Worker }
325*8975f5c5SAndroid Build Coastguard Worker
326*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> mData;
327*8975f5c5SAndroid Build Coastguard Worker };
328*8975f5c5SAndroid Build Coastguard Worker
BinaryOutputStream()329*8975f5c5SAndroid Build Coastguard Worker inline BinaryOutputStream::BinaryOutputStream() {}
330*8975f5c5SAndroid Build Coastguard Worker
331*8975f5c5SAndroid Build Coastguard Worker inline BinaryOutputStream::~BinaryOutputStream() = default;
332*8975f5c5SAndroid Build Coastguard Worker
333*8975f5c5SAndroid Build Coastguard Worker } // namespace gl
334*8975f5c5SAndroid Build Coastguard Worker
335*8975f5c5SAndroid Build Coastguard Worker #endif // COMMON_BINARYSTREAM_H_
336