Skip to content

Commit

Permalink
feat: add more operators to UniqueTagPtr, resolve #1607
Browse files Browse the repository at this point in the history
  • Loading branch information
OEOTYAN committed Jan 3, 2025
1 parent a6f010b commit 1a76095
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 44 deletions.
8 changes: 8 additions & 0 deletions src-test/server/TestNbt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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]});
}
3 changes: 0 additions & 3 deletions src/ll/api/base/Concepts.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ concept IsInTypes = traits::is_in_types_v<T, U>;
template <class T, class... Ts>
concept IsOneOf = traits::is_one_of_v<T, Ts...>;

template <class T>
concept IsNonCharIntegral = traits::is_non_char_integral_v<T>;

template <class T>
concept IsString = traits::is_string_v<T>;

Expand Down
5 changes: 1 addition & 4 deletions src/ll/api/base/TypeTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,7 @@ template <class T>
constexpr bool is_string_v = std::is_constructible_v<std::string, T>;

template <class T>
constexpr bool is_char_v = is_one_of_v<T, char, wchar_t, char8_t, char16_t, char32_t>;

template <class T>
constexpr bool is_non_char_integral_v = std::is_integral_v<T> && !is_char_v<T>;
constexpr bool is_char_v = is_one_of_v<std::remove_cv_t<T>, char, wchar_t, char8_t, char16_t, char32_t>;

template <class T, template <class...> class Z>
constexpr bool is_specialization_of_v = false;
Expand Down
8 changes: 4 additions & 4 deletions src/mc/nbt/CompoundTag.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<CompoundTag>
fromSnbt(std::string_view snbt, optional_ref<size_t> parsedLength = std::nullopt) noexcept;
Expand Down
102 changes: 69 additions & 33 deletions src/mc/nbt/CompoundTagVariant.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class CompoundTagVariant {
}
}

[[nodiscard]] CompoundTagVariant& operator[](char const* index) {
[[nodiscard]] CompoundTagVariant& operator[](std::string_view index) {
if (is_null()) {
mTagStorage = CompoundTag{};
}
Expand All @@ -231,28 +231,21 @@ class CompoundTagVariant {
return get<CompoundTag>()[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<CompoundTag>()[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<CompoundTag>()[index];
template <size_t N>
[[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<CompoundTag>()[index];
template <size_t N>
[[nodiscard]] CompoundTagVariant const& operator[](char const (&index)[N]) const { // make EDG happy
return operator[](std::string_view{index});
}

[[nodiscard]] UniqueTagPtr toUnique() const& {
Expand Down Expand Up @@ -288,7 +281,8 @@ class CompoundTagVariant {
get<ListTag>().add(std::move(val).toUnique());
}

template <ll::concepts::IsNonCharIntegral T>
template <class T>
requires(std::is_arithmetic_v<T> && !ll::traits::is_char_v<T>)
[[nodiscard]] constexpr operator T() const {
if (is_number()) {
return std::visit(
Expand All @@ -305,23 +299,6 @@ class CompoundTagVariant {
throw std::runtime_error("tag not hold an number");
}
}
template <std::floating_point T>
[[nodiscard]] constexpr operator T() const {
if (is_number()) {
return std::visit(
[](auto& val) -> T {
if constexpr (std::is_convertible_v<std::decay_t<decltype(val)>, 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<StringTag>(); }
[[nodiscard]] operator std::string&() { return get<StringTag>(); }
[[nodiscard]] operator std::string&&() && { return std::move(get<StringTag>()); }
Expand All @@ -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<CompoundTagVariant> tags) {
if (tags.empty()) {
mType = Tag::End;
Expand Down Expand Up @@ -410,3 +400,49 @@ template <std::derived_from<Tag> T>
[[nodiscard]] inline UniqueTagPtr::operator std::string&() & { return get<StringTag>(); }
[[nodiscard]] inline UniqueTagPtr::operator std::string&&() && { return std::move(get<StringTag>()); }
[[nodiscard]] inline UniqueTagPtr::operator std::string_view() const { return get<StringTag>(); }

[[nodiscard]] inline UniqueTagPtr& UniqueTagPtr::operator[](size_t index) {
if (hold(Tag::List)) {
return get<ListTag>()[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<ListTag>()[index];
} else {
throw std::runtime_error("tag not hold an array");
}
}
[[nodiscard]] inline CompoundTagVariant& UniqueTagPtr::operator[](std::string_view index) {
if (is_null()) {
emplace<CompoundTag>();
}
if (!hold(Tag::Compound)) {
throw std::runtime_error("tag not hold an object");
}
return get<CompoundTag>()[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<CompoundTag>()[index];
}
template <class T>
requires(std::is_arithmetic_v<T> && !ll::traits::is_char_v<T>)
[[nodiscard]] inline UniqueTagPtr::operator T() const {
if (is_number()) {
return ll::meta::visitIndex<CompoundTagVariant::Types::size>((size_t)getId(), [&]<size_t I>() -> T {
auto& val = *static_cast<CompoundTagVariant::Types::get<I>*>(ptr);
if constexpr (std::is_convertible_v<std::decay_t<decltype(val)>, T>) {
return (T)val;
} else {
return {};
}
});
} else {
throw std::runtime_error("tag not hold an number");
}
}
17 changes: 17 additions & 0 deletions src/mc/nbt/UniqueTagPtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <size_t N>
[[nodiscard]] CompoundTagVariant& operator[](char const (&index)[N]) { // make EDG happy
return operator[](std::string_view{index});
}
template <size_t N>
[[nodiscard]] CompoundTagVariant const& operator[](char const (&index)[N]) const { // make EDG happy
return operator[](std::string_view{index});
}

public:
[[nodiscard]] std::unique_ptr<Tag> copy() const { return ptr ? ptr->copy() : nullptr; }

Expand Down Expand Up @@ -143,4 +156,8 @@ class UniqueTagPtr {
[[nodiscard]] operator std::string&() &;
[[nodiscard]] operator std::string&&() &&;
[[nodiscard]] operator std::string_view() const;

template <class T>
requires(std::is_arithmetic_v<T> && !ll::traits::is_char_v<T>)
[[nodiscard]] operator T() const;
};

0 comments on commit 1a76095

Please sign in to comment.