#pragma once #include "../CommonDef.h" #include "MetadataUtil.h" namespace hybridclr { namespace metadata { class BlobReader { public: BlobReader(const byte* buf, uint32_t length) : _buf(buf), _length(length), _readPos(0) { } const byte* GetData() const { return _buf; } uint32_t GetLength() const { return _length; } uint32_t GetReadPosition() const { return _readPos; } const byte* GetDataOfReadPosition() const { return _buf + _readPos; } bool IsEmpty() const { return _readPos >= _length; } bool NonEmpty() const { return _readPos < _length; } int32_t ReadCompressedInt32() { uint32_t unsignedValue = ReadCompressedUint32(); uint32_t value = unsignedValue >> 1; if (!(unsignedValue & 0x1)) { return value; } if (value < 0x40) { return value - 0x40; } if (value < 0x2000) { return value - 0x2000; } if (value < 0x10000000) { return value - 0x10000000; } IL2CPP_ASSERT(value < 0x20000000); return value - 0x20000000; } static uint32_t ReadCompressedUint32(const byte* buf, uint32_t& lengthSize) { uint32_t firstByte = buf[0]; if (firstByte < 128) { lengthSize = 1; return firstByte; } else if (firstByte < 192) { lengthSize = 2; return ((firstByte & 0x3f) << 8) | buf[1]; } else if (firstByte < 224) { lengthSize = 4; return ((firstByte & 0x1f) << 24) | (((uint32_t)buf[1]) << 16) | ((uint32_t)buf[2] << 8) | (uint32_t)buf[3]; } else { RaiseExecutionEngineException("bad metadata data. ReadEncodeLength fail"); return 0; } } uint32_t ReadCompressedUint32() { uint32_t lengthSize; uint32_t value = ReadCompressedUint32(_buf + _readPos, lengthSize); _readPos += lengthSize; return value; } uint8_t ReadByte() { IL2CPP_ASSERT(_readPos < _length); return _buf[_readPos++]; } uint16_t Read16() { IL2CPP_ASSERT(_readPos + 2 <= _length); uint16_t value = GetU2LittleEndian(_buf + _readPos); _readPos += 2; return value; } uint32_t Read32() { IL2CPP_ASSERT(_readPos + 4 <= _length); uint32_t value = (uint32_t)GetI4LittleEndian(_buf + _readPos); _readPos += 4; return value; } bool TryRead32(uint32_t& value) { if (_readPos + 4 <= _length) { value = Read32(); return true; } return false; } uint64_t Read64() { IL2CPP_ASSERT(_readPos + 8 <= _length); uint64_t value = (uint64_t)GetI8LittleEndian(_buf + _readPos); _readPos += 8; return value; } float ReadFloat() { uint32_t x = Read32(); return *(float*)&x; } double ReadDouble() { uint64_t x = Read64(); return *(double*)&x; } //template //T Read() //{ // IL2CPP_ASSERT(_readPos + sizeof(T) <= _length); // T value = *(T*)(_buf + _readPos); // _readPos += sizeof(T); // return value; //} uint8_t PeekByte() { IL2CPP_ASSERT(_readPos < _length); return _buf[_readPos]; } void SkipByte() { IL2CPP_ASSERT(_readPos < _length); ++_readPos; } void SkipBytes(uint32_t len) { IL2CPP_ASSERT(_readPos + len <= _length); const byte* data = _buf + _readPos; _readPos += len; } const byte* GetAndSkipCurBytes(uint32_t len) { IL2CPP_ASSERT(_readPos + len <= _length); const byte* data = _buf + _readPos; _readPos += len; return data; } private: const byte* const _buf; const uint32_t _length; uint32_t _readPos; }; } }