• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2012 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // BinaryStream.h: Provides binary serialization of simple types.
8 
9 #ifndef LIBANGLE_BINARYSTREAM_H_
10 #define LIBANGLE_BINARYSTREAM_H_
11 
12 #include <stdint.h>
13 #include <cstddef>
14 #include <string>
15 #include <vector>
16 
17 #include "common/angleutils.h"
18 #include "common/mathutil.h"
19 
20 namespace gl
21 {
22 
23 class BinaryInputStream : angle::NonCopyable
24 {
25   public:
BinaryInputStream(const void * data,size_t length)26     BinaryInputStream(const void *data, size_t length)
27     {
28         mError  = false;
29         mOffset = 0;
30         mData   = static_cast<const uint8_t *>(data);
31         mLength = length;
32     }
33 
34     // readInt will generate an error for bool types
35     template <class IntT>
readInt()36     IntT readInt()
37     {
38         int value = 0;
39         read(&value);
40         return static_cast<IntT>(value);
41     }
42 
43     template <class IntT>
readInt(IntT * outValue)44     void readInt(IntT *outValue)
45     {
46         *outValue = readInt<IntT>();
47     }
48 
49     template <class IntT, class VectorElementT>
readIntVector(std::vector<VectorElementT> * param)50     void readIntVector(std::vector<VectorElementT> *param)
51     {
52         unsigned int size = readInt<unsigned int>();
53         for (unsigned int index = 0; index < size; ++index)
54         {
55             param->push_back(readInt<IntT>());
56         }
57     }
58 
59     template <class EnumT>
readEnum()60     EnumT readEnum()
61     {
62         using UnderlyingType = typename std::underlying_type<EnumT>::type;
63         return static_cast<EnumT>(readInt<UnderlyingType>());
64     }
65 
66     template <class EnumT>
readEnum(EnumT * outValue)67     void readEnum(EnumT *outValue)
68     {
69         *outValue = readEnum<EnumT>();
70     }
71 
readBool()72     bool readBool()
73     {
74         int value = 0;
75         read(&value);
76         return (value > 0);
77     }
78 
readBool(bool * outValue)79     void readBool(bool *outValue) { *outValue = readBool(); }
80 
readBytes(unsigned char outArray[],size_t count)81     void readBytes(unsigned char outArray[], size_t count) { read<unsigned char>(outArray, count); }
82 
readString()83     std::string readString()
84     {
85         std::string outString;
86         readString(&outString);
87         return outString;
88     }
89 
readString(std::string * v)90     void readString(std::string *v)
91     {
92         size_t length;
93         readInt(&length);
94 
95         if (mError)
96         {
97             return;
98         }
99 
100         angle::CheckedNumeric<size_t> checkedOffset(mOffset);
101         checkedOffset += length;
102 
103         if (!checkedOffset.IsValid() || mOffset + length > mLength)
104         {
105             mError = true;
106             return;
107         }
108 
109         v->assign(reinterpret_cast<const char *>(mData) + mOffset, length);
110         mOffset = checkedOffset.ValueOrDie();
111     }
112 
skip(size_t length)113     void skip(size_t length)
114     {
115         angle::CheckedNumeric<size_t> checkedOffset(mOffset);
116         checkedOffset += length;
117 
118         if (!checkedOffset.IsValid() || mOffset + length > mLength)
119         {
120             mError = true;
121             return;
122         }
123 
124         mOffset = checkedOffset.ValueOrDie();
125     }
126 
offset()127     size_t offset() const { return mOffset; }
remainingSize()128     size_t remainingSize() const
129     {
130         ASSERT(mLength >= mOffset);
131         return mLength - mOffset;
132     }
133 
error()134     bool error() const { return mError; }
135 
endOfStream()136     bool endOfStream() const { return mOffset == mLength; }
137 
data()138     const uint8_t *data() { return mData; }
139 
140   private:
141     bool mError;
142     size_t mOffset;
143     const uint8_t *mData;
144     size_t mLength;
145 
146     template <typename T>
read(T * v,size_t num)147     void read(T *v, size_t num)
148     {
149         static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
150 
151         angle::CheckedNumeric<size_t> checkedLength(num);
152         checkedLength *= sizeof(T);
153         if (!checkedLength.IsValid())
154         {
155             mError = true;
156             return;
157         }
158 
159         angle::CheckedNumeric<size_t> checkedOffset(mOffset);
160         checkedOffset += checkedLength;
161 
162         if (!checkedOffset.IsValid() || checkedOffset.ValueOrDie() > mLength)
163         {
164             mError = true;
165             return;
166         }
167 
168         memcpy(v, mData + mOffset, checkedLength.ValueOrDie());
169         mOffset = checkedOffset.ValueOrDie();
170     }
171 
172     template <typename T>
read(T * v)173     void read(T *v)
174     {
175         read(v, 1);
176     }
177 };
178 
179 class BinaryOutputStream : angle::NonCopyable
180 {
181   public:
182     BinaryOutputStream();
183     ~BinaryOutputStream();
184 
185     // writeInt also handles bool types
186     template <class IntT>
writeInt(IntT param)187     void writeInt(IntT param)
188     {
189         using PromotedIntT =
190             typename std::conditional<std::is_signed<IntT>::value, int, unsigned>::type;
191         ASSERT(angle::IsValueInRangeForNumericType<PromotedIntT>(param));
192         PromotedIntT intValue = static_cast<PromotedIntT>(param);
193         write(&intValue, 1);
194     }
195 
196     // Specialized writeInt for values that can also be exactly -1.
197     template <class UintT>
writeIntOrNegOne(UintT param)198     void writeIntOrNegOne(UintT param)
199     {
200         if (param == static_cast<UintT>(-1))
201         {
202             writeInt(-1);
203         }
204         else
205         {
206             writeInt(param);
207         }
208     }
209 
210     template <class IntT>
writeIntVector(const std::vector<IntT> & param)211     void writeIntVector(const std::vector<IntT> &param)
212     {
213         writeInt(param.size());
214         for (IntT element : param)
215         {
216             writeIntOrNegOne(element);
217         }
218     }
219 
220     template <class EnumT>
writeEnum(EnumT param)221     void writeEnum(EnumT param)
222     {
223         using UnderlyingType = typename std::underlying_type<EnumT>::type;
224         writeInt<UnderlyingType>(static_cast<UnderlyingType>(param));
225     }
226 
writeString(const std::string & v)227     void writeString(const std::string &v)
228     {
229         writeInt(v.length());
230         write(v.c_str(), v.length());
231     }
232 
writeBytes(const unsigned char * bytes,size_t count)233     void writeBytes(const unsigned char *bytes, size_t count) { write(bytes, count); }
234 
length()235     size_t length() const { return mData.size(); }
236 
data()237     const void *data() const { return mData.size() ? &mData[0] : nullptr; }
238 
239   private:
240     std::vector<char> mData;
241 
242     template <typename T>
write(const T * v,size_t num)243     void write(const T *v, size_t num)
244     {
245         static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
246         const char *asBytes = reinterpret_cast<const char *>(v);
247         mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T));
248     }
249 };
250 
BinaryOutputStream()251 inline BinaryOutputStream::BinaryOutputStream() {}
252 
253 inline BinaryOutputStream::~BinaryOutputStream() = default;
254 
255 }  // namespace gl
256 
257 #endif  // LIBANGLE_BINARYSTREAM_H_
258