mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'new-data-structures' into 'master'
New data structures See merge request kart-krew-dev/ring-racers-internal!2498
This commit is contained in:
commit
4e13f61de5
87 changed files with 6082 additions and 538 deletions
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -153,8 +153,8 @@ OggComment Ogg::comment() const
|
|||
stb_vorbis_comment c_comment = stb_vorbis_get_comment(instance_);
|
||||
|
||||
return OggComment {
|
||||
std::string(c_comment.vendor),
|
||||
std::vector<std::string>(c_comment.comment_list, c_comment.comment_list + c_comment.comment_list_length)};
|
||||
String(c_comment.vendor),
|
||||
Vector<String>(c_comment.comment_list, c_comment.comment_list + c_comment.comment_list_length)};
|
||||
}
|
||||
|
||||
std::size_t Ogg::sample_rate() const
|
||||
|
|
|
|||
|
|
@ -35,19 +35,19 @@ public:
|
|||
|
||||
struct OggComment
|
||||
{
|
||||
std::string vendor;
|
||||
std::vector<std::string> comments;
|
||||
String vendor;
|
||||
Vector<String> comments;
|
||||
};
|
||||
|
||||
class Ogg final
|
||||
{
|
||||
std::vector<std::byte> memory_data_;
|
||||
Vector<std::byte> memory_data_;
|
||||
stb_vorbis* instance_;
|
||||
|
||||
public:
|
||||
Ogg() noexcept;
|
||||
|
||||
explicit Ogg(std::vector<std::byte> data);
|
||||
explicit Ogg(Vector<std::byte> data);
|
||||
explicit Ogg(tcb::span<std::byte> data);
|
||||
|
||||
Ogg(const Ogg&) = delete;
|
||||
|
|
@ -77,7 +77,7 @@ private:
|
|||
template <typename I, typename std::enable_if_t<srb2::io::IsInputStreamV<I>, int> = 0>
|
||||
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)};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,9 +126,9 @@ void visit_tag(Visitor& visitor, io::SpanStream& stream, const TagHeader& header
|
|||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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::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)
|
||||
{
|
||||
|
|
@ -247,7 +247,7 @@ template <typename T>
|
|||
std::size_t read_samples(
|
||||
std::size_t channels,
|
||||
std::size_t offset,
|
||||
const std::vector<T>& samples,
|
||||
const Vector<T>& samples,
|
||||
tcb::span<audio::Sample<1>> buffer
|
||||
) 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
|
||||
{
|
||||
auto samples_visitor = srb2::Overload {
|
||||
[&](const std::vector<uint8_t>& samples) { return read_samples<uint8_t>(channels(), offset, samples, buffer); },
|
||||
[&](const std::vector<int16_t>& samples)
|
||||
[&](const Vector<uint8_t>& samples) { return read_samples<uint8_t>(channels(), offset, samples, buffer); },
|
||||
[&](const Vector<int16_t>& samples)
|
||||
{ return read_samples<int16_t>(channels(), offset, samples, buffer); }};
|
||||
|
||||
return std::visit(samples_visitor, interleaved_samples_);
|
||||
|
|
@ -291,7 +291,7 @@ std::size_t Wav::get_samples(std::size_t offset, tcb::span<audio::Sample<1>> buf
|
|||
std::size_t Wav::interleaved_length() const noexcept
|
||||
{
|
||||
auto samples_visitor = srb2::Overload {
|
||||
[](const std::vector<uint8_t>& samples) { return samples.size(); },
|
||||
[](const std::vector<int16_t>& samples) { return samples.size(); }};
|
||||
[](const Vector<uint8_t>& samples) { return samples.size(); },
|
||||
[](const Vector<int16_t>& samples) { return samples.size(); }};
|
||||
return std::visit(samples_visitor, interleaved_samples_);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@
|
|||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include <tcb/span.hpp>
|
||||
|
||||
#include "../core/vector.hpp"
|
||||
#include "../io/streams.hpp"
|
||||
#include "sample.hpp"
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ namespace srb2::audio
|
|||
|
||||
class Wav final
|
||||
{
|
||||
std::variant<std::vector<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 sample_rate_ = 44100;
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ public:
|
|||
template <typename I, typename std::enable_if_t<srb2::io::IsInputStreamV<I>, int> = 0>
|
||||
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};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ Xmp<C>::Xmp() : data_(), instance_(nullptr), module_loaded_(false), looping_(fal
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
_init();
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@
|
|||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <tcb/span.hpp>
|
||||
#include <xmp.h>
|
||||
|
||||
#include "../core/vector.hpp"
|
||||
#include "../io/streams.hpp"
|
||||
|
||||
namespace srb2::audio
|
||||
|
|
@ -37,7 +37,7 @@ public:
|
|||
template <size_t C>
|
||||
class Xmp final
|
||||
{
|
||||
std::vector<std::byte> data_;
|
||||
Vector<std::byte> data_;
|
||||
xmp_context instance_;
|
||||
bool module_loaded_;
|
||||
bool looping_;
|
||||
|
|
@ -45,7 +45,7 @@ class Xmp final
|
|||
public:
|
||||
Xmp();
|
||||
|
||||
explicit Xmp(std::vector<std::byte> data);
|
||||
explicit Xmp(Vector<std::byte> data);
|
||||
explicit Xmp(tcb::span<std::byte> data);
|
||||
|
||||
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>
|
||||
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)};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#include <cmath>
|
||||
|
||||
#include "../core/vector.hpp"
|
||||
|
||||
using namespace srb2;
|
||||
using namespace srb2::audio;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
#include "source.hpp"
|
||||
#include "xmp.hpp"
|
||||
|
||||
#include "../core/vector.hpp"
|
||||
|
||||
namespace srb2::audio
|
||||
{
|
||||
|
||||
|
|
@ -21,7 +23,7 @@ template <size_t C>
|
|||
class XmpPlayer final : public Source<C>
|
||||
{
|
||||
Xmp<C> xmp_;
|
||||
std::vector<std::array<int16_t, C>> buf_;
|
||||
srb2::Vector<std::array<int16_t, C>> buf_;
|
||||
|
||||
public:
|
||||
XmpPlayer(Xmp<C>&& xmp);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,17 @@
|
|||
target_sources(SRB2SDL2 PRIVATE
|
||||
hash_map.hpp
|
||||
hash_set.cpp
|
||||
hash_set.hpp
|
||||
json.cpp
|
||||
json.hpp
|
||||
memory.cpp
|
||||
memory.h
|
||||
spmc_queue.hpp
|
||||
static_vec.hpp
|
||||
string.cpp
|
||||
string.h
|
||||
thread_pool.cpp
|
||||
thread_pool.h
|
||||
vector.cpp
|
||||
vector.hpp
|
||||
)
|
||||
|
|
|
|||
678
src/core/hash_map.hpp
Normal file
678
src/core/hash_map.hpp
Normal file
|
|
@ -0,0 +1,678 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2025 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef SRB2_CORE_HASH_MAP_HPP
|
||||
#define SRB2_CORE_HASH_MAP_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include "../cxxutil.hpp"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
template <typename V>
|
||||
class HashSet;
|
||||
|
||||
template <typename K, typename V>
|
||||
class HashMap
|
||||
{
|
||||
struct Elem;
|
||||
|
||||
using Hasher = std::hash<K>;
|
||||
using KeyEqual = std::equal_to<K>;
|
||||
|
||||
public:
|
||||
using Entry = std::pair<K, V>;
|
||||
|
||||
class ConstIter;
|
||||
|
||||
class Iter
|
||||
{
|
||||
const HashMap* self_;
|
||||
uint32_t bucket_;
|
||||
Elem* cur_;
|
||||
|
||||
Iter(const HashMap* self, uint32_t bucket, Elem* cur)
|
||||
: self_(self)
|
||||
, bucket_(bucket)
|
||||
, cur_(cur)
|
||||
{}
|
||||
|
||||
Iter(const ConstIter& r)
|
||||
: self_(r.iter_.self_)
|
||||
, bucket_(r.iter_.bucket_)
|
||||
, cur_(r.iter_.cur_)
|
||||
{}
|
||||
|
||||
friend class HashMap;
|
||||
friend class HashSet<K>;
|
||||
friend class ConstIter;
|
||||
|
||||
public:
|
||||
Iter() : Iter(nullptr, 0, nullptr) {}
|
||||
Iter(const Iter&) = default;
|
||||
Iter(Iter&&) noexcept = default;
|
||||
~Iter() = default;
|
||||
Iter& operator=(const Iter&) = default;
|
||||
Iter& operator=(Iter&&) noexcept = default;
|
||||
|
||||
Entry& operator*() const noexcept { return cur_->entry; }
|
||||
Entry* operator->() const noexcept { return &cur_->entry; }
|
||||
bool operator==(const Iter& r) const noexcept
|
||||
{
|
||||
return self_ == r.self_ && bucket_ == r.bucket_ && cur_ == r.cur_;
|
||||
}
|
||||
bool operator!=(const Iter& r) const noexcept { return !(*this == r); }
|
||||
|
||||
Iter& operator++()
|
||||
{
|
||||
if (cur_ == nullptr)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (cur_->next == nullptr)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (bucket_ < self_->buckets_ - 1)
|
||||
{
|
||||
bucket_++;
|
||||
cur_ = self_->heads_[bucket_];
|
||||
}
|
||||
else
|
||||
{
|
||||
self_ = nullptr;
|
||||
bucket_ = 0;
|
||||
cur_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
} while (cur_ == nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_ = cur_->next;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iter operator++(int)
|
||||
{
|
||||
Iter itr = *this;
|
||||
++(*this);
|
||||
return itr;
|
||||
}
|
||||
};
|
||||
|
||||
class ConstIter
|
||||
{
|
||||
mutable Iter iter_;
|
||||
|
||||
friend class HashMap;
|
||||
public:
|
||||
ConstIter() : iter_() {}
|
||||
ConstIter(const ConstIter&) = default;
|
||||
ConstIter(ConstIter&&) noexcept = default;
|
||||
~ConstIter() = default;
|
||||
ConstIter& operator=(const ConstIter&) = default;
|
||||
ConstIter& operator=(ConstIter&&) noexcept = default;
|
||||
|
||||
ConstIter(const Iter& iter) : iter_(iter) {}
|
||||
|
||||
const Entry& operator*() const noexcept { return iter_.cur_->entry; }
|
||||
const Entry* operator->() const noexcept { return &iter_.cur_->entry; }
|
||||
bool operator==(const ConstIter& r) const noexcept { return iter_ == r.iter_; }
|
||||
bool operator!=(const ConstIter& r) const noexcept { return !(*this == r); }
|
||||
ConstIter& operator++() noexcept
|
||||
{
|
||||
++iter_;
|
||||
return *this;
|
||||
}
|
||||
ConstIter operator++(int) noexcept
|
||||
{
|
||||
ConstIter itr = *this;
|
||||
++*this;
|
||||
return itr;
|
||||
}
|
||||
};
|
||||
|
||||
// iter traits
|
||||
using key_type = K;
|
||||
using mapped_type = V;
|
||||
using value_type = Entry;
|
||||
using size_type = uint32_t;
|
||||
using difference_type = int64_t;
|
||||
using hasher = Hasher;
|
||||
using key_equal = KeyEqual;
|
||||
using reference = Entry&;
|
||||
using const_reference = const Entry&;
|
||||
using pointer = Entry*;
|
||||
using const_pointer = const Entry*;
|
||||
using iterator = Iter;
|
||||
using const_iterator = ConstIter;
|
||||
|
||||
private:
|
||||
struct Elem
|
||||
{
|
||||
Elem* prev;
|
||||
Elem* next;
|
||||
Entry entry;
|
||||
};
|
||||
|
||||
Elem** heads_ = nullptr;
|
||||
size_t size_ = 0;
|
||||
uint32_t buckets_;
|
||||
Hasher hasher_;
|
||||
KeyEqual key_equal_;
|
||||
|
||||
constexpr static uint32_t kDefaultBuckets = 16;
|
||||
|
||||
void init_buckets()
|
||||
{
|
||||
if (buckets_ == 0)
|
||||
{
|
||||
buckets_ = kDefaultBuckets;
|
||||
}
|
||||
|
||||
std::allocator<Elem*> allocator;
|
||||
heads_ = allocator.allocate(buckets_);
|
||||
for (uint32_t i = 0; i < buckets_; i++)
|
||||
{
|
||||
heads_[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void init_if_needed()
|
||||
{
|
||||
if (heads_ == nullptr)
|
||||
{
|
||||
init_buckets();
|
||||
}
|
||||
}
|
||||
|
||||
void rehash_if_needed(size_t target_size)
|
||||
{
|
||||
if (target_size >= buckets_)
|
||||
{
|
||||
rehash(std::max<size_t>(target_size, buckets_ * 2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
friend class Iter;
|
||||
friend class ConstIter;
|
||||
|
||||
public:
|
||||
HashMap() : heads_(nullptr), size_(0), buckets_(0), hasher_(), key_equal_()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
HashMap(uint32_t buckets)
|
||||
: heads_(nullptr)
|
||||
, size_(0)
|
||||
, buckets_(buckets)
|
||||
, hasher_()
|
||||
, key_equal_()
|
||||
{
|
||||
init_buckets();
|
||||
}
|
||||
|
||||
HashMap(const HashMap& r)
|
||||
{
|
||||
*this = r;
|
||||
}
|
||||
|
||||
HashMap(HashMap&& r) noexcept
|
||||
{
|
||||
*this = std::move(r);
|
||||
};
|
||||
|
||||
~HashMap()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
HashMap(std::initializer_list<Entry> list) : HashMap(list.size())
|
||||
{
|
||||
for (auto v : list)
|
||||
{
|
||||
insert(v);
|
||||
}
|
||||
}
|
||||
|
||||
HashMap& operator=(const HashMap& r)
|
||||
{
|
||||
clear();
|
||||
buckets_ = r.buckets_;
|
||||
if (buckets_ == 0)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
init_buckets();
|
||||
for (auto itr = r.begin(); itr != r.end(); itr++)
|
||||
{
|
||||
insert({itr->first, itr->second});
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
HashMap& operator=(HashMap&& r) noexcept
|
||||
{
|
||||
std::swap(buckets_, r.buckets_);
|
||||
std::swap(size_, r.size_);
|
||||
std::swap(heads_, r.heads_);
|
||||
std::swap(hasher_, r.hasher_);
|
||||
std::swap(key_equal_, r.key_equal_);
|
||||
return *this;
|
||||
};
|
||||
|
||||
constexpr bool empty() const noexcept { return size_ == 0; }
|
||||
constexpr size_t size() const noexcept { return size_; }
|
||||
constexpr uint32_t buckets() const noexcept { return buckets_; }
|
||||
|
||||
Iter begin() noexcept
|
||||
{
|
||||
if (size_ == 0)
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
Iter ret = end();
|
||||
for (uint32_t i = 0; i < buckets_; i++)
|
||||
{
|
||||
Elem* ptr = heads_[i];
|
||||
if (ptr != nullptr)
|
||||
{
|
||||
ret = Iter { this, i, ptr };
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ConstIter cbegin() const noexcept
|
||||
{
|
||||
ConstIter ret = end();
|
||||
for (uint32_t i = 0; i < buckets_; i++)
|
||||
{
|
||||
Elem* ptr = heads_[i];
|
||||
if (ptr != nullptr)
|
||||
{
|
||||
ret = ConstIter { Iter { this, i, ptr } };
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ConstIter begin() const noexcept { return cbegin(); }
|
||||
|
||||
constexpr Iter end() noexcept { return Iter(); }
|
||||
|
||||
constexpr ConstIter cend() const noexcept { return ConstIter(); }
|
||||
|
||||
constexpr ConstIter end() const noexcept { return cend(); }
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (heads_)
|
||||
{
|
||||
std::allocator<Elem> elem_allocator;
|
||||
for (uint32_t i = 0; i < buckets_; i++)
|
||||
{
|
||||
auto itr = heads_[i];
|
||||
while (itr != nullptr)
|
||||
{
|
||||
auto nextitr = itr->next;
|
||||
itr->~Elem();
|
||||
elem_allocator.deallocate(itr, 1);
|
||||
itr = nextitr;
|
||||
}
|
||||
}
|
||||
|
||||
std::allocator<Elem*> buckets_allocator;
|
||||
buckets_allocator.deallocate(heads_, buckets_);
|
||||
}
|
||||
heads_ = nullptr;
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
Iter find(const K& key)
|
||||
{
|
||||
if (buckets_ == 0 || heads_ == nullptr)
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
uint32_t bucket = (hasher_)(key) % buckets_;
|
||||
for (Elem* p = heads_[bucket]; p != nullptr; p = p->next)
|
||||
{
|
||||
if ((key_equal_)(p->entry.first, key))
|
||||
{
|
||||
return Iter { this, bucket, p };
|
||||
}
|
||||
};
|
||||
return end();
|
||||
}
|
||||
|
||||
ConstIter find(const K& key) const
|
||||
{
|
||||
Iter iter = const_cast<HashMap*>(this)->find(key);
|
||||
return ConstIter { iter };
|
||||
}
|
||||
|
||||
std::pair<Iter, bool> insert(const Entry& value)
|
||||
{
|
||||
Entry copy = value;
|
||||
return insert(std::move(copy));
|
||||
}
|
||||
|
||||
void rehash(uint32_t count)
|
||||
{
|
||||
count = size_ > count ? size_ : count;
|
||||
HashMap rehashed { count };
|
||||
for (Iter itr = begin(); itr != end();)
|
||||
{
|
||||
Iter itrcopy = itr;
|
||||
++itr;
|
||||
|
||||
uint32_t oldbucket = itrcopy.bucket_;
|
||||
if (heads_[oldbucket] == itrcopy.cur_)
|
||||
{
|
||||
heads_[oldbucket] = nullptr;
|
||||
}
|
||||
itrcopy.self_ = &rehashed;
|
||||
itrcopy.bucket_ = (rehashed.hasher_)(itrcopy.cur_->entry.first) % count;
|
||||
Elem* p = rehashed.heads_[itrcopy.bucket_];
|
||||
if (p == nullptr)
|
||||
{
|
||||
p = rehashed.heads_[itrcopy.bucket_] = itrcopy.cur_;
|
||||
size_ -= 1;
|
||||
rehashed.size_ += 1;
|
||||
|
||||
if (p->next)
|
||||
{
|
||||
p->next->prev = nullptr;
|
||||
}
|
||||
if (p->prev)
|
||||
{
|
||||
p->prev->next = nullptr;
|
||||
}
|
||||
p->next = nullptr;
|
||||
p->prev = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; p != nullptr; p = p->next)
|
||||
{
|
||||
if (p->next != nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
p->next = itrcopy.cur_;
|
||||
size_ -= 1;
|
||||
rehashed.size_ += 1;
|
||||
p->next->prev = p;
|
||||
p->next->next = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (heads_)
|
||||
{
|
||||
std::allocator<Elem*> buckets_allocator;
|
||||
buckets_allocator.deallocate(heads_, buckets_);
|
||||
heads_ = nullptr;
|
||||
}
|
||||
|
||||
*this = std::move(rehashed);
|
||||
}
|
||||
|
||||
std::pair<Iter, bool> insert(Entry&& value)
|
||||
{
|
||||
std::pair<Iter, bool> ret { end(), false };
|
||||
std::allocator<Elem> allocator;
|
||||
|
||||
init_if_needed();
|
||||
|
||||
rehash_if_needed(size_ + 1);
|
||||
|
||||
uint32_t bucket = (hasher_)(value.first) % buckets_;
|
||||
Elem* p = heads_[bucket];
|
||||
if (p == nullptr)
|
||||
{
|
||||
// Make a new slot
|
||||
ret.second = true;
|
||||
Elem* newslot = allocator.allocate(1);
|
||||
newslot->prev = nullptr;
|
||||
newslot->next = nullptr;
|
||||
heads_[bucket] = newslot;
|
||||
new (&newslot->entry) Entry { std::move(value) };
|
||||
size_++;
|
||||
ret.first = Iter { this, bucket, newslot };
|
||||
return ret;
|
||||
}
|
||||
|
||||
for(; p != nullptr;)
|
||||
{
|
||||
if ((key_equal_)(p->entry.first, value.first))
|
||||
{
|
||||
ret.second = false;
|
||||
ret.first = Iter { this, bucket, p };
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (p->next == nullptr)
|
||||
{
|
||||
// Make a new slot
|
||||
ret.second = true;
|
||||
Elem* newslot = allocator.allocate(1);
|
||||
newslot->prev = p;
|
||||
newslot->next = nullptr;
|
||||
p->next = newslot;
|
||||
new (&newslot->entry) Entry { std::move(value) };
|
||||
size_++;
|
||||
ret.first = Iter { this, bucket, newslot };
|
||||
return ret;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
std::pair<Iter, bool> insert_or_assign(const K& key, M&& value)
|
||||
{
|
||||
K kcopy = key;
|
||||
return insert_or_assign(std::move(kcopy), std::forward<M>(value));
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
std::pair<Iter, bool> insert_or_assign(K&& key, M&& value)
|
||||
{
|
||||
std::pair<Iter, bool> ret { find(key), false };
|
||||
if (ret.first != end())
|
||||
{
|
||||
ret.first->second = std::forward<M>(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = insert({ std::move(key), std::forward<M>(value) });
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
std::pair<Iter, bool> emplace(Args&&... args)
|
||||
{
|
||||
Entry entry { std::forward<Args>(args)... };
|
||||
return insert(std::move(entry));
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
std::pair<Iter, bool> try_emplace(const K& key, Args&&... args)
|
||||
{
|
||||
Iter itr = find(key);
|
||||
if (itr != end())
|
||||
{
|
||||
return { itr, false };
|
||||
}
|
||||
|
||||
return insert({ key, V(std::forward<Args>(args)...) });
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
std::pair<Iter, bool> try_emplace(K&& key, Args... args)
|
||||
{
|
||||
std::pair<Iter, bool> ret { end(), false };
|
||||
return insert({ std::move(key), V(std::forward<Args>(args)...)});
|
||||
}
|
||||
|
||||
V& operator[](const K& key)
|
||||
{
|
||||
K copy { key };
|
||||
return this->operator[](std::move(copy));
|
||||
}
|
||||
|
||||
V& operator[](K&& key)
|
||||
{
|
||||
std::allocator<Elem> allocator;
|
||||
init_if_needed();
|
||||
|
||||
rehash_if_needed(size_ + 1);
|
||||
|
||||
uint32_t bucket = (hasher_)(key) % buckets_;
|
||||
Elem* p = heads_[bucket];
|
||||
if (p == nullptr)
|
||||
{
|
||||
// Make a new slot
|
||||
Elem* newslot = allocator.allocate(1);
|
||||
newslot->prev = nullptr;
|
||||
newslot->next = nullptr;
|
||||
heads_[bucket] = newslot;
|
||||
new (&newslot->entry) Entry { std::move(key), {} };
|
||||
size_++;
|
||||
return newslot->entry.second;
|
||||
}
|
||||
for (; p != nullptr;)
|
||||
{
|
||||
if ((key_equal_)(p->entry.first, key))
|
||||
{
|
||||
return p->entry.second;
|
||||
}
|
||||
|
||||
if (p->next == nullptr)
|
||||
{
|
||||
// Make a new slot
|
||||
Elem* newslot = allocator.allocate(1);
|
||||
newslot->prev = p;
|
||||
newslot->next = nullptr;
|
||||
p->next = newslot;
|
||||
new (&newslot->entry) Entry { std::move(key), {} };
|
||||
size_++;
|
||||
return newslot->entry.second;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
return end()->second;
|
||||
}
|
||||
|
||||
V& at(const K& key)
|
||||
{
|
||||
auto itr = find(key);
|
||||
if (itr == end())
|
||||
{
|
||||
throw std::out_of_range("key not found");
|
||||
}
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
const V& at(const K& key) const
|
||||
{
|
||||
auto itr = find(key);
|
||||
if (itr == cend())
|
||||
{
|
||||
throw std::out_of_range("key not found");
|
||||
}
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
Iter erase(Iter pos)
|
||||
{
|
||||
Iter ret = pos;
|
||||
if (pos == end())
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
std::allocator<Elem> allocator;
|
||||
uint32_t bucket = (hasher_)(pos.cur_->entry.first) % buckets_;
|
||||
Elem* p = heads_[bucket];
|
||||
for (; p != nullptr;)
|
||||
{
|
||||
if ((key_equal_)(p->entry.first, pos.cur_->entry.first))
|
||||
{
|
||||
// found it; remove, return next iter
|
||||
++ret;
|
||||
if (p->next != nullptr)
|
||||
{
|
||||
p->next->prev = p->prev;
|
||||
}
|
||||
if (p->prev != nullptr)
|
||||
{
|
||||
p->prev->next = p->next;
|
||||
}
|
||||
if (p == heads_[bucket])
|
||||
{
|
||||
heads_[bucket] = p->next;
|
||||
}
|
||||
p->~Elem();
|
||||
allocator.deallocate(p, 1);
|
||||
size_ -= 1;
|
||||
return ret;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Iter erase(ConstIter pos)
|
||||
{
|
||||
return erase(pos.iter_);
|
||||
}
|
||||
|
||||
uint32_t erase(const K& key)
|
||||
{
|
||||
Iter pos = find(key);
|
||||
if (pos != end())
|
||||
{
|
||||
erase(pos);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
#endif // SRB2_CORE_HASH_MAP_HPP
|
||||
32
src/core/hash_set.cpp
Normal file
32
src/core/hash_set.cpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2025 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "hash_set.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
template class HashSet<bool>;
|
||||
template class HashSet<uint8_t>;
|
||||
template class HashSet<uint16_t>;
|
||||
template class HashSet<uint32_t>;
|
||||
template class HashSet<uint64_t>;
|
||||
template class HashSet<int8_t>;
|
||||
template class HashSet<int16_t>;
|
||||
template class HashSet<int32_t>;
|
||||
template class HashSet<int64_t>;
|
||||
template class HashSet<String>;
|
||||
template class HashSet<std::string>;
|
||||
|
||||
} // namespace srb2
|
||||
214
src/core/hash_set.hpp
Normal file
214
src/core/hash_set.hpp
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2025 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef SRB2_CORE_HASH_SET_HPP
|
||||
#define SRB2_CORE_HASH_SET_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "hash_map.hpp"
|
||||
#include "string.h"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
template <typename V>
|
||||
class HashSet
|
||||
{
|
||||
using Inner = HashMap<V, uint8_t>;
|
||||
|
||||
public:
|
||||
class Iter
|
||||
{
|
||||
typename Inner::Iter iter_;
|
||||
|
||||
Iter(typename Inner::Iter iter) : iter_(iter) {}
|
||||
|
||||
friend class HashSet;
|
||||
friend class ConstIter;
|
||||
|
||||
public:
|
||||
Iter() = default;
|
||||
Iter(const Iter&) = default;
|
||||
Iter(Iter&&) noexcept = default;
|
||||
~Iter() = default;
|
||||
|
||||
Iter& operator=(const Iter&) = default;
|
||||
Iter& operator=(Iter&&) noexcept = default;
|
||||
|
||||
bool operator==(const Iter& r) const noexcept { return iter_ == r.iter_; }
|
||||
bool operator!=(const Iter& r) const noexcept { return !(*this == r); }
|
||||
|
||||
V& operator*() const noexcept { return iter_->first; }
|
||||
V* operator->() const noexcept { return &iter_->first; }
|
||||
Iter& operator++() noexcept
|
||||
{
|
||||
++iter_;
|
||||
return *this;
|
||||
}
|
||||
Iter operator++(int) noexcept
|
||||
{
|
||||
Iter self = *this;
|
||||
++*this;
|
||||
return self;
|
||||
}
|
||||
};
|
||||
|
||||
class ConstIter
|
||||
{
|
||||
typename Inner::ConstIter iter_;
|
||||
|
||||
friend class HashSet;
|
||||
friend class Iter;
|
||||
|
||||
public:
|
||||
ConstIter() = default;
|
||||
ConstIter(const ConstIter&) = default;
|
||||
ConstIter(ConstIter&&) noexcept = default;
|
||||
~ConstIter() = default;
|
||||
|
||||
ConstIter(const Iter& iter) : iter_(iter.iter_) {}
|
||||
ConstIter(const typename Inner::ConstIter& iter) : iter_(iter) {}
|
||||
|
||||
ConstIter& operator=(const ConstIter&) = default;
|
||||
ConstIter& operator=(ConstIter&&) noexcept = default;
|
||||
|
||||
bool operator==(const ConstIter& r) const noexcept { return iter_ == r.iter_; }
|
||||
bool operator!=(const ConstIter& r) const noexcept { return !(*this == r); }
|
||||
|
||||
const V& operator*() const noexcept { return iter_->first; }
|
||||
const V* operator->() const noexcept { return &iter_->first; }
|
||||
ConstIter& operator++() noexcept
|
||||
{
|
||||
++iter_;
|
||||
return *this;
|
||||
}
|
||||
ConstIter operator++(int) noexcept
|
||||
{
|
||||
ConstIter self = *this;
|
||||
++*this;
|
||||
return self;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
Inner map_;
|
||||
|
||||
public:
|
||||
using key_type = V;
|
||||
using value_type = V;
|
||||
using size_type = typename Inner::size_type;
|
||||
using difference_type = typename Inner::difference_type;
|
||||
using hasher = typename Inner::hasher;
|
||||
using key_equal = typename Inner::key_equal;
|
||||
using reference = V&;
|
||||
using const_reference = const V&;
|
||||
using pointer = V*;
|
||||
using const_pointer = const V*;
|
||||
using iterator = Iter;
|
||||
using const_iterator = ConstIter;
|
||||
|
||||
HashSet() = default;
|
||||
HashSet(const HashSet&) = default;
|
||||
HashSet(HashSet&&) noexcept = default;
|
||||
~HashSet() = default;
|
||||
|
||||
HashSet& operator=(const HashSet&) = default;
|
||||
HashSet& operator=(HashSet&&) noexcept = default;
|
||||
|
||||
Iter begin() { return map_.begin(); }
|
||||
Iter end() { return map_.end(); }
|
||||
ConstIter cbegin() const { return map_.cbegin(); }
|
||||
ConstIter cend() const { return map_.cend(); }
|
||||
ConstIter begin() const { return cbegin(); }
|
||||
ConstIter end() const { return cend(); }
|
||||
|
||||
bool empty() const noexcept { return map_.empty(); }
|
||||
size_t size() const noexcept { return map_.size(); }
|
||||
|
||||
void clear() { map_.clear(); }
|
||||
|
||||
std::pair<Iter, bool> insert(const V& value)
|
||||
{
|
||||
V copy { value };
|
||||
return insert(std::move(copy));
|
||||
}
|
||||
|
||||
std::pair<Iter, bool> insert(V&& value)
|
||||
{
|
||||
return emplace(std::move(value));
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
std::pair<Iter, bool> emplace(Args&&... args)
|
||||
{
|
||||
std::pair<Iter, bool> res;
|
||||
auto [map_iter, map_inserted] = map_.emplace(std::forward<Args&&>(args)..., 0);
|
||||
res.first = map_iter;
|
||||
res.second = map_inserted;
|
||||
return res;
|
||||
}
|
||||
|
||||
Iter erase(Iter pos)
|
||||
{
|
||||
auto map_ret = map_.erase(pos.iter_);
|
||||
return map_ret;
|
||||
}
|
||||
|
||||
Iter erase(ConstIter pos)
|
||||
{
|
||||
auto map_ret = map_.erase(pos.iter_);
|
||||
return map_ret;
|
||||
}
|
||||
|
||||
Iter erase(ConstIter first, ConstIter last)
|
||||
{
|
||||
ConstIter iter;
|
||||
for (iter = first; iter != last;)
|
||||
{
|
||||
iter = erase(iter);
|
||||
}
|
||||
return typename Inner::Iter(iter.iter_);
|
||||
}
|
||||
|
||||
Iter find(const V& value)
|
||||
{
|
||||
auto map_ret = map_.find(value);
|
||||
return map_ret;
|
||||
}
|
||||
|
||||
ConstIter find(const V& value) const
|
||||
{
|
||||
auto map_ret = map_.find(value);
|
||||
return map_ret;
|
||||
}
|
||||
|
||||
void rehash(size_t count)
|
||||
{
|
||||
map_.rehash(count);
|
||||
}
|
||||
};
|
||||
|
||||
extern template class HashSet<bool>;
|
||||
extern template class HashSet<uint8_t>;
|
||||
extern template class HashSet<uint16_t>;
|
||||
extern template class HashSet<uint32_t>;
|
||||
extern template class HashSet<uint64_t>;
|
||||
extern template class HashSet<int8_t>;
|
||||
extern template class HashSet<int16_t>;
|
||||
extern template class HashSet<int32_t>;
|
||||
extern template class HashSet<int64_t>;
|
||||
extern template class HashSet<String>;
|
||||
extern template class HashSet<std::string>;
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
#endif // SRB2_CORE_HASH_SET_HPP
|
||||
1809
src/core/json.cpp
Normal file
1809
src/core/json.cpp
Normal file
File diff suppressed because it is too large
Load diff
533
src/core/json.hpp
Normal file
533
src/core/json.hpp
Normal file
|
|
@ -0,0 +1,533 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2025 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef SRB2_CORE_JSON_HPP
|
||||
#define SRB2_CORE_JSON_HPP
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <tcb/span.hpp>
|
||||
|
||||
#include "hash_map.hpp"
|
||||
#include "string.h"
|
||||
#include "vector.hpp"
|
||||
|
||||
#include "json_macro.inl"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
class JsonValue;
|
||||
|
||||
using JsonArray = Vector<JsonValue>;
|
||||
using JsonObject = HashMap<String, JsonValue>;
|
||||
|
||||
class JsonError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
JsonError(const std::string& what);
|
||||
JsonError(const char* what);
|
||||
JsonError(const JsonError&) noexcept;
|
||||
};
|
||||
|
||||
class JsonParseError : public JsonError
|
||||
{
|
||||
public:
|
||||
JsonParseError(const std::string& what);
|
||||
JsonParseError(const char* what);
|
||||
JsonParseError(const JsonParseError&) noexcept;
|
||||
};
|
||||
|
||||
class JsonValue
|
||||
{
|
||||
public:
|
||||
enum class Type : int
|
||||
{
|
||||
kNull,
|
||||
kBoolean,
|
||||
kNumber,
|
||||
kString,
|
||||
kArray,
|
||||
kObject
|
||||
};
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
union {
|
||||
struct {} dummy;
|
||||
bool boolean_;
|
||||
double number_;
|
||||
String string_;
|
||||
JsonArray array_;
|
||||
JsonObject object_;
|
||||
};
|
||||
|
||||
static void value_to_ubjson(srb2::Vector<std::byte>& out);
|
||||
static void value_to_ubjson(srb2::Vector<std::byte>& out, bool value);
|
||||
static void value_to_ubjson(srb2::Vector<std::byte>& out, double value);
|
||||
static void value_to_ubjson(srb2::Vector<std::byte>& out, uint64_t value);
|
||||
static void value_to_ubjson(srb2::Vector<std::byte>& out, const String& value, bool include_type);
|
||||
static void value_to_ubjson(srb2::Vector<std::byte>& out, const JsonArray& value);
|
||||
static void value_to_ubjson(srb2::Vector<std::byte>& out, const JsonObject& value);
|
||||
|
||||
void do_to_ubjson(srb2::Vector<std::byte>& out) const;
|
||||
|
||||
public:
|
||||
JsonValue();
|
||||
JsonValue(const JsonValue&);
|
||||
JsonValue(JsonValue&&) noexcept;
|
||||
~JsonValue();
|
||||
JsonValue& operator=(const JsonValue&);
|
||||
JsonValue& operator=(JsonValue&&) noexcept;
|
||||
|
||||
JsonValue(const String& value);
|
||||
JsonValue(String&& value);
|
||||
JsonValue(const JsonArray& value);
|
||||
JsonValue(JsonArray&& value);
|
||||
JsonValue(const JsonObject& value);
|
||||
JsonValue(JsonObject&& value);
|
||||
JsonValue(float value);
|
||||
JsonValue(double value);
|
||||
JsonValue(int8_t value);
|
||||
JsonValue(int16_t value);
|
||||
JsonValue(int32_t value);
|
||||
JsonValue(int64_t value);
|
||||
JsonValue(uint8_t value);
|
||||
JsonValue(uint16_t value);
|
||||
JsonValue(uint32_t value);
|
||||
JsonValue(uint64_t value);
|
||||
JsonValue(bool value);
|
||||
|
||||
static JsonValue array() { return JsonValue(JsonArray()); }
|
||||
static JsonValue object() { return JsonValue(JsonObject()); }
|
||||
|
||||
bool operator==(const JsonValue& rhs) const;
|
||||
bool operator!=(const JsonValue& rhs) const { return !(*this == rhs); }
|
||||
|
||||
void to_json(JsonValue& to) const;
|
||||
void from_json(const JsonValue& from);
|
||||
String to_json_string() const;
|
||||
static JsonValue from_json_string(const String& str);
|
||||
srb2::Vector<std::byte> to_ubjson() const;
|
||||
static JsonValue from_ubjson(tcb::span<const std::byte> ubjson);
|
||||
constexpr Type type() const noexcept { return type_; }
|
||||
|
||||
template <typename V> V get() const;
|
||||
|
||||
constexpr bool is_null() const noexcept { return type_ == Type::kNull; }
|
||||
constexpr bool is_boolean() const noexcept { return type_ == Type::kBoolean; }
|
||||
constexpr bool is_number() const noexcept { return type_ == Type::kNumber; }
|
||||
constexpr bool is_string() const noexcept { return type_ == Type::kString; }
|
||||
constexpr bool is_array() const noexcept { return type_ == Type::kArray; }
|
||||
constexpr bool is_object() const noexcept { return type_ == Type::kObject; }
|
||||
JsonArray& as_array();
|
||||
JsonObject& as_object();
|
||||
const JsonArray& as_array() const;
|
||||
const JsonObject& as_object() const;
|
||||
|
||||
JsonValue& at(uint32_t i);
|
||||
const JsonValue& at(uint32_t i) const;
|
||||
JsonValue& at(const char* key);
|
||||
JsonValue& at(const String& key);
|
||||
const JsonValue& at(const char* key) const;
|
||||
const JsonValue& at(const String& key) const;
|
||||
|
||||
template <typename V>
|
||||
V value(const char* key, const V& def) const;
|
||||
template <typename V>
|
||||
V value(const String& key, const V& def) const;
|
||||
template <typename V>
|
||||
V value(const char* key, V&& def) const;
|
||||
template <typename V>
|
||||
V value(const String& key, V&& def) const;
|
||||
|
||||
bool contains(const char* key) const;
|
||||
bool contains(const String& key) const;
|
||||
|
||||
JsonValue& operator[](uint32_t i);
|
||||
JsonValue& operator[](const char* key);
|
||||
JsonValue& operator[](const String& key);
|
||||
};
|
||||
|
||||
void to_json(JsonValue& to, bool value);
|
||||
void to_json(JsonValue& to, int8_t value);
|
||||
void to_json(JsonValue& to, int16_t value);
|
||||
void to_json(JsonValue& to, int32_t value);
|
||||
void to_json(JsonValue& to, int64_t value);
|
||||
void to_json(JsonValue& to, uint8_t value);
|
||||
void to_json(JsonValue& to, uint16_t value);
|
||||
void to_json(JsonValue& to, uint32_t value);
|
||||
void to_json(JsonValue& to, uint64_t value);
|
||||
void to_json(JsonValue& to, float value);
|
||||
void to_json(JsonValue& to, double value);
|
||||
void to_json(JsonValue& to, const String& value);
|
||||
void to_json(JsonValue& to, const JsonArray& value);
|
||||
void to_json(JsonValue& to, const JsonObject& value);
|
||||
|
||||
void from_json(const JsonValue& to, bool& value);
|
||||
void from_json(const JsonValue& to, int8_t& value);
|
||||
void from_json(const JsonValue& to, int16_t& value);
|
||||
void from_json(const JsonValue& to, int32_t& value);
|
||||
void from_json(const JsonValue& to, int64_t& value);
|
||||
void from_json(const JsonValue& to, uint8_t& value);
|
||||
void from_json(const JsonValue& to, uint16_t& value);
|
||||
void from_json(const JsonValue& to, uint32_t& value);
|
||||
void from_json(const JsonValue& to, uint64_t& value);
|
||||
void from_json(const JsonValue& to, float& value);
|
||||
void from_json(const JsonValue& to, double& value);
|
||||
void from_json(const JsonValue& to, String& value);
|
||||
void from_json(const JsonValue& to, JsonArray& value);
|
||||
void from_json(const JsonValue& to, JsonObject& value);
|
||||
|
||||
template <typename T, size_t S>
|
||||
inline void to_json(JsonValue& to, const std::array<T, S>& v)
|
||||
{
|
||||
JsonArray arr;
|
||||
for (auto itr = v.begin(); itr != v.end(); itr++)
|
||||
{
|
||||
JsonValue conv;
|
||||
to_json(conv, *itr);
|
||||
arr.push_back(conv);
|
||||
}
|
||||
to = JsonValue(std::move(arr));
|
||||
}
|
||||
|
||||
template <typename T, size_t S>
|
||||
inline void from_json(const JsonValue& to, std::array<T, S>& v)
|
||||
{
|
||||
if (!to.is_array())
|
||||
{
|
||||
throw JsonError("json value must be an array");
|
||||
}
|
||||
const JsonArray& arr = to.as_array();
|
||||
size_t si = 0;
|
||||
for (auto& i : arr)
|
||||
{
|
||||
if (si >= v.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
T conv;
|
||||
from_json(i, conv);
|
||||
v[si] = std::move(conv);
|
||||
si++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename A>
|
||||
inline void to_json(JsonValue& to, const std::vector<T, A>& v)
|
||||
{
|
||||
JsonArray arr;
|
||||
for (auto itr = v.begin(); itr != v.end(); itr++)
|
||||
{
|
||||
JsonValue conv;
|
||||
to_json(conv, *itr);
|
||||
arr.push_back(conv);
|
||||
}
|
||||
to = JsonValue(std::move(arr));
|
||||
}
|
||||
|
||||
template <typename T, typename A>
|
||||
inline void from_json(const JsonValue& to, std::vector<T, A>& v)
|
||||
{
|
||||
if (!to.is_array())
|
||||
{
|
||||
throw JsonError("json value must be an array");
|
||||
}
|
||||
v.clear();
|
||||
const JsonArray& arr = to.as_array();
|
||||
for (auto& i : arr)
|
||||
{
|
||||
T conv;
|
||||
from_json(i, conv);
|
||||
v.push_back(std::move(conv));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void to_json(JsonValue& to, const srb2::Vector<T>& v)
|
||||
{
|
||||
JsonArray arr;
|
||||
for (auto itr = v.begin(); itr != v.end(); itr++)
|
||||
{
|
||||
JsonValue conv;
|
||||
to_json(conv, *itr);
|
||||
arr.push_back(conv);
|
||||
}
|
||||
to = JsonValue(std::move(arr));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void from_json(const JsonValue& to, srb2::Vector<T>& v)
|
||||
{
|
||||
if (!to.is_array())
|
||||
{
|
||||
throw JsonError("json value must be an array");
|
||||
}
|
||||
v.clear();
|
||||
const JsonArray& arr = to.as_array();
|
||||
for (auto& i : arr)
|
||||
{
|
||||
T conv;
|
||||
from_json(i, conv);
|
||||
v.push_back(std::move(conv));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename K, typename V, typename H, typename E, typename A>
|
||||
inline void to_json(JsonValue& to, const std::unordered_map<K, V, H, E, A>& v)
|
||||
{
|
||||
JsonObject obj;
|
||||
for (auto itr = v.begin(); itr != v.end(); itr++)
|
||||
{
|
||||
to_json(obj[itr->first], itr->second);
|
||||
}
|
||||
to = JsonValue(std::move(obj));
|
||||
}
|
||||
|
||||
template <typename K, typename V, typename H, typename E, typename A>
|
||||
inline void from_json(const JsonValue& to, std::unordered_map<K, V, H, E, A>& v)
|
||||
{
|
||||
if (!to.is_object())
|
||||
{
|
||||
throw JsonError("json value must be an object");
|
||||
}
|
||||
v.clear();
|
||||
const JsonObject& obj = to.as_object();
|
||||
for (auto itr = obj.begin(); itr != obj.end(); itr++)
|
||||
{
|
||||
V conv;
|
||||
from_json(itr->second, conv);
|
||||
v[itr->first] = std::move(conv);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
inline void to_json(JsonValue& to, const srb2::HashMap<K, V>& v)
|
||||
{
|
||||
JsonObject obj;
|
||||
for (auto itr = v.begin(); itr != v.end(); itr++)
|
||||
{
|
||||
to_json(obj[itr->first], itr->second);
|
||||
}
|
||||
to = JsonValue(std::move(obj));
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
inline void from_json(const JsonValue& to, srb2::HashMap<K, V>& v)
|
||||
{
|
||||
if (!to.is_object())
|
||||
{
|
||||
throw JsonError("json value must be an object");
|
||||
}
|
||||
v.clear();
|
||||
const JsonObject& obj = to.as_object();
|
||||
for (auto itr = obj.begin(); itr != obj.end(); itr++)
|
||||
{
|
||||
V conv;
|
||||
from_json(itr->second, conv);
|
||||
v[itr->first] = std::move(conv);
|
||||
}
|
||||
}
|
||||
|
||||
void from_json(const JsonValue& to, std::string& v);
|
||||
void to_json(JsonValue& to, const std::string& v);
|
||||
|
||||
// template <typename K, typename V>
|
||||
// inline void to_json(JsonValue& to, const srb2::OAHashMap<K, V>& v)
|
||||
// {
|
||||
// JsonObject obj;
|
||||
// for (auto itr = v.begin(); itr != v.end(); itr++)
|
||||
// {
|
||||
// to_json(obj[itr->first], itr->second);
|
||||
// }
|
||||
// to = JsonValue(std::move(obj));
|
||||
// }
|
||||
|
||||
// template <typename K, typename V>
|
||||
// inline void from_json(const JsonValue& to, srb2::OAHashMap<K, V>& v)
|
||||
// {
|
||||
// if (!to.is_object())
|
||||
// {
|
||||
// throw JsonError("json value must be an object");
|
||||
// }
|
||||
// v.clear();
|
||||
// const JsonObject& obj = to.as_object();
|
||||
// for (auto itr = obj.begin(); itr != obj.end(); itr++)
|
||||
// {
|
||||
// V conv;
|
||||
// from_json(itr->second, conv);
|
||||
// v[itr->first] = std::move(conv);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
template <typename V>
|
||||
inline V JsonValue::get() const
|
||||
{
|
||||
V v;
|
||||
from_json(*this, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
inline V JsonValue::value(const char* key, const V& def) const
|
||||
{
|
||||
V copy { def };
|
||||
return value(key, std::move(copy));
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
inline V JsonValue::value(const String& key, const V& def) const
|
||||
{
|
||||
return value(key.c_str(), def);
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
inline V JsonValue::value(const char* key, V&& def) const
|
||||
{
|
||||
const JsonObject& obj = as_object();
|
||||
auto itr = obj.find(key);
|
||||
if (itr != obj.end())
|
||||
{
|
||||
return itr->second.get<V>();
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
template <> bool JsonValue::get() const;
|
||||
template <> int8_t JsonValue::get() const;
|
||||
template <> int16_t JsonValue::get() const;
|
||||
template <> int32_t JsonValue::get() const;
|
||||
template <> int64_t JsonValue::get() const;
|
||||
template <> uint8_t JsonValue::get() const;
|
||||
template <> uint16_t JsonValue::get() const;
|
||||
template <> uint32_t JsonValue::get() const;
|
||||
template <> uint64_t JsonValue::get() const;
|
||||
template <> float JsonValue::get() const;
|
||||
template <> double JsonValue::get() const;
|
||||
template <> String JsonValue::get() const;
|
||||
template <> std::string JsonValue::get() const;
|
||||
template <> std::string_view JsonValue::get() const;
|
||||
template <> JsonArray JsonValue::get() const;
|
||||
template <> JsonObject JsonValue::get() const;
|
||||
template <> JsonValue JsonValue::get() const;
|
||||
|
||||
inline bool operator==(const JsonValue& lhs, bool rhs)
|
||||
{
|
||||
if (!lhs.is_boolean())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return lhs.get<bool>() == rhs;
|
||||
}
|
||||
|
||||
inline bool operator==(const JsonValue& lhs, int64_t rhs)
|
||||
{
|
||||
if (!lhs.is_number())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return lhs.get<int64_t>() == rhs;
|
||||
}
|
||||
|
||||
inline bool operator==(const JsonValue& lhs, uint64_t rhs)
|
||||
{
|
||||
if (!lhs.is_number())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return lhs.get<uint64_t>() == rhs;
|
||||
}
|
||||
|
||||
inline bool operator==(const JsonValue& lhs, double rhs)
|
||||
{
|
||||
if (!lhs.is_number())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return lhs.get<double>() == rhs;
|
||||
}
|
||||
|
||||
inline bool operator==(const JsonValue& lhs, std::string_view rhs)
|
||||
{
|
||||
if (!lhs.is_string())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return lhs.get<std::string_view>() == rhs;
|
||||
}
|
||||
|
||||
inline bool operator==(const JsonValue& lhs, const JsonArray& rhs)
|
||||
{
|
||||
if (!lhs.is_array())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return lhs.as_array() == rhs;
|
||||
}
|
||||
|
||||
inline bool operator==(const JsonValue& lhs, const JsonObject& rhs)
|
||||
{
|
||||
if (!lhs.is_object())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return lhs.as_object() == rhs;
|
||||
}
|
||||
|
||||
inline bool operator!=(const JsonValue& lhs, bool rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const JsonValue& lhs, int64_t rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const JsonValue& lhs, uint64_t rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const JsonValue& lhs, double rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const JsonValue& lhs, std::string_view rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const JsonValue& lhs, const JsonArray& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const JsonValue& lhs, const JsonObject& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
extern template class Vector<srb2::JsonValue>;
|
||||
extern template class HashMap<String, srb2::JsonValue>;
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
#endif // SRB2_CORE_JSON_HPP
|
||||
185
src/core/json_macro.inl
Normal file
185
src/core/json_macro.inl
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++
|
||||
// | | |__ | | | | | | version 3.11.3
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// file: macro_scope.hpp
|
||||
|
||||
// This file is derived from nlohmman json's codegen macros and thus is provided under its license.
|
||||
|
||||
#define SRB2_JSON_EXPAND( x ) x
|
||||
#define SRB2_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
|
||||
#define SRB2_JSON_PASTE(...) SRB2_JSON_EXPAND(SRB2_JSON_GET_MACRO(__VA_ARGS__, \
|
||||
SRB2_JSON_PASTE64, \
|
||||
SRB2_JSON_PASTE63, \
|
||||
SRB2_JSON_PASTE62, \
|
||||
SRB2_JSON_PASTE61, \
|
||||
SRB2_JSON_PASTE60, \
|
||||
SRB2_JSON_PASTE59, \
|
||||
SRB2_JSON_PASTE58, \
|
||||
SRB2_JSON_PASTE57, \
|
||||
SRB2_JSON_PASTE56, \
|
||||
SRB2_JSON_PASTE55, \
|
||||
SRB2_JSON_PASTE54, \
|
||||
SRB2_JSON_PASTE53, \
|
||||
SRB2_JSON_PASTE52, \
|
||||
SRB2_JSON_PASTE51, \
|
||||
SRB2_JSON_PASTE50, \
|
||||
SRB2_JSON_PASTE49, \
|
||||
SRB2_JSON_PASTE48, \
|
||||
SRB2_JSON_PASTE47, \
|
||||
SRB2_JSON_PASTE46, \
|
||||
SRB2_JSON_PASTE45, \
|
||||
SRB2_JSON_PASTE44, \
|
||||
SRB2_JSON_PASTE43, \
|
||||
SRB2_JSON_PASTE42, \
|
||||
SRB2_JSON_PASTE41, \
|
||||
SRB2_JSON_PASTE40, \
|
||||
SRB2_JSON_PASTE39, \
|
||||
SRB2_JSON_PASTE38, \
|
||||
SRB2_JSON_PASTE37, \
|
||||
SRB2_JSON_PASTE36, \
|
||||
SRB2_JSON_PASTE35, \
|
||||
SRB2_JSON_PASTE34, \
|
||||
SRB2_JSON_PASTE33, \
|
||||
SRB2_JSON_PASTE32, \
|
||||
SRB2_JSON_PASTE31, \
|
||||
SRB2_JSON_PASTE30, \
|
||||
SRB2_JSON_PASTE29, \
|
||||
SRB2_JSON_PASTE28, \
|
||||
SRB2_JSON_PASTE27, \
|
||||
SRB2_JSON_PASTE26, \
|
||||
SRB2_JSON_PASTE25, \
|
||||
SRB2_JSON_PASTE24, \
|
||||
SRB2_JSON_PASTE23, \
|
||||
SRB2_JSON_PASTE22, \
|
||||
SRB2_JSON_PASTE21, \
|
||||
SRB2_JSON_PASTE20, \
|
||||
SRB2_JSON_PASTE19, \
|
||||
SRB2_JSON_PASTE18, \
|
||||
SRB2_JSON_PASTE17, \
|
||||
SRB2_JSON_PASTE16, \
|
||||
SRB2_JSON_PASTE15, \
|
||||
SRB2_JSON_PASTE14, \
|
||||
SRB2_JSON_PASTE13, \
|
||||
SRB2_JSON_PASTE12, \
|
||||
SRB2_JSON_PASTE11, \
|
||||
SRB2_JSON_PASTE10, \
|
||||
SRB2_JSON_PASTE9, \
|
||||
SRB2_JSON_PASTE8, \
|
||||
SRB2_JSON_PASTE7, \
|
||||
SRB2_JSON_PASTE6, \
|
||||
SRB2_JSON_PASTE5, \
|
||||
SRB2_JSON_PASTE4, \
|
||||
SRB2_JSON_PASTE3, \
|
||||
SRB2_JSON_PASTE2, \
|
||||
SRB2_JSON_PASTE1)(__VA_ARGS__))
|
||||
#define SRB2_JSON_PASTE2(func, v1) func(v1)
|
||||
#define SRB2_JSON_PASTE3(func, v1, v2) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE2(func, v2)
|
||||
#define SRB2_JSON_PASTE4(func, v1, v2, v3) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE3(func, v2, v3)
|
||||
#define SRB2_JSON_PASTE5(func, v1, v2, v3, v4) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE4(func, v2, v3, v4)
|
||||
#define SRB2_JSON_PASTE6(func, v1, v2, v3, v4, v5) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE5(func, v2, v3, v4, v5)
|
||||
#define SRB2_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE6(func, v2, v3, v4, v5, v6)
|
||||
#define SRB2_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
|
||||
#define SRB2_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
|
||||
#define SRB2_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
|
||||
#define SRB2_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
|
||||
#define SRB2_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
|
||||
#define SRB2_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
|
||||
#define SRB2_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
|
||||
#define SRB2_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
|
||||
#define SRB2_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
|
||||
#define SRB2_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
|
||||
#define SRB2_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
|
||||
#define SRB2_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
|
||||
#define SRB2_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
|
||||
#define SRB2_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
|
||||
#define SRB2_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
|
||||
#define SRB2_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
|
||||
#define SRB2_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
|
||||
#define SRB2_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
|
||||
#define SRB2_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
|
||||
#define SRB2_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
|
||||
#define SRB2_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
|
||||
#define SRB2_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
|
||||
#define SRB2_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
|
||||
#define SRB2_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
|
||||
#define SRB2_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
|
||||
#define SRB2_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
|
||||
#define SRB2_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
|
||||
#define SRB2_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
|
||||
#define SRB2_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
|
||||
#define SRB2_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
|
||||
#define SRB2_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
|
||||
#define SRB2_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
|
||||
#define SRB2_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
|
||||
#define SRB2_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
|
||||
#define SRB2_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
|
||||
#define SRB2_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
|
||||
#define SRB2_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
|
||||
#define SRB2_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
|
||||
#define SRB2_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
|
||||
#define SRB2_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
|
||||
#define SRB2_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
|
||||
#define SRB2_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
|
||||
#define SRB2_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
|
||||
#define SRB2_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
|
||||
#define SRB2_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
|
||||
#define SRB2_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
|
||||
#define SRB2_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
|
||||
#define SRB2_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
|
||||
#define SRB2_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
|
||||
#define SRB2_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
|
||||
#define SRB2_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
|
||||
#define SRB2_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
|
||||
#define SRB2_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
|
||||
#define SRB2_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
|
||||
#define SRB2_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
|
||||
#define SRB2_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
|
||||
#define SRB2_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) SRB2_JSON_PASTE2(func, v1) SRB2_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
|
||||
|
||||
#define SRB2_JSON_TO(v1) to_json(srb2_json_j.as_object()[#v1], srb2_json_t.v1);
|
||||
#define SRB2_JSON_FROM(v1) srb2_json_t.v1 = srb2_json_j.as_object().at(#v1);
|
||||
#define SRB2_JSON_FROM_WITH_DEFAULT(v1) if (srb2_json_j.as_object().find(#v1) != srb2_json_j.as_object().end()) \
|
||||
{ \
|
||||
from_json(srb2_json_j.as_object().find(#v1)->second, srb2_json_t.v1); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
srb2_json_t.v1 = srb2_json_default_obj.v1; \
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief macro
|
||||
@def SRB2_JSON_DEFINE_TYPE_INTRUSIVE
|
||||
@since version 3.9.0
|
||||
*/
|
||||
#define SRB2_JSON_DEFINE_TYPE_INTRUSIVE(Type, ...) \
|
||||
friend void to_json(srb2::JsonValue& srb2_json_j, const Type& srb2_json_t) { srb2_json_j = srb2::JsonObject(); SRB2_JSON_EXPAND(SRB2_JSON_PASTE(SRB2_JSON_TO, __VA_ARGS__)) } \
|
||||
friend void from_json(const srb2::JsonValue& srb2_json_j, Type& srb2_json_t) { SRB2_JSON_EXPAND(SRB2_JSON_PASTE(SRB2_JSON_FROM, __VA_ARGS__)) }
|
||||
|
||||
#define SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
|
||||
friend void to_json(srb2::JsonValue& srb2_json_j, const Type& srb2_json_t) { srb2_json_j = srb2::JsonObject(); SRB2_JSON_EXPAND(SRB2_JSON_PASTE(SRB2_JSON_TO, __VA_ARGS__)) } \
|
||||
friend void from_json(const srb2::JsonValue& srb2_json_j, Type& srb2_json_t) { const Type srb2_json_default_obj{}; SRB2_JSON_EXPAND(SRB2_JSON_PASTE(SRB2_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
|
||||
|
||||
/*!
|
||||
@brief macro
|
||||
@def SRB2_JSON_DEFINE_TYPE_NON_INTRUSIVE
|
||||
@since version 3.9.0
|
||||
*/
|
||||
#define SRB2_JSON_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
|
||||
inline void to_json(srb2::JsonValue& srb2_json_j, const Type& srb2_json_t) { SRB2_JSON_EXPAND(SRB2_JSON_PASTE(SRB2_JSON_TO, __VA_ARGS__)) } \
|
||||
inline void from_json(const srb2::JsonValue& srb2_json_j, Type& srb2_json_t) { SRB2_JSON_EXPAND(SRB2_JSON_PASTE(SRB2_JSON_FROM, __VA_ARGS__)) }
|
||||
|
||||
/*!
|
||||
@brief macro
|
||||
@def SRB2_JSON_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT
|
||||
@since version 3.11.0
|
||||
*/
|
||||
#define SRB2_JSON_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
|
||||
inline void to_json(srb2::JsonValue& srb2_json_j, const Type& srb2_json_t) { SRB2_JSON_EXPAND(SRB2_JSON_PASTE(SRB2_JSON_TO, __VA_ARGS__)) } \
|
||||
inline void from_json(const srb2::JsonValue& srb2_json_j, Type& srb2_json_t) { const Type srb2_json_default_obj{}; SRB2_JSON_EXPAND(SRB2_JSON_PASTE(SRB2_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
|
||||
1125
src/core/string.cpp
Normal file
1125
src/core/string.cpp
Normal file
File diff suppressed because it is too large
Load diff
453
src/core/string.h
Normal file
453
src/core/string.h
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2025 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef SRB2_CORE_STRING_HPP
|
||||
#define SRB2_CORE_STRING_HPP
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
#include "fmt/core.h"
|
||||
|
||||
#include "static_vec.hpp"
|
||||
#include "vector.hpp"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
class Utf8Iter
|
||||
{
|
||||
public:
|
||||
using difference_type = size_t;
|
||||
using value_type = uint32_t;
|
||||
using pointer = void;
|
||||
using reference = void;
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
|
||||
private:
|
||||
size_t i_;
|
||||
std::string_view s_;
|
||||
|
||||
Utf8Iter(std::string_view s, size_t i) : i_(i), s_(s) {}
|
||||
|
||||
friend class String;
|
||||
uint32_t do_codepoint() const;
|
||||
|
||||
public:
|
||||
Utf8Iter() = default;
|
||||
Utf8Iter(const Utf8Iter&) = default;
|
||||
Utf8Iter(Utf8Iter&&) noexcept = default;
|
||||
~Utf8Iter() = default;
|
||||
Utf8Iter& operator=(const Utf8Iter&) = default;
|
||||
Utf8Iter& operator=(Utf8Iter&&) noexcept = default;
|
||||
|
||||
static Utf8Iter begin(std::string_view s) { return Utf8Iter(s, 0); }
|
||||
static Utf8Iter end(std::string_view s) { return Utf8Iter(s, s.size()); }
|
||||
|
||||
bool operator==(const Utf8Iter& r) const noexcept
|
||||
{
|
||||
return s_ == r.s_ && i_ == r.i_;
|
||||
}
|
||||
|
||||
bool operator!=(const Utf8Iter& r) const noexcept { return !(*this == r); }
|
||||
|
||||
uint32_t operator*() const { return codepoint(); }
|
||||
Utf8Iter& operator++()
|
||||
{
|
||||
i_ += size();
|
||||
return *this;
|
||||
}
|
||||
Utf8Iter operator++(int)
|
||||
{
|
||||
Utf8Iter copy = *this;
|
||||
++*this;
|
||||
return copy;
|
||||
}
|
||||
uint32_t codepoint() const;
|
||||
bool valid() const;
|
||||
uint8_t size() const;
|
||||
};
|
||||
|
||||
class Utf16Iter
|
||||
{
|
||||
public:
|
||||
using difference_type = size_t;
|
||||
using value_type = uint32_t;
|
||||
using pointer = void;
|
||||
using reference = void;
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
|
||||
private:
|
||||
size_t i_;
|
||||
std::u16string_view s_;
|
||||
|
||||
Utf16Iter(std::u16string_view s, size_t i) : i_(i), s_(s) {}
|
||||
|
||||
uint32_t do_codepoint() const;
|
||||
|
||||
public:
|
||||
Utf16Iter() = default;
|
||||
Utf16Iter(const Utf16Iter&) = default;
|
||||
Utf16Iter(Utf16Iter&&) noexcept = default;
|
||||
~Utf16Iter() = default;
|
||||
Utf16Iter& operator=(const Utf16Iter&) = default;
|
||||
Utf16Iter& operator=(Utf16Iter&&) = default;
|
||||
|
||||
static Utf16Iter begin(std::u16string_view s) { return Utf16Iter(s, 0); }
|
||||
static Utf16Iter end(std::u16string_view s) { return Utf16Iter(s, s.size()); }
|
||||
|
||||
bool operator==(const Utf16Iter& r) const noexcept
|
||||
{
|
||||
return s_ == r.s_ && i_ == r.i_;
|
||||
}
|
||||
|
||||
bool operator!=(const Utf16Iter& r) const noexcept { return !(*this == r); }
|
||||
|
||||
uint32_t operator*() const { return codepoint(); }
|
||||
Utf16Iter& operator++()
|
||||
{
|
||||
i_ += size();
|
||||
return *this;
|
||||
}
|
||||
Utf16Iter operator++(int)
|
||||
{
|
||||
Utf16Iter copy = *this;
|
||||
++*this;
|
||||
return copy;
|
||||
}
|
||||
|
||||
uint32_t codepoint() const;
|
||||
bool valid() const { return true; } // we allow unpaired surrogates in general
|
||||
uint8_t size() const;
|
||||
};
|
||||
|
||||
class String
|
||||
{
|
||||
public:
|
||||
using size_type = uint32_t;
|
||||
using difference_type = int64_t;
|
||||
using value_type = uint8_t;
|
||||
using reference = uint8_t&;
|
||||
using const_reference = const uint8_t&;
|
||||
using pointer = uint8_t*;
|
||||
using const_pointer = const uint8_t*;
|
||||
using iterator = uint8_t*;
|
||||
using const_iterator = const uint8_t*;
|
||||
|
||||
private:
|
||||
srb2::Vector<uint8_t> data_;
|
||||
|
||||
public:
|
||||
|
||||
friend struct std::hash<String>;
|
||||
|
||||
static constexpr const size_type npos = -1;
|
||||
|
||||
String() = default;
|
||||
String(const String&);
|
||||
String(String&&) noexcept;
|
||||
~String();
|
||||
String& operator=(const String&);
|
||||
String& operator=(String&&) noexcept;
|
||||
|
||||
String(const char* s);
|
||||
String(const char* s, size_t len);
|
||||
String(const std::string&);
|
||||
|
||||
explicit String(std::string_view view);
|
||||
|
||||
operator std::string() const;
|
||||
operator std::string_view() const;
|
||||
|
||||
size_type size() const noexcept;
|
||||
bool empty() const noexcept { return data_.empty(); }
|
||||
const char* c_str() const;
|
||||
uint8_t* data() noexcept { return data_.data(); }
|
||||
const uint8_t* data() const noexcept { return data_.data(); }
|
||||
void reserve(size_type capacity);
|
||||
|
||||
uint8_t* begin() noexcept;
|
||||
uint8_t* end() noexcept;
|
||||
const uint8_t* cbegin() const noexcept;
|
||||
const uint8_t* cend() const noexcept;
|
||||
const uint8_t* begin() const noexcept { return cbegin(); }
|
||||
const uint8_t* end() const noexcept { return cend(); }
|
||||
|
||||
uint8_t& at(size_type i);
|
||||
const uint8_t& at(size_type i) const;
|
||||
uint8_t& operator[](size_type i) { return data_[i]; }
|
||||
const uint8_t& operator[](size_type i) const { return data_[i]; }
|
||||
uint8_t& front() { return data_[0]; }
|
||||
const uint8_t& front() const { return data_[0]; }
|
||||
uint8_t& back() { return data_[size() - 1]; }
|
||||
const uint8_t& back() const { return data_[size() - 1]; }
|
||||
|
||||
void clear() { data_.clear(); }
|
||||
String& insert(size_type index, size_type count, uint8_t ch);
|
||||
String& insert(size_type index, const char* s);
|
||||
String& insert(size_type index, const char* s, size_type count);
|
||||
String& insert(size_type index, std::string_view str);
|
||||
String& insert(size_type index, std::string_view str, size_t s_index, size_t count = npos);
|
||||
iterator insert(const_iterator pos, uint8_t ch);
|
||||
iterator insert(const_iterator pos, size_type count, uint8_t ch);
|
||||
|
||||
template <
|
||||
typename InputIt,
|
||||
typename std::enable_if_t<
|
||||
std::is_constructible<
|
||||
uint8_t,
|
||||
typename std::iterator_traits<InputIt>::reference
|
||||
>::value,
|
||||
int
|
||||
> = 0
|
||||
>
|
||||
iterator insert(const_iterator pos, InputIt first, InputIt last)
|
||||
{
|
||||
size_type offset = pos - data();
|
||||
if (!empty())
|
||||
{
|
||||
// remove null byte
|
||||
data_.pop_back();
|
||||
}
|
||||
auto ret = data_.insert(pos, first, last);
|
||||
if (data_.size() > 0)
|
||||
{
|
||||
data_.push_back(0);
|
||||
}
|
||||
return data() + offset;
|
||||
}
|
||||
|
||||
iterator insert(const_iterator pos, std::initializer_list<uint8_t> list);
|
||||
String& erase(size_type index = 0, size_type count = npos);
|
||||
iterator erase(const_iterator position);
|
||||
iterator erase(const_iterator first, const_iterator last);
|
||||
void push_back(uint8_t v);
|
||||
void pop_back();
|
||||
String& append(size_type count, uint8_t ch);
|
||||
String& append(const char* s, size_type count);
|
||||
String& append(const char* s);
|
||||
String& append(std::string_view str);
|
||||
String& append(std::string_view str, size_type pos, size_type count = npos);
|
||||
|
||||
template <
|
||||
typename InputIt,
|
||||
typename std::enable_if_t<
|
||||
std::is_constructible<
|
||||
uint8_t,
|
||||
typename std::iterator_traits<InputIt>::reference
|
||||
>::value,
|
||||
int
|
||||
> = 0
|
||||
>
|
||||
String& append(InputIt first, InputIt last)
|
||||
{
|
||||
if (!empty())
|
||||
{
|
||||
// remove null byte
|
||||
data_.pop_back();
|
||||
}
|
||||
for (; first != last; first++)
|
||||
{
|
||||
data_.push_back(*first);
|
||||
}
|
||||
if (data_.size() > 0)
|
||||
{
|
||||
data_.push_back(0);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& append(std::initializer_list<uint8_t> ilist);
|
||||
String& operator+=(std::string_view r);
|
||||
String& operator+=(const char* r);
|
||||
String& operator+=(uint8_t r);
|
||||
String& operator+=(std::initializer_list<uint8_t> r);
|
||||
String& replace(size_type pos, size_type count, std::string_view str);
|
||||
String& replace(const_iterator first, const_iterator last, std::string_view str);
|
||||
String& replace(size_type pos, size_type count, std::string_view str, size_t pos2, size_t count2 = -1);
|
||||
String& replace(size_type pos, size_type count, const char* cstr, size_type count2);
|
||||
String& replace(const_iterator first, const_iterator last, const char* cstr, size_type count2);
|
||||
String& replace(size_type pos, size_type count, const char* cstr);
|
||||
String& replace(const_iterator first, const_iterator last, const char* cstr);
|
||||
// String& replace(size_type pos, size_type count, size_type count2, uint8_t ch);
|
||||
String& replace(const_iterator first, const_iterator last, uint8_t ch);
|
||||
|
||||
template <
|
||||
typename InputIt,
|
||||
typename std::enable_if_t<
|
||||
std::is_constructible<
|
||||
uint8_t,
|
||||
typename std::iterator_traits<InputIt>::reference
|
||||
>::value,
|
||||
int
|
||||
> = 0
|
||||
>
|
||||
String& replace(const_iterator first, const_iterator last, InputIt first2, InputIt last2)
|
||||
{
|
||||
for (; first != last && first2 != last2; first++, first2++)
|
||||
{
|
||||
*const_cast<iterator>(first) = *first2;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& replace(const_iterator first, const_iterator last, std::initializer_list<uint8_t> ilist);
|
||||
size_type copy(uint8_t* dest, size_type count, size_type pos = 0) const;
|
||||
size_type copy(char* dest, size_type count, size_type pos = 0) const;
|
||||
void resize(size_type count);
|
||||
void resize(size_type count, uint8_t ch);
|
||||
void swap(String& other) noexcept;
|
||||
|
||||
size_type find(const String& str, size_type pos = 0) const;
|
||||
size_type find(std::string_view str, size_type pos = 0) const;
|
||||
size_type find(const char* s, size_type pos, size_t count) const;
|
||||
size_type find(const char* s, size_type pos = 0) const;
|
||||
size_type find(uint8_t ch, size_type pos = 0) const;
|
||||
size_type rfind(const String& str, size_type pos = npos) const;
|
||||
size_type rfind(std::string_view str, size_type pos = npos) const;
|
||||
size_type rfind(const char* s, size_type pos, size_type count) const;
|
||||
size_type rfind(const char* s, size_type pos = npos) const;
|
||||
size_type rfind(uint8_t ch, size_type pos = npos) const;
|
||||
// size_type find_first_of(std::string_view str, size_type pos = 0) const;
|
||||
// size_type find_first_of(const char* s, size_type pos, size_type count) const;
|
||||
// size_type find_first_of(const char* s, size_type pos = 0) const;
|
||||
// size_type find_first_of(uint8_t ch, size_type pos = 0) const;
|
||||
// size_type find_first_not_of(std::string_view str, size_type pos = 0) const;
|
||||
// size_type find_first_not_of(const char* s, size_type pos, size_type count) const;
|
||||
// size_type find_first_not_of(const char* s, size_type pos = 0) const;
|
||||
// size_type find_first_not_of(uint8_t ch, size_type pos = 0) const;
|
||||
// size_type find_last_of(std::string_view str, size_type pos = npos) const;
|
||||
// size_type find_last_of(const char* s, size_type pos, size_type count) const;
|
||||
// size_type find_last_of(const char* s, size_type pos = npos) const;
|
||||
// size_type find_last_of(uint8_t ch, size_type pos = npos) const;
|
||||
// size_type find_last_not_of(std::string_view str, size_type pos = npos) const;
|
||||
// size_type find_last_not_of(const char* s, size_type pos, size_type count) const;
|
||||
// size_type find_last_not_of(const char* s, size_type pos = npos) const;
|
||||
// size_type find_last_not_of(uint8_t ch, size_type pos = npos) const;
|
||||
|
||||
int compare(std::string_view str) const noexcept;
|
||||
// int compare(size_type pos1, size_type count1, std::string_view str) const;
|
||||
// int compare(size_type pos1, size_type count1, std::string_view str, size_type pos2, size_type count2 = npos) const;
|
||||
int compare(const char* s) const;
|
||||
// int compare(size_type pos1, size_type count1, const char* s) const;
|
||||
// int compare(size_type pos1, size_type count1, const char* s, size_type count2) const;
|
||||
String substr(size_type pos = 0, size_type count = npos) const;
|
||||
|
||||
// Non-STL String functions
|
||||
bool valid_utf8() const noexcept;
|
||||
srb2::Vector<uint16_t> to_utf16() const;
|
||||
srb2::Vector<uint32_t> to_utf32() const;
|
||||
size_t length_decoded() const;
|
||||
|
||||
Utf8Iter decode_begin() const { return Utf8Iter(*this, 0); }
|
||||
Utf8Iter decode_end() const { return Utf8Iter(*this, size()); };
|
||||
};
|
||||
|
||||
String operator+(const String& lhs, const String& rhs);
|
||||
String operator+(const String& lhs, const char* rhs);
|
||||
String operator+(const String& lhs, uint8_t rhs);
|
||||
String operator+(const String& lhs, std::string_view view);
|
||||
|
||||
bool operator==(const String& lhs, const String& rhs);
|
||||
bool operator==(const String& lhs, const char* rhs);
|
||||
// bool operator==(const String& lhs, std::string_view rhs);
|
||||
bool operator!=(const String& lhs, const String& rhs);
|
||||
bool operator!=(const String& lhs, const char* rhs);
|
||||
// bool operator!=(const String& lhs, std::string_view rhs);
|
||||
bool operator<(const String& lhs, const String& rhs);
|
||||
bool operator<(const String& lhs, const char* rhs);
|
||||
// bool operator<(const String& lhs, std::string_view rhs);
|
||||
bool operator<=(const String& lhs, const String& rhs);
|
||||
bool operator<=(const String& lhs, const char* rhs);
|
||||
// bool operator<=(const String& lhs, std::string_view rhs);
|
||||
bool operator>(const String& lhs, const String& rhs);
|
||||
bool operator>(const String& lhs, const char* rhs);
|
||||
// bool operator>(const String& lhs, std::string_view rhs);
|
||||
bool operator>=(const String& lhs, const String& rhs);
|
||||
bool operator>=(const String& lhs, const char* rhs);
|
||||
// bool operator>=(const String& lhs, std::string_view rhs);
|
||||
|
||||
Vector<uint16_t> to_utf16(std::string_view utf8);
|
||||
Vector<uint32_t> to_utf32(std::string_view utf8);
|
||||
|
||||
srb2::StaticVec<uint8_t, 4> to_utf8(uint32_t codepoint);
|
||||
|
||||
template <
|
||||
typename ItUTF32,
|
||||
typename std::enable_if_t<
|
||||
std::is_constructible<
|
||||
uint32_t,
|
||||
typename std::iterator_traits<ItUTF32>::reference
|
||||
>::value,
|
||||
int
|
||||
> = 0
|
||||
>
|
||||
srb2::String to_utf8(ItUTF32 begin, ItUTF32 end)
|
||||
{
|
||||
srb2::String ret;
|
||||
for (auto itr = begin; itr != end; ++itr)
|
||||
{
|
||||
srb2::StaticVec<uint8_t, 4> utf8 = to_utf8(*itr);
|
||||
ret.append(utf8.begin(), utf8.end());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
srb2::String to_utf8(std::u32string_view utf32view);
|
||||
|
||||
// fmtlib
|
||||
inline auto format_as(const String& str) { return fmt::string_view(static_cast<std::string_view>(str)); }
|
||||
|
||||
srb2::String vformat(fmt::string_view fmt, fmt::format_args args);
|
||||
|
||||
template <typename... T>
|
||||
inline auto format(fmt::format_string<T...> fmt, T&&... args)
|
||||
{
|
||||
return ::srb2::vformat(fmt, fmt::vargs<T...>{{args...}});
|
||||
}
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template <> struct hash<srb2::String>
|
||||
{
|
||||
size_t operator()(const srb2::String& v);
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
int Str_IsValidUTF8(const char* str);
|
||||
// int Str_ToUTF16(uint16_t* dst, size_t dstlen, const char* src);
|
||||
// int Str_ToUTF32(uint32_t* dst, size_t dstlen, const char* src);
|
||||
uint32_t Str_NextCodepointFromUTF8(const char** itr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // SRB2_CORE_STRING_HPP
|
||||
|
|
@ -14,12 +14,13 @@
|
|||
#include <condition_variable>
|
||||
#include <exception>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <tracy/tracy/Tracy.hpp>
|
||||
|
||||
#include "../core/string.h"
|
||||
#include "../core/vector.hpp"
|
||||
#include "../cxxutil.hpp"
|
||||
#include "../m_argv.h"
|
||||
|
||||
|
|
@ -50,11 +51,11 @@ static void pool_executor(
|
|||
std::shared_ptr<std::mutex> worker_ready_mutex,
|
||||
std::shared_ptr<std::condition_variable> worker_ready_condvar,
|
||||
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());
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +134,7 @@ ThreadPool::ThreadPool(size_t threads)
|
|||
for (size_t i = 0; i < threads; 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++)
|
||||
{
|
||||
// Order the other queues starting from the next adjacent worker
|
||||
|
|
|
|||
61
src/core/vector.cpp
Normal file
61
src/core/vector.cpp
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2025 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "vector.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
AbstractVector::GrowResult AbstractVector::_realloc_mem(void* data, size_t size, size_t old_cap, size_t elem_size, Move move, size_t cap) noexcept
|
||||
{
|
||||
GrowResult ret;
|
||||
std::allocator<uint8_t> allocator;
|
||||
|
||||
if (old_cap == 0)
|
||||
{
|
||||
cap = std::max<size_t>(cap, 1);
|
||||
ret.data = allocator.allocate(cap * elem_size + sizeof(std::max_align_t));
|
||||
ret.cap = cap;
|
||||
return ret;
|
||||
}
|
||||
|
||||
cap = std::max<size_t>(cap, old_cap * 2);
|
||||
ret.data = allocator.allocate(cap * elem_size + sizeof(std::max_align_t));
|
||||
(move)(ret.data, data, size);
|
||||
allocator.deallocate(reinterpret_cast<uint8_t*>(data), old_cap * elem_size + sizeof(std::max_align_t));
|
||||
ret.cap = cap;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AbstractVector::_free_mem(void* data, size_t cap, size_t elem_size) noexcept
|
||||
{
|
||||
std::allocator<uint8_t> allocator;
|
||||
allocator.deallocate(reinterpret_cast<uint8_t*>(data), cap * elem_size + sizeof(std::max_align_t));
|
||||
}
|
||||
|
||||
template class Vector<bool>;
|
||||
template class Vector<std::byte>;
|
||||
template class Vector<uint8_t>;
|
||||
template class Vector<uint16_t>;
|
||||
template class Vector<uint32_t>;
|
||||
template class Vector<uint64_t>;
|
||||
template class Vector<int8_t>;
|
||||
template class Vector<int16_t>;
|
||||
template class Vector<int32_t>;
|
||||
template class Vector<int64_t>;
|
||||
template class Vector<String>;
|
||||
|
||||
} // namespace srb2
|
||||
366
src/core/vector.hpp
Normal file
366
src/core/vector.hpp
Normal file
|
|
@ -0,0 +1,366 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2025 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef SRB2_CORE_VEC_HPP
|
||||
#define SRB2_CORE_VEC_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
class AbstractVector
|
||||
{
|
||||
protected:
|
||||
size_t size_;
|
||||
size_t capacity_;
|
||||
size_t elem_size_;
|
||||
void* data_;
|
||||
|
||||
using Move = void(*)(void* dst, void* src, size_t size);
|
||||
|
||||
template <typename T>
|
||||
static void _move(void* dst, void* src, size_t size) noexcept
|
||||
{
|
||||
T* d = (T*)dst;
|
||||
T* s = (T*)src;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
new (&d[i]) T(std::move(s[i]));
|
||||
}
|
||||
}
|
||||
|
||||
struct GrowResult
|
||||
{
|
||||
void* data;
|
||||
size_t cap;
|
||||
};
|
||||
static GrowResult _realloc_mem(void* data, size_t size, size_t old_cap, size_t elem_size, Move move, size_t cap) noexcept;
|
||||
static void _free_mem(void* data, size_t cap, size_t elem_size) noexcept;
|
||||
|
||||
template <typename T>
|
||||
void _reserve_mem(size_t c) noexcept
|
||||
{
|
||||
if (c > capacity_)
|
||||
{
|
||||
GrowResult r = _realloc_mem(data_, size_, capacity_, elem_size_, _move<T>, c);
|
||||
data_ = r.data;
|
||||
capacity_ = r.cap;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr AbstractVector() : size_(0), capacity_(0), elem_size_(0), data_(nullptr) {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Vector : AbstractVector
|
||||
{
|
||||
public:
|
||||
// iter traits
|
||||
using value_type = T;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
using pointer = T*;
|
||||
using const_pointer = const T*;
|
||||
using iterator = T*;
|
||||
using const_iterator = const T*;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
Vector() : AbstractVector()
|
||||
{
|
||||
elem_size_ = sizeof(T);
|
||||
}
|
||||
Vector(const Vector& rhs) : Vector()
|
||||
{
|
||||
*this = rhs;
|
||||
}
|
||||
Vector(Vector&& rhs) noexcept : AbstractVector()
|
||||
{
|
||||
elem_size_ = sizeof(T);
|
||||
*this = std::move(rhs);
|
||||
}
|
||||
~Vector()
|
||||
{
|
||||
if (data_)
|
||||
{
|
||||
for (size_type i = 0; i < size_; i++)
|
||||
{
|
||||
((T*)(data_))[(size_ - i - 1)].~T();
|
||||
}
|
||||
_free_mem(data_, capacity_, elem_size_);
|
||||
}
|
||||
data_ = nullptr;
|
||||
}
|
||||
|
||||
explicit Vector(size_type capacity) : AbstractVector()
|
||||
{
|
||||
elem_size_ = sizeof(T);
|
||||
_reserve_mem<T>(capacity);
|
||||
}
|
||||
Vector(std::initializer_list<T> l) : AbstractVector()
|
||||
{
|
||||
elem_size_ = sizeof(T);
|
||||
if (l.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_reserve_mem<T>(l.size());
|
||||
for (auto itr = l.begin(); itr != l.end(); itr++)
|
||||
{
|
||||
emplace_back(*itr);
|
||||
}
|
||||
}
|
||||
|
||||
template <
|
||||
typename It,
|
||||
typename std::enable_if_t<
|
||||
std::is_constructible_v<
|
||||
T,
|
||||
typename std::iterator_traits<It>::reference
|
||||
>,
|
||||
int
|
||||
> = 0
|
||||
>
|
||||
Vector(It begin, It end) : AbstractVector()
|
||||
{
|
||||
elem_size_ = sizeof(T);
|
||||
for (auto itr = begin; itr != end; ++itr)
|
||||
{
|
||||
push_back(*itr);
|
||||
}
|
||||
}
|
||||
|
||||
Vector& operator=(const Vector& rhs)
|
||||
{
|
||||
for (auto itr = rhs.begin(); itr != rhs.end(); itr++)
|
||||
{
|
||||
push_back(*itr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector& operator=(Vector&& rhs) noexcept
|
||||
{
|
||||
std::swap(size_, rhs.size_);
|
||||
std::swap(capacity_, rhs.capacity_);
|
||||
std::swap(data_, rhs.data_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr size_type size() const noexcept { return size_; }
|
||||
constexpr size_type capacity() const noexcept { return capacity_; }
|
||||
constexpr bool empty() const noexcept { return size_ == 0; }
|
||||
|
||||
constexpr T* data() noexcept { return (T*) data_; }
|
||||
constexpr const T* data() const noexcept { return (const T*) data_; }
|
||||
constexpr T* begin() noexcept { return data(); }
|
||||
constexpr const T* begin() const noexcept { return data(); }
|
||||
constexpr T* end() noexcept { return data() + size(); }
|
||||
constexpr const T* end() const noexcept { return data() + size(); }
|
||||
constexpr const T* cbegin() const noexcept { return data(); }
|
||||
constexpr const T* cend() const noexcept { return end(); }
|
||||
constexpr auto rbegin() noexcept { return std::reverse_iterator(end()); }
|
||||
constexpr auto rbegin() const noexcept { return std::reverse_iterator(end()); }
|
||||
constexpr auto rend() noexcept { return std::reverse_iterator(begin()); }
|
||||
constexpr auto rend() const noexcept { return std::reverse_iterator(begin()); }
|
||||
constexpr auto crbegin() const noexcept { return rbegin(); }
|
||||
constexpr auto crend() const noexcept { return rend(); }
|
||||
T& front() noexcept { return data()[0]; }
|
||||
const T& front() const noexcept { return data()[0]; }
|
||||
T& back() noexcept { return data()[size() - 1]; }
|
||||
const T& back() const noexcept { return data()[size() - 1]; }
|
||||
|
||||
void push_back(const T& t)
|
||||
{
|
||||
reserve(size() + 1);
|
||||
new (&data()[size()]) T(t);
|
||||
size_++;
|
||||
}
|
||||
|
||||
void push_back(T&& t)
|
||||
{
|
||||
reserve(size() + 1);
|
||||
new (&data()[size()]) T(std::move(t));
|
||||
size_++;
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
T* end = &data()[size() - 1];
|
||||
end->~T();
|
||||
size_--;
|
||||
}
|
||||
|
||||
void clear() { for (auto& x : *this) x.~T(); size_ = 0; }
|
||||
|
||||
void reserve(size_type c)
|
||||
{
|
||||
_reserve_mem<T>(c);
|
||||
}
|
||||
|
||||
void resize(size_type s)
|
||||
{
|
||||
resize(s, T());
|
||||
}
|
||||
|
||||
void resize(size_type s, const T& value)
|
||||
{
|
||||
if (s <= size())
|
||||
{
|
||||
auto itr_begin = rbegin();
|
||||
auto itr_end = std::prev(rend(), s);
|
||||
size_t count_destroyed = 0;
|
||||
for (auto itr = itr_begin; itr != itr_end; itr++)
|
||||
{
|
||||
itr->~T();
|
||||
count_destroyed++;
|
||||
}
|
||||
size_ = s;
|
||||
}
|
||||
else
|
||||
{
|
||||
reserve(s);
|
||||
size_type oldsize = size();
|
||||
size_ = s;
|
||||
for (auto itr = std::next(begin(), oldsize); itr != end(); itr++)
|
||||
{
|
||||
try
|
||||
{
|
||||
new (itr) T(value);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
size_ = oldsize;
|
||||
std::rethrow_exception(std::current_exception());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const T& at(size_type i) const { if (i >= size()) throw std::out_of_range("index out of range"); return data()[i]; }
|
||||
T& at(size_type i) { if (i >= size()) throw std::out_of_range("index out of range"); return data()[i]; }
|
||||
|
||||
T& operator[](size_type i) { return data()[i]; }
|
||||
const T& operator[](size_type i) const { return data()[i]; }
|
||||
|
||||
iterator erase(const_iterator first) { return erase(first, first + 1); }
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
iterator firstm = const_cast<iterator>(first);
|
||||
iterator lastm = const_cast<iterator>(last);
|
||||
if (first == last) return firstm;
|
||||
|
||||
auto diff = last - first;
|
||||
if (last != end()) std::move(lastm, end(), firstm);
|
||||
resize(size_ - diff);
|
||||
|
||||
return firstm;
|
||||
}
|
||||
|
||||
iterator insert(const_iterator pos, const T& value)
|
||||
{
|
||||
return insert(pos, (size_type)1, std::forward<const T&>(value));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator pos, T&& value)
|
||||
{
|
||||
size_type oldsize = size();
|
||||
difference_type offs = pos - data();
|
||||
push_back(std::move(value));
|
||||
std::rotate(data() + offs, data() + oldsize, data() + size());
|
||||
return data() + offs;
|
||||
}
|
||||
|
||||
iterator insert(const_iterator pos, size_type count, const T& value)
|
||||
{
|
||||
size_type oldsize = size();
|
||||
difference_type offs = pos - data();
|
||||
reserve(oldsize + count);
|
||||
T* d = data();
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
// must be copy-initialized;
|
||||
// value is currently uninitialized
|
||||
new ((T*)(&d[oldsize + i])) T(value);
|
||||
}
|
||||
size_ = oldsize + count;
|
||||
std::rotate(d + offs, d + oldsize, d + (oldsize + count));
|
||||
return data() + offs;
|
||||
}
|
||||
|
||||
template <
|
||||
class InputIt,
|
||||
typename std::enable_if_t<
|
||||
std::is_constructible<
|
||||
T,
|
||||
typename std::iterator_traits<InputIt>::reference
|
||||
>::value,
|
||||
int
|
||||
> = 0
|
||||
>
|
||||
iterator insert(const_iterator pos, InputIt first, InputIt last)
|
||||
{
|
||||
size_type oldsize = size();
|
||||
difference_type offs = pos - data();
|
||||
|
||||
size_type count = 0;
|
||||
while (first != last)
|
||||
{
|
||||
push_back(*first);
|
||||
++first;
|
||||
++count;
|
||||
}
|
||||
std::rotate(data() + offs, data() + oldsize, data() + (oldsize + count));
|
||||
return data() + offs;
|
||||
}
|
||||
|
||||
template <typename... A>
|
||||
iterator emplace(const_iterator position, A&&... args)
|
||||
{
|
||||
return insert(position, T(std::forward<A>(args)...));
|
||||
}
|
||||
|
||||
template <typename... A>
|
||||
T& emplace_back(A&&... args)
|
||||
{
|
||||
reserve(size() + 1);
|
||||
new (&data()[size()]) T(std::forward<A>(args)...);
|
||||
size_++;
|
||||
return (*this)[size_ - 1];
|
||||
}
|
||||
};
|
||||
|
||||
class String;
|
||||
|
||||
extern template class Vector<bool>;
|
||||
extern template class Vector<std::byte>;
|
||||
extern template class Vector<uint8_t>;
|
||||
extern template class Vector<uint16_t>;
|
||||
extern template class Vector<uint32_t>;
|
||||
extern template class Vector<uint64_t>;
|
||||
extern template class Vector<int8_t>;
|
||||
extern template class Vector<int16_t>;
|
||||
extern template class Vector<int32_t>;
|
||||
extern template class Vector<int64_t>;
|
||||
extern template class Vector<String>;
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
#endif // SRB2_CORE_VEC_HPP
|
||||
|
|
@ -16,7 +16,6 @@
|
|||
#include <cstddef>
|
||||
|
||||
#include <tcb/span.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomtype.h"
|
||||
|
|
@ -50,6 +49,7 @@
|
|||
#include "md5.h" // demo checksums
|
||||
#include "p_saveg.h" // savebuffer_t
|
||||
#include "g_party.h"
|
||||
#include "core/json.hpp"
|
||||
|
||||
// SRB2Kart
|
||||
#include "d_netfil.h" // nameonly
|
||||
|
|
@ -2437,17 +2437,18 @@ void G_BeginRecording(void)
|
|||
void srb2::write_current_demo_standings(const srb2::StandingsJson& standings)
|
||||
{
|
||||
using namespace srb2;
|
||||
using json = nlohmann::json;
|
||||
|
||||
// TODO populate standings data
|
||||
|
||||
std::vector<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();
|
||||
|
||||
WRITEUINT8(demobuf.p, DW_STANDING2);
|
||||
|
||||
WRITEUINT32(demobuf.p, bytes);
|
||||
WRITEMEM(demobuf.p, ubjson.data(), bytes);
|
||||
WRITEMEM(demobuf.p, (UINT8*)ubjson.data(), bytes);
|
||||
}
|
||||
|
||||
void srb2::write_current_demo_end_marker()
|
||||
|
|
@ -2615,12 +2616,12 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
static bool load_ubjson_standing(menudemo_t* pdemo, tcb::span<std::byte> slice, tcb::span<democharlist_t> demoskins)
|
||||
{
|
||||
using namespace srb2;
|
||||
using json = nlohmann::json;
|
||||
|
||||
StandingsJson js;
|
||||
try
|
||||
{
|
||||
js = json::from_ubjson(slice).template get<StandingsJson>();
|
||||
JsonValue value { JsonValue::from_ubjson(tcb::as_bytes(slice)) };
|
||||
from_json(value, js);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
|
|
|||
17
src/g_demo.h
17
src/g_demo.h
|
|
@ -21,10 +21,9 @@
|
|||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "core/json.hpp"
|
||||
#include "core/string.h"
|
||||
#include "core/vector.hpp"
|
||||
|
||||
// Modern json formats
|
||||
namespace srb2
|
||||
|
|
@ -32,12 +31,12 @@ namespace srb2
|
|||
struct StandingJson
|
||||
{
|
||||
uint8_t ranking;
|
||||
std::string name;
|
||||
String name;
|
||||
uint8_t demoskin;
|
||||
std::string skincolor;
|
||||
String skincolor;
|
||||
uint32_t timeorscore;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
StandingJson,
|
||||
ranking,
|
||||
name,
|
||||
|
|
@ -48,9 +47,9 @@ struct StandingJson
|
|||
};
|
||||
struct StandingsJson
|
||||
{
|
||||
std::vector<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);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#include "z_zone.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
using json = nlohmann::json;
|
||||
|
||||
#define GD_VERSION_MAJOR (0xBA5ED321)
|
||||
#define GD_VERSION_MINOR (1)
|
||||
|
|
@ -137,13 +136,13 @@ void srb2::save_ng_gamedata()
|
|||
skin_t& memskin = skins[i];
|
||||
|
||||
auto skin = skintojson(&memskin.records);
|
||||
std::string name = std::string(memskin.name);
|
||||
srb2::String name { memskin.name };
|
||||
ng.skins[name] = std::move(skin);
|
||||
}
|
||||
for (auto unloadedskin = unloadedskins; unloadedskin; unloadedskin = unloadedskin->next)
|
||||
{
|
||||
auto skin = skintojson(&unloadedskin->records);
|
||||
std::string name = std::string(unloadedskin->name);
|
||||
srb2::String name { unloadedskin->name };
|
||||
ng.skins[name] = std::move(skin);
|
||||
}
|
||||
|
||||
|
|
@ -175,13 +174,13 @@ void srb2::save_ng_gamedata()
|
|||
for (int i = 0; i < nummapheaders; i++)
|
||||
{
|
||||
auto map = maptojson(&mapheaderinfo[i]->records);
|
||||
std::string lumpname = std::string(mapheaderinfo[i]->lumpname);
|
||||
srb2::String lumpname { mapheaderinfo[i]->lumpname };
|
||||
ng.maps[lumpname] = std::move(map);
|
||||
}
|
||||
for (auto unloadedmap = unloadedmapheaders; unloadedmap; unloadedmap = unloadedmap->next)
|
||||
{
|
||||
auto map = maptojson(&unloadedmap->records);
|
||||
std::string lumpname = std::string(unloadedmap->lumpname);
|
||||
srb2::String lumpname { unloadedmap->lumpname };
|
||||
ng.maps[lumpname] = std::move(map);
|
||||
}
|
||||
for (int i = 0; i < gamedata->numspraycans; i++)
|
||||
|
|
@ -194,7 +193,7 @@ void srb2::save_ng_gamedata()
|
|||
{
|
||||
continue;
|
||||
}
|
||||
spraycan.color = std::string(skincolors[can->col].name);
|
||||
spraycan.color = String(skincolors[can->col].name);
|
||||
|
||||
if (can->map == NEXTMAP_INVALID)
|
||||
{
|
||||
|
|
@ -213,7 +212,7 @@ void srb2::save_ng_gamedata()
|
|||
{
|
||||
continue;
|
||||
}
|
||||
spraycan.map = std::string(mapheader->lumpname);
|
||||
spraycan.map = String(mapheader->lumpname);
|
||||
ng.spraycans.emplace_back(std::move(spraycan));
|
||||
}
|
||||
|
||||
|
|
@ -230,11 +229,11 @@ void srb2::save_ng_gamedata()
|
|||
skinreference_t& skinref = windata[i].best_skin;
|
||||
if (skinref.unloaded)
|
||||
{
|
||||
newrecords.bestskin = std::string(skinref.unloaded->name);
|
||||
newrecords.bestskin = String(skinref.unloaded->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
newrecords.bestskin = std::string(skins[skinref.id].name);
|
||||
newrecords.bestskin = String(skins[skinref.id].name);
|
||||
}
|
||||
newrecords.gotemerald = windata[i].got_emerald;
|
||||
|
||||
|
|
@ -252,7 +251,7 @@ void srb2::save_ng_gamedata()
|
|||
}
|
||||
|
||||
auto cupdata = cuptojson(cup->windata);
|
||||
cupdata.name = std::string(cup->name);
|
||||
cupdata.name = String(cup->name);
|
||||
ng.cups[cupdata.name] = std::move(cupdata);
|
||||
}
|
||||
for (auto unloadedcup = unloadedcupheaders; unloadedcup; unloadedcup = unloadedcup->next)
|
||||
|
|
@ -263,7 +262,7 @@ void srb2::save_ng_gamedata()
|
|||
}
|
||||
|
||||
auto cupdata = cuptojson(unloadedcup->windata);
|
||||
cupdata.name = std::string(unloadedcup->name);
|
||||
cupdata.name = String(unloadedcup->name);
|
||||
ng.cups[cupdata.name] = std::move(cupdata);
|
||||
}
|
||||
|
||||
|
|
@ -273,17 +272,19 @@ void srb2::save_ng_gamedata()
|
|||
|
||||
cupheader_t* cup = gamedata->sealedswaps[i];
|
||||
|
||||
sealedswap.name = std::string(cup->name);
|
||||
sealedswap.name = String(cup->name);
|
||||
|
||||
ng.sealedswaps.emplace_back(std::move(sealedswap));
|
||||
}
|
||||
|
||||
std::string gamedataname_s {gamedatafilename};
|
||||
fs::path savepath {fmt::format("{}/{}", srb2home, gamedataname_s)};
|
||||
fs::path baksavepath {fmt::format("{}/{}.bak", srb2home, gamedataname_s)};
|
||||
|
||||
json ngdata_json = ng;
|
||||
String gamedataname_s {gamedatafilename};
|
||||
String savepath_string = srb2::format("{}/{}", srb2home, gamedataname_s);
|
||||
String baksavepath_string = srb2::format("{}/{}.bak", srb2home, gamedataname_s);
|
||||
fs::path savepath { static_cast<std::string_view>(savepath_string) };
|
||||
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))
|
||||
{
|
||||
|
|
@ -300,7 +301,7 @@ void srb2::save_ng_gamedata()
|
|||
|
||||
try
|
||||
{
|
||||
std::string savepathstring = savepath.string();
|
||||
String savepathstring = savepath.string();
|
||||
srb2::io::FileStream file {savepathstring, srb2::io::FileStreamMode::kWrite};
|
||||
|
||||
// The header is necessary to validate during loading.
|
||||
|
|
@ -308,7 +309,7 @@ void srb2::save_ng_gamedata()
|
|||
srb2::io::write(static_cast<uint8_t>(GD_VERSION_MINOR), file); // minor/flags
|
||||
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)));
|
||||
file.close();
|
||||
}
|
||||
|
|
@ -382,7 +383,7 @@ void srb2::load_ng_gamedata()
|
|||
return;
|
||||
}
|
||||
|
||||
std::string datapath {fmt::format("{}/{}", srb2home, gamedatafilename)};
|
||||
String datapath {srb2::format("{}/{}", srb2home, gamedatafilename)};
|
||||
|
||||
srb2::io::BufferedInputStream<srb2::io::FileStream> bis;
|
||||
try
|
||||
|
|
@ -419,15 +420,13 @@ void srb2::load_ng_gamedata()
|
|||
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;
|
||||
try
|
||||
{
|
||||
// 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());
|
||||
json parsed = json::from_ubjson(remainder_as_u8);
|
||||
js = parsed.template get<GamedataJson>();
|
||||
JsonValue parsed = JsonValue::from_ubjson(remainder);
|
||||
from_json(parsed, js);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
|
|
@ -542,7 +541,7 @@ void srb2::load_ng_gamedata()
|
|||
gamedata->challengegrid = static_cast<uint16_t*>(Z_Malloc(
|
||||
(gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT * sizeof(UINT16)),
|
||||
PU_STATIC, NULL));
|
||||
for (size_t i = 0; i < std::min((size_t)(gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT), js.challengegrid.grid.size()); i++)
|
||||
for (size_t i = 0; i < std::min<size_t>((size_t)(gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT), js.challengegrid.grid.size()); i++)
|
||||
{
|
||||
uint16_t gridvalue = js.challengegrid.grid[i];
|
||||
gamedata->challengegrid[i] = gridvalue;
|
||||
|
|
@ -745,7 +744,7 @@ void srb2::load_ng_gamedata()
|
|||
// Find the loaded cup
|
||||
for (cup = kartcupheaders; cup; cup = cup->next)
|
||||
{
|
||||
std::string cupname = std::string(cup->name);
|
||||
String cupname { cup->name };
|
||||
if (cupname == cuppair.first)
|
||||
{
|
||||
break;
|
||||
|
|
@ -770,7 +769,7 @@ void srb2::load_ng_gamedata()
|
|||
}
|
||||
for (auto unloadedskin = unloadedskins; unloadedskin; unloadedskin = unloadedskin->next)
|
||||
{
|
||||
std::string skinname = std::string(unloadedskin->name);
|
||||
String skinname { unloadedskin->name };
|
||||
if (skinname == cuppair.second.records[j].bestskin)
|
||||
{
|
||||
skinreference_t ref {};
|
||||
|
|
@ -826,7 +825,7 @@ void srb2::load_ng_gamedata()
|
|||
break;
|
||||
}
|
||||
|
||||
std::string cupname = std::string(cup->name);
|
||||
String cupname { cup->name };
|
||||
if (cupname == js.sealedswaps[i].name)
|
||||
{
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -13,13 +13,12 @@
|
|||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <array>
|
||||
#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
|
||||
{
|
||||
|
|
@ -39,7 +38,7 @@ struct GamedataPlaytimeJson final
|
|||
uint32_t statistics;
|
||||
uint32_t tumble;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
GamedataPlaytimeJson,
|
||||
total,
|
||||
netgame,
|
||||
|
|
@ -60,7 +59,7 @@ struct GamedataRingsJson final
|
|||
{
|
||||
uint32_t total;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataRingsJson, total)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataRingsJson, total)
|
||||
};
|
||||
|
||||
struct GamedataRoundsJson final
|
||||
|
|
@ -71,7 +70,7 @@ struct GamedataRoundsJson final
|
|||
uint32_t special;
|
||||
uint32_t custom;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataRoundsJson, race, battle, prisons, special, custom)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataRoundsJson, race, battle, prisons, special, custom)
|
||||
};
|
||||
|
||||
struct GamedataChallengeKeysJson final
|
||||
|
|
@ -81,7 +80,7 @@ struct GamedataChallengeKeysJson final
|
|||
uint16_t keyspending;
|
||||
uint16_t chaokeys;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataChallengeKeysJson, pendingkeyrounds, pendingkeyroundoffset, keyspending, chaokeys)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataChallengeKeysJson, pendingkeyrounds, pendingkeyroundoffset, keyspending, chaokeys)
|
||||
};
|
||||
|
||||
struct GamedataMilestonesJson final
|
||||
|
|
@ -98,7 +97,7 @@ struct GamedataMilestonesJson final
|
|||
bool sealedswapalerted;
|
||||
bool tutorialdone;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
GamedataMilestonesJson,
|
||||
gonerlevel,
|
||||
everloadedaddon,
|
||||
|
|
@ -119,15 +118,15 @@ struct GamedataPrisonEggPickupsJson final
|
|||
uint16_t thisprisoneggpickup;
|
||||
uint16_t prisoneggstothispickup;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataPrisonEggPickupsJson, thisprisoneggpickup, prisoneggstothispickup)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataPrisonEggPickupsJson, thisprisoneggpickup, prisoneggstothispickup)
|
||||
};
|
||||
|
||||
struct GamedataChallengeGridJson final
|
||||
{
|
||||
uint32_t width;
|
||||
std::vector<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
|
||||
|
|
@ -140,7 +139,7 @@ struct GamedataSkinRecordsPlaytimeJson final
|
|||
uint32_t custom;
|
||||
uint32_t tumble;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
GamedataSkinRecordsPlaytimeJson,
|
||||
total,
|
||||
race,
|
||||
|
|
@ -158,7 +157,7 @@ struct GamedataSkinRecordsJson final
|
|||
uint32_t rounds;
|
||||
GamedataSkinRecordsPlaytimeJson time;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
GamedataSkinRecordsJson,
|
||||
wins,
|
||||
rounds,
|
||||
|
|
@ -170,7 +169,7 @@ struct GamedataSkinJson final
|
|||
{
|
||||
GamedataSkinRecordsJson records;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSkinJson, records)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSkinJson, records)
|
||||
};
|
||||
|
||||
struct GamedataMapVisitedJson final
|
||||
|
|
@ -181,7 +180,7 @@ struct GamedataMapVisitedJson final
|
|||
bool spbattack;
|
||||
bool mysticmelody;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapVisitedJson, visited, beaten, encore, spbattack, mysticmelody)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapVisitedJson, visited, beaten, encore, spbattack, mysticmelody)
|
||||
};
|
||||
|
||||
struct GamedataMapStatsTimeAttackJson final
|
||||
|
|
@ -189,7 +188,7 @@ struct GamedataMapStatsTimeAttackJson final
|
|||
uint32_t besttime;
|
||||
uint32_t bestlap;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapStatsTimeAttackJson, besttime, bestlap)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapStatsTimeAttackJson, besttime, bestlap)
|
||||
};
|
||||
|
||||
struct GamedataMapStatsSpbAttackJson final
|
||||
|
|
@ -197,7 +196,7 @@ struct GamedataMapStatsSpbAttackJson final
|
|||
uint32_t besttime;
|
||||
uint32_t bestlap;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapStatsSpbAttackJson, besttime, bestlap)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapStatsSpbAttackJson, besttime, bestlap)
|
||||
};
|
||||
|
||||
struct GamedataMapStatsPlaytimeJson final
|
||||
|
|
@ -212,7 +211,7 @@ struct GamedataMapStatsPlaytimeJson final
|
|||
uint32_t timeattack;
|
||||
uint32_t spbattack;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
GamedataMapStatsPlaytimeJson,
|
||||
total,
|
||||
netgame,
|
||||
|
|
@ -232,7 +231,7 @@ struct GamedataMapStatsJson final
|
|||
GamedataMapStatsSpbAttackJson spbattack;
|
||||
GamedataMapStatsPlaytimeJson time;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
GamedataMapStatsJson,
|
||||
timeattack,
|
||||
spbattack,
|
||||
|
|
@ -245,15 +244,15 @@ struct GamedataMapJson final
|
|||
GamedataMapVisitedJson visited;
|
||||
GamedataMapStatsJson stats;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapJson, visited, stats)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataMapJson, visited, stats)
|
||||
};
|
||||
|
||||
struct GamedataSprayCanJson final
|
||||
{
|
||||
std::string map;
|
||||
std::string color;
|
||||
String map;
|
||||
String color;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSprayCanJson, map, color)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSprayCanJson, map, color)
|
||||
};
|
||||
|
||||
struct GamedataCupRecordsJson final
|
||||
|
|
@ -261,24 +260,24 @@ struct GamedataCupRecordsJson final
|
|||
uint8_t bestplacement;
|
||||
uint8_t bestgrade;
|
||||
bool gotemerald;
|
||||
std::string bestskin;
|
||||
String bestskin;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataCupRecordsJson, bestplacement, bestgrade, gotemerald, bestskin)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataCupRecordsJson, bestplacement, bestgrade, gotemerald, bestskin)
|
||||
};
|
||||
|
||||
struct GamedataCupJson final
|
||||
{
|
||||
std::string name;
|
||||
std::vector<GamedataCupRecordsJson> records;
|
||||
String name;
|
||||
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
|
||||
{
|
||||
std::string name;
|
||||
String name;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSealedSwapJson, name)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSealedSwapJson, name)
|
||||
};
|
||||
|
||||
struct GamedataJson final
|
||||
|
|
@ -290,19 +289,19 @@ struct GamedataJson final
|
|||
GamedataMilestonesJson milestones;
|
||||
GamedataPrisonEggPickupsJson prisons;
|
||||
uint32_t tafolderhash;
|
||||
std::vector<bool> emblems;
|
||||
std::vector<bool> unlockables;
|
||||
std::vector<bool> unlockpending;
|
||||
std::vector<bool> conditionsets;
|
||||
Vector<bool> emblems;
|
||||
Vector<bool> unlockables;
|
||||
Vector<bool> unlockpending;
|
||||
Vector<bool> conditionsets;
|
||||
GamedataChallengeGridJson challengegrid;
|
||||
uint32_t timesBeaten;
|
||||
std::unordered_map<std::string, GamedataSkinJson> skins;
|
||||
std::unordered_map<std::string, GamedataMapJson> maps;
|
||||
std::vector<GamedataSprayCanJson> spraycans;
|
||||
std::unordered_map<std::string, GamedataCupJson> cups;
|
||||
std::vector<GamedataSealedSwapJson> sealedswaps;
|
||||
HashMap<String, GamedataSkinJson> skins;
|
||||
HashMap<String, GamedataMapJson> maps;
|
||||
Vector<GamedataSprayCanJson> spraycans;
|
||||
HashMap<String, GamedataCupJson> cups;
|
||||
Vector<GamedataSealedSwapJson> sealedswaps;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
GamedataJson,
|
||||
playtime,
|
||||
rings,
|
||||
|
|
|
|||
|
|
@ -85,8 +85,8 @@ void K_DrawInputDisplay(float x, float y, INT32 flags, char mode, UINT8 pid, boo
|
|||
|
||||
const ticcmd_t& cmd = players[displayplayers[pid]].cmd;
|
||||
const boolean analog = (mode == '4' || mode == '5') ? players[displayplayers[pid]].analoginput : false;
|
||||
const std::string prefix = fmt::format("PR{}", mode);
|
||||
auto gfx = [&](auto format, auto&&... args) { return prefix + fmt::format(format, args...); };
|
||||
srb2::String prefix = srb2::format("PR{}", mode);
|
||||
auto gfx = [&](auto format, auto&&... args) { return prefix + srb2::format(format, args...); };
|
||||
auto but = [&](char key, INT32 gc, UINT32 bt)
|
||||
{
|
||||
bool press = local ? G_PlayerInputAnalog(pid, gc, guessinput) : ((cmd.buttons & bt) == bt);
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ void K_drawSpectatorHUD(boolean director)
|
|||
|
||||
if (player)
|
||||
{
|
||||
std::string label = [player]
|
||||
srb2::String label = [player]
|
||||
{
|
||||
if (player->flashing)
|
||||
{
|
||||
|
|
@ -183,7 +183,7 @@ void K_drawSpectatorHUD(boolean director)
|
|||
|
||||
if (cv_maxplayers.value)
|
||||
{
|
||||
label += fmt::format(" [{}/{}]", numingame, cv_maxplayers.value);
|
||||
label += srb2::format(" [{}/{}]", numingame, cv_maxplayers.value);
|
||||
}
|
||||
|
||||
list.insert({{label.c_str(), "<l_animated>"}});
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@
|
|||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "../core/hash_map.hpp"
|
||||
#include "../core/vector.hpp"
|
||||
#include "../rhi/rhi.hpp"
|
||||
|
||||
namespace srb2::hwr2
|
||||
|
|
@ -77,10 +77,10 @@ class MainPaletteManager final
|
|||
rhi::Handle<rhi::Texture> encore_lighttable_;
|
||||
rhi::Handle<rhi::Texture> default_colormap_;
|
||||
|
||||
std::unordered_map<const uint8_t*, rhi::Handle<rhi::Texture>> colormaps_;
|
||||
std::unordered_map<const uint8_t*, rhi::Handle<rhi::Texture>> lighttables_;
|
||||
std::vector<const uint8_t*> colormaps_to_upload_;
|
||||
std::vector<const uint8_t*> lighttables_to_upload_;
|
||||
srb2::HashMap<const uint8_t*, rhi::Handle<rhi::Texture>> colormaps_;
|
||||
srb2::HashMap<const uint8_t*, rhi::Handle<rhi::Texture>> lighttables_;
|
||||
srb2::Vector<const uint8_t*> colormaps_to_upload_;
|
||||
srb2::Vector<const uint8_t*> lighttables_to_upload_;
|
||||
|
||||
void upload_palette(rhi::Rhi& rhi);
|
||||
void upload_lighttables(rhi::Rhi& rhi);
|
||||
|
|
|
|||
|
|
@ -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)};
|
||||
}
|
||||
|
||||
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);
|
||||
if (trimmed_rect.w % 2 > 0)
|
||||
|
|
@ -299,7 +299,7 @@ void PatchAtlasCache::pack(Rhi& rhi)
|
|||
SRB2_ASSERT(ready_for_lookup());
|
||||
|
||||
// Upload atlased patches
|
||||
std::vector<uint8_t> patch_data;
|
||||
srb2::Vector<uint8_t> patch_data;
|
||||
for (const patch_t* patch_to_upload : patches_to_upload_)
|
||||
{
|
||||
srb2::NotNull<PatchAtlas*> atlas = find_patch(patch_to_upload);
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@
|
|||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <tcb/span.hpp>
|
||||
|
||||
#include "../core/hash_map.hpp"
|
||||
#include "../core/hash_set.hpp"
|
||||
#include "../core/vector.hpp"
|
||||
#include "../r_defs.h"
|
||||
#include "../rhi/rhi.hpp"
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ private:
|
|||
rhi::Handle<rhi::Texture> tex_;
|
||||
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_node[]> rp_nodes {nullptr};
|
||||
|
|
@ -84,11 +84,11 @@ public:
|
|||
/// drawing things like sprites and 2D elements.
|
||||
class PatchAtlasCache
|
||||
{
|
||||
std::vector<PatchAtlas> atlases_;
|
||||
std::unordered_map<const patch_t*, size_t> patch_lookup_;
|
||||
srb2::Vector<PatchAtlas> atlases_;
|
||||
srb2::HashMap<const patch_t*, size_t> patch_lookup_;
|
||||
|
||||
std::unordered_set<const patch_t*> patches_to_pack_;
|
||||
std::unordered_set<const patch_t*> patches_to_upload_;
|
||||
srb2::HashSet<const patch_t*> patches_to_pack_;
|
||||
srb2::HashSet<const patch_t*> patches_to_upload_;
|
||||
|
||||
uint32_t tex_size_ = 2048;
|
||||
size_t max_textures_ = 2;
|
||||
|
|
@ -135,7 +135,7 @@ rhi::Rect trimmed_patch_dimensions(const patch_t* patch);
|
|||
/// during upload, but required for the RHI device's Unpack Alignment of 4 bytes.
|
||||
/// @param patch the patch to convert
|
||||
/// @param out the output vector, cleared before writing.
|
||||
void convert_patch_to_trimmed_rg8_pixels(const patch_t* patch, std::vector<uint8_t>& out);
|
||||
void convert_patch_to_trimmed_rg8_pixels(const patch_t* patch, srb2::Vector<uint8_t>& out);
|
||||
|
||||
} // namespace srb2::hwr2
|
||||
|
||||
|
|
|
|||
|
|
@ -10,12 +10,11 @@
|
|||
|
||||
#include "postprocess_wipe.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <tcb/span.hpp>
|
||||
|
||||
#include "../core/string.h"
|
||||
#include "../f_finale.h"
|
||||
#include "../w_wad.h"
|
||||
|
||||
|
|
@ -106,7 +105,7 @@ void PostprocessWipePass::prepass(Rhi& rhi)
|
|||
return;
|
||||
}
|
||||
|
||||
std::string lumpname = fmt::format(FMT_STRING("FADE{:02d}{:02d}"), wipe_type, wipe_frame);
|
||||
String lumpname = format(FMT_STRING("FADE{:02d}{:02d}"), wipe_type, wipe_frame);
|
||||
lumpnum_t mask_lump = W_CheckNumForName(lumpname.c_str());
|
||||
if (mask_lump == LUMPERROR)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ Handle<Texture> FlatTextureManager::find_or_create_indexed(Rhi& rhi, lumpnum_t l
|
|||
});
|
||||
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);
|
||||
flat_data.reserve(flat_size * flat_size);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@
|
|||
#ifndef __SRB2_HWR2_RESOURCE_MANAGEMENT_HPP__
|
||||
#define __SRB2_HWR2_RESOURCE_MANAGEMENT_HPP__
|
||||
|
||||
#include "../core/hash_map.hpp"
|
||||
#include "../core/vector.hpp"
|
||||
#include "../rhi/rhi.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace srb2::hwr2
|
||||
{
|
||||
|
||||
|
|
@ -27,8 +27,8 @@ class PaletteManager
|
|||
#endif
|
||||
rhi::Handle<rhi::Texture> default_colormap_;
|
||||
|
||||
std::unordered_map<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>> colormaps_;
|
||||
srb2::HashMap<const uint8_t*, rhi::Handle<rhi::Texture>> lighttables_;
|
||||
|
||||
public:
|
||||
PaletteManager();
|
||||
|
|
@ -67,9 +67,9 @@ from patch_t.
|
|||
/// @brief Manages textures corresponding to specific flats indexed by lump number.
|
||||
class FlatTextureManager
|
||||
{
|
||||
std::unordered_map<lumpnum_t, rhi::Handle<rhi::Texture>> flats_;
|
||||
std::vector<lumpnum_t> to_upload_;
|
||||
std::vector<rhi::Handle<rhi::Texture>> disposed_textures_;
|
||||
srb2::HashMap<lumpnum_t, rhi::Handle<rhi::Texture>> flats_;
|
||||
srb2::Vector<lumpnum_t> to_upload_;
|
||||
srb2::Vector<rhi::Handle<rhi::Texture>> disposed_textures_;
|
||||
|
||||
public:
|
||||
FlatTextureManager();
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@
|
|||
#include "twodee_renderer.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <stb_rect_pack.h>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include "../core/hash_set.hpp"
|
||||
#include "blendmode.hpp"
|
||||
#include "../r_patch.h"
|
||||
#include "../v_video.h"
|
||||
|
|
@ -248,7 +248,7 @@ void TwodeeRenderer::flush(Rhi& rhi, Twodee& twodee)
|
|||
}
|
||||
|
||||
// Stage 1 - command list patch detection
|
||||
std::unordered_set<const patch_t*> found_patches;
|
||||
srb2::HashSet<const patch_t*> found_patches;
|
||||
for (const auto& list : twodee)
|
||||
{
|
||||
for (const auto& cmd : list.cmds)
|
||||
|
|
|
|||
|
|
@ -12,16 +12,16 @@
|
|||
#define __SRB2_IO_STREAMS_HPP__
|
||||
|
||||
#include <cstddef>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <tcb/span.hpp>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "../core/string.h"
|
||||
#include "../core/vector.hpp"
|
||||
|
||||
namespace srb2::io
|
||||
{
|
||||
|
||||
|
|
@ -484,13 +484,13 @@ inline void read_exact(SpanStream& stream, tcb::span<std::byte> buffer)
|
|||
}
|
||||
|
||||
class VecStream {
|
||||
std::vector<std::byte> vec_;
|
||||
srb2::Vector<std::byte> vec_;
|
||||
std::size_t head_ {0};
|
||||
|
||||
public:
|
||||
VecStream() = default;
|
||||
VecStream(const std::vector<std::byte>& vec) : vec_(vec) {}
|
||||
VecStream(std::vector<std::byte>&& vec) : vec_(std::move(vec)) {}
|
||||
VecStream(const srb2::Vector<std::byte>& vec) : vec_(vec) {}
|
||||
VecStream(srb2::Vector<std::byte>&& vec) : vec_(std::move(vec)) {}
|
||||
VecStream(const VecStream& rhs) = default;
|
||||
VecStream(VecStream&& rhs) = default;
|
||||
|
||||
|
|
@ -549,7 +549,7 @@ public:
|
|||
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);
|
||||
};
|
||||
|
|
@ -674,7 +674,7 @@ template <typename I,
|
|||
class ZlibInputStream {
|
||||
I inner_;
|
||||
z_stream stream_;
|
||||
std::vector<std::byte> buf_;
|
||||
srb2::Vector<std::byte> buf_;
|
||||
std::size_t buf_head_;
|
||||
bool zstream_initialized_;
|
||||
bool zstream_ended_;
|
||||
|
|
@ -820,7 +820,7 @@ template <typename O,
|
|||
class BufferedOutputStream final
|
||||
{
|
||||
O inner_;
|
||||
std::vector<std::byte> buf_;
|
||||
srb2::Vector<std::byte> buf_;
|
||||
tcb::span<const std::byte>::size_type cap_;
|
||||
|
||||
public:
|
||||
|
|
@ -872,7 +872,7 @@ template <typename I,
|
|||
class BufferedInputStream final
|
||||
{
|
||||
I inner_;
|
||||
std::vector<std::byte> buf_;
|
||||
srb2::Vector<std::byte> buf_;
|
||||
tcb::span<std::byte>::size_type cap_;
|
||||
|
||||
public:
|
||||
|
|
@ -933,7 +933,7 @@ extern template class BufferedInputStream<FileStream>;
|
|||
|
||||
template <typename I, typename O>
|
||||
StreamSize pipe_all(I& input, O& output) {
|
||||
std::vector<std::byte> buf;
|
||||
srb2::Vector<std::byte> buf;
|
||||
|
||||
StreamSize total_written = 0;
|
||||
StreamSize read_this_time = 0;
|
||||
|
|
@ -951,7 +951,7 @@ StreamSize pipe_all(I& input, O& output) {
|
|||
}
|
||||
|
||||
template <typename I>
|
||||
std::vector<std::byte> read_to_vec(I& input) {
|
||||
srb2::Vector<std::byte> read_to_vec(I& input) {
|
||||
VecStream out;
|
||||
pipe_all(input, out);
|
||||
return std::move(out.vector());
|
||||
|
|
|
|||
|
|
@ -12,13 +12,14 @@
|
|||
/// \file k_bans.c
|
||||
/// \brief replacement for DooM Legacy ban system
|
||||
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#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 "k_bans.h"
|
||||
#include "byteptr.h" // READ/WRITE macros
|
||||
|
|
@ -34,7 +35,9 @@
|
|||
#include "z_zone.h"
|
||||
#include "i_addrinfo.h" // I_getaddrinfo
|
||||
|
||||
using nlohmann::json;
|
||||
using srb2::JsonArray;
|
||||
using srb2::JsonObject;
|
||||
using srb2::JsonValue;
|
||||
|
||||
static mysockaddr_t *DuplicateSockAddr(const mysockaddr_t *source)
|
||||
{
|
||||
|
|
@ -43,22 +46,22 @@ static mysockaddr_t *DuplicateSockAddr(const mysockaddr_t *source)
|
|||
return dup;
|
||||
}
|
||||
|
||||
static std::vector<banrecord_t> bans;
|
||||
static srb2::Vector<banrecord_t> bans;
|
||||
|
||||
static uint8_t allZero[PUBKEYLENGTH];
|
||||
|
||||
static void load_bans_array_v1(json& array)
|
||||
static void load_bans_array_v1(const JsonArray& array)
|
||||
{
|
||||
for (json& object : array)
|
||||
for (const JsonValue& object : array)
|
||||
{
|
||||
uint8_t public_key_bin[PUBKEYLENGTH];
|
||||
|
||||
std::string public_key = object.at("public_key");
|
||||
std::string ip_address = object.at("ip_address");
|
||||
time_t expires = object.at("expires");
|
||||
UINT8 subnet_mask = object.at("subnet_mask");
|
||||
std::string username = object.at("username");
|
||||
std::string reason = object.at("reason");
|
||||
srb2::String public_key = object.at("public_key").get<srb2::String>();
|
||||
srb2::String ip_address = object.at("ip_address").get<srb2::String>();
|
||||
time_t expires = object.at("expires").get<int64_t>();
|
||||
UINT8 subnet_mask = object.at("subnet_mask").get<UINT8>();
|
||||
srb2::String username = object.at("username").get<srb2::String>();
|
||||
srb2::String reason = object.at("reason").get<srb2::String>();
|
||||
|
||||
if (!FromPrettyRRID(public_key_bin, public_key.c_str()))
|
||||
{
|
||||
|
|
@ -86,16 +89,31 @@ void SV_LoadBans(void)
|
|||
if (!server)
|
||||
return;
|
||||
|
||||
json object;
|
||||
JsonValue object;
|
||||
|
||||
srb2::String banspath { srb2::format("{}/{}", srb2home, BANFILE) };
|
||||
srb2::io::BufferedInputStream<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
|
||||
{
|
||||
std::ifstream f(va(pandf, srb2home, BANFILE));
|
||||
|
||||
if (f.is_open())
|
||||
srb2::Vector<tcb::byte> data = srb2::io::read_to_vec(bis);
|
||||
srb2::String data_s;
|
||||
data_s.reserve(data.size());
|
||||
for (auto b : data)
|
||||
{
|
||||
f >> object;
|
||||
data_s.push_back(std::to_integer<char>(b));
|
||||
}
|
||||
object = JsonValue::from_json_string(data_s);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
|
|
@ -115,11 +133,11 @@ void SV_LoadBans(void)
|
|||
{
|
||||
if (object.value("version", 1) == 1)
|
||||
{
|
||||
json& array = object.at("bans");
|
||||
JsonValue& array = object.at("bans");
|
||||
|
||||
if (array.is_array())
|
||||
{
|
||||
load_bans_array_v1(array);
|
||||
load_bans_array_v1(array.as_array());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -131,31 +149,36 @@ void SV_LoadBans(void)
|
|||
|
||||
void SV_SaveBans(void)
|
||||
{
|
||||
json object = json::object();
|
||||
JsonValue object = JsonValue(JsonObject());
|
||||
|
||||
object["version"] = 1;
|
||||
json& array = object["bans"];
|
||||
JsonValue& array_value = object["bans"];
|
||||
|
||||
array = json::array();
|
||||
array_value = JsonValue(JsonArray());
|
||||
JsonArray& array = array_value.as_array();
|
||||
|
||||
for (banrecord_t& ban : bans)
|
||||
{
|
||||
if (ban.deleted)
|
||||
continue;
|
||||
|
||||
array.push_back({
|
||||
array.push_back(JsonObject {
|
||||
{"public_key", GetPrettyRRID(ban.public_key, false)},
|
||||
{"ip_address", SOCK_AddrToStr(ban.address)},
|
||||
{"subnet_mask", ban.mask},
|
||||
{"expires", ban.expires},
|
||||
{"expires", static_cast<int64_t>(ban.expires)},
|
||||
{"username", ban.username},
|
||||
{"reason", ban.reason},
|
||||
});
|
||||
}
|
||||
|
||||
srb2::String json_string = object.to_json_string();
|
||||
srb2::String banfile_path = srb2::format("{}/{}", srb2home, BANFILE);
|
||||
|
||||
try
|
||||
{
|
||||
std::ofstream(va(pandf, srb2home, BANFILE)) << object;
|
||||
srb2::io::FileStream fs { banfile_path, srb2::io::FileStreamMode::kWrite };
|
||||
srb2::io::write_exact(fs, tcb::as_bytes(tcb::span(json_string)));
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
|
|
@ -345,10 +368,10 @@ static void SV_BanSearch(boolean remove)
|
|||
const char* stringaddress = SOCK_AddrToStr(ban.address);
|
||||
const char* stringkey = GetPrettyRRID(ban.public_key, true);
|
||||
|
||||
std::string recordprint = fmt::format(
|
||||
srb2::String recordprint = srb2::format(
|
||||
"{}{} - {} [{}] - {}",
|
||||
stringaddress,
|
||||
ban.mask && ban.mask != 32 ? fmt::format("/{}", ban.mask) : "",
|
||||
ban.mask && ban.mask != 32 ? srb2::format("/{}", ban.mask) : "",
|
||||
ban.username,
|
||||
stringkey,
|
||||
ban.reason
|
||||
|
|
@ -359,7 +382,7 @@ static void SV_BanSearch(boolean remove)
|
|||
if (ban.expires < now)
|
||||
recordprint += " - EXPIRED";
|
||||
else
|
||||
recordprint += fmt::format(" - expires {}m", (ban.expires - now)/60);
|
||||
recordprint += srb2::format(" - expires {}m", (ban.expires - now)/60);
|
||||
}
|
||||
|
||||
CONS_Printf("%s\n", recordprint.c_str());
|
||||
|
|
|
|||
|
|
@ -12,11 +12,8 @@
|
|||
|
||||
#include "k_credits.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <fmt/format.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
|
|
@ -59,7 +56,9 @@
|
|||
#include "r_main.h"
|
||||
#include "m_easing.h"
|
||||
|
||||
using nlohmann::json;
|
||||
using srb2::JsonArray;
|
||||
using srb2::JsonObject;
|
||||
using srb2::JsonValue;
|
||||
|
||||
enum credits_slide_types_e
|
||||
{
|
||||
|
|
@ -75,14 +74,14 @@ enum credits_slide_types_e
|
|||
struct credits_slide_s
|
||||
{
|
||||
credits_slide_types_e type;
|
||||
std::string label;
|
||||
std::vector<std::string> strings;
|
||||
srb2::String label;
|
||||
srb2::Vector<srb2::String> strings;
|
||||
size_t strings_height;
|
||||
boolean play_demo_afterwards;
|
||||
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
|
||||
{
|
||||
|
|
@ -94,10 +93,10 @@ struct credits_star_s
|
|||
static struct credits_s
|
||||
{
|
||||
size_t current_slide;
|
||||
std::vector<UINT16> demo_maps;
|
||||
srb2::Vector<UINT16> demo_maps;
|
||||
boolean skip;
|
||||
|
||||
std::vector<struct credits_star_s> stars;
|
||||
srb2::Vector<struct credits_star_s> stars;
|
||||
|
||||
fixed_t transition;
|
||||
fixed_t transition_prev;
|
||||
|
|
@ -105,7 +104,7 @@ static struct credits_s
|
|||
|
||||
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;
|
||||
tic_t split_slide_delay;
|
||||
|
||||
|
|
@ -142,12 +141,14 @@ void F_LoadCreditsDefinitions(void)
|
|||
size_t credits_lump_len = W_LumpLength(credits_lump_id);
|
||||
const char *credits_lump = static_cast<const char *>( W_CacheLumpNum(credits_lump_id, PU_CACHE) );
|
||||
|
||||
json credits_array = json::parse(credits_lump, credits_lump + credits_lump_len);
|
||||
if (credits_array.is_array() == false)
|
||||
srb2::String json_string { credits_lump, credits_lump_len };
|
||||
JsonValue credits_parsed = JsonValue::from_json_string(json_string);
|
||||
if (credits_parsed.is_array() == false)
|
||||
{
|
||||
I_Error("credits_def parse error: Not a JSON array");
|
||||
return;
|
||||
}
|
||||
JsonArray credits_array = credits_parsed.as_array();
|
||||
|
||||
if (credits_array.size() == 0)
|
||||
{
|
||||
|
|
@ -156,11 +157,11 @@ void F_LoadCreditsDefinitions(void)
|
|||
|
||||
try
|
||||
{
|
||||
for (json& slide_obj : credits_array)
|
||||
for (JsonValue& slide_obj : credits_array)
|
||||
{
|
||||
struct credits_slide_s slide;
|
||||
|
||||
std::string type_str = slide_obj.value("type", "scroll");
|
||||
srb2::String type_str = slide_obj.value("type", srb2::String("scroll"));
|
||||
|
||||
if (type_str == "scroll")
|
||||
{
|
||||
|
|
@ -196,18 +197,19 @@ void F_LoadCreditsDefinitions(void)
|
|||
throw std::runtime_error("unexpected type name '" + type_str + "'");
|
||||
}
|
||||
|
||||
slide.label = slide_obj.value("label", "");
|
||||
slide.label = slide_obj.value("label", srb2::String(""));
|
||||
|
||||
slide.strings_height = 0;
|
||||
|
||||
if (slide_obj.contains("strings"))
|
||||
{
|
||||
json strings_array = slide_obj.at("strings");
|
||||
if (strings_array.is_array() == true)
|
||||
JsonValue strings_value = slide_obj.at("strings");
|
||||
if (strings_value.is_array() == true)
|
||||
{
|
||||
JsonArray& strings_array = strings_value.as_array();
|
||||
for (size_t i = 0; i < strings_array.size(); i++)
|
||||
{
|
||||
slide.strings.push_back( strings_array.at(i) );
|
||||
slide.strings.push_back( strings_array.at(i).get<srb2::String>() );
|
||||
|
||||
if (slide.type == CRED_TYPE_SCROLL)
|
||||
{
|
||||
|
|
@ -289,7 +291,7 @@ static void F_InitCreditsSlide(void)
|
|||
size_t max_strings_per_screen = (num_strings - 1) / num_sub_screens + 1;
|
||||
|
||||
size_t str_id = 0;
|
||||
std::vector<std::string> screen_strings;
|
||||
srb2::Vector<srb2::String> screen_strings;
|
||||
|
||||
if (max_strings_per_screen == kMaxSlideStrings
|
||||
&& num_strings % kMaxSlideStrings == 1)
|
||||
|
|
@ -342,24 +344,24 @@ static void F_InitCreditsSlide(void)
|
|||
#endif
|
||||
)
|
||||
{
|
||||
slide->strings.push_back("#" + std::string(def->title));
|
||||
slide->strings.push_back("#" + srb2::String(def->title));
|
||||
slide->strings_height += 12;
|
||||
|
||||
if (def->author)
|
||||
{
|
||||
slide->strings.push_back("by " + std::string(def->author));
|
||||
slide->strings.push_back("by " + srb2::String(def->author));
|
||||
slide->strings_height += 12;
|
||||
}
|
||||
|
||||
if (def->source)
|
||||
{
|
||||
slide->strings.push_back("from " + std::string(def->source));
|
||||
slide->strings.push_back("from " + srb2::String(def->source));
|
||||
slide->strings_height += 12;
|
||||
}
|
||||
|
||||
if (def->composers)
|
||||
{
|
||||
slide->strings.push_back("originally by " + std::string(def->composers));
|
||||
slide->strings.push_back("originally by " + srb2::String(def->composers));
|
||||
slide->strings_height += 12;
|
||||
}
|
||||
|
||||
|
|
@ -478,7 +480,7 @@ void F_ContinueCredits(void)
|
|||
|
||||
static UINT16 F_PickRandomCreditsDemoMap(void)
|
||||
{
|
||||
std::vector<UINT16> allowedMaps;
|
||||
srb2::Vector<UINT16> allowedMaps;
|
||||
|
||||
for (INT32 i = 0; i < basenummapheaders; i++) // Only take from the base game.
|
||||
{
|
||||
|
|
@ -911,7 +913,7 @@ static void F_DrawCreditsScroll(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
std::string new_str = str;
|
||||
srb2::String new_str = str;
|
||||
|
||||
if (new_str.at(0) == '*')
|
||||
{
|
||||
|
|
@ -1017,7 +1019,7 @@ static void F_DrawCreditsSlide(void)
|
|||
return;
|
||||
}
|
||||
|
||||
const std::vector<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;
|
||||
|
||||
fixed_t y = 0;
|
||||
|
|
@ -1113,7 +1115,7 @@ static void F_DrawCreditsTyler52(void)
|
|||
V_DrawFadeScreen(0xFF00, 31 - (g_credits.tyler_fade * 4));
|
||||
}
|
||||
|
||||
std::string memory_str = "In memory of";
|
||||
srb2::String memory_str = "In memory of";
|
||||
const fixed_t memory_width = V_StringScaledWidth(
|
||||
FRACUNIT, FRACUNIT, FRACUNIT,
|
||||
0, LSLOW_FONT,
|
||||
|
|
@ -1126,7 +1128,7 @@ static void F_DrawCreditsTyler52(void)
|
|||
memory_str.c_str()
|
||||
);
|
||||
|
||||
std::string tyler_str = "Tyler52";
|
||||
srb2::String tyler_str = "Tyler52";
|
||||
const fixed_t tyler_width = V_StringScaledWidth(
|
||||
FRACUNIT, FRACUNIT, FRACUNIT,
|
||||
0, LSHI_FONT,
|
||||
|
|
|
|||
|
|
@ -14,9 +14,10 @@
|
|||
#include "k_dialogue.hpp"
|
||||
#include "k_dialogue.h"
|
||||
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
|
||||
#include "core/string.h"
|
||||
#include "info.h"
|
||||
#include "sounds.h"
|
||||
#include "g_game.h"
|
||||
|
|
@ -43,7 +44,7 @@ void Dialogue::Typewriter::ClearText(void)
|
|||
textDest.clear();
|
||||
}
|
||||
|
||||
void Dialogue::Typewriter::NewText(std::string newText)
|
||||
void Dialogue::Typewriter::NewText(const srb2::String& newText)
|
||||
{
|
||||
text.clear();
|
||||
|
||||
|
|
@ -174,7 +175,7 @@ void Dialogue::SetSpeaker(void)
|
|||
typewriter.voiceSfx = sfx_ktalk;
|
||||
}
|
||||
|
||||
void Dialogue::SetSpeaker(std::string skinName, int portraitID)
|
||||
void Dialogue::SetSpeaker(srb2::String skinName, int portraitID)
|
||||
{
|
||||
Init();
|
||||
|
||||
|
|
@ -215,7 +216,7 @@ void Dialogue::SetSpeaker(std::string skinName, int portraitID)
|
|||
}
|
||||
}
|
||||
|
||||
void Dialogue::SetSpeaker(std::string name, patch_t *patch, UINT8 *colormap, sfxenum_t voice)
|
||||
void Dialogue::SetSpeaker(srb2::String name, patch_t *patch, UINT8 *colormap, sfxenum_t voice)
|
||||
{
|
||||
Init();
|
||||
|
||||
|
|
@ -472,7 +473,7 @@ void Dialogue::Draw(void)
|
|||
.flags(V_VFLIP|V_FLIP)
|
||||
.patch(patchCache["TUTDIAGE"]);
|
||||
|
||||
std::string intertext = "<large>";
|
||||
srb2::String intertext = "<large>";
|
||||
|
||||
drawer
|
||||
.xy(10 - BASEVIDWIDTH, -3-32)
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@
|
|||
#ifndef __K_DIALOGUE_HPP__
|
||||
#define __K_DIALOGUE_HPP__
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "core/hash_map.hpp"
|
||||
#include "core/string.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomtype.h"
|
||||
#include "typedef.h"
|
||||
|
|
@ -33,8 +33,8 @@ public:
|
|||
static constexpr fixed_t kSlideSpeed = FRACUNIT / (TICRATE / 5);
|
||||
|
||||
void SetSpeaker(void);
|
||||
void SetSpeaker(std::string skinName, int portraitID);
|
||||
void SetSpeaker(std::string name, patch_t *patch, UINT8 *colormap, sfxenum_t voice);
|
||||
void SetSpeaker(srb2::String skinName, int portraitID);
|
||||
void SetSpeaker(srb2::String name, patch_t *patch, UINT8 *colormap, sfxenum_t voice);
|
||||
|
||||
void NewText(std::string_view newText);
|
||||
|
||||
|
|
@ -60,8 +60,8 @@ public:
|
|||
static constexpr fixed_t kTextSpeedDefault = FRACUNIT;
|
||||
static constexpr fixed_t kTextPunctPause = (FRACUNIT * TICRATE * 2) / 5;
|
||||
|
||||
std::string text;
|
||||
std::string textDest;
|
||||
srb2::String text;
|
||||
srb2::String textDest;
|
||||
|
||||
fixed_t textTimer;
|
||||
fixed_t textSpeed;
|
||||
|
|
@ -71,7 +71,7 @@ public:
|
|||
sfxenum_t voiceSfx;
|
||||
bool syllable;
|
||||
|
||||
void NewText(std::string newText);
|
||||
void NewText(const srb2::String& newText);
|
||||
void ClearText(void);
|
||||
|
||||
void WriteText(void);
|
||||
|
|
@ -86,11 +86,11 @@ private:
|
|||
patch_t *bgPatch;
|
||||
patch_t *confirmPatch;
|
||||
|
||||
std::string speaker;
|
||||
srb2::String speaker;
|
||||
patch_t *portrait;
|
||||
UINT8 *portraitColormap;
|
||||
|
||||
std::unordered_map<std::string_view, patch_t*> patchCache;
|
||||
srb2::HashMap<std::string_view, patch_t*> patchCache;
|
||||
|
||||
bool active;
|
||||
fixed_t slide;
|
||||
|
|
|
|||
|
|
@ -11,11 +11,12 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "core/string.h"
|
||||
#include "core/vector.hpp"
|
||||
#include "k_hud.h"
|
||||
#include "k_kart.h"
|
||||
#include "k_battle.h"
|
||||
|
|
@ -6332,21 +6333,21 @@ typedef enum
|
|||
|
||||
typedef struct
|
||||
{
|
||||
std::string text;
|
||||
srb2::String text;
|
||||
sfxenum_t sound;
|
||||
} message_t;
|
||||
|
||||
struct messagestate_t
|
||||
{
|
||||
std::deque<std::string> messages;
|
||||
std::string objective = "";
|
||||
std::deque<srb2::String> messages;
|
||||
srb2::String objective = "";
|
||||
tic_t timer = 0;
|
||||
boolean persist = false;
|
||||
messagemode_t mode = MM_IN;
|
||||
const tic_t speedyswitch = 2*TICRATE;
|
||||
const tic_t lazyswitch = 4*TICRATE;
|
||||
|
||||
void add(std::string msg)
|
||||
void add(srb2::String msg)
|
||||
{
|
||||
messages.push_back(msg);
|
||||
}
|
||||
|
|
@ -6384,7 +6385,7 @@ struct messagestate_t
|
|||
switch (mode)
|
||||
{
|
||||
case MM_IN:
|
||||
if (timer > messages[0].length())
|
||||
if (timer > messages[0].size())
|
||||
switch_mode(MM_HOLD);
|
||||
break;
|
||||
case MM_HOLD:
|
||||
|
|
@ -6394,7 +6395,7 @@ struct messagestate_t
|
|||
switch_mode(MM_OUT);
|
||||
break;
|
||||
case MM_OUT:
|
||||
if (timer > messages[0].length())
|
||||
if (timer > messages[0].size())
|
||||
next();
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "k_podium.h"
|
||||
|
||||
#include "core/string.h"
|
||||
#include "doomdef.h"
|
||||
#include "d_main.h"
|
||||
#include "d_netcmd.h"
|
||||
|
|
@ -51,8 +52,6 @@
|
|||
|
||||
#include "k_hud.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PODIUM_ST_CONGRATS_SLIDEIN,
|
||||
|
|
@ -652,7 +651,7 @@ void podiumData_s::Draw(void)
|
|||
}
|
||||
|
||||
{
|
||||
std::string emeraldName;
|
||||
srb2::String emeraldName;
|
||||
if (emeraldNum > 7)
|
||||
{
|
||||
emeraldName = (useWhiteFrame ? "K_SUPER2" : "K_SUPER1");
|
||||
|
|
|
|||
|
|
@ -12,10 +12,13 @@
|
|||
/// \brief implements methods for profiles etc.
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <exception>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "core/string.h"
|
||||
#include "core/vector.hpp"
|
||||
#include "io/streams.hpp"
|
||||
#include "doomtype.h"
|
||||
#include "d_main.h" // pandf
|
||||
|
|
@ -253,7 +256,6 @@ void PR_InitNewProfile(void)
|
|||
void PR_SaveProfiles(void)
|
||||
{
|
||||
namespace fs = std::filesystem;
|
||||
using json = nlohmann::json;
|
||||
using namespace srb2;
|
||||
namespace io = srb2::io;
|
||||
|
||||
|
|
@ -271,13 +273,13 @@ void PR_SaveProfiles(void)
|
|||
profile_t* cprof = profilesList[i];
|
||||
|
||||
jsonprof.version = PROFILEVER;
|
||||
jsonprof.profilename = std::string(cprof->profilename);
|
||||
jsonprof.profilename = String(cprof->profilename);
|
||||
std::copy(std::begin(cprof->public_key), std::end(cprof->public_key), std::begin(jsonprof.publickey));
|
||||
std::copy(std::begin(cprof->secret_key), std::end(cprof->secret_key), std::begin(jsonprof.secretkey));
|
||||
jsonprof.playername = std::string(cprof->playername);
|
||||
jsonprof.skinname = std::string(cprof->skinname);
|
||||
jsonprof.colorname = std::string(skincolors[cprof->color].name);
|
||||
jsonprof.followername = std::string(cprof->follower);
|
||||
jsonprof.playername = String(cprof->playername);
|
||||
jsonprof.skinname = String(cprof->skinname);
|
||||
jsonprof.colorname = String(skincolors[cprof->color].name);
|
||||
jsonprof.followername = String(cprof->follower);
|
||||
if (cprof->followercolor == FOLLOWERCOLOR_MATCH)
|
||||
{
|
||||
jsonprof.followercolorname = "Match";
|
||||
|
|
@ -292,11 +294,11 @@ void PR_SaveProfiles(void)
|
|||
}
|
||||
else if (cprof->followercolor >= numskincolors)
|
||||
{
|
||||
jsonprof.followercolorname = std::string();
|
||||
jsonprof.followercolorname = String();
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonprof.followercolorname = std::string(skincolors[cprof->followercolor].name);
|
||||
jsonprof.followercolorname = String(skincolors[cprof->followercolor].name);
|
||||
}
|
||||
jsonprof.records.wins = cprof->wins;
|
||||
jsonprof.records.rounds = cprof->rounds;
|
||||
|
|
@ -310,7 +312,7 @@ void PR_SaveProfiles(void)
|
|||
|
||||
for (size_t j = 0; j < num_gamecontrols; j++)
|
||||
{
|
||||
std::vector<int32_t> mappings;
|
||||
srb2::Vector<int32_t> mappings;
|
||||
for (size_t k = 0; k < MAXINPUTMAPPING; k++)
|
||||
{
|
||||
mappings.push_back(cprof->controls[j][k]);
|
||||
|
|
@ -321,16 +323,18 @@ void PR_SaveProfiles(void)
|
|||
ng.profiles.emplace_back(std::move(jsonprof));
|
||||
}
|
||||
|
||||
std::vector<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);
|
||||
std::string bakpath = fmt::format("{}.bak", realpath);
|
||||
String realpath = srb2::format("{}/{}", srb2home, PROFILESFILE);
|
||||
String bakpath = srb2::format("{}.bak", realpath);
|
||||
|
||||
if (fs::exists(realpath))
|
||||
if (fs::exists(fs::path(static_cast<std::string_view>(realpath))))
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
@ -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); // reserved3
|
||||
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();
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
|
|
@ -367,7 +371,6 @@ void PR_LoadProfiles(void)
|
|||
namespace fs = std::filesystem;
|
||||
using namespace srb2;
|
||||
namespace io = srb2::io;
|
||||
using json = nlohmann::json;
|
||||
|
||||
profile_t *dprofile = PR_MakeProfile(
|
||||
PROFILEDEFAULTNAME,
|
||||
|
|
@ -378,7 +381,7 @@ void PR_LoadProfiles(void)
|
|||
true
|
||||
);
|
||||
|
||||
std::string datapath {fmt::format("{}/{}", srb2home, PROFILESFILE)};
|
||||
String datapath { srb2::format("{}/{}", srb2home, PROFILESFILE) };
|
||||
|
||||
io::BufferedInputStream<io::FileStream> bis;
|
||||
try
|
||||
|
|
@ -413,11 +416,10 @@ void PR_LoadProfiles(void)
|
|||
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
|
||||
tcb::span<uint8_t> remainder_as_u8 = tcb::span((uint8_t*)remainder.data(), remainder.size());
|
||||
json parsed = json::from_ubjson(remainder_as_u8);
|
||||
js = parsed.template get<ProfilesJson>();
|
||||
JsonValue parsed = JsonValue::from_ubjson(remainder);
|
||||
from_json(parsed, js);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@
|
|||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "core/json.hpp"
|
||||
#include "core/string.h"
|
||||
#include "core/vector.hpp"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
|
@ -38,7 +38,7 @@ struct ProfileRecordsJson
|
|||
uint32_t wins;
|
||||
uint32_t rounds;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ProfileRecordsJson, wins, rounds)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ProfileRecordsJson, wins, rounds)
|
||||
};
|
||||
|
||||
struct ProfilePreferencesJson
|
||||
|
|
@ -50,9 +50,8 @@ struct ProfilePreferencesJson
|
|||
bool autoring;
|
||||
bool rumble;
|
||||
uint8_t fov;
|
||||
tm test;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
ProfilePreferencesJson,
|
||||
kickstartaccel,
|
||||
autoroulette,
|
||||
|
|
@ -67,19 +66,19 @@ struct ProfilePreferencesJson
|
|||
struct ProfileJson
|
||||
{
|
||||
uint32_t version;
|
||||
std::string profilename;
|
||||
std::string playername;
|
||||
String profilename;
|
||||
String playername;
|
||||
std::array<uint8_t, 32> publickey = {{}};
|
||||
std::array<uint8_t, 64> secretkey = {{}};
|
||||
std::string skinname;
|
||||
std::string colorname;
|
||||
std::string followername;
|
||||
std::string followercolorname;
|
||||
String skinname;
|
||||
String colorname;
|
||||
String followername;
|
||||
String followercolorname;
|
||||
ProfileRecordsJson records;
|
||||
ProfilePreferencesJson preferences;
|
||||
std::vector<std::vector<int32_t>> controls = {};
|
||||
Vector<Vector<int32_t>> controls = {};
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
ProfileJson,
|
||||
version,
|
||||
profilename,
|
||||
|
|
@ -98,9 +97,9 @@ struct ProfileJson
|
|||
|
||||
struct ProfilesJson
|
||||
{
|
||||
std::vector<ProfileJson> profiles;
|
||||
Vector<ProfileJson> profiles;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ProfilesJson, profiles)
|
||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ProfilesJson, profiles)
|
||||
};
|
||||
|
||||
} // namespace srb2
|
||||
|
|
|
|||
|
|
@ -24,10 +24,12 @@
|
|||
#include "cxxutil.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "core/string.h"
|
||||
#include "core/vector.hpp"
|
||||
|
||||
// The number of sparkles per waypoint connection in the waypoint visualisation
|
||||
static const UINT32 SPARKLES_PER_CONNECTION = 16U;
|
||||
|
||||
|
|
@ -2377,8 +2379,8 @@ static BlockItReturn_t K_TrackWaypointNearOffroad(line_t *line)
|
|||
struct complexity_sneaker_s
|
||||
{
|
||||
fixed_t bbox[4];
|
||||
//std::vector<sector_t *> sectors;
|
||||
//std::vector<mapthing_t *> things;
|
||||
//srb2::Vector<sector_t *> sectors;
|
||||
//srb2::Vector<mapthing_t *> things;
|
||||
|
||||
complexity_sneaker_s(sector_t *sec)
|
||||
{
|
||||
|
|
@ -2631,7 +2633,7 @@ static INT32 K_CalculateTrackComplexity(void)
|
|||
|
||||
delta = FixedMul(delta, FixedMul(FixedMul(dist_factor, radius_factor), wall_factor));
|
||||
|
||||
std::string msg = fmt::format(
|
||||
srb2::String msg = srb2::format(
|
||||
"TURN [{}]: r: {:.2f}, d: {:.2f}, w: {:.2f}, r*d*w: {:.2f}, DELTA: {}\n",
|
||||
turn_id,
|
||||
FixedToFloat(radius_factor),
|
||||
|
|
@ -2644,7 +2646,7 @@ static INT32 K_CalculateTrackComplexity(void)
|
|||
trackcomplexity += (delta / FRACUNIT);
|
||||
}
|
||||
|
||||
std::vector<complexity_sneaker_s> sneaker_panels;
|
||||
srb2::Vector<complexity_sneaker_s> sneaker_panels;
|
||||
|
||||
for (size_t i = 0; i < numsectors; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,10 +10,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
|
|
@ -21,6 +19,9 @@ extern "C" {
|
|||
#include "blua/lua.h"
|
||||
};
|
||||
|
||||
#include "core/hash_map.hpp"
|
||||
#include "core/string.h"
|
||||
#include "core/vector.hpp"
|
||||
#include "v_draw.hpp"
|
||||
|
||||
#include "command.h"
|
||||
|
|
@ -58,7 +59,7 @@ struct lua_timer_t
|
|||
namespace
|
||||
{
|
||||
|
||||
std::unordered_map<std::string, lua_timer_t> g_tic_timers;
|
||||
srb2::HashMap<srb2::String, lua_timer_t> g_tic_timers;
|
||||
|
||||
}; // namespace
|
||||
|
||||
|
|
@ -156,7 +157,7 @@ void LUA_RenderTimers(void)
|
|||
return;
|
||||
}
|
||||
|
||||
std::vector<decltype(g_tic_timers)::iterator> view;
|
||||
srb2::Vector<decltype(g_tic_timers)::Iter> view;
|
||||
view.reserve(g_tic_timers.size());
|
||||
|
||||
auto color_flag = [](double t)
|
||||
|
|
|
|||
21
src/m_pw.cpp
21
src/m_pw.cpp
|
|
@ -14,13 +14,13 @@
|
|||
#include <cctype>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include "modp_b64/modp_b64.h"
|
||||
|
||||
#include "core/string.h"
|
||||
#include "core/vector.hpp"
|
||||
#include "cxxutil.hpp"
|
||||
|
||||
#include "command.h"
|
||||
|
|
@ -43,12 +43,13 @@ namespace
|
|||
|
||||
constexpr const UINT8 kRRSalt[17] = "0L4rlK}{9ay6'VJS";
|
||||
|
||||
std::array<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;
|
||||
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");
|
||||
std::copy(encoded.begin(), encoded.end(), decoded.begin());
|
||||
std::copy(encoded_stl.begin(), encoded_stl.end(), decoded.begin());
|
||||
return decoded;
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +61,7 @@ struct Pw
|
|||
const std::array<UINT8, M_PW_BUF_SIZE> hash_;
|
||||
};
|
||||
|
||||
std::vector<Pw> passwords;
|
||||
srb2::Vector<Pw> passwords;
|
||||
|
||||
// m_cond.c
|
||||
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*>;
|
||||
|
||||
// Normalize input casing
|
||||
std::string key = password;
|
||||
strlwr(key.data());
|
||||
srb2::String key = password;
|
||||
strlwr((char*)key.data());
|
||||
|
||||
UINT8 key_hash[M_PW_HASH_SIZE];
|
||||
M_HashPassword(key_hash, key.c_str(), kRRSalt);
|
||||
|
|
@ -684,8 +685,8 @@ try_password_e M_TryPassword(const char *password, boolean conditions)
|
|||
boolean M_TryExactPassword(const char *password, const char *encodedhash)
|
||||
{
|
||||
// Normalize input casing
|
||||
std::string key = password;
|
||||
strlwr(key.data());
|
||||
srb2::String key = password;
|
||||
strlwr((char*)key.data());
|
||||
|
||||
UINT8 key_hash[M_PW_HASH_SIZE];
|
||||
M_HashPassword(key_hash, key.c_str(), kRRSalt);
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@
|
|||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <tcb/span.hpp>
|
||||
|
||||
#include "../core/string.h"
|
||||
#include "../core/vector.hpp"
|
||||
#include "../audio/sample.hpp"
|
||||
|
||||
namespace srb2::media
|
||||
|
|
@ -49,7 +49,7 @@ public:
|
|||
int frame_rate;
|
||||
};
|
||||
|
||||
std::string file_name;
|
||||
srb2::String file_name;
|
||||
|
||||
std::optional<std::size_t> max_size; // file size limit
|
||||
std::optional<std::chrono::duration<float>> max_duration;
|
||||
|
|
@ -63,7 +63,7 @@ public:
|
|||
{
|
||||
using instance_t = std::unique_ptr<StagingVideoFrame>;
|
||||
|
||||
std::vector<uint8_t> screen;
|
||||
srb2::Vector<uint8_t> screen;
|
||||
uint32_t width, height;
|
||||
int pts;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@
|
|||
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "../core/string.h"
|
||||
#include "../cxxutil.hpp"
|
||||
#include "avrecorder_impl.hpp"
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ void Impl::container_dtor_handler(const MediaContainer& container) const
|
|||
|
||||
if (max_size_ && container.size() > *max_size_)
|
||||
{
|
||||
const std::string line = fmt::format(
|
||||
const srb2::String line = srb2::format(
|
||||
"Video size has exceeded limit {} > {} ({}%)."
|
||||
" This should not happen, please report this bug.\n",
|
||||
container.size(),
|
||||
|
|
@ -100,7 +100,7 @@ void AVRecorder::draw_statistics() const
|
|||
{
|
||||
SRB2_ASSERT(impl_->video_encoder_ != nullptr);
|
||||
|
||||
auto draw = [](int x, std::string text, int32_t flags = 0)
|
||||
auto draw = [](int x, const srb2::String text, int32_t flags = 0)
|
||||
{
|
||||
V_DrawThinString(
|
||||
x,
|
||||
|
|
@ -144,7 +144,7 @@ void AVRecorder::draw_statistics() const
|
|||
return 0;
|
||||
}();
|
||||
|
||||
draw(200, fmt::format("{:.0f}", fps), fps_color);
|
||||
draw(230, fmt::format("{:.1f}s", impl_->container_->duration().count()));
|
||||
draw(260, fmt::format("{:.1f} MB", size / kMb), mb_color);
|
||||
draw(200, srb2::format("{:.0f}", fps), fps_color);
|
||||
draw(230, srb2::format("{:.1f}s", impl_->container_->duration().count()));
|
||||
draw(260, srb2::format("{:.1f} MB", size / kMb), mb_color);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@
|
|||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "../core/string.h"
|
||||
#include "../i_time.h"
|
||||
#include "avrecorder.hpp"
|
||||
#include "container.hpp"
|
||||
|
|
@ -57,7 +57,7 @@ public:
|
|||
using frame_type = StagingVideoFrame::instance_t;
|
||||
};
|
||||
|
||||
std::vector<typename Traits<T>::frame_type> vec_;
|
||||
srb2::Vector<typename Traits<T>::frame_type> vec_;
|
||||
|
||||
// This number only decrements once a frame has
|
||||
// actually been written to container.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
using namespace srb2::media;
|
||||
|
||||
CFile::CFile(const std::string file_name) : name_(file_name)
|
||||
CFile::CFile(const srb2::String& file_name) : name_(file_name)
|
||||
{
|
||||
file_ = std::fopen(name(), "wb");
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@
|
|||
#define __SRB2_MEDIA_CFILE_HPP__
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#include "../core/string.h"
|
||||
|
||||
namespace srb2::media
|
||||
{
|
||||
|
|
@ -20,7 +21,7 @@ namespace srb2::media
|
|||
class CFile
|
||||
{
|
||||
public:
|
||||
CFile(const std::string file_name);
|
||||
CFile(const srb2::String& file_name);
|
||||
~CFile();
|
||||
|
||||
operator std::FILE*() const { return file_; }
|
||||
|
|
@ -28,7 +29,7 @@ public:
|
|||
const char* name() const { return name_.c_str(); }
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
srb2::String name_;
|
||||
std::FILE* file_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "../core/string.h"
|
||||
#include "audio_encoder.hpp"
|
||||
#include "video_encoder.hpp"
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ public:
|
|||
|
||||
struct Config
|
||||
{
|
||||
std::string file_name;
|
||||
srb2::String file_name;
|
||||
dtor_cb_t destructor_callback;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@
|
|||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "../core/hash_map.hpp"
|
||||
#include "../core/string.h"
|
||||
#include "../core/vector.hpp"
|
||||
#include "../command.h"
|
||||
|
||||
namespace srb2::media
|
||||
|
|
@ -26,7 +26,7 @@ namespace srb2::media
|
|||
class Options
|
||||
{
|
||||
public:
|
||||
using map_t = std::unordered_map<std::string, consvar_t>;
|
||||
using map_t = srb2::HashMap<srb2::String, consvar_t>;
|
||||
|
||||
template <typename T>
|
||||
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 = {});
|
||||
|
||||
private:
|
||||
static std::vector<consvar_t*> cvars_;
|
||||
static srb2::Vector<consvar_t*> cvars_;
|
||||
|
||||
const char* prefix_;
|
||||
map_t map_;
|
||||
|
|
@ -54,6 +54,11 @@ private:
|
|||
const consvar_t& cvar(const char* option) const;
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
extern template consvar_t Options::values(const char* default_value, const Range<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
|
||||
|
||||
#endif // __SRB2_MEDIA_OPTIONS_HPP__
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <vpx/vpx_encoder.h>
|
||||
|
||||
#include "../core/vector.hpp"
|
||||
#include "options.hpp"
|
||||
#include "vorbis.hpp"
|
||||
#include "vp8.hpp"
|
||||
|
|
@ -23,7 +24,7 @@ using namespace srb2::media;
|
|||
// to be defined in the same translation unit as
|
||||
// Options::cvars_ to guarantee initialization order.
|
||||
|
||||
std::vector<consvar_t*> Options::cvars_;
|
||||
srb2::Vector<consvar_t*> Options::cvars_;
|
||||
|
||||
// clang-format off
|
||||
const Options VorbisEncoder::options_("vorbis", {
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@
|
|||
#ifndef __SRB2_MEDIA_VORBIS_ERROR_HPP__
|
||||
#define __SRB2_MEDIA_VORBIS_ERROR_HPP__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <vorbis/codec.h>
|
||||
|
||||
#include "../core/string.h"
|
||||
|
||||
class VorbisError
|
||||
{
|
||||
public:
|
||||
|
|
@ -23,7 +23,7 @@ public:
|
|||
|
||||
operator int() const { return error_; }
|
||||
|
||||
std::string name() const
|
||||
srb2::String name() const
|
||||
{
|
||||
switch (error_)
|
||||
{
|
||||
|
|
@ -43,12 +43,12 @@ private:
|
|||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<VorbisError> : formatter<std::string>
|
||||
struct fmt::formatter<VorbisError> : formatter<srb2::String>
|
||||
{
|
||||
template <typename FormatContext>
|
||||
auto format(const VorbisError& error, FormatContext& ctx) const
|
||||
{
|
||||
return formatter<std::string>::format(error.name(), ctx);
|
||||
return formatter<srb2::String>::format(error.name(), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,22 +11,22 @@
|
|||
#ifndef __SRB2_MEDIA_VPX_ERROR_HPP__
|
||||
#define __SRB2_MEDIA_VPX_ERROR_HPP__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <vpx/vpx_codec.h>
|
||||
|
||||
#include "../core/string.h"
|
||||
|
||||
class VpxError
|
||||
{
|
||||
public:
|
||||
VpxError(vpx_codec_ctx_t& ctx) : ctx_(&ctx) {}
|
||||
|
||||
std::string description() const
|
||||
srb2::String description() const
|
||||
{
|
||||
const char* error = vpx_codec_error(ctx_);
|
||||
const char* detail = vpx_codec_error_detail(ctx_);
|
||||
|
||||
return detail ? fmt::format("{}: {}", error, detail) : error;
|
||||
return detail ? srb2::format("{}: {}", error, detail) : error;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -34,12 +34,12 @@ private:
|
|||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<VpxError> : formatter<std::string>
|
||||
struct fmt::formatter<VpxError> : formatter<srb2::String>
|
||||
{
|
||||
template <typename FormatContext>
|
||||
auto format(const VpxError& error, FormatContext& ctx) const
|
||||
{
|
||||
return formatter<std::string>::format(error.description(), ctx);
|
||||
return formatter<srb2::String>::format(error.description(), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@
|
|||
|
||||
#include <cstddef>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <mkvmuxer/mkvmuxer.h>
|
||||
|
||||
#include "../core/hash_map.hpp"
|
||||
#include "container.hpp"
|
||||
#include "webm.hpp"
|
||||
#include "webm_writer.hpp"
|
||||
|
|
@ -88,7 +88,7 @@ private:
|
|||
|
||||
mutable std::recursive_mutex queue_mutex_;
|
||||
|
||||
std::unordered_map<webm::track, FrameQueue> queue_;
|
||||
srb2::HashMap<webm::track, FrameQueue> queue_;
|
||||
|
||||
webm::timestamp latest_timestamp_ = 0;
|
||||
std::size_t queue_size_ = 0;
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@
|
|||
#define __SRB2_MEDIA_WEBM_WRITER_HPP__
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#include <mkvmuxer/mkvwriter.h>
|
||||
|
||||
#include "../core/string.h"
|
||||
#include "cfile.hpp"
|
||||
|
||||
namespace srb2::media
|
||||
|
|
@ -24,7 +24,7 @@ namespace srb2::media
|
|||
class WebmWriter : public CFile, public mkvmuxer::MkvWriter
|
||||
{
|
||||
public:
|
||||
WebmWriter(const std::string file_name) : CFile(file_name), MkvWriter(static_cast<std::FILE*>(*this)) {}
|
||||
WebmWriter(const srb2::String& file_name) : CFile(file_name), MkvWriter(static_cast<std::FILE*>(*this)) {}
|
||||
~WebmWriter() { MkvWriter::Close(); }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
#define __SRB2_MEDIA_YUV420P_HPP__
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "../core/vector.hpp"
|
||||
#include "video_frame.hpp"
|
||||
|
||||
namespace srb2::media
|
||||
|
|
@ -40,7 +40,7 @@ public:
|
|||
int width_ = 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);
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@
|
|||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <fmt/chrono.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "../../core/string.h"
|
||||
#include "../../cxxutil.hpp"
|
||||
#include "../../v_draw.hpp"
|
||||
#include "EggTV.hpp"
|
||||
|
|
@ -85,11 +85,11 @@ void draw_face(const Draw& draw, const EggTVData::Replay::Standing& player, face
|
|||
}
|
||||
}
|
||||
|
||||
std::string player_time_string(const EggTVData::Replay::Standing& player)
|
||||
srb2::String player_time_string(const EggTVData::Replay::Standing& player)
|
||||
{
|
||||
if (player.time)
|
||||
{
|
||||
return fmt::format(
|
||||
return srb2::format(
|
||||
R"({}'{}"{})",
|
||||
G_TicsToMinutes(*player.time, true),
|
||||
G_TicsToSeconds(*player.time),
|
||||
|
|
@ -102,7 +102,7 @@ std::string player_time_string(const EggTVData::Replay::Standing& player)
|
|||
}
|
||||
}
|
||||
|
||||
std::string player_points_string(const EggTVData::Replay::Standing& player)
|
||||
srb2::String player_points_string(const EggTVData::Replay::Standing& player)
|
||||
{
|
||||
return player.score ? fmt::format("{} PTS", *player.score) : "NO CONTEST";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "EggTVData.hpp"
|
||||
#include "EggTVGraphics.hpp"
|
||||
|
||||
#include "../../core/vector.hpp"
|
||||
#include "../../doomdef.h" // TICRATE
|
||||
#include "../../i_time.h"
|
||||
#include "../../k_menu.h"
|
||||
|
|
@ -197,7 +198,7 @@ private:
|
|||
{
|
||||
public:
|
||||
using limiter_t = std::function<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) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,13 +14,14 @@
|
|||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#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 "EggTVData.hpp"
|
||||
|
||||
|
|
@ -34,15 +35,15 @@ using namespace srb2::menus::egg_tv;
|
|||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
using nlohmann::json;
|
||||
using srb2::JsonValue;
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<fs::filesystem_error> : formatter<std::string>
|
||||
struct fmt::formatter<fs::filesystem_error> : formatter<srb2::String>
|
||||
{
|
||||
template <typename FormatContext>
|
||||
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()),
|
||||
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()));
|
||||
}
|
||||
|
||||
json& ensure_array(json& object, const char* key)
|
||||
JsonValue& ensure_array(JsonValue& object, const char* key)
|
||||
{
|
||||
json& array = object[key];
|
||||
JsonValue& array = object[key];
|
||||
|
||||
if (!array.is_array())
|
||||
{
|
||||
array = json::array();
|
||||
array = JsonValue::array();
|
||||
}
|
||||
|
||||
return array;
|
||||
|
|
@ -91,18 +92,16 @@ EggTVData::EggTVData() : favorites_(ensure_array(favoritesFile_, "favorites"))
|
|||
}
|
||||
}
|
||||
|
||||
json EggTVData::cache_favorites() const
|
||||
JsonValue EggTVData::cache_favorites() const
|
||||
{
|
||||
json object;
|
||||
JsonValue object;
|
||||
|
||||
try
|
||||
{
|
||||
std::ifstream f(favoritesPath_);
|
||||
|
||||
if (f.is_open())
|
||||
{
|
||||
f >> object;
|
||||
}
|
||||
srb2::io::FileStream stream { favoritesPath_.generic_string() };
|
||||
srb2::Vector<std::byte> f = srb2::io::read_to_vec(stream);
|
||||
srb2::String json_string { (const char*)f.data(), f.size() };
|
||||
object = JsonValue::from_json_string(json_string);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
|
|
@ -199,9 +198,9 @@ EggTVData::Folder::Folder(EggTVData& tv, const fs::directory_entry& entry) :
|
|||
}
|
||||
}
|
||||
|
||||
EggTVData::Replay::Title::operator const std::string() const
|
||||
EggTVData::Replay::Title::operator const srb2::String() const
|
||||
{
|
||||
return second().empty() ? first() : fmt::format("{} - {}", first(), second());
|
||||
return second().empty() ? first() : srb2::format("{} - {}", first(), second());
|
||||
}
|
||||
|
||||
EggTVData::Replay::Replay(Folder::Cache::ReplayRef& ref) : ref_(&ref)
|
||||
|
|
@ -230,7 +229,7 @@ EggTVData::Replay::Replay(Folder::Cache::ReplayRef& ref) : ref_(&ref)
|
|||
const std::string_view str = info.title;
|
||||
const std::size_t mid = str.find(kDelimiter);
|
||||
|
||||
title_ = Title(str.substr(0, mid), mid == std::string::npos ? "" : str.substr(mid + kDelimiter.size()));
|
||||
title_ = Title(str.substr(0, mid), mid == srb2::String::npos ? "" : str.substr(mid + kDelimiter.size()));
|
||||
//title_ = Title("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW", "WWWWWWWWWWWWWWWWWWWWWWWWWWW");
|
||||
}
|
||||
|
||||
|
|
@ -316,13 +315,13 @@ void EggTVData::Replay::toggle_favorite() const
|
|||
{
|
||||
const auto& it = ref_->iterator_to_favorite();
|
||||
|
||||
if (it != ref_->favorites().end())
|
||||
if (it != ref_->favorites().as_array().end())
|
||||
{
|
||||
ref_->favorites().erase(it);
|
||||
ref_->favorites().as_array().erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
ref_->favorites().emplace_back(ref_->favorites_path());
|
||||
ref_->favorites().as_array().emplace_back(ref_->favorites_path());
|
||||
}
|
||||
|
||||
ref_->cache().folder().tv().save_favorites();
|
||||
|
|
@ -382,7 +381,9 @@ void EggTVData::save_favorites() const
|
|||
{
|
||||
try
|
||||
{
|
||||
std::ofstream(favoritesPath_) << favoritesFile_;
|
||||
srb2::String json_string = favoritesFile_.to_json_string();
|
||||
srb2::io::FileStream fs { favoritesPath_.generic_string(), srb2::io::FileStreamMode::kWrite };
|
||||
srb2::io::write_exact(fs, tcb::as_bytes(tcb::span(json_string.data(), json_string.size())));
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,14 +17,13 @@
|
|||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "../../core/string.h"
|
||||
#include "../../core/json.hpp"
|
||||
#include "../../cxxutil.hpp"
|
||||
|
||||
#include "../../d_main.h" // srb2home
|
||||
|
|
@ -40,10 +39,10 @@ private:
|
|||
const std::filesystem::path root_ = std::filesystem::path{srb2home} / "media/replay/online";
|
||||
const std::filesystem::path favoritesPath_ = root_ / "favorites.json";
|
||||
|
||||
nlohmann::json favoritesFile_ = cache_favorites();
|
||||
nlohmann::json& favorites_;
|
||||
JsonValue favoritesFile_ = cache_favorites();
|
||||
JsonValue& favorites_;
|
||||
|
||||
nlohmann::json cache_favorites() const;
|
||||
JsonValue cache_favorites() const;
|
||||
|
||||
void cache_folders();
|
||||
void save_favorites() const;
|
||||
|
|
@ -91,20 +90,21 @@ public:
|
|||
released_ = true;
|
||||
}
|
||||
|
||||
bool favorited() const { return iterator_to_favorite() != favorites().end(); }
|
||||
nlohmann::json& favorites() const { return cache().folder().tv().favorites_; }
|
||||
bool favorited() const { return iterator_to_favorite() != favorites().as_array().end(); }
|
||||
JsonValue& favorites() const { return cache().folder().tv().favorites_; }
|
||||
|
||||
std::string favorites_path() const
|
||||
srb2::String favorites_path() const
|
||||
{
|
||||
// path::generic_string converts to forward
|
||||
// slashes on Windows. This should suffice to make
|
||||
// the JSON file portable across installations.
|
||||
return (std::filesystem::path{cache().folder().name()} / filename()).generic_string();
|
||||
return (std::filesystem::path{std::string_view(cache().folder().name())} / filename()).generic_string();
|
||||
}
|
||||
|
||||
nlohmann::json::const_iterator iterator_to_favorite() const
|
||||
JsonArray::const_iterator iterator_to_favorite() const
|
||||
{
|
||||
return std::find(favorites().begin(), favorites().end(), favorites_path());
|
||||
srb2::String path = favorites_path();
|
||||
return std::find(favorites().as_array().begin(), favorites().as_array().end(), static_cast<std::string_view>(path));
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -134,13 +134,13 @@ public:
|
|||
int y = 0;
|
||||
|
||||
bool empty() { return size() == 0; }
|
||||
std::filesystem::path path() const { return tv_->root_ / name_; }
|
||||
std::filesystem::path path() const { return tv_->root_ / std::string_view(name_); }
|
||||
|
||||
EggTVData& tv() const { return *tv_; }
|
||||
|
||||
std::size_t size() const { return size_; }
|
||||
const time_point_t& time() const { return time_; }
|
||||
const std::string& name() const { return name_; }
|
||||
const srb2::String& name() const { return name_; }
|
||||
|
||||
std::unique_ptr<Cache> load() { return std::make_unique<Cache>(*this); };
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ public:
|
|||
std::size_t size_;
|
||||
time_point_t time_;
|
||||
EggTVData* tv_;
|
||||
std::string name_;
|
||||
srb2::String name_;
|
||||
};
|
||||
|
||||
class Replay
|
||||
|
|
@ -165,18 +165,18 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
const std::string& first() const { return first_; }
|
||||
const std::string& second() const { return second_; }
|
||||
const srb2::String& first() const { return first_; }
|
||||
const srb2::String& second() const { return second_; }
|
||||
|
||||
operator const std::string() const;
|
||||
operator const srb2::String() const;
|
||||
|
||||
private:
|
||||
std::string first_, second_;
|
||||
srb2::String first_, second_;
|
||||
};
|
||||
|
||||
struct Standing
|
||||
{
|
||||
std::string name;
|
||||
srb2::String name;
|
||||
std::optional<std::size_t> skin;
|
||||
std::size_t color;
|
||||
std::optional<tic_t> time;
|
||||
|
|
@ -247,7 +247,7 @@ public:
|
|||
void toggle_favorite() const;
|
||||
|
||||
bool invalid() const { return invalid_; }
|
||||
bool favorited() const { return ref_->iterator_to_favorite() != ref_->favorites().end(); }
|
||||
bool favorited() const { return ref_->iterator_to_favorite() != ref_->favorites().as_array().end(); }
|
||||
|
||||
std::filesystem::path path() const { return ref_->cache().folder().path() / ref_->filename(); }
|
||||
const time_point_t& date() const { return ref_->time(); }
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
|
||||
#include <array>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "../../core/hash_map.hpp"
|
||||
#include "../../doomdef.h" // skincolornum_t
|
||||
#include "../../v_draw.hpp"
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ public:
|
|||
|
||||
patch select = "RHTVSQSL";
|
||||
|
||||
std::unordered_map<std::string_view, patch> gametype = {
|
||||
srb2::HashMap<std::string_view, patch> gametype = {
|
||||
{"Race", "RHGT1"},
|
||||
{"Battle", "RHGT2"},
|
||||
{"Prison Break", "RHGT3"},
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
/// \file menus/extras-challenges.c
|
||||
/// \brief Statistics menu
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "../k_menu.h"
|
||||
#include "../z_zone.h"
|
||||
#include "../m_cond.h" // Condition Sets
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include <forward_list>
|
||||
|
||||
#include "../core/string.h"
|
||||
|
||||
static void M_GonerDrawer(void);
|
||||
static void M_GonerConclude(INT32 choice);
|
||||
static boolean M_GonerInputs(INT32 ch);
|
||||
|
|
@ -95,7 +97,7 @@ class GonerSpeaker
|
|||
public:
|
||||
float offset = 0;
|
||||
|
||||
GonerSpeaker(std::string skinName, float offset)
|
||||
GonerSpeaker(const srb2::String& skinName, float offset)
|
||||
{
|
||||
if (!skinName.empty())
|
||||
{
|
||||
|
|
@ -144,11 +146,11 @@ class GonerChatLine
|
|||
{
|
||||
public:
|
||||
gonerspeakers_t speaker;
|
||||
std::string dialogue;
|
||||
srb2::String dialogue;
|
||||
int value; // Mutlipurpose.
|
||||
void (*routine)(void);
|
||||
|
||||
GonerChatLine(gonerspeakers_t speaker, int delay, std::string dialogue)
|
||||
GonerChatLine(gonerspeakers_t speaker, int delay, const srb2::String& dialogue)
|
||||
{
|
||||
char *newText = V_ScaledWordWrap(
|
||||
(BASEVIDWIDTH/2 + 6) << FRACBITS,
|
||||
|
|
@ -158,7 +160,7 @@ public:
|
|||
);
|
||||
|
||||
this->speaker = speaker;
|
||||
this->dialogue = std::string(newText);
|
||||
this->dialogue = srb2::String(newText);
|
||||
this->value = delay;
|
||||
|
||||
this->routine = nullptr;
|
||||
|
|
@ -1142,7 +1144,7 @@ static void M_GonerDrawer(void)
|
|||
|
||||
for (auto & element : LinesOutput)
|
||||
{
|
||||
std::string text;
|
||||
srb2::String text;
|
||||
INT32 flags;
|
||||
|
||||
if (newy < 0) break;
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ void Music_Init(void)
|
|||
{
|
||||
Tune& tune = g_tunes.insert("credits");
|
||||
|
||||
tune.priority = 100;
|
||||
tune.priority = 101;
|
||||
tune.song = "_creds";
|
||||
tune.credit = true;
|
||||
}
|
||||
|
|
@ -182,7 +182,7 @@ void Music_Init(void)
|
|||
{
|
||||
Tune& tune = g_tunes.insert("shore");
|
||||
|
||||
tune.priority = 100;
|
||||
tune.priority = 101;
|
||||
tune.loop = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@
|
|||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "music_manager.hpp"
|
||||
#include "music_tune.hpp"
|
||||
|
||||
#include "core/string.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "doomtype.h"
|
||||
#include "i_sound.h"
|
||||
|
|
@ -49,8 +49,8 @@ void TuneManager::tick()
|
|||
|
||||
Tune* tune = current_tune();
|
||||
|
||||
std::string old_song = current_song_;
|
||||
current_song_ = tune && tune->playing() && !tune->suspend ? tune->song : std::string{};
|
||||
srb2::String old_song = current_song_;
|
||||
current_song_ = tune && tune->playing() && !tune->suspend ? tune->song : srb2::String{};
|
||||
|
||||
bool changed = current_song_ != old_song;
|
||||
|
||||
|
|
@ -167,7 +167,8 @@ void TuneManager::pause_unpause() const
|
|||
|
||||
bool TuneManager::load() const
|
||||
{
|
||||
lumpnum_t lumpnum = W_CheckNumForLongName(fmt::format("O_{}", current_song_).c_str());
|
||||
srb2::String lumpstring = srb2::format("O_{}", current_song_);
|
||||
lumpnum_t lumpnum = W_CheckNumForLongName(lumpstring.c_str());
|
||||
|
||||
if (lumpnum == LUMPERROR)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,11 +11,10 @@
|
|||
#ifndef MUSIC_MANAGER_HPP
|
||||
#define MUSIC_MANAGER_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "core/hash_map.hpp"
|
||||
#include "core/string.h"
|
||||
#include "cxxutil.hpp"
|
||||
#include "music_tune.hpp"
|
||||
|
||||
|
|
@ -25,7 +24,7 @@ namespace srb2::music
|
|||
class TuneManager
|
||||
{
|
||||
public:
|
||||
const std::string& current_song() const { return current_song_; }
|
||||
const srb2::String& current_song() const { return current_song_; }
|
||||
|
||||
Tune* current_tune() const
|
||||
{
|
||||
|
|
@ -99,8 +98,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, Tune> map_;
|
||||
std::string current_song_;
|
||||
srb2::HashMap<srb2::String, Tune> map_;
|
||||
srb2::String current_song_;
|
||||
|
||||
tic_t time_sync_;
|
||||
tic_t time_local_;
|
||||
|
|
@ -113,11 +112,20 @@ private:
|
|||
|
||||
decltype(map_)::const_iterator current_iterator() const
|
||||
{
|
||||
return std::max_element(
|
||||
map_.begin(),
|
||||
map_.end(),
|
||||
[](const auto& a, const auto& b) { return a.second < b.second; }
|
||||
);
|
||||
// Not using std::max_element due to buggy clang libc++ LegacyInputIterator assertion
|
||||
auto first = map_.begin();
|
||||
auto last = map_.end();
|
||||
if (first == last) return first;
|
||||
|
||||
auto max = first;
|
||||
while (++first != last)
|
||||
{
|
||||
if (max->second < first->second)
|
||||
{
|
||||
max = first;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
bool load() const;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "core/string.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomtype.h"
|
||||
#include "k_boss.h"
|
||||
|
|
@ -29,7 +29,7 @@ class Tune
|
|||
public:
|
||||
explicit Tune() {}
|
||||
|
||||
std::string song; // looks up the lump
|
||||
srb2::String song; // looks up the lump
|
||||
|
||||
// Higher priority tunes play first.
|
||||
int priority = 0;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
/// \file ballhog.cpp
|
||||
/// \brief Ballhog item code.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "../doomdef.h"
|
||||
#include "../doomstat.h"
|
||||
#include "../info.h"
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "../mobj_list.hpp"
|
||||
|
||||
#include "../core/hash_map.hpp"
|
||||
#include "../core/vector.hpp"
|
||||
#include "../doomdef.h"
|
||||
#include "../doomtype.h"
|
||||
#include "../info.h"
|
||||
|
|
@ -506,7 +506,7 @@ struct CheckpointManager
|
|||
|
||||
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());
|
||||
return it != lines_.end() ? &it->second : nullptr;
|
||||
|
|
@ -514,11 +514,11 @@ struct CheckpointManager
|
|||
|
||||
private:
|
||||
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;
|
||||
TAG_ITER_LINES(tag, li)
|
||||
{
|
||||
|
|
@ -573,7 +573,7 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe
|
|||
}
|
||||
|
||||
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())
|
||||
{
|
||||
|
|
@ -584,7 +584,7 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe
|
|||
}
|
||||
else
|
||||
{
|
||||
auto it = find_if(
|
||||
auto it = std::find_if(
|
||||
lines->begin(),
|
||||
lines->end(),
|
||||
[&](const line_t* line)
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@
|
|||
/// \brief Do all the WAD I/O, get map description, set up initial state and misc. LUTs
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
|
|
@ -96,6 +94,8 @@
|
|||
#include "taglist.h"
|
||||
|
||||
// SRB2Kart
|
||||
#include "core/string.h"
|
||||
#include "core/vector.hpp"
|
||||
#include "k_kart.h"
|
||||
#include "k_race.h"
|
||||
#include "k_battle.h" // K_BattleInit
|
||||
|
|
@ -7854,7 +7854,7 @@ static void P_LoadRecordGhosts(void)
|
|||
map(cv_ghost_last, value, kLast);
|
||||
};
|
||||
|
||||
auto add_ghosts = [gpath](const std::string& base, UINT8 bits)
|
||||
auto add_ghosts = [gpath](const srb2::String& base, UINT8 bits)
|
||||
{
|
||||
auto load = [base](const char* suffix) { P_TryAddExternalGhost(fmt::format("{}-{}.lmp", base, suffix).c_str()); };
|
||||
|
||||
|
|
@ -7991,7 +7991,7 @@ static void P_ShuffleTeams(void)
|
|||
|
||||
CONS_Debug(DBG_TEAMS, "Shuffling player teams...\n");
|
||||
|
||||
std::vector<UINT8> player_shuffle;
|
||||
srb2::Vector<UINT8> player_shuffle;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] == false || players[i].spectator == true)
|
||||
|
|
@ -9135,7 +9135,7 @@ static tic_t round_to_next_second(tic_t time)
|
|||
static void P_DeriveAutoMedalTimes(mapheader_t& map)
|
||||
{
|
||||
// Gather staff ghost times
|
||||
std::vector<tic_t> stafftimes;
|
||||
srb2::Vector<tic_t> stafftimes;
|
||||
for (int i = 0; i < map.ghostCount; i++)
|
||||
{
|
||||
tic_t time = map.ghostBrief[i]->time;
|
||||
|
|
@ -9325,7 +9325,7 @@ UINT8 P_InitMapData(void)
|
|||
{
|
||||
continue;
|
||||
}
|
||||
std::string ghostdirname = fmt::format("staffghosts/{}/", mapheaderinfo[i]->lumpname);
|
||||
srb2::String ghostdirname = srb2::format("staffghosts/{}/", mapheaderinfo[i]->lumpname);
|
||||
|
||||
UINT16 lumpstart = W_CheckNumForFolderStartPK3(ghostdirname.c_str(), wadindex, 0);
|
||||
if (lumpstart == INT16_MAX)
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "r_debug.hpp"
|
||||
#include "v_draw.hpp"
|
||||
|
||||
#include "core/hash_map.hpp"
|
||||
#include "core/hash_set.hpp"
|
||||
#include "doomdef.h"
|
||||
#include "doomtype.h"
|
||||
#include "r_textures.h"
|
||||
|
|
@ -25,7 +25,7 @@ using srb2::Draw;
|
|||
namespace
|
||||
{
|
||||
|
||||
std::unordered_set<INT32> frame_list;
|
||||
srb2::HashSet<INT32> frame_list;
|
||||
|
||||
}; // namespace
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
/// while maintaining a per column clipping list only.
|
||||
/// Moreover, the sky areas have to be determined.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <tracy/tracy/Tracy.hpp>
|
||||
|
||||
#include "command.h"
|
||||
|
|
|
|||
|
|
@ -13,14 +13,14 @@
|
|||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "core/hash_map.hpp"
|
||||
#include "core/string.h"
|
||||
#include "core/vector.hpp"
|
||||
#include "cxxutil.hpp"
|
||||
#include "doomstat.h"
|
||||
#include "r_textures.h"
|
||||
|
|
@ -29,14 +29,14 @@
|
|||
namespace
|
||||
{
|
||||
|
||||
std::unordered_map<std::string, std::vector<const texture_t*>> g_dups;
|
||||
std::map<std::string, std::vector<std::string>> g_warnings;
|
||||
srb2::HashMap<srb2::String, srb2::Vector<const texture_t*>> g_dups;
|
||||
std::map<srb2::String, srb2::Vector<srb2::String>> g_warnings;
|
||||
std::thread g_dups_thread;
|
||||
|
||||
std::string key8char(const char cstr[8])
|
||||
srb2::String key8char(const char cstr[8])
|
||||
{
|
||||
std::string_view view(cstr, 8);
|
||||
std::string key;
|
||||
srb2::String key;
|
||||
|
||||
view = view.substr(0, view.find('\0')); // terminate by '\0'
|
||||
key.reserve(view.size());
|
||||
|
|
@ -50,7 +50,7 @@ std::string key8char(const char cstr[8])
|
|||
return key;
|
||||
}
|
||||
|
||||
std::string texture_location(const texture_t& tex)
|
||||
srb2::String texture_location(const texture_t& tex)
|
||||
{
|
||||
if (tex.type == TEXTURETYPE_SINGLEPATCH)
|
||||
{
|
||||
|
|
@ -59,7 +59,7 @@ std::string texture_location(const texture_t& tex)
|
|||
const texpatch_t& texpat = tex.patches[0];
|
||||
const wadfile_t& wad = *wadfiles[texpat.wad];
|
||||
|
||||
return fmt::format(
|
||||
return srb2::format(
|
||||
"'{}/{}'",
|
||||
std::filesystem::path(wad.filename).filename().string(),
|
||||
wad.lumpinfo[texpat.lump].fullname
|
||||
|
|
@ -108,7 +108,7 @@ void R_CheckTextureDuplicates(INT32 start, INT32 end)
|
|||
auto collate_dups = [end, find_dup](int32_t start)
|
||||
{
|
||||
const texture_t* t1 = textures[start];
|
||||
const std::string key = key8char(t1->name);
|
||||
const srb2::String key = key8char(t1->name);
|
||||
|
||||
if (g_dups.find(key) != g_dups.end())
|
||||
{
|
||||
|
|
@ -119,7 +119,7 @@ void R_CheckTextureDuplicates(INT32 start, INT32 end)
|
|||
|
||||
if (idx < end)
|
||||
{
|
||||
std::vector<const texture_t*>& v = g_dups[key];
|
||||
srb2::Vector<const texture_t*>& v = g_dups[key];
|
||||
|
||||
v.push_back(textures[start]);
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ void R_PrintTextureWarnings(void)
|
|||
{
|
||||
CONS_Alert(CONS_WARNING, "\n%s", header.c_str());
|
||||
|
||||
for (const std::string& warning : v)
|
||||
for (const srb2::String& warning : v)
|
||||
{
|
||||
CONS_Printf("%s\n", warning.c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@
|
|||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <glad/gl.h>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include "../../core/vector.hpp"
|
||||
#include "../shader_load_context.hpp"
|
||||
|
||||
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.
|
||||
|
||||
// Process shader sources
|
||||
std::vector<const char*> vert_sources;
|
||||
std::vector<const char*> frag_sources;
|
||||
srb2::Vector<const char*> vert_sources;
|
||||
srb2::Vector<const char*> frag_sources;
|
||||
ShaderLoadContext vert_ctx;
|
||||
ShaderLoadContext frag_ctx;
|
||||
vert_ctx.set_version("120");
|
||||
|
|
@ -873,11 +873,11 @@ rhi::Handle<rhi::Program> Gl2Rhi::create_program(const ProgramDesc& desc)
|
|||
{
|
||||
GLint max_length = 0;
|
||||
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_->DeleteShader(program.vertex_shader);
|
||||
throw std::runtime_error(fmt::format("Vertex shader compilation failed: {}", std::string(compile_error.data())));
|
||||
throw std::runtime_error(fmt::format("Vertex shader compilation failed: {}", String(compile_error.data())));
|
||||
}
|
||||
|
||||
program.fragment_shader = gl_->CreateShader(GL_FRAGMENT_SHADER);
|
||||
|
|
@ -889,11 +889,11 @@ rhi::Handle<rhi::Program> Gl2Rhi::create_program(const ProgramDesc& desc)
|
|||
{
|
||||
GLint max_length = 0;
|
||||
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_->DeleteShader(program.fragment_shader);
|
||||
throw std::runtime_error(fmt::format("Fragment shader compilation failed: {}", std::string(compile_error.data())));
|
||||
throw std::runtime_error(fmt::format("Fragment shader compilation failed: {}", String(compile_error.data())));
|
||||
}
|
||||
|
||||
program.program = gl_->CreateProgram();
|
||||
|
|
@ -907,13 +907,13 @@ rhi::Handle<rhi::Program> Gl2Rhi::create_program(const ProgramDesc& desc)
|
|||
{
|
||||
GLint max_length = 0;
|
||||
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_->DeleteProgram(program.program);
|
||||
gl_->DeleteShader(program.fragment_shader);
|
||||
gl_->DeleteShader(program.vertex_shader);
|
||||
throw std::runtime_error(fmt::format("Pipeline program link failed: {}", std::string(link_error.data())));
|
||||
throw std::runtime_error(fmt::format("Pipeline program link failed: {}", String(link_error.data())));
|
||||
}
|
||||
|
||||
// get attribute information
|
||||
|
|
@ -936,7 +936,7 @@ rhi::Handle<rhi::Program> Gl2Rhi::create_program(const ProgramDesc& desc)
|
|||
GL_ASSERT;
|
||||
GLint location = gl_->GetAttribLocation(program.program, name);
|
||||
GL_ASSERT;
|
||||
program.attrib_locations[std::string(name)] = location;
|
||||
program.attrib_locations[String(name)] = location;
|
||||
}
|
||||
|
||||
// get uniform information
|
||||
|
|
@ -959,7 +959,7 @@ rhi::Handle<rhi::Program> Gl2Rhi::create_program(const ProgramDesc& desc)
|
|||
GL_ASSERT;
|
||||
GLint location = gl_->GetUniformLocation(program.program, name);
|
||||
GL_ASSERT;
|
||||
program.uniform_locations[std::string(name)] = location;
|
||||
program.uniform_locations[String(name)] = location;
|
||||
}
|
||||
|
||||
Handle<Program> program_handle = program_slab_.insert(std::move(program));
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@
|
|||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "../../core/hash_map.hpp"
|
||||
#include "../../core/string.h"
|
||||
#include "../../core/vector.hpp"
|
||||
#include "../rhi.hpp"
|
||||
|
||||
namespace srb2::rhi
|
||||
|
|
@ -71,7 +71,7 @@ struct Gl2Platform
|
|||
virtual ~Gl2Platform();
|
||||
|
||||
virtual void present() = 0;
|
||||
virtual std::tuple<std::vector<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;
|
||||
};
|
||||
|
||||
|
|
@ -98,8 +98,8 @@ struct Gl2Program : public rhi::Program
|
|||
uint32_t vertex_shader = 0;
|
||||
uint32_t fragment_shader = 0;
|
||||
uint32_t program = 0;
|
||||
std::unordered_map<std::string, uint32_t> attrib_locations;
|
||||
std::unordered_map<std::string, uint32_t> uniform_locations;
|
||||
srb2::HashMap<srb2::String, uint32_t> attrib_locations;
|
||||
srb2::HashMap<srb2::String, uint32_t> uniform_locations;
|
||||
};
|
||||
|
||||
struct Gl2ActiveUniform
|
||||
|
|
@ -121,14 +121,14 @@ class Gl2Rhi final : public Rhi
|
|||
|
||||
Handle<Buffer> current_index_buffer_;
|
||||
|
||||
std::unordered_map<Gl2FramebufferKey, uint32_t> framebuffers_ {16};
|
||||
srb2::HashMap<Gl2FramebufferKey, uint32_t> framebuffers_ {16};
|
||||
|
||||
struct DefaultRenderPassState
|
||||
{
|
||||
bool clear = false;
|
||||
};
|
||||
using RenderPassState = std::variant<DefaultRenderPassState, RenderPassBeginInfo>;
|
||||
std::vector<RenderPassState> render_pass_stack_;
|
||||
srb2::Vector<RenderPassState> render_pass_stack_;
|
||||
std::optional<Handle<Program>> current_program_;
|
||||
PrimitiveType current_primitive_type_ = PrimitiveType::kPoints;
|
||||
uint32_t index_buffer_offset_ = 0;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@
|
|||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "../core/string.h"
|
||||
#include "../core/vector.hpp"
|
||||
|
||||
using namespace srb2;
|
||||
using namespace rhi;
|
||||
|
||||
|
|
@ -19,27 +22,27 @@ ShaderLoadContext::ShaderLoadContext() = default;
|
|||
|
||||
void ShaderLoadContext::set_version(std::string_view version)
|
||||
{
|
||||
version_ = fmt::format("#version {}\n", version);
|
||||
version_ = srb2::format("#version {}\n", version);
|
||||
}
|
||||
|
||||
void ShaderLoadContext::add_source(const std::string& source)
|
||||
void ShaderLoadContext::add_source(const srb2::String& source)
|
||||
{
|
||||
sources_.push_back(source);
|
||||
}
|
||||
|
||||
void ShaderLoadContext::add_source(std::string&& source)
|
||||
void ShaderLoadContext::add_source(srb2::String&& source)
|
||||
{
|
||||
sources_.push_back(std::move(source));
|
||||
}
|
||||
|
||||
void ShaderLoadContext::define(std::string_view name)
|
||||
{
|
||||
defines_.append(fmt::format("#define {}\n", name));
|
||||
defines_.append(srb2::format("#define {}\n", name));
|
||||
}
|
||||
|
||||
std::vector<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(defines_.c_str());
|
||||
|
|
|
|||
|
|
@ -11,29 +11,30 @@
|
|||
#ifndef __SRB2_RHI_SHADER_LOAD_CONTEXT_HPP__
|
||||
#define __SRB2_RHI_SHADER_LOAD_CONTEXT_HPP__
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "../core/string.h"
|
||||
#include "../core/vector.hpp"
|
||||
|
||||
namespace srb2::rhi
|
||||
{
|
||||
|
||||
class ShaderLoadContext
|
||||
{
|
||||
std::string version_;
|
||||
std::string defines_;
|
||||
std::vector<std::string> sources_;
|
||||
srb2::String version_;
|
||||
srb2::String defines_;
|
||||
srb2::Vector<srb2::String> sources_;
|
||||
|
||||
public:
|
||||
ShaderLoadContext();
|
||||
|
||||
void set_version(std::string_view version);
|
||||
void add_source(const std::string& source);
|
||||
void add_source(std::string&& source);
|
||||
void add_source(const srb2::String& source);
|
||||
void add_source(srb2::String&& source);
|
||||
|
||||
void define(std::string_view name);
|
||||
|
||||
std::vector<const char*> get_sources_array();
|
||||
srb2::Vector<const char*> get_sources_array();
|
||||
};
|
||||
|
||||
}; // namespace srb2::rhi
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@
|
|||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "core/string.h"
|
||||
#include "doomtype.h"
|
||||
#include "sanitize.h"
|
||||
#include "v_draw.hpp"
|
||||
|
|
@ -34,7 +34,7 @@ bool color_filter(char c)
|
|||
}
|
||||
|
||||
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(
|
||||
range.begin(),
|
||||
|
|
@ -62,9 +62,9 @@ int hexconv(int c)
|
|||
namespace srb2::sanitize
|
||||
{
|
||||
|
||||
std::string sanitize(std::string_view in, SanitizeMode mode)
|
||||
srb2::String sanitize(std::string_view in, SanitizeMode mode)
|
||||
{
|
||||
std::string out;
|
||||
srb2::String out;
|
||||
return filter_out(out, in, [mode]
|
||||
{
|
||||
switch (mode)
|
||||
|
|
@ -78,9 +78,9 @@ std::string sanitize(std::string_view in, SanitizeMode mode)
|
|||
}());
|
||||
}
|
||||
|
||||
std::string parse_carets(std::string_view in, ParseMode mode)
|
||||
srb2::String parse_carets(std::string_view in, ParseMode mode)
|
||||
{
|
||||
std::string out;
|
||||
srb2::String out;
|
||||
|
||||
using std::size_t;
|
||||
for (;;)
|
||||
|
|
|
|||
|
|
@ -14,9 +14,10 @@
|
|||
#include "doomtype.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "core/string.h"
|
||||
|
||||
namespace srb2::sanitize
|
||||
{
|
||||
|
||||
|
|
@ -33,10 +34,10 @@ enum class ParseMode
|
|||
};
|
||||
|
||||
// sanitizes string of all 0x80 codes
|
||||
std::string sanitize(std::string_view in, SanitizeMode mode);
|
||||
srb2::String sanitize(std::string_view in, SanitizeMode mode);
|
||||
|
||||
// sanitizes string of all 0x80 codes then parses caret codes
|
||||
std::string parse_carets(std::string_view in, ParseMode mode);
|
||||
srb2::String parse_carets(std::string_view in, ParseMode mode);
|
||||
|
||||
}; // namespace srb2
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@
|
|||
#include "../d_main.h"
|
||||
#include "../m_misc.h"/* path shit */
|
||||
#include "../i_system.h"
|
||||
#include "../core/string.h"
|
||||
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <tracy/tracy/Tracy.hpp>
|
||||
|
||||
|
|
@ -227,14 +227,14 @@ ChDirToExe (void)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void walk_exception_stack(std::string& accum, bool nested) {
|
||||
static void walk_exception_stack(srb2::String& accum, bool nested) {
|
||||
if (nested)
|
||||
accum.append("\n Caused by: Unknown exception");
|
||||
else
|
||||
accum.append("Uncaught exception: Unknown exception");
|
||||
}
|
||||
|
||||
static void walk_exception_stack(std::string& accum, const std::exception& ex, bool nested) {
|
||||
static void walk_exception_stack(srb2::String& accum, const std::exception& ex, bool nested) {
|
||||
if (nested)
|
||||
accum.append("\n Caused by: ");
|
||||
else
|
||||
|
|
@ -331,11 +331,11 @@ int main(int argc, char **argv)
|
|||
D_SRB2Loop();
|
||||
|
||||
} catch (const std::exception& ex) {
|
||||
std::string exception;
|
||||
srb2::String exception;
|
||||
walk_exception_stack(exception, ex, false);
|
||||
I_Error("%s", exception.c_str());
|
||||
} catch (...) {
|
||||
std::string exception;
|
||||
srb2::String exception;
|
||||
walk_exception_stack(exception, false);
|
||||
I_Error("%s", exception.c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,11 +11,13 @@
|
|||
#include "rhi_gl2_platform.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <SDL.h>
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "../core/string.h"
|
||||
#include "../core/vector.hpp"
|
||||
#include "../cxxutil.hpp"
|
||||
#include "../doomstat.h" // mainwads
|
||||
#include "../w_wad.h"
|
||||
|
|
@ -34,22 +36,22 @@ void SdlGl2Platform::present()
|
|||
SDL_GL_SwapWindow(window);
|
||||
}
|
||||
|
||||
static std::array<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);
|
||||
std::string fragment_list_name = fmt::format("rhi_glsllist_{}_fragment.txt", name);
|
||||
srb2::String vertex_list_name = fmt::format("rhi_glsllist_{}_vertex.txt", name);
|
||||
srb2::String fragment_list_name = fmt::format("rhi_glsllist_{}_fragment.txt", name);
|
||||
|
||||
return {std::move(vertex_list_name), std::move(fragment_list_name)};
|
||||
}
|
||||
|
||||
static std::vector<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;
|
||||
if (!W_ReadShader(lumpname, &buffer_size, nullptr))
|
||||
{
|
||||
throw std::runtime_error(fmt::format("Unable to find glsllist lump {}", lumpname));
|
||||
}
|
||||
std::string glsllist_lump_data;
|
||||
srb2::String glsllist_lump_data;
|
||||
glsllist_lump_data.resize(buffer_size);
|
||||
if (!W_ReadShader(lumpname, &buffer_size, glsllist_lump_data.data()))
|
||||
{
|
||||
|
|
@ -57,7 +59,7 @@ static std::vector<std::string> get_sources_from_glsllist_lump(const char* lumpn
|
|||
}
|
||||
|
||||
std::istringstream glsllist(glsllist_lump_data);
|
||||
std::vector<std::string> sources;
|
||||
srb2::Vector<srb2::String> sources;
|
||||
for (std::string line; std::getline(glsllist, line); )
|
||||
{
|
||||
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));
|
||||
}
|
||||
std::string source_lump;
|
||||
srb2::String source_lump;
|
||||
source_lump.resize(source_lump_size);
|
||||
if (!W_ReadShader(line.c_str(), &source_lump_size, source_lump.data()))
|
||||
{
|
||||
|
|
@ -100,13 +102,13 @@ static std::vector<std::string> get_sources_from_glsllist_lump(const char* lumpn
|
|||
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)
|
||||
{
|
||||
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());
|
||||
std::vector<std::string> fragment_sources = get_sources_from_glsllist_lump(glsllist_names[1].c_str());
|
||||
srb2::Vector<srb2::String> vertex_sources = get_sources_from_glsllist_lump(glsllist_names[0].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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@
|
|||
#ifndef __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/rhi.hpp"
|
||||
|
||||
|
|
@ -26,7 +30,7 @@ struct SdlGl2Platform final : public Gl2Platform
|
|||
virtual ~SdlGl2Platform();
|
||||
|
||||
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;
|
||||
virtual Rect get_default_framebuffer_dimensions() override;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@
|
|||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "core/hash_map.hpp"
|
||||
#include "doomdef.h" // skincolornum_t
|
||||
#include "doomtype.h"
|
||||
#include "hu_stuff.h"
|
||||
|
|
@ -34,7 +33,7 @@ int Draw::TextElement::width() const
|
|||
|
||||
Draw::TextElement& Draw::TextElement::parse(std::string_view raw)
|
||||
{
|
||||
static const std::unordered_map<std::string_view, char> translation = {
|
||||
static const srb2::HashMap<std::string_view, char> translation = {
|
||||
#define BUTTON(str, lower_bits) \
|
||||
{str, 0xB0 | lower_bits},\
|
||||
{str "_animated", 0xA0 | lower_bits},\
|
||||
|
|
@ -88,7 +87,7 @@ Draw::TextElement& Draw::TextElement::parse(std::string_view raw)
|
|||
};
|
||||
|
||||
// When we encounter a Saturn button, what gamecontrol does it represent?
|
||||
static const std::unordered_map<char, gamecontrols_e> inputdefinition = {
|
||||
static const srb2::HashMap<char, gamecontrols_e> inputdefinition = {
|
||||
{sb_up, gc_up},
|
||||
{sb_down, gc_down},
|
||||
{sb_right, gc_right},
|
||||
|
|
@ -114,7 +113,7 @@ Draw::TextElement& Draw::TextElement::parse(std::string_view raw)
|
|||
// What physical binds should appear as Saturn icons anyway?
|
||||
// (We don't have generic binds for stick/dpad directions, so
|
||||
// using the existing arrow graphics is the best thing here.)
|
||||
static const std::unordered_map<INT32, char> prettyinputs = {
|
||||
static const srb2::HashMap<INT32, char> prettyinputs = {
|
||||
{KEY_UPARROW, sb_up},
|
||||
{KEY_DOWNARROW, sb_down},
|
||||
{KEY_LEFTARROW, sb_left},
|
||||
|
|
@ -198,7 +197,7 @@ Draw::TextElement& Draw::TextElement::parse(std::string_view raw)
|
|||
|
||||
// EXTRA: descriptiveinput values above 1 translate binds back to Saturn buttons,
|
||||
// with various modes for various fucked up 6bt pads
|
||||
std::unordered_map<INT32, char> padconfig = {};
|
||||
srb2::HashMap<INT32, char> padconfig = {};
|
||||
switch (cv_descriptiveinput[localplayer].value)
|
||||
{
|
||||
case 1:
|
||||
|
|
@ -349,6 +348,11 @@ void Chain::fill(UINT8 color) const
|
|||
|
||||
void Chain::string(const char* str, INT32 flags, Font font) const
|
||||
{
|
||||
if (!str)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto _ = Clipper(*this);
|
||||
|
||||
flags |= default_font_flags(font);
|
||||
|
|
@ -576,5 +580,10 @@ INT32 Draw::default_font_flags(Font font)
|
|||
|
||||
fixed_t Draw::font_width(Font font, INT32 flags, const char* string)
|
||||
{
|
||||
if (!string)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return V_StringScaledWidth(FRACUNIT, FRACUNIT, FRACUNIT, flags, font_to_fontno(font), string);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@
|
|||
#ifndef __V_DRAW_HPP__
|
||||
#define __V_DRAW_HPP__
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "core/hash_map.hpp"
|
||||
#include "core/string.h"
|
||||
#include "doomdef.h" // skincolornum_t
|
||||
#include "doomtype.h"
|
||||
#include "screen.h" // BASEVIDWIDTH
|
||||
|
|
@ -66,7 +66,7 @@ typedef enum
|
|||
} saturn_buttons_e;
|
||||
|
||||
// Garden-variety standard gamepad
|
||||
static const std::unordered_map<INT32, char> standardpad = {
|
||||
static const srb2::HashMap<INT32, char> standardpad = {
|
||||
{nc_a, gb_a},
|
||||
{nc_b, gb_b},
|
||||
{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
|
||||
// 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_b, gb_a},
|
||||
{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)
|
||||
static const std::unordered_map<INT32, char> saturntypeA = {
|
||||
static const srb2::HashMap<INT32, char> saturntypeA = {
|
||||
{nc_a, sb_a},
|
||||
{nc_b, sb_b},
|
||||
{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)
|
||||
static const std::unordered_map<INT32, char> saturntypeB = {
|
||||
static const srb2::HashMap<INT32, char> saturntypeB = {
|
||||
{nc_a, sb_a},
|
||||
{nc_b, sb_b},
|
||||
{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)
|
||||
static const std::unordered_map<INT32, char> saturntypeC = {
|
||||
static const srb2::HashMap<INT32, char> saturntypeC = {
|
||||
{nc_a, sb_a},
|
||||
{nc_b, sb_b},
|
||||
{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)
|
||||
// but is more spatially correct w/r/t SDL expectations
|
||||
// and standard arcade mapping (Z on top, C on bottom)
|
||||
static const std::unordered_map<INT32, char> saturntypeD = {
|
||||
static const srb2::HashMap<INT32, char> saturntypeD = {
|
||||
{nc_a, sb_a},
|
||||
{nc_b, sb_b},
|
||||
{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
|
||||
// unique buttons in every slot while having both bumpers and triggers,
|
||||
// so there's no way to accurately portray it without using generics.
|
||||
static const std::unordered_map<INT32, char> saturntypeE = {
|
||||
static const srb2::HashMap<INT32, char> saturntypeE = {
|
||||
{nc_a, sb_a},
|
||||
{nc_b, sb_b},
|
||||
{nc_x, sb_x},
|
||||
|
|
@ -263,7 +263,7 @@ public:
|
|||
public:
|
||||
explicit TextElement() {}
|
||||
|
||||
explicit TextElement(std::string string) : string_(string) {}
|
||||
explicit TextElement(const srb2::String& string) : string_(string) {}
|
||||
|
||||
template <class... 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<INT32> flags() const { return flags_; }
|
||||
std::optional<UINT8> as() const { return as_; }
|
||||
|
||||
int width() const;
|
||||
|
||||
TextElement& string(std::string string)
|
||||
TextElement& string(srb2::String string)
|
||||
{
|
||||
string_ = string;
|
||||
return *this;
|
||||
|
|
@ -310,7 +310,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
private:
|
||||
std::string string_;
|
||||
srb2::String string_;
|
||||
std::optional<Font> font_;
|
||||
std::optional<INT32> flags_;
|
||||
std::optional<UINT8> as_;
|
||||
|
|
@ -357,7 +357,7 @@ public:
|
|||
Chain& colorize(UINT16 color);
|
||||
|
||||
void text(const char* str) const { string(str, flags_, font_); }
|
||||
void text(const std::string& str) const { text(str.c_str()); }
|
||||
void text(const srb2::String& str) const { text(str.c_str()); }
|
||||
void text(const TextElement& elm) const
|
||||
{
|
||||
string(elm.string().c_str(), elm.flags().value_or(flags_), elm.font().value_or(font_));
|
||||
|
|
@ -370,7 +370,7 @@ public:
|
|||
|
||||
void patch(patch_t* patch) const;
|
||||
void patch(const char* name) const { patch(Draw::cache_patch(name)); }
|
||||
void patch(const std::string& name) const { patch(name.c_str()); }
|
||||
void patch(const srb2::String& name) const { patch(name.c_str()); }
|
||||
|
||||
void thumbnail(UINT16 mapnum) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -322,9 +322,9 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
|
|||
{
|
||||
srb2::StandingJson standing {};
|
||||
standing.ranking = data.pos[data.numplayers];
|
||||
standing.name = std::string(player_names[i]);
|
||||
standing.name = srb2::String(player_names[i]);
|
||||
standing.demoskin = players[i].skin;
|
||||
standing.skincolor = std::string(skincolors[players[i].skincolor].name);
|
||||
standing.skincolor = srb2::String(skincolors[players[i].skincolor].name);
|
||||
standing.timeorscore = data.val[data.numplayers];
|
||||
standings.standings.emplace_back(std::move(standing));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue