xref: /aosp_15_r20/external/angle/src/common/BinaryStream.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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> &param)
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> &param)
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 &param)
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 *>(&param), 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