#include #include #include #include #include #include #include #include std::string rez::ball::toupper(const std::string &s) const { std::string ret; // Assume ASCII encoding. for (const auto &c: s) ret += std::toupper(c); return ret; } std::unique_ptr rez::ball::open(const char *path) { std::istringstream stream(path); std::string token; const rez::dir *dir = &root_dir; const rez::resource *resource = nullptr; while (std::getline(stream, token, '/')) { std::string uctoken = toupper(token); const auto &map = dir->entries(); auto it = map.find(uctoken); if (it == map.end()) return nullptr; const rez::dir::direntry &de = it->second; if (std::holds_alternative(de)) dir = &std::get(de); else if (std::holds_alternative(de)) { dir = nullptr; resource = &std::get(de); } } if (dir) { std::cerr << path << " is a directory\n"; return nullptr; } else if (!resource) { std::cerr << io.path() << ": could not find " << path << '\n'; return nullptr; } return std::make_unique(*resource, io); } int rez::ball::parse() { static const char title[63] = "\r\nRezMgr Version 1 Copyright (C) 1995 MONOLITH INC. ", subtitle[65] = "\r\nLithTech Resource File \r\n"; if (io.open()) return -1; else if (io.check(title)) { std::cerr << path << ": wrong title\n"; return -1; } else if (io.check(subtitle)) { std::cerr << path << ": wrong subtitle\n"; return -1; } else if (io.check(0x1a)) { std::cerr << path << ": wrong EOF\n"; return -1; } struct { uint32_t w[N_WORDS]; uint8_t is_sorted; } header; for (auto &w : header.w) if (io.read_le(w)) return -1; if (header.w[FILE_FORMAT_VERSION] != 1) { std::cerr << path << ": expected file format version 1, got " << header.w[FILE_FORMAT_VERSION] << '\n'; return -1; } else if (io.read(header.is_sorted)) { std::cerr << path << ": could not read sorted flag" << '\n'; return -1; } struct rez::entry::cfg cfg = {0}; cfg.size = header.w[ROOT_DIR_SIZE]; cfg.offset = header.w[ROOT_DIR_POS]; cfg.maxcomlen = header.w[MAX_COMMENT_SIZE]; cfg.maxdirlen = header.w[MAX_DIR_NAME_SIZE]; cfg.maxreslen = header.w[MAX_REZ_NAME_SIZE]; root_dir.read(cfg, io, 0); return 0; } rez::ball::ball(const char *path) : path(path), io(path) { }