void Wad::loadEntries() { if (WadLayout::NumEntriesAddress + sizeof(int32_t) >= m_file->size() || WadLayout::DirOffsetAddress + sizeof(int32_t) >= m_file->size()) throw AssetException("Invalid wad layout"); const char* cursor = m_file->begin() + WadLayout::NumEntriesAddress; const size_t entryCount = readSize<int32_t>(cursor); cursor = m_file->begin() + WadLayout::DirOffsetAddress; const size_t directoryAddr = readSize<int32_t>(cursor); if (directoryAddr >= m_file->size()) throw AssetException("Wad directory beyond end of file"); char entryType; char entryName[WadLayout::DirEntryNameSize]; cursor = m_file->begin() + directoryAddr; for (size_t i = 0; i < entryCount; i++) { size_t entryAddress = readSize<int32_t>(cursor); size_t entrySize = readSize<int32_t>(cursor); if (entryAddress + entrySize > m_file->size()) throw AssetException("Wad entry beyond end of file"); cursor += WadLayout::DirEntryTypeOffset; readBytes(cursor, &entryType, 1); cursor += WadLayout::DirEntryNameOffset; readBytes(cursor, entryName, WadLayout::DirEntryNameSize); // might leak if there are duplicate entries m_entries.push_back(WadEntry(entryName, entryType, entryAddress, entrySize)); } }
Wad::Wad(const String& path) throw (IOException) : m_stream(path.c_str(), std::ios::binary | std::ios::in) { if (!m_stream.is_open()) throw IOException::openError(); if (!m_stream.good()) throw IOException::badStream(m_stream); m_stream.exceptions(std::ios::goodbit); m_stream.seekg(0, std::ios::end); m_stream.clear(); m_length = static_cast<size_t>(m_stream.tellg()); m_stream.seekg(0, std::ios::beg); if (WadLayout::NumEntriesAddress >= m_length || WadLayout::DirOffsetAddress >= m_length) throw IOException("Invalid wad layout"); m_stream.seekg(WadLayout::NumEntriesAddress, std::ios::beg); unsigned int entryCount = IO::readUnsignedInt<int32_t>(m_stream); m_stream.seekg(WadLayout::DirOffsetAddress, std::ios::beg); unsigned int directoryAddr = IO::readUnsignedInt<int32_t>(m_stream); if (directoryAddr >= m_length) throw IOException("Wad directory beyond end of file"); char entryType; char entryName[WadLayout::DirEntryNameLength]; m_stream.seekg(directoryAddr, std::ios::beg); for (unsigned int i = 0; i < entryCount; i++) { if (m_stream.eof()) throw IOException::unexpectedEof(); unsigned int entryAddress = IO::readUnsignedInt<int32_t>(m_stream); unsigned int entryLength = IO::readUnsignedInt<int32_t>(m_stream); if (entryAddress + entryLength > m_length) throw IOException("Wad entry beyond end of file"); m_stream.seekg(WadLayout::DirEntryTypeOffset, std::ios::cur); m_stream.read(&entryType, 1); m_stream.seekg(WadLayout::DirEntryNameOffset, std::ios::cur); m_stream.read(reinterpret_cast<char *>(entryName), WadLayout::DirEntryNameLength); // might leak if there are duplicate entries m_entries[entryName] = WadEntry(entryAddress, entryLength, entryType, entryName); } m_stream.clear(); }
Wad::Wad(const String& path) throw (IOException) { FileManager fileManager; m_file = fileManager.mapFile(path); if (m_file.get() == NULL) throw IOException::openError(); if (WadLayout::NumEntriesAddress + sizeof(int32_t) >= m_file->size() || WadLayout::DirOffsetAddress + sizeof(int32_t) >= m_file->size()) throw IOException("Invalid wad layout"); char* cursor = m_file->begin() + WadLayout::NumEntriesAddress; unsigned int entryCount = readUnsignedInt<int32_t>(cursor); cursor = m_file->begin() + WadLayout::DirOffsetAddress; unsigned int directoryAddr = readUnsignedInt<int32_t>(cursor); if (directoryAddr >= m_file->size()) throw IOException("Wad directory beyond end of file"); char entryType; char entryName[WadLayout::DirEntryNameLength]; cursor = m_file->begin() + directoryAddr; for (unsigned int i = 0; i < entryCount; i++) { unsigned int entryAddress = readUnsignedInt<int32_t>(cursor); unsigned int entryLength = readUnsignedInt<int32_t>(cursor); if (entryAddress + entryLength >= m_file->size()) throw IOException("Wad entry beyond end of file"); cursor += WadLayout::DirEntryTypeOffset; readBytes(cursor, &entryType, 1); cursor += WadLayout::DirEntryNameOffset; readBytes(cursor, entryName, WadLayout::DirEntryNameLength); // might leak if there are duplicate entries m_entries[entryName] = WadEntry(entryAddress, entryLength, entryType, entryName); } }