From e57633bbca411666d4d73ab5e34a20daa6c5e937 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Thu, 16 Jun 2022 20:22:03 -0400 Subject: [PATCH] the old Safe read/writes are gonedy now --- common/fs.cc | 62 ---------------------------------- include/common/bspfile.hh | 2 +- include/common/fs.hh | 9 ----- include/light/litfile.hh | 6 +++- include/qbsp/wad.hh | 13 +++++--- light/litfile.cc | 65 +++++++++++++++--------------------- qbsp/wad.cc | 55 +++++++++++++++--------------- vis/vis.cc | 70 +++++++++++++++++++++++---------------- 8 files changed, 112 insertions(+), 170 deletions(-) diff --git a/common/fs.cc b/common/fs.cc index bc9ee192..d7261252 100644 --- a/common/fs.cc +++ b/common/fs.cc @@ -322,65 +322,3 @@ data load(const path &p) return arch->load(filename); } } // namespace fs - -qfile_t SafeOpenWrite(const fs::path &filename) -{ - FILE *f; - -#ifdef _WIN32 - f = _wfopen(filename.c_str(), L"wb"); -#else - f = fopen(filename.string().c_str(), "wb"); -#endif - - if (!f) - FError("Error opening {}: {}", filename, strerror(errno)); - - return {f, fclose}; -} - -qfile_t SafeOpenRead(const fs::path &filename, bool must_exist) -{ - FILE *f; - -#ifdef _WIN32 - f = _wfopen(filename.c_str(), L"rb"); -#else - f = fopen(filename.string().c_str(), "rb"); -#endif - - if (!f) { - if (must_exist) - FError("Error opening {}: {}", filename, strerror(errno)); - - return {nullptr, nullptr}; - } - - return {f, fclose}; -} - -size_t SafeRead(const qfile_t &f, void *buffer, size_t count) -{ - if (fread(buffer, 1, count, f.get()) != (size_t)count) - FError("File read failure"); - - return count; -} - -size_t SafeWrite(const qfile_t &f, const void *buffer, size_t count) -{ - if (fwrite(buffer, 1, count, f.get()) != (size_t)count) - FError("File write failure"); - - return count; -} - -void SafeSeek(const qfile_t &f, long offset, int32_t origin) -{ - fseek(f.get(), offset, origin); -} - -long SafeTell(const qfile_t &f) -{ - return ftell(f.get()); -} diff --git a/include/common/bspfile.hh b/include/common/bspfile.hh index bf79eb9f..69cc1d4f 100644 --- a/include/common/bspfile.hh +++ b/include/common/bspfile.hh @@ -352,7 +352,7 @@ struct fmt::formatter } // Q1-esque BSPs are printed as, ex, 29 - return format_to(ctx.out(), "{}", v.version.value()); + return format_to(ctx.out(), "{}", v.ident); } }; diff --git a/include/common/fs.hh b/include/common/fs.hh index 79aef0fd..62b6738d 100644 --- a/include/common/fs.hh +++ b/include/common/fs.hh @@ -124,15 +124,6 @@ inline fs::path DefaultExtension(const fs::path &path, const fs::path &extension return fs::path(path).replace_extension(extension); } -using qfile_t = std::unique_ptr; - -qfile_t SafeOpenWrite(const fs::path &filename); -qfile_t SafeOpenRead(const fs::path &filename, bool must_exist = false); -size_t SafeRead(const qfile_t &f, void *buffer, size_t count); -size_t SafeWrite(const qfile_t &f, const void *buffer, size_t count); -void SafeSeek(const qfile_t &f, long offset, int32_t origin); -long SafeTell(const qfile_t &f); - #include // TODO: no wchar_t support in this version apparently diff --git a/include/light/litfile.hh b/include/light/litfile.hh index bf24323b..30130996 100644 --- a/include/light/litfile.hh +++ b/include/light/litfile.hh @@ -27,13 +27,17 @@ struct litheader_t { struct { - char ident[4]; + std::array ident = { 'Q', 'L', 'I', 'T' }; int version; + + auto stream_data() { return std::tie(ident, version); } } v1; struct { int numsurfs; int lmsamples; + + auto stream_data() { return std::tie(numsurfs, lmsamples); } } v2; }; diff --git a/include/qbsp/wad.hh b/include/qbsp/wad.hh index 1349a5fd..c9d4571c 100644 --- a/include/qbsp/wad.hh +++ b/include/qbsp/wad.hh @@ -24,22 +24,25 @@ #include #include #include +#include #include "common/cmdlib.hh" #include "common/fs.hh" // Texture data stored for quick searching struct texture_t { - char name[16]; + std::string name; int width, height; }; // WAD Format struct wadinfo_t { - char identification[4]; // should be WAD2 + std::array identification; // should be WAD2 int numlumps; int infotableofs; + + auto stream_data() { return std::tie(identification, numlumps, infotableofs); } }; struct lumpinfo_t @@ -50,7 +53,9 @@ struct lumpinfo_t char type; char compression; char pad1, pad2; - char name[16]; // must be null terminated + std::array name; // must be null terminated + + auto stream_data() { return std::tie(filepos, disksize, size, type, compression, pad1, pad2, name); } }; struct wad_t @@ -59,7 +64,7 @@ struct wad_t int version; std::unordered_map lumps; std::unordered_map textures; - qfile_t file = {nullptr, nullptr}; + std::ifstream file; }; void WADList_Init(const std::string_view &wadstring); diff --git a/light/litfile.cc b/light/litfile.cc index 47fda418..1948649b 100644 --- a/light/litfile.cc +++ b/light/litfile.cc @@ -17,6 +17,8 @@ See file, 'COPYING', for details. */ +#include + #include #include @@ -31,47 +33,38 @@ void WriteLitFile(const mbsp_t *bsp, facesup_t *facesup, const fs::path &filenam fs::path litname = filename; litname.replace_extension("lit"); - header.v1.ident[0] = 'Q'; - header.v1.ident[1] = 'L'; - header.v1.ident[2] = 'I'; - header.v1.ident[3] = 'T'; - header.v1.version = LittleLong(version); - header.v2.numsurfs = LittleLong(bsp->dfaces.size()); - header.v2.lmsamples = LittleLong(bsp->dlightdata.size()); + header.v1.version = version; + header.v2.numsurfs = bsp->dfaces.size(); + header.v2.lmsamples = bsp->dlightdata.size(); logging::print("Writing {}\n", litname); - auto litfile = SafeOpenWrite(litname); - SafeWrite(litfile, &header.v1, sizeof(header.v1)); + std::ofstream litfile(litname, std::ios_base::out | std::ios_base::binary); + litfile <= header.v1; if (version == 2) { unsigned int i, j; - unsigned int *offsets = new unsigned int[bsp->dfaces.size()]; - unsigned short *extents = new unsigned short[2 * bsp->dfaces.size()]; - unsigned char *styles = new unsigned char[4 * bsp->dfaces.size()]; - unsigned char *shifts = new unsigned char[bsp->dfaces.size()]; + litfile <= header.v2; for (i = 0; i < bsp->dfaces.size(); i++) { - offsets[i] = LittleLong(facesup[i].lightofs); - styles[i * 4 + 0] = LittleShort(facesup[i].styles[0]); - styles[i * 4 + 1] = LittleShort(facesup[i].styles[1]); - styles[i * 4 + 2] = LittleShort(facesup[i].styles[2]); - styles[i * 4 + 3] = LittleShort(facesup[i].styles[3]); - extents[i * 2 + 0] = LittleShort(facesup[i].extent[0]); - extents[i * 2 + 1] = LittleShort(facesup[i].extent[1]); + litfile <= facesup[i].lightofs; + for (int j = 0; j < 4; j++) { + litfile <= facesup[i].styles[j]; + } + for (int j = 0; j < 2; j++) { + litfile <= facesup[i].extent[j]; + } j = 0; while (nth_bit(j) < facesup[i].lmscale) j++; - shifts[i] = j; + litfile <= (uint8_t) j; } - SafeWrite(litfile, &header.v2, sizeof(header.v2)); - SafeWrite(litfile, offsets, bsp->dfaces.size() * sizeof(*offsets)); - SafeWrite(litfile, extents, 2 * bsp->dfaces.size() * sizeof(*extents)); - SafeWrite(litfile, styles, 4 * bsp->dfaces.size() * sizeof(*styles)); - SafeWrite(litfile, shifts, bsp->dfaces.size() * sizeof(*shifts)); - SafeWrite(litfile, lit_filebase, bsp->dlightdata.size() * 3); - SafeWrite(litfile, lux_filebase, bsp->dlightdata.size() * 3); - } else - SafeWrite(litfile, lit_filebase, bsp->dlightdata.size() * 3); + litfile.write((const char *) lit_filebase, bsp->dlightdata.size() * 3); + litfile.write((const char *) lux_filebase, bsp->dlightdata.size() * 3); + } + else + litfile.write((const char *) lit_filebase, bsp->dlightdata.size() * 3); } +#include + void WriteLuxFile(const mbsp_t *bsp, const fs::path &filename, int version) { litheader_t header; @@ -79,13 +72,9 @@ void WriteLuxFile(const mbsp_t *bsp, const fs::path &filename, int version) fs::path luxname = filename; luxname.replace_extension("lux"); - header.v1.ident[0] = 'Q'; - header.v1.ident[1] = 'L'; - header.v1.ident[2] = 'I'; - header.v1.ident[3] = 'T'; - header.v1.version = LittleLong(version); + header.v1.version = version; - auto luxfile = SafeOpenWrite(luxname); - SafeWrite(luxfile, &header.v1, sizeof(header.v1)); - SafeWrite(luxfile, lux_filebase, bsp->dlightdata.size() * 3); + std::ofstream luxfile(luxname, std::ios_base::out | std::ios_base::binary); + luxfile <= header.v1; + luxfile.write((const char *) lux_filebase, bsp->dlightdata.size() * 3); } diff --git a/qbsp/wad.cc b/qbsp/wad.cc index 5c784756..0d1e641b 100644 --- a/qbsp/wad.cc +++ b/qbsp/wad.cc @@ -59,43 +59,47 @@ uint8_t thepalette[768] = // Quake palette static bool WAD_LoadInfo(wad_t &wad, bool external) { - wadinfo_t *hdr = &wad.header; - int i, len; + wadinfo_t &hdr = wad.header; + int i; dmiptex_t miptex; external |= options.notextures.value(); - len = SafeRead(wad.file, hdr, sizeof(wadinfo_t)); - if (len != sizeof(wadinfo_t)) + wad.file >= hdr; + + if (wad.file.bad()) return false; wad.version = 0; - if (!strncmp(hdr->identification, "WAD2", 4)) + if (!strncmp(hdr.identification.data(), "WAD2", 4)) wad.version = 2; - else if (!strncmp(hdr->identification, "WAD3", 4)) + else if (!strncmp(hdr.identification.data(), "WAD3", 4)) wad.version = 3; if (!wad.version) return false; - SafeSeek(wad.file, hdr->infotableofs, SEEK_SET); + wad.file.seekg(hdr.infotableofs, std::ios_base::beg); wad.lumps.reserve(wad.header.numlumps); /* Get the dimensions and make a texture_t */ for (i = 0; i < wad.header.numlumps; i++) { lumpinfo_t lump; + wad.file >= lump; - len = SafeRead(wad.file, &lump, sizeof(lump)); - if (len != sizeof(lump)) + if (wad.file.bad()) return false; - auto restore_pos = SafeTell(wad.file); + std::streampos restore_pos = wad.file.tellg(); + wad.file.seekg(lump.filepos, std::ios_base::beg); + wad.file >= miptex; + miptex.name[15] = '\0'; // just in case we encounter a bad name - SafeSeek(wad.file, lump.filepos, SEEK_SET); - len = SafeRead(wad.file, &miptex, sizeof(miptex)); - - if (len == sizeof(miptex)) { - int w = LittleLong(miptex.width); - int h = LittleLong(miptex.height); + if (wad.file.bad()) { + lump.size = 0; + wad.lumps.insert({lump.name.data(), lump}); + } else { + int w = miptex.width; + int h = miptex.height; lump.size = sizeof(miptex) + (w >> 0) * (h >> 0) + (w >> 1) * (h >> 1) + (w >> 2) * (h >> 2) + (w >> 3) * (h >> 3); if (options.target_game->id == GAME_HALF_LIFE) @@ -103,8 +107,7 @@ static bool WAD_LoadInfo(wad_t &wad, bool external) lump.size = (lump.size + 3) & ~3; // keep things aligned if we can. texture_t tex; - memcpy(tex.name, miptex.name.data(), 16); - tex.name[15] = '\0'; + tex.name = miptex.name.data(); tex.width = miptex.width; tex.height = miptex.height; wad.textures.insert({tex.name, tex}); @@ -115,12 +118,9 @@ static bool WAD_LoadInfo(wad_t &wad, bool external) // fmt::print("Created texture_t {} {} {}\n", tex->name, tex->width, tex->height); wad.lumps.insert({tex.name, lump}); - } else { - lump.size = 0; - wad.lumps.insert({lump.name, lump}); } - SafeSeek(wad.file, restore_pos, SEEK_SET); + wad.file.seekg(restore_pos, std::ios_base::beg); } return true; @@ -130,7 +130,7 @@ static void WADList_OpenWad(const fs::path &fpath, bool external) { wad_t wad; - wad.file = SafeOpenRead(fpath); + wad.file.open(fpath, std::ios_base::in | std::ios_base::binary); if (wad.file) { if (options.fVerbose) @@ -142,7 +142,7 @@ static void WADList_OpenWad(const fs::path &fpath, bool external) } logging::print("WARNING: {} isn't a wadfile\n", fpath); - wad.file.reset(); + wad.file.close(); } else { // Message? } @@ -196,7 +196,7 @@ static const lumpinfo_t *WADList_FindTexture(const std::string &name) return NULL; } -static bool WAD_LoadLump(const wad_t &wad, const char *name, miptexhl_t &dest) +static bool WAD_LoadLump(wad_t &wad, const char *name, miptexhl_t &dest) { auto it = wad.lumps.find(name); @@ -207,7 +207,7 @@ static bool WAD_LoadLump(const wad_t &wad, const char *name, miptexhl_t &dest) auto &lump = it->second; - SafeSeek(wad.file, lump.filepos, SEEK_SET); + wad.file.seekg(lump.filepos, std::ios_base::beg); if (lump.disksize < sizeof(dmiptex_t)) { logging::print("Wad texture {} is invalid", name); @@ -215,7 +215,8 @@ static bool WAD_LoadLump(const wad_t &wad, const char *name, miptexhl_t &dest) } std::unique_ptr buffer = std::make_unique(lump.disksize); - size_t size = SafeRead(wad.file, buffer.get(), lump.disksize); + wad.file.read((char *) buffer.get(), lump.disksize); + size_t size = wad.file.gcount(); if (size != lump.disksize) FError("Failure reading from file"); diff --git a/vis/vis.cc b/vis/vis.cc index efb92ba4..8ae2e91a 100644 --- a/vis/vis.cc +++ b/vis/vis.cc @@ -598,6 +598,8 @@ void CalcVis(mbsp_t *bsp) // =========================================================================== +#include + /* ============ LoadPortals @@ -605,26 +607,28 @@ void CalcVis(mbsp_t *bsp) */ static void LoadPortals(const fs::path &name, mbsp_t *bsp) { - int i, j, count; + int i, j; portal_t *p; leaf_t *l; - char magic[80]; + std::string magic; int numpoints; int leafnums[2]; qplane3d plane; - qfile_t f = SafeOpenRead(name, true); + std::ifstream f(name); /* * Parse the portal file header */ - count = fscanf(f.get(), "%79s\n", magic); - if (count != 1) - FError("unknown header: {}\n", magic); + std::getline(f, magic); + if (magic.empty()) { + FError("unknown header/empty portal file {}\n", name); + } - if (!strcmp(magic, PORTALFILE)) { - count = fscanf(f.get(), "%i\n%i\n", &portalleafs, &numportals); - if (count != 2) - FError("unable to parse {} HEADER\n", PORTALFILE); + if (magic == PORTALFILE) { + f >> portalleafs >> numportals; + + if (f.bad()) + FError("unable to parse {} header\n", PORTALFILE); if (bsp->loadversion->game->id == GAME_QUAKE_II) { // since q2bsp has native cluster support, we shouldn't look at portalleafs_real at all. @@ -636,23 +640,25 @@ static void LoadPortals(const fs::path &name, mbsp_t *bsp) logging::print("{:6} leafs\n", portalleafs); logging::print("{:6} portals\n", numportals); } - } else if (!strcmp(magic, PORTALFILE2)) { - count = fscanf(f.get(), "%i\n%i\n%i\n", &portalleafs_real, &portalleafs, &numportals); - if (count != 3) - FError("unable to parse {} HEADER\n", PORTALFILE); + } else if (magic == PORTALFILE2) { if (bsp->loadversion->game->id == GAME_QUAKE_II) { FError("{} can not be used with Q2\n", PORTALFILE2); } + f >> portalleafs_real >> portalleafs >> numportals; + + if (f.bad()) + FError("unable to parse {} header\n", PORTALFILE); logging::print("{:6} leafs\n", portalleafs_real); logging::print("{:6} clusters\n", portalleafs); logging::print("{:6} portals\n", numportals); - } else if (!strcmp(magic, PORTALFILEAM)) { - count = fscanf(f.get(), "%i\n%i\n%i\n", &portalleafs, &numportals, &portalleafs_real); - if (count != 3) - FError("unable to parse {} HEADER\n", PORTALFILE); + } else if (magic == PORTALFILEAM) { if (bsp->loadversion->game->id == GAME_QUAKE_II) { FError("{} can not be used with Q2\n", PORTALFILEAM); } + f >> portalleafs >> numportals >> portalleafs_real; + + if (f.bad()) + FError("unable to parse {} header\n", PORTALFILE); logging::print("{:6} leafs\n", portalleafs_real); logging::print("{:6} clusters\n", portalleafs); logging::print("{:6} portals\n", numportals); @@ -688,7 +694,8 @@ static void LoadPortals(const fs::path &name, mbsp_t *bsp) vismap_end = vismap + bsp->dvis.bits.size(); for (i = 0, p = portals; i < numportals; i++) { - if (fscanf(f.get(), "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3) + f >> numpoints >> leafnums[0] >> leafnums[1]; + if (f.bad()) FError("reading portal {}", i); if (numpoints > MAX_WINDING) FError("portal {} has too many points", i); @@ -698,10 +705,17 @@ static void LoadPortals(const fs::path &name, mbsp_t *bsp) winding_t &w = *(p->winding = std::make_shared(numpoints)); for (j = 0; j < numpoints; j++) { - if (fscanf(f.get(), "(%lf %lf %lf ) ", &w[j][0], &w[j][1], &w[j][2]) != 3) + while (!f.bad() && f.get() != '(') + ; + + f >> w[j][0] >> w[j][1] >> w[j][2]; + + while (!f.bad() && f.get() != ')') + ; + + if (f.bad()) FError("reading portal {}", i); } - fscanf(f.get(), "\n"); // calc plane plane = w.plane(); @@ -752,12 +766,12 @@ static void LoadPortals(const fs::path &name, mbsp_t *bsp) return; } - if (!strcmp(magic, PORTALFILE2)) { + if (magic == PORTALFILE2) { for (i = 0; i < portalleafs; i++) { while (1) { int leafnum; - count = fscanf(f.get(), "%i", &leafnum); - if (!count || count == EOF) + f >> leafnum; + if (f.bad() || f.eof()) break; if (leafnum < 0) break; @@ -765,16 +779,16 @@ static void LoadPortals(const fs::path &name, mbsp_t *bsp) FError("Invalid leaf number in cluster map ({} >= {})", leafnum, portalleafs_real); bsp->dleafs[leafnum + 1].cluster = i; } - if (count == EOF) + if (f.bad() || f.eof()) break; } if (i < portalleafs) FError("Couldn't read cluster map ({} / {})\n", i, portalleafs); - } else if (!strcmp(magic, PORTALFILEAM)) { + } else if (magic == PORTALFILEAM) { for (i = 0; i < portalleafs_real; i++) { int clusternum; - count = fscanf(f.get(), "%i", &clusternum); - if (!count || count == EOF) { + f >> clusternum; + if (f.bad() || f.eof()) { Error("Unexpected end of cluster map\n"); } if (clusternum < 0 || clusternum >= portalleafs) {