From d42c729df1a3c1726e2b21b8f2a95570c9238289 Mon Sep 17 00:00:00 2001 From: gentlegiantJGC Date: Sat, 17 Feb 2024 15:15:40 +0000 Subject: [PATCH] Removed templates from write_nbt.hpp Hopefully this will solve the template issues here --- .../_nbt_encoding/_binary/_cpp/write_nbt.hpp | 235 +++++++++--------- 1 file changed, 117 insertions(+), 118 deletions(-) diff --git a/src/amulet_nbt/_nbt_encoding/_binary/_cpp/write_nbt.hpp b/src/amulet_nbt/_nbt_encoding/_binary/_cpp/write_nbt.hpp index f2800878..05de3342 100644 --- a/src/amulet_nbt/_nbt_encoding/_binary/_cpp/write_nbt.hpp +++ b/src/amulet_nbt/_nbt_encoding/_binary/_cpp/write_nbt.hpp @@ -10,8 +10,24 @@ #include "../../../_tag/_cpp/nbt.hpp" #include "../../../_tag/_cpp/array.hpp" +// I wanted to use templates to reduce code duplication but I can't get this to work +// The template version compiled and passed all tests on my computer but it just wasn't working on the remote servers + + +void write_byte_payload(BinaryWriter& writer, const CByteTag& value); +void write_short_payload(BinaryWriter& writer, const CShortTag& value); +void write_int_payload(BinaryWriter& writer, const CIntTag& value); +void write_long_payload(BinaryWriter& writer, const CLongTag& value); +void write_float_payload(BinaryWriter& writer, const CFloatTag& value); +void write_double_payload(BinaryWriter& writer, const CDoubleTag& value); +void write_byte_array_payload(BinaryWriter& writer, const CByteArrayTagPtr& value); +void write_string_payload(BinaryWriter& writer, const CStringTag& value); +void write_list_payload(BinaryWriter& writer, const CListTagPtr& value); +void write_compound_payload(BinaryWriter& writer, const CCompoundTagPtr& value); +void write_int_array_payload(BinaryWriter& writer, const CIntArrayTagPtr& value); +void write_long_array_payload(BinaryWriter& writer, const CLongArrayTagPtr& value); + -// Forward declarations template < typename T, std::enable_if_t< @@ -28,9 +44,47 @@ template < std::is_same_v || std::is_same_v, bool - > + > = true > -void write_tag_payload(BinaryWriter& writer, const T& value); +void write_named_tag(BinaryWriter& writer, const std::string& name, const T& tag){ + writer.writeNumeric(variant_index()); + write_string_payload(writer, name); + if constexpr (std::is_same_v){write_byte_payload(writer, tag);} else + if constexpr (std::is_same_v){write_short_payload(writer, tag);} else + if constexpr (std::is_same_v){write_int_payload(writer, tag);} else + if constexpr (std::is_same_v){write_long_payload(writer, tag);} else + if constexpr (std::is_same_v){write_float_payload(writer, tag);} else + if constexpr (std::is_same_v){write_double_payload(writer, tag);} else + if constexpr (std::is_same_v){write_byte_array_payload(writer, tag);} else + if constexpr (std::is_same_v){write_string_payload(writer, tag);} else + if constexpr (std::is_same_v){write_list_payload(writer, tag);} else + if constexpr (std::is_same_v){write_compound_payload(writer, tag);} else + if constexpr (std::is_same_v){write_int_array_payload(writer, tag);} else + if constexpr (std::is_same_v){write_long_array_payload(writer, tag);} +} + + +template < + typename T, + std::enable_if_t, bool> = true +> +void write_named_tag(BinaryWriter& writer, const std::string& name, const TagNode& node){ + switch (node.index()){ + case 1: write_named_tag(writer, name, std::get(node)); break; + case 2: write_named_tag(writer, name, std::get(node)); break; + case 3: write_named_tag(writer, name, std::get(node)); break; + case 4: write_named_tag(writer, name, std::get(node)); break; + case 5: write_named_tag(writer, name, std::get(node)); break; + case 6: write_named_tag(writer, name, std::get(node)); break; + case 7: write_named_tag(writer, name, std::get(node)); break; + case 8: write_named_tag(writer, name, std::get(node)); break; + case 9: write_named_tag(writer, name, std::get(node)); break; + case 10: write_named_tag(writer, name, std::get(node)); break; + case 11: write_named_tag(writer, name, std::get(node)); break; + case 12: write_named_tag(writer, name, std::get(node)); break; + default: throw std::runtime_error("TagNode cannot be in null state when writing."); + } +} template < @@ -50,9 +104,13 @@ template < std::is_same_v || std::is_same_v, bool - > + > = true > -void write_named_tag(BinaryWriter& writer, const std::string& name, const T& tag); +std::string write_named_tag(const std::string& name, const T& tag, std::endian endianness, StringEncode stringEncode){ + BinaryWriter writer(endianness, stringEncode); + write_named_tag(writer, name, tag); + return writer.getBuffer(); +} template @@ -66,32 +124,31 @@ constexpr size_t variant_index() { } -template -struct overloaded : Ts... { using Ts::operator()...; }; +void write_byte_payload(BinaryWriter& writer, const CByteTag& value){ + writer.writeNumeric(value); +} +void write_short_payload(BinaryWriter& writer, const CShortTag& value){ + writer.writeNumeric(value); +} -template < - typename T, - std::enable_if_t< - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v, - bool - > = true -> -void write_tag_payload(BinaryWriter& writer, const T& value){ - writer.writeNumeric(value); +void write_int_payload(BinaryWriter& writer, const CIntTag& value){ + writer.writeNumeric(value); } +void write_long_payload(BinaryWriter& writer, const CLongTag& value){ + writer.writeNumeric(value); +} -template < - typename T, - std::enable_if_t, bool> = true -> -void write_tag_payload(BinaryWriter& writer, const CStringTag& value){ +void write_float_payload(BinaryWriter& writer, const CFloatTag& value){ + writer.writeNumeric(value); +} + +void write_double_payload(BinaryWriter& writer, const CDoubleTag& value){ + writer.writeNumeric(value); +} + +void write_string_payload(BinaryWriter& writer, const CStringTag& value){ std::string encoded_string = writer.encodeString(value); if (encoded_string.size() > static_cast(std::numeric_limits::max())){ throw std::overflow_error(std::format("String of length {} is too long.", encoded_string.size())); @@ -129,16 +186,23 @@ void write_list_tag_payload(BinaryWriter& writer, const CListTagPtr& value){ std::int32_t length = static_cast(list.size()); writer.writeNumeric(length); for (const T& element: list){ - write_tag_payload(writer, element); + if constexpr (std::is_same_v){write_byte_payload(writer, element);} else + if constexpr (std::is_same_v){write_short_payload(writer, element);} else + if constexpr (std::is_same_v){write_int_payload(writer, element);} else + if constexpr (std::is_same_v){write_long_payload(writer, element);} else + if constexpr (std::is_same_v){write_float_payload(writer, element);} else + if constexpr (std::is_same_v){write_double_payload(writer, element);} else + if constexpr (std::is_same_v){write_byte_array_payload(writer, element);} else + if constexpr (std::is_same_v){write_string_payload(writer, element);} else + if constexpr (std::is_same_v){write_list_payload(writer, element);} else + if constexpr (std::is_same_v){write_compound_payload(writer, element);} else + if constexpr (std::is_same_v){write_int_array_payload(writer, element);} else + if constexpr (std::is_same_v){write_long_array_payload(writer, element);} } } -template < - typename T, - std::enable_if_t, bool> = true -> -void write_tag_payload(BinaryWriter& writer, const CListTagPtr& value){ +void write_list_payload(BinaryWriter& writer, const CListTagPtr& value){ switch (value->index()){ case 0: writer.writeNumeric(0); @@ -160,11 +224,7 @@ void write_tag_payload(BinaryWriter& writer, const CListTagPtr& value){ } -template < - typename T, - std::enable_if_t, bool> = true -> -void write_tag_payload(BinaryWriter& writer, const CCompoundTagPtr& value){ +void write_compound_payload(BinaryWriter& writer, const CCompoundTagPtr& value){ for (auto it = value->begin(); it != value->end(); it++){ write_named_tag(writer, it->first, it->second); } @@ -172,96 +232,35 @@ void write_tag_payload(BinaryWriter& writer, const CCompoundTagPtr& value){ }; -template < - typename T, - std::enable_if_t< - std::is_same_v || - std::is_same_v || - std::is_same_v, - bool - > = true -> -void write_tag_payload(BinaryWriter& writer, const T& value){ +void write_byte_array_payload(BinaryWriter& writer, const CByteArrayTagPtr& value){ if (value->size() > static_cast(std::numeric_limits::max())){ throw std::overflow_error(std::format("Array of length {} is too long.", value->size())); } std::int32_t length = static_cast(value->size()); writer.writeNumeric(length); - for (const typename T::element_type::value_type& element: *value){ - writer.writeNumeric(element); + for (const CByteTag& element: *value){ + writer.writeNumeric(element); } } - -template < - typename T, - std::enable_if_t< - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v, - bool - > = true -> -void write_named_tag(BinaryWriter& writer, const std::string& name, const T& tag){ - writer.writeNumeric(variant_index()); - write_tag_payload(writer, name); - write_tag_payload(writer, tag); -} - - -template < - typename T, - std::enable_if_t, bool> = true -> -void write_named_tag(BinaryWriter& writer, const std::string& name, const TagNode& node){ - switch (node.index()){ - case 1: write_named_tag(writer, name, std::get(node)); break; - case 2: write_named_tag(writer, name, std::get(node)); break; - case 3: write_named_tag(writer, name, std::get(node)); break; - case 4: write_named_tag(writer, name, std::get(node)); break; - case 5: write_named_tag(writer, name, std::get(node)); break; - case 6: write_named_tag(writer, name, std::get(node)); break; - case 7: write_named_tag(writer, name, std::get(node)); break; - case 8: write_named_tag(writer, name, std::get(node)); break; - case 9: write_named_tag(writer, name, std::get(node)); break; - case 10: write_named_tag(writer, name, std::get(node)); break; - case 11: write_named_tag(writer, name, std::get(node)); break; - case 12: write_named_tag(writer, name, std::get(node)); break; - default: throw std::runtime_error("TagNode cannot be in null state when writing."); +void write_int_array_payload(BinaryWriter& writer, const CIntArrayTagPtr& value){ + if (value->size() > static_cast(std::numeric_limits::max())){ + throw std::overflow_error(std::format("Array of length {} is too long.", value->size())); + } + std::int32_t length = static_cast(value->size()); + writer.writeNumeric(length); + for (const CIntTag& element: *value){ + writer.writeNumeric(element); } } - -template < - typename T, - std::enable_if_t< - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v, - bool - > = true -> -std::string write_named_tag(const std::string& name, const T& tag, std::endian endianness, StringEncode stringEncode){ - BinaryWriter writer(endianness, stringEncode); - write_named_tag(writer, name, tag); - return writer.getBuffer(); +void write_long_array_payload(BinaryWriter& writer, const CLongArrayTagPtr& value){ + if (value->size() > static_cast(std::numeric_limits::max())){ + throw std::overflow_error(std::format("Array of length {} is too long.", value->size())); + } + std::int32_t length = static_cast(value->size()); + writer.writeNumeric(length); + for (const CLongTag& element: *value){ + writer.writeNumeric(element); + } }