1//
2// Copyright (c) 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 LIBGLESV2_BINARYSTREAM_H_
10#define LIBGLESV2_BINARYSTREAM_H_
11
12#include "common/angleutils.h"
13#include "common/mathutil.h"
14
15#include <cstddef>
16#include <string>
17#include <vector>
18
19namespace gl
20{
21
22class BinaryInputStream
23{
24  public:
25    BinaryInputStream(const void *data, size_t length)
26    {
27        mError = false;
28        mOffset = 0;
29        mData = static_cast<const char*>(data);
30        mLength = length;
31    }
32
33    // readInt will generate an error for bool types
34    template <class IntT>
35    IntT readInt()
36    {
37        int value;
38        read(&value);
39        return static_cast<IntT>(value);
40    }
41
42    template <class IntT>
43    void readInt(IntT *outValue)
44    {
45        *outValue = readInt<IntT>();
46    }
47
48    bool readBool()
49    {
50        int value;
51        read(&value);
52        return (value > 0);
53    }
54
55    void readBool(bool *outValue)
56    {
57        *outValue = readBool();
58    }
59
60    void readBytes(unsigned char outArray[], size_t count)
61    {
62        read<unsigned char>(outArray, count);
63    }
64
65    std::string readString()
66    {
67        std::string outString;
68        readString(&outString);
69        return outString;
70    }
71
72    void readString(std::string *v)
73    {
74        size_t length;
75        readInt(&length);
76
77        if (mError)
78        {
79            return;
80        }
81
82        if (mOffset + length > mLength)
83        {
84            mError = true;
85            return;
86        }
87
88        v->assign(mData + mOffset, length);
89        mOffset += length;
90    }
91
92    void skip(size_t length)
93    {
94        if (mOffset + length > mLength)
95        {
96            mError = true;
97            return;
98        }
99
100        mOffset += length;
101    }
102
103    size_t offset() const
104    {
105        return mOffset;
106    }
107
108    bool error() const
109    {
110        return mError;
111    }
112
113    bool endOfStream() const
114    {
115        return mOffset == mLength;
116    }
117
118  private:
119    DISALLOW_COPY_AND_ASSIGN(BinaryInputStream);
120    bool mError;
121    size_t mOffset;
122    const char *mData;
123    size_t mLength;
124
125    template <typename T>
126    void read(T *v, size_t num)
127    {
128        META_ASSERT(std::is_fundamental<T>::value);
129
130        size_t length = num * sizeof(T);
131
132        if (mOffset + length > mLength)
133        {
134            mError = true;
135            return;
136        }
137
138        memcpy(v, mData + mOffset, length);
139        mOffset += length;
140    }
141
142    template <typename T>
143    void read(T *v)
144    {
145        read(v, 1);
146    }
147
148};
149
150class BinaryOutputStream
151{
152  public:
153    BinaryOutputStream()
154    {
155    }
156
157    // writeInt also handles bool types
158    template <class IntT>
159    void writeInt(IntT param)
160    {
161        ASSERT(rx::IsIntegerCastSafe<int>(param));
162        int intValue = static_cast<int>(param);
163        write(&intValue, 1);
164    }
165
166    void writeString(const std::string &v)
167    {
168        writeInt(v.length());
169        write(v.c_str(), v.length());
170    }
171
172    void writeBytes(const unsigned char *bytes, size_t count)
173    {
174        write(bytes, count);
175    }
176
177    size_t length() const
178    {
179        return mData.size();
180    }
181
182    const void* data() const
183    {
184        return mData.size() ? &mData[0] : NULL;
185    }
186
187  private:
188    DISALLOW_COPY_AND_ASSIGN(BinaryOutputStream);
189    std::vector<char> mData;
190
191    template <typename T>
192    void write(const T *v, size_t num)
193    {
194        META_ASSERT(std::is_fundamental<T>::value);
195        const char *asBytes = reinterpret_cast<const char*>(v);
196        mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T));
197    }
198
199};
200}
201
202#endif  // LIBGLESV2_BINARYSTREAM_H_
203