summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 17:35:01 +0300
committerMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 17:35:01 +0300
commit1a0ffe372f4da8408c5d08a36013536a3396b9e6 (patch)
tree440f2a9a325c9ab4cb5b16dc6a8193317cabf8d7 /src
parentf4d8ea0fa76174843adf7f77ebad0ad17d2377ed (diff)
downloadProject-Tick-1a0ffe372f4da8408c5d08a36013536a3396b9e6.tar.gz
Project-Tick-1a0ffe372f4da8408c5d08a36013536a3396b9e6.zip
NOISSUE reformat libnbtplusplus to new MeshMC clang format rules
Signed-off-by: Mehmet Samet Duman <yongdohyun@projecttick.org>
Diffstat (limited to 'src')
-rw-r--r--src/endian_str.cpp518
-rw-r--r--src/io/izlibstream.cpp123
-rw-r--r--src/io/ozlibstream.cpp155
-rw-r--r--src/io/stream_reader.cpp155
-rw-r--r--src/io/stream_writer.cpp53
-rw-r--r--src/tag.cpp300
-rw-r--r--src/tag_compound.cpp138
-rw-r--r--src/tag_list.cpp278
-rw-r--r--src/tag_string.cpp29
-rw-r--r--src/text/json_formatter.cpp426
-rw-r--r--src/value.cpp576
-rw-r--r--src/value_initializer.cpp29
12 files changed, 1443 insertions, 1337 deletions
diff --git a/src/endian_str.cpp b/src/endian_str.cpp
index c6de84201d..e9553cd9d3 100644
--- a/src/endian_str.cpp
+++ b/src/endian_str.cpp
@@ -33,256 +33,268 @@ static_assert(sizeof(double) == 8, "Assuming that a double is 8 byte long");
namespace endian
{
-namespace //anonymous
-{
- void pun_int_to_float(float& f, uint32_t i)
- {
- //Yes we need to do it this way to avoid undefined behavior
- memcpy(&f, &i, 4);
- }
-
- uint32_t pun_float_to_int(float f)
- {
- uint32_t ret;
- memcpy(&ret, &f, 4);
- return ret;
- }
-
- void pun_int_to_double(double& d, uint64_t i)
- {
- memcpy(&d, &i, 8);
- }
-
- uint64_t pun_double_to_int(double f)
- {
- uint64_t ret;
- memcpy(&ret, &f, 8);
- return ret;
- }
-}
-
-//------------------------------------------------------------------------------
-
-void read_little(std::istream& is, uint8_t& x)
-{
- is.get(reinterpret_cast<char&>(x));
-}
-
-void read_little(std::istream& is, uint16_t& x)
-{
- uint8_t tmp[2];
- is.read(reinterpret_cast<char*>(tmp), 2);
- x = uint16_t(tmp[0])
- | (uint16_t(tmp[1]) << 8);
-}
-
-void read_little(std::istream& is, uint32_t& x)
-{
- uint8_t tmp[4];
- is.read(reinterpret_cast<char*>(tmp), 4);
- x = uint32_t(tmp[0])
- | (uint32_t(tmp[1]) << 8)
- | (uint32_t(tmp[2]) << 16)
- | (uint32_t(tmp[3]) << 24);
-}
-
-void read_little(std::istream& is, uint64_t& x)
-{
- uint8_t tmp[8];
- is.read(reinterpret_cast<char*>(tmp), 8);
- x = uint64_t(tmp[0])
- | (uint64_t(tmp[1]) << 8)
- | (uint64_t(tmp[2]) << 16)
- | (uint64_t(tmp[3]) << 24)
- | (uint64_t(tmp[4]) << 32)
- | (uint64_t(tmp[5]) << 40)
- | (uint64_t(tmp[6]) << 48)
- | (uint64_t(tmp[7]) << 56);
-}
-
-void read_little(std::istream& is, int8_t & x) { read_little(is, reinterpret_cast<uint8_t &>(x)); }
-void read_little(std::istream& is, int16_t& x) { read_little(is, reinterpret_cast<uint16_t&>(x)); }
-void read_little(std::istream& is, int32_t& x) { read_little(is, reinterpret_cast<uint32_t&>(x)); }
-void read_little(std::istream& is, int64_t& x) { read_little(is, reinterpret_cast<uint64_t&>(x)); }
-
-void read_little(std::istream& is, float& x)
-{
- uint32_t tmp;
- read_little(is, tmp);
- pun_int_to_float(x, tmp);
-}
-
-void read_little(std::istream& is, double& x)
-{
- uint64_t tmp;
- read_little(is, tmp);
- pun_int_to_double(x, tmp);
-}
-
-//------------------------------------------------------------------------------
-
-void read_big(std::istream& is, uint8_t& x)
-{
- is.read(reinterpret_cast<char*>(&x), 1);
-}
-
-void read_big(std::istream& is, uint16_t& x)
-{
- uint8_t tmp[2];
- is.read(reinterpret_cast<char*>(tmp), 2);
- x = uint16_t(tmp[1])
- | (uint16_t(tmp[0]) << 8);
-}
-
-void read_big(std::istream& is, uint32_t& x)
-{
- uint8_t tmp[4];
- is.read(reinterpret_cast<char*>(tmp), 4);
- x = uint32_t(tmp[3])
- | (uint32_t(tmp[2]) << 8)
- | (uint32_t(tmp[1]) << 16)
- | (uint32_t(tmp[0]) << 24);
-}
-
-void read_big(std::istream& is, uint64_t& x)
-{
- uint8_t tmp[8];
- is.read(reinterpret_cast<char*>(tmp), 8);
- x = uint64_t(tmp[7])
- | (uint64_t(tmp[6]) << 8)
- | (uint64_t(tmp[5]) << 16)
- | (uint64_t(tmp[4]) << 24)
- | (uint64_t(tmp[3]) << 32)
- | (uint64_t(tmp[2]) << 40)
- | (uint64_t(tmp[1]) << 48)
- | (uint64_t(tmp[0]) << 56);
-}
-
-void read_big(std::istream& is, int8_t & x) { read_big(is, reinterpret_cast<uint8_t &>(x)); }
-void read_big(std::istream& is, int16_t& x) { read_big(is, reinterpret_cast<uint16_t&>(x)); }
-void read_big(std::istream& is, int32_t& x) { read_big(is, reinterpret_cast<uint32_t&>(x)); }
-void read_big(std::istream& is, int64_t& x) { read_big(is, reinterpret_cast<uint64_t&>(x)); }
-
-void read_big(std::istream& is, float& x)
-{
- uint32_t tmp;
- read_big(is, tmp);
- pun_int_to_float(x, tmp);
-}
-
-void read_big(std::istream& is, double& x)
-{
- uint64_t tmp;
- read_big(is, tmp);
- pun_int_to_double(x, tmp);
-}
-
-//------------------------------------------------------------------------------
-
-void write_little(std::ostream& os, uint8_t x)
-{
- os.put(x);
-}
-
-void write_little(std::ostream& os, uint16_t x)
-{
- uint8_t tmp[2] {
- uint8_t(x),
- uint8_t(x >> 8)};
- os.write(reinterpret_cast<const char*>(tmp), 2);
-}
-
-void write_little(std::ostream& os, uint32_t x)
-{
- uint8_t tmp[4] {
- uint8_t(x),
- uint8_t(x >> 8),
- uint8_t(x >> 16),
- uint8_t(x >> 24)};
- os.write(reinterpret_cast<const char*>(tmp), 4);
-}
-
-void write_little(std::ostream& os, uint64_t x)
-{
- uint8_t tmp[8] {
- uint8_t(x),
- uint8_t(x >> 8),
- uint8_t(x >> 16),
- uint8_t(x >> 24),
- uint8_t(x >> 32),
- uint8_t(x >> 40),
- uint8_t(x >> 48),
- uint8_t(x >> 56)};
- os.write(reinterpret_cast<const char*>(tmp), 8);
-}
-
-void write_little(std::ostream& os, int8_t x) { write_little(os, static_cast<uint8_t >(x)); }
-void write_little(std::ostream& os, int16_t x) { write_little(os, static_cast<uint16_t>(x)); }
-void write_little(std::ostream& os, int32_t x) { write_little(os, static_cast<uint32_t>(x)); }
-void write_little(std::ostream& os, int64_t x) { write_little(os, static_cast<uint64_t>(x)); }
-
-void write_little(std::ostream& os, float x)
-{
- write_little(os, pun_float_to_int(x));
-}
-
-void write_little(std::ostream& os, double x)
-{
- write_little(os, pun_double_to_int(x));
-}
-
-//------------------------------------------------------------------------------
-
-void write_big(std::ostream& os, uint8_t x)
-{
- os.put(x);
-}
-
-void write_big(std::ostream& os, uint16_t x)
-{
- uint8_t tmp[2] {
- uint8_t(x >> 8),
- uint8_t(x)};
- os.write(reinterpret_cast<const char*>(tmp), 2);
-}
-
-void write_big(std::ostream& os, uint32_t x)
-{
- uint8_t tmp[4] {
- uint8_t(x >> 24),
- uint8_t(x >> 16),
- uint8_t(x >> 8),
- uint8_t(x)};
- os.write(reinterpret_cast<const char*>(tmp), 4);
-}
-
-void write_big(std::ostream& os, uint64_t x)
-{
- uint8_t tmp[8] {
- uint8_t(x >> 56),
- uint8_t(x >> 48),
- uint8_t(x >> 40),
- uint8_t(x >> 32),
- uint8_t(x >> 24),
- uint8_t(x >> 16),
- uint8_t(x >> 8),
- uint8_t(x)};
- os.write(reinterpret_cast<const char*>(tmp), 8);
-}
-
-void write_big(std::ostream& os, int8_t x) { write_big(os, static_cast<uint8_t >(x)); }
-void write_big(std::ostream& os, int16_t x) { write_big(os, static_cast<uint16_t>(x)); }
-void write_big(std::ostream& os, int32_t x) { write_big(os, static_cast<uint32_t>(x)); }
-void write_big(std::ostream& os, int64_t x) { write_big(os, static_cast<uint64_t>(x)); }
-
-void write_big(std::ostream& os, float x)
-{
- write_big(os, pun_float_to_int(x));
-}
-
-void write_big(std::ostream& os, double x)
-{
- write_big(os, pun_double_to_int(x));
-}
-
-}
+ namespace // anonymous
+ {
+ void pun_int_to_float(float& f, uint32_t i)
+ {
+ // Yes we need to do it this way to avoid undefined behavior
+ memcpy(&f, &i, 4);
+ }
+
+ uint32_t pun_float_to_int(float f)
+ {
+ uint32_t ret;
+ memcpy(&ret, &f, 4);
+ return ret;
+ }
+
+ void pun_int_to_double(double& d, uint64_t i)
+ {
+ memcpy(&d, &i, 8);
+ }
+
+ uint64_t pun_double_to_int(double f)
+ {
+ uint64_t ret;
+ memcpy(&ret, &f, 8);
+ return ret;
+ }
+ } // namespace
+
+ //------------------------------------------------------------------------------
+
+ void read_little(std::istream& is, uint8_t& x)
+ {
+ is.get(reinterpret_cast<char&>(x));
+ }
+
+ void read_little(std::istream& is, uint16_t& x)
+ {
+ uint8_t tmp[2];
+ is.read(reinterpret_cast<char*>(tmp), 2);
+ x = uint16_t(tmp[0]) | (uint16_t(tmp[1]) << 8);
+ }
+
+ void read_little(std::istream& is, uint32_t& x)
+ {
+ uint8_t tmp[4];
+ is.read(reinterpret_cast<char*>(tmp), 4);
+ x = uint32_t(tmp[0]) | (uint32_t(tmp[1]) << 8) |
+ (uint32_t(tmp[2]) << 16) | (uint32_t(tmp[3]) << 24);
+ }
+
+ void read_little(std::istream& is, uint64_t& x)
+ {
+ uint8_t tmp[8];
+ is.read(reinterpret_cast<char*>(tmp), 8);
+ x = uint64_t(tmp[0]) | (uint64_t(tmp[1]) << 8) |
+ (uint64_t(tmp[2]) << 16) | (uint64_t(tmp[3]) << 24) |
+ (uint64_t(tmp[4]) << 32) | (uint64_t(tmp[5]) << 40) |
+ (uint64_t(tmp[6]) << 48) | (uint64_t(tmp[7]) << 56);
+ }
+
+ void read_little(std::istream& is, int8_t& x)
+ {
+ read_little(is, reinterpret_cast<uint8_t&>(x));
+ }
+ void read_little(std::istream& is, int16_t& x)
+ {
+ read_little(is, reinterpret_cast<uint16_t&>(x));
+ }
+ void read_little(std::istream& is, int32_t& x)
+ {
+ read_little(is, reinterpret_cast<uint32_t&>(x));
+ }
+ void read_little(std::istream& is, int64_t& x)
+ {
+ read_little(is, reinterpret_cast<uint64_t&>(x));
+ }
+
+ void read_little(std::istream& is, float& x)
+ {
+ uint32_t tmp;
+ read_little(is, tmp);
+ pun_int_to_float(x, tmp);
+ }
+
+ void read_little(std::istream& is, double& x)
+ {
+ uint64_t tmp;
+ read_little(is, tmp);
+ pun_int_to_double(x, tmp);
+ }
+
+ //------------------------------------------------------------------------------
+
+ void read_big(std::istream& is, uint8_t& x)
+ {
+ is.read(reinterpret_cast<char*>(&x), 1);
+ }
+
+ void read_big(std::istream& is, uint16_t& x)
+ {
+ uint8_t tmp[2];
+ is.read(reinterpret_cast<char*>(tmp), 2);
+ x = uint16_t(tmp[1]) | (uint16_t(tmp[0]) << 8);
+ }
+
+ void read_big(std::istream& is, uint32_t& x)
+ {
+ uint8_t tmp[4];
+ is.read(reinterpret_cast<char*>(tmp), 4);
+ x = uint32_t(tmp[3]) | (uint32_t(tmp[2]) << 8) |
+ (uint32_t(tmp[1]) << 16) | (uint32_t(tmp[0]) << 24);
+ }
+
+ void read_big(std::istream& is, uint64_t& x)
+ {
+ uint8_t tmp[8];
+ is.read(reinterpret_cast<char*>(tmp), 8);
+ x = uint64_t(tmp[7]) | (uint64_t(tmp[6]) << 8) |
+ (uint64_t(tmp[5]) << 16) | (uint64_t(tmp[4]) << 24) |
+ (uint64_t(tmp[3]) << 32) | (uint64_t(tmp[2]) << 40) |
+ (uint64_t(tmp[1]) << 48) | (uint64_t(tmp[0]) << 56);
+ }
+
+ void read_big(std::istream& is, int8_t& x)
+ {
+ read_big(is, reinterpret_cast<uint8_t&>(x));
+ }
+ void read_big(std::istream& is, int16_t& x)
+ {
+ read_big(is, reinterpret_cast<uint16_t&>(x));
+ }
+ void read_big(std::istream& is, int32_t& x)
+ {
+ read_big(is, reinterpret_cast<uint32_t&>(x));
+ }
+ void read_big(std::istream& is, int64_t& x)
+ {
+ read_big(is, reinterpret_cast<uint64_t&>(x));
+ }
+
+ void read_big(std::istream& is, float& x)
+ {
+ uint32_t tmp;
+ read_big(is, tmp);
+ pun_int_to_float(x, tmp);
+ }
+
+ void read_big(std::istream& is, double& x)
+ {
+ uint64_t tmp;
+ read_big(is, tmp);
+ pun_int_to_double(x, tmp);
+ }
+
+ //------------------------------------------------------------------------------
+
+ void write_little(std::ostream& os, uint8_t x)
+ {
+ os.put(x);
+ }
+
+ void write_little(std::ostream& os, uint16_t x)
+ {
+ uint8_t tmp[2]{uint8_t(x), uint8_t(x >> 8)};
+ os.write(reinterpret_cast<const char*>(tmp), 2);
+ }
+
+ void write_little(std::ostream& os, uint32_t x)
+ {
+ uint8_t tmp[4]{uint8_t(x), uint8_t(x >> 8), uint8_t(x >> 16),
+ uint8_t(x >> 24)};
+ os.write(reinterpret_cast<const char*>(tmp), 4);
+ }
+
+ void write_little(std::ostream& os, uint64_t x)
+ {
+ uint8_t tmp[8]{uint8_t(x), uint8_t(x >> 8), uint8_t(x >> 16),
+ uint8_t(x >> 24), uint8_t(x >> 32), uint8_t(x >> 40),
+ uint8_t(x >> 48), uint8_t(x >> 56)};
+ os.write(reinterpret_cast<const char*>(tmp), 8);
+ }
+
+ void write_little(std::ostream& os, int8_t x)
+ {
+ write_little(os, static_cast<uint8_t>(x));
+ }
+ void write_little(std::ostream& os, int16_t x)
+ {
+ write_little(os, static_cast<uint16_t>(x));
+ }
+ void write_little(std::ostream& os, int32_t x)
+ {
+ write_little(os, static_cast<uint32_t>(x));
+ }
+ void write_little(std::ostream& os, int64_t x)
+ {
+ write_little(os, static_cast<uint64_t>(x));
+ }
+
+ void write_little(std::ostream& os, float x)
+ {
+ write_little(os, pun_float_to_int(x));
+ }
+
+ void write_little(std::ostream& os, double x)
+ {
+ write_little(os, pun_double_to_int(x));
+ }
+
+ //------------------------------------------------------------------------------
+
+ void write_big(std::ostream& os, uint8_t x)
+ {
+ os.put(x);
+ }
+
+ void write_big(std::ostream& os, uint16_t x)
+ {
+ uint8_t tmp[2]{uint8_t(x >> 8), uint8_t(x)};
+ os.write(reinterpret_cast<const char*>(tmp), 2);
+ }
+
+ void write_big(std::ostream& os, uint32_t x)
+ {
+ uint8_t tmp[4]{uint8_t(x >> 24), uint8_t(x >> 16), uint8_t(x >> 8),
+ uint8_t(x)};
+ os.write(reinterpret_cast<const char*>(tmp), 4);
+ }
+
+ void write_big(std::ostream& os, uint64_t x)
+ {
+ uint8_t tmp[8]{uint8_t(x >> 56), uint8_t(x >> 48), uint8_t(x >> 40),
+ uint8_t(x >> 32), uint8_t(x >> 24), uint8_t(x >> 16),
+ uint8_t(x >> 8), uint8_t(x)};
+ os.write(reinterpret_cast<const char*>(tmp), 8);
+ }
+
+ void write_big(std::ostream& os, int8_t x)
+ {
+ write_big(os, static_cast<uint8_t>(x));
+ }
+ void write_big(std::ostream& os, int16_t x)
+ {
+ write_big(os, static_cast<uint16_t>(x));
+ }
+ void write_big(std::ostream& os, int32_t x)
+ {
+ write_big(os, static_cast<uint32_t>(x));
+ }
+ void write_big(std::ostream& os, int64_t x)
+ {
+ write_big(os, static_cast<uint64_t>(x));
+ }
+
+ void write_big(std::ostream& os, float x)
+ {
+ write_big(os, pun_float_to_int(x));
+ }
+
+ void write_big(std::ostream& os, double x)
+ {
+ write_big(os, pun_double_to_int(x));
+ }
+
+} // namespace endian
diff --git a/src/io/izlibstream.cpp b/src/io/izlibstream.cpp
index b361971081..9d57545360 100644
--- a/src/io/izlibstream.cpp
+++ b/src/io/izlibstream.cpp
@@ -27,76 +27,75 @@
namespace zlib
{
-inflate_streambuf::inflate_streambuf(std::istream& input, size_t bufsize, int window_bits):
- zlib_streambuf(bufsize), is(input), stream_end(false)
-{
- zstr.next_in = Z_NULL;
- zstr.avail_in = 0;
- int ret = inflateInit2(&zstr, window_bits);
- if(ret != Z_OK)
- throw zlib_error(zstr.msg, ret);
+ inflate_streambuf::inflate_streambuf(std::istream& input, size_t bufsize,
+ int window_bits)
+ : zlib_streambuf(bufsize), is(input), stream_end(false)
+ {
+ zstr.next_in = Z_NULL;
+ zstr.avail_in = 0;
+ int ret = inflateInit2(&zstr, window_bits);
+ if (ret != Z_OK)
+ throw zlib_error(zstr.msg, ret);
- char* end = out.data() + out.size();
- setg(end, end, end);
-}
+ char* end = out.data() + out.size();
+ setg(end, end, end);
+ }
-inflate_streambuf::~inflate_streambuf() noexcept
-{
- inflateEnd(&zstr);
-}
+ inflate_streambuf::~inflate_streambuf() noexcept
+ {
+ inflateEnd(&zstr);
+ }
-inflate_streambuf::int_type inflate_streambuf::underflow()
-{
- if(gptr() < egptr())
- return traits_type::to_int_type(*gptr());
+ inflate_streambuf::int_type inflate_streambuf::underflow()
+ {
+ if (gptr() < egptr())
+ return traits_type::to_int_type(*gptr());
- size_t have;
- do
- {
- //Read if input buffer is empty
- if(zstr.avail_in <= 0)
- {
- is.read(in.data(), in.size());
- if(is.bad())
- throw std::ios_base::failure("Input stream is bad");
- size_t count = is.gcount();
- if(count == 0 && !stream_end)
- throw zlib_error("Unexpected end of stream", Z_DATA_ERROR);
+ size_t have;
+ do {
+ // Read if input buffer is empty
+ if (zstr.avail_in <= 0) {
+ is.read(in.data(), in.size());
+ if (is.bad())
+ throw std::ios_base::failure("Input stream is bad");
+ size_t count = is.gcount();
+ if (count == 0 && !stream_end)
+ throw zlib_error("Unexpected end of stream", Z_DATA_ERROR);
- zstr.next_in = reinterpret_cast<Bytef*>(in.data());
- zstr.avail_in = count;
- }
+ zstr.next_in = reinterpret_cast<Bytef*>(in.data());
+ zstr.avail_in = count;
+ }
- zstr.next_out = reinterpret_cast<Bytef*>(out.data());
- zstr.avail_out = out.size();
+ zstr.next_out = reinterpret_cast<Bytef*>(out.data());
+ zstr.avail_out = out.size();
- int ret = inflate(&zstr, Z_NO_FLUSH);
- have = out.size() - zstr.avail_out;
- switch(ret)
- {
- case Z_NEED_DICT:
- case Z_DATA_ERROR:
- throw zlib_error(zstr.msg, ret);
+ int ret = inflate(&zstr, Z_NO_FLUSH);
+ have = out.size() - zstr.avail_out;
+ switch (ret) {
+ case Z_NEED_DICT:
+ case Z_DATA_ERROR:
+ throw zlib_error(zstr.msg, ret);
- case Z_MEM_ERROR:
- throw std::bad_alloc();
+ case Z_MEM_ERROR:
+ throw std::bad_alloc();
- case Z_STREAM_END:
- if(!stream_end)
- {
- stream_end = true;
- //In case we consumed too much, we have to rewind the input stream
- is.clear();
- is.seekg(-static_cast<std::streamoff>(zstr.avail_in), std::ios_base::cur);
- }
- if(have == 0)
- return traits_type::eof();
- break;
- }
- } while(have == 0);
+ case Z_STREAM_END:
+ if (!stream_end) {
+ stream_end = true;
+ // In case we consumed too much, we have to rewind the
+ // input stream
+ is.clear();
+ is.seekg(-static_cast<std::streamoff>(zstr.avail_in),
+ std::ios_base::cur);
+ }
+ if (have == 0)
+ return traits_type::eof();
+ break;
+ }
+ } while (have == 0);
- setg(out.data(), out.data(), out.data() + have);
- return traits_type::to_int_type(*gptr());
-}
+ setg(out.data(), out.data(), out.data() + have);
+ return traits_type::to_int_type(*gptr());
+ }
-}
+} // namespace zlib
diff --git a/src/io/ozlibstream.cpp b/src/io/ozlibstream.cpp
index eefe38a91c..c8a3e862a1 100644
--- a/src/io/ozlibstream.cpp
+++ b/src/io/ozlibstream.cpp
@@ -27,93 +27,88 @@
namespace zlib
{
-deflate_streambuf::deflate_streambuf(std::ostream& output, size_t bufsize, int level, int window_bits, int mem_level, int strategy):
- zlib_streambuf(bufsize), os(output)
-{
- int ret = deflateInit2(&zstr, level, Z_DEFLATED, window_bits, mem_level, strategy);
- if(ret != Z_OK)
- throw zlib_error(zstr.msg, ret);
+ deflate_streambuf::deflate_streambuf(std::ostream& output, size_t bufsize,
+ int level, int window_bits,
+ int mem_level, int strategy)
+ : zlib_streambuf(bufsize), os(output)
+ {
+ int ret = deflateInit2(&zstr, level, Z_DEFLATED, window_bits, mem_level,
+ strategy);
+ if (ret != Z_OK)
+ throw zlib_error(zstr.msg, ret);
- setp(in.data(), in.data() + in.size());
-}
+ setp(in.data(), in.data() + in.size());
+ }
-deflate_streambuf::~deflate_streambuf() noexcept
-{
- try
- {
- close();
- }
- catch(...)
- {
- //ignore as we can't do anything about it
- }
- deflateEnd(&zstr);
-}
+ deflate_streambuf::~deflate_streambuf() noexcept
+ {
+ try {
+ close();
+ } catch (...) {
+ // ignore as we can't do anything about it
+ }
+ deflateEnd(&zstr);
+ }
-void deflate_streambuf::close()
-{
- deflate_chunk(Z_FINISH);
-}
+ void deflate_streambuf::close()
+ {
+ deflate_chunk(Z_FINISH);
+ }
-void deflate_streambuf::deflate_chunk(int flush)
-{
- zstr.next_in = reinterpret_cast<Bytef*>(pbase());
- zstr.avail_in = pptr() - pbase();
- do
- {
- zstr.next_out = reinterpret_cast<Bytef*>(out.data());
- zstr.avail_out = out.size();
- int ret = deflate(&zstr, flush);
- if(ret != Z_OK && ret != Z_STREAM_END)
- {
- os.setstate(std::ios_base::failbit);
- throw zlib_error(zstr.msg, ret);
- }
- int have = out.size() - zstr.avail_out;
- if(!os.write(out.data(), have))
- throw std::ios_base::failure("Could not write to the output stream");
- } while(zstr.avail_out == 0);
- setp(in.data(), in.data() + in.size());
-}
+ void deflate_streambuf::deflate_chunk(int flush)
+ {
+ zstr.next_in = reinterpret_cast<Bytef*>(pbase());
+ zstr.avail_in = pptr() - pbase();
+ do {
+ zstr.next_out = reinterpret_cast<Bytef*>(out.data());
+ zstr.avail_out = out.size();
+ int ret = deflate(&zstr, flush);
+ if (ret != Z_OK && ret != Z_STREAM_END) {
+ os.setstate(std::ios_base::failbit);
+ throw zlib_error(zstr.msg, ret);
+ }
+ int have = out.size() - zstr.avail_out;
+ if (!os.write(out.data(), have))
+ throw std::ios_base::failure(
+ "Could not write to the output stream");
+ } while (zstr.avail_out == 0);
+ setp(in.data(), in.data() + in.size());
+ }
-deflate_streambuf::int_type deflate_streambuf::overflow(int_type ch)
-{
- deflate_chunk();
- if(ch != traits_type::eof())
- {
- *pptr() = ch;
- pbump(1);
- }
- return ch;
-}
+ deflate_streambuf::int_type deflate_streambuf::overflow(int_type ch)
+ {
+ deflate_chunk();
+ if (ch != traits_type::eof()) {
+ *pptr() = ch;
+ pbump(1);
+ }
+ return ch;
+ }
-int deflate_streambuf::sync()
-{
- deflate_chunk();
- return 0;
-}
+ int deflate_streambuf::sync()
+ {
+ deflate_chunk();
+ return 0;
+ }
-void ozlibstream::close()
-{
- // Capture the exception mask so we can restore it if close() fails.
- std::ios_base::iostate old_ex = exceptions();
- try
- {
- buf.close();
- return;
- }
- catch(...)
- {
- // fall through to mark the stream as bad
- }
+ void ozlibstream::close()
+ {
+ // Capture the exception mask so we can restore it if close() fails.
+ std::ios_base::iostate old_ex = exceptions();
+ try {
+ buf.close();
+ return;
+ } catch (...) {
+ // fall through to mark the stream as bad
+ }
- // Setting the stream state while exceptions are enabled may cause
- // `setstate` to throw an `ios_base::failure` which would replace
- // the original exception. Temporarily disable exceptions on this
- // stream, set the `badbit`, then restore the exception mask.
- exceptions(std::ios_base::goodbit);
- setstate(std::ios_base::badbit);
- exceptions(old_ex);
-}
+ // Setting the stream state while exceptions are enabled may cause
+ // `setstate` to throw an `ios_base::failure` which would replace
+ // the original exception. Temporarily disable exceptions on this
+ // stream, set the `badbit`, then restore the exception mask.
+ exceptions(std::ios_base::goodbit);
+ setstate(std::ios_base::badbit);
+ exceptions(old_ex);
+ }
} // namespace zlib
diff --git a/src/io/stream_reader.cpp b/src/io/stream_reader.cpp
index 06375ca0d5..43032b1120 100644
--- a/src/io/stream_reader.cpp
+++ b/src/io/stream_reader.cpp
@@ -28,92 +28,95 @@
namespace nbt
{
-namespace io
-{
+ namespace io
+ {
-static constexpr int MAX_DEPTH = 1024;
+ static constexpr int MAX_DEPTH = 1024;
-std::pair<std::string, std::unique_ptr<tag_compound>> read_compound(std::istream& is, endian::endian e)
-{
- return stream_reader(is, e).read_compound();
-}
+ std::pair<std::string, std::unique_ptr<tag_compound>>
+ read_compound(std::istream& is, endian::endian e)
+ {
+ return stream_reader(is, e).read_compound();
+ }
-std::pair<std::string, std::unique_ptr<tag>> read_tag(std::istream& is, endian::endian e)
-{
- return stream_reader(is, e).read_tag();
-}
+ std::pair<std::string, std::unique_ptr<tag>> read_tag(std::istream& is,
+ endian::endian e)
+ {
+ return stream_reader(is, e).read_tag();
+ }
-stream_reader::stream_reader(std::istream& is, endian::endian e) noexcept:
- is(is), endian(e)
-{}
+ stream_reader::stream_reader(std::istream& is,
+ endian::endian e) noexcept
+ : is(is), endian(e)
+ {
+ }
-std::istream& stream_reader::get_istr() const
-{
- return is;
-}
+ std::istream& stream_reader::get_istr() const
+ {
+ return is;
+ }
-endian::endian stream_reader::get_endian() const
-{
- return endian;
-}
+ endian::endian stream_reader::get_endian() const
+ {
+ return endian;
+ }
-std::pair<std::string, std::unique_ptr<tag_compound>> stream_reader::read_compound()
-{
- if(read_type() != tag_type::Compound)
- {
- is.setstate(std::ios::failbit);
- throw input_error("Tag is not a compound");
- }
- std::string key = read_string();
- auto comp = make_unique<tag_compound>();
- comp->read_payload(*this);
- return {std::move(key), std::move(comp)};
-}
+ std::pair<std::string, std::unique_ptr<tag_compound>>
+ stream_reader::read_compound()
+ {
+ if (read_type() != tag_type::Compound) {
+ is.setstate(std::ios::failbit);
+ throw input_error("Tag is not a compound");
+ }
+ std::string key = read_string();
+ auto comp = make_unique<tag_compound>();
+ comp->read_payload(*this);
+ return {std::move(key), std::move(comp)};
+ }
-std::pair<std::string, std::unique_ptr<tag>> stream_reader::read_tag()
-{
- tag_type type = read_type();
- std::string key = read_string();
- std::unique_ptr<tag> t = read_payload(type);
- return {std::move(key), std::move(t)};
-}
+ std::pair<std::string, std::unique_ptr<tag>> stream_reader::read_tag()
+ {
+ tag_type type = read_type();
+ std::string key = read_string();
+ std::unique_ptr<tag> t = read_payload(type);
+ return {std::move(key), std::move(t)};
+ }
-std::unique_ptr<tag> stream_reader::read_payload(tag_type type)
-{
- if (++depth > MAX_DEPTH)
- throw input_error("Too deeply nested");
- std::unique_ptr<tag> t = tag::create(type);
- t->read_payload(*this);
- --depth;
- return t;
-}
+ std::unique_ptr<tag> stream_reader::read_payload(tag_type type)
+ {
+ if (++depth > MAX_DEPTH)
+ throw input_error("Too deeply nested");
+ std::unique_ptr<tag> t = tag::create(type);
+ t->read_payload(*this);
+ --depth;
+ return t;
+ }
-tag_type stream_reader::read_type(bool allow_end)
-{
- int type = is.get();
- if(!is)
- throw input_error("Error reading tag type");
- if(!is_valid_type(type, allow_end))
- {
- is.setstate(std::ios::failbit);
- throw input_error("Invalid tag type: " + std::to_string(type));
- }
- return static_cast<tag_type>(type);
-}
+ tag_type stream_reader::read_type(bool allow_end)
+ {
+ int type = is.get();
+ if (!is)
+ throw input_error("Error reading tag type");
+ if (!is_valid_type(type, allow_end)) {
+ is.setstate(std::ios::failbit);
+ throw input_error("Invalid tag type: " + std::to_string(type));
+ }
+ return static_cast<tag_type>(type);
+ }
-std::string stream_reader::read_string()
-{
- uint16_t len;
- read_num(len);
- if(!is)
- throw input_error("Error reading string");
+ std::string stream_reader::read_string()
+ {
+ uint16_t len;
+ read_num(len);
+ if (!is)
+ throw input_error("Error reading string");
- std::string ret(len, '\0');
- is.read(&ret[0], len); //C++11 allows us to do this
- if(!is)
- throw input_error("Error reading string");
- return ret;
-}
+ std::string ret(len, '\0');
+ is.read(&ret[0], len); // C++11 allows us to do this
+ if (!is)
+ throw input_error("Error reading string");
+ return ret;
+ }
-}
-}
+ } // namespace io
+} // namespace nbt
diff --git a/src/io/stream_writer.cpp b/src/io/stream_writer.cpp
index 0294a6d4e9..5275c5a1b4 100644
--- a/src/io/stream_writer.cpp
+++ b/src/io/stream_writer.cpp
@@ -26,33 +26,34 @@
namespace nbt
{
-namespace io
-{
+ namespace io
+ {
-void write_tag(const std::string& key, const tag& t, std::ostream& os, endian::endian e)
-{
- stream_writer(os, e).write_tag(key, t);
-}
+ void write_tag(const std::string& key, const tag& t, std::ostream& os,
+ endian::endian e)
+ {
+ stream_writer(os, e).write_tag(key, t);
+ }
-void stream_writer::write_tag(const std::string& key, const tag& t)
-{
- write_type(t.get_type());
- write_string(key);
- write_payload(t);
-}
+ void stream_writer::write_tag(const std::string& key, const tag& t)
+ {
+ write_type(t.get_type());
+ write_string(key);
+ write_payload(t);
+ }
-void stream_writer::write_string(const std::string& str)
-{
- if(str.size() > max_string_len)
- {
- os.setstate(std::ios::failbit);
- std::ostringstream sstr;
- sstr << "String is too long for NBT (" << str.size() << " > " << max_string_len << ")";
- throw std::length_error(sstr.str());
- }
- write_num(static_cast<uint16_t>(str.size()));
- os.write(str.data(), str.size());
-}
+ void stream_writer::write_string(const std::string& str)
+ {
+ if (str.size() > max_string_len) {
+ os.setstate(std::ios::failbit);
+ std::ostringstream sstr;
+ sstr << "String is too long for NBT (" << str.size() << " > "
+ << max_string_len << ")";
+ throw std::length_error(sstr.str());
+ }
+ write_num(static_cast<uint16_t>(str.size()));
+ os.write(str.data(), str.size());
+ }
-}
-}
+ } // namespace io
+} // namespace nbt
diff --git a/src/tag.cpp b/src/tag.cpp
index 0446dfd3f8..8e57548f2d 100644
--- a/src/tag.cpp
+++ b/src/tag.cpp
@@ -32,136 +32,170 @@
namespace nbt
{
-//Explicit instantiation definitions for tag_primitive
-template class tag_primitive<int8_t>;
-template class tag_primitive<int16_t>;
-template class tag_primitive<int32_t>;
-template class tag_primitive<int64_t>;
-template class tag_primitive<float>;
-template class tag_primitive<double>;
-
-static_assert(std::numeric_limits<float>::is_iec559 && std::numeric_limits<double>::is_iec559,
- "The floating point values for NBT must conform to IEC 559/IEEE 754");
-
-bool is_valid_type(int type, bool allow_end)
-{
- return (allow_end ? 0 : 1) <= type && type <= 12;
-}
-
-std::unique_ptr<tag> tag::clone() &&
-{
- return std::move(*this).move_clone();
-}
-
-namespace
-{
- template<typename T>
- std::unique_ptr<tag> create_numeric_tag(tag_type type, T val)
- {
- switch(type)
- {
- case tag_type::Byte: return make_unique<tag_byte>(static_cast<int8_t>(val));
- case tag_type::Short: return make_unique<tag_short>(static_cast<int16_t>(val));
- case tag_type::Int: return make_unique<tag_int>(static_cast<int32_t>(val));
- case tag_type::Long: return make_unique<tag_long>(static_cast<int64_t>(val));
- case tag_type::Float: return make_unique<tag_float>(static_cast<float>(val));
- case tag_type::Double: return make_unique<tag_double>(static_cast<double>(val));
- default: throw std::invalid_argument("Invalid numeric tag type");
- }
- }
-}
-
-std::unique_ptr<tag> tag::create(tag_type type)
-{
- switch(type)
- {
- case tag_type::Byte: return make_unique<tag_byte>();
- case tag_type::Short: return make_unique<tag_short>();
- case tag_type::Int: return make_unique<tag_int>();
- case tag_type::Long: return make_unique<tag_long>();
- case tag_type::Float: return make_unique<tag_float>();
- case tag_type::Double: return make_unique<tag_double>();
- case tag_type::Byte_Array: return make_unique<tag_byte_array>();
- case tag_type::String: return make_unique<tag_string>();
- case tag_type::List: return make_unique<tag_list>();
- case tag_type::Compound: return make_unique<tag_compound>();
- case tag_type::Int_Array: return make_unique<tag_int_array>();
- case tag_type::Long_Array: return make_unique<tag_long_array>();
-
- default: throw std::invalid_argument("Invalid tag type");
- }
-}
-
-std::unique_ptr<tag> tag::create(tag_type type, int8_t val)
-{
- return create_numeric_tag(type, val);
-}
-
-std::unique_ptr<tag> tag::create(tag_type type, int16_t val)
-{
- return create_numeric_tag(type, val);
-}
-
-std::unique_ptr<tag> tag::create(tag_type type, int32_t val)
-{
- return create_numeric_tag(type, val);
-}
-
-std::unique_ptr<tag> tag::create(tag_type type, int64_t val)
-{
- return create_numeric_tag(type, val);
-}
-
-std::unique_ptr<tag> tag::create(tag_type type, float val)
-{
- return create_numeric_tag(type, val);
-}
-
-std::unique_ptr<tag> tag::create(tag_type type, double val)
-{
- return create_numeric_tag(type, val);
-}
-
-bool operator==(const tag& lhs, const tag& rhs)
-{
- if(typeid(lhs) != typeid(rhs))
- return false;
- return lhs.equals(rhs);
-}
-
-bool operator!=(const tag& lhs, const tag& rhs)
-{
- return !(lhs == rhs);
-}
-
-std::ostream& operator<<(std::ostream& os, tag_type tt)
-{
- switch(tt)
- {
- case tag_type::End: return os << "end";
- case tag_type::Byte: return os << "byte";
- case tag_type::Short: return os << "short";
- case tag_type::Int: return os << "int";
- case tag_type::Long: return os << "long";
- case tag_type::Float: return os << "float";
- case tag_type::Double: return os << "double";
- case tag_type::Byte_Array: return os << "byte_array";
- case tag_type::String: return os << "string";
- case tag_type::List: return os << "list";
- case tag_type::Compound: return os << "compound";
- case tag_type::Int_Array: return os << "int_array";
- case tag_type::Long_Array: return os << "long_array";
- case tag_type::Null: return os << "null";
-
- default: return os << "invalid";
- }
-}
-
-std::ostream& operator<<(std::ostream& os, const tag& t)
-{
- static const text::json_formatter formatter;
- formatter.print(os, t);
- return os;
-}
-
-}
+ // Explicit instantiation definitions for tag_primitive
+ template class tag_primitive<int8_t>;
+ template class tag_primitive<int16_t>;
+ template class tag_primitive<int32_t>;
+ template class tag_primitive<int64_t>;
+ template class tag_primitive<float>;
+ template class tag_primitive<double>;
+
+ static_assert(
+ std::numeric_limits<float>::is_iec559 &&
+ std::numeric_limits<double>::is_iec559,
+ "The floating point values for NBT must conform to IEC 559/IEEE 754");
+
+ bool is_valid_type(int type, bool allow_end)
+ {
+ return (allow_end ? 0 : 1) <= type && type <= 12;
+ }
+
+ std::unique_ptr<tag> tag::clone() &&
+ {
+ return std::move(*this).move_clone();
+ }
+
+ namespace
+ {
+ template <typename T>
+ std::unique_ptr<tag> create_numeric_tag(tag_type type, T val)
+ {
+ switch (type) {
+ case tag_type::Byte:
+ return make_unique<tag_byte>(static_cast<int8_t>(val));
+ case tag_type::Short:
+ return make_unique<tag_short>(static_cast<int16_t>(val));
+ case tag_type::Int:
+ return make_unique<tag_int>(static_cast<int32_t>(val));
+ case tag_type::Long:
+ return make_unique<tag_long>(static_cast<int64_t>(val));
+ case tag_type::Float:
+ return make_unique<tag_float>(static_cast<float>(val));
+ case tag_type::Double:
+ return make_unique<tag_double>(static_cast<double>(val));
+ default:
+ throw std::invalid_argument("Invalid numeric tag type");
+ }
+ }
+ } // namespace
+
+ std::unique_ptr<tag> tag::create(tag_type type)
+ {
+ switch (type) {
+ case tag_type::Byte:
+ return make_unique<tag_byte>();
+ case tag_type::Short:
+ return make_unique<tag_short>();
+ case tag_type::Int:
+ return make_unique<tag_int>();
+ case tag_type::Long:
+ return make_unique<tag_long>();
+ case tag_type::Float:
+ return make_unique<tag_float>();
+ case tag_type::Double:
+ return make_unique<tag_double>();
+ case tag_type::Byte_Array:
+ return make_unique<tag_byte_array>();
+ case tag_type::String:
+ return make_unique<tag_string>();
+ case tag_type::List:
+ return make_unique<tag_list>();
+ case tag_type::Compound:
+ return make_unique<tag_compound>();
+ case tag_type::Int_Array:
+ return make_unique<tag_int_array>();
+ case tag_type::Long_Array:
+ return make_unique<tag_long_array>();
+
+ default:
+ throw std::invalid_argument("Invalid tag type");
+ }
+ }
+
+ std::unique_ptr<tag> tag::create(tag_type type, int8_t val)
+ {
+ return create_numeric_tag(type, val);
+ }
+
+ std::unique_ptr<tag> tag::create(tag_type type, int16_t val)
+ {
+ return create_numeric_tag(type, val);
+ }
+
+ std::unique_ptr<tag> tag::create(tag_type type, int32_t val)
+ {
+ return create_numeric_tag(type, val);
+ }
+
+ std::unique_ptr<tag> tag::create(tag_type type, int64_t val)
+ {
+ return create_numeric_tag(type, val);
+ }
+
+ std::unique_ptr<tag> tag::create(tag_type type, float val)
+ {
+ return create_numeric_tag(type, val);
+ }
+
+ std::unique_ptr<tag> tag::create(tag_type type, double val)
+ {
+ return create_numeric_tag(type, val);
+ }
+
+ bool operator==(const tag& lhs, const tag& rhs)
+ {
+ if (typeid(lhs) != typeid(rhs))
+ return false;
+ return lhs.equals(rhs);
+ }
+
+ bool operator!=(const tag& lhs, const tag& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+ std::ostream& operator<<(std::ostream& os, tag_type tt)
+ {
+ switch (tt) {
+ case tag_type::End:
+ return os << "end";
+ case tag_type::Byte:
+ return os << "byte";
+ case tag_type::Short:
+ return os << "short";
+ case tag_type::Int:
+ return os << "int";
+ case tag_type::Long:
+ return os << "long";
+ case tag_type::Float:
+ return os << "float";
+ case tag_type::Double:
+ return os << "double";
+ case tag_type::Byte_Array:
+ return os << "byte_array";
+ case tag_type::String:
+ return os << "string";
+ case tag_type::List:
+ return os << "list";
+ case tag_type::Compound:
+ return os << "compound";
+ case tag_type::Int_Array:
+ return os << "int_array";
+ case tag_type::Long_Array:
+ return os << "long_array";
+ case tag_type::Null:
+ return os << "null";
+
+ default:
+ return os << "invalid";
+ }
+ }
+
+ std::ostream& operator<<(std::ostream& os, const tag& t)
+ {
+ static const text::json_formatter formatter;
+ formatter.print(os, t);
+ return os;
+ }
+
+} // namespace nbt
diff --git a/src/tag_compound.cpp b/src/tag_compound.cpp
index c71166de95..c35ef5d53f 100644
--- a/src/tag_compound.cpp
+++ b/src/tag_compound.cpp
@@ -30,84 +30,80 @@
namespace nbt
{
-tag_compound::tag_compound(std::initializer_list<std::pair<std::string, value_initializer>> init)
-{
- for(const auto& pair: init)
- tags.emplace(std::move(pair.first), std::move(pair.second));
-}
+ tag_compound::tag_compound(
+ std::initializer_list<std::pair<std::string, value_initializer>> init)
+ {
+ for (const auto& pair : init)
+ tags.emplace(std::move(pair.first), std::move(pair.second));
+ }
-value& tag_compound::at(const std::string& key)
-{
- return tags.at(key);
-}
+ value& tag_compound::at(const std::string& key)
+ {
+ return tags.at(key);
+ }
-const value& tag_compound::at(const std::string& key) const
-{
- return tags.at(key);
-}
+ const value& tag_compound::at(const std::string& key) const
+ {
+ return tags.at(key);
+ }
-std::pair<tag_compound::iterator, bool> tag_compound::put(const std::string& key, value_initializer&& val)
-{
- auto it = tags.find(key);
- if(it != tags.end())
- {
- it->second = std::move(val);
- return {it, false};
- }
- else
- {
- return tags.emplace(key, std::move(val));
- }
-}
+ std::pair<tag_compound::iterator, bool>
+ tag_compound::put(const std::string& key, value_initializer&& val)
+ {
+ auto it = tags.find(key);
+ if (it != tags.end()) {
+ it->second = std::move(val);
+ return {it, false};
+ } else {
+ return tags.emplace(key, std::move(val));
+ }
+ }
-std::pair<tag_compound::iterator, bool> tag_compound::insert(const std::string& key, value_initializer&& val)
-{
- return tags.emplace(key, std::move(val));
-}
+ std::pair<tag_compound::iterator, bool>
+ tag_compound::insert(const std::string& key, value_initializer&& val)
+ {
+ return tags.emplace(key, std::move(val));
+ }
-bool tag_compound::erase(const std::string& key)
-{
- return tags.erase(key) != 0;
-}
+ bool tag_compound::erase(const std::string& key)
+ {
+ return tags.erase(key) != 0;
+ }
-bool tag_compound::has_key(const std::string& key) const
-{
- return tags.find(key) != tags.end();
-}
+ bool tag_compound::has_key(const std::string& key) const
+ {
+ return tags.find(key) != tags.end();
+ }
-bool tag_compound::has_key(const std::string& key, tag_type type) const
-{
- auto it = tags.find(key);
- return it != tags.end() && it->second.get_type() == type;
-}
+ bool tag_compound::has_key(const std::string& key, tag_type type) const
+ {
+ auto it = tags.find(key);
+ return it != tags.end() && it->second.get_type() == type;
+ }
-void tag_compound::read_payload(io::stream_reader& reader)
-{
- clear();
- tag_type tt;
- while((tt = reader.read_type(true)) != tag_type::End)
- {
- std::string key;
- try
- {
- key = reader.read_string();
- }
- catch(io::input_error& ex)
- {
- std::ostringstream str;
- str << "Error reading key of tag_" << tt;
- throw io::input_error(str.str());
- }
- auto tptr = reader.read_payload(tt);
- tags.emplace(std::move(key), value(std::move(tptr)));
- }
-}
+ void tag_compound::read_payload(io::stream_reader& reader)
+ {
+ clear();
+ tag_type tt;
+ while ((tt = reader.read_type(true)) != tag_type::End) {
+ std::string key;
+ try {
+ key = reader.read_string();
+ } catch (io::input_error& ex) {
+ std::ostringstream str;
+ str << "Error reading key of tag_" << tt;
+ throw io::input_error(str.str());
+ }
+ auto tptr = reader.read_payload(tt);
+ tags.emplace(std::move(key), value(std::move(tptr)));
+ }
+ }
-void tag_compound::write_payload(io::stream_writer& writer) const
-{
- for(const auto& pair: tags)
- writer.write_tag(pair.first, pair.second);
- writer.write_type(tag_type::End);
-}
+ void tag_compound::write_payload(io::stream_writer& writer) const
+ {
+ for (const auto& pair : tags)
+ writer.write_tag(pair.first, pair.second);
+ writer.write_type(tag_type::End);
+ }
-}
+} // namespace nbt
diff --git a/src/tag_list.cpp b/src/tag_list.cpp
index f72f86bb24..413af779ae 100644
--- a/src/tag_list.cpp
+++ b/src/tag_list.cpp
@@ -30,126 +30,158 @@
namespace nbt
{
-tag_list::tag_list(std::initializer_list<int8_t> il) { init<tag_byte>(il); }
-tag_list::tag_list(std::initializer_list<int16_t> il) { init<tag_short>(il); }
-tag_list::tag_list(std::initializer_list<int32_t> il) { init<tag_int>(il); }
-tag_list::tag_list(std::initializer_list<int64_t> il) { init<tag_long>(il); }
-tag_list::tag_list(std::initializer_list<float> il) { init<tag_float>(il); }
-tag_list::tag_list(std::initializer_list<double> il) { init<tag_double>(il); }
-tag_list::tag_list(std::initializer_list<std::string> il) { init<tag_string>(il); }
-tag_list::tag_list(std::initializer_list<tag_byte_array> il) { init<tag_byte_array>(il); }
-tag_list::tag_list(std::initializer_list<tag_list> il) { init<tag_list>(il); }
-tag_list::tag_list(std::initializer_list<tag_compound> il) { init<tag_compound>(il); }
-tag_list::tag_list(std::initializer_list<tag_int_array> il) { init<tag_int_array>(il); }
-tag_list::tag_list(std::initializer_list<tag_long_array> il) { init<tag_long_array>(il); }
-
-tag_list::tag_list(std::initializer_list<value> init)
-{
- if(init.size() == 0)
- el_type_ = tag_type::Null;
- else
- {
- el_type_ = init.begin()->get_type();
- for(const value& val: init)
- {
- if(!val || val.get_type() != el_type_)
- throw std::invalid_argument("The values are not all the same type");
- }
- tags.assign(init.begin(), init.end());
- }
-}
-
-value& tag_list::at(size_t i)
-{
- return tags.at(i);
-}
-
-const value& tag_list::at(size_t i) const
-{
- return tags.at(i);
-}
-
-void tag_list::set(size_t i, value&& val)
-{
- if(val.get_type() != el_type_)
- throw std::invalid_argument("The tag type does not match the list's content type");
- tags.at(i) = std::move(val);
-}
-
-void tag_list::push_back(value_initializer&& val)
-{
- if(!val) //don't allow null values
- throw std::invalid_argument("The value must not be null");
- if(el_type_ == tag_type::Null) //set content type if undetermined
- el_type_ = val.get_type();
- else if(el_type_ != val.get_type())
- throw std::invalid_argument("The tag type does not match the list's content type");
- tags.push_back(std::move(val));
-}
-
-void tag_list::reset(tag_type type)
-{
- clear();
- el_type_ = type;
-}
-
-void tag_list::read_payload(io::stream_reader& reader)
-{
- tag_type lt = reader.read_type(true);
-
- int32_t length;
- reader.read_num(length);
- if(length < 0)
- reader.get_istr().setstate(std::ios::failbit);
- if(!reader.get_istr())
- throw io::input_error("Error reading length of tag_list");
-
- if(lt != tag_type::End)
- {
- reset(lt);
- tags.reserve(length);
-
- for(int32_t i = 0; i < length; ++i)
- tags.emplace_back(reader.read_payload(lt));
- }
- else
- {
- //In case of tag_end, ignore the length and leave the type undetermined
- reset(tag_type::Null);
- }
-}
-
-void tag_list::write_payload(io::stream_writer& writer) const
-{
- if(size() > io::stream_writer::max_array_len)
- {
- writer.get_ostr().setstate(std::ios::failbit);
- throw std::length_error("List is too large for NBT");
- }
- writer.write_type(el_type_ != tag_type::Null
- ? el_type_
- : tag_type::End);
- writer.write_num(static_cast<int32_t>(size()));
- for(const auto& val: tags)
- {
- //check if the value is of the correct type
- if(val.get_type() != el_type_)
- {
- writer.get_ostr().setstate(std::ios::failbit);
- throw std::logic_error("The tags in the list do not all match the content type");
- }
- writer.write_payload(val);
- }
-}
-
-bool operator==(const tag_list& lhs, const tag_list& rhs)
-{
- return lhs.el_type_ == rhs.el_type_ && lhs.tags == rhs.tags;
-}
-
-bool operator!=(const tag_list& lhs, const tag_list& rhs)
-{
- return !(lhs == rhs);
-}
-
-}
+ tag_list::tag_list(std::initializer_list<int8_t> il)
+ {
+ init<tag_byte>(il);
+ }
+ tag_list::tag_list(std::initializer_list<int16_t> il)
+ {
+ init<tag_short>(il);
+ }
+ tag_list::tag_list(std::initializer_list<int32_t> il)
+ {
+ init<tag_int>(il);
+ }
+ tag_list::tag_list(std::initializer_list<int64_t> il)
+ {
+ init<tag_long>(il);
+ }
+ tag_list::tag_list(std::initializer_list<float> il)
+ {
+ init<tag_float>(il);
+ }
+ tag_list::tag_list(std::initializer_list<double> il)
+ {
+ init<tag_double>(il);
+ }
+ tag_list::tag_list(std::initializer_list<std::string> il)
+ {
+ init<tag_string>(il);
+ }
+ tag_list::tag_list(std::initializer_list<tag_byte_array> il)
+ {
+ init<tag_byte_array>(il);
+ }
+ tag_list::tag_list(std::initializer_list<tag_list> il)
+ {
+ init<tag_list>(il);
+ }
+ tag_list::tag_list(std::initializer_list<tag_compound> il)
+ {
+ init<tag_compound>(il);
+ }
+ tag_list::tag_list(std::initializer_list<tag_int_array> il)
+ {
+ init<tag_int_array>(il);
+ }
+ tag_list::tag_list(std::initializer_list<tag_long_array> il)
+ {
+ init<tag_long_array>(il);
+ }
+
+ tag_list::tag_list(std::initializer_list<value> init)
+ {
+ if (init.size() == 0)
+ el_type_ = tag_type::Null;
+ else {
+ el_type_ = init.begin()->get_type();
+ for (const value& val : init) {
+ if (!val || val.get_type() != el_type_)
+ throw std::invalid_argument(
+ "The values are not all the same type");
+ }
+ tags.assign(init.begin(), init.end());
+ }
+ }
+
+ value& tag_list::at(size_t i)
+ {
+ return tags.at(i);
+ }
+
+ const value& tag_list::at(size_t i) const
+ {
+ return tags.at(i);
+ }
+
+ void tag_list::set(size_t i, value&& val)
+ {
+ if (val.get_type() != el_type_)
+ throw std::invalid_argument(
+ "The tag type does not match the list's content type");
+ tags.at(i) = std::move(val);
+ }
+
+ void tag_list::push_back(value_initializer&& val)
+ {
+ if (!val) // don't allow null values
+ throw std::invalid_argument("The value must not be null");
+ if (el_type_ == tag_type::Null) // set content type if undetermined
+ el_type_ = val.get_type();
+ else if (el_type_ != val.get_type())
+ throw std::invalid_argument(
+ "The tag type does not match the list's content type");
+ tags.push_back(std::move(val));
+ }
+
+ void tag_list::reset(tag_type type)
+ {
+ clear();
+ el_type_ = type;
+ }
+
+ void tag_list::read_payload(io::stream_reader& reader)
+ {
+ tag_type lt = reader.read_type(true);
+
+ int32_t length;
+ reader.read_num(length);
+ if (length < 0)
+ reader.get_istr().setstate(std::ios::failbit);
+ if (!reader.get_istr())
+ throw io::input_error("Error reading length of tag_list");
+
+ if (lt != tag_type::End) {
+ reset(lt);
+ tags.reserve(length);
+
+ for (int32_t i = 0; i < length; ++i)
+ tags.emplace_back(reader.read_payload(lt));
+ } else {
+ // In case of tag_end, ignore the length and leave the type
+ // undetermined
+ reset(tag_type::Null);
+ }
+ }
+
+ void tag_list::write_payload(io::stream_writer& writer) const
+ {
+ if (size() > io::stream_writer::max_array_len) {
+ writer.get_ostr().setstate(std::ios::failbit);
+ throw std::length_error("List is too large for NBT");
+ }
+ writer.write_type(el_type_ != tag_type::Null ? el_type_
+ : tag_type::End);
+ writer.write_num(static_cast<int32_t>(size()));
+ for (const auto& val : tags) {
+ // check if the value is of the correct type
+ if (val.get_type() != el_type_) {
+ writer.get_ostr().setstate(std::ios::failbit);
+ throw std::logic_error(
+ "The tags in the list do not all match the content type");
+ }
+ writer.write_payload(val);
+ }
+ }
+
+ bool operator==(const tag_list& lhs, const tag_list& rhs)
+ {
+ return lhs.el_type_ == rhs.el_type_ && lhs.tags == rhs.tags;
+ }
+
+ bool operator!=(const tag_list& lhs, const tag_list& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+} // namespace nbt
diff --git a/src/tag_string.cpp b/src/tag_string.cpp
index e630b1dfc4..481ad19dee 100644
--- a/src/tag_string.cpp
+++ b/src/tag_string.cpp
@@ -28,21 +28,18 @@
namespace nbt
{
-void tag_string::read_payload(io::stream_reader& reader)
-{
- try
- {
- value = reader.read_string();
- }
- catch(io::input_error& ex)
- {
- throw io::input_error("Error reading tag_string");
- }
-}
+ void tag_string::read_payload(io::stream_reader& reader)
+ {
+ try {
+ value = reader.read_string();
+ } catch (io::input_error& ex) {
+ throw io::input_error("Error reading tag_string");
+ }
+ }
-void tag_string::write_payload(io::stream_writer& writer) const
-{
- writer.write_string(value);
-}
+ void tag_string::write_payload(io::stream_writer& writer) const
+ {
+ writer.write_string(value);
+ }
-}
+} // namespace nbt
diff --git a/src/text/json_formatter.cpp b/src/text/json_formatter.cpp
index 88f3a7c58e..46d726a3c9 100644
--- a/src/text/json_formatter.cpp
+++ b/src/text/json_formatter.cpp
@@ -30,209 +30,227 @@
namespace nbt
{
-namespace text
-{
+ namespace text
+ {
-namespace //anonymous
-{
- ///Helper class which uses the Visitor pattern to pretty-print tags
- class json_fmt_visitor : public const_nbt_visitor
- {
- public:
- json_fmt_visitor(std::ostream& os):
- os(os)
- {}
-
- void visit(const tag_byte& b) override
- { os << static_cast<int>(b.get()) << "b"; } //We don't want to print a character
-
- void visit(const tag_short& s) override
- { os << s.get() << "s"; }
-
- void visit(const tag_int& i) override
- { os << i.get(); }
-
- void visit(const tag_long& l) override
- { os << l.get() << "l"; }
-
- void visit(const tag_float& f) override
- {
- write_float(f.get());
- os << "f";
- }
-
- void visit(const tag_double& d) override
- {
- write_float(d.get());
- os << "d";
- }
-
- void visit(const tag_byte_array& ba) override
- { os << "[" << ba.size() << " bytes]"; }
-
- void visit(const tag_string& s) override
- {
- os << '"';
- write_escaped_string(s.get());
- os << '"';
- }
-
- void visit(const tag_list& l) override
- {
- //Wrap lines for lists of lists or compounds.
- //Lists of other types can usually be on one line without problem.
- const bool break_lines = l.size() > 0 &&
- (l.el_type() == tag_type::List || l.el_type() == tag_type::Compound);
-
- os << "[";
- if(break_lines)
- {
- os << "\n";
- ++indent_lvl;
- for(unsigned int i = 0; i < l.size(); ++i)
- {
- indent();
- if(l[i])
- l[i].get().accept(*this);
- else
- write_null();
- if(i != l.size()-1)
- os << ",";
- os << "\n";
- }
- --indent_lvl;
- indent();
- }
- else
- {
- for(unsigned int i = 0; i < l.size(); ++i)
- {
- if(l[i])
- l[i].get().accept(*this);
- else
- write_null();
- if(i != l.size()-1)
- os << ", ";
- }
- }
- os << "]";
- }
-
- void visit(const tag_compound& c) override
- {
- if(c.size() == 0) //No line breaks inside empty compounds please
- {
- os << "{}";
- return;
- }
-
- os << "{\n";
- ++indent_lvl;
- unsigned int i = 0;
- for(const auto& kv: c)
- {
- indent();
- os << kv.first << ": ";
- if(kv.second)
- kv.second.get().accept(*this);
- else
- write_null();
- if(i != c.size()-1)
- os << ",";
- os << "\n";
- ++i;
- }
- --indent_lvl;
- indent();
- os << "}";
- }
-
- void visit(const tag_int_array& ia) override
- {
- os << "[";
- for(unsigned int i = 0; i < ia.size(); ++i)
- {
- os << ia[i];
- if(i != ia.size()-1)
- os << ", ";
- }
- os << "]";
- }
-
- void visit(const tag_long_array& la) override
- {
- os << "[";
- for(unsigned int i = 0; i < la.size(); ++i)
- {
- os << la[i];
- if(i != la.size()-1)
- os << ", ";
- }
- os << "]";
- }
-
- private:
- const std::string indent_str = " ";
-
- std::ostream& os;
- int indent_lvl = 0;
-
- void indent()
- {
- for(int i = 0; i < indent_lvl; ++i)
- os << indent_str;
- }
-
- template<class T>
- void write_float(T val, int precision = std::numeric_limits<T>::max_digits10)
- {
- if(std::isfinite(val))
- os << std::setprecision(precision) << val;
- else if(std::isinf(val))
- {
- if(std::signbit(val))
- os << "-";
- os << "Infinity";
- }
- else
- os << "NaN";
- }
-
- void write_null()
- {
- os << "null";
- }
-
- void write_escaped_string(const std::string& str)
- {
- for (char c : str) {
- switch (c) {
- case '"': os << "\\\""; break;
- case '\\': os << "\\\\"; break;
- case '\b': os << "\\b"; break;
- case '\f': os << "\\f"; break;
- case '\n': os << "\\n"; break;
- case '\r': os << "\\r"; break;
- case '\t': os << "\\t"; break;
- default:
- if (c < 32 || c == 127) {
- // Control characters, escape as \u00XX
- os << "\\u00" << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(c);
- } else {
- os << c;
- }
- break;
- }
- }
- }
- };
-}
-
-void json_formatter::print(std::ostream& os, const tag& t) const
-{
- json_fmt_visitor v(os);
- t.accept(v);
-}
+ namespace // anonymous
+ {
+ /// Helper class which uses the Visitor pattern to pretty-print tags
+ class json_fmt_visitor : public const_nbt_visitor
+ {
+ public:
+ json_fmt_visitor(std::ostream& os) : os(os) {}
+
+ void visit(const tag_byte& b) override
+ {
+ os << static_cast<int>(b.get()) << "b";
+ } // We don't want to print a character
+
+ void visit(const tag_short& s) override
+ {
+ os << s.get() << "s";
+ }
+
+ void visit(const tag_int& i) override
+ {
+ os << i.get();
+ }
+
+ void visit(const tag_long& l) override
+ {
+ os << l.get() << "l";
+ }
+
+ void visit(const tag_float& f) override
+ {
+ write_float(f.get());
+ os << "f";
+ }
+
+ void visit(const tag_double& d) override
+ {
+ write_float(d.get());
+ os << "d";
+ }
+
+ void visit(const tag_byte_array& ba) override
+ {
+ os << "[" << ba.size() << " bytes]";
+ }
+
+ void visit(const tag_string& s) override
+ {
+ os << '"';
+ write_escaped_string(s.get());
+ os << '"';
+ }
+
+ void visit(const tag_list& l) override
+ {
+ // Wrap lines for lists of lists or compounds.
+ // Lists of other types can usually be on one line without
+ // problem.
+ const bool break_lines =
+ l.size() > 0 && (l.el_type() == tag_type::List ||
+ l.el_type() == tag_type::Compound);
+
+ os << "[";
+ if (break_lines) {
+ os << "\n";
+ ++indent_lvl;
+ for (unsigned int i = 0; i < l.size(); ++i) {
+ indent();
+ if (l[i])
+ l[i].get().accept(*this);
+ else
+ write_null();
+ if (i != l.size() - 1)
+ os << ",";
+ os << "\n";
+ }
+ --indent_lvl;
+ indent();
+ } else {
+ for (unsigned int i = 0; i < l.size(); ++i) {
+ if (l[i])
+ l[i].get().accept(*this);
+ else
+ write_null();
+ if (i != l.size() - 1)
+ os << ", ";
+ }
+ }
+ os << "]";
+ }
+
+ void visit(const tag_compound& c) override
+ {
+ if (c.size() ==
+ 0) // No line breaks inside empty compounds please
+ {
+ os << "{}";
+ return;
+ }
+
+ os << "{\n";
+ ++indent_lvl;
+ unsigned int i = 0;
+ for (const auto& kv : c) {
+ indent();
+ os << kv.first << ": ";
+ if (kv.second)
+ kv.second.get().accept(*this);
+ else
+ write_null();
+ if (i != c.size() - 1)
+ os << ",";
+ os << "\n";
+ ++i;
+ }
+ --indent_lvl;
+ indent();
+ os << "}";
+ }
+
+ void visit(const tag_int_array& ia) override
+ {
+ os << "[";
+ for (unsigned int i = 0; i < ia.size(); ++i) {
+ os << ia[i];
+ if (i != ia.size() - 1)
+ os << ", ";
+ }
+ os << "]";
+ }
+
+ void visit(const tag_long_array& la) override
+ {
+ os << "[";
+ for (unsigned int i = 0; i < la.size(); ++i) {
+ os << la[i];
+ if (i != la.size() - 1)
+ os << ", ";
+ }
+ os << "]";
+ }
+
+ private:
+ const std::string indent_str = " ";
+
+ std::ostream& os;
+ int indent_lvl = 0;
+
+ void indent()
+ {
+ for (int i = 0; i < indent_lvl; ++i)
+ os << indent_str;
+ }
+
+ template <class T>
+ void write_float(
+ T val, int precision = std::numeric_limits<T>::max_digits10)
+ {
+ if (std::isfinite(val))
+ os << std::setprecision(precision) << val;
+ else if (std::isinf(val)) {
+ if (std::signbit(val))
+ os << "-";
+ os << "Infinity";
+ } else
+ os << "NaN";
+ }
+
+ void write_null()
+ {
+ os << "null";
+ }
+
+ void write_escaped_string(const std::string& str)
+ {
+ for (char c : str) {
+ switch (c) {
+ case '"':
+ os << "\\\"";
+ break;
+ case '\\':
+ os << "\\\\";
+ break;
+ case '\b':
+ os << "\\b";
+ break;
+ case '\f':
+ os << "\\f";
+ break;
+ case '\n':
+ os << "\\n";
+ break;
+ case '\r':
+ os << "\\r";
+ break;
+ case '\t':
+ os << "\\t";
+ break;
+ default:
+ if (c < 32 || c == 127) {
+ // Control characters, escape as \u00XX
+ os << "\\u00" << std::hex << std::setw(2)
+ << std::setfill('0')
+ << static_cast<int>(c);
+ } else {
+ os << c;
+ }
+ break;
+ }
+ }
+ }
+ };
+ } // namespace
+
+ void json_formatter::print(std::ostream& os, const tag& t) const
+ {
+ json_fmt_visitor v(os);
+ t.accept(v);
+ }
-}
-}
+ } // namespace text
+} // namespace nbt
diff --git a/src/value.cpp b/src/value.cpp
index bf0ffcad78..3a9ccb71bc 100644
--- a/src/value.cpp
+++ b/src/value.cpp
@@ -32,286 +32,296 @@
namespace nbt
{
-value::value(tag&& t):
- tag_(std::move(t).move_clone())
-{}
-
-value::value(const value& rhs):
- tag_(rhs.tag_ ? rhs.tag_->clone() : nullptr)
-{}
-
-value& value::operator=(const value& rhs)
-{
- if(this != &rhs)
- {
- tag_ = rhs.tag_ ? rhs.tag_->clone() : nullptr;
- }
- return *this;
-}
-
-value& value::operator=(tag&& t)
-{
- set(std::move(t));
- return *this;
-}
-
-void value::set(tag&& t)
-{
- if(tag_)
- tag_->assign(std::move(t));
- else
- tag_ = std::move(t).move_clone();
-}
-
-//Primitive assignment
-namespace // helper functions local to this translation unit
-{
- template<typename T>
- void assign_numeric_impl(std::unique_ptr<tag>& tag_ptr, T val,
- tag_type default_type)
- {
- using nbt::tag_type;
- if(!tag_ptr)
- {
- tag_ptr = tag::create(default_type, val);
- return;
- }
-
- // Determine the incoming tag type for T
- auto incoming_type = detail::get_primitive_type<T>::value;
-
- // If the existing tag is of a narrower type than the incoming type,
- // reject the assignment to avoid widening the stored tag type.
- auto existing_type = tag_ptr->get_type();
-
- if(static_cast<int>(existing_type) < static_cast<int>(incoming_type))
- {
- throw std::bad_cast();
- }
-
- // Existing type is same or wider: write into the existing tag (may narrow)
- switch(existing_type)
- {
- case tag_type::Byte: static_cast<tag_byte&>(*tag_ptr).set(static_cast<int8_t>(val)); break;
- case tag_type::Short: static_cast<tag_short&>(*tag_ptr).set(static_cast<int16_t>(val)); break;
- case tag_type::Int: static_cast<tag_int&>(*tag_ptr).set(static_cast<int32_t>(val)); break;
- case tag_type::Long: static_cast<tag_long&>(*tag_ptr).set(static_cast<int64_t>(val)); break;
- case tag_type::Float: static_cast<tag_float&>(*tag_ptr).set(static_cast<float>(val)); break;
- case tag_type::Double: static_cast<tag_double&>(*tag_ptr).set(static_cast<double>(val)); break;
- default: throw std::bad_cast();
- }
- }
-}
-
-value& value::operator=(int8_t val)
-{
- assign_numeric_impl(tag_, val, tag_type::Byte);
- return *this;
-}
-
-value& value::operator=(int16_t val)
-{
- assign_numeric_impl(tag_, val, tag_type::Short);
- return *this;
-}
-
-value& value::operator=(int32_t val)
-{
- assign_numeric_impl(tag_, val, tag_type::Int);
- return *this;
-}
-
-value& value::operator=(int64_t val)
-{
- assign_numeric_impl(tag_, val, tag_type::Long);
- return *this;
-}
-
-value& value::operator=(float val)
-{
- assign_numeric_impl(tag_, val, tag_type::Float);
- return *this;
-}
-
-value& value::operator=(double val)
-{
- assign_numeric_impl(tag_, val, tag_type::Double);
- return *this;
-}
-
-//Primitive conversion
-value::operator int8_t() const
-{
- switch(tag_->get_type())
- {
- case tag_type::Byte:
- return static_cast<tag_byte&>(*tag_).get();
-
- default:
- throw std::bad_cast();
- }
-}
-
-value::operator int16_t() const
-{
- switch(tag_->get_type())
- {
- case tag_type::Byte:
- return static_cast<tag_byte&>(*tag_).get();
- case tag_type::Short:
- return static_cast<tag_short&>(*tag_).get();
-
- default:
- throw std::bad_cast();
- }
-}
-
-value::operator int32_t() const
-{
- switch(tag_->get_type())
- {
- case tag_type::Byte:
- return static_cast<tag_byte&>(*tag_).get();
- case tag_type::Short:
- return static_cast<tag_short&>(*tag_).get();
- case tag_type::Int:
- return static_cast<tag_int&>(*tag_).get();
-
- default:
- throw std::bad_cast();
- }
-}
-
-value::operator int64_t() const
-{
- switch(tag_->get_type())
- {
- case tag_type::Byte:
- return static_cast<tag_byte&>(*tag_).get();
- case tag_type::Short:
- return static_cast<tag_short&>(*tag_).get();
- case tag_type::Int:
- return static_cast<tag_int&>(*tag_).get();
- case tag_type::Long:
- return static_cast<tag_long&>(*tag_).get();
-
- default:
- throw std::bad_cast();
- }
-}
-
-value::operator float() const
-{
- switch(tag_->get_type())
- {
- case tag_type::Byte:
- return static_cast<tag_byte&>(*tag_).get();
- case tag_type::Short:
- return static_cast<tag_short&>(*tag_).get();
- case tag_type::Int:
- return static_cast<tag_int&>(*tag_).get();
- case tag_type::Long:
- return static_cast<tag_long&>(*tag_).get();
- case tag_type::Float:
- return static_cast<tag_float&>(*tag_).get();
-
- default:
- throw std::bad_cast();
- }
-}
-
-value::operator double() const
-{
- switch(tag_->get_type())
- {
- case tag_type::Byte:
- return static_cast<tag_byte&>(*tag_).get();
- case tag_type::Short:
- return static_cast<tag_short&>(*tag_).get();
- case tag_type::Int:
- return static_cast<tag_int&>(*tag_).get();
- case tag_type::Long:
- return static_cast<tag_long&>(*tag_).get();
- case tag_type::Float:
- return static_cast<tag_float&>(*tag_).get();
- case tag_type::Double:
- return static_cast<tag_double&>(*tag_).get();
-
- default:
- throw std::bad_cast();
- }
-}
-
-value& value::operator=(std::string&& str)
-{
- if(!tag_)
- set(tag_string(std::move(str)));
- else
- dynamic_cast<tag_string&>(*tag_).set(std::move(str));
- return *this;
-}
-
-value::operator const std::string&() const
-{
- return dynamic_cast<tag_string&>(*tag_).get();
-}
-
-value& value::at(const std::string& key)
-{
- return dynamic_cast<tag_compound&>(*tag_).at(key);
-}
-
-const value& value::at(const std::string& key) const
-{
- return dynamic_cast<const tag_compound&>(*tag_).at(key);
-}
-
-value& value::operator[](const std::string& key)
-{
- return dynamic_cast<tag_compound&>(*tag_)[key];
-}
-
-value& value::operator[](const char* key)
-{
- return (*this)[std::string(key)];
-}
-
-value& value::at(size_t i)
-{
- return dynamic_cast<tag_list&>(*tag_).at(i);
-}
-
-const value& value::at(size_t i) const
-{
- return dynamic_cast<const tag_list&>(*tag_).at(i);
-}
-
-value& value::operator[](size_t i)
-{
- return dynamic_cast<tag_list&>(*tag_)[i];
-}
-
-const value& value::operator[](size_t i) const
-{
- return dynamic_cast<const tag_list&>(*tag_)[i];
-}
-
-tag_type value::get_type() const
-{
- return tag_ ? tag_->get_type() : tag_type::Null;
-}
-
-bool operator==(const value& lhs, const value& rhs)
-{
- if(lhs.tag_ != nullptr && rhs.tag_ != nullptr)
- return *lhs.tag_ == *rhs.tag_;
- else
- return lhs.tag_ == nullptr && rhs.tag_ == nullptr;
-}
-
-bool operator!=(const value& lhs, const value& rhs)
-{
- return !(lhs == rhs);
-}
-
-}
+ value::value(tag&& t) : tag_(std::move(t).move_clone()) {}
+
+ value::value(const value& rhs)
+ : tag_(rhs.tag_ ? rhs.tag_->clone() : nullptr)
+ {
+ }
+
+ value& value::operator=(const value& rhs)
+ {
+ if (this != &rhs) {
+ tag_ = rhs.tag_ ? rhs.tag_->clone() : nullptr;
+ }
+ return *this;
+ }
+
+ value& value::operator=(tag&& t)
+ {
+ set(std::move(t));
+ return *this;
+ }
+
+ void value::set(tag&& t)
+ {
+ if (tag_)
+ tag_->assign(std::move(t));
+ else
+ tag_ = std::move(t).move_clone();
+ }
+
+ // Primitive assignment
+ namespace // helper functions local to this translation unit
+ {
+ template <typename T>
+ void assign_numeric_impl(std::unique_ptr<tag>& tag_ptr, T val,
+ tag_type default_type)
+ {
+ using nbt::tag_type;
+ if (!tag_ptr) {
+ tag_ptr = tag::create(default_type, val);
+ return;
+ }
+
+ // Determine the incoming tag type for T
+ auto incoming_type = detail::get_primitive_type<T>::value;
+
+ // If the existing tag is of a narrower type than the incoming type,
+ // reject the assignment to avoid widening the stored tag type.
+ auto existing_type = tag_ptr->get_type();
+
+ if (static_cast<int>(existing_type) <
+ static_cast<int>(incoming_type)) {
+ throw std::bad_cast();
+ }
+
+ // Existing type is same or wider: write into the existing tag (may
+ // narrow)
+ switch (existing_type) {
+ case tag_type::Byte:
+ static_cast<tag_byte&>(*tag_ptr).set(
+ static_cast<int8_t>(val));
+ break;
+ case tag_type::Short:
+ static_cast<tag_short&>(*tag_ptr).set(
+ static_cast<int16_t>(val));
+ break;
+ case tag_type::Int:
+ static_cast<tag_int&>(*tag_ptr).set(
+ static_cast<int32_t>(val));
+ break;
+ case tag_type::Long:
+ static_cast<tag_long&>(*tag_ptr).set(
+ static_cast<int64_t>(val));
+ break;
+ case tag_type::Float:
+ static_cast<tag_float&>(*tag_ptr).set(
+ static_cast<float>(val));
+ break;
+ case tag_type::Double:
+ static_cast<tag_double&>(*tag_ptr).set(
+ static_cast<double>(val));
+ break;
+ default:
+ throw std::bad_cast();
+ }
+ }
+ } // namespace
+
+ value& value::operator=(int8_t val)
+ {
+ assign_numeric_impl(tag_, val, tag_type::Byte);
+ return *this;
+ }
+
+ value& value::operator=(int16_t val)
+ {
+ assign_numeric_impl(tag_, val, tag_type::Short);
+ return *this;
+ }
+
+ value& value::operator=(int32_t val)
+ {
+ assign_numeric_impl(tag_, val, tag_type::Int);
+ return *this;
+ }
+
+ value& value::operator=(int64_t val)
+ {
+ assign_numeric_impl(tag_, val, tag_type::Long);
+ return *this;
+ }
+
+ value& value::operator=(float val)
+ {
+ assign_numeric_impl(tag_, val, tag_type::Float);
+ return *this;
+ }
+
+ value& value::operator=(double val)
+ {
+ assign_numeric_impl(tag_, val, tag_type::Double);
+ return *this;
+ }
+
+ // Primitive conversion
+ value::operator int8_t() const
+ {
+ switch (tag_->get_type()) {
+ case tag_type::Byte:
+ return static_cast<tag_byte&>(*tag_).get();
+
+ default:
+ throw std::bad_cast();
+ }
+ }
+
+ value::operator int16_t() const
+ {
+ switch (tag_->get_type()) {
+ case tag_type::Byte:
+ return static_cast<tag_byte&>(*tag_).get();
+ case tag_type::Short:
+ return static_cast<tag_short&>(*tag_).get();
+
+ default:
+ throw std::bad_cast();
+ }
+ }
+
+ value::operator int32_t() const
+ {
+ switch (tag_->get_type()) {
+ case tag_type::Byte:
+ return static_cast<tag_byte&>(*tag_).get();
+ case tag_type::Short:
+ return static_cast<tag_short&>(*tag_).get();
+ case tag_type::Int:
+ return static_cast<tag_int&>(*tag_).get();
+
+ default:
+ throw std::bad_cast();
+ }
+ }
+
+ value::operator int64_t() const
+ {
+ switch (tag_->get_type()) {
+ case tag_type::Byte:
+ return static_cast<tag_byte&>(*tag_).get();
+ case tag_type::Short:
+ return static_cast<tag_short&>(*tag_).get();
+ case tag_type::Int:
+ return static_cast<tag_int&>(*tag_).get();
+ case tag_type::Long:
+ return static_cast<tag_long&>(*tag_).get();
+
+ default:
+ throw std::bad_cast();
+ }
+ }
+
+ value::operator float() const
+ {
+ switch (tag_->get_type()) {
+ case tag_type::Byte:
+ return static_cast<tag_byte&>(*tag_).get();
+ case tag_type::Short:
+ return static_cast<tag_short&>(*tag_).get();
+ case tag_type::Int:
+ return static_cast<tag_int&>(*tag_).get();
+ case tag_type::Long:
+ return static_cast<tag_long&>(*tag_).get();
+ case tag_type::Float:
+ return static_cast<tag_float&>(*tag_).get();
+
+ default:
+ throw std::bad_cast();
+ }
+ }
+
+ value::operator double() const
+ {
+ switch (tag_->get_type()) {
+ case tag_type::Byte:
+ return static_cast<tag_byte&>(*tag_).get();
+ case tag_type::Short:
+ return static_cast<tag_short&>(*tag_).get();
+ case tag_type::Int:
+ return static_cast<tag_int&>(*tag_).get();
+ case tag_type::Long:
+ return static_cast<tag_long&>(*tag_).get();
+ case tag_type::Float:
+ return static_cast<tag_float&>(*tag_).get();
+ case tag_type::Double:
+ return static_cast<tag_double&>(*tag_).get();
+
+ default:
+ throw std::bad_cast();
+ }
+ }
+
+ value& value::operator=(std::string&& str)
+ {
+ if (!tag_)
+ set(tag_string(std::move(str)));
+ else
+ dynamic_cast<tag_string&>(*tag_).set(std::move(str));
+ return *this;
+ }
+
+ value::operator const std::string&() const
+ {
+ return dynamic_cast<tag_string&>(*tag_).get();
+ }
+
+ value& value::at(const std::string& key)
+ {
+ return dynamic_cast<tag_compound&>(*tag_).at(key);
+ }
+
+ const value& value::at(const std::string& key) const
+ {
+ return dynamic_cast<const tag_compound&>(*tag_).at(key);
+ }
+
+ value& value::operator[](const std::string& key)
+ {
+ return dynamic_cast<tag_compound&>(*tag_)[key];
+ }
+
+ value& value::operator[](const char* key)
+ {
+ return (*this)[std::string(key)];
+ }
+
+ value& value::at(size_t i)
+ {
+ return dynamic_cast<tag_list&>(*tag_).at(i);
+ }
+
+ const value& value::at(size_t i) const
+ {
+ return dynamic_cast<const tag_list&>(*tag_).at(i);
+ }
+
+ value& value::operator[](size_t i)
+ {
+ return dynamic_cast<tag_list&>(*tag_)[i];
+ }
+
+ const value& value::operator[](size_t i) const
+ {
+ return dynamic_cast<const tag_list&>(*tag_)[i];
+ }
+
+ tag_type value::get_type() const
+ {
+ return tag_ ? tag_->get_type() : tag_type::Null;
+ }
+
+ bool operator==(const value& lhs, const value& rhs)
+ {
+ if (lhs.tag_ != nullptr && rhs.tag_ != nullptr)
+ return *lhs.tag_ == *rhs.tag_;
+ else
+ return lhs.tag_ == nullptr && rhs.tag_ == nullptr;
+ }
+
+ bool operator!=(const value& lhs, const value& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+} // namespace nbt
diff --git a/src/value_initializer.cpp b/src/value_initializer.cpp
index b0d0d3d747..ec52f544fe 100644
--- a/src/value_initializer.cpp
+++ b/src/value_initializer.cpp
@@ -27,14 +27,23 @@
namespace nbt
{
-value_initializer::value_initializer(int8_t val) : value(tag_byte(val)) {}
-value_initializer::value_initializer(int16_t val) : value(tag_short(val)) {}
-value_initializer::value_initializer(int32_t val) : value(tag_int(val)) {}
-value_initializer::value_initializer(int64_t val) : value(tag_long(val)) {}
-value_initializer::value_initializer(float val) : value(tag_float(val)) {}
-value_initializer::value_initializer(double val) : value(tag_double(val)) {}
-value_initializer::value_initializer(const std::string& str): value(tag_string(str)) {}
-value_initializer::value_initializer(std::string&& str) : value(tag_string(std::move(str))) {}
-value_initializer::value_initializer(const char* str) : value(tag_string(str)) {}
+ value_initializer::value_initializer(int8_t val) : value(tag_byte(val)) {}
+ value_initializer::value_initializer(int16_t val) : value(tag_short(val)) {}
+ value_initializer::value_initializer(int32_t val) : value(tag_int(val)) {}
+ value_initializer::value_initializer(int64_t val) : value(tag_long(val)) {}
+ value_initializer::value_initializer(float val) : value(tag_float(val)) {}
+ value_initializer::value_initializer(double val) : value(tag_double(val)) {}
+ value_initializer::value_initializer(const std::string& str)
+ : value(tag_string(str))
+ {
+ }
+ value_initializer::value_initializer(std::string&& str)
+ : value(tag_string(std::move(str)))
+ {
+ }
+ value_initializer::value_initializer(const char* str)
+ : value(tag_string(str))
+ {
+ }
-}
+} // namespace nbt