#include #include #include #include #include #include #include "common.hh" #include "util.hh" MmapFile::MmapFile(std::string fileName) : name_(std::move(fileName)), fd_(fopen(name_.c_str(), "rb")), size_(0), base_(nullptr) { if (!fd_) throw POSIXException{errno, "Could not open " + name_}; struct stat statBuf; if (fstat(fileno(fd_.get()), &statBuf) != 0) throw POSIXException(errno, "Could not stat"); if (statBuf.st_size <= 0) throw Exception{"File size is zero or less"}; size_ = static_cast(statBuf.st_size); base_ = mmap(nullptr, size_, PROT_READ, MAP_SHARED, fileno(fd_.get()), 0); if (!base_) throw POSIXException(errno, "mmap failed"); } MmapFile::MmapFile(MmapFile && move): name_(std::move(move.name_)), fd_(std::move(move.fd_)), size_(move.size_), base_(move.base_) { move.base_ = nullptr; } MmapFile::~MmapFile() { if (base_) { if (munmap(base_, size_) != 0) fprintf(stderr, "Warning: munmap failed: %s\n", strerror(errno)); base_ = nullptr; } } MmapFile& MmapFile::operator=(MmapFile && move) { fd_ = std::move(move.fd_); if (base_) if (munmap(base_, size_) != 0) fprintf(stderr, "Warning: munmap failed: %s\n", strerror(errno)); base_ = move.base_; move.base_ = nullptr; size_ = move.size_; name_ = std::move(move.name_); return *this; } std::string const& MmapFile::name() const { if (!*this) throw std::logic_error("name() called on invalid MmapFile"); return name_; } size_t MmapFile::size() const { if (!*this) throw std::logic_error("size() called on invalid MmapFile"); return size_; } char const* MmapFile::data() const { if (!*this) throw std::logic_error("data() called on invalid MmapFile"); return static_cast(base_); } MmapFile::operator bool() const { return base_; } uint16_t readU16BE(char const* data) { if(!data) throw std::logic_error("readU16BE() called with nullptr"); uint16_t ret; #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ret = ((static_cast(*data)&0xff)<<8) | static_cast(*(data+1)); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ memcpy(&ret, data, 2); #else #error Unknown endianess #endif return ret; } uint32_t readU24BE(char const* data) { if(!data) throw std::logic_error("readU24BE() called with nullptr"); uint32_t ret = 0; #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ret = ((static_cast(*data)&0xff)<<16) | ((static_cast(*(data+1))&0xff)<<8) | static_cast(*(data+2)); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ memcpy(static_cast(&ret)+1, data, 3); #else #error Unknown endianess #endif return ret; } uint32_t readU32BE(char const* data) { if(!data) throw std::logic_error("readU32BE() called with nullptr"); uint32_t ret; #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ret = ((static_cast(*data)&0xff)<<24) | ((static_cast(*(data+1))&0xff)<<16) | ((static_cast(*(data+2))&0xff)<<8) | static_cast(*(data+3)); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ memcpy(&ret, data, 4); #else #error Unknown endianess #endif return ret; } uint16_t readU16LE(char const* data) { if(!data) throw std::logic_error("readU16LE() called with nullptr"); uint16_t ret; #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ memcpy(&ret, data, 2); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ret = ((static_cast(*(data+1))&0xff)<<8) | static_cast(*data); #else #error Unknown endianess #endif return ret; } uint32_t readU24LE(char const* data) { if(!data) throw std::logic_error("readU24LE() called with nullptr"); uint32_t ret = 0; #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ memcpy(&ret, data, 3); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ret = ((static_cast(*(data+2))&0xff)<<16) | ((static_cast(*(data+1))&0xff)<<8) | static_cast(*data); #else #error Unknown endianess #endif return ret; } uint32_t readU32LE(char const* data) { if(!data) throw std::logic_error("readU32LE() called with nullptr"); uint32_t ret; #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ memcpy(&ret, data, 4); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ret = ((static_cast(*(data+3))&0xff)<<24) | ((static_cast(*(data+2))&0xff)<<16) | ((static_cast(*(data+1))&0xff)<<8) | static_cast(*data); #else #error Unknown endianess #endif return ret; } int sextend(unsigned b, int msb) { if (msb >= sizeof(unsigned)*8) throw std::logic_error("sextend: msb out of range"); if (b&(1<<(msb-1))) { // msb is 1 return ~((1<