Use new containers and json

This commit is contained in:
Eidolon 2025-01-13 13:56:44 -06:00
parent c58f2c7dbd
commit bd7646346b
78 changed files with 644 additions and 542 deletions

View file

@ -76,7 +76,7 @@ Ogg::Ogg() noexcept : memory_data_(), instance_(nullptr)
{ {
} }
Ogg::Ogg(std::vector<std::byte> data) : memory_data_(std::move(data)), instance_(nullptr) Ogg::Ogg(Vector<std::byte> data) : memory_data_(std::move(data)), instance_(nullptr)
{ {
_init_with_data(); _init_with_data();
} }
@ -153,8 +153,8 @@ OggComment Ogg::comment() const
stb_vorbis_comment c_comment = stb_vorbis_get_comment(instance_); stb_vorbis_comment c_comment = stb_vorbis_get_comment(instance_);
return OggComment { return OggComment {
std::string(c_comment.vendor), String(c_comment.vendor),
std::vector<std::string>(c_comment.comment_list, c_comment.comment_list + c_comment.comment_list_length)}; Vector<String>(c_comment.comment_list, c_comment.comment_list + c_comment.comment_list_length)};
} }
std::size_t Ogg::sample_rate() const std::size_t Ogg::sample_rate() const

View file

@ -35,19 +35,19 @@ public:
struct OggComment struct OggComment
{ {
std::string vendor; String vendor;
std::vector<std::string> comments; Vector<String> comments;
}; };
class Ogg final class Ogg final
{ {
std::vector<std::byte> memory_data_; Vector<std::byte> memory_data_;
stb_vorbis* instance_; stb_vorbis* instance_;
public: public:
Ogg() noexcept; Ogg() noexcept;
explicit Ogg(std::vector<std::byte> data); explicit Ogg(Vector<std::byte> data);
explicit Ogg(tcb::span<std::byte> data); explicit Ogg(tcb::span<std::byte> data);
Ogg(const Ogg&) = delete; Ogg(const Ogg&) = delete;
@ -77,7 +77,7 @@ private:
template <typename I, typename std::enable_if_t<srb2::io::IsInputStreamV<I>, int> = 0> template <typename I, typename std::enable_if_t<srb2::io::IsInputStreamV<I>, int> = 0>
inline Ogg load_ogg(I& stream) inline Ogg load_ogg(I& stream)
{ {
std::vector<std::byte> data = srb2::io::read_to_vec(stream); srb2::Vector<std::byte> data = srb2::io::read_to_vec(stream);
return Ogg {std::move(data)}; return Ogg {std::move(data)};
} }

View file

@ -126,9 +126,9 @@ void visit_tag(Visitor& visitor, io::SpanStream& stream, const TagHeader& header
stream.seek(io::SeekFrom::kStart, dest); stream.seek(io::SeekFrom::kStart, dest);
} }
std::vector<uint8_t> read_uint8_samples_from_stream(io::SpanStream& stream, std::size_t count) Vector<uint8_t> read_uint8_samples_from_stream(io::SpanStream& stream, std::size_t count)
{ {
std::vector<uint8_t> samples; Vector<uint8_t> samples;
samples.reserve(count); samples.reserve(count);
for (std::size_t i = 0; i < count; i++) for (std::size_t i = 0; i < count; i++)
{ {
@ -137,9 +137,9 @@ std::vector<uint8_t> read_uint8_samples_from_stream(io::SpanStream& stream, std:
return samples; return samples;
} }
std::vector<int16_t> read_int16_samples_from_stream(io::SpanStream& stream, std::size_t count) Vector<int16_t> read_int16_samples_from_stream(io::SpanStream& stream, std::size_t count)
{ {
std::vector<int16_t> samples; Vector<int16_t> samples;
samples.reserve(count); samples.reserve(count);
for (std::size_t i = 0; i < count; i++) for (std::size_t i = 0; i < count; i++)
{ {
@ -177,7 +177,7 @@ Wav::Wav(tcb::span<std::byte> data)
} }
std::optional<FmtTag> read_fmt; std::optional<FmtTag> read_fmt;
std::variant<std::vector<uint8_t>, std::vector<int16_t>> interleaved_samples; std::variant<Vector<uint8_t>, Vector<int16_t>> interleaved_samples;
while (stream.seek(io::SeekFrom::kCurrent, 0) < riff_end) while (stream.seek(io::SeekFrom::kCurrent, 0) < riff_end)
{ {
@ -247,7 +247,7 @@ template <typename T>
std::size_t read_samples( std::size_t read_samples(
std::size_t channels, std::size_t channels,
std::size_t offset, std::size_t offset,
const std::vector<T>& samples, const Vector<T>& samples,
tcb::span<audio::Sample<1>> buffer tcb::span<audio::Sample<1>> buffer
) noexcept ) noexcept
{ {
@ -281,8 +281,8 @@ std::size_t read_samples(
std::size_t Wav::get_samples(std::size_t offset, tcb::span<audio::Sample<1>> buffer) const noexcept std::size_t Wav::get_samples(std::size_t offset, tcb::span<audio::Sample<1>> buffer) const noexcept
{ {
auto samples_visitor = srb2::Overload { auto samples_visitor = srb2::Overload {
[&](const std::vector<uint8_t>& samples) { return read_samples<uint8_t>(channels(), offset, samples, buffer); }, [&](const Vector<uint8_t>& samples) { return read_samples<uint8_t>(channels(), offset, samples, buffer); },
[&](const std::vector<int16_t>& samples) [&](const Vector<int16_t>& samples)
{ return read_samples<int16_t>(channels(), offset, samples, buffer); }}; { return read_samples<int16_t>(channels(), offset, samples, buffer); }};
return std::visit(samples_visitor, interleaved_samples_); return std::visit(samples_visitor, interleaved_samples_);
@ -291,7 +291,7 @@ std::size_t Wav::get_samples(std::size_t offset, tcb::span<audio::Sample<1>> buf
std::size_t Wav::interleaved_length() const noexcept std::size_t Wav::interleaved_length() const noexcept
{ {
auto samples_visitor = srb2::Overload { auto samples_visitor = srb2::Overload {
[](const std::vector<uint8_t>& samples) { return samples.size(); }, [](const Vector<uint8_t>& samples) { return samples.size(); },
[](const std::vector<int16_t>& samples) { return samples.size(); }}; [](const Vector<int16_t>& samples) { return samples.size(); }};
return std::visit(samples_visitor, interleaved_samples_); return std::visit(samples_visitor, interleaved_samples_);
} }

View file

@ -15,10 +15,10 @@
#include <cstdint> #include <cstdint>
#include <type_traits> #include <type_traits>
#include <variant> #include <variant>
#include <vector>
#include <tcb/span.hpp> #include <tcb/span.hpp>
#include "../core/vector.hpp"
#include "../io/streams.hpp" #include "../io/streams.hpp"
#include "sample.hpp" #include "sample.hpp"
@ -27,7 +27,7 @@ namespace srb2::audio
class Wav final class Wav final
{ {
std::variant<std::vector<uint8_t>, std::vector<int16_t>> interleaved_samples_; std::variant<Vector<uint8_t>, Vector<int16_t>> interleaved_samples_;
std::size_t channels_ = 1; std::size_t channels_ = 1;
std::size_t sample_rate_ = 44100; std::size_t sample_rate_ = 44100;
@ -46,7 +46,7 @@ public:
template <typename I, typename std::enable_if_t<srb2::io::IsInputStreamV<I>, int> = 0> template <typename I, typename std::enable_if_t<srb2::io::IsInputStreamV<I>, int> = 0>
inline Wav load_wav(I& stream) inline Wav load_wav(I& stream)
{ {
std::vector<std::byte> data = srb2::io::read_to_vec(stream); Vector<std::byte> data = srb2::io::read_to_vec(stream);
return Wav {data}; return Wav {data};
} }

View file

@ -50,7 +50,7 @@ Xmp<C>::Xmp() : data_(), instance_(nullptr), module_loaded_(false), looping_(fal
} }
template <size_t C> template <size_t C>
Xmp<C>::Xmp(std::vector<std::byte> data) Xmp<C>::Xmp(Vector<std::byte> data)
: data_(std::move(data)), instance_(nullptr), module_loaded_(false), looping_(false) : data_(std::move(data)), instance_(nullptr), module_loaded_(false), looping_(false)
{ {
_init(); _init();

View file

@ -15,11 +15,11 @@
#include <cstddef> #include <cstddef>
#include <exception> #include <exception>
#include <utility> #include <utility>
#include <vector>
#include <tcb/span.hpp> #include <tcb/span.hpp>
#include <xmp.h> #include <xmp.h>
#include "../core/vector.hpp"
#include "../io/streams.hpp" #include "../io/streams.hpp"
namespace srb2::audio namespace srb2::audio
@ -37,7 +37,7 @@ public:
template <size_t C> template <size_t C>
class Xmp final class Xmp final
{ {
std::vector<std::byte> data_; Vector<std::byte> data_;
xmp_context instance_; xmp_context instance_;
bool module_loaded_; bool module_loaded_;
bool looping_; bool looping_;
@ -45,7 +45,7 @@ class Xmp final
public: public:
Xmp(); Xmp();
explicit Xmp(std::vector<std::byte> data); explicit Xmp(Vector<std::byte> data);
explicit Xmp(tcb::span<std::byte> data); explicit Xmp(tcb::span<std::byte> data);
Xmp(const Xmp<C>&) = delete; Xmp(const Xmp<C>&) = delete;
@ -74,7 +74,7 @@ extern template class Xmp<2>;
template <size_t C, typename I, typename std::enable_if_t<srb2::io::IsInputStreamV<I>, int> = 0> template <size_t C, typename I, typename std::enable_if_t<srb2::io::IsInputStreamV<I>, int> = 0>
inline Xmp<C> load_xmp(I& stream) inline Xmp<C> load_xmp(I& stream)
{ {
std::vector<std::byte> data = srb2::io::read_to_vec(stream); Vector<std::byte> data = srb2::io::read_to_vec(stream);
return Xmp<C> {std::move(data)}; return Xmp<C> {std::move(data)};
} }

View file

@ -12,6 +12,8 @@
#include <cmath> #include <cmath>
#include "../core/vector.hpp"
using namespace srb2; using namespace srb2;
using namespace srb2::audio; using namespace srb2::audio;

View file

@ -14,6 +14,8 @@
#include "source.hpp" #include "source.hpp"
#include "xmp.hpp" #include "xmp.hpp"
#include "../core/vector.hpp"
namespace srb2::audio namespace srb2::audio
{ {
@ -21,7 +23,7 @@ template <size_t C>
class XmpPlayer final : public Source<C> class XmpPlayer final : public Source<C>
{ {
Xmp<C> xmp_; Xmp<C> xmp_;
std::vector<std::array<int16_t, C>> buf_; srb2::Vector<std::array<int16_t, C>> buf_;
public: public:
XmpPlayer(Xmp<C>&& xmp); XmpPlayer(Xmp<C>&& xmp);

View file

@ -60,6 +60,17 @@ uint32_t String::size() const noexcept
return data_.size() - 1; return data_.size() - 1;
} }
static const char* kEmptyString = "";
const char* String::c_str() const
{
if (data_.empty())
{
return kEmptyString;
}
return reinterpret_cast<const char*>(data_.data());
}
void String::reserve(size_type capacity) void String::reserve(size_type capacity)
{ {
if (capacity == 0) 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) 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) 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 void String::swap(String& other) noexcept

View file

@ -153,7 +153,7 @@ public:
friend struct std::hash<String>; friend struct std::hash<String>;
static const size_type npos = -1; static constexpr const size_type npos = -1;
String() = default; String() = default;
String(const String&); String(const String&);
@ -173,7 +173,7 @@ public:
size_type size() const noexcept; size_type size() const noexcept;
bool empty() const noexcept { return data_.empty(); } bool empty() const noexcept { return data_.empty(); }
const char* c_str() const noexcept { return reinterpret_cast<const char*>(data_.data()); } const char* c_str() const;
uint8_t* data() noexcept { return data_.data(); } uint8_t* data() noexcept { return data_.data(); }
const uint8_t* data() const noexcept { return data_.data(); } const uint8_t* data() const noexcept { return data_.data(); }
void reserve(size_type capacity); void reserve(size_type capacity);

View file

@ -14,12 +14,13 @@
#include <condition_variable> #include <condition_variable>
#include <exception> #include <exception>
#include <mutex> #include <mutex>
#include <string>
#include <system_error> #include <system_error>
#include <fmt/format.h> #include <fmt/format.h>
#include <tracy/tracy/Tracy.hpp> #include <tracy/tracy/Tracy.hpp>
#include "../core/string.h"
#include "../core/vector.hpp"
#include "../cxxutil.hpp" #include "../cxxutil.hpp"
#include "../m_argv.h" #include "../m_argv.h"
@ -50,11 +51,11 @@ static void pool_executor(
std::shared_ptr<std::mutex> worker_ready_mutex, std::shared_ptr<std::mutex> worker_ready_mutex,
std::shared_ptr<std::condition_variable> worker_ready_condvar, std::shared_ptr<std::condition_variable> worker_ready_condvar,
std::shared_ptr<ThreadPool::Queue> my_wq, std::shared_ptr<ThreadPool::Queue> my_wq,
std::vector<std::shared_ptr<ThreadPool::Queue>> other_wqs srb2::Vector<std::shared_ptr<ThreadPool::Queue>> 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()); tracy::SetThreadName(thread_name.c_str());
} }
@ -133,7 +134,7 @@ ThreadPool::ThreadPool(size_t threads)
for (size_t i = 0; i < threads; i++) for (size_t i = 0; i < threads; i++)
{ {
std::shared_ptr<Queue> my_queue = work_queues_[i]; std::shared_ptr<Queue> my_queue = work_queues_[i];
std::vector<std::shared_ptr<Queue>> other_queues; srb2::Vector<std::shared_ptr<Queue>> other_queues;
for (size_t j = 0; j < threads; j++) for (size_t j = 0; j < threads; j++)
{ {
// Order the other queues starting from the next adjacent worker // Order the other queues starting from the next adjacent worker

View file

@ -16,7 +16,6 @@
#include <cstddef> #include <cstddef>
#include <tcb/span.hpp> #include <tcb/span.hpp>
#include <nlohmann/json.hpp>
#include "doomdef.h" #include "doomdef.h"
#include "doomtype.h" #include "doomtype.h"
@ -50,6 +49,7 @@
#include "md5.h" // demo checksums #include "md5.h" // demo checksums
#include "p_saveg.h" // savebuffer_t #include "p_saveg.h" // savebuffer_t
#include "g_party.h" #include "g_party.h"
#include "core/json.hpp"
// SRB2Kart // SRB2Kart
#include "d_netfil.h" // nameonly #include "d_netfil.h" // nameonly
@ -2437,17 +2437,18 @@ void G_BeginRecording(void)
void srb2::write_current_demo_standings(const srb2::StandingsJson& standings) void srb2::write_current_demo_standings(const srb2::StandingsJson& standings)
{ {
using namespace srb2; using namespace srb2;
using json = nlohmann::json;
// TODO populate standings data // TODO populate standings data
std::vector<uint8_t> ubjson = json::to_ubjson(standings); JsonValue value { JsonObject() };
to_json(value, standings);
Vector<std::byte> ubjson = value.to_ubjson();
uint32_t bytes = ubjson.size(); uint32_t bytes = ubjson.size();
WRITEUINT8(demobuf.p, DW_STANDING2); WRITEUINT8(demobuf.p, DW_STANDING2);
WRITEUINT32(demobuf.p, bytes); WRITEUINT32(demobuf.p, bytes);
WRITEMEM(demobuf.p, ubjson.data(), bytes); WRITEMEM(demobuf.p, (UINT8*)ubjson.data(), bytes);
} }
void srb2::write_current_demo_end_marker() 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<std::byte> slice, tcb::span<democharlist_t> demoskins) static bool load_ubjson_standing(menudemo_t* pdemo, tcb::span<std::byte> slice, tcb::span<democharlist_t> demoskins)
{ {
using namespace srb2; using namespace srb2;
using json = nlohmann::json;
StandingsJson js; StandingsJson js;
try try
{ {
js = json::from_ubjson(slice).template get<StandingsJson>(); JsonValue value { JsonValue::from_ubjson(tcb::as_bytes(slice)) };
from_json(value, js);
} }
catch (...) catch (...)
{ {

View file

@ -21,10 +21,9 @@
#ifdef __cplusplus #ifdef __cplusplus
#include <string> #include "core/json.hpp"
#include <vector> #include "core/string.h"
#include "core/vector.hpp"
#include <nlohmann/json.hpp>
// Modern json formats // Modern json formats
namespace srb2 namespace srb2
@ -32,12 +31,12 @@ namespace srb2
struct StandingJson struct StandingJson
{ {
uint8_t ranking; uint8_t ranking;
std::string name; String name;
uint8_t demoskin; uint8_t demoskin;
std::string skincolor; String skincolor;
uint32_t timeorscore; uint32_t timeorscore;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
StandingJson, StandingJson,
ranking, ranking,
name, name,
@ -48,9 +47,9 @@ struct StandingJson
}; };
struct StandingsJson struct StandingsJson
{ {
std::vector<StandingJson> standings; Vector<StandingJson> 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); void write_current_demo_standings(const StandingsJson& standings);

View file

@ -27,7 +27,6 @@
#include "z_zone.h" #include "z_zone.h"
namespace fs = std::filesystem; namespace fs = std::filesystem;
using json = nlohmann::json;
#define GD_VERSION_MAJOR (0xBA5ED321) #define GD_VERSION_MAJOR (0xBA5ED321)
#define GD_VERSION_MINOR (1) #define GD_VERSION_MINOR (1)
@ -137,13 +136,13 @@ void srb2::save_ng_gamedata()
skin_t& memskin = skins[i]; skin_t& memskin = skins[i];
auto skin = skintojson(&memskin.records); auto skin = skintojson(&memskin.records);
std::string name = std::string(memskin.name); srb2::String name { memskin.name };
ng.skins[name] = std::move(skin); ng.skins[name] = std::move(skin);
} }
for (auto unloadedskin = unloadedskins; unloadedskin; unloadedskin = unloadedskin->next) for (auto unloadedskin = unloadedskins; unloadedskin; unloadedskin = unloadedskin->next)
{ {
auto skin = skintojson(&unloadedskin->records); auto skin = skintojson(&unloadedskin->records);
std::string name = std::string(unloadedskin->name); srb2::String name { unloadedskin->name };
ng.skins[name] = std::move(skin); ng.skins[name] = std::move(skin);
} }
@ -175,13 +174,13 @@ void srb2::save_ng_gamedata()
for (int i = 0; i < nummapheaders; i++) for (int i = 0; i < nummapheaders; i++)
{ {
auto map = maptojson(&mapheaderinfo[i]->records); 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); ng.maps[lumpname] = std::move(map);
} }
for (auto unloadedmap = unloadedmapheaders; unloadedmap; unloadedmap = unloadedmap->next) for (auto unloadedmap = unloadedmapheaders; unloadedmap; unloadedmap = unloadedmap->next)
{ {
auto map = maptojson(&unloadedmap->records); auto map = maptojson(&unloadedmap->records);
std::string lumpname = std::string(unloadedmap->lumpname); srb2::String lumpname { unloadedmap->lumpname };
ng.maps[lumpname] = std::move(map); ng.maps[lumpname] = std::move(map);
} }
for (int i = 0; i < gamedata->numspraycans; i++) for (int i = 0; i < gamedata->numspraycans; i++)
@ -194,7 +193,7 @@ void srb2::save_ng_gamedata()
{ {
continue; continue;
} }
spraycan.color = std::string(skincolors[can->col].name); spraycan.color = String(skincolors[can->col].name);
if (can->map == NEXTMAP_INVALID) if (can->map == NEXTMAP_INVALID)
{ {
@ -213,7 +212,7 @@ void srb2::save_ng_gamedata()
{ {
continue; continue;
} }
spraycan.map = std::string(mapheader->lumpname); spraycan.map = String(mapheader->lumpname);
ng.spraycans.emplace_back(std::move(spraycan)); ng.spraycans.emplace_back(std::move(spraycan));
} }
@ -230,11 +229,11 @@ void srb2::save_ng_gamedata()
skinreference_t& skinref = windata[i].best_skin; skinreference_t& skinref = windata[i].best_skin;
if (skinref.unloaded) if (skinref.unloaded)
{ {
newrecords.bestskin = std::string(skinref.unloaded->name); newrecords.bestskin = String(skinref.unloaded->name);
} }
else else
{ {
newrecords.bestskin = std::string(skins[skinref.id].name); newrecords.bestskin = String(skins[skinref.id].name);
} }
newrecords.gotemerald = windata[i].got_emerald; newrecords.gotemerald = windata[i].got_emerald;
@ -252,7 +251,7 @@ void srb2::save_ng_gamedata()
} }
auto cupdata = cuptojson(cup->windata); auto cupdata = cuptojson(cup->windata);
cupdata.name = std::string(cup->name); cupdata.name = String(cup->name);
ng.cups[cupdata.name] = std::move(cupdata); ng.cups[cupdata.name] = std::move(cupdata);
} }
for (auto unloadedcup = unloadedcupheaders; unloadedcup; unloadedcup = unloadedcup->next) for (auto unloadedcup = unloadedcupheaders; unloadedcup; unloadedcup = unloadedcup->next)
@ -263,7 +262,7 @@ void srb2::save_ng_gamedata()
} }
auto cupdata = cuptojson(unloadedcup->windata); auto cupdata = cuptojson(unloadedcup->windata);
cupdata.name = std::string(unloadedcup->name); cupdata.name = String(unloadedcup->name);
ng.cups[cupdata.name] = std::move(cupdata); ng.cups[cupdata.name] = std::move(cupdata);
} }
@ -273,17 +272,19 @@ void srb2::save_ng_gamedata()
cupheader_t* cup = gamedata->sealedswaps[i]; cupheader_t* cup = gamedata->sealedswaps[i];
sealedswap.name = std::string(cup->name); sealedswap.name = String(cup->name);
ng.sealedswaps.emplace_back(std::move(sealedswap)); ng.sealedswaps.emplace_back(std::move(sealedswap));
} }
std::string gamedataname_s {gamedatafilename}; String gamedataname_s {gamedatafilename};
fs::path savepath {fmt::format("{}/{}", srb2home, gamedataname_s)}; String savepath_string = srb2::format("{}/{}", srb2home, gamedataname_s);
fs::path baksavepath {fmt::format("{}/{}.bak", srb2home, gamedataname_s)}; String baksavepath_string = srb2::format("{}/{}.bak", srb2home, gamedataname_s);
fs::path savepath { static_cast<std::string_view>(savepath_string) };
json ngdata_json = ng; fs::path baksavepath { static_cast<std::string_view>(srb2::format("{}/{}.bak", srb2home, gamedataname_s)) };
JsonValue ngdata_json { JsonObject() };
to_json(ngdata_json, ng);
if (fs::exists(savepath)) if (fs::exists(savepath))
{ {
@ -300,7 +301,7 @@ void srb2::save_ng_gamedata()
try try
{ {
std::string savepathstring = savepath.string(); String savepathstring = savepath.string();
srb2::io::FileStream file {savepathstring, srb2::io::FileStreamMode::kWrite}; srb2::io::FileStream file {savepathstring, srb2::io::FileStreamMode::kWrite};
// The header is necessary to validate during loading. // The header is necessary to validate during loading.
@ -308,7 +309,7 @@ void srb2::save_ng_gamedata()
srb2::io::write(static_cast<uint8_t>(GD_VERSION_MINOR), file); // minor/flags srb2::io::write(static_cast<uint8_t>(GD_VERSION_MINOR), file); // minor/flags
srb2::io::write(static_cast<uint8_t>(gamedata->evercrashed), file); // dirty (crash recovery) srb2::io::write(static_cast<uint8_t>(gamedata->evercrashed), file); // dirty (crash recovery)
std::vector<uint8_t> ubjson = json::to_ubjson(ng); srb2::Vector<std::byte> ubjson = ngdata_json.to_ubjson();
srb2::io::write_exact(file, tcb::as_bytes(tcb::make_span(ubjson))); srb2::io::write_exact(file, tcb::as_bytes(tcb::make_span(ubjson)));
file.close(); file.close();
} }
@ -382,7 +383,7 @@ void srb2::load_ng_gamedata()
return; return;
} }
std::string datapath {fmt::format("{}/{}", srb2home, gamedatafilename)}; String datapath {srb2::format("{}/{}", srb2home, gamedatafilename)};
srb2::io::BufferedInputStream<srb2::io::FileStream> bis; srb2::io::BufferedInputStream<srb2::io::FileStream> bis;
try try
@ -419,15 +420,13 @@ void srb2::load_ng_gamedata()
return; return;
} }
std::vector<std::byte> remainder = srb2::io::read_to_vec(bis); srb2::Vector<std::byte> remainder = srb2::io::read_to_vec(bis);
GamedataJson js; GamedataJson js;
try try
{ {
// safety: std::byte repr is always uint8_t 1-byte aligned JsonValue parsed = JsonValue::from_ubjson(remainder);
tcb::span<uint8_t> remainder_as_u8 = tcb::span((uint8_t*)remainder.data(), remainder.size()); from_json(parsed, js);
json parsed = json::from_ubjson(remainder_as_u8);
js = parsed.template get<GamedataJson>();
} }
catch (const std::exception& ex) catch (const std::exception& ex)
{ {
@ -542,7 +541,7 @@ void srb2::load_ng_gamedata()
gamedata->challengegrid = static_cast<uint16_t*>(Z_Malloc( gamedata->challengegrid = static_cast<uint16_t*>(Z_Malloc(
(gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT * sizeof(UINT16)), (gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT * sizeof(UINT16)),
PU_STATIC, NULL)); 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>((size_t)(gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT), js.challengegrid.grid.size()); i++)
{ {
uint16_t gridvalue = js.challengegrid.grid[i]; uint16_t gridvalue = js.challengegrid.grid[i];
gamedata->challengegrid[i] = gridvalue; gamedata->challengegrid[i] = gridvalue;
@ -745,7 +744,7 @@ void srb2::load_ng_gamedata()
// Find the loaded cup // Find the loaded cup
for (cup = kartcupheaders; cup; cup = cup->next) for (cup = kartcupheaders; cup; cup = cup->next)
{ {
std::string cupname = std::string(cup->name); String cupname { cup->name };
if (cupname == cuppair.first) if (cupname == cuppair.first)
{ {
break; break;
@ -770,7 +769,7 @@ void srb2::load_ng_gamedata()
} }
for (auto unloadedskin = unloadedskins; unloadedskin; unloadedskin = unloadedskin->next) 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) if (skinname == cuppair.second.records[j].bestskin)
{ {
skinreference_t ref {}; skinreference_t ref {};
@ -826,7 +825,7 @@ void srb2::load_ng_gamedata()
break; break;
} }
std::string cupname = std::string(cup->name); String cupname { cup->name };
if (cupname == js.sealedswaps[i].name) if (cupname == js.sealedswaps[i].name)
{ {
break; break;

View file

@ -13,13 +13,12 @@
#ifdef __cplusplus #ifdef __cplusplus
#include <array>
#include <cstdint> #include <cstdint>
#include <string>
#include <unordered_map>
#include <vector>
#include <nlohmann/json.hpp> #include "core/json.hpp"
#include "core/hash_map.hpp"
#include "core/string.h"
#include "core/vector.hpp"
namespace srb2 namespace srb2
{ {
@ -39,7 +38,7 @@ struct GamedataPlaytimeJson final
uint32_t statistics; uint32_t statistics;
uint32_t tumble; uint32_t tumble;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
GamedataPlaytimeJson, GamedataPlaytimeJson,
total, total,
netgame, netgame,
@ -60,7 +59,7 @@ struct GamedataRingsJson final
{ {
uint32_t total; uint32_t total;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataRingsJson, total) SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataRingsJson, total)
}; };
struct GamedataRoundsJson final struct GamedataRoundsJson final
@ -71,7 +70,7 @@ struct GamedataRoundsJson final
uint32_t special; uint32_t special;
uint32_t custom; 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 struct GamedataChallengeKeysJson final
@ -81,7 +80,7 @@ struct GamedataChallengeKeysJson final
uint16_t keyspending; uint16_t keyspending;
uint16_t chaokeys; 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 struct GamedataMilestonesJson final
@ -98,7 +97,7 @@ struct GamedataMilestonesJson final
bool sealedswapalerted; bool sealedswapalerted;
bool tutorialdone; bool tutorialdone;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
GamedataMilestonesJson, GamedataMilestonesJson,
gonerlevel, gonerlevel,
everloadedaddon, everloadedaddon,
@ -119,15 +118,15 @@ struct GamedataPrisonEggPickupsJson final
uint16_t thisprisoneggpickup; uint16_t thisprisoneggpickup;
uint16_t prisoneggstothispickup; 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 struct GamedataChallengeGridJson final
{ {
uint32_t width; uint32_t width;
std::vector<uint16_t> grid; Vector<uint16_t> grid;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataChallengeGridJson, width, grid) SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataChallengeGridJson, width, grid)
}; };
struct GamedataSkinRecordsPlaytimeJson final struct GamedataSkinRecordsPlaytimeJson final
@ -140,7 +139,7 @@ struct GamedataSkinRecordsPlaytimeJson final
uint32_t custom; uint32_t custom;
uint32_t tumble; uint32_t tumble;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
GamedataSkinRecordsPlaytimeJson, GamedataSkinRecordsPlaytimeJson,
total, total,
race, race,
@ -158,7 +157,7 @@ struct GamedataSkinRecordsJson final
uint32_t rounds; uint32_t rounds;
GamedataSkinRecordsPlaytimeJson time; GamedataSkinRecordsPlaytimeJson time;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
GamedataSkinRecordsJson, GamedataSkinRecordsJson,
wins, wins,
rounds, rounds,
@ -170,7 +169,7 @@ struct GamedataSkinJson final
{ {
GamedataSkinRecordsJson records; GamedataSkinRecordsJson records;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSkinJson, records) SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSkinJson, records)
}; };
struct GamedataMapVisitedJson final struct GamedataMapVisitedJson final
@ -181,7 +180,7 @@ struct GamedataMapVisitedJson final
bool spbattack; bool spbattack;
bool mysticmelody; 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 struct GamedataMapStatsTimeAttackJson final
@ -189,7 +188,7 @@ struct GamedataMapStatsTimeAttackJson final
uint32_t besttime; uint32_t besttime;
uint32_t bestlap; 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 struct GamedataMapStatsSpbAttackJson final
@ -197,7 +196,7 @@ struct GamedataMapStatsSpbAttackJson final
uint32_t besttime; uint32_t besttime;
uint32_t bestlap; 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 struct GamedataMapStatsPlaytimeJson final
@ -212,7 +211,7 @@ struct GamedataMapStatsPlaytimeJson final
uint32_t timeattack; uint32_t timeattack;
uint32_t spbattack; uint32_t spbattack;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
GamedataMapStatsPlaytimeJson, GamedataMapStatsPlaytimeJson,
total, total,
netgame, netgame,
@ -232,7 +231,7 @@ struct GamedataMapStatsJson final
GamedataMapStatsSpbAttackJson spbattack; GamedataMapStatsSpbAttackJson spbattack;
GamedataMapStatsPlaytimeJson time; GamedataMapStatsPlaytimeJson time;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
GamedataMapStatsJson, GamedataMapStatsJson,
timeattack, timeattack,
spbattack, spbattack,
@ -245,15 +244,15 @@ struct GamedataMapJson final
GamedataMapVisitedJson visited; GamedataMapVisitedJson visited;
GamedataMapStatsJson stats; GamedataMapStatsJson stats;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapJson, visited, stats) SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapJson, visited, stats)
}; };
struct GamedataSprayCanJson final struct GamedataSprayCanJson final
{ {
std::string map; String map;
std::string color; String color;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSprayCanJson, map, color) SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSprayCanJson, map, color)
}; };
struct GamedataCupRecordsJson final struct GamedataCupRecordsJson final
@ -261,24 +260,24 @@ struct GamedataCupRecordsJson final
uint8_t bestplacement; uint8_t bestplacement;
uint8_t bestgrade; uint8_t bestgrade;
bool gotemerald; 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 struct GamedataCupJson final
{ {
std::string name; String name;
std::vector<GamedataCupRecordsJson> records; Vector<GamedataCupRecordsJson> records;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataCupJson, name, records) SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataCupJson, name, records)
}; };
struct GamedataSealedSwapJson final 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 struct GamedataJson final
@ -290,19 +289,19 @@ struct GamedataJson final
GamedataMilestonesJson milestones; GamedataMilestonesJson milestones;
GamedataPrisonEggPickupsJson prisons; GamedataPrisonEggPickupsJson prisons;
uint32_t tafolderhash; uint32_t tafolderhash;
std::vector<bool> emblems; Vector<bool> emblems;
std::vector<bool> unlockables; Vector<bool> unlockables;
std::vector<bool> unlockpending; Vector<bool> unlockpending;
std::vector<bool> conditionsets; Vector<bool> conditionsets;
GamedataChallengeGridJson challengegrid; GamedataChallengeGridJson challengegrid;
uint32_t timesBeaten; uint32_t timesBeaten;
std::unordered_map<std::string, GamedataSkinJson> skins; HashMap<String, GamedataSkinJson> skins;
std::unordered_map<std::string, GamedataMapJson> maps; HashMap<String, GamedataMapJson> maps;
std::vector<GamedataSprayCanJson> spraycans; Vector<GamedataSprayCanJson> spraycans;
std::unordered_map<std::string, GamedataCupJson> cups; HashMap<String, GamedataCupJson> cups;
std::vector<GamedataSealedSwapJson> sealedswaps; Vector<GamedataSealedSwapJson> sealedswaps;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
GamedataJson, GamedataJson,
playtime, playtime,
rings, rings,

View file

@ -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 ticcmd_t& cmd = players[displayplayers[pid]].cmd;
const boolean analog = (mode == '4' || mode == '5') ? players[displayplayers[pid]].analoginput : false; const boolean analog = (mode == '4' || mode == '5') ? players[displayplayers[pid]].analoginput : false;
const std::string prefix = fmt::format("PR{}", mode); srb2::String prefix = srb2::format("PR{}", mode);
auto gfx = [&](auto format, auto&&... args) { return prefix + fmt::format(format, args...); }; auto gfx = [&](auto format, auto&&... args) { return prefix + srb2::format(format, args...); };
auto but = [&](char key, INT32 gc, UINT32 bt) auto but = [&](char key, INT32 gc, UINT32 bt)
{ {
bool press = local ? G_PlayerInputAnalog(pid, gc, guessinput) : ((cmd.buttons & bt) == bt); bool press = local ? G_PlayerInputAnalog(pid, gc, guessinput) : ((cmd.buttons & bt) == bt);

View file

@ -165,7 +165,7 @@ void K_drawSpectatorHUD(boolean director)
if (player) if (player)
{ {
std::string label = [player] srb2::String label = [player]
{ {
if (player->flashing) if (player->flashing)
{ {
@ -183,7 +183,7 @@ void K_drawSpectatorHUD(boolean director)
if (cv_maxplayers.value) if (cv_maxplayers.value)
{ {
label += fmt::format(" [{}/{}]", numingame, cv_maxplayers.value); label += srb2::format(" [{}/{}]", numingame, cv_maxplayers.value);
} }
list.insert({{label.c_str(), "<l_animated>"}}); list.insert({{label.c_str(), "<l_animated>"}});

View file

@ -13,9 +13,9 @@
#include <array> #include <array>
#include <cstddef> #include <cstddef>
#include <unordered_map>
#include <vector>
#include "../core/hash_map.hpp"
#include "../core/vector.hpp"
#include "../rhi/rhi.hpp" #include "../rhi/rhi.hpp"
namespace srb2::hwr2 namespace srb2::hwr2
@ -77,10 +77,10 @@ class MainPaletteManager final
rhi::Handle<rhi::Texture> encore_lighttable_; rhi::Handle<rhi::Texture> encore_lighttable_;
rhi::Handle<rhi::Texture> default_colormap_; rhi::Handle<rhi::Texture> default_colormap_;
std::unordered_map<const uint8_t*, rhi::Handle<rhi::Texture>> colormaps_; srb2::HashMap<const uint8_t*, rhi::Handle<rhi::Texture>> colormaps_;
std::unordered_map<const uint8_t*, rhi::Handle<rhi::Texture>> lighttables_; srb2::HashMap<const uint8_t*, rhi::Handle<rhi::Texture>> lighttables_;
std::vector<const uint8_t*> colormaps_to_upload_; srb2::Vector<const uint8_t*> colormaps_to_upload_;
std::vector<const uint8_t*> lighttables_to_upload_; srb2::Vector<const uint8_t*> lighttables_to_upload_;
void upload_palette(rhi::Rhi& rhi); void upload_palette(rhi::Rhi& rhi);
void upload_lighttables(rhi::Rhi& rhi); void upload_lighttables(rhi::Rhi& rhi);

View file

@ -72,7 +72,7 @@ rhi::Rect srb2::hwr2::trimmed_patch_dimensions(const patch_t* patch)
return {minx, miny, static_cast<uint32_t>(maxx - minx), static_cast<uint32_t>(maxy - miny)}; return {minx, miny, static_cast<uint32_t>(maxx - minx), static_cast<uint32_t>(maxy - miny)};
} }
void srb2::hwr2::convert_patch_to_trimmed_rg8_pixels(const patch_t* patch, std::vector<uint8_t>& out) void srb2::hwr2::convert_patch_to_trimmed_rg8_pixels(const patch_t* patch, srb2::Vector<uint8_t>& out)
{ {
Rect trimmed_rect = srb2::hwr2::trimmed_patch_dimensions(patch); Rect trimmed_rect = srb2::hwr2::trimmed_patch_dimensions(patch);
if (trimmed_rect.w % 2 > 0) if (trimmed_rect.w % 2 > 0)
@ -299,7 +299,7 @@ void PatchAtlasCache::pack(Rhi& rhi)
SRB2_ASSERT(ready_for_lookup()); SRB2_ASSERT(ready_for_lookup());
// Upload atlased patches // Upload atlased patches
std::vector<uint8_t> patch_data; srb2::Vector<uint8_t> patch_data;
for (const patch_t* patch_to_upload : patches_to_upload_) for (const patch_t* patch_to_upload : patches_to_upload_)
{ {
srb2::NotNull<PatchAtlas*> atlas = find_patch(patch_to_upload); srb2::NotNull<PatchAtlas*> atlas = find_patch(patch_to_upload);

View file

@ -14,12 +14,12 @@
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <tcb/span.hpp> #include <tcb/span.hpp>
#include "../core/hash_map.hpp"
#include "../core/hash_set.hpp"
#include "../core/vector.hpp"
#include "../r_defs.h" #include "../r_defs.h"
#include "../rhi/rhi.hpp" #include "../rhi/rhi.hpp"
@ -55,7 +55,7 @@ private:
rhi::Handle<rhi::Texture> tex_; rhi::Handle<rhi::Texture> tex_;
uint32_t size_; uint32_t size_;
std::unordered_map<const patch_t*, Entry> entries_; srb2::HashMap<const patch_t*, Entry> entries_;
std::unique_ptr<stbrp_context> rp_ctx {nullptr}; std::unique_ptr<stbrp_context> rp_ctx {nullptr};
std::unique_ptr<stbrp_node[]> rp_nodes {nullptr}; std::unique_ptr<stbrp_node[]> rp_nodes {nullptr};
@ -84,11 +84,11 @@ public:
/// drawing things like sprites and 2D elements. /// drawing things like sprites and 2D elements.
class PatchAtlasCache class PatchAtlasCache
{ {
std::vector<PatchAtlas> atlases_; srb2::Vector<PatchAtlas> atlases_;
std::unordered_map<const patch_t*, size_t> patch_lookup_; srb2::HashMap<const patch_t*, size_t> patch_lookup_;
std::unordered_set<const patch_t*> patches_to_pack_; srb2::HashSet<const patch_t*> patches_to_pack_;
std::unordered_set<const patch_t*> patches_to_upload_; srb2::HashSet<const patch_t*> patches_to_upload_;
uint32_t tex_size_ = 2048; uint32_t tex_size_ = 2048;
size_t max_textures_ = 2; 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. /// during upload, but required for the RHI device's Unpack Alignment of 4 bytes.
/// @param patch the patch to convert /// @param patch the patch to convert
/// @param out the output vector, cleared before writing. /// @param out the output vector, cleared before writing.
void convert_patch_to_trimmed_rg8_pixels(const patch_t* patch, std::vector<uint8_t>& out); void convert_patch_to_trimmed_rg8_pixels(const patch_t* patch, srb2::Vector<uint8_t>& out);
} // namespace srb2::hwr2 } // namespace srb2::hwr2

View file

@ -10,12 +10,11 @@
#include "postprocess_wipe.hpp" #include "postprocess_wipe.hpp"
#include <string>
#include <fmt/format.h> #include <fmt/format.h>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <tcb/span.hpp> #include <tcb/span.hpp>
#include "../core/string.h"
#include "../f_finale.h" #include "../f_finale.h"
#include "../w_wad.h" #include "../w_wad.h"
@ -106,7 +105,7 @@ void PostprocessWipePass::prepass(Rhi& rhi)
return; 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()); lumpnum_t mask_lump = W_CheckNumForName(lumpname.c_str());
if (mask_lump == LUMPERROR) if (mask_lump == LUMPERROR)
{ {

View file

@ -181,7 +181,7 @@ Handle<Texture> FlatTextureManager::find_or_create_indexed(Rhi& rhi, lumpnum_t l
}); });
flats_.insert({lump, new_tex}); flats_.insert({lump, new_tex});
std::vector<std::array<uint8_t, 2>> flat_data; srb2::Vector<std::array<uint8_t, 2>> flat_data;
std::size_t lump_length = W_LumpLength(lump); std::size_t lump_length = W_LumpLength(lump);
flat_data.reserve(flat_size * flat_size); flat_data.reserve(flat_size * flat_size);

View file

@ -11,10 +11,10 @@
#ifndef __SRB2_HWR2_RESOURCE_MANAGEMENT_HPP__ #ifndef __SRB2_HWR2_RESOURCE_MANAGEMENT_HPP__
#define __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 "../rhi/rhi.hpp"
#include <unordered_map>
namespace srb2::hwr2 namespace srb2::hwr2
{ {
@ -27,8 +27,8 @@ class PaletteManager
#endif #endif
rhi::Handle<rhi::Texture> default_colormap_; rhi::Handle<rhi::Texture> default_colormap_;
std::unordered_map<const uint8_t*, rhi::Handle<rhi::Texture>> colormaps_; srb2::HashMap<const uint8_t*, rhi::Handle<rhi::Texture>> colormaps_;
std::unordered_map<const uint8_t*, rhi::Handle<rhi::Texture>> lighttables_; srb2::HashMap<const uint8_t*, rhi::Handle<rhi::Texture>> lighttables_;
public: public:
PaletteManager(); PaletteManager();
@ -67,9 +67,9 @@ from patch_t.
/// @brief Manages textures corresponding to specific flats indexed by lump number. /// @brief Manages textures corresponding to specific flats indexed by lump number.
class FlatTextureManager class FlatTextureManager
{ {
std::unordered_map<lumpnum_t, rhi::Handle<rhi::Texture>> flats_; srb2::HashMap<lumpnum_t, rhi::Handle<rhi::Texture>> flats_;
std::vector<lumpnum_t> to_upload_; srb2::Vector<lumpnum_t> to_upload_;
std::vector<rhi::Handle<rhi::Texture>> disposed_textures_; srb2::Vector<rhi::Handle<rhi::Texture>> disposed_textures_;
public: public:
FlatTextureManager(); FlatTextureManager();

View file

@ -11,11 +11,11 @@
#include "twodee_renderer.hpp" #include "twodee_renderer.hpp"
#include <algorithm> #include <algorithm>
#include <unordered_set>
#include <stb_rect_pack.h> #include <stb_rect_pack.h>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include "../core/hash_set.hpp"
#include "blendmode.hpp" #include "blendmode.hpp"
#include "../r_patch.h" #include "../r_patch.h"
#include "../v_video.h" #include "../v_video.h"
@ -248,7 +248,7 @@ void TwodeeRenderer::flush(Rhi& rhi, Twodee& twodee)
} }
// Stage 1 - command list patch detection // Stage 1 - command list patch detection
std::unordered_set<const patch_t*> found_patches; srb2::HashSet<const patch_t*> found_patches;
for (const auto& list : twodee) for (const auto& list : twodee)
{ {
for (const auto& cmd : list.cmds) for (const auto& cmd : list.cmds)

View file

@ -12,16 +12,16 @@
#define __SRB2_IO_STREAMS_HPP__ #define __SRB2_IO_STREAMS_HPP__
#include <cstddef> #include <cstddef>
#include <optional>
#include <stdexcept> #include <stdexcept>
#include <string>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <vector>
#include <tcb/span.hpp> #include <tcb/span.hpp>
#include <zlib.h> #include <zlib.h>
#include "../core/string.h"
#include "../core/vector.hpp"
namespace srb2::io namespace srb2::io
{ {
@ -484,13 +484,13 @@ inline void read_exact(SpanStream& stream, tcb::span<std::byte> buffer)
} }
class VecStream { class VecStream {
std::vector<std::byte> vec_; srb2::Vector<std::byte> vec_;
std::size_t head_ {0}; std::size_t head_ {0};
public: public:
VecStream() = default; VecStream() = default;
VecStream(const std::vector<std::byte>& vec) : vec_(vec) {} VecStream(const srb2::Vector<std::byte>& vec) : vec_(vec) {}
VecStream(std::vector<std::byte>&& vec) : vec_(std::move(vec)) {} VecStream(srb2::Vector<std::byte>&& vec) : vec_(std::move(vec)) {}
VecStream(const VecStream& rhs) = default; VecStream(const VecStream& rhs) = default;
VecStream(VecStream&& rhs) = default; VecStream(VecStream&& rhs) = default;
@ -549,7 +549,7 @@ public:
return head_; return head_;
} }
std::vector<std::byte>& vector() { return vec_; } srb2::Vector<std::byte>& vector() { return vec_; }
friend void read_exact(VecStream& stream, tcb::span<std::byte> buffer); friend void read_exact(VecStream& stream, tcb::span<std::byte> buffer);
}; };
@ -674,7 +674,7 @@ template <typename I,
class ZlibInputStream { class ZlibInputStream {
I inner_; I inner_;
z_stream stream_; z_stream stream_;
std::vector<std::byte> buf_; srb2::Vector<std::byte> buf_;
std::size_t buf_head_; std::size_t buf_head_;
bool zstream_initialized_; bool zstream_initialized_;
bool zstream_ended_; bool zstream_ended_;
@ -820,7 +820,7 @@ template <typename O,
class BufferedOutputStream final class BufferedOutputStream final
{ {
O inner_; O inner_;
std::vector<std::byte> buf_; srb2::Vector<std::byte> buf_;
tcb::span<const std::byte>::size_type cap_; tcb::span<const std::byte>::size_type cap_;
public: public:
@ -872,7 +872,7 @@ template <typename I,
class BufferedInputStream final class BufferedInputStream final
{ {
I inner_; I inner_;
std::vector<std::byte> buf_; srb2::Vector<std::byte> buf_;
tcb::span<std::byte>::size_type cap_; tcb::span<std::byte>::size_type cap_;
public: public:
@ -933,7 +933,7 @@ extern template class BufferedInputStream<FileStream>;
template <typename I, typename O> template <typename I, typename O>
StreamSize pipe_all(I& input, O& output) { StreamSize pipe_all(I& input, O& output) {
std::vector<std::byte> buf; srb2::Vector<std::byte> buf;
StreamSize total_written = 0; StreamSize total_written = 0;
StreamSize read_this_time = 0; StreamSize read_this_time = 0;
@ -951,7 +951,7 @@ StreamSize pipe_all(I& input, O& output) {
} }
template <typename I> template <typename I>
std::vector<std::byte> read_to_vec(I& input) { srb2::Vector<std::byte> read_to_vec(I& input) {
VecStream out; VecStream out;
pipe_all(input, out); pipe_all(input, out);
return std::move(out.vector()); return std::move(out.vector());

View file

@ -12,13 +12,14 @@
/// \file k_bans.c /// \file k_bans.c
/// \brief replacement for DooM Legacy ban system /// \brief replacement for DooM Legacy ban system
#include <fstream>
#include <stdexcept> #include <stdexcept>
#include <vector>
#include <fmt/format.h> #include <fmt/format.h>
#include <nlohmann/json.hpp> #include <tcb/span.hpp>
#include "core/json.hpp"
#include "core/string.h"
#include "io/streams.hpp"
#include "i_tcp_detail.h" // clientaddress #include "i_tcp_detail.h" // clientaddress
#include "k_bans.h" #include "k_bans.h"
#include "byteptr.h" // READ/WRITE macros #include "byteptr.h" // READ/WRITE macros
@ -34,7 +35,9 @@
#include "z_zone.h" #include "z_zone.h"
#include "i_addrinfo.h" // I_getaddrinfo #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) static mysockaddr_t *DuplicateSockAddr(const mysockaddr_t *source)
{ {
@ -43,22 +46,22 @@ static mysockaddr_t *DuplicateSockAddr(const mysockaddr_t *source)
return dup; return dup;
} }
static std::vector<banrecord_t> bans; static srb2::Vector<banrecord_t> bans;
static uint8_t allZero[PUBKEYLENGTH]; 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]; uint8_t public_key_bin[PUBKEYLENGTH];
std::string public_key = object.at("public_key"); srb2::String public_key = object.at("public_key").get<srb2::String>();
std::string ip_address = object.at("ip_address"); srb2::String ip_address = object.at("ip_address").get<srb2::String>();
time_t expires = object.at("expires"); time_t expires = object.at("expires").get<int64_t>();
UINT8 subnet_mask = object.at("subnet_mask"); UINT8 subnet_mask = object.at("subnet_mask").get<UINT8>();
std::string username = object.at("username"); srb2::String username = object.at("username").get<srb2::String>();
std::string reason = object.at("reason"); srb2::String reason = object.at("reason").get<srb2::String>();
if (!FromPrettyRRID(public_key_bin, public_key.c_str())) if (!FromPrettyRRID(public_key_bin, public_key.c_str()))
{ {
@ -86,16 +89,31 @@ void SV_LoadBans(void)
if (!server) if (!server)
return; return;
json object; JsonValue object;
srb2::String banspath { srb2::format("{}/{}", srb2home, BANFILE) };
srb2::io::BufferedInputStream<srb2::io::FileStream> 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 try
{ {
std::ifstream f(va(pandf, srb2home, BANFILE)); srb2::Vector<tcb::byte> data = srb2::io::read_to_vec(bis);
srb2::String data_s;
if (f.is_open()) data_s.reserve(data.size());
for (auto b : data)
{ {
f >> object; data_s.push_back(std::to_integer<char>(b));
} }
object = JsonValue::from_json_string(data_s);
} }
catch (const std::exception& ex) catch (const std::exception& ex)
{ {
@ -115,11 +133,11 @@ void SV_LoadBans(void)
{ {
if (object.value("version", 1) == 1) if (object.value("version", 1) == 1)
{ {
json& array = object.at("bans"); JsonValue& array = object.at("bans");
if (array.is_array()) 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) void SV_SaveBans(void)
{ {
json object = json::object(); JsonValue object = JsonValue(JsonObject());
object["version"] = 1; 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) for (banrecord_t& ban : bans)
{ {
if (ban.deleted) if (ban.deleted)
continue; continue;
array.push_back({ array.push_back(JsonObject {
{"public_key", GetPrettyRRID(ban.public_key, false)}, {"public_key", GetPrettyRRID(ban.public_key, false)},
{"ip_address", SOCK_AddrToStr(ban.address)}, {"ip_address", SOCK_AddrToStr(ban.address)},
{"subnet_mask", ban.mask}, {"subnet_mask", ban.mask},
{"expires", ban.expires}, {"expires", static_cast<int64_t>(ban.expires)},
{"username", ban.username}, {"username", ban.username},
{"reason", ban.reason}, {"reason", ban.reason},
}); });
} }
srb2::String json_string = object.to_json_string();
srb2::String banfile_path = srb2::format("{}/{}", srb2home, BANFILE);
try 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) catch (const std::exception& ex)
{ {
@ -345,10 +368,10 @@ static void SV_BanSearch(boolean remove)
const char* stringaddress = SOCK_AddrToStr(ban.address); const char* stringaddress = SOCK_AddrToStr(ban.address);
const char* stringkey = GetPrettyRRID(ban.public_key, true); const char* stringkey = GetPrettyRRID(ban.public_key, true);
std::string recordprint = fmt::format( srb2::String recordprint = srb2::format(
"{}{} - {} [{}] - {}", "{}{} - {} [{}] - {}",
stringaddress, stringaddress,
ban.mask && ban.mask != 32 ? fmt::format("/{}", ban.mask) : "", ban.mask && ban.mask != 32 ? srb2::format("/{}", ban.mask) : "",
ban.username, ban.username,
stringkey, stringkey,
ban.reason ban.reason
@ -359,7 +382,7 @@ static void SV_BanSearch(boolean remove)
if (ban.expires < now) if (ban.expires < now)
recordprint += " - EXPIRED"; recordprint += " - EXPIRED";
else 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()); CONS_Printf("%s\n", recordprint.c_str());

View file

@ -12,11 +12,8 @@
#include "k_credits.h" #include "k_credits.h"
#include <string>
#include <vector>
#include <algorithm> #include <algorithm>
#include <fmt/format.h> #include <fmt/format.h>
#include <nlohmann/json.hpp>
#include "doomdef.h" #include "doomdef.h"
#include "doomstat.h" #include "doomstat.h"
@ -59,7 +56,9 @@
#include "r_main.h" #include "r_main.h"
#include "m_easing.h" #include "m_easing.h"
using nlohmann::json; using srb2::JsonArray;
using srb2::JsonObject;
using srb2::JsonValue;
enum credits_slide_types_e enum credits_slide_types_e
{ {
@ -75,14 +74,14 @@ enum credits_slide_types_e
struct credits_slide_s struct credits_slide_s
{ {
credits_slide_types_e type; credits_slide_types_e type;
std::string label; srb2::String label;
std::vector<std::string> strings; srb2::Vector<srb2::String> strings;
size_t strings_height; size_t strings_height;
boolean play_demo_afterwards; boolean play_demo_afterwards;
int fade_out_music; int fade_out_music;
}; };
static std::vector<struct credits_slide_s> g_credits_slides; static srb2::Vector<struct credits_slide_s> g_credits_slides;
struct credits_star_s struct credits_star_s
{ {
@ -94,10 +93,10 @@ struct credits_star_s
static struct credits_s static struct credits_s
{ {
size_t current_slide; size_t current_slide;
std::vector<UINT16> demo_maps; srb2::Vector<UINT16> demo_maps;
boolean skip; boolean skip;
std::vector<struct credits_star_s> stars; srb2::Vector<struct credits_star_s> stars;
fixed_t transition; fixed_t transition;
fixed_t transition_prev; fixed_t transition_prev;
@ -105,7 +104,7 @@ static struct credits_s
tic_t animation_timer; tic_t animation_timer;
std::vector<std::vector<std::string>> split_slide_strings; srb2::Vector<srb2::Vector<srb2::String>> split_slide_strings;
size_t split_slide_id; size_t split_slide_id;
tic_t split_slide_delay; tic_t split_slide_delay;
@ -142,12 +141,14 @@ void F_LoadCreditsDefinitions(void)
size_t credits_lump_len = W_LumpLength(credits_lump_id); size_t credits_lump_len = W_LumpLength(credits_lump_id);
const char *credits_lump = static_cast<const char *>( W_CacheLumpNum(credits_lump_id, PU_CACHE) ); const char *credits_lump = static_cast<const char *>( W_CacheLumpNum(credits_lump_id, PU_CACHE) );
json credits_array = json::parse(credits_lump, credits_lump + credits_lump_len); srb2::String json_string { credits_lump, credits_lump_len };
if (credits_array.is_array() == false) 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"); I_Error("credits_def parse error: Not a JSON array");
return; return;
} }
JsonArray credits_array = credits_parsed.as_array();
if (credits_array.size() == 0) if (credits_array.size() == 0)
{ {
@ -156,11 +157,11 @@ void F_LoadCreditsDefinitions(void)
try try
{ {
for (json& slide_obj : credits_array) for (JsonValue& slide_obj : credits_array)
{ {
struct credits_slide_s slide; 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") if (type_str == "scroll")
{ {
@ -196,18 +197,19 @@ void F_LoadCreditsDefinitions(void)
throw std::runtime_error("unexpected type name '" + type_str + "'"); 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; slide.strings_height = 0;
if (slide_obj.contains("strings")) if (slide_obj.contains("strings"))
{ {
json strings_array = slide_obj.at("strings"); JsonValue strings_value = slide_obj.at("strings");
if (strings_array.is_array() == true) if (strings_value.is_array() == true)
{ {
JsonArray& strings_array = strings_value.as_array();
for (size_t i = 0; i < strings_array.size(); i++) 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<srb2::String>() );
if (slide.type == CRED_TYPE_SCROLL) 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 max_strings_per_screen = (num_strings - 1) / num_sub_screens + 1;
size_t str_id = 0; size_t str_id = 0;
std::vector<std::string> screen_strings; srb2::Vector<srb2::String> screen_strings;
if (max_strings_per_screen == kMaxSlideStrings if (max_strings_per_screen == kMaxSlideStrings
&& num_strings % kMaxSlideStrings == 1) && num_strings % kMaxSlideStrings == 1)
@ -342,24 +344,24 @@ static void F_InitCreditsSlide(void)
#endif #endif
) )
{ {
slide->strings.push_back("#" + std::string(def->title)); slide->strings.push_back("#" + srb2::String(def->title));
slide->strings_height += 12; slide->strings_height += 12;
if (def->author) 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; slide->strings_height += 12;
} }
if (def->source) 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; slide->strings_height += 12;
} }
if (def->composers) 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; slide->strings_height += 12;
} }
@ -478,7 +480,7 @@ void F_ContinueCredits(void)
static UINT16 F_PickRandomCreditsDemoMap(void) static UINT16 F_PickRandomCreditsDemoMap(void)
{ {
std::vector<UINT16> allowedMaps; srb2::Vector<UINT16> allowedMaps;
for (INT32 i = 0; i < basenummapheaders; i++) // Only take from the base game. for (INT32 i = 0; i < basenummapheaders; i++) // Only take from the base game.
{ {
@ -911,7 +913,7 @@ static void F_DrawCreditsScroll(void)
} }
else else
{ {
std::string new_str = str; srb2::String new_str = str;
if (new_str.at(0) == '*') if (new_str.at(0) == '*')
{ {
@ -1017,7 +1019,7 @@ static void F_DrawCreditsSlide(void)
return; return;
} }
const std::vector<std::string> *slide_strings = &g_credits.split_slide_strings[ g_credits.split_slide_id ]; const srb2::Vector<srb2::String> *slide_strings = &g_credits.split_slide_strings[ g_credits.split_slide_id ];
const fixed_t strings_height = slide_strings->size() * 30 * FRACUNIT; const fixed_t strings_height = slide_strings->size() * 30 * FRACUNIT;
fixed_t y = 0; fixed_t y = 0;
@ -1113,7 +1115,7 @@ static void F_DrawCreditsTyler52(void)
V_DrawFadeScreen(0xFF00, 31 - (g_credits.tyler_fade * 4)); 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( const fixed_t memory_width = V_StringScaledWidth(
FRACUNIT, FRACUNIT, FRACUNIT, FRACUNIT, FRACUNIT, FRACUNIT,
0, LSLOW_FONT, 0, LSLOW_FONT,
@ -1126,7 +1128,7 @@ static void F_DrawCreditsTyler52(void)
memory_str.c_str() memory_str.c_str()
); );
std::string tyler_str = "Tyler52"; srb2::String tyler_str = "Tyler52";
const fixed_t tyler_width = V_StringScaledWidth( const fixed_t tyler_width = V_StringScaledWidth(
FRACUNIT, FRACUNIT, FRACUNIT, FRACUNIT, FRACUNIT, FRACUNIT,
0, LSHI_FONT, 0, LSHI_FONT,

View file

@ -14,9 +14,10 @@
#include "k_dialogue.hpp" #include "k_dialogue.hpp"
#include "k_dialogue.h" #include "k_dialogue.h"
#include <string>
#include <algorithm> #include <algorithm>
#include <string_view>
#include "core/string.h"
#include "info.h" #include "info.h"
#include "sounds.h" #include "sounds.h"
#include "g_game.h" #include "g_game.h"
@ -43,7 +44,7 @@ void Dialogue::Typewriter::ClearText(void)
textDest.clear(); textDest.clear();
} }
void Dialogue::Typewriter::NewText(std::string newText) void Dialogue::Typewriter::NewText(const srb2::String& newText)
{ {
text.clear(); text.clear();
@ -174,7 +175,7 @@ void Dialogue::SetSpeaker(void)
typewriter.voiceSfx = sfx_ktalk; typewriter.voiceSfx = sfx_ktalk;
} }
void Dialogue::SetSpeaker(std::string skinName, int portraitID) void Dialogue::SetSpeaker(srb2::String skinName, int portraitID)
{ {
Init(); 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(); Init();
@ -472,7 +473,7 @@ void Dialogue::Draw(void)
.flags(V_VFLIP|V_FLIP) .flags(V_VFLIP|V_FLIP)
.patch(patchCache["TUTDIAGE"]); .patch(patchCache["TUTDIAGE"]);
std::string intertext = "<large>"; srb2::String intertext = "<large>";
drawer drawer
.xy(10 - BASEVIDWIDTH, -3-32) .xy(10 - BASEVIDWIDTH, -3-32)
@ -486,7 +487,7 @@ void Dialogue::Draw(void)
.patch(patchCache["TUTDIAG2"]); .patch(patchCache["TUTDIAG2"]);
if (Held()) if (Held())
intertext += "<z_pressed>"; intertext += "<z_pressed>";
else else
intertext += "<z_animated>"; intertext += "<z_animated>";

View file

@ -14,10 +14,10 @@
#ifndef __K_DIALOGUE_HPP__ #ifndef __K_DIALOGUE_HPP__
#define __K_DIALOGUE_HPP__ #define __K_DIALOGUE_HPP__
#include <string>
#include <string_view> #include <string_view>
#include <unordered_map>
#include "core/hash_map.hpp"
#include "core/string.h"
#include "doomdef.h" #include "doomdef.h"
#include "doomtype.h" #include "doomtype.h"
#include "typedef.h" #include "typedef.h"
@ -33,8 +33,8 @@ public:
static constexpr fixed_t kSlideSpeed = FRACUNIT / (TICRATE / 5); static constexpr fixed_t kSlideSpeed = FRACUNIT / (TICRATE / 5);
void SetSpeaker(void); void SetSpeaker(void);
void SetSpeaker(std::string skinName, int portraitID); void SetSpeaker(srb2::String skinName, int portraitID);
void SetSpeaker(std::string name, patch_t *patch, UINT8 *colormap, sfxenum_t voice); void SetSpeaker(srb2::String name, patch_t *patch, UINT8 *colormap, sfxenum_t voice);
void NewText(std::string_view newText); void NewText(std::string_view newText);
@ -60,8 +60,8 @@ public:
static constexpr fixed_t kTextSpeedDefault = FRACUNIT; static constexpr fixed_t kTextSpeedDefault = FRACUNIT;
static constexpr fixed_t kTextPunctPause = (FRACUNIT * TICRATE * 2) / 5; static constexpr fixed_t kTextPunctPause = (FRACUNIT * TICRATE * 2) / 5;
std::string text; srb2::String text;
std::string textDest; srb2::String textDest;
fixed_t textTimer; fixed_t textTimer;
fixed_t textSpeed; fixed_t textSpeed;
@ -71,7 +71,7 @@ public:
sfxenum_t voiceSfx; sfxenum_t voiceSfx;
bool syllable; bool syllable;
void NewText(std::string newText); void NewText(const srb2::String& newText);
void ClearText(void); void ClearText(void);
void WriteText(void); void WriteText(void);
@ -86,11 +86,11 @@ private:
patch_t *bgPatch; patch_t *bgPatch;
patch_t *confirmPatch; patch_t *confirmPatch;
std::string speaker; srb2::String speaker;
patch_t *portrait; patch_t *portrait;
UINT8 *portraitColormap; UINT8 *portraitColormap;
std::unordered_map<std::string_view, patch_t*> patchCache; srb2::HashMap<std::string_view, patch_t*> patchCache;
bool active; bool active;
fixed_t slide; fixed_t slide;

View file

@ -11,11 +11,12 @@
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <vector>
#include <deque> #include <deque>
#include <fmt/format.h> #include <fmt/format.h>
#include "core/string.h"
#include "core/vector.hpp"
#include "k_hud.h" #include "k_hud.h"
#include "k_kart.h" #include "k_kart.h"
#include "k_battle.h" #include "k_battle.h"
@ -6332,21 +6333,21 @@ typedef enum
typedef struct typedef struct
{ {
std::string text; srb2::String text;
sfxenum_t sound; sfxenum_t sound;
} message_t; } message_t;
struct messagestate_t struct messagestate_t
{ {
std::deque<std::string> messages; std::deque<srb2::String> messages;
std::string objective = ""; srb2::String objective = "";
tic_t timer = 0; tic_t timer = 0;
boolean persist = false; boolean persist = false;
messagemode_t mode = MM_IN; messagemode_t mode = MM_IN;
const tic_t speedyswitch = 2*TICRATE; const tic_t speedyswitch = 2*TICRATE;
const tic_t lazyswitch = 4*TICRATE; const tic_t lazyswitch = 4*TICRATE;
void add(std::string msg) void add(srb2::String msg)
{ {
messages.push_back(msg); messages.push_back(msg);
} }
@ -6384,7 +6385,7 @@ struct messagestate_t
switch (mode) switch (mode)
{ {
case MM_IN: case MM_IN:
if (timer > messages[0].length()) if (timer > messages[0].size())
switch_mode(MM_HOLD); switch_mode(MM_HOLD);
break; break;
case MM_HOLD: case MM_HOLD:
@ -6394,7 +6395,7 @@ struct messagestate_t
switch_mode(MM_OUT); switch_mode(MM_OUT);
break; break;
case MM_OUT: case MM_OUT:
if (timer > messages[0].length()) if (timer > messages[0].size())
next(); next();
break; break;
} }

View file

@ -12,6 +12,7 @@
#include "k_podium.h" #include "k_podium.h"
#include "core/string.h"
#include "doomdef.h" #include "doomdef.h"
#include "d_main.h" #include "d_main.h"
#include "d_netcmd.h" #include "d_netcmd.h"
@ -51,8 +52,6 @@
#include "k_hud.h" #include "k_hud.h"
#include <string>
typedef enum typedef enum
{ {
PODIUM_ST_CONGRATS_SLIDEIN, PODIUM_ST_CONGRATS_SLIDEIN,
@ -652,7 +651,7 @@ void podiumData_s::Draw(void)
} }
{ {
std::string emeraldName; srb2::String emeraldName;
if (emeraldNum > 7) if (emeraldNum > 7)
{ {
emeraldName = (useWhiteFrame ? "K_SUPER2" : "K_SUPER1"); emeraldName = (useWhiteFrame ? "K_SUPER2" : "K_SUPER1");

View file

@ -12,10 +12,13 @@
/// \brief implements methods for profiles etc. /// \brief implements methods for profiles etc.
#include <algorithm> #include <algorithm>
#include <filesystem>
#include <exception> #include <exception>
#include <fmt/format.h> #include <fmt/format.h>
#include "core/string.h"
#include "core/vector.hpp"
#include "io/streams.hpp" #include "io/streams.hpp"
#include "doomtype.h" #include "doomtype.h"
#include "d_main.h" // pandf #include "d_main.h" // pandf
@ -253,7 +256,6 @@ void PR_InitNewProfile(void)
void PR_SaveProfiles(void) void PR_SaveProfiles(void)
{ {
namespace fs = std::filesystem; namespace fs = std::filesystem;
using json = nlohmann::json;
using namespace srb2; using namespace srb2;
namespace io = srb2::io; namespace io = srb2::io;
@ -271,13 +273,13 @@ void PR_SaveProfiles(void)
profile_t* cprof = profilesList[i]; profile_t* cprof = profilesList[i];
jsonprof.version = PROFILEVER; 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->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)); std::copy(std::begin(cprof->secret_key), std::end(cprof->secret_key), std::begin(jsonprof.secretkey));
jsonprof.playername = std::string(cprof->playername); jsonprof.playername = String(cprof->playername);
jsonprof.skinname = std::string(cprof->skinname); jsonprof.skinname = String(cprof->skinname);
jsonprof.colorname = std::string(skincolors[cprof->color].name); jsonprof.colorname = String(skincolors[cprof->color].name);
jsonprof.followername = std::string(cprof->follower); jsonprof.followername = String(cprof->follower);
if (cprof->followercolor == FOLLOWERCOLOR_MATCH) if (cprof->followercolor == FOLLOWERCOLOR_MATCH)
{ {
jsonprof.followercolorname = "Match"; jsonprof.followercolorname = "Match";
@ -292,11 +294,11 @@ void PR_SaveProfiles(void)
} }
else if (cprof->followercolor >= numskincolors) else if (cprof->followercolor >= numskincolors)
{ {
jsonprof.followercolorname = std::string(); jsonprof.followercolorname = String();
} }
else else
{ {
jsonprof.followercolorname = std::string(skincolors[cprof->followercolor].name); jsonprof.followercolorname = String(skincolors[cprof->followercolor].name);
} }
jsonprof.records.wins = cprof->wins; jsonprof.records.wins = cprof->wins;
jsonprof.records.rounds = cprof->rounds; jsonprof.records.rounds = cprof->rounds;
@ -310,7 +312,7 @@ void PR_SaveProfiles(void)
for (size_t j = 0; j < num_gamecontrols; j++) for (size_t j = 0; j < num_gamecontrols; j++)
{ {
std::vector<int32_t> mappings; srb2::Vector<int32_t> mappings;
for (size_t k = 0; k < MAXINPUTMAPPING; k++) for (size_t k = 0; k < MAXINPUTMAPPING; k++)
{ {
mappings.push_back(cprof->controls[j][k]); mappings.push_back(cprof->controls[j][k]);
@ -321,16 +323,18 @@ void PR_SaveProfiles(void)
ng.profiles.emplace_back(std::move(jsonprof)); ng.profiles.emplace_back(std::move(jsonprof));
} }
std::vector<uint8_t> ubjson = json::to_ubjson(ng); JsonValue ngv;
to_json(ngv, ng);
Vector<std::byte> ubjson = ngv.to_ubjson();
std::string realpath = fmt::format("{}/{}", srb2home, PROFILESFILE); String realpath = srb2::format("{}/{}", srb2home, PROFILESFILE);
std::string bakpath = fmt::format("{}.bak", realpath); String bakpath = srb2::format("{}.bak", realpath);
if (fs::exists(realpath)) if (fs::exists(fs::path(static_cast<std::string_view>(realpath))))
{ {
try try
{ {
fs::rename(realpath, bakpath); fs::rename(fs::path(static_cast<std::string_view>(realpath)), fs::path(static_cast<std::string_view>(bakpath)));
} }
catch (const fs::filesystem_error& ex) catch (const fs::filesystem_error& ex)
{ {
@ -349,7 +353,7 @@ void PR_SaveProfiles(void)
io::write(static_cast<uint8_t>(0), file); // reserved2 io::write(static_cast<uint8_t>(0), file); // reserved2
io::write(static_cast<uint8_t>(0), file); // reserved3 io::write(static_cast<uint8_t>(0), file); // reserved3
io::write(static_cast<uint8_t>(0), file); // reserved4 io::write(static_cast<uint8_t>(0), file); // reserved4
io::write_exact(file, tcb::as_bytes(tcb::make_span(ubjson))); io::write_exact(file, ubjson);
file.close(); file.close();
} }
catch (const std::exception& ex) catch (const std::exception& ex)
@ -367,7 +371,6 @@ void PR_LoadProfiles(void)
namespace fs = std::filesystem; namespace fs = std::filesystem;
using namespace srb2; using namespace srb2;
namespace io = srb2::io; namespace io = srb2::io;
using json = nlohmann::json;
profile_t *dprofile = PR_MakeProfile( profile_t *dprofile = PR_MakeProfile(
PROFILEDEFAULTNAME, PROFILEDEFAULTNAME,
@ -378,7 +381,7 @@ void PR_LoadProfiles(void)
true true
); );
std::string datapath {fmt::format("{}/{}", srb2home, PROFILESFILE)}; String datapath { srb2::format("{}/{}", srb2home, PROFILESFILE) };
io::BufferedInputStream<io::FileStream> bis; io::BufferedInputStream<io::FileStream> bis;
try try
@ -413,11 +416,10 @@ void PR_LoadProfiles(void)
throw std::domain_error("Header is incompatible"); throw std::domain_error("Header is incompatible");
} }
std::vector<std::byte> remainder = io::read_to_vec(bis); Vector<std::byte> remainder = io::read_to_vec(bis);
// safety: std::byte repr is always uint8_t 1-byte aligned // safety: std::byte repr is always uint8_t 1-byte aligned
tcb::span<uint8_t> remainder_as_u8 = tcb::span((uint8_t*)remainder.data(), remainder.size()); JsonValue parsed = JsonValue::from_ubjson(remainder);
json parsed = json::from_ubjson(remainder_as_u8); from_json(parsed, js);
js = parsed.template get<ProfilesJson>();
} }
catch (const std::exception& ex) catch (const std::exception& ex)
{ {

View file

@ -25,10 +25,10 @@
#include <array> #include <array>
#include <cstdint> #include <cstdint>
#include <string>
#include <vector>
#include <nlohmann/json.hpp> #include "core/json.hpp"
#include "core/string.h"
#include "core/vector.hpp"
namespace srb2 namespace srb2
{ {
@ -38,7 +38,7 @@ struct ProfileRecordsJson
uint32_t wins; uint32_t wins;
uint32_t rounds; uint32_t rounds;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ProfileRecordsJson, wins, rounds) SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ProfileRecordsJson, wins, rounds)
}; };
struct ProfilePreferencesJson struct ProfilePreferencesJson
@ -50,9 +50,8 @@ struct ProfilePreferencesJson
bool autoring; bool autoring;
bool rumble; bool rumble;
uint8_t fov; uint8_t fov;
tm test;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
ProfilePreferencesJson, ProfilePreferencesJson,
kickstartaccel, kickstartaccel,
autoroulette, autoroulette,
@ -67,19 +66,19 @@ struct ProfilePreferencesJson
struct ProfileJson struct ProfileJson
{ {
uint32_t version; uint32_t version;
std::string profilename; String profilename;
std::string playername; String playername;
std::array<uint8_t, 32> publickey = {{}}; std::array<uint8_t, 32> publickey = {{}};
std::array<uint8_t, 64> secretkey = {{}}; std::array<uint8_t, 64> secretkey = {{}};
std::string skinname; String skinname;
std::string colorname; String colorname;
std::string followername; String followername;
std::string followercolorname; String followercolorname;
ProfileRecordsJson records; ProfileRecordsJson records;
ProfilePreferencesJson preferences; ProfilePreferencesJson preferences;
std::vector<std::vector<int32_t>> controls = {}; Vector<Vector<int32_t>> controls = {};
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT( SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
ProfileJson, ProfileJson,
version, version,
profilename, profilename,
@ -98,9 +97,9 @@ struct ProfileJson
struct ProfilesJson struct ProfilesJson
{ {
std::vector<ProfileJson> profiles; Vector<ProfileJson> profiles;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ProfilesJson, profiles) SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ProfilesJson, profiles)
}; };
} // namespace srb2 } // namespace srb2

View file

@ -24,10 +24,12 @@
#include "cxxutil.hpp" #include "cxxutil.hpp"
#include <algorithm> #include <algorithm>
#include <vector>
#include <fmt/format.h> #include <fmt/format.h>
#include "core/string.h"
#include "core/vector.hpp"
// The number of sparkles per waypoint connection in the waypoint visualisation // The number of sparkles per waypoint connection in the waypoint visualisation
static const UINT32 SPARKLES_PER_CONNECTION = 16U; static const UINT32 SPARKLES_PER_CONNECTION = 16U;
@ -2377,8 +2379,8 @@ static BlockItReturn_t K_TrackWaypointNearOffroad(line_t *line)
struct complexity_sneaker_s struct complexity_sneaker_s
{ {
fixed_t bbox[4]; fixed_t bbox[4];
//std::vector<sector_t *> sectors; //srb2::Vector<sector_t *> sectors;
//std::vector<mapthing_t *> things; //srb2::Vector<mapthing_t *> things;
complexity_sneaker_s(sector_t *sec) 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)); 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 [{}]: r: {:.2f}, d: {:.2f}, w: {:.2f}, r*d*w: {:.2f}, DELTA: {}\n",
turn_id, turn_id,
FixedToFloat(radius_factor), FixedToFloat(radius_factor),
@ -2644,7 +2646,7 @@ static INT32 K_CalculateTrackComplexity(void)
trackcomplexity += (delta / FRACUNIT); trackcomplexity += (delta / FRACUNIT);
} }
std::vector<complexity_sneaker_s> sneaker_panels; srb2::Vector<complexity_sneaker_s> sneaker_panels;
for (size_t i = 0; i < numsectors; i++) for (size_t i = 0; i < numsectors; i++)
{ {

View file

@ -10,10 +10,8 @@
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef>
#include <unordered_map>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <vector>
#include <fmt/format.h> #include <fmt/format.h>
@ -21,6 +19,9 @@ extern "C" {
#include "blua/lua.h" #include "blua/lua.h"
}; };
#include "core/hash_map.hpp"
#include "core/string.h"
#include "core/vector.hpp"
#include "v_draw.hpp" #include "v_draw.hpp"
#include "command.h" #include "command.h"
@ -58,7 +59,7 @@ struct lua_timer_t
namespace namespace
{ {
std::unordered_map<std::string, lua_timer_t> g_tic_timers; srb2::HashMap<srb2::String, lua_timer_t> g_tic_timers;
}; // namespace }; // namespace
@ -156,7 +157,7 @@ void LUA_RenderTimers(void)
return; return;
} }
std::vector<decltype(g_tic_timers)::iterator> view; srb2::Vector<decltype(g_tic_timers)::Iter> view;
view.reserve(g_tic_timers.size()); view.reserve(g_tic_timers.size());
auto color_flag = [](double t) auto color_flag = [](double t)

View file

@ -14,13 +14,13 @@
#include <cctype> #include <cctype>
#include <fstream> #include <fstream>
#include <stdexcept> #include <stdexcept>
#include <string>
#include <utility> #include <utility>
#include <variant> #include <variant>
#include <vector>
#include "modp_b64/modp_b64.h" #include "modp_b64/modp_b64.h"
#include "core/string.h"
#include "core/vector.hpp"
#include "cxxutil.hpp" #include "cxxutil.hpp"
#include "command.h" #include "command.h"
@ -43,12 +43,13 @@ namespace
constexpr const UINT8 kRRSalt[17] = "0L4rlK}{9ay6'VJS"; constexpr const UINT8 kRRSalt[17] = "0L4rlK}{9ay6'VJS";
std::array<UINT8, M_PW_BUF_SIZE> decode_hash(std::string encoded) std::array<UINT8, M_PW_BUF_SIZE> decode_hash(srb2::String encoded)
{ {
std::array<UINT8, M_PW_BUF_SIZE> decoded; std::array<UINT8, M_PW_BUF_SIZE> decoded;
if (modp::b64_decode(encoded).size() != decoded.size()) std::string encoded_stl { static_cast<std::string_view>(encoded) };
if (modp::b64_decode(encoded_stl).size() != decoded.size())
throw std::invalid_argument("hash is incorrectly sized"); 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; return decoded;
} }
@ -60,7 +61,7 @@ struct Pw
const std::array<UINT8, M_PW_BUF_SIZE> hash_; const std::array<UINT8, M_PW_BUF_SIZE> hash_;
}; };
std::vector<Pw> passwords; srb2::Vector<Pw> passwords;
// m_cond.c // m_cond.c
template <typename F> template <typename F>
@ -629,8 +630,8 @@ try_password_e M_TryPassword(const char *password, boolean conditions)
using var = std::variant<std::monostate, condition_t*, Pw*>; using var = std::variant<std::monostate, condition_t*, Pw*>;
// Normalize input casing // Normalize input casing
std::string key = password; srb2::String key = password;
strlwr(key.data()); strlwr((char*)key.data());
UINT8 key_hash[M_PW_HASH_SIZE]; UINT8 key_hash[M_PW_HASH_SIZE];
M_HashPassword(key_hash, key.c_str(), kRRSalt); 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) boolean M_TryExactPassword(const char *password, const char *encodedhash)
{ {
// Normalize input casing // Normalize input casing
std::string key = password; srb2::String key = password;
strlwr(key.data()); strlwr((char*)key.data());
UINT8 key_hash[M_PW_HASH_SIZE]; UINT8 key_hash[M_PW_HASH_SIZE];
M_HashPassword(key_hash, key.c_str(), kRRSalt); M_HashPassword(key_hash, key.c_str(), kRRSalt);

View file

@ -17,11 +17,11 @@
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <string>
#include <vector>
#include <tcb/span.hpp> #include <tcb/span.hpp>
#include "../core/string.h"
#include "../core/vector.hpp"
#include "../audio/sample.hpp" #include "../audio/sample.hpp"
namespace srb2::media namespace srb2::media
@ -49,7 +49,7 @@ public:
int frame_rate; int frame_rate;
}; };
std::string file_name; srb2::String file_name;
std::optional<std::size_t> max_size; // file size limit std::optional<std::size_t> max_size; // file size limit
std::optional<std::chrono::duration<float>> max_duration; std::optional<std::chrono::duration<float>> max_duration;
@ -63,7 +63,7 @@ public:
{ {
using instance_t = std::unique_ptr<StagingVideoFrame>; using instance_t = std::unique_ptr<StagingVideoFrame>;
std::vector<uint8_t> screen; srb2::Vector<uint8_t> screen;
uint32_t width, height; uint32_t width, height;
int pts; int pts;

View file

@ -10,10 +10,10 @@
#include <filesystem> #include <filesystem>
#include <sstream> #include <sstream>
#include <string>
#include <fmt/format.h> #include <fmt/format.h>
#include "../core/string.h"
#include "../cxxutil.hpp" #include "../cxxutil.hpp"
#include "avrecorder_impl.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_) if (max_size_ && container.size() > *max_size_)
{ {
const std::string line = fmt::format( const srb2::String line = srb2::format(
"Video size has exceeded limit {} > {} ({}%)." "Video size has exceeded limit {} > {} ({}%)."
" This should not happen, please report this bug.\n", " This should not happen, please report this bug.\n",
container.size(), container.size(),
@ -100,7 +100,7 @@ void AVRecorder::draw_statistics() const
{ {
SRB2_ASSERT(impl_->video_encoder_ != nullptr); 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( V_DrawThinString(
x, x,
@ -144,7 +144,7 @@ void AVRecorder::draw_statistics() const
return 0; return 0;
}(); }();
draw(200, fmt::format("{:.0f}", fps), fps_color); draw(200, srb2::format("{:.0f}", fps), fps_color);
draw(230, fmt::format("{:.1f}s", impl_->container_->duration().count())); draw(230, srb2::format("{:.1f}s", impl_->container_->duration().count()));
draw(260, fmt::format("{:.1f} MB", size / kMb), mb_color); draw(260, srb2::format("{:.1f} MB", size / kMb), mb_color);
} }

View file

@ -19,8 +19,8 @@
#include <mutex> #include <mutex>
#include <optional> #include <optional>
#include <thread> #include <thread>
#include <vector>
#include "../core/string.h"
#include "../i_time.h" #include "../i_time.h"
#include "avrecorder.hpp" #include "avrecorder.hpp"
#include "container.hpp" #include "container.hpp"
@ -57,7 +57,7 @@ public:
using frame_type = StagingVideoFrame::instance_t; using frame_type = StagingVideoFrame::instance_t;
}; };
std::vector<typename Traits<T>::frame_type> vec_; srb2::Vector<typename Traits<T>::frame_type> vec_;
// This number only decrements once a frame has // This number only decrements once a frame has
// actually been written to container. // actually been written to container.

View file

@ -19,7 +19,7 @@
using namespace srb2::media; 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"); file_ = std::fopen(name(), "wb");

View file

@ -12,7 +12,8 @@
#define __SRB2_MEDIA_CFILE_HPP__ #define __SRB2_MEDIA_CFILE_HPP__
#include <cstdio> #include <cstdio>
#include <string>
#include "../core/string.h"
namespace srb2::media namespace srb2::media
{ {
@ -20,7 +21,7 @@ namespace srb2::media
class CFile class CFile
{ {
public: public:
CFile(const std::string file_name); CFile(const srb2::String& file_name);
~CFile(); ~CFile();
operator std::FILE*() const { return file_; } operator std::FILE*() const { return file_; }
@ -28,7 +29,7 @@ public:
const char* name() const { return name_.c_str(); } const char* name() const { return name_.c_str(); }
private: private:
std::string name_; srb2::String name_;
std::FILE* file_; std::FILE* file_;
}; };

View file

@ -14,8 +14,8 @@
#include <chrono> #include <chrono>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <string>
#include "../core/string.h"
#include "audio_encoder.hpp" #include "audio_encoder.hpp"
#include "video_encoder.hpp" #include "video_encoder.hpp"
@ -30,7 +30,7 @@ public:
struct Config struct Config
{ {
std::string file_name; srb2::String file_name;
dtor_cb_t destructor_callback; dtor_cb_t destructor_callback;
}; };

View file

@ -13,11 +13,11 @@
#include <map> #include <map>
#include <optional> #include <optional>
#include <string>
#include <string_view> #include <string_view>
#include <unordered_map>
#include <vector>
#include "../core/hash_map.hpp"
#include "../core/string.h"
#include "../core/vector.hpp"
#include "../command.h" #include "../command.h"
namespace srb2::media namespace srb2::media
@ -26,7 +26,7 @@ namespace srb2::media
class Options class Options
{ {
public: public:
using map_t = std::unordered_map<std::string, consvar_t>; using map_t = srb2::HashMap<srb2::String, consvar_t>;
template <typename T> template <typename T>
struct Range struct Range
@ -46,7 +46,7 @@ public:
static consvar_t values(const char* default_value, const Range<T> range, std::map<std::string_view, T> list = {}); static consvar_t values(const char* default_value, const Range<T> range, std::map<std::string_view, T> list = {});
private: private:
static std::vector<consvar_t*> cvars_; static srb2::Vector<consvar_t*> cvars_;
const char* prefix_; const char* prefix_;
map_t map_; map_t map_;
@ -54,6 +54,11 @@ private:
const consvar_t& cvar(const char* option) const; const consvar_t& cvar(const char* option) const;
}; };
// clang-format off
extern template consvar_t Options::values(const char* default_value, const Range<int> range, std::map<std::string_view, int> list);
extern template consvar_t Options::values(const char* default_value, const Range<float> range, std::map<std::string_view, float> list);
// clang-format on
}; // namespace srb2::media }; // namespace srb2::media
#endif // __SRB2_MEDIA_OPTIONS_HPP__ #endif // __SRB2_MEDIA_OPTIONS_HPP__

View file

@ -12,6 +12,7 @@
#include <vpx/vpx_encoder.h> #include <vpx/vpx_encoder.h>
#include "../core/vector.hpp"
#include "options.hpp" #include "options.hpp"
#include "vorbis.hpp" #include "vorbis.hpp"
#include "vp8.hpp" #include "vp8.hpp"
@ -23,7 +24,7 @@ using namespace srb2::media;
// to be defined in the same translation unit as // to be defined in the same translation unit as
// Options::cvars_ to guarantee initialization order. // Options::cvars_ to guarantee initialization order.
std::vector<consvar_t*> Options::cvars_; srb2::Vector<consvar_t*> Options::cvars_;
// clang-format off // clang-format off
const Options VorbisEncoder::options_("vorbis", { const Options VorbisEncoder::options_("vorbis", {

View file

@ -11,11 +11,11 @@
#ifndef __SRB2_MEDIA_VORBIS_ERROR_HPP__ #ifndef __SRB2_MEDIA_VORBIS_ERROR_HPP__
#define __SRB2_MEDIA_VORBIS_ERROR_HPP__ #define __SRB2_MEDIA_VORBIS_ERROR_HPP__
#include <string>
#include <fmt/format.h> #include <fmt/format.h>
#include <vorbis/codec.h> #include <vorbis/codec.h>
#include "../core/string.h"
class VorbisError class VorbisError
{ {
public: public:
@ -23,7 +23,7 @@ public:
operator int() const { return error_; } operator int() const { return error_; }
std::string name() const srb2::String name() const
{ {
switch (error_) switch (error_)
{ {
@ -43,12 +43,12 @@ private:
}; };
template <> template <>
struct fmt::formatter<VorbisError> : formatter<std::string> struct fmt::formatter<VorbisError> : formatter<srb2::String>
{ {
template <typename FormatContext> template <typename FormatContext>
auto format(const VorbisError& error, FormatContext& ctx) const auto format(const VorbisError& error, FormatContext& ctx) const
{ {
return formatter<std::string>::format(error.name(), ctx); return formatter<srb2::String>::format(error.name(), ctx);
} }
}; };

View file

@ -11,22 +11,22 @@
#ifndef __SRB2_MEDIA_VPX_ERROR_HPP__ #ifndef __SRB2_MEDIA_VPX_ERROR_HPP__
#define __SRB2_MEDIA_VPX_ERROR_HPP__ #define __SRB2_MEDIA_VPX_ERROR_HPP__
#include <string>
#include <fmt/format.h> #include <fmt/format.h>
#include <vpx/vpx_codec.h> #include <vpx/vpx_codec.h>
#include "../core/string.h"
class VpxError class VpxError
{ {
public: public:
VpxError(vpx_codec_ctx_t& ctx) : ctx_(&ctx) {} 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* error = vpx_codec_error(ctx_);
const char* detail = vpx_codec_error_detail(ctx_); const char* detail = vpx_codec_error_detail(ctx_);
return detail ? fmt::format("{}: {}", error, detail) : error; return detail ? srb2::format("{}: {}", error, detail) : error;
} }
private: private:
@ -34,12 +34,12 @@ private:
}; };
template <> template <>
struct fmt::formatter<VpxError> : formatter<std::string> struct fmt::formatter<VpxError> : formatter<srb2::String>
{ {
template <typename FormatContext> template <typename FormatContext>
auto format(const VpxError& error, FormatContext& ctx) const auto format(const VpxError& error, FormatContext& ctx) const
{ {
return formatter<std::string>::format(error.description(), ctx); return formatter<srb2::String>::format(error.description(), ctx);
} }
}; };

View file

@ -13,11 +13,11 @@
#include <cstddef> #include <cstddef>
#include <mutex> #include <mutex>
#include <unordered_map>
#include <vector> #include <vector>
#include <mkvmuxer/mkvmuxer.h> #include <mkvmuxer/mkvmuxer.h>
#include "../core/hash_map.hpp"
#include "container.hpp" #include "container.hpp"
#include "webm.hpp" #include "webm.hpp"
#include "webm_writer.hpp" #include "webm_writer.hpp"
@ -88,7 +88,7 @@ private:
mutable std::recursive_mutex queue_mutex_; mutable std::recursive_mutex queue_mutex_;
std::unordered_map<webm::track, FrameQueue> queue_; srb2::HashMap<webm::track, FrameQueue> queue_;
webm::timestamp latest_timestamp_ = 0; webm::timestamp latest_timestamp_ = 0;
std::size_t queue_size_ = 0; std::size_t queue_size_ = 0;

View file

@ -12,10 +12,10 @@
#define __SRB2_MEDIA_WEBM_WRITER_HPP__ #define __SRB2_MEDIA_WEBM_WRITER_HPP__
#include <cstdio> #include <cstdio>
#include <string>
#include <mkvmuxer/mkvwriter.h> #include <mkvmuxer/mkvwriter.h>
#include "../core/string.h"
#include "cfile.hpp" #include "cfile.hpp"
namespace srb2::media namespace srb2::media
@ -24,7 +24,7 @@ namespace srb2::media
class WebmWriter : public CFile, public mkvmuxer::MkvWriter class WebmWriter : public CFile, public mkvmuxer::MkvWriter
{ {
public: public:
WebmWriter(const std::string file_name) : CFile(file_name), MkvWriter(static_cast<std::FILE*>(*this)) {} WebmWriter(const srb2::String& file_name) : CFile(file_name), MkvWriter(static_cast<std::FILE*>(*this)) {}
~WebmWriter() { MkvWriter::Close(); } ~WebmWriter() { MkvWriter::Close(); }
}; };

View file

@ -12,8 +12,8 @@
#define __SRB2_MEDIA_YUV420P_HPP__ #define __SRB2_MEDIA_YUV420P_HPP__
#include <cstdint> #include <cstdint>
#include <vector>
#include "../core/vector.hpp"
#include "video_frame.hpp" #include "video_frame.hpp"
namespace srb2::media namespace srb2::media
@ -40,7 +40,7 @@ public:
int width_ = 0; int width_ = 0;
int height_ = 0; int height_ = 0;
std::vector<uint8_t> vec_; srb2::Vector<uint8_t> vec_;
}; };
YUV420pFrame(int pts, Buffer y, Buffer u, Buffer v, const BufferRGBA& rgba); YUV420pFrame(int pts, Buffer y, Buffer u, Buffer v, const BufferRGBA& rgba);

View file

@ -11,11 +11,11 @@
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef>
#include <memory> #include <memory>
#include <string>
#include <fmt/chrono.h> #include <fmt/chrono.h>
#include <fmt/format.h> #include <fmt/format.h>
#include "../../core/string.h"
#include "../../cxxutil.hpp" #include "../../cxxutil.hpp"
#include "../../v_draw.hpp" #include "../../v_draw.hpp"
#include "EggTV.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) if (player.time)
{ {
return fmt::format( return srb2::format(
R"({}'{}"{})", R"({}'{}"{})",
G_TicsToMinutes(*player.time, true), G_TicsToMinutes(*player.time, true),
G_TicsToSeconds(*player.time), 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"; return player.score ? fmt::format("{} PTS", *player.score) : "NO CONTEST";
} }

View file

@ -19,6 +19,7 @@
#include "EggTVData.hpp" #include "EggTVData.hpp"
#include "EggTVGraphics.hpp" #include "EggTVGraphics.hpp"
#include "../../core/vector.hpp"
#include "../../doomdef.h" // TICRATE #include "../../doomdef.h" // TICRATE
#include "../../i_time.h" #include "../../i_time.h"
#include "../../k_menu.h" #include "../../k_menu.h"
@ -197,7 +198,7 @@ private:
{ {
public: public:
using limiter_t = std::function<int()>; using limiter_t = std::function<int()>;
using anims_t = std::vector<Animation*>; using anims_t = srb2::Vector<Animation*>;
explicit Cursor(anims_t anims, limiter_t limiter) : limiter_(limiter), anims_(anims) {} explicit Cursor(anims_t anims, limiter_t limiter) : limiter_(limiter), anims_(anims) {}

View file

@ -14,13 +14,14 @@
#include <fstream> #include <fstream>
#include <iterator> #include <iterator>
#include <memory> #include <memory>
#include <string>
#include <string_view> #include <string_view>
#include <fmt/format.h> #include <fmt/format.h>
#include <fmt/std.h> // std::filesystem::path formatter #include <fmt/std.h> // std::filesystem::path formatter
#include <nlohmann/json.hpp>
#include "../../core/string.h"
#include "../../core/json.hpp"
#include "../../io/streams.hpp"
#include "../../cxxutil.hpp" #include "../../cxxutil.hpp"
#include "EggTVData.hpp" #include "EggTVData.hpp"
@ -34,15 +35,15 @@ using namespace srb2::menus::egg_tv;
namespace fs = std::filesystem; namespace fs = std::filesystem;
using nlohmann::json; using srb2::JsonValue;
template <> template <>
struct fmt::formatter<fs::filesystem_error> : formatter<std::string> struct fmt::formatter<fs::filesystem_error> : formatter<srb2::String>
{ {
template <typename FormatContext> template <typename FormatContext>
auto format(const fs::filesystem_error& ex, FormatContext& ctx) const auto format(const fs::filesystem_error& ex, FormatContext& ctx) const
{ {
return formatter<std::string>::format( return formatter<srb2::String>::format(
fmt::format("{}, path1={}, path2={}", ex.what(), ex.path1(), ex.path2()), fmt::format("{}, path1={}, path2={}", ex.what(), ex.path1(), ex.path2()),
ctx ctx
); );
@ -65,13 +66,13 @@ To time_point_conv(From time)
return std::chrono::time_point_cast<typename To::duration>(To::clock::now() + (time - From::clock::now())); return std::chrono::time_point_cast<typename To::duration>(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()) if (!array.is_array())
{ {
array = json::array(); array = JsonValue::array();
} }
return 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 try
{ {
std::ifstream f(favoritesPath_); srb2::io::FileStream stream { favoritesPath_.generic_string() };
srb2::Vector<std::byte> f = srb2::io::read_to_vec(stream);
if (f.is_open()) srb2::String json_string { (const char*)f.data(), f.size() };
{ object = JsonValue::from_json_string(json_string);
f >> object;
}
} }
catch (const std::exception& ex) 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) 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::string_view str = info.title;
const std::size_t mid = str.find(kDelimiter); 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"); //title_ = Title("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW", "WWWWWWWWWWWWWWWWWWWWWWWWWWW");
} }
@ -316,13 +315,13 @@ void EggTVData::Replay::toggle_favorite() const
{ {
const auto& it = ref_->iterator_to_favorite(); 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 else
{ {
ref_->favorites().emplace_back(ref_->favorites_path()); ref_->favorites().as_array().emplace_back(ref_->favorites_path());
} }
ref_->cache().folder().tv().save_favorites(); ref_->cache().folder().tv().save_favorites();
@ -382,7 +381,9 @@ void EggTVData::save_favorites() const
{ {
try 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) catch (const std::exception& ex)
{ {

View file

@ -17,14 +17,13 @@
#include <filesystem> #include <filesystem>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <string>
#include <string_view> #include <string_view>
#include <utility> #include <utility>
#include <variant> #include <variant>
#include <vector> #include <vector>
#include <nlohmann/json.hpp> #include "../../core/string.h"
#include "../../core/json.hpp"
#include "../../cxxutil.hpp" #include "../../cxxutil.hpp"
#include "../../d_main.h" // srb2home #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 root_ = std::filesystem::path{srb2home} / "media/replay/online";
const std::filesystem::path favoritesPath_ = root_ / "favorites.json"; const std::filesystem::path favoritesPath_ = root_ / "favorites.json";
nlohmann::json favoritesFile_ = cache_favorites(); JsonValue favoritesFile_ = cache_favorites();
nlohmann::json& favorites_; JsonValue& favorites_;
nlohmann::json cache_favorites() const; JsonValue cache_favorites() const;
void cache_folders(); void cache_folders();
void save_favorites() const; void save_favorites() const;
@ -91,20 +90,21 @@ public:
released_ = true; released_ = true;
} }
bool favorited() const { return iterator_to_favorite() != favorites().end(); } bool favorited() const { return iterator_to_favorite() != favorites().as_array().end(); }
nlohmann::json& favorites() const { return cache().folder().tv().favorites_; } JsonValue& favorites() const { return cache().folder().tv().favorites_; }
std::string favorites_path() const srb2::String favorites_path() const
{ {
// path::generic_string converts to forward // path::generic_string converts to forward
// slashes on Windows. This should suffice to make // slashes on Windows. This should suffice to make
// the JSON file portable across installations. // 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<std::string_view>(path));
} }
private: private:
@ -134,13 +134,13 @@ public:
int y = 0; int y = 0;
bool empty() { return size() == 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_; } EggTVData& tv() const { return *tv_; }
std::size_t size() const { return size_; } std::size_t size() const { return size_; }
const time_point_t& time() const { return time_; } 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<Cache> load() { return std::make_unique<Cache>(*this); }; std::unique_ptr<Cache> load() { return std::make_unique<Cache>(*this); };
@ -150,7 +150,7 @@ public:
std::size_t size_; std::size_t size_;
time_point_t time_; time_point_t time_;
EggTVData* tv_; EggTVData* tv_;
std::string name_; srb2::String name_;
}; };
class Replay class Replay
@ -165,18 +165,18 @@ public:
{ {
} }
const std::string& first() const { return first_; } const srb2::String& first() const { return first_; }
const std::string& second() const { return second_; } const srb2::String& second() const { return second_; }
operator const std::string() const; operator const srb2::String() const;
private: private:
std::string first_, second_; srb2::String first_, second_;
}; };
struct Standing struct Standing
{ {
std::string name; srb2::String name;
std::optional<std::size_t> skin; std::optional<std::size_t> skin;
std::size_t color; std::size_t color;
std::optional<tic_t> time; std::optional<tic_t> time;
@ -247,7 +247,7 @@ public:
void toggle_favorite() const; void toggle_favorite() const;
bool invalid() const { return invalid_; } 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(); } std::filesystem::path path() const { return ref_->cache().folder().path() / ref_->filename(); }
const time_point_t& date() const { return ref_->time(); } const time_point_t& date() const { return ref_->time(); }

View file

@ -13,8 +13,8 @@
#include <array> #include <array>
#include <string_view> #include <string_view>
#include <unordered_map>
#include "../../core/hash_map.hpp"
#include "../../doomdef.h" // skincolornum_t #include "../../doomdef.h" // skincolornum_t
#include "../../v_draw.hpp" #include "../../v_draw.hpp"
@ -90,7 +90,7 @@ public:
patch select = "RHTVSQSL"; patch select = "RHTVSQSL";
std::unordered_map<std::string_view, patch> gametype = { srb2::HashMap<std::string_view, patch> gametype = {
{"Race", "RHGT1"}, {"Race", "RHGT1"},
{"Battle", "RHGT2"}, {"Battle", "RHGT2"},
{"Prison Break", "RHGT3"}, {"Prison Break", "RHGT3"},

View file

@ -11,6 +11,8 @@
/// \file menus/extras-challenges.c /// \file menus/extras-challenges.c
/// \brief Statistics menu /// \brief Statistics menu
#include <algorithm>
#include "../k_menu.h" #include "../k_menu.h"
#include "../z_zone.h" #include "../z_zone.h"
#include "../m_cond.h" // Condition Sets #include "../m_cond.h" // Condition Sets
@ -260,7 +262,7 @@ static void M_StatisticsPageInit(void)
M_StatisticsChars(); M_StatisticsChars();
break; break;
} }
case statisticspage_gp: case statisticspage_gp:
{ {
M_StatisticsGP(); M_StatisticsGP();

View file

@ -29,6 +29,8 @@
#include <forward_list> #include <forward_list>
#include "../core/string.h"
static void M_GonerDrawer(void); static void M_GonerDrawer(void);
static void M_GonerConclude(INT32 choice); static void M_GonerConclude(INT32 choice);
static boolean M_GonerInputs(INT32 ch); static boolean M_GonerInputs(INT32 ch);
@ -46,7 +48,7 @@ menuitem_t MAIN_Goner[] =
{.routine = M_VideoOptions}, 0, 0}, {.routine = M_VideoOptions}, 0, 0},
{IT_STRING | IT_CALL, "SOUND OPTIONS", {IT_STRING | IT_CALL, "SOUND OPTIONS",
"CALIBRATE AURAL DATASTREAM.", NULL, "CALIBRATE AURAL DATASTREAM.", NULL,
{.routine = M_SoundOptions}, 0, 0}, {.routine = M_SoundOptions}, 0, 0},
{IT_STRING | IT_CALL, "PROFILE SETUP", {IT_STRING | IT_CALL, "PROFILE SETUP",
@ -95,7 +97,7 @@ class GonerSpeaker
public: public:
float offset = 0; float offset = 0;
GonerSpeaker(std::string skinName, float offset) GonerSpeaker(const srb2::String& skinName, float offset)
{ {
if (!skinName.empty()) if (!skinName.empty())
{ {
@ -144,11 +146,11 @@ class GonerChatLine
{ {
public: public:
gonerspeakers_t speaker; gonerspeakers_t speaker;
std::string dialogue; srb2::String dialogue;
int value; // Mutlipurpose. int value; // Mutlipurpose.
void (*routine)(void); 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( char *newText = V_ScaledWordWrap(
(BASEVIDWIDTH/2 + 6) << FRACBITS, (BASEVIDWIDTH/2 + 6) << FRACBITS,
@ -158,7 +160,7 @@ public:
); );
this->speaker = speaker; this->speaker = speaker;
this->dialogue = std::string(newText); this->dialogue = srb2::String(newText);
this->value = delay; this->value = delay;
this->routine = nullptr; this->routine = nullptr;
@ -1142,7 +1144,7 @@ static void M_GonerDrawer(void)
for (auto & element : LinesOutput) for (auto & element : LinesOutput)
{ {
std::string text; srb2::String text;
INT32 flags; INT32 flags;
if (newy < 0) break; if (newy < 0) break;

View file

@ -174,7 +174,7 @@ void Music_Init(void)
{ {
Tune& tune = g_tunes.insert("credits"); Tune& tune = g_tunes.insert("credits");
tune.priority = 100; tune.priority = 101;
tune.song = "_creds"; tune.song = "_creds";
tune.credit = true; tune.credit = true;
} }
@ -182,7 +182,7 @@ void Music_Init(void)
{ {
Tune& tune = g_tunes.insert("shore"); Tune& tune = g_tunes.insert("shore");
tune.priority = 100; tune.priority = 101;
tune.loop = false; tune.loop = false;
} }

View file

@ -14,13 +14,13 @@
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <string>
#include <fmt/format.h> #include <fmt/format.h>
#include "music_manager.hpp" #include "music_manager.hpp"
#include "music_tune.hpp" #include "music_tune.hpp"
#include "core/string.h"
#include "d_clisrv.h" #include "d_clisrv.h"
#include "doomtype.h" #include "doomtype.h"
#include "i_sound.h" #include "i_sound.h"
@ -49,8 +49,8 @@ void TuneManager::tick()
Tune* tune = current_tune(); Tune* tune = current_tune();
std::string old_song = current_song_; srb2::String old_song = current_song_;
current_song_ = tune && tune->playing() && !tune->suspend ? tune->song : std::string{}; current_song_ = tune && tune->playing() && !tune->suspend ? tune->song : srb2::String{};
bool changed = current_song_ != old_song; bool changed = current_song_ != old_song;
@ -167,7 +167,8 @@ void TuneManager::pause_unpause() const
bool TuneManager::load() 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) if (lumpnum == LUMPERROR)
{ {

View file

@ -11,11 +11,10 @@
#ifndef MUSIC_MANAGER_HPP #ifndef MUSIC_MANAGER_HPP
#define MUSIC_MANAGER_HPP #define MUSIC_MANAGER_HPP
#include <algorithm>
#include <cstdlib> #include <cstdlib>
#include <string>
#include <unordered_map>
#include "core/hash_map.hpp"
#include "core/string.h"
#include "cxxutil.hpp" #include "cxxutil.hpp"
#include "music_tune.hpp" #include "music_tune.hpp"
@ -25,7 +24,7 @@ namespace srb2::music
class TuneManager class TuneManager
{ {
public: public:
const std::string& current_song() const { return current_song_; } const srb2::String& current_song() const { return current_song_; }
Tune* current_tune() const Tune* current_tune() const
{ {
@ -99,8 +98,8 @@ public:
} }
private: private:
std::unordered_map<std::string, Tune> map_; srb2::HashMap<srb2::String, Tune> map_;
std::string current_song_; srb2::String current_song_;
tic_t time_sync_; tic_t time_sync_;
tic_t time_local_; tic_t time_local_;
@ -113,11 +112,20 @@ private:
decltype(map_)::const_iterator current_iterator() const decltype(map_)::const_iterator current_iterator() const
{ {
return std::max_element( // Not using std::max_element due to buggy clang libc++ LegacyInputIterator assertion
map_.begin(), auto first = map_.begin();
map_.end(), auto last = map_.end();
[](const auto& a, const auto& b) { return a.second < b.second; } if (first == last) return first;
);
auto max = first;
while (++first != last)
{
if (max->second < first->second)
{
max = first;
}
}
return max;
} }
bool load() const; bool load() const;

View file

@ -14,8 +14,8 @@
#include <algorithm> #include <algorithm>
#include <cstdint> #include <cstdint>
#include <optional> #include <optional>
#include <string>
#include "core/string.h"
#include "doomdef.h" #include "doomdef.h"
#include "doomtype.h" #include "doomtype.h"
#include "k_boss.h" #include "k_boss.h"
@ -29,7 +29,7 @@ class Tune
public: public:
explicit Tune() {} explicit Tune() {}
std::string song; // looks up the lump srb2::String song; // looks up the lump
// Higher priority tunes play first. // Higher priority tunes play first.
int priority = 0; int priority = 0;

View file

@ -10,6 +10,8 @@
/// \file ballhog.cpp /// \file ballhog.cpp
/// \brief Ballhog item code. /// \brief Ballhog item code.
#include <algorithm>
#include "../doomdef.h" #include "../doomdef.h"
#include "../doomstat.h" #include "../doomstat.h"
#include "../info.h" #include "../info.h"

View file

@ -9,13 +9,13 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <algorithm> #include <algorithm>
#include <unordered_map>
#include <vector>
#include <fmt/format.h> #include <fmt/format.h>
#include "../mobj_list.hpp" #include "../mobj_list.hpp"
#include "../core/hash_map.hpp"
#include "../core/vector.hpp"
#include "../doomdef.h" #include "../doomdef.h"
#include "../doomtype.h" #include "../doomtype.h"
#include "../info.h" #include "../info.h"
@ -224,7 +224,7 @@ struct Checkpoint : mobj_t
speed(speed() - FixedDiv(speed() / 50, max<fixed_t>(speed_multiplier(), 1))); speed(speed() - FixedDiv(speed() / 50, max<fixed_t>(speed_multiplier(), 1)));
} }
} }
if (!top_half_has_passed()) if (!top_half_has_passed())
{ {
sparkle_between(0); sparkle_between(0);
@ -506,7 +506,7 @@ struct CheckpointManager
auto count() { return list_.count(); } auto count() { return list_.count(); }
const std::vector<line_t*>* lines_for(const Checkpoint* chk) const const srb2::Vector<line_t*>* lines_for(const Checkpoint* chk) const
{ {
auto it = lines_.find(chk->linetag()); auto it = lines_.find(chk->linetag());
return it != lines_.end() ? &it->second : nullptr; return it != lines_.end() ? &it->second : nullptr;
@ -514,11 +514,11 @@ struct CheckpointManager
private: private:
srb2::MobjList<Checkpoint, svg_checkpoints> list_; srb2::MobjList<Checkpoint, svg_checkpoints> list_;
std::unordered_map<INT32, std::vector<line_t*>> lines_; srb2::HashMap<INT32, srb2::Vector<line_t*>> lines_;
static std::vector<line_t*> tagged_lines(INT32 tag) static srb2::Vector<line_t*> tagged_lines(INT32 tag)
{ {
std::vector<line_t*> checklines; srb2::Vector<line_t*> checklines;
INT32 li; INT32 li;
TAG_ITER_LINES(tag, li) TAG_ITER_LINES(tag, li)
{ {
@ -573,18 +573,18 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe
} }
LineOnDemand* gate; LineOnDemand* gate;
const std::vector<line_t*>* lines = g_checkpoints.lines_for(chk); const srb2::Vector<line_t*>* lines = g_checkpoints.lines_for(chk);
if (!lines || lines->empty()) if (!lines || lines->empty())
{ {
LineOnDemand dyngate = chk->crossing_line(); LineOnDemand dyngate = chk->crossing_line();
if (!ray.overlaps(dyngate)) if (!ray.overlaps(dyngate))
return false; return false;
gate = &dyngate; gate = &dyngate;
} }
else else
{ {
auto it = find_if( auto it = std::find_if(
lines->begin(), lines->begin(),
lines->end(), lines->end(),
[&](const line_t* line) [&](const line_t* line)
@ -592,7 +592,7 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe
return ray.overlaps(*line); return ray.overlaps(*line);
} }
); );
if (it == lines->end()) if (it == lines->end())
{ {
return false; return false;
@ -615,7 +615,7 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe
{ {
// Did not cross. // Did not cross.
return false; return false;
} }
return true; return true;

View file

@ -13,8 +13,6 @@
/// \brief Do all the WAD I/O, get map description, set up initial state and misc. LUTs /// \brief Do all the WAD I/O, get map description, set up initial state and misc. LUTs
#include <algorithm> #include <algorithm>
#include <string>
#include <vector>
#include <fmt/format.h> #include <fmt/format.h>
@ -96,6 +94,8 @@
#include "taglist.h" #include "taglist.h"
// SRB2Kart // SRB2Kart
#include "core/string.h"
#include "core/vector.hpp"
#include "k_kart.h" #include "k_kart.h"
#include "k_race.h" #include "k_race.h"
#include "k_battle.h" // K_BattleInit #include "k_battle.h" // K_BattleInit
@ -7854,7 +7854,7 @@ static void P_LoadRecordGhosts(void)
map(cv_ghost_last, value, kLast); 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()); }; 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"); CONS_Debug(DBG_TEAMS, "Shuffling player teams...\n");
std::vector<UINT8> player_shuffle; srb2::Vector<UINT8> player_shuffle;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i] == false || players[i].spectator == true) 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) static void P_DeriveAutoMedalTimes(mapheader_t& map)
{ {
// Gather staff ghost times // Gather staff ghost times
std::vector<tic_t> stafftimes; srb2::Vector<tic_t> stafftimes;
for (int i = 0; i < map.ghostCount; i++) for (int i = 0; i < map.ghostCount; i++)
{ {
tic_t time = map.ghostBrief[i]->time; tic_t time = map.ghostBrief[i]->time;
@ -9325,7 +9325,7 @@ UINT8 P_InitMapData(void)
{ {
continue; 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); UINT16 lumpstart = W_CheckNumForFolderStartPK3(ghostdirname.c_str(), wadindex, 0);
if (lumpstart == INT16_MAX) if (lumpstart == INT16_MAX)

View file

@ -9,12 +9,12 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <string_view> #include <string_view>
#include <unordered_map>
#include <unordered_set>
#include "r_debug.hpp" #include "r_debug.hpp"
#include "v_draw.hpp" #include "v_draw.hpp"
#include "core/hash_map.hpp"
#include "core/hash_set.hpp"
#include "doomdef.h" #include "doomdef.h"
#include "doomtype.h" #include "doomtype.h"
#include "r_textures.h" #include "r_textures.h"
@ -25,7 +25,7 @@ using srb2::Draw;
namespace namespace
{ {
std::unordered_set<INT32> frame_list; srb2::HashSet<INT32> frame_list;
}; // namespace }; // namespace

View file

@ -14,6 +14,8 @@
/// while maintaining a per column clipping list only. /// while maintaining a per column clipping list only.
/// Moreover, the sky areas have to be determined. /// Moreover, the sky areas have to be determined.
#include <algorithm>
#include <tracy/tracy/Tracy.hpp> #include <tracy/tracy/Tracy.hpp>
#include "command.h" #include "command.h"

View file

@ -13,14 +13,14 @@
#include <cstdint> #include <cstdint>
#include <filesystem> #include <filesystem>
#include <map> #include <map>
#include <string>
#include <string_view> #include <string_view>
#include <thread> #include <thread>
#include <unordered_map>
#include <vector>
#include <fmt/format.h> #include <fmt/format.h>
#include "core/hash_map.hpp"
#include "core/string.h"
#include "core/vector.hpp"
#include "cxxutil.hpp" #include "cxxutil.hpp"
#include "doomstat.h" #include "doomstat.h"
#include "r_textures.h" #include "r_textures.h"
@ -29,14 +29,14 @@
namespace namespace
{ {
std::unordered_map<std::string, std::vector<const texture_t*>> g_dups; srb2::HashMap<srb2::String, srb2::Vector<const texture_t*>> g_dups;
std::map<std::string, std::vector<std::string>> g_warnings; std::map<srb2::String, srb2::Vector<srb2::String>> g_warnings;
std::thread g_dups_thread; 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_view view(cstr, 8);
std::string key; srb2::String key;
view = view.substr(0, view.find('\0')); // terminate by '\0' view = view.substr(0, view.find('\0')); // terminate by '\0'
key.reserve(view.size()); key.reserve(view.size());
@ -50,7 +50,7 @@ std::string key8char(const char cstr[8])
return key; return key;
} }
std::string texture_location(const texture_t& tex) srb2::String texture_location(const texture_t& tex)
{ {
if (tex.type == TEXTURETYPE_SINGLEPATCH) 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 texpatch_t& texpat = tex.patches[0];
const wadfile_t& wad = *wadfiles[texpat.wad]; const wadfile_t& wad = *wadfiles[texpat.wad];
return fmt::format( return srb2::format(
"'{}/{}'", "'{}/{}'",
std::filesystem::path(wad.filename).filename().string(), std::filesystem::path(wad.filename).filename().string(),
wad.lumpinfo[texpat.lump].fullname 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) auto collate_dups = [end, find_dup](int32_t start)
{ {
const texture_t* t1 = textures[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()) if (g_dups.find(key) != g_dups.end())
{ {
@ -119,7 +119,7 @@ void R_CheckTextureDuplicates(INT32 start, INT32 end)
if (idx < end) if (idx < end)
{ {
std::vector<const texture_t*>& v = g_dups[key]; srb2::Vector<const texture_t*>& v = g_dups[key];
v.push_back(textures[start]); v.push_back(textures[start]);
@ -175,7 +175,7 @@ void R_PrintTextureWarnings(void)
{ {
CONS_Alert(CONS_WARNING, "\n%s", header.c_str()); 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()); CONS_Printf("%s\n", warning.c_str());
} }

View file

@ -14,13 +14,13 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <tuple> #include <tuple>
#include <unordered_map>
#include <utility> #include <utility>
#include <fmt/format.h> #include <fmt/format.h>
#include <glad/gl.h> #include <glad/gl.h>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include "../../core/vector.hpp"
#include "../shader_load_context.hpp" #include "../shader_load_context.hpp"
using namespace srb2; using namespace srb2;
@ -840,8 +840,8 @@ rhi::Handle<rhi::Program> Gl2Rhi::create_program(const ProgramDesc& desc)
// breaks the AMD driver's program linker in a bizarre way. // breaks the AMD driver's program linker in a bizarre way.
// Process shader sources // Process shader sources
std::vector<const char*> vert_sources; srb2::Vector<const char*> vert_sources;
std::vector<const char*> frag_sources; srb2::Vector<const char*> frag_sources;
ShaderLoadContext vert_ctx; ShaderLoadContext vert_ctx;
ShaderLoadContext frag_ctx; ShaderLoadContext frag_ctx;
vert_ctx.set_version("120"); vert_ctx.set_version("120");
@ -873,11 +873,11 @@ rhi::Handle<rhi::Program> Gl2Rhi::create_program(const ProgramDesc& desc)
{ {
GLint max_length = 0; GLint max_length = 0;
gl_->GetShaderiv(program.vertex_shader, GL_INFO_LOG_LENGTH, &max_length); gl_->GetShaderiv(program.vertex_shader, GL_INFO_LOG_LENGTH, &max_length);
std::vector<GLchar> compile_error(max_length); srb2::Vector<GLchar> compile_error(max_length);
gl_->GetShaderInfoLog(program.vertex_shader, max_length, &max_length, compile_error.data()); gl_->GetShaderInfoLog(program.vertex_shader, max_length, &max_length, compile_error.data());
gl_->DeleteShader(program.vertex_shader); 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); program.fragment_shader = gl_->CreateShader(GL_FRAGMENT_SHADER);
@ -889,11 +889,11 @@ rhi::Handle<rhi::Program> Gl2Rhi::create_program(const ProgramDesc& desc)
{ {
GLint max_length = 0; GLint max_length = 0;
gl_->GetShaderiv(program.fragment_shader, GL_INFO_LOG_LENGTH, &max_length); gl_->GetShaderiv(program.fragment_shader, GL_INFO_LOG_LENGTH, &max_length);
std::vector<GLchar> compile_error(max_length); srb2::Vector<GLchar> compile_error(max_length);
gl_->GetShaderInfoLog(program.fragment_shader, max_length, &max_length, compile_error.data()); gl_->GetShaderInfoLog(program.fragment_shader, max_length, &max_length, compile_error.data());
gl_->DeleteShader(program.fragment_shader); 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(); program.program = gl_->CreateProgram();
@ -907,13 +907,13 @@ rhi::Handle<rhi::Program> Gl2Rhi::create_program(const ProgramDesc& desc)
{ {
GLint max_length = 0; GLint max_length = 0;
gl_->GetProgramiv(program.program, GL_INFO_LOG_LENGTH, &max_length); gl_->GetProgramiv(program.program, GL_INFO_LOG_LENGTH, &max_length);
std::vector<GLchar> link_error(max_length); srb2::Vector<GLchar> link_error(max_length);
gl_->GetProgramInfoLog(program.program, max_length, &max_length, link_error.data()); gl_->GetProgramInfoLog(program.program, max_length, &max_length, link_error.data());
gl_->DeleteProgram(program.program); gl_->DeleteProgram(program.program);
gl_->DeleteShader(program.fragment_shader); gl_->DeleteShader(program.fragment_shader);
gl_->DeleteShader(program.vertex_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 // get attribute information
@ -936,7 +936,7 @@ rhi::Handle<rhi::Program> Gl2Rhi::create_program(const ProgramDesc& desc)
GL_ASSERT; GL_ASSERT;
GLint location = gl_->GetAttribLocation(program.program, name); GLint location = gl_->GetAttribLocation(program.program, name);
GL_ASSERT; GL_ASSERT;
program.attrib_locations[std::string(name)] = location; program.attrib_locations[String(name)] = location;
} }
// get uniform information // get uniform information
@ -959,7 +959,7 @@ rhi::Handle<rhi::Program> Gl2Rhi::create_program(const ProgramDesc& desc)
GL_ASSERT; GL_ASSERT;
GLint location = gl_->GetUniformLocation(program.program, name); GLint location = gl_->GetUniformLocation(program.program, name);
GL_ASSERT; GL_ASSERT;
program.uniform_locations[std::string(name)] = location; program.uniform_locations[String(name)] = location;
} }
Handle<Program> program_handle = program_slab_.insert(std::move(program)); Handle<Program> program_handle = program_slab_.insert(std::move(program));

View file

@ -14,11 +14,11 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <string>
#include <tuple> #include <tuple>
#include <unordered_map>
#include <vector>
#include "../../core/hash_map.hpp"
#include "../../core/string.h"
#include "../../core/vector.hpp"
#include "../rhi.hpp" #include "../rhi.hpp"
namespace srb2::rhi namespace srb2::rhi
@ -71,7 +71,7 @@ struct Gl2Platform
virtual ~Gl2Platform(); virtual ~Gl2Platform();
virtual void present() = 0; virtual void present() = 0;
virtual std::tuple<std::vector<std::string>, std::vector<std::string>> find_shader_sources(const char* name) = 0; virtual std::tuple<srb2::Vector<srb2::String>, srb2::Vector<srb2::String>> find_shader_sources(const char* name) = 0;
virtual Rect get_default_framebuffer_dimensions() = 0; virtual Rect get_default_framebuffer_dimensions() = 0;
}; };
@ -98,8 +98,8 @@ struct Gl2Program : public rhi::Program
uint32_t vertex_shader = 0; uint32_t vertex_shader = 0;
uint32_t fragment_shader = 0; uint32_t fragment_shader = 0;
uint32_t program = 0; uint32_t program = 0;
std::unordered_map<std::string, uint32_t> attrib_locations; srb2::HashMap<srb2::String, uint32_t> attrib_locations;
std::unordered_map<std::string, uint32_t> uniform_locations; srb2::HashMap<srb2::String, uint32_t> uniform_locations;
}; };
struct Gl2ActiveUniform struct Gl2ActiveUniform
@ -121,14 +121,14 @@ class Gl2Rhi final : public Rhi
Handle<Buffer> current_index_buffer_; Handle<Buffer> current_index_buffer_;
std::unordered_map<Gl2FramebufferKey, uint32_t> framebuffers_ {16}; srb2::HashMap<Gl2FramebufferKey, uint32_t> framebuffers_ {16};
struct DefaultRenderPassState struct DefaultRenderPassState
{ {
bool clear = false; bool clear = false;
}; };
using RenderPassState = std::variant<DefaultRenderPassState, RenderPassBeginInfo>; using RenderPassState = std::variant<DefaultRenderPassState, RenderPassBeginInfo>;
std::vector<RenderPassState> render_pass_stack_; srb2::Vector<RenderPassState> render_pass_stack_;
std::optional<Handle<Program>> current_program_; std::optional<Handle<Program>> current_program_;
PrimitiveType current_primitive_type_ = PrimitiveType::kPoints; PrimitiveType current_primitive_type_ = PrimitiveType::kPoints;
uint32_t index_buffer_offset_ = 0; uint32_t index_buffer_offset_ = 0;

View file

@ -12,6 +12,9 @@
#include <fmt/core.h> #include <fmt/core.h>
#include "../core/string.h"
#include "../core/vector.hpp"
using namespace srb2; using namespace srb2;
using namespace rhi; using namespace rhi;
@ -19,27 +22,27 @@ ShaderLoadContext::ShaderLoadContext() = default;
void ShaderLoadContext::set_version(std::string_view version) 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); sources_.push_back(source);
} }
void ShaderLoadContext::add_source(std::string&& source) void ShaderLoadContext::add_source(srb2::String&& source)
{ {
sources_.push_back(std::move(source)); sources_.push_back(std::move(source));
} }
void ShaderLoadContext::define(std::string_view name) void ShaderLoadContext::define(std::string_view name)
{ {
defines_.append(fmt::format("#define {}\n", name)); defines_.append(srb2::format("#define {}\n", name));
} }
std::vector<const char*> ShaderLoadContext::get_sources_array() srb2::Vector<const char*> ShaderLoadContext::get_sources_array()
{ {
std::vector<const char*> ret; srb2::Vector<const char*> ret;
ret.push_back(version_.c_str()); ret.push_back(version_.c_str());
ret.push_back(defines_.c_str()); ret.push_back(defines_.c_str());

View file

@ -11,29 +11,30 @@
#ifndef __SRB2_RHI_SHADER_LOAD_CONTEXT_HPP__ #ifndef __SRB2_RHI_SHADER_LOAD_CONTEXT_HPP__
#define __SRB2_RHI_SHADER_LOAD_CONTEXT_HPP__ #define __SRB2_RHI_SHADER_LOAD_CONTEXT_HPP__
#include <string>
#include <string_view> #include <string_view>
#include <vector>
#include "../core/string.h"
#include "../core/vector.hpp"
namespace srb2::rhi namespace srb2::rhi
{ {
class ShaderLoadContext class ShaderLoadContext
{ {
std::string version_; srb2::String version_;
std::string defines_; srb2::String defines_;
std::vector<std::string> sources_; srb2::Vector<srb2::String> sources_;
public: public:
ShaderLoadContext(); ShaderLoadContext();
void set_version(std::string_view version); void set_version(std::string_view version);
void add_source(const std::string& source); void add_source(const srb2::String& source);
void add_source(std::string&& source); void add_source(srb2::String&& source);
void define(std::string_view name); void define(std::string_view name);
std::vector<const char*> get_sources_array(); srb2::Vector<const char*> get_sources_array();
}; };
}; // namespace srb2::rhi }; // namespace srb2::rhi

View file

@ -11,9 +11,9 @@
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <iterator> #include <iterator>
#include <string>
#include <string_view> #include <string_view>
#include "core/string.h"
#include "doomtype.h" #include "doomtype.h"
#include "sanitize.h" #include "sanitize.h"
#include "v_draw.hpp" #include "v_draw.hpp"
@ -34,7 +34,7 @@ bool color_filter(char c)
} }
template <typename F> template <typename F>
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( std::remove_copy_if(
range.begin(), range.begin(),
@ -62,9 +62,9 @@ int hexconv(int c)
namespace srb2::sanitize 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] return filter_out(out, in, [mode]
{ {
switch (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; using std::size_t;
for (;;) for (;;)

View file

@ -14,9 +14,10 @@
#include "doomtype.h" #include "doomtype.h"
#ifdef __cplusplus #ifdef __cplusplus
#include <string>
#include <string_view> #include <string_view>
#include "core/string.h"
namespace srb2::sanitize namespace srb2::sanitize
{ {
@ -33,10 +34,10 @@ enum class ParseMode
}; };
// sanitizes string of all 0x80 codes // 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 // 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 }; // namespace srb2

View file

@ -17,10 +17,10 @@
#include "../d_main.h" #include "../d_main.h"
#include "../m_misc.h"/* path shit */ #include "../m_misc.h"/* path shit */
#include "../i_system.h" #include "../i_system.h"
#include "../core/string.h"
#include <exception> #include <exception>
#include <stdexcept> #include <stdexcept>
#include <string>
#include <tracy/tracy/Tracy.hpp> #include <tracy/tracy/Tracy.hpp>
@ -227,14 +227,14 @@ ChDirToExe (void)
} }
#endif #endif
static void walk_exception_stack(std::string& accum, bool nested) { static void walk_exception_stack(srb2::String& accum, bool nested) {
if (nested) if (nested)
accum.append("\n Caused by: Unknown exception"); accum.append("\n Caused by: Unknown exception");
else else
accum.append("Uncaught exception: Unknown exception"); 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) if (nested)
accum.append("\n Caused by: "); accum.append("\n Caused by: ");
else else
@ -331,11 +331,11 @@ int main(int argc, char **argv)
D_SRB2Loop(); D_SRB2Loop();
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
std::string exception; srb2::String exception;
walk_exception_stack(exception, ex, false); walk_exception_stack(exception, ex, false);
I_Error("%s", exception.c_str()); I_Error("%s", exception.c_str());
} catch (...) { } catch (...) {
std::string exception; srb2::String exception;
walk_exception_stack(exception, false); walk_exception_stack(exception, false);
I_Error("%s", exception.c_str()); I_Error("%s", exception.c_str());
} }

View file

@ -11,11 +11,13 @@
#include "rhi_gl2_platform.hpp" #include "rhi_gl2_platform.hpp"
#include <array> #include <array>
#include <string>
#include <sstream> #include <sstream>
#include <SDL.h> #include <SDL.h>
#include <fmt/core.h>
#include "../core/string.h"
#include "../core/vector.hpp"
#include "../cxxutil.hpp" #include "../cxxutil.hpp"
#include "../doomstat.h" // mainwads #include "../doomstat.h" // mainwads
#include "../w_wad.h" #include "../w_wad.h"
@ -34,22 +36,22 @@ void SdlGl2Platform::present()
SDL_GL_SwapWindow(window); SDL_GL_SwapWindow(window);
} }
static std::array<std::string, 2> glsllist_lump_names(const char* name) static std::array<srb2::String, 2> glsllist_lump_names(const char* name)
{ {
std::string vertex_list_name = fmt::format("rhi_glsllist_{}_vertex.txt", name); srb2::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 fragment_list_name = fmt::format("rhi_glsllist_{}_fragment.txt", name);
return {std::move(vertex_list_name), std::move(fragment_list_name)}; return {std::move(vertex_list_name), std::move(fragment_list_name)};
} }
static std::vector<std::string> get_sources_from_glsllist_lump(const char* lumpname) static srb2::Vector<srb2::String> get_sources_from_glsllist_lump(const char* lumpname)
{ {
size_t buffer_size; size_t buffer_size;
if (!W_ReadShader(lumpname, &buffer_size, nullptr)) if (!W_ReadShader(lumpname, &buffer_size, nullptr))
{ {
throw std::runtime_error(fmt::format("Unable to find glsllist lump {}", lumpname)); 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); glsllist_lump_data.resize(buffer_size);
if (!W_ReadShader(lumpname, &buffer_size, glsllist_lump_data.data())) if (!W_ReadShader(lumpname, &buffer_size, glsllist_lump_data.data()))
{ {
@ -57,7 +59,7 @@ static std::vector<std::string> get_sources_from_glsllist_lump(const char* lumpn
} }
std::istringstream glsllist(glsllist_lump_data); std::istringstream glsllist(glsllist_lump_data);
std::vector<std::string> sources; srb2::Vector<srb2::String> sources;
for (std::string line; std::getline(glsllist, line); ) for (std::string line; std::getline(glsllist, line); )
{ {
if (line.empty()) if (line.empty())
@ -87,7 +89,7 @@ static std::vector<std::string> get_sources_from_glsllist_lump(const char* lumpn
{ {
throw std::runtime_error(fmt::format("Unable to find glsl source lump lump {}", line)); 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); source_lump.resize(source_lump_size);
if (!W_ReadShader(line.c_str(), &source_lump_size, source_lump.data())) if (!W_ReadShader(line.c_str(), &source_lump_size, source_lump.data()))
{ {
@ -100,13 +102,13 @@ static std::vector<std::string> get_sources_from_glsllist_lump(const char* lumpn
return sources; return sources;
} }
std::tuple<std::vector<std::string>, std::vector<std::string>> std::tuple<srb2::Vector<srb2::String>, srb2::Vector<srb2::String>>
SdlGl2Platform::find_shader_sources(const char* name) SdlGl2Platform::find_shader_sources(const char* name)
{ {
std::array<std::string, 2> glsllist_names = glsllist_lump_names(name); std::array<srb2::String, 2> glsllist_names = glsllist_lump_names(name);
std::vector<std::string> vertex_sources = get_sources_from_glsllist_lump(glsllist_names[0].c_str()); srb2::Vector<srb2::String> vertex_sources = get_sources_from_glsllist_lump(glsllist_names[0].c_str());
std::vector<std::string> fragment_sources = get_sources_from_glsllist_lump(glsllist_names[1].c_str()); srb2::Vector<srb2::String> fragment_sources = get_sources_from_glsllist_lump(glsllist_names[1].c_str());
return std::make_tuple(std::move(vertex_sources), std::move(fragment_sources)); return std::make_tuple(std::move(vertex_sources), std::move(fragment_sources));
} }

View file

@ -11,6 +11,10 @@
#ifndef __SRB2_SDL_RHI_GL2_PLATFORM_HPP__ #ifndef __SRB2_SDL_RHI_GL2_PLATFORM_HPP__
#define __SRB2_SDL_RHI_GL2_PLATFORM_HPP__ #define __SRB2_SDL_RHI_GL2_PLATFORM_HPP__
#include <tuple>
#include "../core/string.h"
#include "../core/vector.hpp"
#include "../rhi/gl2/gl2_rhi.hpp" #include "../rhi/gl2/gl2_rhi.hpp"
#include "../rhi/rhi.hpp" #include "../rhi/rhi.hpp"
@ -26,7 +30,7 @@ struct SdlGl2Platform final : public Gl2Platform
virtual ~SdlGl2Platform(); virtual ~SdlGl2Platform();
virtual void present() override; virtual void present() override;
virtual std::tuple<std::vector<std::string>, std::vector<std::string>> virtual std::tuple<Vector<srb2::String>, Vector<srb2::String>>
find_shader_sources(const char* name) override; find_shader_sources(const char* name) override;
virtual Rect get_default_framebuffer_dimensions() override; virtual Rect get_default_framebuffer_dimensions() override;
}; };

View file

@ -8,8 +8,7 @@
// See the 'LICENSE' file for more details. // See the 'LICENSE' file for more details.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <unordered_map> #include "core/hash_map.hpp"
#include "doomdef.h" // skincolornum_t #include "doomdef.h" // skincolornum_t
#include "doomtype.h" #include "doomtype.h"
#include "hu_stuff.h" #include "hu_stuff.h"
@ -34,7 +33,7 @@ int Draw::TextElement::width() const
Draw::TextElement& Draw::TextElement::parse(std::string_view raw) Draw::TextElement& Draw::TextElement::parse(std::string_view raw)
{ {
static const std::unordered_map<std::string_view, char> translation = { static const srb2::HashMap<std::string_view, char> translation = {
#define BUTTON(str, lower_bits) \ #define BUTTON(str, lower_bits) \
{str, 0xB0 | lower_bits},\ {str, 0xB0 | lower_bits},\
{str "_animated", 0xA0 | 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? // When we encounter a Saturn button, what gamecontrol does it represent?
static const std::unordered_map<char, gamecontrols_e> inputdefinition = { static const srb2::HashMap<char, gamecontrols_e> inputdefinition = {
{sb_up, gc_up}, {sb_up, gc_up},
{sb_down, gc_down}, {sb_down, gc_down},
{sb_right, gc_right}, {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? // What physical binds should appear as Saturn icons anyway?
// (We don't have generic binds for stick/dpad directions, so // (We don't have generic binds for stick/dpad directions, so
// using the existing arrow graphics is the best thing here.) // using the existing arrow graphics is the best thing here.)
static const std::unordered_map<INT32, char> prettyinputs = { static const srb2::HashMap<INT32, char> prettyinputs = {
{KEY_UPARROW, sb_up}, {KEY_UPARROW, sb_up},
{KEY_DOWNARROW, sb_down}, {KEY_DOWNARROW, sb_down},
{KEY_LEFTARROW, sb_left}, {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. // 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, // 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. // 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(0xEF); // Control code: "switch to descriptive input mode"
string_.push_back(0xEB); // Control code: "large button" string_.push_back(0xEB); // Control code: "large button"
if (code == "dpad") 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, // EXTRA: descriptiveinput values above 1 translate binds back to Saturn buttons,
// with various modes for various fucked up 6bt pads // with various modes for various fucked up 6bt pads
std::unordered_map<INT32, char> padconfig = {}; srb2::HashMap<INT32, char> padconfig = {};
switch (cv_descriptiveinput[localplayer].value) switch (cv_descriptiveinput[localplayer].value)
{ {
case 1: case 1:
@ -277,7 +276,7 @@ Draw::TextElement& Draw::TextElement::parse(std::string_view raw)
pad->second = pad->second & (0x0F); pad->second = pad->second & (0x0F);
// original invocation has the animation bits, but the glyph bits come from the table // 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 else
{ {
@ -349,6 +348,11 @@ void Chain::fill(UINT8 color) const
void Chain::string(const char* str, INT32 flags, Font font) const void Chain::string(const char* str, INT32 flags, Font font) const
{ {
if (!str)
{
return;
}
const auto _ = Clipper(*this); const auto _ = Clipper(*this);
flags |= default_font_flags(font); 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) 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); return V_StringScaledWidth(FRACUNIT, FRACUNIT, FRACUNIT, flags, font_to_fontno(font), string);
} }

View file

@ -11,14 +11,14 @@
#ifndef __V_DRAW_HPP__ #ifndef __V_DRAW_HPP__
#define __V_DRAW_HPP__ #define __V_DRAW_HPP__
#include <string>
#include <string_view> #include <string_view>
#include <optional> #include <optional>
#include <utility> #include <utility>
#include <unordered_map>
#include <fmt/core.h> #include <fmt/core.h>
#include "core/hash_map.hpp"
#include "core/string.h"
#include "doomdef.h" // skincolornum_t #include "doomdef.h" // skincolornum_t
#include "doomtype.h" #include "doomtype.h"
#include "screen.h" // BASEVIDWIDTH #include "screen.h" // BASEVIDWIDTH
@ -66,7 +66,7 @@ typedef enum
} saturn_buttons_e; } saturn_buttons_e;
// Garden-variety standard gamepad // Garden-variety standard gamepad
static const std::unordered_map<INT32, char> standardpad = { static const srb2::HashMap<INT32, char> standardpad = {
{nc_a, gb_a}, {nc_a, gb_a},
{nc_b, gb_b}, {nc_b, gb_b},
{nc_x, gb_x}, {nc_x, gb_x},
@ -83,7 +83,7 @@ static const std::unordered_map<INT32, char> standardpad = {
// Standard gamepad, but evil Nintendo layout flip was applied by your // Standard gamepad, but evil Nintendo layout flip was applied by your
// controller firmware or Steam Input—swap B/A and X/Y // controller firmware or Steam Input—swap B/A and X/Y
static const std::unordered_map<INT32, char> flippedpad = { static const srb2::HashMap<INT32, char> flippedpad = {
{nc_a, gb_b}, {nc_a, gb_b},
{nc_b, gb_a}, {nc_b, gb_a},
{nc_x, gb_y}, {nc_x, gb_y},
@ -99,7 +99,7 @@ static const std::unordered_map<INT32, char> flippedpad = {
}; };
// Saturn Type A - Retrobit Wired Dinput, RB RT LB LT (CZLR) // Saturn Type A - Retrobit Wired Dinput, RB RT LB LT (CZLR)
static const std::unordered_map<INT32, char> saturntypeA = { static const srb2::HashMap<INT32, char> saturntypeA = {
{nc_a, sb_a}, {nc_a, sb_a},
{nc_b, sb_b}, {nc_b, sb_b},
{nc_x, sb_x}, {nc_x, sb_x},
@ -115,7 +115,7 @@ static const std::unordered_map<INT32, char> saturntypeA = {
}; };
// Saturn Type B - Retrobit Wireless Dinput, LB RB LT RT (CZLR) // Saturn Type B - Retrobit Wireless Dinput, LB RB LT RT (CZLR)
static const std::unordered_map<INT32, char> saturntypeB = { static const srb2::HashMap<INT32, char> saturntypeB = {
{nc_a, sb_a}, {nc_a, sb_a},
{nc_b, sb_b}, {nc_b, sb_b},
{nc_x, sb_x}, {nc_x, sb_x},
@ -131,7 +131,7 @@ static const std::unordered_map<INT32, char> saturntypeB = {
}; };
// Saturn Type C - Retrobit Xinput, RT LT LB RB (CZLR) // Saturn Type C - Retrobit Xinput, RT LT LB RB (CZLR)
static const std::unordered_map<INT32, char> saturntypeC = { static const srb2::HashMap<INT32, char> saturntypeC = {
{nc_a, sb_a}, {nc_a, sb_a},
{nc_b, sb_b}, {nc_b, sb_b},
{nc_x, sb_x}, {nc_x, sb_x},
@ -150,7 +150,7 @@ static const std::unordered_map<INT32, char> saturntypeC = {
// This cannot be disambiguated (shares L/R with type 1) // This cannot be disambiguated (shares L/R with type 1)
// but is more spatially correct w/r/t SDL expectations // but is more spatially correct w/r/t SDL expectations
// and standard arcade mapping (Z on top, C on bottom) // and standard arcade mapping (Z on top, C on bottom)
static const std::unordered_map<INT32, char> saturntypeD = { static const srb2::HashMap<INT32, char> saturntypeD = {
{nc_a, sb_a}, {nc_a, sb_a},
{nc_b, sb_b}, {nc_b, sb_b},
{nc_x, sb_x}, {nc_x, sb_x},
@ -169,7 +169,7 @@ static const std::unordered_map<INT32, char> saturntypeD = {
// The Hori layout is, to my knowledge, the only 6bt one that has fully // 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, // unique buttons in every slot while having both bumpers and triggers,
// so there's no way to accurately portray it without using generics. // so there's no way to accurately portray it without using generics.
static const std::unordered_map<INT32, char> saturntypeE = { static const srb2::HashMap<INT32, char> saturntypeE = {
{nc_a, sb_a}, {nc_a, sb_a},
{nc_b, sb_b}, {nc_b, sb_b},
{nc_x, sb_x}, {nc_x, sb_x},
@ -263,7 +263,7 @@ public:
public: public:
explicit TextElement() {} explicit TextElement() {}
explicit TextElement(std::string string) : string_(string) {} explicit TextElement(const srb2::String& string) : string_(string) {}
template <class... Args> template <class... Args>
explicit TextElement(fmt::format_string<Args...> format, Args&&... args) : explicit TextElement(fmt::format_string<Args...> 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> font() const { return font_; } std::optional<Font> font() const { return font_; }
std::optional<INT32> flags() const { return flags_; } std::optional<INT32> flags() const { return flags_; }
std::optional<UINT8> as() const { return as_; } std::optional<UINT8> as() const { return as_; }
int width() const; int width() const;
TextElement& string(std::string string) TextElement& string(srb2::String string)
{ {
string_ = string; string_ = string;
return *this; return *this;
@ -310,7 +310,7 @@ public:
return *this; return *this;
} }
private: private:
std::string string_; srb2::String string_;
std::optional<Font> font_; std::optional<Font> font_;
std::optional<INT32> flags_; std::optional<INT32> flags_;
std::optional<UINT8> as_; std::optional<UINT8> as_;
@ -357,7 +357,7 @@ public:
Chain& colorize(UINT16 color); Chain& colorize(UINT16 color);
void text(const char* str) const { string(str, flags_, font_); } 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 void text(const TextElement& elm) const
{ {
string(elm.string().c_str(), elm.flags().value_or(flags_), elm.font().value_or(font_)); 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(patch_t* patch) const;
void patch(const char* name) const { patch(Draw::cache_patch(name)); } 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; void thumbnail(UINT16 mapnum) const;

View file

@ -322,9 +322,9 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
{ {
srb2::StandingJson standing {}; srb2::StandingJson standing {};
standing.ranking = data.pos[data.numplayers]; 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.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]; standing.timeorscore = data.val[data.numplayers];
standings.standings.emplace_back(std::move(standing)); standings.standings.emplace_back(std::move(standing));
} }