Many fixes and ZInt
This commit is contained in:
@@ -94,7 +94,7 @@ struct context {
|
|||||||
big_endian, little_endian
|
big_endian, little_endian
|
||||||
} order;
|
} order;
|
||||||
enum class formats {
|
enum class formats {
|
||||||
bin, zigzag, mojangson
|
bin, zigzag, mojangson, zint
|
||||||
} format;
|
} format;
|
||||||
static const context & get(std::ios_base & ios);
|
static const context & get(std::ios_base & ios);
|
||||||
void set(std::ios_base & ios) const;
|
void set(std::ios_base & ios) const;
|
||||||
@@ -123,7 +123,7 @@ inline const context java {
|
|||||||
context::formats::bin
|
context::formats::bin
|
||||||
}, kbt {
|
}, kbt {
|
||||||
context::orders::big_endian,
|
context::orders::big_endian,
|
||||||
context::formats::zigzag
|
context::formats::zint
|
||||||
}, mojangson {
|
}, mojangson {
|
||||||
context::orders::big_endian,
|
context::orders::big_endian,
|
||||||
context::formats::mojangson
|
context::formats::mojangson
|
||||||
@@ -210,6 +210,9 @@ inline std::uint64_t load<std::uint64_t>(std::istream & input, const context & c
|
|||||||
|
|
||||||
void skip_space(std::istream & input);
|
void skip_space(std::istream & input);
|
||||||
|
|
||||||
|
std::size_t load_size(std::istream & input, const context & ctxt);
|
||||||
|
void dump_size(std::ostream & output, const context & ctxt, std::size_t size);
|
||||||
|
|
||||||
template <typename number_t>
|
template <typename number_t>
|
||||||
std::vector<number_t> load_array_text(std::istream & input) {
|
std::vector<number_t> load_array_text(std::istream & input) {
|
||||||
std::vector<number_t> result;
|
std::vector<number_t> result;
|
||||||
@@ -228,10 +231,10 @@ std::vector<number_t> load_array_text(std::istream & input) {
|
|||||||
|
|
||||||
template <typename number_t>
|
template <typename number_t>
|
||||||
std::vector<number_t> load_array_bin(std::istream & input, const context & ctxt) {
|
std::vector<number_t> load_array_bin(std::istream & input, const context & ctxt) {
|
||||||
auto size = load<std::uint32_t>(input, ctxt);
|
auto size = load_size(input, ctxt);
|
||||||
std::vector<number_t> result;
|
std::vector<number_t> result;
|
||||||
result.reserve(size);
|
result.reserve(size);
|
||||||
for (std::uint32_t i = 0; i < size; i++)
|
for (std::size_t i = 0; i < size; i++)
|
||||||
result.emplace_back(load<number_t>(input, ctxt));
|
result.emplace_back(load<number_t>(input, ctxt));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -316,7 +319,7 @@ void dump_array_text(std::ostream & output, const std::vector<number_t> & array)
|
|||||||
|
|
||||||
template <typename number_t>
|
template <typename number_t>
|
||||||
void dump_array_bin(std::ostream & output, const std::vector<number_t> & array, const context & ctxt) {
|
void dump_array_bin(std::ostream & output, const std::vector<number_t> & array, const context & ctxt) {
|
||||||
dump(output, static_cast<std::uint32_t>(array.size()), ctxt);
|
dump_size(output, ctxt, array.size());
|
||||||
for (const auto & element : array)
|
for (const auto & element : array)
|
||||||
dump(output, element, ctxt);
|
dump(output, element, ctxt);
|
||||||
}
|
}
|
||||||
@@ -336,7 +339,8 @@ void dump_list(std::ostream & output, tag_id aid, const std::vector<element_type
|
|||||||
output << '[';
|
output << '[';
|
||||||
} else {
|
} else {
|
||||||
output.put(static_cast<char>(aid));
|
output.put(static_cast<char>(aid));
|
||||||
dump(output, static_cast<std::uint32_t>(list.size()), ctxt);
|
auto size = static_cast<std::size_t>(list.size());
|
||||||
|
dump_size(output, ctxt, size);
|
||||||
}
|
}
|
||||||
auto iter = list.cbegin();
|
auto iter = list.cbegin();
|
||||||
auto end = list.cend();
|
auto end = list.cend();
|
||||||
@@ -358,9 +362,9 @@ std::unique_ptr<tag_type> load_list(std::istream & input, F action) {
|
|||||||
auto ptr = std::make_unique<tag_type>();
|
auto ptr = std::make_unique<tag_type>();
|
||||||
typename tag_type::value_type & result = ptr->value;
|
typename tag_type::value_type & result = ptr->value;
|
||||||
if (ctxt.format != context::formats::mojangson) {
|
if (ctxt.format != context::formats::mojangson) {
|
||||||
auto size = load<std::uint32_t>(input, ctxt);
|
std::size_t size = load_size(input, ctxt);
|
||||||
result.reserve(size);
|
result.reserve(size);
|
||||||
for (std::uint32_t i = 0; i < size; i++)
|
for (std::size_t i = 0; i < size; i++)
|
||||||
result.emplace_back(action(ctxt));
|
result.emplace_back(action(ctxt));
|
||||||
} else {
|
} else {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -915,4 +919,10 @@ std::ostream & operator<<(std::ostream & output, const tags::tag & tag);
|
|||||||
|
|
||||||
} // namespace nbt
|
} // namespace nbt
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
|
||||||
|
string to_string(const nbt::tags::tag & tag);
|
||||||
|
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
#endif // NBT_HEAD_BNTYGTFREQXCPVMFFG
|
#endif // NBT_HEAD_BNTYGTFREQXCPVMFFG
|
||||||
|
|||||||
154
src/nbt.cpp
154
src/nbt.cpp
@@ -1,8 +1,9 @@
|
|||||||
#include "nbt.hpp"
|
#include "nbt_internal.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace nbt {
|
namespace nbt {
|
||||||
|
|
||||||
@@ -49,39 +50,6 @@ void context::set(std::ios_base & ios) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename number_t>
|
|
||||||
constexpr std::size_t varnum_max() {
|
|
||||||
return sizeof(number_t) * 8 / 7 + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename number_t>
|
|
||||||
number_t load_varnum(std::istream & input) {
|
|
||||||
std::size_t numRead = 0;
|
|
||||||
number_t value = 0;
|
|
||||||
int read;
|
|
||||||
do {
|
|
||||||
read = cheof(input);
|
|
||||||
number_t tmp = static_cast<number_t>(read & 0b01111111);
|
|
||||||
value |= (tmp << (7 * numRead));
|
|
||||||
numRead++;
|
|
||||||
if (numRead > varnum_max<number_t>())
|
|
||||||
throw std::runtime_error("varint is too big");
|
|
||||||
} while ((read & 0b10000000) != 0);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename number_t>
|
|
||||||
void dump_varnum(std::ostream & output, number_t value) {
|
|
||||||
std::make_unsigned_t<number_t> uval = value;
|
|
||||||
do {
|
|
||||||
auto temp = static_cast<std::int8_t>(uval & 0b01111111u);
|
|
||||||
uval >>= 7;
|
|
||||||
if (uval != 0)
|
|
||||||
temp |= 0b10000000;
|
|
||||||
output.put(temp);
|
|
||||||
} while (uval != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::int32_t load_varint(std::istream & input) {
|
std::int32_t load_varint(std::istream & input) {
|
||||||
return load_varnum<std::int32_t>(input);
|
return load_varnum<std::int32_t>(input);
|
||||||
}
|
}
|
||||||
@@ -153,8 +121,10 @@ std::int32_t load<std::int32_t>(std::istream & input, const context & ctxt) {
|
|||||||
case context::formats::zigzag:
|
case context::formats::zigzag:
|
||||||
return load_varint(input);
|
return load_varint(input);
|
||||||
case context::formats::mojangson:
|
case context::formats::mojangson:
|
||||||
default:
|
|
||||||
return load_text<std::int32_t>(input);
|
return load_text<std::int32_t>(input);
|
||||||
|
case context::formats::zint:
|
||||||
|
default:
|
||||||
|
return load_zint<std::int32_t>(input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,8 +136,10 @@ std::int64_t load<std::int64_t>(std::istream & input, const context & ctxt) {
|
|||||||
case context::formats::zigzag:
|
case context::formats::zigzag:
|
||||||
return load_varlong(input);
|
return load_varlong(input);
|
||||||
case context::formats::mojangson:
|
case context::formats::mojangson:
|
||||||
default:
|
|
||||||
return load_text<std::int64_t>(input);
|
return load_text<std::int64_t>(input);
|
||||||
|
case context::formats::zint:
|
||||||
|
default:
|
||||||
|
return load_zint<std::int64_t>(input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,8 +151,10 @@ void dump<std::int32_t>(std::ostream & output, std::int32_t number, const contex
|
|||||||
case context::formats::zigzag:
|
case context::formats::zigzag:
|
||||||
return dump_varint(output, number);
|
return dump_varint(output, number);
|
||||||
case context::formats::mojangson:
|
case context::formats::mojangson:
|
||||||
default:
|
|
||||||
return dump_text(output, number);
|
return dump_text(output, number);
|
||||||
|
case context::formats::zint:
|
||||||
|
default:
|
||||||
|
return dump_zint(output, number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,8 +166,10 @@ void dump<std::int64_t>(std::ostream & output, std::int64_t number, const contex
|
|||||||
case context::formats::zigzag:
|
case context::formats::zigzag:
|
||||||
return dump_varlong(output, number);
|
return dump_varlong(output, number);
|
||||||
case context::formats::mojangson:
|
case context::formats::mojangson:
|
||||||
default:
|
|
||||||
return dump_text(output, number);
|
return dump_text(output, number);
|
||||||
|
case context::formats::zint:
|
||||||
|
default:
|
||||||
|
return dump_zint(output, number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +203,21 @@ void dump_text<double>(std::ostream & output, double number) {
|
|||||||
output << number;
|
output << number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t load_size(std::istream & input, const context & ctxt) {
|
||||||
|
if (ctxt.format == context::formats::bin)
|
||||||
|
return load_flat<std::uint32_t>(input, ctxt.order);
|
||||||
|
else
|
||||||
|
return static_cast<std::size_t>(load_varint(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_size(std::ostream & output, const context & ctxt, std::size_t size) {
|
||||||
|
auto sz = static_cast<std::uint32_t>(size);
|
||||||
|
if (ctxt.format == context::formats::bin)
|
||||||
|
dump_flat(output, sz, ctxt.order);
|
||||||
|
else
|
||||||
|
dump_varint(output, sz);
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream & operator<<(std::ostream & output, tag_id tid) {
|
std::ostream & operator<<(std::ostream & output, tag_id tid) {
|
||||||
return output << std::to_string(tid);
|
return output << std::to_string(tid);
|
||||||
}
|
}
|
||||||
@@ -238,6 +229,10 @@ inline bool is_valid_char(char c) {
|
|||||||
tag_id deduce_tag(std::istream & input) {
|
tag_id deduce_tag(std::istream & input) {
|
||||||
skip_space(input);
|
skip_space(input);
|
||||||
char a = cheof(input);
|
char a = cheof(input);
|
||||||
|
if (a == '}' || a == ']') {
|
||||||
|
input.putback(a);
|
||||||
|
return tag_id::tag_end;
|
||||||
|
}
|
||||||
if (a == '[') {
|
if (a == '[') {
|
||||||
char b = cheof(input);
|
char b = cheof(input);
|
||||||
tag_id id;
|
tag_id id;
|
||||||
@@ -282,6 +277,27 @@ tag_id deduce_tag(std::istream & input) {
|
|||||||
deduced = tag_id::tag_float;
|
deduced = tag_id::tag_float;
|
||||||
} else if (b == 'd') {
|
} else if (b == 'd') {
|
||||||
deduced = tag_id::tag_double;
|
deduced = tag_id::tag_double;
|
||||||
|
} else if (b == 'e') {
|
||||||
|
char c = cheof(input);
|
||||||
|
buffer.push_back(c);
|
||||||
|
if (std::isdigit(c) || c == '-' || c == '+') {
|
||||||
|
for (;;) {
|
||||||
|
char d = cheof(input);
|
||||||
|
buffer.push_back(d);
|
||||||
|
if (std::isdigit(d)) {
|
||||||
|
continue;
|
||||||
|
} else if (d == 'f') {
|
||||||
|
deduced = tag_id::tag_float;
|
||||||
|
} else if (d == 'd') {
|
||||||
|
deduced = tag_id::tag_double;
|
||||||
|
} else {
|
||||||
|
deduced = tag_id::tag_double;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
deduced = tag_id::tag_int;
|
||||||
|
}
|
||||||
} else if (b == '.') {
|
} else if (b == '.') {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char c = cheof(input);
|
char c = cheof(input);
|
||||||
@@ -291,7 +307,7 @@ tag_id deduce_tag(std::istream & input) {
|
|||||||
} else if (c == 'e' || c == 'E') {
|
} else if (c == 'e' || c == 'E') {
|
||||||
char d = cheof(input);
|
char d = cheof(input);
|
||||||
buffer.push_back(d);
|
buffer.push_back(d);
|
||||||
if (std::isdigit(a) || a == '-' || a == '+')
|
if (std::isdigit(d) || d == '-' || d == '+')
|
||||||
continue;
|
continue;
|
||||||
} else if (c == 'f') {
|
} else if (c == 'f') {
|
||||||
deduced = tag_id::tag_float;
|
deduced = tag_id::tag_float;
|
||||||
@@ -379,8 +395,8 @@ std::string read_string_text(std::istream & input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string read_string_bin(std::istream & input, const context & ctxt) {
|
std::string read_string_bin(std::istream & input, const context & ctxt) {
|
||||||
auto size = ctxt.format == context::formats::zigzag ?
|
std::uint32_t size = (ctxt.format == context::formats::zigzag || ctxt.format == context::formats::zint) ?
|
||||||
load_varint(input) : load<std::uint16_t>(input, ctxt);
|
load_varint(input) : load_flat<std::uint16_t>(input, ctxt.order);
|
||||||
std::string result;
|
std::string result;
|
||||||
result.resize(size);
|
result.resize(size);
|
||||||
input.read(result.data(), size);
|
input.read(result.data(), size);
|
||||||
@@ -423,11 +439,12 @@ void write_string(std::ostream & output, const std::string & string, const conte
|
|||||||
switch (ctxt.format) {
|
switch (ctxt.format) {
|
||||||
case context::formats::bin:
|
case context::formats::bin:
|
||||||
dump(output, static_cast<std::uint16_t>(string.size()), ctxt); break;
|
dump(output, static_cast<std::uint16_t>(string.size()), ctxt); break;
|
||||||
case context::formats::zigzag:
|
|
||||||
dump_varint(output, static_cast<std::int32_t>(string.size())); break;
|
|
||||||
case context::formats::mojangson:
|
case context::formats::mojangson:
|
||||||
default:
|
|
||||||
write_string_text(output, string); return;
|
write_string_text(output, string); return;
|
||||||
|
case context::formats::zigzag:
|
||||||
|
case context::formats::zint:
|
||||||
|
default:
|
||||||
|
dump_varint(output, static_cast<std::int32_t>(string.size())); break;
|
||||||
}
|
}
|
||||||
output << string;
|
output << string;
|
||||||
}
|
}
|
||||||
@@ -681,34 +698,43 @@ std::unique_ptr<compound_tag> compound_tag::read(std::istream & input) {
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void compound_tag::write(std::ostream & output) const {
|
void compound_write_text(std::ostream & output, const compound_tag & compound, const context & ctxt) {
|
||||||
const context & ctxt = context::get(output);
|
const auto & value = compound.value;
|
||||||
if (ctxt.format == context::formats::mojangson)
|
output << '{';
|
||||||
output << '{';
|
|
||||||
auto iter = value.cbegin();
|
auto iter = value.cbegin();
|
||||||
auto end = value.cend();
|
auto end = value.cend();
|
||||||
if (iter != end) {
|
if (iter != end) {
|
||||||
auto action = [&](const compound_tag::value_type::value_type & entry) {
|
auto action = [&](const compound_tag::value_type::value_type & entry) {
|
||||||
if (ctxt.format != context::formats::mojangson)
|
|
||||||
output.put(static_cast<char>(entry.second->id()));
|
|
||||||
write_string(output, entry.first, ctxt);
|
write_string(output, entry.first, ctxt);
|
||||||
if (ctxt.format == context::formats::mojangson)
|
output << ':';
|
||||||
output << ':';
|
|
||||||
entry.second->write(output);
|
entry.second->write(output);
|
||||||
};
|
};
|
||||||
action(*iter);
|
action(*iter);
|
||||||
for (++iter; iter != end; ++iter) {
|
for (++iter; iter != end; ++iter) {
|
||||||
if (ctxt.format == context::formats::mojangson)
|
output << ',';
|
||||||
output << ',';
|
|
||||||
action(*iter);
|
action(*iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ctxt.format == context::formats::mojangson) {
|
output << '}';
|
||||||
output << '}';
|
}
|
||||||
} else {
|
|
||||||
if (!is_root)
|
void compound_write_bin(std::ostream & output, const compound_tag & compound, const context & ctxt) {
|
||||||
tags::end.write(output);
|
const auto & value = compound.value;
|
||||||
|
for (const auto & entry : value) {
|
||||||
|
output.put(static_cast<char>(entry.second->id()));
|
||||||
|
write_string(output, entry.first, ctxt);
|
||||||
|
entry.second->write(output);
|
||||||
}
|
}
|
||||||
|
if (!compound.is_root)
|
||||||
|
tags::end.write(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void compound_tag::write(std::ostream & output) const {
|
||||||
|
const context & ctxt = context::get(output);
|
||||||
|
if (ctxt.format == context::formats::mojangson)
|
||||||
|
compound_write_text(output, *this, ctxt);
|
||||||
|
else
|
||||||
|
compound_write_bin(output, *this, ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<tag> compound_tag::copy() const {
|
std::unique_ptr<tag> compound_tag::copy() const {
|
||||||
@@ -782,6 +808,9 @@ void read_compound_text(std::istream & input, tags::compound_tag & compound, con
|
|||||||
tag_id key_type = deduce_tag(input);
|
tag_id key_type = deduce_tag(input);
|
||||||
switch (key_type) {
|
switch (key_type) {
|
||||||
case tag_id::tag_end:
|
case tag_id::tag_end:
|
||||||
|
skip_space(input);
|
||||||
|
if (cheof(input) != '}')
|
||||||
|
throw std::runtime_error("failed to close compound tag");
|
||||||
return;
|
return;
|
||||||
case tag_id::tag_string:
|
case tag_id::tag_string:
|
||||||
break;
|
break;
|
||||||
@@ -866,4 +895,11 @@ string to_string(nbt::tag_id tid) {
|
|||||||
# undef TAG_ID_CASE
|
# undef TAG_ID_CASE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string to_string(const nbt::tags::tag & tag) {
|
||||||
|
using namespace nbt;
|
||||||
|
std::stringstream result;
|
||||||
|
tag.write(result << contexts::mojangson);
|
||||||
|
return result.str();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|||||||
101
src/nbt_internal.hpp
Normal file
101
src/nbt_internal.hpp
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#ifndef NBT_INTERNAL_HEAD_BFGUDYHGVWCEARSTYJGHI
|
||||||
|
#define NBT_INTERNAL_HEAD_BFGUDYHGVWCEARSTYJGHI
|
||||||
|
|
||||||
|
#include <nbt.hpp>
|
||||||
|
|
||||||
|
namespace nbt {
|
||||||
|
|
||||||
|
template <typename number_t>
|
||||||
|
constexpr std::size_t varnum_max() {
|
||||||
|
return sizeof(number_t) * 8 / 7 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename numeric>
|
||||||
|
constexpr std::enable_if_t<std::is_unsigned_v<numeric>, std::size_t> zint_max() {
|
||||||
|
return varnum_max<numeric>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename numeric>
|
||||||
|
constexpr std::enable_if_t<std::is_signed_v<numeric>, std::size_t> zint_max() {
|
||||||
|
return (sizeof(numeric) * 8 + 1) / 7 + ((sizeof(numeric) * 8 + 1) % 7 > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename number_t>
|
||||||
|
number_t load_varnum(std::istream & input) {
|
||||||
|
std::size_t numRead = 0;
|
||||||
|
number_t value = 0;
|
||||||
|
int read;
|
||||||
|
do {
|
||||||
|
read = cheof(input);
|
||||||
|
number_t tmp = static_cast<number_t>(read & 0b01111111);
|
||||||
|
value |= (tmp << (7 * numRead));
|
||||||
|
numRead++;
|
||||||
|
if (numRead > varnum_max<number_t>())
|
||||||
|
throw std::runtime_error("varint is too big");
|
||||||
|
} while ((read & 0b10000000) != 0);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename number_t>
|
||||||
|
void dump_varnum(std::ostream & output, number_t value) {
|
||||||
|
std::make_unsigned_t<number_t> uval = value;
|
||||||
|
do {
|
||||||
|
auto temp = static_cast<std::int8_t>(uval & 0b01111111u);
|
||||||
|
uval >>= 7;
|
||||||
|
if (uval != 0)
|
||||||
|
temp |= 0b10000000;
|
||||||
|
output.put(temp);
|
||||||
|
} while (uval != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename numeric>
|
||||||
|
std::enable_if_t<std::is_unsigned_v<numeric>, numeric> load_zint(std::istream & input) {
|
||||||
|
return load_varnum<numeric>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename numeric>
|
||||||
|
std::enable_if_t<std::is_signed_v<numeric>, numeric> load_zint(std::istream & input) {
|
||||||
|
std::uint8_t read = cheof(input);
|
||||||
|
bool sign = read & 1;
|
||||||
|
numeric value = (read >> 1) & 0b00111111;
|
||||||
|
unsigned numRead = 0;
|
||||||
|
while ((read & 0b10000000) != 0) {
|
||||||
|
read = cheof(input);
|
||||||
|
numeric tmp = (read & 0b01111111);
|
||||||
|
value |= (tmp << (7 * numRead + 6));
|
||||||
|
++numRead;
|
||||||
|
if (numRead > zint_max<numeric>() - 1)
|
||||||
|
throw std::runtime_error("szint is too big");
|
||||||
|
}
|
||||||
|
if (sign)
|
||||||
|
return -value;
|
||||||
|
else
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename numeric>
|
||||||
|
std::enable_if_t<std::is_unsigned_v<numeric>> dump_zint(std::ostream & output, numeric value) {
|
||||||
|
dump_varnum(output, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename numeric>
|
||||||
|
std::enable_if_t<std::is_signed_v<numeric>> dump_zint(std::ostream & output, numeric value) {
|
||||||
|
std::uint8_t sign = value < 0;
|
||||||
|
std::make_unsigned_t<numeric> uval = sign ? -value : value;
|
||||||
|
std::uint8_t temp = (static_cast<std::uint8_t>(uval & 0b00111111) << 1) | sign;
|
||||||
|
uval >>= 6;
|
||||||
|
if (uval != 0)
|
||||||
|
temp |= 0b10000000;
|
||||||
|
output.put(temp);
|
||||||
|
while (uval != 0) {
|
||||||
|
temp = static_cast<std::uint8_t>(uval & 0b01111111);
|
||||||
|
uval >>= 7;
|
||||||
|
if (uval != 0)
|
||||||
|
temp |= 0b10000000;
|
||||||
|
output.put(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace nbt
|
||||||
|
|
||||||
|
#endif // NBT_INTERNAL_HEAD_BFGUDYHGVWCEARSTYJGHI
|
||||||
17
src/nbtc.cpp
17
src/nbtc.cpp
@@ -1,4 +1,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <nbt.hpp>
|
#include <nbt.hpp>
|
||||||
|
|
||||||
@@ -53,12 +55,13 @@ int main(int argc, char ** argv) {
|
|||||||
const context & from = iter_from->second;
|
const context & from = iter_from->second;
|
||||||
const context & to = iter_to->second;
|
const context & to = iter_to->second;
|
||||||
std::unique_ptr<tags::tag> root;
|
std::unique_ptr<tags::tag> root;
|
||||||
std::cin >> from;
|
auto & input = std::cin;
|
||||||
|
input >> from;
|
||||||
std::cout << to;
|
std::cout << to;
|
||||||
try {
|
try {
|
||||||
if (from.format == context::formats::mojangson) {
|
if (from.format == context::formats::mojangson) {
|
||||||
tag_id id = deduce_tag(std::cin);
|
tag_id id = deduce_tag(input);
|
||||||
std::unique_ptr<tags::tag> tag = tags::read(id, std::cin);
|
std::unique_ptr<tags::tag> tag = tags::read(id, input);
|
||||||
if (tag->id() == tag_id::tag_compound) {
|
if (tag->id() == tag_id::tag_compound) {
|
||||||
root = std::move(tag);
|
root = std::move(tag);
|
||||||
} else {
|
} else {
|
||||||
@@ -67,16 +70,18 @@ int main(int argc, char ** argv) {
|
|||||||
root = std::move(compound);
|
root = std::move(compound);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
root = tags::read<tag_id::tag_compound>(std::cin);
|
root = tags::read<tag_id::tag_compound>(input);
|
||||||
}
|
}
|
||||||
} catch (const std::exception & e) {
|
} catch (const std::exception & e) {
|
||||||
std::cerr
|
std::cerr
|
||||||
<< "failed to read NBT (stream position "
|
<< "failed to read NBT (stream position "
|
||||||
<< std::cin.tellg() << "): " << e.what() << std::endl;
|
<< input.tellg() << "): " << e.what() << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
std::cout << *root << std::endl;
|
std::cout << *root;
|
||||||
|
if (context::formats::mojangson == to.format)
|
||||||
|
std::cout << std::endl;
|
||||||
} catch (const std::exception & e) {
|
} catch (const std::exception & e) {
|
||||||
std::cerr
|
std::cerr
|
||||||
<< "failed to write NBT (stream position "
|
<< "failed to write NBT (stream position "
|
||||||
|
|||||||
Reference in New Issue
Block a user