From bd7646346b1450ff956d48f271adff764fd463e1 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Mon, 13 Jan 2025 13:56:44 -0600 Subject: [PATCH] Use new containers and json --- src/audio/ogg.cpp | 6 +- src/audio/ogg.hpp | 10 +-- src/audio/wav.cpp | 20 +++--- src/audio/wav.hpp | 6 +- src/audio/xmp.cpp | 2 +- src/audio/xmp.hpp | 8 +-- src/audio/xmp_player.cpp | 2 + src/audio/xmp_player.hpp | 4 +- src/core/string.cpp | 27 +++++++- src/core/string.h | 4 +- src/core/thread_pool.cpp | 9 +-- src/g_demo.cpp | 13 ++-- src/g_demo.h | 17 +++-- src/g_gamedata.cpp | 57 ++++++++-------- src/g_gamedata.h | 83 ++++++++++++------------ src/hud/input-display.cpp | 4 +- src/hud/spectator.cpp | 4 +- src/hwr2/pass_resource_managers.hpp | 12 ++-- src/hwr2/patch_atlas.cpp | 4 +- src/hwr2/patch_atlas.hpp | 18 ++--- src/hwr2/postprocess_wipe.cpp | 5 +- src/hwr2/resource_management.cpp | 2 +- src/hwr2/resource_management.hpp | 14 ++-- src/hwr2/twodee_renderer.cpp | 4 +- src/io/streams.hpp | 24 +++---- src/k_bans.cpp | 81 ++++++++++++++--------- src/k_credits.cpp | 58 +++++++++-------- src/k_dialogue.cpp | 13 ++-- src/k_dialogue.hpp | 18 ++--- src/k_hud.cpp | 15 +++-- src/k_podium.cpp | 5 +- src/k_profiles.cpp | 44 +++++++------ src/k_profiles.h | 31 +++++---- src/k_waypoint.cpp | 12 ++-- src/lua_profile.cpp | 9 +-- src/m_pw.cpp | 21 +++--- src/media/avrecorder.hpp | 8 +-- src/media/avrecorder_feedback.cpp | 12 ++-- src/media/avrecorder_impl.hpp | 4 +- src/media/cfile.cpp | 2 +- src/media/cfile.hpp | 7 +- src/media/container.hpp | 4 +- src/media/options.hpp | 15 +++-- src/media/options_values.cpp | 3 +- src/media/vorbis_error.hpp | 10 +-- src/media/vpx_error.hpp | 12 ++-- src/media/webm_container.hpp | 4 +- src/media/webm_writer.hpp | 4 +- src/media/yuv420p.hpp | 4 +- src/menus/class-egg-tv/EggTV.cpp | 8 +-- src/menus/class-egg-tv/EggTV.hpp | 3 +- src/menus/class-egg-tv/EggTVData.cpp | 47 +++++++------- src/menus/class-egg-tv/EggTVData.hpp | 42 ++++++------ src/menus/class-egg-tv/EggTVGraphics.hpp | 4 +- src/menus/extras-statistics.cpp | 4 +- src/menus/main-goner.cpp | 14 ++-- src/music.cpp | 4 +- src/music_manager.cpp | 9 +-- src/music_manager.hpp | 30 +++++---- src/music_tune.hpp | 4 +- src/objects/ballhog.cpp | 2 + src/objects/checkpoint.cpp | 26 ++++---- src/p_setup.cpp | 12 ++-- src/r_debug_printer.cpp | 6 +- src/r_plane.cpp | 2 + src/r_textures_dups.cpp | 24 +++---- src/rhi/gl2/gl2_rhi.cpp | 22 +++---- src/rhi/gl2/gl2_rhi.hpp | 16 ++--- src/rhi/shader_load_context.cpp | 15 +++-- src/rhi/shader_load_context.hpp | 17 ++--- src/sanitize.cpp | 12 ++-- src/sanitize.h | 7 +- src/sdl/i_main.cpp | 10 +-- src/sdl/rhi_gl2_platform.cpp | 26 ++++---- src/sdl/rhi_gl2_platform.hpp | 6 +- src/v_draw.cpp | 25 ++++--- src/v_draw.hpp | 30 ++++----- src/y_inter.cpp | 4 +- 78 files changed, 644 insertions(+), 542 deletions(-) diff --git a/src/audio/ogg.cpp b/src/audio/ogg.cpp index 436be650b..6afaf849a 100644 --- a/src/audio/ogg.cpp +++ b/src/audio/ogg.cpp @@ -76,7 +76,7 @@ Ogg::Ogg() noexcept : memory_data_(), instance_(nullptr) { } -Ogg::Ogg(std::vector data) : memory_data_(std::move(data)), instance_(nullptr) +Ogg::Ogg(Vector data) : memory_data_(std::move(data)), instance_(nullptr) { _init_with_data(); } @@ -153,8 +153,8 @@ OggComment Ogg::comment() const stb_vorbis_comment c_comment = stb_vorbis_get_comment(instance_); return OggComment { - std::string(c_comment.vendor), - std::vector(c_comment.comment_list, c_comment.comment_list + c_comment.comment_list_length)}; + String(c_comment.vendor), + Vector(c_comment.comment_list, c_comment.comment_list + c_comment.comment_list_length)}; } std::size_t Ogg::sample_rate() const diff --git a/src/audio/ogg.hpp b/src/audio/ogg.hpp index cbee6405a..ef19a0ce0 100644 --- a/src/audio/ogg.hpp +++ b/src/audio/ogg.hpp @@ -35,19 +35,19 @@ public: struct OggComment { - std::string vendor; - std::vector comments; + String vendor; + Vector comments; }; class Ogg final { - std::vector memory_data_; + Vector memory_data_; stb_vorbis* instance_; public: Ogg() noexcept; - explicit Ogg(std::vector data); + explicit Ogg(Vector data); explicit Ogg(tcb::span data); Ogg(const Ogg&) = delete; @@ -77,7 +77,7 @@ private: template , int> = 0> inline Ogg load_ogg(I& stream) { - std::vector data = srb2::io::read_to_vec(stream); + srb2::Vector data = srb2::io::read_to_vec(stream); return Ogg {std::move(data)}; } diff --git a/src/audio/wav.cpp b/src/audio/wav.cpp index 42d1c1dea..a57eed22b 100644 --- a/src/audio/wav.cpp +++ b/src/audio/wav.cpp @@ -126,9 +126,9 @@ void visit_tag(Visitor& visitor, io::SpanStream& stream, const TagHeader& header stream.seek(io::SeekFrom::kStart, dest); } -std::vector read_uint8_samples_from_stream(io::SpanStream& stream, std::size_t count) +Vector read_uint8_samples_from_stream(io::SpanStream& stream, std::size_t count) { - std::vector samples; + Vector samples; samples.reserve(count); for (std::size_t i = 0; i < count; i++) { @@ -137,9 +137,9 @@ std::vector read_uint8_samples_from_stream(io::SpanStream& stream, std: return samples; } -std::vector read_int16_samples_from_stream(io::SpanStream& stream, std::size_t count) +Vector read_int16_samples_from_stream(io::SpanStream& stream, std::size_t count) { - std::vector samples; + Vector samples; samples.reserve(count); for (std::size_t i = 0; i < count; i++) { @@ -177,7 +177,7 @@ Wav::Wav(tcb::span data) } std::optional read_fmt; - std::variant, std::vector> interleaved_samples; + std::variant, Vector> interleaved_samples; while (stream.seek(io::SeekFrom::kCurrent, 0) < riff_end) { @@ -247,7 +247,7 @@ template std::size_t read_samples( std::size_t channels, std::size_t offset, - const std::vector& samples, + const Vector& samples, tcb::span> buffer ) noexcept { @@ -281,8 +281,8 @@ std::size_t read_samples( std::size_t Wav::get_samples(std::size_t offset, tcb::span> buffer) const noexcept { auto samples_visitor = srb2::Overload { - [&](const std::vector& samples) { return read_samples(channels(), offset, samples, buffer); }, - [&](const std::vector& samples) + [&](const Vector& samples) { return read_samples(channels(), offset, samples, buffer); }, + [&](const Vector& samples) { return read_samples(channels(), offset, samples, buffer); }}; return std::visit(samples_visitor, interleaved_samples_); @@ -291,7 +291,7 @@ std::size_t Wav::get_samples(std::size_t offset, tcb::span> buf std::size_t Wav::interleaved_length() const noexcept { auto samples_visitor = srb2::Overload { - [](const std::vector& samples) { return samples.size(); }, - [](const std::vector& samples) { return samples.size(); }}; + [](const Vector& samples) { return samples.size(); }, + [](const Vector& samples) { return samples.size(); }}; return std::visit(samples_visitor, interleaved_samples_); } diff --git a/src/audio/wav.hpp b/src/audio/wav.hpp index 8dff09f3c..fa1aec374 100644 --- a/src/audio/wav.hpp +++ b/src/audio/wav.hpp @@ -15,10 +15,10 @@ #include #include #include -#include #include +#include "../core/vector.hpp" #include "../io/streams.hpp" #include "sample.hpp" @@ -27,7 +27,7 @@ namespace srb2::audio class Wav final { - std::variant, std::vector> interleaved_samples_; + std::variant, Vector> interleaved_samples_; std::size_t channels_ = 1; std::size_t sample_rate_ = 44100; @@ -46,7 +46,7 @@ public: template , int> = 0> inline Wav load_wav(I& stream) { - std::vector data = srb2::io::read_to_vec(stream); + Vector data = srb2::io::read_to_vec(stream); return Wav {data}; } diff --git a/src/audio/xmp.cpp b/src/audio/xmp.cpp index d4e619e3e..9ed496e5f 100644 --- a/src/audio/xmp.cpp +++ b/src/audio/xmp.cpp @@ -50,7 +50,7 @@ Xmp::Xmp() : data_(), instance_(nullptr), module_loaded_(false), looping_(fal } template -Xmp::Xmp(std::vector data) +Xmp::Xmp(Vector data) : data_(std::move(data)), instance_(nullptr), module_loaded_(false), looping_(false) { _init(); diff --git a/src/audio/xmp.hpp b/src/audio/xmp.hpp index 7b34ccacd..50aba1711 100644 --- a/src/audio/xmp.hpp +++ b/src/audio/xmp.hpp @@ -15,11 +15,11 @@ #include #include #include -#include #include #include +#include "../core/vector.hpp" #include "../io/streams.hpp" namespace srb2::audio @@ -37,7 +37,7 @@ public: template class Xmp final { - std::vector data_; + Vector data_; xmp_context instance_; bool module_loaded_; bool looping_; @@ -45,7 +45,7 @@ class Xmp final public: Xmp(); - explicit Xmp(std::vector data); + explicit Xmp(Vector data); explicit Xmp(tcb::span data); Xmp(const Xmp&) = delete; @@ -74,7 +74,7 @@ extern template class Xmp<2>; template , int> = 0> inline Xmp load_xmp(I& stream) { - std::vector data = srb2::io::read_to_vec(stream); + Vector data = srb2::io::read_to_vec(stream); return Xmp {std::move(data)}; } diff --git a/src/audio/xmp_player.cpp b/src/audio/xmp_player.cpp index 9062f0a50..35285bacc 100644 --- a/src/audio/xmp_player.cpp +++ b/src/audio/xmp_player.cpp @@ -12,6 +12,8 @@ #include +#include "../core/vector.hpp" + using namespace srb2; using namespace srb2::audio; diff --git a/src/audio/xmp_player.hpp b/src/audio/xmp_player.hpp index e3b31bbfa..bc9e1898c 100644 --- a/src/audio/xmp_player.hpp +++ b/src/audio/xmp_player.hpp @@ -14,6 +14,8 @@ #include "source.hpp" #include "xmp.hpp" +#include "../core/vector.hpp" + namespace srb2::audio { @@ -21,7 +23,7 @@ template class XmpPlayer final : public Source { Xmp xmp_; - std::vector> buf_; + srb2::Vector> buf_; public: XmpPlayer(Xmp&& xmp); diff --git a/src/core/string.cpp b/src/core/string.cpp index fab807c14..2bd0bd24f 100644 --- a/src/core/string.cpp +++ b/src/core/string.cpp @@ -60,6 +60,17 @@ uint32_t String::size() const noexcept return data_.size() - 1; } +static const char* kEmptyString = ""; + +const char* String::c_str() const +{ + if (data_.empty()) + { + return kEmptyString; + } + return reinterpret_cast(data_.data()); +} + void String::reserve(size_type capacity) { if (capacity == 0) @@ -432,12 +443,24 @@ String::size_type String::copy(char* dest, size_type count, size_type pos) const void String::resize(size_type count) { - data_.resize(count); + if (count == 0) + { + data_.clear(); + return; + } + data_.resize(count + 1); + data_[count] = 0; } void String::resize(size_type count, uint8_t ch) { - data_.resize(count, ch); + if (count == 0) + { + data_.clear(); + return; + } + data_.resize(count + 1, ch); + data_[count] = 0; } void String::swap(String& other) noexcept diff --git a/src/core/string.h b/src/core/string.h index 249371f16..f91294b97 100644 --- a/src/core/string.h +++ b/src/core/string.h @@ -153,7 +153,7 @@ public: friend struct std::hash; - static const size_type npos = -1; + static constexpr const size_type npos = -1; String() = default; String(const String&); @@ -173,7 +173,7 @@ public: size_type size() const noexcept; bool empty() const noexcept { return data_.empty(); } - const char* c_str() const noexcept { return reinterpret_cast(data_.data()); } + const char* c_str() const; uint8_t* data() noexcept { return data_.data(); } const uint8_t* data() const noexcept { return data_.data(); } void reserve(size_type capacity); diff --git a/src/core/thread_pool.cpp b/src/core/thread_pool.cpp index eabd46c70..8a434ba63 100644 --- a/src/core/thread_pool.cpp +++ b/src/core/thread_pool.cpp @@ -14,12 +14,13 @@ #include #include #include -#include #include #include #include +#include "../core/string.h" +#include "../core/vector.hpp" #include "../cxxutil.hpp" #include "../m_argv.h" @@ -50,11 +51,11 @@ static void pool_executor( std::shared_ptr worker_ready_mutex, std::shared_ptr worker_ready_condvar, std::shared_ptr my_wq, - std::vector> other_wqs + srb2::Vector> other_wqs ) { { - std::string thread_name = fmt::format("Thread Pool Thread {}", thread_index); + srb2::String thread_name = srb2::format("Thread Pool Thread {}", thread_index); tracy::SetThreadName(thread_name.c_str()); } @@ -133,7 +134,7 @@ ThreadPool::ThreadPool(size_t threads) for (size_t i = 0; i < threads; i++) { std::shared_ptr my_queue = work_queues_[i]; - std::vector> other_queues; + srb2::Vector> other_queues; for (size_t j = 0; j < threads; j++) { // Order the other queues starting from the next adjacent worker diff --git a/src/g_demo.cpp b/src/g_demo.cpp index 06a6a4089..1d36dcb7e 100644 --- a/src/g_demo.cpp +++ b/src/g_demo.cpp @@ -16,7 +16,6 @@ #include #include -#include #include "doomdef.h" #include "doomtype.h" @@ -50,6 +49,7 @@ #include "md5.h" // demo checksums #include "p_saveg.h" // savebuffer_t #include "g_party.h" +#include "core/json.hpp" // SRB2Kart #include "d_netfil.h" // nameonly @@ -2437,17 +2437,18 @@ void G_BeginRecording(void) void srb2::write_current_demo_standings(const srb2::StandingsJson& standings) { using namespace srb2; - using json = nlohmann::json; // TODO populate standings data - std::vector ubjson = json::to_ubjson(standings); + JsonValue value { JsonObject() }; + to_json(value, standings); + Vector ubjson = value.to_ubjson(); uint32_t bytes = ubjson.size(); WRITEUINT8(demobuf.p, DW_STANDING2); WRITEUINT32(demobuf.p, bytes); - WRITEMEM(demobuf.p, ubjson.data(), bytes); + WRITEMEM(demobuf.p, (UINT8*)ubjson.data(), bytes); } void srb2::write_current_demo_end_marker() @@ -2615,12 +2616,12 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) static bool load_ubjson_standing(menudemo_t* pdemo, tcb::span slice, tcb::span demoskins) { using namespace srb2; - using json = nlohmann::json; StandingsJson js; try { - js = json::from_ubjson(slice).template get(); + JsonValue value { JsonValue::from_ubjson(tcb::as_bytes(slice)) }; + from_json(value, js); } catch (...) { diff --git a/src/g_demo.h b/src/g_demo.h index 89bc8d227..e3c4c74ff 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -21,10 +21,9 @@ #ifdef __cplusplus -#include -#include - -#include +#include "core/json.hpp" +#include "core/string.h" +#include "core/vector.hpp" // Modern json formats namespace srb2 @@ -32,12 +31,12 @@ namespace srb2 struct StandingJson { uint8_t ranking; - std::string name; + String name; uint8_t demoskin; - std::string skincolor; + String skincolor; uint32_t timeorscore; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( StandingJson, ranking, name, @@ -48,9 +47,9 @@ struct StandingJson }; struct StandingsJson { - std::vector standings; + Vector standings; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(StandingsJson, standings) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(StandingsJson, standings) }; void write_current_demo_standings(const StandingsJson& standings); diff --git a/src/g_gamedata.cpp b/src/g_gamedata.cpp index 20ba10530..58a84685c 100644 --- a/src/g_gamedata.cpp +++ b/src/g_gamedata.cpp @@ -27,7 +27,6 @@ #include "z_zone.h" namespace fs = std::filesystem; -using json = nlohmann::json; #define GD_VERSION_MAJOR (0xBA5ED321) #define GD_VERSION_MINOR (1) @@ -137,13 +136,13 @@ void srb2::save_ng_gamedata() skin_t& memskin = skins[i]; auto skin = skintojson(&memskin.records); - std::string name = std::string(memskin.name); + srb2::String name { memskin.name }; ng.skins[name] = std::move(skin); } for (auto unloadedskin = unloadedskins; unloadedskin; unloadedskin = unloadedskin->next) { auto skin = skintojson(&unloadedskin->records); - std::string name = std::string(unloadedskin->name); + srb2::String name { unloadedskin->name }; ng.skins[name] = std::move(skin); } @@ -175,13 +174,13 @@ void srb2::save_ng_gamedata() for (int i = 0; i < nummapheaders; i++) { auto map = maptojson(&mapheaderinfo[i]->records); - std::string lumpname = std::string(mapheaderinfo[i]->lumpname); + srb2::String lumpname { mapheaderinfo[i]->lumpname }; ng.maps[lumpname] = std::move(map); } for (auto unloadedmap = unloadedmapheaders; unloadedmap; unloadedmap = unloadedmap->next) { auto map = maptojson(&unloadedmap->records); - std::string lumpname = std::string(unloadedmap->lumpname); + srb2::String lumpname { unloadedmap->lumpname }; ng.maps[lumpname] = std::move(map); } for (int i = 0; i < gamedata->numspraycans; i++) @@ -194,7 +193,7 @@ void srb2::save_ng_gamedata() { continue; } - spraycan.color = std::string(skincolors[can->col].name); + spraycan.color = String(skincolors[can->col].name); if (can->map == NEXTMAP_INVALID) { @@ -213,7 +212,7 @@ void srb2::save_ng_gamedata() { continue; } - spraycan.map = std::string(mapheader->lumpname); + spraycan.map = String(mapheader->lumpname); ng.spraycans.emplace_back(std::move(spraycan)); } @@ -230,11 +229,11 @@ void srb2::save_ng_gamedata() skinreference_t& skinref = windata[i].best_skin; if (skinref.unloaded) { - newrecords.bestskin = std::string(skinref.unloaded->name); + newrecords.bestskin = String(skinref.unloaded->name); } else { - newrecords.bestskin = std::string(skins[skinref.id].name); + newrecords.bestskin = String(skins[skinref.id].name); } newrecords.gotemerald = windata[i].got_emerald; @@ -252,7 +251,7 @@ void srb2::save_ng_gamedata() } auto cupdata = cuptojson(cup->windata); - cupdata.name = std::string(cup->name); + cupdata.name = String(cup->name); ng.cups[cupdata.name] = std::move(cupdata); } for (auto unloadedcup = unloadedcupheaders; unloadedcup; unloadedcup = unloadedcup->next) @@ -263,7 +262,7 @@ void srb2::save_ng_gamedata() } auto cupdata = cuptojson(unloadedcup->windata); - cupdata.name = std::string(unloadedcup->name); + cupdata.name = String(unloadedcup->name); ng.cups[cupdata.name] = std::move(cupdata); } @@ -273,17 +272,19 @@ void srb2::save_ng_gamedata() cupheader_t* cup = gamedata->sealedswaps[i]; - sealedswap.name = std::string(cup->name); + sealedswap.name = String(cup->name); ng.sealedswaps.emplace_back(std::move(sealedswap)); } - std::string gamedataname_s {gamedatafilename}; - fs::path savepath {fmt::format("{}/{}", srb2home, gamedataname_s)}; - fs::path baksavepath {fmt::format("{}/{}.bak", srb2home, gamedataname_s)}; - - json ngdata_json = ng; + String gamedataname_s {gamedatafilename}; + String savepath_string = srb2::format("{}/{}", srb2home, gamedataname_s); + String baksavepath_string = srb2::format("{}/{}.bak", srb2home, gamedataname_s); + fs::path savepath { static_cast(savepath_string) }; + fs::path baksavepath { static_cast(srb2::format("{}/{}.bak", srb2home, gamedataname_s)) }; + JsonValue ngdata_json { JsonObject() }; + to_json(ngdata_json, ng); if (fs::exists(savepath)) { @@ -300,7 +301,7 @@ void srb2::save_ng_gamedata() try { - std::string savepathstring = savepath.string(); + String savepathstring = savepath.string(); srb2::io::FileStream file {savepathstring, srb2::io::FileStreamMode::kWrite}; // The header is necessary to validate during loading. @@ -308,7 +309,7 @@ void srb2::save_ng_gamedata() srb2::io::write(static_cast(GD_VERSION_MINOR), file); // minor/flags srb2::io::write(static_cast(gamedata->evercrashed), file); // dirty (crash recovery) - std::vector ubjson = json::to_ubjson(ng); + srb2::Vector ubjson = ngdata_json.to_ubjson(); srb2::io::write_exact(file, tcb::as_bytes(tcb::make_span(ubjson))); file.close(); } @@ -382,7 +383,7 @@ void srb2::load_ng_gamedata() return; } - std::string datapath {fmt::format("{}/{}", srb2home, gamedatafilename)}; + String datapath {srb2::format("{}/{}", srb2home, gamedatafilename)}; srb2::io::BufferedInputStream bis; try @@ -419,15 +420,13 @@ void srb2::load_ng_gamedata() return; } - std::vector remainder = srb2::io::read_to_vec(bis); + srb2::Vector remainder = srb2::io::read_to_vec(bis); GamedataJson js; try { - // safety: std::byte repr is always uint8_t 1-byte aligned - tcb::span remainder_as_u8 = tcb::span((uint8_t*)remainder.data(), remainder.size()); - json parsed = json::from_ubjson(remainder_as_u8); - js = parsed.template get(); + JsonValue parsed = JsonValue::from_ubjson(remainder); + from_json(parsed, js); } catch (const std::exception& ex) { @@ -542,7 +541,7 @@ void srb2::load_ng_gamedata() gamedata->challengegrid = static_cast(Z_Malloc( (gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT * sizeof(UINT16)), PU_STATIC, NULL)); - for (size_t i = 0; i < std::min((size_t)(gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT), js.challengegrid.grid.size()); i++) + for (size_t i = 0; i < std::min((size_t)(gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT), js.challengegrid.grid.size()); i++) { uint16_t gridvalue = js.challengegrid.grid[i]; gamedata->challengegrid[i] = gridvalue; @@ -745,7 +744,7 @@ void srb2::load_ng_gamedata() // Find the loaded cup for (cup = kartcupheaders; cup; cup = cup->next) { - std::string cupname = std::string(cup->name); + String cupname { cup->name }; if (cupname == cuppair.first) { break; @@ -770,7 +769,7 @@ void srb2::load_ng_gamedata() } for (auto unloadedskin = unloadedskins; unloadedskin; unloadedskin = unloadedskin->next) { - std::string skinname = std::string(unloadedskin->name); + String skinname { unloadedskin->name }; if (skinname == cuppair.second.records[j].bestskin) { skinreference_t ref {}; @@ -826,7 +825,7 @@ void srb2::load_ng_gamedata() break; } - std::string cupname = std::string(cup->name); + String cupname { cup->name }; if (cupname == js.sealedswaps[i].name) { break; diff --git a/src/g_gamedata.h b/src/g_gamedata.h index 130252692..bde624c4b 100644 --- a/src/g_gamedata.h +++ b/src/g_gamedata.h @@ -13,13 +13,12 @@ #ifdef __cplusplus -#include #include -#include -#include -#include -#include +#include "core/json.hpp" +#include "core/hash_map.hpp" +#include "core/string.h" +#include "core/vector.hpp" namespace srb2 { @@ -39,7 +38,7 @@ struct GamedataPlaytimeJson final uint32_t statistics; uint32_t tumble; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( GamedataPlaytimeJson, total, netgame, @@ -60,7 +59,7 @@ struct GamedataRingsJson final { uint32_t total; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataRingsJson, total) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataRingsJson, total) }; struct GamedataRoundsJson final @@ -71,7 +70,7 @@ struct GamedataRoundsJson final uint32_t special; uint32_t custom; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataRoundsJson, race, battle, prisons, special, custom) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataRoundsJson, race, battle, prisons, special, custom) }; struct GamedataChallengeKeysJson final @@ -81,7 +80,7 @@ struct GamedataChallengeKeysJson final uint16_t keyspending; uint16_t chaokeys; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataChallengeKeysJson, pendingkeyrounds, pendingkeyroundoffset, keyspending, chaokeys) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataChallengeKeysJson, pendingkeyrounds, pendingkeyroundoffset, keyspending, chaokeys) }; struct GamedataMilestonesJson final @@ -98,7 +97,7 @@ struct GamedataMilestonesJson final bool sealedswapalerted; bool tutorialdone; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( GamedataMilestonesJson, gonerlevel, everloadedaddon, @@ -119,15 +118,15 @@ struct GamedataPrisonEggPickupsJson final uint16_t thisprisoneggpickup; uint16_t prisoneggstothispickup; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataPrisonEggPickupsJson, thisprisoneggpickup, prisoneggstothispickup) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataPrisonEggPickupsJson, thisprisoneggpickup, prisoneggstothispickup) }; struct GamedataChallengeGridJson final { uint32_t width; - std::vector grid; + Vector grid; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataChallengeGridJson, width, grid) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataChallengeGridJson, width, grid) }; struct GamedataSkinRecordsPlaytimeJson final @@ -140,7 +139,7 @@ struct GamedataSkinRecordsPlaytimeJson final uint32_t custom; uint32_t tumble; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( GamedataSkinRecordsPlaytimeJson, total, race, @@ -158,7 +157,7 @@ struct GamedataSkinRecordsJson final uint32_t rounds; GamedataSkinRecordsPlaytimeJson time; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( GamedataSkinRecordsJson, wins, rounds, @@ -170,7 +169,7 @@ struct GamedataSkinJson final { GamedataSkinRecordsJson records; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSkinJson, records) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSkinJson, records) }; struct GamedataMapVisitedJson final @@ -181,7 +180,7 @@ struct GamedataMapVisitedJson final bool spbattack; bool mysticmelody; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapVisitedJson, visited, beaten, encore, spbattack, mysticmelody) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapVisitedJson, visited, beaten, encore, spbattack, mysticmelody) }; struct GamedataMapStatsTimeAttackJson final @@ -189,7 +188,7 @@ struct GamedataMapStatsTimeAttackJson final uint32_t besttime; uint32_t bestlap; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapStatsTimeAttackJson, besttime, bestlap) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapStatsTimeAttackJson, besttime, bestlap) }; struct GamedataMapStatsSpbAttackJson final @@ -197,7 +196,7 @@ struct GamedataMapStatsSpbAttackJson final uint32_t besttime; uint32_t bestlap; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapStatsSpbAttackJson, besttime, bestlap) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapStatsSpbAttackJson, besttime, bestlap) }; struct GamedataMapStatsPlaytimeJson final @@ -212,7 +211,7 @@ struct GamedataMapStatsPlaytimeJson final uint32_t timeattack; uint32_t spbattack; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( GamedataMapStatsPlaytimeJson, total, netgame, @@ -232,7 +231,7 @@ struct GamedataMapStatsJson final GamedataMapStatsSpbAttackJson spbattack; GamedataMapStatsPlaytimeJson time; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( GamedataMapStatsJson, timeattack, spbattack, @@ -245,15 +244,15 @@ struct GamedataMapJson final GamedataMapVisitedJson visited; GamedataMapStatsJson stats; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapJson, visited, stats) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapJson, visited, stats) }; struct GamedataSprayCanJson final { - std::string map; - std::string color; + String map; + String color; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSprayCanJson, map, color) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSprayCanJson, map, color) }; struct GamedataCupRecordsJson final @@ -261,24 +260,24 @@ struct GamedataCupRecordsJson final uint8_t bestplacement; uint8_t bestgrade; bool gotemerald; - std::string bestskin; + String bestskin; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataCupRecordsJson, bestplacement, bestgrade, gotemerald, bestskin) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataCupRecordsJson, bestplacement, bestgrade, gotemerald, bestskin) }; struct GamedataCupJson final { - std::string name; - std::vector records; + String name; + Vector records; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataCupJson, name, records) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataCupJson, name, records) }; struct GamedataSealedSwapJson final { - std::string name; + String name; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSealedSwapJson, name) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSealedSwapJson, name) }; struct GamedataJson final @@ -290,19 +289,19 @@ struct GamedataJson final GamedataMilestonesJson milestones; GamedataPrisonEggPickupsJson prisons; uint32_t tafolderhash; - std::vector emblems; - std::vector unlockables; - std::vector unlockpending; - std::vector conditionsets; + Vector emblems; + Vector unlockables; + Vector unlockpending; + Vector conditionsets; GamedataChallengeGridJson challengegrid; uint32_t timesBeaten; - std::unordered_map skins; - std::unordered_map maps; - std::vector spraycans; - std::unordered_map cups; - std::vector sealedswaps; + HashMap skins; + HashMap maps; + Vector spraycans; + HashMap cups; + Vector sealedswaps; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( GamedataJson, playtime, rings, diff --git a/src/hud/input-display.cpp b/src/hud/input-display.cpp index 383d19a62..fbfd03ee2 100644 --- a/src/hud/input-display.cpp +++ b/src/hud/input-display.cpp @@ -85,8 +85,8 @@ void K_DrawInputDisplay(float x, float y, INT32 flags, char mode, UINT8 pid, boo const ticcmd_t& cmd = players[displayplayers[pid]].cmd; const boolean analog = (mode == '4' || mode == '5') ? players[displayplayers[pid]].analoginput : false; - const std::string prefix = fmt::format("PR{}", mode); - auto gfx = [&](auto format, auto&&... args) { return prefix + fmt::format(format, args...); }; + srb2::String prefix = srb2::format("PR{}", mode); + auto gfx = [&](auto format, auto&&... args) { return prefix + srb2::format(format, args...); }; auto but = [&](char key, INT32 gc, UINT32 bt) { bool press = local ? G_PlayerInputAnalog(pid, gc, guessinput) : ((cmd.buttons & bt) == bt); diff --git a/src/hud/spectator.cpp b/src/hud/spectator.cpp index c20d05cf3..f0606378a 100644 --- a/src/hud/spectator.cpp +++ b/src/hud/spectator.cpp @@ -165,7 +165,7 @@ void K_drawSpectatorHUD(boolean director) if (player) { - std::string label = [player] + srb2::String label = [player] { if (player->flashing) { @@ -183,7 +183,7 @@ void K_drawSpectatorHUD(boolean director) if (cv_maxplayers.value) { - label += fmt::format(" [{}/{}]", numingame, cv_maxplayers.value); + label += srb2::format(" [{}/{}]", numingame, cv_maxplayers.value); } list.insert({{label.c_str(), ""}}); diff --git a/src/hwr2/pass_resource_managers.hpp b/src/hwr2/pass_resource_managers.hpp index 7d03d950e..9636480dd 100644 --- a/src/hwr2/pass_resource_managers.hpp +++ b/src/hwr2/pass_resource_managers.hpp @@ -13,9 +13,9 @@ #include #include -#include -#include +#include "../core/hash_map.hpp" +#include "../core/vector.hpp" #include "../rhi/rhi.hpp" namespace srb2::hwr2 @@ -77,10 +77,10 @@ class MainPaletteManager final rhi::Handle encore_lighttable_; rhi::Handle default_colormap_; - std::unordered_map> colormaps_; - std::unordered_map> lighttables_; - std::vector colormaps_to_upload_; - std::vector lighttables_to_upload_; + srb2::HashMap> colormaps_; + srb2::HashMap> lighttables_; + srb2::Vector colormaps_to_upload_; + srb2::Vector lighttables_to_upload_; void upload_palette(rhi::Rhi& rhi); void upload_lighttables(rhi::Rhi& rhi); diff --git a/src/hwr2/patch_atlas.cpp b/src/hwr2/patch_atlas.cpp index fb6b4d965..5dad04e5f 100644 --- a/src/hwr2/patch_atlas.cpp +++ b/src/hwr2/patch_atlas.cpp @@ -72,7 +72,7 @@ rhi::Rect srb2::hwr2::trimmed_patch_dimensions(const patch_t* patch) return {minx, miny, static_cast(maxx - minx), static_cast(maxy - miny)}; } -void srb2::hwr2::convert_patch_to_trimmed_rg8_pixels(const patch_t* patch, std::vector& out) +void srb2::hwr2::convert_patch_to_trimmed_rg8_pixels(const patch_t* patch, srb2::Vector& out) { Rect trimmed_rect = srb2::hwr2::trimmed_patch_dimensions(patch); if (trimmed_rect.w % 2 > 0) @@ -299,7 +299,7 @@ void PatchAtlasCache::pack(Rhi& rhi) SRB2_ASSERT(ready_for_lookup()); // Upload atlased patches - std::vector patch_data; + srb2::Vector patch_data; for (const patch_t* patch_to_upload : patches_to_upload_) { srb2::NotNull atlas = find_patch(patch_to_upload); diff --git a/src/hwr2/patch_atlas.hpp b/src/hwr2/patch_atlas.hpp index e19ff4345..46e39740d 100644 --- a/src/hwr2/patch_atlas.hpp +++ b/src/hwr2/patch_atlas.hpp @@ -14,12 +14,12 @@ #include #include #include -#include -#include -#include #include +#include "../core/hash_map.hpp" +#include "../core/hash_set.hpp" +#include "../core/vector.hpp" #include "../r_defs.h" #include "../rhi/rhi.hpp" @@ -55,7 +55,7 @@ private: rhi::Handle tex_; uint32_t size_; - std::unordered_map entries_; + srb2::HashMap entries_; std::unique_ptr rp_ctx {nullptr}; std::unique_ptr rp_nodes {nullptr}; @@ -84,11 +84,11 @@ public: /// drawing things like sprites and 2D elements. class PatchAtlasCache { - std::vector atlases_; - std::unordered_map patch_lookup_; + srb2::Vector atlases_; + srb2::HashMap patch_lookup_; - std::unordered_set patches_to_pack_; - std::unordered_set patches_to_upload_; + srb2::HashSet patches_to_pack_; + srb2::HashSet patches_to_upload_; uint32_t tex_size_ = 2048; size_t max_textures_ = 2; @@ -135,7 +135,7 @@ rhi::Rect trimmed_patch_dimensions(const patch_t* patch); /// during upload, but required for the RHI device's Unpack Alignment of 4 bytes. /// @param patch the patch to convert /// @param out the output vector, cleared before writing. -void convert_patch_to_trimmed_rg8_pixels(const patch_t* patch, std::vector& out); +void convert_patch_to_trimmed_rg8_pixels(const patch_t* patch, srb2::Vector& out); } // namespace srb2::hwr2 diff --git a/src/hwr2/postprocess_wipe.cpp b/src/hwr2/postprocess_wipe.cpp index d0adf2349..86364ab23 100644 --- a/src/hwr2/postprocess_wipe.cpp +++ b/src/hwr2/postprocess_wipe.cpp @@ -10,12 +10,11 @@ #include "postprocess_wipe.hpp" -#include - #include #include #include +#include "../core/string.h" #include "../f_finale.h" #include "../w_wad.h" @@ -106,7 +105,7 @@ void PostprocessWipePass::prepass(Rhi& rhi) return; } - std::string lumpname = fmt::format(FMT_STRING("FADE{:02d}{:02d}"), wipe_type, wipe_frame); + String lumpname = format(FMT_STRING("FADE{:02d}{:02d}"), wipe_type, wipe_frame); lumpnum_t mask_lump = W_CheckNumForName(lumpname.c_str()); if (mask_lump == LUMPERROR) { diff --git a/src/hwr2/resource_management.cpp b/src/hwr2/resource_management.cpp index 850bebfb2..0ac7d7358 100644 --- a/src/hwr2/resource_management.cpp +++ b/src/hwr2/resource_management.cpp @@ -181,7 +181,7 @@ Handle FlatTextureManager::find_or_create_indexed(Rhi& rhi, lumpnum_t l }); flats_.insert({lump, new_tex}); - std::vector> flat_data; + srb2::Vector> flat_data; std::size_t lump_length = W_LumpLength(lump); flat_data.reserve(flat_size * flat_size); diff --git a/src/hwr2/resource_management.hpp b/src/hwr2/resource_management.hpp index cf69d7591..3fd6666cf 100644 --- a/src/hwr2/resource_management.hpp +++ b/src/hwr2/resource_management.hpp @@ -11,10 +11,10 @@ #ifndef __SRB2_HWR2_RESOURCE_MANAGEMENT_HPP__ #define __SRB2_HWR2_RESOURCE_MANAGEMENT_HPP__ +#include "../core/hash_map.hpp" +#include "../core/vector.hpp" #include "../rhi/rhi.hpp" -#include - namespace srb2::hwr2 { @@ -27,8 +27,8 @@ class PaletteManager #endif rhi::Handle default_colormap_; - std::unordered_map> colormaps_; - std::unordered_map> lighttables_; + srb2::HashMap> colormaps_; + srb2::HashMap> lighttables_; public: PaletteManager(); @@ -67,9 +67,9 @@ from patch_t. /// @brief Manages textures corresponding to specific flats indexed by lump number. class FlatTextureManager { - std::unordered_map> flats_; - std::vector to_upload_; - std::vector> disposed_textures_; + srb2::HashMap> flats_; + srb2::Vector to_upload_; + srb2::Vector> disposed_textures_; public: FlatTextureManager(); diff --git a/src/hwr2/twodee_renderer.cpp b/src/hwr2/twodee_renderer.cpp index 5cf18e3b9..020b8306d 100644 --- a/src/hwr2/twodee_renderer.cpp +++ b/src/hwr2/twodee_renderer.cpp @@ -11,11 +11,11 @@ #include "twodee_renderer.hpp" #include -#include #include #include +#include "../core/hash_set.hpp" #include "blendmode.hpp" #include "../r_patch.h" #include "../v_video.h" @@ -248,7 +248,7 @@ void TwodeeRenderer::flush(Rhi& rhi, Twodee& twodee) } // Stage 1 - command list patch detection - std::unordered_set found_patches; + srb2::HashSet found_patches; for (const auto& list : twodee) { for (const auto& cmd : list.cmds) diff --git a/src/io/streams.hpp b/src/io/streams.hpp index ab0da285a..e46093e93 100644 --- a/src/io/streams.hpp +++ b/src/io/streams.hpp @@ -12,16 +12,16 @@ #define __SRB2_IO_STREAMS_HPP__ #include -#include #include -#include #include #include -#include #include #include +#include "../core/string.h" +#include "../core/vector.hpp" + namespace srb2::io { @@ -484,13 +484,13 @@ inline void read_exact(SpanStream& stream, tcb::span buffer) } class VecStream { - std::vector vec_; + srb2::Vector vec_; std::size_t head_ {0}; public: VecStream() = default; - VecStream(const std::vector& vec) : vec_(vec) {} - VecStream(std::vector&& vec) : vec_(std::move(vec)) {} + VecStream(const srb2::Vector& vec) : vec_(vec) {} + VecStream(srb2::Vector&& vec) : vec_(std::move(vec)) {} VecStream(const VecStream& rhs) = default; VecStream(VecStream&& rhs) = default; @@ -549,7 +549,7 @@ public: return head_; } - std::vector& vector() { return vec_; } + srb2::Vector& vector() { return vec_; } friend void read_exact(VecStream& stream, tcb::span buffer); }; @@ -674,7 +674,7 @@ template buf_; + srb2::Vector buf_; std::size_t buf_head_; bool zstream_initialized_; bool zstream_ended_; @@ -820,7 +820,7 @@ template buf_; + srb2::Vector buf_; tcb::span::size_type cap_; public: @@ -872,7 +872,7 @@ template buf_; + srb2::Vector buf_; tcb::span::size_type cap_; public: @@ -933,7 +933,7 @@ extern template class BufferedInputStream; template StreamSize pipe_all(I& input, O& output) { - std::vector buf; + srb2::Vector buf; StreamSize total_written = 0; StreamSize read_this_time = 0; @@ -951,7 +951,7 @@ StreamSize pipe_all(I& input, O& output) { } template -std::vector read_to_vec(I& input) { +srb2::Vector read_to_vec(I& input) { VecStream out; pipe_all(input, out); return std::move(out.vector()); diff --git a/src/k_bans.cpp b/src/k_bans.cpp index bbc86ee57..673adf0b7 100644 --- a/src/k_bans.cpp +++ b/src/k_bans.cpp @@ -12,13 +12,14 @@ /// \file k_bans.c /// \brief replacement for DooM Legacy ban system -#include #include -#include #include -#include +#include +#include "core/json.hpp" +#include "core/string.h" +#include "io/streams.hpp" #include "i_tcp_detail.h" // clientaddress #include "k_bans.h" #include "byteptr.h" // READ/WRITE macros @@ -34,7 +35,9 @@ #include "z_zone.h" #include "i_addrinfo.h" // I_getaddrinfo -using nlohmann::json; +using srb2::JsonArray; +using srb2::JsonObject; +using srb2::JsonValue; static mysockaddr_t *DuplicateSockAddr(const mysockaddr_t *source) { @@ -43,22 +46,22 @@ static mysockaddr_t *DuplicateSockAddr(const mysockaddr_t *source) return dup; } -static std::vector bans; +static srb2::Vector bans; static uint8_t allZero[PUBKEYLENGTH]; -static void load_bans_array_v1(json& array) +static void load_bans_array_v1(const JsonArray& array) { - for (json& object : array) + for (const JsonValue& object : array) { uint8_t public_key_bin[PUBKEYLENGTH]; - std::string public_key = object.at("public_key"); - std::string ip_address = object.at("ip_address"); - time_t expires = object.at("expires"); - UINT8 subnet_mask = object.at("subnet_mask"); - std::string username = object.at("username"); - std::string reason = object.at("reason"); + srb2::String public_key = object.at("public_key").get(); + srb2::String ip_address = object.at("ip_address").get(); + time_t expires = object.at("expires").get(); + UINT8 subnet_mask = object.at("subnet_mask").get(); + srb2::String username = object.at("username").get(); + srb2::String reason = object.at("reason").get(); if (!FromPrettyRRID(public_key_bin, public_key.c_str())) { @@ -86,16 +89,31 @@ void SV_LoadBans(void) if (!server) return; - json object; + JsonValue object; + + srb2::String banspath { srb2::format("{}/{}", srb2home, BANFILE) }; + srb2::io::BufferedInputStream bis; + try + { + srb2::io::FileStream fs { banspath, srb2::io::FileStreamMode::kRead }; + bis = srb2::io::BufferedInputStream(std::move(fs)); + } + catch (const srb2::io::FileStreamException& ex) + { + // file didn't open, likely doesn't exist + return; + } try { - std::ifstream f(va(pandf, srb2home, BANFILE)); - - if (f.is_open()) + srb2::Vector data = srb2::io::read_to_vec(bis); + srb2::String data_s; + data_s.reserve(data.size()); + for (auto b : data) { - f >> object; + data_s.push_back(std::to_integer(b)); } + object = JsonValue::from_json_string(data_s); } catch (const std::exception& ex) { @@ -115,11 +133,11 @@ void SV_LoadBans(void) { if (object.value("version", 1) == 1) { - json& array = object.at("bans"); + JsonValue& array = object.at("bans"); if (array.is_array()) { - load_bans_array_v1(array); + load_bans_array_v1(array.as_array()); } } } @@ -131,31 +149,36 @@ void SV_LoadBans(void) void SV_SaveBans(void) { - json object = json::object(); + JsonValue object = JsonValue(JsonObject()); object["version"] = 1; - json& array = object["bans"]; + JsonValue& array_value = object["bans"]; - array = json::array(); + array_value = JsonValue(JsonArray()); + JsonArray& array = array_value.as_array(); for (banrecord_t& ban : bans) { if (ban.deleted) continue; - array.push_back({ + array.push_back(JsonObject { {"public_key", GetPrettyRRID(ban.public_key, false)}, {"ip_address", SOCK_AddrToStr(ban.address)}, {"subnet_mask", ban.mask}, - {"expires", ban.expires}, + {"expires", static_cast(ban.expires)}, {"username", ban.username}, {"reason", ban.reason}, }); } + srb2::String json_string = object.to_json_string(); + srb2::String banfile_path = srb2::format("{}/{}", srb2home, BANFILE); + try { - std::ofstream(va(pandf, srb2home, BANFILE)) << object; + srb2::io::FileStream fs { banfile_path, srb2::io::FileStreamMode::kWrite }; + srb2::io::write_exact(fs, tcb::as_bytes(tcb::span(json_string))); } catch (const std::exception& ex) { @@ -345,10 +368,10 @@ static void SV_BanSearch(boolean remove) const char* stringaddress = SOCK_AddrToStr(ban.address); const char* stringkey = GetPrettyRRID(ban.public_key, true); - std::string recordprint = fmt::format( + srb2::String recordprint = srb2::format( "{}{} - {} [{}] - {}", stringaddress, - ban.mask && ban.mask != 32 ? fmt::format("/{}", ban.mask) : "", + ban.mask && ban.mask != 32 ? srb2::format("/{}", ban.mask) : "", ban.username, stringkey, ban.reason @@ -359,7 +382,7 @@ static void SV_BanSearch(boolean remove) if (ban.expires < now) recordprint += " - EXPIRED"; else - recordprint += fmt::format(" - expires {}m", (ban.expires - now)/60); + recordprint += srb2::format(" - expires {}m", (ban.expires - now)/60); } CONS_Printf("%s\n", recordprint.c_str()); diff --git a/src/k_credits.cpp b/src/k_credits.cpp index 401086b32..5b9023c19 100644 --- a/src/k_credits.cpp +++ b/src/k_credits.cpp @@ -12,11 +12,8 @@ #include "k_credits.h" -#include -#include #include #include -#include #include "doomdef.h" #include "doomstat.h" @@ -59,7 +56,9 @@ #include "r_main.h" #include "m_easing.h" -using nlohmann::json; +using srb2::JsonArray; +using srb2::JsonObject; +using srb2::JsonValue; enum credits_slide_types_e { @@ -75,14 +74,14 @@ enum credits_slide_types_e struct credits_slide_s { credits_slide_types_e type; - std::string label; - std::vector strings; + srb2::String label; + srb2::Vector strings; size_t strings_height; boolean play_demo_afterwards; int fade_out_music; }; -static std::vector g_credits_slides; +static srb2::Vector g_credits_slides; struct credits_star_s { @@ -94,10 +93,10 @@ struct credits_star_s static struct credits_s { size_t current_slide; - std::vector demo_maps; + srb2::Vector demo_maps; boolean skip; - std::vector stars; + srb2::Vector stars; fixed_t transition; fixed_t transition_prev; @@ -105,7 +104,7 @@ static struct credits_s tic_t animation_timer; - std::vector> split_slide_strings; + srb2::Vector> split_slide_strings; size_t split_slide_id; tic_t split_slide_delay; @@ -142,12 +141,14 @@ void F_LoadCreditsDefinitions(void) size_t credits_lump_len = W_LumpLength(credits_lump_id); const char *credits_lump = static_cast( W_CacheLumpNum(credits_lump_id, PU_CACHE) ); - json credits_array = json::parse(credits_lump, credits_lump + credits_lump_len); - if (credits_array.is_array() == false) + srb2::String json_string { credits_lump, credits_lump_len }; + JsonValue credits_parsed = JsonValue::from_json_string(json_string); + if (credits_parsed.is_array() == false) { I_Error("credits_def parse error: Not a JSON array"); return; } + JsonArray credits_array = credits_parsed.as_array(); if (credits_array.size() == 0) { @@ -156,11 +157,11 @@ void F_LoadCreditsDefinitions(void) try { - for (json& slide_obj : credits_array) + for (JsonValue& slide_obj : credits_array) { struct credits_slide_s slide; - std::string type_str = slide_obj.value("type", "scroll"); + srb2::String type_str = slide_obj.value("type", srb2::String("scroll")); if (type_str == "scroll") { @@ -196,18 +197,19 @@ void F_LoadCreditsDefinitions(void) throw std::runtime_error("unexpected type name '" + type_str + "'"); } - slide.label = slide_obj.value("label", ""); + slide.label = slide_obj.value("label", srb2::String("")); slide.strings_height = 0; if (slide_obj.contains("strings")) { - json strings_array = slide_obj.at("strings"); - if (strings_array.is_array() == true) + JsonValue strings_value = slide_obj.at("strings"); + if (strings_value.is_array() == true) { + JsonArray& strings_array = strings_value.as_array(); for (size_t i = 0; i < strings_array.size(); i++) { - slide.strings.push_back( strings_array.at(i) ); + slide.strings.push_back( strings_array.at(i).get() ); if (slide.type == CRED_TYPE_SCROLL) { @@ -289,7 +291,7 @@ static void F_InitCreditsSlide(void) size_t max_strings_per_screen = (num_strings - 1) / num_sub_screens + 1; size_t str_id = 0; - std::vector screen_strings; + srb2::Vector screen_strings; if (max_strings_per_screen == kMaxSlideStrings && num_strings % kMaxSlideStrings == 1) @@ -342,24 +344,24 @@ static void F_InitCreditsSlide(void) #endif ) { - slide->strings.push_back("#" + std::string(def->title)); + slide->strings.push_back("#" + srb2::String(def->title)); slide->strings_height += 12; if (def->author) { - slide->strings.push_back("by " + std::string(def->author)); + slide->strings.push_back("by " + srb2::String(def->author)); slide->strings_height += 12; } if (def->source) { - slide->strings.push_back("from " + std::string(def->source)); + slide->strings.push_back("from " + srb2::String(def->source)); slide->strings_height += 12; } if (def->composers) { - slide->strings.push_back("originally by " + std::string(def->composers)); + slide->strings.push_back("originally by " + srb2::String(def->composers)); slide->strings_height += 12; } @@ -478,7 +480,7 @@ void F_ContinueCredits(void) static UINT16 F_PickRandomCreditsDemoMap(void) { - std::vector allowedMaps; + srb2::Vector allowedMaps; for (INT32 i = 0; i < basenummapheaders; i++) // Only take from the base game. { @@ -911,7 +913,7 @@ static void F_DrawCreditsScroll(void) } else { - std::string new_str = str; + srb2::String new_str = str; if (new_str.at(0) == '*') { @@ -1017,7 +1019,7 @@ static void F_DrawCreditsSlide(void) return; } - const std::vector *slide_strings = &g_credits.split_slide_strings[ g_credits.split_slide_id ]; + const srb2::Vector *slide_strings = &g_credits.split_slide_strings[ g_credits.split_slide_id ]; const fixed_t strings_height = slide_strings->size() * 30 * FRACUNIT; fixed_t y = 0; @@ -1113,7 +1115,7 @@ static void F_DrawCreditsTyler52(void) V_DrawFadeScreen(0xFF00, 31 - (g_credits.tyler_fade * 4)); } - std::string memory_str = "In memory of"; + srb2::String memory_str = "In memory of"; const fixed_t memory_width = V_StringScaledWidth( FRACUNIT, FRACUNIT, FRACUNIT, 0, LSLOW_FONT, @@ -1126,7 +1128,7 @@ static void F_DrawCreditsTyler52(void) memory_str.c_str() ); - std::string tyler_str = "Tyler52"; + srb2::String tyler_str = "Tyler52"; const fixed_t tyler_width = V_StringScaledWidth( FRACUNIT, FRACUNIT, FRACUNIT, 0, LSHI_FONT, diff --git a/src/k_dialogue.cpp b/src/k_dialogue.cpp index 8d9214b6a..10b7f8796 100644 --- a/src/k_dialogue.cpp +++ b/src/k_dialogue.cpp @@ -14,9 +14,10 @@ #include "k_dialogue.hpp" #include "k_dialogue.h" -#include #include +#include +#include "core/string.h" #include "info.h" #include "sounds.h" #include "g_game.h" @@ -43,7 +44,7 @@ void Dialogue::Typewriter::ClearText(void) textDest.clear(); } -void Dialogue::Typewriter::NewText(std::string newText) +void Dialogue::Typewriter::NewText(const srb2::String& newText) { text.clear(); @@ -174,7 +175,7 @@ void Dialogue::SetSpeaker(void) typewriter.voiceSfx = sfx_ktalk; } -void Dialogue::SetSpeaker(std::string skinName, int portraitID) +void Dialogue::SetSpeaker(srb2::String skinName, int portraitID) { Init(); @@ -215,7 +216,7 @@ void Dialogue::SetSpeaker(std::string skinName, int portraitID) } } -void Dialogue::SetSpeaker(std::string name, patch_t *patch, UINT8 *colormap, sfxenum_t voice) +void Dialogue::SetSpeaker(srb2::String name, patch_t *patch, UINT8 *colormap, sfxenum_t voice) { Init(); @@ -472,7 +473,7 @@ void Dialogue::Draw(void) .flags(V_VFLIP|V_FLIP) .patch(patchCache["TUTDIAGE"]); - std::string intertext = ""; + srb2::String intertext = ""; drawer .xy(10 - BASEVIDWIDTH, -3-32) @@ -486,7 +487,7 @@ void Dialogue::Draw(void) .patch(patchCache["TUTDIAG2"]); if (Held()) - intertext += ""; + intertext += ""; else intertext += ""; diff --git a/src/k_dialogue.hpp b/src/k_dialogue.hpp index d0a2a1578..678cc36b0 100644 --- a/src/k_dialogue.hpp +++ b/src/k_dialogue.hpp @@ -14,10 +14,10 @@ #ifndef __K_DIALOGUE_HPP__ #define __K_DIALOGUE_HPP__ -#include #include -#include +#include "core/hash_map.hpp" +#include "core/string.h" #include "doomdef.h" #include "doomtype.h" #include "typedef.h" @@ -33,8 +33,8 @@ public: static constexpr fixed_t kSlideSpeed = FRACUNIT / (TICRATE / 5); void SetSpeaker(void); - void SetSpeaker(std::string skinName, int portraitID); - void SetSpeaker(std::string name, patch_t *patch, UINT8 *colormap, sfxenum_t voice); + void SetSpeaker(srb2::String skinName, int portraitID); + void SetSpeaker(srb2::String name, patch_t *patch, UINT8 *colormap, sfxenum_t voice); void NewText(std::string_view newText); @@ -60,8 +60,8 @@ public: static constexpr fixed_t kTextSpeedDefault = FRACUNIT; static constexpr fixed_t kTextPunctPause = (FRACUNIT * TICRATE * 2) / 5; - std::string text; - std::string textDest; + srb2::String text; + srb2::String textDest; fixed_t textTimer; fixed_t textSpeed; @@ -71,7 +71,7 @@ public: sfxenum_t voiceSfx; bool syllable; - void NewText(std::string newText); + void NewText(const srb2::String& newText); void ClearText(void); void WriteText(void); @@ -86,11 +86,11 @@ private: patch_t *bgPatch; patch_t *confirmPatch; - std::string speaker; + srb2::String speaker; patch_t *portrait; UINT8 *portraitColormap; - std::unordered_map patchCache; + srb2::HashMap patchCache; bool active; fixed_t slide; diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 2410e904f..dfd24a6cc 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -11,11 +11,12 @@ #include #include -#include #include #include +#include "core/string.h" +#include "core/vector.hpp" #include "k_hud.h" #include "k_kart.h" #include "k_battle.h" @@ -6332,21 +6333,21 @@ typedef enum typedef struct { - std::string text; + srb2::String text; sfxenum_t sound; } message_t; struct messagestate_t { - std::deque messages; - std::string objective = ""; + std::deque messages; + srb2::String objective = ""; tic_t timer = 0; boolean persist = false; messagemode_t mode = MM_IN; const tic_t speedyswitch = 2*TICRATE; const tic_t lazyswitch = 4*TICRATE; - void add(std::string msg) + void add(srb2::String msg) { messages.push_back(msg); } @@ -6384,7 +6385,7 @@ struct messagestate_t switch (mode) { case MM_IN: - if (timer > messages[0].length()) + if (timer > messages[0].size()) switch_mode(MM_HOLD); break; case MM_HOLD: @@ -6394,7 +6395,7 @@ struct messagestate_t switch_mode(MM_OUT); break; case MM_OUT: - if (timer > messages[0].length()) + if (timer > messages[0].size()) next(); break; } diff --git a/src/k_podium.cpp b/src/k_podium.cpp index 29dd5ae4a..9d326d7aa 100644 --- a/src/k_podium.cpp +++ b/src/k_podium.cpp @@ -12,6 +12,7 @@ #include "k_podium.h" +#include "core/string.h" #include "doomdef.h" #include "d_main.h" #include "d_netcmd.h" @@ -51,8 +52,6 @@ #include "k_hud.h" -#include - typedef enum { PODIUM_ST_CONGRATS_SLIDEIN, @@ -652,7 +651,7 @@ void podiumData_s::Draw(void) } { - std::string emeraldName; + srb2::String emeraldName; if (emeraldNum > 7) { emeraldName = (useWhiteFrame ? "K_SUPER2" : "K_SUPER1"); diff --git a/src/k_profiles.cpp b/src/k_profiles.cpp index 1cededc39..8ccab2229 100644 --- a/src/k_profiles.cpp +++ b/src/k_profiles.cpp @@ -12,10 +12,13 @@ /// \brief implements methods for profiles etc. #include +#include #include #include +#include "core/string.h" +#include "core/vector.hpp" #include "io/streams.hpp" #include "doomtype.h" #include "d_main.h" // pandf @@ -253,7 +256,6 @@ void PR_InitNewProfile(void) void PR_SaveProfiles(void) { namespace fs = std::filesystem; - using json = nlohmann::json; using namespace srb2; namespace io = srb2::io; @@ -271,13 +273,13 @@ void PR_SaveProfiles(void) profile_t* cprof = profilesList[i]; jsonprof.version = PROFILEVER; - jsonprof.profilename = std::string(cprof->profilename); + jsonprof.profilename = String(cprof->profilename); std::copy(std::begin(cprof->public_key), std::end(cprof->public_key), std::begin(jsonprof.publickey)); std::copy(std::begin(cprof->secret_key), std::end(cprof->secret_key), std::begin(jsonprof.secretkey)); - jsonprof.playername = std::string(cprof->playername); - jsonprof.skinname = std::string(cprof->skinname); - jsonprof.colorname = std::string(skincolors[cprof->color].name); - jsonprof.followername = std::string(cprof->follower); + jsonprof.playername = String(cprof->playername); + jsonprof.skinname = String(cprof->skinname); + jsonprof.colorname = String(skincolors[cprof->color].name); + jsonprof.followername = String(cprof->follower); if (cprof->followercolor == FOLLOWERCOLOR_MATCH) { jsonprof.followercolorname = "Match"; @@ -292,11 +294,11 @@ void PR_SaveProfiles(void) } else if (cprof->followercolor >= numskincolors) { - jsonprof.followercolorname = std::string(); + jsonprof.followercolorname = String(); } else { - jsonprof.followercolorname = std::string(skincolors[cprof->followercolor].name); + jsonprof.followercolorname = String(skincolors[cprof->followercolor].name); } jsonprof.records.wins = cprof->wins; jsonprof.records.rounds = cprof->rounds; @@ -310,7 +312,7 @@ void PR_SaveProfiles(void) for (size_t j = 0; j < num_gamecontrols; j++) { - std::vector mappings; + srb2::Vector mappings; for (size_t k = 0; k < MAXINPUTMAPPING; k++) { mappings.push_back(cprof->controls[j][k]); @@ -321,16 +323,18 @@ void PR_SaveProfiles(void) ng.profiles.emplace_back(std::move(jsonprof)); } - std::vector ubjson = json::to_ubjson(ng); + JsonValue ngv; + to_json(ngv, ng); + Vector ubjson = ngv.to_ubjson(); - std::string realpath = fmt::format("{}/{}", srb2home, PROFILESFILE); - std::string bakpath = fmt::format("{}.bak", realpath); + String realpath = srb2::format("{}/{}", srb2home, PROFILESFILE); + String bakpath = srb2::format("{}.bak", realpath); - if (fs::exists(realpath)) + if (fs::exists(fs::path(static_cast(realpath)))) { try { - fs::rename(realpath, bakpath); + fs::rename(fs::path(static_cast(realpath)), fs::path(static_cast(bakpath))); } catch (const fs::filesystem_error& ex) { @@ -349,7 +353,7 @@ void PR_SaveProfiles(void) io::write(static_cast(0), file); // reserved2 io::write(static_cast(0), file); // reserved3 io::write(static_cast(0), file); // reserved4 - io::write_exact(file, tcb::as_bytes(tcb::make_span(ubjson))); + io::write_exact(file, ubjson); file.close(); } catch (const std::exception& ex) @@ -367,7 +371,6 @@ void PR_LoadProfiles(void) namespace fs = std::filesystem; using namespace srb2; namespace io = srb2::io; - using json = nlohmann::json; profile_t *dprofile = PR_MakeProfile( PROFILEDEFAULTNAME, @@ -378,7 +381,7 @@ void PR_LoadProfiles(void) true ); - std::string datapath {fmt::format("{}/{}", srb2home, PROFILESFILE)}; + String datapath { srb2::format("{}/{}", srb2home, PROFILESFILE) }; io::BufferedInputStream bis; try @@ -413,11 +416,10 @@ void PR_LoadProfiles(void) throw std::domain_error("Header is incompatible"); } - std::vector remainder = io::read_to_vec(bis); + Vector remainder = io::read_to_vec(bis); // safety: std::byte repr is always uint8_t 1-byte aligned - tcb::span remainder_as_u8 = tcb::span((uint8_t*)remainder.data(), remainder.size()); - json parsed = json::from_ubjson(remainder_as_u8); - js = parsed.template get(); + JsonValue parsed = JsonValue::from_ubjson(remainder); + from_json(parsed, js); } catch (const std::exception& ex) { diff --git a/src/k_profiles.h b/src/k_profiles.h index 9d9e1c3bd..4c71ee074 100644 --- a/src/k_profiles.h +++ b/src/k_profiles.h @@ -25,10 +25,10 @@ #include #include -#include -#include -#include +#include "core/json.hpp" +#include "core/string.h" +#include "core/vector.hpp" namespace srb2 { @@ -38,7 +38,7 @@ struct ProfileRecordsJson uint32_t wins; uint32_t rounds; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ProfileRecordsJson, wins, rounds) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ProfileRecordsJson, wins, rounds) }; struct ProfilePreferencesJson @@ -50,9 +50,8 @@ struct ProfilePreferencesJson bool autoring; bool rumble; uint8_t fov; - tm test; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( ProfilePreferencesJson, kickstartaccel, autoroulette, @@ -67,19 +66,19 @@ struct ProfilePreferencesJson struct ProfileJson { uint32_t version; - std::string profilename; - std::string playername; + String profilename; + String playername; std::array publickey = {{}}; std::array secretkey = {{}}; - std::string skinname; - std::string colorname; - std::string followername; - std::string followercolorname; + String skinname; + String colorname; + String followername; + String followercolorname; ProfileRecordsJson records; ProfilePreferencesJson preferences; - std::vector> controls = {}; + Vector> controls = {}; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( ProfileJson, version, profilename, @@ -98,9 +97,9 @@ struct ProfileJson struct ProfilesJson { - std::vector profiles; + Vector profiles; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ProfilesJson, profiles) + SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ProfilesJson, profiles) }; } // namespace srb2 diff --git a/src/k_waypoint.cpp b/src/k_waypoint.cpp index c7e6a8f35..a43fb1b1c 100644 --- a/src/k_waypoint.cpp +++ b/src/k_waypoint.cpp @@ -24,10 +24,12 @@ #include "cxxutil.hpp" #include -#include #include +#include "core/string.h" +#include "core/vector.hpp" + // The number of sparkles per waypoint connection in the waypoint visualisation static const UINT32 SPARKLES_PER_CONNECTION = 16U; @@ -2377,8 +2379,8 @@ static BlockItReturn_t K_TrackWaypointNearOffroad(line_t *line) struct complexity_sneaker_s { fixed_t bbox[4]; - //std::vector sectors; - //std::vector things; + //srb2::Vector sectors; + //srb2::Vector things; complexity_sneaker_s(sector_t *sec) { @@ -2631,7 +2633,7 @@ static INT32 K_CalculateTrackComplexity(void) delta = FixedMul(delta, FixedMul(FixedMul(dist_factor, radius_factor), wall_factor)); - std::string msg = fmt::format( + srb2::String msg = srb2::format( "TURN [{}]: r: {:.2f}, d: {:.2f}, w: {:.2f}, r*d*w: {:.2f}, DELTA: {}\n", turn_id, FixedToFloat(radius_factor), @@ -2644,7 +2646,7 @@ static INT32 K_CalculateTrackComplexity(void) trackcomplexity += (delta / FRACUNIT); } - std::vector sneaker_panels; + srb2::Vector sneaker_panels; for (size_t i = 0; i < numsectors; i++) { diff --git a/src/lua_profile.cpp b/src/lua_profile.cpp index 140833e40..0cbd704fc 100644 --- a/src/lua_profile.cpp +++ b/src/lua_profile.cpp @@ -10,10 +10,8 @@ #include #include -#include #include #include -#include #include @@ -21,6 +19,9 @@ extern "C" { #include "blua/lua.h" }; +#include "core/hash_map.hpp" +#include "core/string.h" +#include "core/vector.hpp" #include "v_draw.hpp" #include "command.h" @@ -58,7 +59,7 @@ struct lua_timer_t namespace { -std::unordered_map g_tic_timers; +srb2::HashMap g_tic_timers; }; // namespace @@ -156,7 +157,7 @@ void LUA_RenderTimers(void) return; } - std::vector view; + srb2::Vector view; view.reserve(g_tic_timers.size()); auto color_flag = [](double t) diff --git a/src/m_pw.cpp b/src/m_pw.cpp index 7a60d58fa..0808ff28c 100644 --- a/src/m_pw.cpp +++ b/src/m_pw.cpp @@ -14,13 +14,13 @@ #include #include #include -#include #include #include -#include #include "modp_b64/modp_b64.h" +#include "core/string.h" +#include "core/vector.hpp" #include "cxxutil.hpp" #include "command.h" @@ -43,12 +43,13 @@ namespace constexpr const UINT8 kRRSalt[17] = "0L4rlK}{9ay6'VJS"; -std::array decode_hash(std::string encoded) +std::array decode_hash(srb2::String encoded) { std::array decoded; - if (modp::b64_decode(encoded).size() != decoded.size()) + std::string encoded_stl { static_cast(encoded) }; + if (modp::b64_decode(encoded_stl).size() != decoded.size()) throw std::invalid_argument("hash is incorrectly sized"); - std::copy(encoded.begin(), encoded.end(), decoded.begin()); + std::copy(encoded_stl.begin(), encoded_stl.end(), decoded.begin()); return decoded; } @@ -60,7 +61,7 @@ struct Pw const std::array hash_; }; -std::vector passwords; +srb2::Vector passwords; // m_cond.c template @@ -629,8 +630,8 @@ try_password_e M_TryPassword(const char *password, boolean conditions) using var = std::variant; // Normalize input casing - std::string key = password; - strlwr(key.data()); + srb2::String key = password; + strlwr((char*)key.data()); UINT8 key_hash[M_PW_HASH_SIZE]; M_HashPassword(key_hash, key.c_str(), kRRSalt); @@ -684,8 +685,8 @@ try_password_e M_TryPassword(const char *password, boolean conditions) boolean M_TryExactPassword(const char *password, const char *encodedhash) { // Normalize input casing - std::string key = password; - strlwr(key.data()); + srb2::String key = password; + strlwr((char*)key.data()); UINT8 key_hash[M_PW_HASH_SIZE]; M_HashPassword(key_hash, key.c_str(), kRRSalt); diff --git a/src/media/avrecorder.hpp b/src/media/avrecorder.hpp index 2c3c9def7..bcf05ad7d 100644 --- a/src/media/avrecorder.hpp +++ b/src/media/avrecorder.hpp @@ -17,11 +17,11 @@ #include #include #include -#include -#include #include +#include "../core/string.h" +#include "../core/vector.hpp" #include "../audio/sample.hpp" namespace srb2::media @@ -49,7 +49,7 @@ public: int frame_rate; }; - std::string file_name; + srb2::String file_name; std::optional max_size; // file size limit std::optional> max_duration; @@ -63,7 +63,7 @@ public: { using instance_t = std::unique_ptr; - std::vector screen; + srb2::Vector screen; uint32_t width, height; int pts; diff --git a/src/media/avrecorder_feedback.cpp b/src/media/avrecorder_feedback.cpp index 38c016b89..bf0d6c4b5 100644 --- a/src/media/avrecorder_feedback.cpp +++ b/src/media/avrecorder_feedback.cpp @@ -10,10 +10,10 @@ #include #include -#include #include +#include "../core/string.h" #include "../cxxutil.hpp" #include "avrecorder_impl.hpp" @@ -39,7 +39,7 @@ void Impl::container_dtor_handler(const MediaContainer& container) const if (max_size_ && container.size() > *max_size_) { - const std::string line = fmt::format( + const srb2::String line = srb2::format( "Video size has exceeded limit {} > {} ({}%)." " This should not happen, please report this bug.\n", container.size(), @@ -100,7 +100,7 @@ void AVRecorder::draw_statistics() const { SRB2_ASSERT(impl_->video_encoder_ != nullptr); - auto draw = [](int x, std::string text, int32_t flags = 0) + auto draw = [](int x, const srb2::String text, int32_t flags = 0) { V_DrawThinString( x, @@ -144,7 +144,7 @@ void AVRecorder::draw_statistics() const return 0; }(); - draw(200, fmt::format("{:.0f}", fps), fps_color); - draw(230, fmt::format("{:.1f}s", impl_->container_->duration().count())); - draw(260, fmt::format("{:.1f} MB", size / kMb), mb_color); + draw(200, srb2::format("{:.0f}", fps), fps_color); + draw(230, srb2::format("{:.1f}s", impl_->container_->duration().count())); + draw(260, srb2::format("{:.1f} MB", size / kMb), mb_color); } diff --git a/src/media/avrecorder_impl.hpp b/src/media/avrecorder_impl.hpp index 0b7adbe70..8a96503fb 100644 --- a/src/media/avrecorder_impl.hpp +++ b/src/media/avrecorder_impl.hpp @@ -19,8 +19,8 @@ #include #include #include -#include +#include "../core/string.h" #include "../i_time.h" #include "avrecorder.hpp" #include "container.hpp" @@ -57,7 +57,7 @@ public: using frame_type = StagingVideoFrame::instance_t; }; - std::vector::frame_type> vec_; + srb2::Vector::frame_type> vec_; // This number only decrements once a frame has // actually been written to container. diff --git a/src/media/cfile.cpp b/src/media/cfile.cpp index ea2bcc434..5837edfc4 100644 --- a/src/media/cfile.cpp +++ b/src/media/cfile.cpp @@ -19,7 +19,7 @@ using namespace srb2::media; -CFile::CFile(const std::string file_name) : name_(file_name) +CFile::CFile(const srb2::String& file_name) : name_(file_name) { file_ = std::fopen(name(), "wb"); diff --git a/src/media/cfile.hpp b/src/media/cfile.hpp index 8dc455881..3f6e73dbd 100644 --- a/src/media/cfile.hpp +++ b/src/media/cfile.hpp @@ -12,7 +12,8 @@ #define __SRB2_MEDIA_CFILE_HPP__ #include -#include + +#include "../core/string.h" namespace srb2::media { @@ -20,7 +21,7 @@ namespace srb2::media class CFile { public: - CFile(const std::string file_name); + CFile(const srb2::String& file_name); ~CFile(); operator std::FILE*() const { return file_; } @@ -28,7 +29,7 @@ public: const char* name() const { return name_.c_str(); } private: - std::string name_; + srb2::String name_; std::FILE* file_; }; diff --git a/src/media/container.hpp b/src/media/container.hpp index c391f4379..836f2e47c 100644 --- a/src/media/container.hpp +++ b/src/media/container.hpp @@ -14,8 +14,8 @@ #include #include #include -#include +#include "../core/string.h" #include "audio_encoder.hpp" #include "video_encoder.hpp" @@ -30,7 +30,7 @@ public: struct Config { - std::string file_name; + srb2::String file_name; dtor_cb_t destructor_callback; }; diff --git a/src/media/options.hpp b/src/media/options.hpp index a97cb4ef1..e17d7ea44 100644 --- a/src/media/options.hpp +++ b/src/media/options.hpp @@ -13,11 +13,11 @@ #include #include -#include #include -#include -#include +#include "../core/hash_map.hpp" +#include "../core/string.h" +#include "../core/vector.hpp" #include "../command.h" namespace srb2::media @@ -26,7 +26,7 @@ namespace srb2::media class Options { public: - using map_t = std::unordered_map; + using map_t = srb2::HashMap; template struct Range @@ -46,7 +46,7 @@ public: static consvar_t values(const char* default_value, const Range range, std::map list = {}); private: - static std::vector cvars_; + static srb2::Vector cvars_; const char* prefix_; map_t map_; @@ -54,6 +54,11 @@ private: const consvar_t& cvar(const char* option) const; }; +// clang-format off +extern template consvar_t Options::values(const char* default_value, const Range range, std::map list); +extern template consvar_t Options::values(const char* default_value, const Range range, std::map list); +// clang-format on + }; // namespace srb2::media #endif // __SRB2_MEDIA_OPTIONS_HPP__ diff --git a/src/media/options_values.cpp b/src/media/options_values.cpp index 2f648c264..66fb9e713 100644 --- a/src/media/options_values.cpp +++ b/src/media/options_values.cpp @@ -12,6 +12,7 @@ #include +#include "../core/vector.hpp" #include "options.hpp" #include "vorbis.hpp" #include "vp8.hpp" @@ -23,7 +24,7 @@ using namespace srb2::media; // to be defined in the same translation unit as // Options::cvars_ to guarantee initialization order. -std::vector Options::cvars_; +srb2::Vector Options::cvars_; // clang-format off const Options VorbisEncoder::options_("vorbis", { diff --git a/src/media/vorbis_error.hpp b/src/media/vorbis_error.hpp index cbd3bffe4..27940080c 100644 --- a/src/media/vorbis_error.hpp +++ b/src/media/vorbis_error.hpp @@ -11,11 +11,11 @@ #ifndef __SRB2_MEDIA_VORBIS_ERROR_HPP__ #define __SRB2_MEDIA_VORBIS_ERROR_HPP__ -#include - #include #include +#include "../core/string.h" + class VorbisError { public: @@ -23,7 +23,7 @@ public: operator int() const { return error_; } - std::string name() const + srb2::String name() const { switch (error_) { @@ -43,12 +43,12 @@ private: }; template <> -struct fmt::formatter : formatter +struct fmt::formatter : formatter { template auto format(const VorbisError& error, FormatContext& ctx) const { - return formatter::format(error.name(), ctx); + return formatter::format(error.name(), ctx); } }; diff --git a/src/media/vpx_error.hpp b/src/media/vpx_error.hpp index ec53945e2..a5625f9da 100644 --- a/src/media/vpx_error.hpp +++ b/src/media/vpx_error.hpp @@ -11,22 +11,22 @@ #ifndef __SRB2_MEDIA_VPX_ERROR_HPP__ #define __SRB2_MEDIA_VPX_ERROR_HPP__ -#include - #include #include +#include "../core/string.h" + class VpxError { public: VpxError(vpx_codec_ctx_t& ctx) : ctx_(&ctx) {} - std::string description() const + srb2::String description() const { const char* error = vpx_codec_error(ctx_); const char* detail = vpx_codec_error_detail(ctx_); - return detail ? fmt::format("{}: {}", error, detail) : error; + return detail ? srb2::format("{}: {}", error, detail) : error; } private: @@ -34,12 +34,12 @@ private: }; template <> -struct fmt::formatter : formatter +struct fmt::formatter : formatter { template auto format(const VpxError& error, FormatContext& ctx) const { - return formatter::format(error.description(), ctx); + return formatter::format(error.description(), ctx); } }; diff --git a/src/media/webm_container.hpp b/src/media/webm_container.hpp index 3b82b3b9b..ed974bb16 100644 --- a/src/media/webm_container.hpp +++ b/src/media/webm_container.hpp @@ -13,11 +13,11 @@ #include #include -#include #include #include +#include "../core/hash_map.hpp" #include "container.hpp" #include "webm.hpp" #include "webm_writer.hpp" @@ -88,7 +88,7 @@ private: mutable std::recursive_mutex queue_mutex_; - std::unordered_map queue_; + srb2::HashMap queue_; webm::timestamp latest_timestamp_ = 0; std::size_t queue_size_ = 0; diff --git a/src/media/webm_writer.hpp b/src/media/webm_writer.hpp index 6ebd998ce..c4b2fd60f 100644 --- a/src/media/webm_writer.hpp +++ b/src/media/webm_writer.hpp @@ -12,10 +12,10 @@ #define __SRB2_MEDIA_WEBM_WRITER_HPP__ #include -#include #include +#include "../core/string.h" #include "cfile.hpp" namespace srb2::media @@ -24,7 +24,7 @@ namespace srb2::media class WebmWriter : public CFile, public mkvmuxer::MkvWriter { public: - WebmWriter(const std::string file_name) : CFile(file_name), MkvWriter(static_cast(*this)) {} + WebmWriter(const srb2::String& file_name) : CFile(file_name), MkvWriter(static_cast(*this)) {} ~WebmWriter() { MkvWriter::Close(); } }; diff --git a/src/media/yuv420p.hpp b/src/media/yuv420p.hpp index cb4648ad5..d430a27bd 100644 --- a/src/media/yuv420p.hpp +++ b/src/media/yuv420p.hpp @@ -12,8 +12,8 @@ #define __SRB2_MEDIA_YUV420P_HPP__ #include -#include +#include "../core/vector.hpp" #include "video_frame.hpp" namespace srb2::media @@ -40,7 +40,7 @@ public: int width_ = 0; int height_ = 0; - std::vector vec_; + srb2::Vector vec_; }; YUV420pFrame(int pts, Buffer y, Buffer u, Buffer v, const BufferRGBA& rgba); diff --git a/src/menus/class-egg-tv/EggTV.cpp b/src/menus/class-egg-tv/EggTV.cpp index 346f2edbf..1fc51337f 100644 --- a/src/menus/class-egg-tv/EggTV.cpp +++ b/src/menus/class-egg-tv/EggTV.cpp @@ -11,11 +11,11 @@ #include #include #include -#include #include #include +#include "../../core/string.h" #include "../../cxxutil.hpp" #include "../../v_draw.hpp" #include "EggTV.hpp" @@ -85,11 +85,11 @@ void draw_face(const Draw& draw, const EggTVData::Replay::Standing& player, face } } -std::string player_time_string(const EggTVData::Replay::Standing& player) +srb2::String player_time_string(const EggTVData::Replay::Standing& player) { if (player.time) { - return fmt::format( + return srb2::format( R"({}'{}"{})", G_TicsToMinutes(*player.time, true), G_TicsToSeconds(*player.time), @@ -102,7 +102,7 @@ std::string player_time_string(const EggTVData::Replay::Standing& player) } } -std::string player_points_string(const EggTVData::Replay::Standing& player) +srb2::String player_points_string(const EggTVData::Replay::Standing& player) { return player.score ? fmt::format("{} PTS", *player.score) : "NO CONTEST"; } diff --git a/src/menus/class-egg-tv/EggTV.hpp b/src/menus/class-egg-tv/EggTV.hpp index 5e346ecde..81f0d0906 100644 --- a/src/menus/class-egg-tv/EggTV.hpp +++ b/src/menus/class-egg-tv/EggTV.hpp @@ -19,6 +19,7 @@ #include "EggTVData.hpp" #include "EggTVGraphics.hpp" +#include "../../core/vector.hpp" #include "../../doomdef.h" // TICRATE #include "../../i_time.h" #include "../../k_menu.h" @@ -197,7 +198,7 @@ private: { public: using limiter_t = std::function; - using anims_t = std::vector; + using anims_t = srb2::Vector; explicit Cursor(anims_t anims, limiter_t limiter) : limiter_(limiter), anims_(anims) {} diff --git a/src/menus/class-egg-tv/EggTVData.cpp b/src/menus/class-egg-tv/EggTVData.cpp index a4ea461c2..4fbe93424 100644 --- a/src/menus/class-egg-tv/EggTVData.cpp +++ b/src/menus/class-egg-tv/EggTVData.cpp @@ -14,13 +14,14 @@ #include #include #include -#include #include #include #include // std::filesystem::path formatter -#include +#include "../../core/string.h" +#include "../../core/json.hpp" +#include "../../io/streams.hpp" #include "../../cxxutil.hpp" #include "EggTVData.hpp" @@ -34,15 +35,15 @@ using namespace srb2::menus::egg_tv; namespace fs = std::filesystem; -using nlohmann::json; +using srb2::JsonValue; template <> -struct fmt::formatter : formatter +struct fmt::formatter : formatter { template auto format(const fs::filesystem_error& ex, FormatContext& ctx) const { - return formatter::format( + return formatter::format( fmt::format("{}, path1={}, path2={}", ex.what(), ex.path1(), ex.path2()), ctx ); @@ -65,13 +66,13 @@ To time_point_conv(From time) return std::chrono::time_point_cast(To::clock::now() + (time - From::clock::now())); } -json& ensure_array(json& object, const char* key) +JsonValue& ensure_array(JsonValue& object, const char* key) { - json& array = object[key]; + JsonValue& array = object[key]; if (!array.is_array()) { - array = json::array(); + array = JsonValue::array(); } return array; @@ -91,18 +92,16 @@ EggTVData::EggTVData() : favorites_(ensure_array(favoritesFile_, "favorites")) } } -json EggTVData::cache_favorites() const +JsonValue EggTVData::cache_favorites() const { - json object; + JsonValue object; try { - std::ifstream f(favoritesPath_); - - if (f.is_open()) - { - f >> object; - } + srb2::io::FileStream stream { favoritesPath_.generic_string() }; + srb2::Vector f = srb2::io::read_to_vec(stream); + srb2::String json_string { (const char*)f.data(), f.size() }; + object = JsonValue::from_json_string(json_string); } catch (const std::exception& ex) { @@ -199,9 +198,9 @@ EggTVData::Folder::Folder(EggTVData& tv, const fs::directory_entry& entry) : } } -EggTVData::Replay::Title::operator const std::string() const +EggTVData::Replay::Title::operator const srb2::String() const { - return second().empty() ? first() : fmt::format("{} - {}", first(), second()); + return second().empty() ? first() : srb2::format("{} - {}", first(), second()); } EggTVData::Replay::Replay(Folder::Cache::ReplayRef& ref) : ref_(&ref) @@ -230,7 +229,7 @@ EggTVData::Replay::Replay(Folder::Cache::ReplayRef& ref) : ref_(&ref) const std::string_view str = info.title; const std::size_t mid = str.find(kDelimiter); - title_ = Title(str.substr(0, mid), mid == std::string::npos ? "" : str.substr(mid + kDelimiter.size())); + title_ = Title(str.substr(0, mid), mid == srb2::String::npos ? "" : str.substr(mid + kDelimiter.size())); //title_ = Title("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW", "WWWWWWWWWWWWWWWWWWWWWWWWWWW"); } @@ -316,13 +315,13 @@ void EggTVData::Replay::toggle_favorite() const { const auto& it = ref_->iterator_to_favorite(); - if (it != ref_->favorites().end()) + if (it != ref_->favorites().as_array().end()) { - ref_->favorites().erase(it); + ref_->favorites().as_array().erase(it); } else { - ref_->favorites().emplace_back(ref_->favorites_path()); + ref_->favorites().as_array().emplace_back(ref_->favorites_path()); } ref_->cache().folder().tv().save_favorites(); @@ -382,7 +381,9 @@ void EggTVData::save_favorites() const { try { - std::ofstream(favoritesPath_) << favoritesFile_; + srb2::String json_string = favoritesFile_.to_json_string(); + srb2::io::FileStream fs { favoritesPath_.generic_string(), srb2::io::FileStreamMode::kWrite }; + srb2::io::write_exact(fs, tcb::as_bytes(tcb::span(json_string.data(), json_string.size()))); } catch (const std::exception& ex) { diff --git a/src/menus/class-egg-tv/EggTVData.hpp b/src/menus/class-egg-tv/EggTVData.hpp index 4661b95e6..09ab45b93 100644 --- a/src/menus/class-egg-tv/EggTVData.hpp +++ b/src/menus/class-egg-tv/EggTVData.hpp @@ -17,14 +17,13 @@ #include #include #include -#include #include #include #include #include -#include - +#include "../../core/string.h" +#include "../../core/json.hpp" #include "../../cxxutil.hpp" #include "../../d_main.h" // srb2home @@ -40,10 +39,10 @@ private: const std::filesystem::path root_ = std::filesystem::path{srb2home} / "media/replay/online"; const std::filesystem::path favoritesPath_ = root_ / "favorites.json"; - nlohmann::json favoritesFile_ = cache_favorites(); - nlohmann::json& favorites_; + JsonValue favoritesFile_ = cache_favorites(); + JsonValue& favorites_; - nlohmann::json cache_favorites() const; + JsonValue cache_favorites() const; void cache_folders(); void save_favorites() const; @@ -91,20 +90,21 @@ public: released_ = true; } - bool favorited() const { return iterator_to_favorite() != favorites().end(); } - nlohmann::json& favorites() const { return cache().folder().tv().favorites_; } + bool favorited() const { return iterator_to_favorite() != favorites().as_array().end(); } + JsonValue& favorites() const { return cache().folder().tv().favorites_; } - std::string favorites_path() const + srb2::String favorites_path() const { // path::generic_string converts to forward // slashes on Windows. This should suffice to make // the JSON file portable across installations. - return (std::filesystem::path{cache().folder().name()} / filename()).generic_string(); + return (std::filesystem::path{std::string_view(cache().folder().name())} / filename()).generic_string(); } - nlohmann::json::const_iterator iterator_to_favorite() const + JsonArray::const_iterator iterator_to_favorite() const { - return std::find(favorites().begin(), favorites().end(), favorites_path()); + srb2::String path = favorites_path(); + return std::find(favorites().as_array().begin(), favorites().as_array().end(), static_cast(path)); } private: @@ -134,13 +134,13 @@ public: int y = 0; bool empty() { return size() == 0; } - std::filesystem::path path() const { return tv_->root_ / name_; } + std::filesystem::path path() const { return tv_->root_ / std::string_view(name_); } EggTVData& tv() const { return *tv_; } std::size_t size() const { return size_; } const time_point_t& time() const { return time_; } - const std::string& name() const { return name_; } + const srb2::String& name() const { return name_; } std::unique_ptr load() { return std::make_unique(*this); }; @@ -150,7 +150,7 @@ public: std::size_t size_; time_point_t time_; EggTVData* tv_; - std::string name_; + srb2::String name_; }; class Replay @@ -165,18 +165,18 @@ public: { } - const std::string& first() const { return first_; } - const std::string& second() const { return second_; } + const srb2::String& first() const { return first_; } + const srb2::String& second() const { return second_; } - operator const std::string() const; + operator const srb2::String() const; private: - std::string first_, second_; + srb2::String first_, second_; }; struct Standing { - std::string name; + srb2::String name; std::optional skin; std::size_t color; std::optional time; @@ -247,7 +247,7 @@ public: void toggle_favorite() const; bool invalid() const { return invalid_; } - bool favorited() const { return ref_->iterator_to_favorite() != ref_->favorites().end(); } + bool favorited() const { return ref_->iterator_to_favorite() != ref_->favorites().as_array().end(); } std::filesystem::path path() const { return ref_->cache().folder().path() / ref_->filename(); } const time_point_t& date() const { return ref_->time(); } diff --git a/src/menus/class-egg-tv/EggTVGraphics.hpp b/src/menus/class-egg-tv/EggTVGraphics.hpp index 280a203a9..d1928a0ae 100644 --- a/src/menus/class-egg-tv/EggTVGraphics.hpp +++ b/src/menus/class-egg-tv/EggTVGraphics.hpp @@ -13,8 +13,8 @@ #include #include -#include +#include "../../core/hash_map.hpp" #include "../../doomdef.h" // skincolornum_t #include "../../v_draw.hpp" @@ -90,7 +90,7 @@ public: patch select = "RHTVSQSL"; - std::unordered_map gametype = { + srb2::HashMap gametype = { {"Race", "RHGT1"}, {"Battle", "RHGT2"}, {"Prison Break", "RHGT3"}, diff --git a/src/menus/extras-statistics.cpp b/src/menus/extras-statistics.cpp index 5ae8832f0..efea7af67 100644 --- a/src/menus/extras-statistics.cpp +++ b/src/menus/extras-statistics.cpp @@ -11,6 +11,8 @@ /// \file menus/extras-challenges.c /// \brief Statistics menu +#include + #include "../k_menu.h" #include "../z_zone.h" #include "../m_cond.h" // Condition Sets @@ -260,7 +262,7 @@ static void M_StatisticsPageInit(void) M_StatisticsChars(); break; } - + case statisticspage_gp: { M_StatisticsGP(); diff --git a/src/menus/main-goner.cpp b/src/menus/main-goner.cpp index 52c936bd6..5539ed5a2 100644 --- a/src/menus/main-goner.cpp +++ b/src/menus/main-goner.cpp @@ -29,6 +29,8 @@ #include +#include "../core/string.h" + static void M_GonerDrawer(void); static void M_GonerConclude(INT32 choice); static boolean M_GonerInputs(INT32 ch); @@ -46,7 +48,7 @@ menuitem_t MAIN_Goner[] = {.routine = M_VideoOptions}, 0, 0}, {IT_STRING | IT_CALL, "SOUND OPTIONS", - "CALIBRATE AURAL DATASTREAM.", NULL, + "CALIBRATE AURAL DATASTREAM.", NULL, {.routine = M_SoundOptions}, 0, 0}, {IT_STRING | IT_CALL, "PROFILE SETUP", @@ -95,7 +97,7 @@ class GonerSpeaker public: float offset = 0; - GonerSpeaker(std::string skinName, float offset) + GonerSpeaker(const srb2::String& skinName, float offset) { if (!skinName.empty()) { @@ -144,11 +146,11 @@ class GonerChatLine { public: gonerspeakers_t speaker; - std::string dialogue; + srb2::String dialogue; int value; // Mutlipurpose. void (*routine)(void); - GonerChatLine(gonerspeakers_t speaker, int delay, std::string dialogue) + GonerChatLine(gonerspeakers_t speaker, int delay, const srb2::String& dialogue) { char *newText = V_ScaledWordWrap( (BASEVIDWIDTH/2 + 6) << FRACBITS, @@ -158,7 +160,7 @@ public: ); this->speaker = speaker; - this->dialogue = std::string(newText); + this->dialogue = srb2::String(newText); this->value = delay; this->routine = nullptr; @@ -1142,7 +1144,7 @@ static void M_GonerDrawer(void) for (auto & element : LinesOutput) { - std::string text; + srb2::String text; INT32 flags; if (newy < 0) break; diff --git a/src/music.cpp b/src/music.cpp index 44f1edb3c..b50dfaf66 100644 --- a/src/music.cpp +++ b/src/music.cpp @@ -174,7 +174,7 @@ void Music_Init(void) { Tune& tune = g_tunes.insert("credits"); - tune.priority = 100; + tune.priority = 101; tune.song = "_creds"; tune.credit = true; } @@ -182,7 +182,7 @@ void Music_Init(void) { Tune& tune = g_tunes.insert("shore"); - tune.priority = 100; + tune.priority = 101; tune.loop = false; } diff --git a/src/music_manager.cpp b/src/music_manager.cpp index b93745a88..86ca4bec9 100644 --- a/src/music_manager.cpp +++ b/src/music_manager.cpp @@ -14,13 +14,13 @@ #include #include #include -#include #include #include "music_manager.hpp" #include "music_tune.hpp" +#include "core/string.h" #include "d_clisrv.h" #include "doomtype.h" #include "i_sound.h" @@ -49,8 +49,8 @@ void TuneManager::tick() Tune* tune = current_tune(); - std::string old_song = current_song_; - current_song_ = tune && tune->playing() && !tune->suspend ? tune->song : std::string{}; + srb2::String old_song = current_song_; + current_song_ = tune && tune->playing() && !tune->suspend ? tune->song : srb2::String{}; bool changed = current_song_ != old_song; @@ -167,7 +167,8 @@ void TuneManager::pause_unpause() const bool TuneManager::load() const { - lumpnum_t lumpnum = W_CheckNumForLongName(fmt::format("O_{}", current_song_).c_str()); + srb2::String lumpstring = srb2::format("O_{}", current_song_); + lumpnum_t lumpnum = W_CheckNumForLongName(lumpstring.c_str()); if (lumpnum == LUMPERROR) { diff --git a/src/music_manager.hpp b/src/music_manager.hpp index adddd3c48..e3d377258 100644 --- a/src/music_manager.hpp +++ b/src/music_manager.hpp @@ -11,11 +11,10 @@ #ifndef MUSIC_MANAGER_HPP #define MUSIC_MANAGER_HPP -#include #include -#include -#include +#include "core/hash_map.hpp" +#include "core/string.h" #include "cxxutil.hpp" #include "music_tune.hpp" @@ -25,7 +24,7 @@ namespace srb2::music class TuneManager { public: - const std::string& current_song() const { return current_song_; } + const srb2::String& current_song() const { return current_song_; } Tune* current_tune() const { @@ -99,8 +98,8 @@ public: } private: - std::unordered_map map_; - std::string current_song_; + srb2::HashMap map_; + srb2::String current_song_; tic_t time_sync_; tic_t time_local_; @@ -113,11 +112,20 @@ private: decltype(map_)::const_iterator current_iterator() const { - return std::max_element( - map_.begin(), - map_.end(), - [](const auto& a, const auto& b) { return a.second < b.second; } - ); + // Not using std::max_element due to buggy clang libc++ LegacyInputIterator assertion + auto first = map_.begin(); + auto last = map_.end(); + if (first == last) return first; + + auto max = first; + while (++first != last) + { + if (max->second < first->second) + { + max = first; + } + } + return max; } bool load() const; diff --git a/src/music_tune.hpp b/src/music_tune.hpp index 2f9c925f7..557eb79a9 100644 --- a/src/music_tune.hpp +++ b/src/music_tune.hpp @@ -14,8 +14,8 @@ #include #include #include -#include +#include "core/string.h" #include "doomdef.h" #include "doomtype.h" #include "k_boss.h" @@ -29,7 +29,7 @@ class Tune public: explicit Tune() {} - std::string song; // looks up the lump + srb2::String song; // looks up the lump // Higher priority tunes play first. int priority = 0; diff --git a/src/objects/ballhog.cpp b/src/objects/ballhog.cpp index a3661fb69..1fe2ba218 100644 --- a/src/objects/ballhog.cpp +++ b/src/objects/ballhog.cpp @@ -10,6 +10,8 @@ /// \file ballhog.cpp /// \brief Ballhog item code. +#include + #include "../doomdef.h" #include "../doomstat.h" #include "../info.h" diff --git a/src/objects/checkpoint.cpp b/src/objects/checkpoint.cpp index 694d0564c..8ceba4df4 100644 --- a/src/objects/checkpoint.cpp +++ b/src/objects/checkpoint.cpp @@ -9,13 +9,13 @@ //----------------------------------------------------------------------------- #include -#include -#include #include #include "../mobj_list.hpp" +#include "../core/hash_map.hpp" +#include "../core/vector.hpp" #include "../doomdef.h" #include "../doomtype.h" #include "../info.h" @@ -224,7 +224,7 @@ struct Checkpoint : mobj_t speed(speed() - FixedDiv(speed() / 50, max(speed_multiplier(), 1))); } } - + if (!top_half_has_passed()) { sparkle_between(0); @@ -506,7 +506,7 @@ struct CheckpointManager auto count() { return list_.count(); } - const std::vector* lines_for(const Checkpoint* chk) const + const srb2::Vector* lines_for(const Checkpoint* chk) const { auto it = lines_.find(chk->linetag()); return it != lines_.end() ? &it->second : nullptr; @@ -514,11 +514,11 @@ struct CheckpointManager private: srb2::MobjList list_; - std::unordered_map> lines_; + srb2::HashMap> lines_; - static std::vector tagged_lines(INT32 tag) + static srb2::Vector tagged_lines(INT32 tag) { - std::vector checklines; + srb2::Vector checklines; INT32 li; TAG_ITER_LINES(tag, li) { @@ -573,18 +573,18 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe } LineOnDemand* gate; - const std::vector* lines = g_checkpoints.lines_for(chk); + const srb2::Vector* lines = g_checkpoints.lines_for(chk); if (!lines || lines->empty()) { LineOnDemand dyngate = chk->crossing_line(); if (!ray.overlaps(dyngate)) return false; - gate = &dyngate; + gate = &dyngate; } - else + else { - auto it = find_if( + auto it = std::find_if( lines->begin(), lines->end(), [&](const line_t* line) @@ -592,7 +592,7 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe return ray.overlaps(*line); } ); - + if (it == lines->end()) { return false; @@ -615,7 +615,7 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe { // Did not cross. return false; - + } return true; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index a0fb9e421..42cd68ad3 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -13,8 +13,6 @@ /// \brief Do all the WAD I/O, get map description, set up initial state and misc. LUTs #include -#include -#include #include @@ -96,6 +94,8 @@ #include "taglist.h" // SRB2Kart +#include "core/string.h" +#include "core/vector.hpp" #include "k_kart.h" #include "k_race.h" #include "k_battle.h" // K_BattleInit @@ -7854,7 +7854,7 @@ static void P_LoadRecordGhosts(void) map(cv_ghost_last, value, kLast); }; - auto add_ghosts = [gpath](const std::string& base, UINT8 bits) + auto add_ghosts = [gpath](const srb2::String& base, UINT8 bits) { auto load = [base](const char* suffix) { P_TryAddExternalGhost(fmt::format("{}-{}.lmp", base, suffix).c_str()); }; @@ -7991,7 +7991,7 @@ static void P_ShuffleTeams(void) CONS_Debug(DBG_TEAMS, "Shuffling player teams...\n"); - std::vector player_shuffle; + srb2::Vector player_shuffle; for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] == false || players[i].spectator == true) @@ -9135,7 +9135,7 @@ static tic_t round_to_next_second(tic_t time) static void P_DeriveAutoMedalTimes(mapheader_t& map) { // Gather staff ghost times - std::vector stafftimes; + srb2::Vector stafftimes; for (int i = 0; i < map.ghostCount; i++) { tic_t time = map.ghostBrief[i]->time; @@ -9325,7 +9325,7 @@ UINT8 P_InitMapData(void) { continue; } - std::string ghostdirname = fmt::format("staffghosts/{}/", mapheaderinfo[i]->lumpname); + srb2::String ghostdirname = srb2::format("staffghosts/{}/", mapheaderinfo[i]->lumpname); UINT16 lumpstart = W_CheckNumForFolderStartPK3(ghostdirname.c_str(), wadindex, 0); if (lumpstart == INT16_MAX) diff --git a/src/r_debug_printer.cpp b/src/r_debug_printer.cpp index a6b2e7749..d19569dcf 100644 --- a/src/r_debug_printer.cpp +++ b/src/r_debug_printer.cpp @@ -9,12 +9,12 @@ //----------------------------------------------------------------------------- #include -#include -#include #include "r_debug.hpp" #include "v_draw.hpp" +#include "core/hash_map.hpp" +#include "core/hash_set.hpp" #include "doomdef.h" #include "doomtype.h" #include "r_textures.h" @@ -25,7 +25,7 @@ using srb2::Draw; namespace { -std::unordered_set frame_list; +srb2::HashSet frame_list; }; // namespace diff --git a/src/r_plane.cpp b/src/r_plane.cpp index ab6659809..36f9b6b03 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -14,6 +14,8 @@ /// while maintaining a per column clipping list only. /// Moreover, the sky areas have to be determined. +#include + #include #include "command.h" diff --git a/src/r_textures_dups.cpp b/src/r_textures_dups.cpp index 90bb48dc5..eed8b2872 100644 --- a/src/r_textures_dups.cpp +++ b/src/r_textures_dups.cpp @@ -13,14 +13,14 @@ #include #include #include -#include #include #include -#include -#include #include +#include "core/hash_map.hpp" +#include "core/string.h" +#include "core/vector.hpp" #include "cxxutil.hpp" #include "doomstat.h" #include "r_textures.h" @@ -29,14 +29,14 @@ namespace { -std::unordered_map> g_dups; -std::map> g_warnings; +srb2::HashMap> g_dups; +std::map> g_warnings; std::thread g_dups_thread; -std::string key8char(const char cstr[8]) +srb2::String key8char(const char cstr[8]) { std::string_view view(cstr, 8); - std::string key; + srb2::String key; view = view.substr(0, view.find('\0')); // terminate by '\0' key.reserve(view.size()); @@ -50,7 +50,7 @@ std::string key8char(const char cstr[8]) return key; } -std::string texture_location(const texture_t& tex) +srb2::String texture_location(const texture_t& tex) { if (tex.type == TEXTURETYPE_SINGLEPATCH) { @@ -59,7 +59,7 @@ std::string texture_location(const texture_t& tex) const texpatch_t& texpat = tex.patches[0]; const wadfile_t& wad = *wadfiles[texpat.wad]; - return fmt::format( + return srb2::format( "'{}/{}'", std::filesystem::path(wad.filename).filename().string(), wad.lumpinfo[texpat.lump].fullname @@ -108,7 +108,7 @@ void R_CheckTextureDuplicates(INT32 start, INT32 end) auto collate_dups = [end, find_dup](int32_t start) { const texture_t* t1 = textures[start]; - const std::string key = key8char(t1->name); + const srb2::String key = key8char(t1->name); if (g_dups.find(key) != g_dups.end()) { @@ -119,7 +119,7 @@ void R_CheckTextureDuplicates(INT32 start, INT32 end) if (idx < end) { - std::vector& v = g_dups[key]; + srb2::Vector& v = g_dups[key]; v.push_back(textures[start]); @@ -175,7 +175,7 @@ void R_PrintTextureWarnings(void) { CONS_Alert(CONS_WARNING, "\n%s", header.c_str()); - for (const std::string& warning : v) + for (const srb2::String& warning : v) { CONS_Printf("%s\n", warning.c_str()); } diff --git a/src/rhi/gl2/gl2_rhi.cpp b/src/rhi/gl2/gl2_rhi.cpp index 0097dea20..cf35eebb5 100644 --- a/src/rhi/gl2/gl2_rhi.cpp +++ b/src/rhi/gl2/gl2_rhi.cpp @@ -14,13 +14,13 @@ #include #include #include -#include #include #include #include #include +#include "../../core/vector.hpp" #include "../shader_load_context.hpp" using namespace srb2; @@ -840,8 +840,8 @@ rhi::Handle Gl2Rhi::create_program(const ProgramDesc& desc) // breaks the AMD driver's program linker in a bizarre way. // Process shader sources - std::vector vert_sources; - std::vector frag_sources; + srb2::Vector vert_sources; + srb2::Vector frag_sources; ShaderLoadContext vert_ctx; ShaderLoadContext frag_ctx; vert_ctx.set_version("120"); @@ -873,11 +873,11 @@ rhi::Handle Gl2Rhi::create_program(const ProgramDesc& desc) { GLint max_length = 0; gl_->GetShaderiv(program.vertex_shader, GL_INFO_LOG_LENGTH, &max_length); - std::vector compile_error(max_length); + srb2::Vector compile_error(max_length); gl_->GetShaderInfoLog(program.vertex_shader, max_length, &max_length, compile_error.data()); gl_->DeleteShader(program.vertex_shader); - throw std::runtime_error(fmt::format("Vertex shader compilation failed: {}", std::string(compile_error.data()))); + throw std::runtime_error(fmt::format("Vertex shader compilation failed: {}", String(compile_error.data()))); } program.fragment_shader = gl_->CreateShader(GL_FRAGMENT_SHADER); @@ -889,11 +889,11 @@ rhi::Handle Gl2Rhi::create_program(const ProgramDesc& desc) { GLint max_length = 0; gl_->GetShaderiv(program.fragment_shader, GL_INFO_LOG_LENGTH, &max_length); - std::vector compile_error(max_length); + srb2::Vector compile_error(max_length); gl_->GetShaderInfoLog(program.fragment_shader, max_length, &max_length, compile_error.data()); gl_->DeleteShader(program.fragment_shader); - throw std::runtime_error(fmt::format("Fragment shader compilation failed: {}", std::string(compile_error.data()))); + throw std::runtime_error(fmt::format("Fragment shader compilation failed: {}", String(compile_error.data()))); } program.program = gl_->CreateProgram(); @@ -907,13 +907,13 @@ rhi::Handle Gl2Rhi::create_program(const ProgramDesc& desc) { GLint max_length = 0; gl_->GetProgramiv(program.program, GL_INFO_LOG_LENGTH, &max_length); - std::vector link_error(max_length); + srb2::Vector link_error(max_length); gl_->GetProgramInfoLog(program.program, max_length, &max_length, link_error.data()); gl_->DeleteProgram(program.program); gl_->DeleteShader(program.fragment_shader); gl_->DeleteShader(program.vertex_shader); - throw std::runtime_error(fmt::format("Pipeline program link failed: {}", std::string(link_error.data()))); + throw std::runtime_error(fmt::format("Pipeline program link failed: {}", String(link_error.data()))); } // get attribute information @@ -936,7 +936,7 @@ rhi::Handle Gl2Rhi::create_program(const ProgramDesc& desc) GL_ASSERT; GLint location = gl_->GetAttribLocation(program.program, name); GL_ASSERT; - program.attrib_locations[std::string(name)] = location; + program.attrib_locations[String(name)] = location; } // get uniform information @@ -959,7 +959,7 @@ rhi::Handle Gl2Rhi::create_program(const ProgramDesc& desc) GL_ASSERT; GLint location = gl_->GetUniformLocation(program.program, name); GL_ASSERT; - program.uniform_locations[std::string(name)] = location; + program.uniform_locations[String(name)] = location; } Handle program_handle = program_slab_.insert(std::move(program)); diff --git a/src/rhi/gl2/gl2_rhi.hpp b/src/rhi/gl2/gl2_rhi.hpp index c12af9445..f8b62987b 100644 --- a/src/rhi/gl2/gl2_rhi.hpp +++ b/src/rhi/gl2/gl2_rhi.hpp @@ -14,11 +14,11 @@ #include #include #include -#include #include -#include -#include +#include "../../core/hash_map.hpp" +#include "../../core/string.h" +#include "../../core/vector.hpp" #include "../rhi.hpp" namespace srb2::rhi @@ -71,7 +71,7 @@ struct Gl2Platform virtual ~Gl2Platform(); virtual void present() = 0; - virtual std::tuple, std::vector> find_shader_sources(const char* name) = 0; + virtual std::tuple, srb2::Vector> find_shader_sources(const char* name) = 0; virtual Rect get_default_framebuffer_dimensions() = 0; }; @@ -98,8 +98,8 @@ struct Gl2Program : public rhi::Program uint32_t vertex_shader = 0; uint32_t fragment_shader = 0; uint32_t program = 0; - std::unordered_map attrib_locations; - std::unordered_map uniform_locations; + srb2::HashMap attrib_locations; + srb2::HashMap uniform_locations; }; struct Gl2ActiveUniform @@ -121,14 +121,14 @@ class Gl2Rhi final : public Rhi Handle current_index_buffer_; - std::unordered_map framebuffers_ {16}; + srb2::HashMap framebuffers_ {16}; struct DefaultRenderPassState { bool clear = false; }; using RenderPassState = std::variant; - std::vector render_pass_stack_; + srb2::Vector render_pass_stack_; std::optional> current_program_; PrimitiveType current_primitive_type_ = PrimitiveType::kPoints; uint32_t index_buffer_offset_ = 0; diff --git a/src/rhi/shader_load_context.cpp b/src/rhi/shader_load_context.cpp index 790fd5df1..ad3ffcf81 100644 --- a/src/rhi/shader_load_context.cpp +++ b/src/rhi/shader_load_context.cpp @@ -12,6 +12,9 @@ #include +#include "../core/string.h" +#include "../core/vector.hpp" + using namespace srb2; using namespace rhi; @@ -19,27 +22,27 @@ ShaderLoadContext::ShaderLoadContext() = default; void ShaderLoadContext::set_version(std::string_view version) { - version_ = fmt::format("#version {}\n", version); + version_ = srb2::format("#version {}\n", version); } -void ShaderLoadContext::add_source(const std::string& source) +void ShaderLoadContext::add_source(const srb2::String& source) { sources_.push_back(source); } -void ShaderLoadContext::add_source(std::string&& source) +void ShaderLoadContext::add_source(srb2::String&& source) { sources_.push_back(std::move(source)); } void ShaderLoadContext::define(std::string_view name) { - defines_.append(fmt::format("#define {}\n", name)); + defines_.append(srb2::format("#define {}\n", name)); } -std::vector ShaderLoadContext::get_sources_array() +srb2::Vector ShaderLoadContext::get_sources_array() { - std::vector ret; + srb2::Vector ret; ret.push_back(version_.c_str()); ret.push_back(defines_.c_str()); diff --git a/src/rhi/shader_load_context.hpp b/src/rhi/shader_load_context.hpp index d11e38f6a..1bc458ea8 100644 --- a/src/rhi/shader_load_context.hpp +++ b/src/rhi/shader_load_context.hpp @@ -11,29 +11,30 @@ #ifndef __SRB2_RHI_SHADER_LOAD_CONTEXT_HPP__ #define __SRB2_RHI_SHADER_LOAD_CONTEXT_HPP__ -#include #include -#include + +#include "../core/string.h" +#include "../core/vector.hpp" namespace srb2::rhi { class ShaderLoadContext { - std::string version_; - std::string defines_; - std::vector sources_; + srb2::String version_; + srb2::String defines_; + srb2::Vector sources_; public: ShaderLoadContext(); void set_version(std::string_view version); - void add_source(const std::string& source); - void add_source(std::string&& source); + void add_source(const srb2::String& source); + void add_source(srb2::String&& source); void define(std::string_view name); - std::vector get_sources_array(); + srb2::Vector get_sources_array(); }; }; // namespace srb2::rhi diff --git a/src/sanitize.cpp b/src/sanitize.cpp index 6862e0ec8..597a27345 100644 --- a/src/sanitize.cpp +++ b/src/sanitize.cpp @@ -11,9 +11,9 @@ #include #include #include -#include #include +#include "core/string.h" #include "doomtype.h" #include "sanitize.h" #include "v_draw.hpp" @@ -34,7 +34,7 @@ bool color_filter(char c) } template -std::string& filter_out(std::string& out, const std::string_view& range, F filter) +srb2::String& filter_out(srb2::String& out, const std::string_view& range, F filter) { std::remove_copy_if( range.begin(), @@ -62,9 +62,9 @@ int hexconv(int c) namespace srb2::sanitize { -std::string sanitize(std::string_view in, SanitizeMode mode) +srb2::String sanitize(std::string_view in, SanitizeMode mode) { - std::string out; + srb2::String out; return filter_out(out, in, [mode] { switch (mode) @@ -78,9 +78,9 @@ std::string sanitize(std::string_view in, SanitizeMode mode) }()); } -std::string parse_carets(std::string_view in, ParseMode mode) +srb2::String parse_carets(std::string_view in, ParseMode mode) { - std::string out; + srb2::String out; using std::size_t; for (;;) diff --git a/src/sanitize.h b/src/sanitize.h index 3bb07c1b3..0fe04e44d 100644 --- a/src/sanitize.h +++ b/src/sanitize.h @@ -14,9 +14,10 @@ #include "doomtype.h" #ifdef __cplusplus -#include #include +#include "core/string.h" + namespace srb2::sanitize { @@ -33,10 +34,10 @@ enum class ParseMode }; // sanitizes string of all 0x80 codes -std::string sanitize(std::string_view in, SanitizeMode mode); +srb2::String sanitize(std::string_view in, SanitizeMode mode); // sanitizes string of all 0x80 codes then parses caret codes -std::string parse_carets(std::string_view in, ParseMode mode); +srb2::String parse_carets(std::string_view in, ParseMode mode); }; // namespace srb2 diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp index fd6ff45c2..827d6314b 100644 --- a/src/sdl/i_main.cpp +++ b/src/sdl/i_main.cpp @@ -17,10 +17,10 @@ #include "../d_main.h" #include "../m_misc.h"/* path shit */ #include "../i_system.h" +#include "../core/string.h" #include #include -#include #include @@ -227,14 +227,14 @@ ChDirToExe (void) } #endif -static void walk_exception_stack(std::string& accum, bool nested) { +static void walk_exception_stack(srb2::String& accum, bool nested) { if (nested) accum.append("\n Caused by: Unknown exception"); else accum.append("Uncaught exception: Unknown exception"); } -static void walk_exception_stack(std::string& accum, const std::exception& ex, bool nested) { +static void walk_exception_stack(srb2::String& accum, const std::exception& ex, bool nested) { if (nested) accum.append("\n Caused by: "); else @@ -331,11 +331,11 @@ int main(int argc, char **argv) D_SRB2Loop(); } catch (const std::exception& ex) { - std::string exception; + srb2::String exception; walk_exception_stack(exception, ex, false); I_Error("%s", exception.c_str()); } catch (...) { - std::string exception; + srb2::String exception; walk_exception_stack(exception, false); I_Error("%s", exception.c_str()); } diff --git a/src/sdl/rhi_gl2_platform.cpp b/src/sdl/rhi_gl2_platform.cpp index 98a87f222..f3f10fe90 100644 --- a/src/sdl/rhi_gl2_platform.cpp +++ b/src/sdl/rhi_gl2_platform.cpp @@ -11,11 +11,13 @@ #include "rhi_gl2_platform.hpp" #include +#include #include #include -#include +#include "../core/string.h" +#include "../core/vector.hpp" #include "../cxxutil.hpp" #include "../doomstat.h" // mainwads #include "../w_wad.h" @@ -34,22 +36,22 @@ void SdlGl2Platform::present() SDL_GL_SwapWindow(window); } -static std::array glsllist_lump_names(const char* name) +static std::array glsllist_lump_names(const char* name) { - std::string vertex_list_name = fmt::format("rhi_glsllist_{}_vertex.txt", name); - std::string fragment_list_name = fmt::format("rhi_glsllist_{}_fragment.txt", name); + srb2::String vertex_list_name = fmt::format("rhi_glsllist_{}_vertex.txt", name); + srb2::String fragment_list_name = fmt::format("rhi_glsllist_{}_fragment.txt", name); return {std::move(vertex_list_name), std::move(fragment_list_name)}; } -static std::vector get_sources_from_glsllist_lump(const char* lumpname) +static srb2::Vector get_sources_from_glsllist_lump(const char* lumpname) { size_t buffer_size; if (!W_ReadShader(lumpname, &buffer_size, nullptr)) { throw std::runtime_error(fmt::format("Unable to find glsllist lump {}", lumpname)); } - std::string glsllist_lump_data; + srb2::String glsllist_lump_data; glsllist_lump_data.resize(buffer_size); if (!W_ReadShader(lumpname, &buffer_size, glsllist_lump_data.data())) { @@ -57,7 +59,7 @@ static std::vector get_sources_from_glsllist_lump(const char* lumpn } std::istringstream glsllist(glsllist_lump_data); - std::vector sources; + srb2::Vector sources; for (std::string line; std::getline(glsllist, line); ) { if (line.empty()) @@ -87,7 +89,7 @@ static std::vector get_sources_from_glsllist_lump(const char* lumpn { throw std::runtime_error(fmt::format("Unable to find glsl source lump lump {}", line)); } - std::string source_lump; + srb2::String source_lump; source_lump.resize(source_lump_size); if (!W_ReadShader(line.c_str(), &source_lump_size, source_lump.data())) { @@ -100,13 +102,13 @@ static std::vector get_sources_from_glsllist_lump(const char* lumpn return sources; } -std::tuple, std::vector> +std::tuple, srb2::Vector> SdlGl2Platform::find_shader_sources(const char* name) { - std::array glsllist_names = glsllist_lump_names(name); + std::array glsllist_names = glsllist_lump_names(name); - std::vector vertex_sources = get_sources_from_glsllist_lump(glsllist_names[0].c_str()); - std::vector fragment_sources = get_sources_from_glsllist_lump(glsllist_names[1].c_str()); + srb2::Vector vertex_sources = get_sources_from_glsllist_lump(glsllist_names[0].c_str()); + srb2::Vector fragment_sources = get_sources_from_glsllist_lump(glsllist_names[1].c_str()); return std::make_tuple(std::move(vertex_sources), std::move(fragment_sources)); } diff --git a/src/sdl/rhi_gl2_platform.hpp b/src/sdl/rhi_gl2_platform.hpp index ea892fce5..acaf48618 100644 --- a/src/sdl/rhi_gl2_platform.hpp +++ b/src/sdl/rhi_gl2_platform.hpp @@ -11,6 +11,10 @@ #ifndef __SRB2_SDL_RHI_GL2_PLATFORM_HPP__ #define __SRB2_SDL_RHI_GL2_PLATFORM_HPP__ +#include + +#include "../core/string.h" +#include "../core/vector.hpp" #include "../rhi/gl2/gl2_rhi.hpp" #include "../rhi/rhi.hpp" @@ -26,7 +30,7 @@ struct SdlGl2Platform final : public Gl2Platform virtual ~SdlGl2Platform(); virtual void present() override; - virtual std::tuple, std::vector> + virtual std::tuple, Vector> find_shader_sources(const char* name) override; virtual Rect get_default_framebuffer_dimensions() override; }; diff --git a/src/v_draw.cpp b/src/v_draw.cpp index bb60b73c2..f8fe7df9c 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -8,8 +8,7 @@ // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -#include - +#include "core/hash_map.hpp" #include "doomdef.h" // skincolornum_t #include "doomtype.h" #include "hu_stuff.h" @@ -34,7 +33,7 @@ int Draw::TextElement::width() const Draw::TextElement& Draw::TextElement::parse(std::string_view raw) { - static const std::unordered_map translation = { + static const srb2::HashMap translation = { #define BUTTON(str, lower_bits) \ {str, 0xB0 | lower_bits},\ {str "_animated", 0xA0 | lower_bits},\ @@ -88,7 +87,7 @@ Draw::TextElement& Draw::TextElement::parse(std::string_view raw) }; // When we encounter a Saturn button, what gamecontrol does it represent? - static const std::unordered_map inputdefinition = { + static const srb2::HashMap inputdefinition = { {sb_up, gc_up}, {sb_down, gc_down}, {sb_right, gc_right}, @@ -114,7 +113,7 @@ Draw::TextElement& Draw::TextElement::parse(std::string_view raw) // What physical binds should appear as Saturn icons anyway? // (We don't have generic binds for stick/dpad directions, so // using the existing arrow graphics is the best thing here.) - static const std::unordered_map prettyinputs = { + static const srb2::HashMap prettyinputs = { {KEY_UPARROW, sb_up}, {KEY_DOWNARROW, sb_down}, {KEY_LEFTARROW, sb_left}, @@ -164,7 +163,7 @@ Draw::TextElement& Draw::TextElement::parse(std::string_view raw) // SPECIAL: Generic button that we invoke explicitly, not via gamecontrol reference. // If we ever add anything else to this category, I promise I will create a real abstraction, // but for now, just hardcode the character replacements and pray for forgiveness. - + string_.push_back(0xEF); // Control code: "switch to descriptive input mode" string_.push_back(0xEB); // Control code: "large button" if (code == "dpad") @@ -198,7 +197,7 @@ Draw::TextElement& Draw::TextElement::parse(std::string_view raw) // EXTRA: descriptiveinput values above 1 translate binds back to Saturn buttons, // with various modes for various fucked up 6bt pads - std::unordered_map padconfig = {}; + srb2::HashMap padconfig = {}; switch (cv_descriptiveinput[localplayer].value) { case 1: @@ -277,7 +276,7 @@ Draw::TextElement& Draw::TextElement::parse(std::string_view raw) pad->second = pad->second & (0x0F); // original invocation has the animation bits, but the glyph bits come from the table - string_.push_back((it->second & 0xF0) | pad->second); + string_.push_back((it->second & 0xF0) | pad->second); } else { @@ -349,6 +348,11 @@ void Chain::fill(UINT8 color) const void Chain::string(const char* str, INT32 flags, Font font) const { + if (!str) + { + return; + } + const auto _ = Clipper(*this); flags |= default_font_flags(font); @@ -576,5 +580,10 @@ INT32 Draw::default_font_flags(Font font) fixed_t Draw::font_width(Font font, INT32 flags, const char* string) { + if (!string) + { + return 0; + } + return V_StringScaledWidth(FRACUNIT, FRACUNIT, FRACUNIT, flags, font_to_fontno(font), string); } diff --git a/src/v_draw.hpp b/src/v_draw.hpp index a5913a2b5..9fe9fa2c1 100644 --- a/src/v_draw.hpp +++ b/src/v_draw.hpp @@ -11,14 +11,14 @@ #ifndef __V_DRAW_HPP__ #define __V_DRAW_HPP__ -#include #include #include #include -#include #include +#include "core/hash_map.hpp" +#include "core/string.h" #include "doomdef.h" // skincolornum_t #include "doomtype.h" #include "screen.h" // BASEVIDWIDTH @@ -66,7 +66,7 @@ typedef enum } saturn_buttons_e; // Garden-variety standard gamepad -static const std::unordered_map standardpad = { +static const srb2::HashMap standardpad = { {nc_a, gb_a}, {nc_b, gb_b}, {nc_x, gb_x}, @@ -83,7 +83,7 @@ static const std::unordered_map standardpad = { // Standard gamepad, but evil Nintendo layout flip was applied by your // controller firmware or Steam Input—swap B/A and X/Y -static const std::unordered_map flippedpad = { +static const srb2::HashMap flippedpad = { {nc_a, gb_b}, {nc_b, gb_a}, {nc_x, gb_y}, @@ -99,7 +99,7 @@ static const std::unordered_map flippedpad = { }; // Saturn Type A - Retrobit Wired Dinput, RB RT LB LT (CZLR) -static const std::unordered_map saturntypeA = { +static const srb2::HashMap saturntypeA = { {nc_a, sb_a}, {nc_b, sb_b}, {nc_x, sb_x}, @@ -115,7 +115,7 @@ static const std::unordered_map saturntypeA = { }; // Saturn Type B - Retrobit Wireless Dinput, LB RB LT RT (CZLR) -static const std::unordered_map saturntypeB = { +static const srb2::HashMap saturntypeB = { {nc_a, sb_a}, {nc_b, sb_b}, {nc_x, sb_x}, @@ -131,7 +131,7 @@ static const std::unordered_map saturntypeB = { }; // Saturn Type C - Retrobit Xinput, RT LT LB RB (CZLR) -static const std::unordered_map saturntypeC = { +static const srb2::HashMap saturntypeC = { {nc_a, sb_a}, {nc_b, sb_b}, {nc_x, sb_x}, @@ -150,7 +150,7 @@ static const std::unordered_map saturntypeC = { // This cannot be disambiguated (shares L/R with type 1) // but is more spatially correct w/r/t SDL expectations // and standard arcade mapping (Z on top, C on bottom) -static const std::unordered_map saturntypeD = { +static const srb2::HashMap saturntypeD = { {nc_a, sb_a}, {nc_b, sb_b}, {nc_x, sb_x}, @@ -169,7 +169,7 @@ static const std::unordered_map saturntypeD = { // The Hori layout is, to my knowledge, the only 6bt one that has fully // unique buttons in every slot while having both bumpers and triggers, // so there's no way to accurately portray it without using generics. -static const std::unordered_map saturntypeE = { +static const srb2::HashMap saturntypeE = { {nc_a, sb_a}, {nc_b, sb_b}, {nc_x, sb_x}, @@ -263,7 +263,7 @@ public: public: explicit TextElement() {} - explicit TextElement(std::string string) : string_(string) {} + explicit TextElement(const srb2::String& string) : string_(string) {} template explicit TextElement(fmt::format_string format, Args&&... args) : @@ -271,14 +271,14 @@ public: { } - const std::string& string() const { return string_; } + const srb2::String& string() const { return string_; } std::optional font() const { return font_; } std::optional flags() const { return flags_; } std::optional as() const { return as_; } int width() const; - TextElement& string(std::string string) + TextElement& string(srb2::String string) { string_ = string; return *this; @@ -310,7 +310,7 @@ public: return *this; } private: - std::string string_; + srb2::String string_; std::optional font_; std::optional flags_; std::optional as_; @@ -357,7 +357,7 @@ public: Chain& colorize(UINT16 color); void text(const char* str) const { string(str, flags_, font_); } - void text(const std::string& str) const { text(str.c_str()); } + void text(const srb2::String& str) const { text(str.c_str()); } void text(const TextElement& elm) const { string(elm.string().c_str(), elm.flags().value_or(flags_), elm.font().value_or(font_)); @@ -370,7 +370,7 @@ public: void patch(patch_t* patch) const; void patch(const char* name) const { patch(Draw::cache_patch(name)); } - void patch(const std::string& name) const { patch(name.c_str()); } + void patch(const srb2::String& name) const { patch(name.c_str()); } void thumbnail(UINT16 mapnum) const; diff --git a/src/y_inter.cpp b/src/y_inter.cpp index 8f2117051..ac91947fe 100644 --- a/src/y_inter.cpp +++ b/src/y_inter.cpp @@ -322,9 +322,9 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) { srb2::StandingJson standing {}; standing.ranking = data.pos[data.numplayers]; - standing.name = std::string(player_names[i]); + standing.name = srb2::String(player_names[i]); standing.demoskin = players[i].skin; - standing.skincolor = std::string(skincolors[players[i].skincolor].name); + standing.skincolor = srb2::String(skincolors[players[i].skincolor].name); standing.timeorscore = data.val[data.numplayers]; standings.standings.emplace_back(std::move(standing)); }