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