#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"); return ((static_cast(*data)&0xff)<<8) | static_cast(*(data+1)); } uint32_t readU24BE(char const* data) { if(!data) throw std::logic_error("readU24BE() called with nullptr"); return ((static_cast(*data)&0xff)<<16) | ((static_cast(*(data+1))&0xff)<<8) | static_cast(*(data+2)); } uint32_t readU32BE(char const* data) { if(!data) throw std::logic_error("readU32BE() called with nullptr"); return ((static_cast(*data)&0xff)<<24) | ((static_cast(*(data+1))&0xff)<<16) | ((static_cast(*(data+2))&0xff)<<8) | static_cast(*(data+3)); } uint16_t readU16LE(char const* data) { if(!data) throw std::logic_error("readU16LE() called with nullptr"); return ((static_cast(*(data+1))&0xff)<<8) | static_cast(*data); } uint32_t readU24LE(char const* data) { if(!data) throw std::logic_error("readU24LE() called with nullptr"); return ((static_cast(*(data+2))&0xff)<<16) | ((static_cast(*(data+1))&0xff)<<8) | static_cast(*data); } uint32_t readU32LE(char const* data) { if(!data) throw std::logic_error("readU32LE() called with nullptr"); return ((static_cast(*(data+3))&0xff)<<24) | ((static_cast(*(data+2))&0xff)<<16) | ((static_cast(*(data+1))&0xff)<<8) | static_cast(*data); } int sextend(unsigned b, unsigned 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< 0) { buf[p] = '\0'; ret.append(buf); } if (!std::feof(file)) { std::fclose(file); throw POSIXException(errno); } std::fclose(file); return ret; }