tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

BinaryStream.h (7139B)


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