#pragma once #include "BlobReader.h" #include "../CommonDef.h" #include "utils/MemoryRead.h" namespace hybridclr { namespace metadata { class CustomAttributeDataWriter { private: uint8_t* _data; uint32_t _capacity; uint32_t _size; public: CustomAttributeDataWriter(uint32_t capacity) : _capacity(Round2Exp(capacity)), _size(0) { _data = (uint8_t*)HYBRIDCLR_MALLOC_ZERO(_capacity); } ~CustomAttributeDataWriter() { HYBRIDCLR_FREE(_data); _data = nullptr; } uint32_t Size() const { return _size; } bool Empty() const { return _size == 0; } const uint8_t* Data() const { return _data; } const uint8_t* DataAt(uint32_t offset) { return _data + offset; } void Reset() { _size = 0; } void WriteAttributeCount(uint32_t count) { WriteCompressedUint32(count); } void Skip(int32_t skipBytes) { SureRemainSize(skipBytes); _size += skipBytes; } void WriteMethodIndex(int32_t offset, int32_t methodIndex) { *(int32_t*)(_data + offset) = methodIndex; } void WriteByte(uint8_t n) { SureRemainSize(1); _data[_size++] = n; } void WriteCompressedUint32(uint32_t n) { SureRemainSize(5); uint8_t* buf = _data + _size; if (n < 0x80) { buf[0] = (uint8_t)n; ++_size; } else if (n < 0x4000) { uint32_t v = n | 0x8000; buf[0] = uint8_t(v >> 8); buf[1] = uint8_t(v); _size += 2; } else if (n < 0x20000000) { uint32_t v = n | 0xC0000000; buf[0] = uint8_t(v >> 24); buf[1] = uint8_t(v >> 16); buf[2] = uint8_t(v >> 8); buf[3] = uint8_t(v); _size += 4; } else if (n < UINT32_MAX - 1) { buf[0] = 0xF0; buf[1] = uint8_t(n); buf[2] = uint8_t(n >> 8); buf[3] = uint8_t(n >> 16); buf[4] = uint8_t(n >> 24); _size += 5; } else if (n == UINT32_MAX - 1) { buf[0] = 0xFE; ++_size; } else { buf[0] = 0xFF; ++_size; } } void WriteUint32(uint32_t n) { WriteData(n); } void WriteCompressedInt32(int32_t n) { uint32_t v = n >= 0 ? (n << 1) : (((-(n + 1)) << 1) | 0x1U); WriteCompressedUint32(v); } template void WriteData(T x) { int32_t n = sizeof(T); SureRemainSize(n); std::memcpy(_data + _size, &x, n); _size += n; } void WriteBytes(const uint8_t* data, uint32_t len) { SureRemainSize(len); std::memcpy(_data + _size, data, len); _size += len; } void Write(const CustomAttributeDataWriter& writer) { SureRemainSize(writer._size); std::memcpy(_data + _size, writer._data, writer._size); _size += writer._size; } void Write(BlobReader& reader, int32_t count) { SureRemainSize(count); std::memcpy(_data + _size, reader.GetDataOfReadPosition(), count); _size += count; reader.SkipBytes(count); } void PopByte() { IL2CPP_ASSERT(_size > 0); --_size; } void ReplaceLastByte(byte x) { IL2CPP_ASSERT(_size > 0); _data[_size - 1] = x; } private: uint32_t Round2Exp(uint32_t n) { uint32_t s = 64; for (uint32_t s = 64; ; s *= 2) { if (s >= n) { return s; } } return n; } void SureRemainSize(uint32_t remainSize) { uint32_t newSize = _size + remainSize; if (newSize > _capacity) { Resize(newSize); } } void Resize(uint32_t newSize) { _capacity = newSize = Round2Exp(newSize); uint8_t* oldData = _data; _data = (uint8_t*)HYBRIDCLR_MALLOC(newSize); std::memcpy(_data, oldData, _size); HYBRIDCLR_FREE(oldData); } }; } }