/* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #ifndef DATA_READER_H #define DATA_READER_H #include #include "Types.h" class DataReader { public: DataReader() : fData(NULL), fSize(0), fInitialSize(0), fAddressSize(4), fIsBigEndian(false), fOverflow(false) { } DataReader(const void* data, off_t size, uint8 addressSize, bool isBigEndian) { SetTo(data, size, addressSize, isBigEndian); } void SetTo(const void* data, off_t size, uint8 addressSize, bool isBigEndian) { fData = (const uint8*)data; fInitialSize = fSize = size; fAddressSize = addressSize; fIsBigEndian = isBigEndian; fOverflow = false; } DataReader RestrictedReader() { return *this; } DataReader RestrictedReader(off_t maxLength) { return DataReader(fData, maxLength, fAddressSize, fIsBigEndian); } DataReader RestrictedReader(off_t relativeOffset, off_t maxLength) { return DataReader(fData + relativeOffset, maxLength, fAddressSize, fIsBigEndian); } bool HasData() const { return fSize > 0; } uint32 AddressSize() const { return fAddressSize; } bool IsBigEndian() const { return fIsBigEndian; } void SetAddressSize(uint8 addressSize) { fAddressSize = addressSize; } bool HasOverflow() const { return fOverflow; } const void* Data() const { return fData; } off_t BytesRemaining() const { return fSize; } off_t Offset() const { return fInitialSize - fSize; } void SeekAbsolute(off_t offset) { if (offset < 0) offset = 0; else if (offset > fInitialSize) offset = fInitialSize; fData += offset - Offset(); fSize = fInitialSize - offset; } //TODO: take care of host vs target endianness template Type Read(const Type& defaultValue) { if (fSize < (off_t)sizeof(Type)) { fOverflow = true; fSize = 0; return defaultValue; } Type data; memcpy(&data, fData, sizeof(Type)); fData += sizeof(Type); fSize -= sizeof(Type); return data; } target_addr_t ReadAddress(target_addr_t defaultValue) { return fAddressSize == 4 ? (target_addr_t)Read(defaultValue) : (target_addr_t)Read(defaultValue); } uint64 ReadUnsignedLEB128(uint64 defaultValue) { uint64 result = 0; int shift = 0; while (true) { uint8 byte = Read(0); result |= uint64(byte & 0x7f) << shift; if ((byte & 0x80) == 0) break; shift += 7; } return fOverflow ? defaultValue : result; } int64 ReadSignedLEB128(int64 defaultValue) { int64 result = 0; int shift = 0; while (true) { uint8 byte = Read(0); result |= uint64(byte & 0x7f) << shift; shift += 7; if ((byte & 0x80) == 0) { // sign extend if ((byte & 0x40) != 0 && shift < 64) result |= -((uint64)1 << shift); break; } } return fOverflow ? defaultValue : result; } uint64 ReadUInt(size_t numBytes, uint64 defaultValue) { uint64 result = 0; if (fIsBigEndian) { for (size_t i = 0; i < numBytes; i++) { uint8 byte = Read(0); result <<= 8; result |= (uint64)byte; } } else { int shift = 0; for (size_t i = 0; i < numBytes; i++) { uint8 byte = Read(0); result |= (uint64)byte << shift; shift += 8; } } return fOverflow ? defaultValue : result; } uint32 ReadU24(uint32 defaultValue) { return ReadUInt(3, defaultValue); } const char* ReadString() { const char* string = (const char*)fData; while (fSize > 0) { fData++; fSize--; if (fData[-1] == 0) return string; } fOverflow = true; return NULL; } uint64 ReadInitialLength(bool& _dwarf64) { uint64 length = Read(0); _dwarf64 = (length == 0xffffffff); if (_dwarf64) length = Read(0); return length; } bool Skip(off_t bytes) { if (bytes < 0) return false; if (bytes > fSize) { fSize = 0; fOverflow = true; return false; } fData += bytes; fSize -= bytes; return true; } private: const uint8* fData; off_t fSize; off_t fInitialSize; uint8 fAddressSize; bool fIsBigEndian; bool fOverflow; }; #endif // DATA_READER_H