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> ¶m) 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