#ifndef NBT_INTERNAL_HEAD_BFGUDYHGVWCEARSTYJGHI #define NBT_INTERNAL_HEAD_BFGUDYHGVWCEARSTYJGHI #include namespace nbt { template constexpr std::size_t varnum_max() { return sizeof(number_t) * 8 / 7 + 1; } template constexpr std::enable_if_t, std::size_t> zint_max() { return varnum_max(); } template constexpr std::enable_if_t, std::size_t> zint_max() { return (sizeof(numeric) * 8 + 1) / 7 + ((sizeof(numeric) * 8 + 1) % 7 > 0); } template 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(read & 0b01111111); value |= (tmp << (7 * numRead)); numRead++; if (numRead > varnum_max()) throw std::runtime_error("varint is too big"); } while ((read & 0b10000000) != 0); return value; } template void dump_varnum(std::ostream & output, number_t value) { std::make_unsigned_t uval = value; do { auto temp = static_cast(uval & 0b01111111u); uval >>= 7; if (uval != 0) temp |= 0b10000000; output.put(temp); } while (uval != 0); } template std::enable_if_t, numeric> load_zint(std::istream & input) { return load_varnum(input); } template std::enable_if_t, 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() - 1) throw std::runtime_error("szint is too big"); } if (sign) return -value; else return value; } template std::enable_if_t> dump_zint(std::ostream & output, numeric value) { dump_varnum(output, value); } template std::enable_if_t> dump_zint(std::ostream & output, numeric value) { std::uint8_t sign = value < 0; std::make_unsigned_t uval = sign ? -value : value; std::uint8_t temp = (static_cast(uval & 0b00111111) << 1) | sign; uval >>= 6; if (uval != 0) temp |= 0b10000000; output.put(temp); while (uval != 0) { temp = static_cast(uval & 0b01111111); uval >>= 7; if (uval != 0) temp |= 0b10000000; output.put(temp); } } } // namespace nbt #endif // NBT_INTERNAL_HEAD_BFGUDYHGVWCEARSTYJGHI