From 1a76095501946f9449af772f733dd5e4cd5846f7 Mon Sep 17 00:00:00 2001 From: OEOTYAN Date: Fri, 3 Jan 2025 16:51:27 +0800 Subject: [PATCH] feat: add more operators to UniqueTagPtr, resolve #1607 --- src-test/server/TestNbt.cpp | 8 +++ src/ll/api/base/Concepts.h | 3 - src/ll/api/base/TypeTraits.h | 5 +- src/mc/nbt/CompoundTag.h | 8 +-- src/mc/nbt/CompoundTagVariant.h | 102 +++++++++++++++++++++----------- src/mc/nbt/UniqueTagPtr.h | 17 ++++++ 6 files changed, 99 insertions(+), 44 deletions(-) diff --git a/src-test/server/TestNbt.cpp b/src-test/server/TestNbt.cpp index 0e06a370d9..a423bc4a6d 100644 --- a/src-test/server/TestNbt.cpp +++ b/src-test/server/TestNbt.cpp @@ -189,4 +189,12 @@ LL_AUTO_TYPE_INSTANCE_HOOK(NbtTest, HookPriority::Normal, ServerInstance, &Serve ll::getLogger().debug("signature {}", "48 8D 05 ? ? ? ? E8"_sig.toString(false, false)); ll::getLogger().debug("resolve {}", "48 8D 05 ? ? ? ? E8"_sig.resolve()); + + auto nbt11 = CompoundTag{ + {"a", {{"b", {{"c", 12345}}}}} + }; + auto nbt12 = ListTag{{ListTag{{ListTag{{54321}}}}}}; + + ll::getLogger().debug("nbt {}\n{}", nbt11.toSnbt(), nbt12.toSnbt()); + ll::getLogger().debug("nbt {} {}", int{nbt11["a"]["b"]["c"]}, int{nbt12[0][0][0]}); } diff --git a/src/ll/api/base/Concepts.h b/src/ll/api/base/Concepts.h index 31359099eb..2585958f2e 100644 --- a/src/ll/api/base/Concepts.h +++ b/src/ll/api/base/Concepts.h @@ -21,9 +21,6 @@ concept IsInTypes = traits::is_in_types_v; template concept IsOneOf = traits::is_one_of_v; -template -concept IsNonCharIntegral = traits::is_non_char_integral_v; - template concept IsString = traits::is_string_v; diff --git a/src/ll/api/base/TypeTraits.h b/src/ll/api/base/TypeTraits.h index ee3de36fce..8d2c129092 100644 --- a/src/ll/api/base/TypeTraits.h +++ b/src/ll/api/base/TypeTraits.h @@ -123,10 +123,7 @@ template constexpr bool is_string_v = std::is_constructible_v; template -constexpr bool is_char_v = is_one_of_v; - -template -constexpr bool is_non_char_integral_v = std::is_integral_v && !is_char_v; +constexpr bool is_char_v = is_one_of_v, char, wchar_t, char8_t, char16_t, char32_t>; template class Z> constexpr bool is_specialization_of_v = false; diff --git a/src/mc/nbt/CompoundTag.h b/src/mc/nbt/CompoundTag.h index 4fbbffc14e..c343457ad0 100644 --- a/src/mc/nbt/CompoundTag.h +++ b/src/mc/nbt/CompoundTag.h @@ -27,11 +27,11 @@ class CompoundTag : public ::Tag { CompoundTag(CompoundTag&&) = default; CompoundTag& operator=(CompoundTag&&) = default; - [[nodiscard]] CompoundTagVariant& operator[](std::string const& index) { return mTags[index]; } - [[nodiscard]] CompoundTagVariant const& operator[](std::string const& index) const { return mTags.at(index); } + [[nodiscard]] CompoundTagVariant& operator[](std::string_view index); + [[nodiscard]] CompoundTagVariant const& operator[](std::string_view index) const; - [[nodiscard]] CompoundTagVariant& at(std::string const& index) { return mTags[index]; } - [[nodiscard]] CompoundTagVariant const& at(std::string const& index) const { return mTags.at(index); } + [[nodiscard]] CompoundTagVariant& at(std::string_view index) { return operator[](index); } + [[nodiscard]] CompoundTagVariant const& at(std::string_view index) const { return operator[](index); } LLNDAPI static ll::Expected fromSnbt(std::string_view snbt, optional_ref parsedLength = std::nullopt) noexcept; diff --git a/src/mc/nbt/CompoundTagVariant.h b/src/mc/nbt/CompoundTagVariant.h index 5d6b9bb16a..cdaa4fa7ab 100644 --- a/src/mc/nbt/CompoundTagVariant.h +++ b/src/mc/nbt/CompoundTagVariant.h @@ -221,7 +221,7 @@ class CompoundTagVariant { } } - [[nodiscard]] CompoundTagVariant& operator[](char const* index) { + [[nodiscard]] CompoundTagVariant& operator[](std::string_view index) { if (is_null()) { mTagStorage = CompoundTag{}; } @@ -231,28 +231,21 @@ class CompoundTagVariant { return get()[index]; } - [[nodiscard]] CompoundTagVariant const& operator[](char const* index) const { + [[nodiscard]] CompoundTagVariant const& operator[](std::string_view index) const { if (!hold(Tag::Compound)) { throw std::runtime_error("tag not hold an object"); } return get()[index]; } - [[nodiscard]] CompoundTagVariant& operator[](std::string const& index) { - if (is_null()) { - mTagStorage = CompoundTag{}; - } - if (!hold(Tag::Compound)) { - throw std::runtime_error("tag not hold an object"); - } - return get()[index]; + template + [[nodiscard]] CompoundTagVariant& operator[](char const (&index)[N]) { // make EDG happy + return operator[](std::string_view{index}); } - [[nodiscard]] CompoundTagVariant const& operator[](std::string const& index) const { - if (!hold(Tag::Compound)) { - throw std::runtime_error("tag not hold an object"); - } - return get()[index]; + template + [[nodiscard]] CompoundTagVariant const& operator[](char const (&index)[N]) const { // make EDG happy + return operator[](std::string_view{index}); } [[nodiscard]] UniqueTagPtr toUnique() const& { @@ -288,7 +281,8 @@ class CompoundTagVariant { get().add(std::move(val).toUnique()); } - template + template + requires(std::is_arithmetic_v && !ll::traits::is_char_v) [[nodiscard]] constexpr operator T() const { if (is_number()) { return std::visit( @@ -305,23 +299,6 @@ class CompoundTagVariant { throw std::runtime_error("tag not hold an number"); } } - template - [[nodiscard]] constexpr operator T() const { - if (is_number()) { - return std::visit( - [](auto& val) -> T { - if constexpr (std::is_convertible_v, T>) { - return (T)val; - } else { - return {}; - } - }, - mTagStorage - ); - } else { - throw std::runtime_error("tag not hold a number"); - } - } [[nodiscard]] operator std::string const&() const { return get(); } [[nodiscard]] operator std::string&() { return get(); } [[nodiscard]] operator std::string&&() && { return std::move(get()); } @@ -334,6 +311,19 @@ class CompoundTagVariant { } }; +[[nodiscard]] inline CompoundTagVariant& CompoundTag::operator[](std::string_view index) { + if (auto it = mTags.find(index); it != mTags.end()) { + return it->second; + } + return mTags[std::string{index}]; +} +[[nodiscard]] inline CompoundTagVariant const& CompoundTag::operator[](std::string_view index) const { + if (auto it = mTags.find(index); it != mTags.end()) { + return it->second; + } + throw std::out_of_range("invalid nbt key"); +} + [[nodiscard]] constexpr ListTag::ListTag(std::vector tags) { if (tags.empty()) { mType = Tag::End; @@ -410,3 +400,49 @@ template T> [[nodiscard]] inline UniqueTagPtr::operator std::string&() & { return get(); } [[nodiscard]] inline UniqueTagPtr::operator std::string&&() && { return std::move(get()); } [[nodiscard]] inline UniqueTagPtr::operator std::string_view() const { return get(); } + +[[nodiscard]] inline UniqueTagPtr& UniqueTagPtr::operator[](size_t index) { + if (hold(Tag::List)) { + return get()[index]; + } else { + throw std::runtime_error("tag not hold an array"); + } +} +[[nodiscard]] inline UniqueTagPtr const& UniqueTagPtr::operator[](size_t index) const { + if (hold(Tag::List)) { + return get()[index]; + } else { + throw std::runtime_error("tag not hold an array"); + } +} +[[nodiscard]] inline CompoundTagVariant& UniqueTagPtr::operator[](std::string_view index) { + if (is_null()) { + emplace(); + } + if (!hold(Tag::Compound)) { + throw std::runtime_error("tag not hold an object"); + } + return get()[index]; +} +[[nodiscard]] inline CompoundTagVariant const& UniqueTagPtr::operator[](std::string_view index) const { + if (!hold(Tag::Compound)) { + throw std::runtime_error("tag not hold an object"); + } + return get()[index]; +} +template + requires(std::is_arithmetic_v && !ll::traits::is_char_v) +[[nodiscard]] inline UniqueTagPtr::operator T() const { + if (is_number()) { + return ll::meta::visitIndex((size_t)getId(), [&]() -> T { + auto& val = *static_cast*>(ptr); + if constexpr (std::is_convertible_v, T>) { + return (T)val; + } else { + return {}; + } + }); + } else { + throw std::runtime_error("tag not hold an number"); + } +} diff --git a/src/mc/nbt/UniqueTagPtr.h b/src/mc/nbt/UniqueTagPtr.h index 9b0e539cf1..f30e36e0fd 100644 --- a/src/mc/nbt/UniqueTagPtr.h +++ b/src/mc/nbt/UniqueTagPtr.h @@ -88,6 +88,19 @@ class UniqueTagPtr { delete old; } + [[nodiscard]] UniqueTagPtr& operator[](size_t index); + [[nodiscard]] UniqueTagPtr const& operator[](size_t index) const; + [[nodiscard]] CompoundTagVariant& operator[](std::string_view index); + [[nodiscard]] CompoundTagVariant const& operator[](std::string_view index) const; + template + [[nodiscard]] CompoundTagVariant& operator[](char const (&index)[N]) { // make EDG happy + return operator[](std::string_view{index}); + } + template + [[nodiscard]] CompoundTagVariant const& operator[](char const (&index)[N]) const { // make EDG happy + return operator[](std::string_view{index}); + } + public: [[nodiscard]] std::unique_ptr copy() const { return ptr ? ptr->copy() : nullptr; } @@ -143,4 +156,8 @@ class UniqueTagPtr { [[nodiscard]] operator std::string&() &; [[nodiscard]] operator std::string&&() &&; [[nodiscard]] operator std::string_view() const; + + template + requires(std::is_arithmetic_v && !ll::traits::is_char_v) + [[nodiscard]] operator T() const; };