diff options
Diffstat (limited to 'include/io')
| -rw-r--r-- | include/io/izlibstream.h | 120 | ||||
| -rw-r--r-- | include/io/ozlibstream.h | 131 | ||||
| -rw-r--r-- | include/io/stream_reader.h | 213 | ||||
| -rw-r--r-- | include/io/stream_writer.h | 195 | ||||
| -rw-r--r-- | include/io/zlib_streambuf.h | 63 |
5 files changed, 385 insertions, 337 deletions
diff --git a/include/io/izlibstream.h b/include/io/izlibstream.h index f7d180f4e8..c2a8e59b04 100644 --- a/include/io/izlibstream.h +++ b/include/io/izlibstream.h @@ -33,67 +33,75 @@ namespace zlib { -/** - * @brief Stream buffer used by zlib::izlibstream - * @sa izlibstream - */ -class NBT_EXPORT inflate_streambuf : public zlib_streambuf -{ -public: - /** - * @param input the istream to wrap - * @param bufsize the size of the internal buffers - * @param window_bits the base two logarithm of the maximum window size that - * zlib will use. - * This parameter also determines which type of input to expect. - * The default argument will autodetect between zlib and gzip data. - * Refer to the zlib documentation of inflateInit2 for more details. - * - * @throw zlib_error if zlib encounters a problem during initialization - */ - explicit inflate_streambuf(std::istream& input, size_t bufsize = 32768, int window_bits = 32 + 15); - ~inflate_streambuf() noexcept; + /** + * @brief Stream buffer used by zlib::izlibstream + * @sa izlibstream + */ + class NBT_EXPORT inflate_streambuf : public zlib_streambuf + { + public: + /** + * @param input the istream to wrap + * @param bufsize the size of the internal buffers + * @param window_bits the base two logarithm of the maximum window size + * that zlib will use. This parameter also determines which type of + * input to expect. The default argument will autodetect between zlib + * and gzip data. Refer to the zlib documentation of inflateInit2 for + * more details. + * + * @throw zlib_error if zlib encounters a problem during initialization + */ + explicit inflate_streambuf(std::istream& input, size_t bufsize = 32768, + int window_bits = 32 + 15); + ~inflate_streambuf() noexcept; - ///@return the wrapped istream - std::istream& get_istr() const { return is; } + ///@return the wrapped istream + std::istream& get_istr() const + { + return is; + } -private: - std::istream& is; - bool stream_end; + private: + std::istream& is; + bool stream_end; - int_type underflow() override; -}; + int_type underflow() override; + }; -/** - * @brief An istream adapter that decompresses data using zlib - * - * This istream wraps another istream. The izlibstream will read compressed - * data from the wrapped istream and inflate (decompress) it with zlib. - * - * @note If you want to read more data from the wrapped istream after the end - * of the compressed data, then it must allow seeking. It is unavoidable for - * the izlibstream to consume more data after the compressed data. - * It will automatically attempt to seek the wrapped istream back to the point - * after the end of the compressed data. - * @sa inflate_streambuf - */ -class NBT_EXPORT izlibstream : public std::istream -{ -public: - /** - * @param input the istream to wrap - * @param bufsize the size of the internal buffers - */ - explicit izlibstream(std::istream& input, size_t bufsize = 32768): - std::istream(&buf), buf(input, bufsize) - {} - ///@return the wrapped istream - std::istream& get_istr() const { return buf.get_istr(); } + /** + * @brief An istream adapter that decompresses data using zlib + * + * This istream wraps another istream. The izlibstream will read compressed + * data from the wrapped istream and inflate (decompress) it with zlib. + * + * @note If you want to read more data from the wrapped istream after the + * end of the compressed data, then it must allow seeking. It is unavoidable + * for the izlibstream to consume more data after the compressed data. It + * will automatically attempt to seek the wrapped istream back to the point + * after the end of the compressed data. + * @sa inflate_streambuf + */ + class NBT_EXPORT izlibstream : public std::istream + { + public: + /** + * @param input the istream to wrap + * @param bufsize the size of the internal buffers + */ + explicit izlibstream(std::istream& input, size_t bufsize = 32768) + : std::istream(&buf), buf(input, bufsize) + { + } + ///@return the wrapped istream + std::istream& get_istr() const + { + return buf.get_istr(); + } -private: - inflate_streambuf buf; -}; + private: + inflate_streambuf buf; + }; -} +} // namespace zlib #endif // IZLIBSTREAM_H_INCLUDED diff --git a/include/io/ozlibstream.h b/include/io/ozlibstream.h index 5ac3dba97f..f04f33deef 100644 --- a/include/io/ozlibstream.h +++ b/include/io/ozlibstream.h @@ -33,69 +33,88 @@ namespace zlib { -/** - * @brief Stream buffer used by zlib::ozlibstream - * @sa ozlibstream - */ -class NBT_EXPORT deflate_streambuf : public zlib_streambuf -{ -public: - /** - * @param output the ostream to wrap - * @param bufsize the size of the internal buffers - * @param level the compression level, ranges from 0 to 9, or -1 for default - * - * Refer to the zlib documentation of deflateInit2 for details about the arguments. - * - * @throw zlib_error if zlib encounters a problem during initialization - */ - explicit deflate_streambuf(std::ostream& output, size_t bufsize = 32768, int level = Z_DEFAULT_COMPRESSION, int window_bits = 15, int mem_level = 8, int strategy = Z_DEFAULT_STRATEGY); - ~deflate_streambuf() noexcept; + /** + * @brief Stream buffer used by zlib::ozlibstream + * @sa ozlibstream + */ + class NBT_EXPORT deflate_streambuf : public zlib_streambuf + { + public: + /** + * @param output the ostream to wrap + * @param bufsize the size of the internal buffers + * @param level the compression level, ranges from 0 to 9, or -1 for + * default + * + * Refer to the zlib documentation of deflateInit2 for details about the + * arguments. + * + * @throw zlib_error if zlib encounters a problem during initialization + */ + explicit deflate_streambuf(std::ostream& output, size_t bufsize = 32768, + int level = Z_DEFAULT_COMPRESSION, + int window_bits = 15, int mem_level = 8, + int strategy = Z_DEFAULT_STRATEGY); + ~deflate_streambuf() noexcept; - ///@return the wrapped ostream - std::ostream& get_ostr() const { return os; } + ///@return the wrapped ostream + std::ostream& get_ostr() const + { + return os; + } - ///Finishes compression and writes all pending data to the output - void close(); -private: - std::ostream& os; + /// Finishes compression and writes all pending data to the output + void close(); - void deflate_chunk(int flush = Z_NO_FLUSH); + private: + std::ostream& os; - int_type overflow(int_type ch) override; - int sync() override; -}; + void deflate_chunk(int flush = Z_NO_FLUSH); -/** - * @brief An ostream adapter that compresses data using zlib - * - * This ostream wraps another ostream. Data written to an ozlibstream will be - * deflated (compressed) with zlib and written to the wrapped ostream. - * - * @sa deflate_streambuf - */ -class NBT_EXPORT ozlibstream : public std::ostream -{ -public: - /** - * @param output the ostream to wrap - * @param level the compression level, ranges from 0 to 9, or -1 for default - * @param gzip if true, the output will be in gzip format rather than zlib - * @param bufsize the size of the internal buffers - */ - explicit ozlibstream(std::ostream& output, int level = Z_DEFAULT_COMPRESSION, bool gzip = false, size_t bufsize = 32768): - std::ostream(&buf), buf(output, bufsize, level, 15 + (gzip ? 16 : 0)) - {} + int_type overflow(int_type ch) override; + int sync() override; + }; + + /** + * @brief An ostream adapter that compresses data using zlib + * + * This ostream wraps another ostream. Data written to an ozlibstream will + * be deflated (compressed) with zlib and written to the wrapped ostream. + * + * @sa deflate_streambuf + */ + class NBT_EXPORT ozlibstream : public std::ostream + { + public: + /** + * @param output the ostream to wrap + * @param level the compression level, ranges from 0 to 9, or -1 for + * default + * @param gzip if true, the output will be in gzip format rather than + * zlib + * @param bufsize the size of the internal buffers + */ + explicit ozlibstream(std::ostream& output, + int level = Z_DEFAULT_COMPRESSION, + bool gzip = false, size_t bufsize = 32768) + : std::ostream(&buf), + buf(output, bufsize, level, 15 + (gzip ? 16 : 0)) + { + } + + ///@return the wrapped ostream + std::ostream& get_ostr() const + { + return buf.get_ostr(); + } - ///@return the wrapped ostream - std::ostream& get_ostr() const { return buf.get_ostr(); } + /// Finishes compression and writes all pending data to the output + void close(); - ///Finishes compression and writes all pending data to the output - void close(); -private: - deflate_streambuf buf; -}; + private: + deflate_streambuf buf; + }; -} +} // namespace zlib #endif // OZLIBSTREAM_H_INCLUDED diff --git a/include/io/stream_reader.h b/include/io/stream_reader.h index 821a9ff8d3..05f8d99c92 100644 --- a/include/io/stream_reader.h +++ b/include/io/stream_reader.h @@ -36,108 +36,115 @@ namespace nbt { -namespace io -{ - -///Exception that gets thrown when reading is not successful -class NBT_EXPORT input_error : public std::runtime_error -{ - using std::runtime_error::runtime_error; -}; - -/** - * @brief Reads a named tag from the stream, making sure that it is a compound - * @param is the stream to read from - * @param e the byte order of the source data. The Java edition - * of Minecraft uses Big Endian, the Pocket edition uses Little Endian - * @throw input_error on failure, or if the tag in the stream is not a compound - */ -NBT_EXPORT std::pair<std::string, std::unique_ptr<tag_compound>> read_compound(std::istream& is, endian::endian e = endian::big); - -/** - * @brief Reads a named tag from the stream - * @param is the stream to read from - * @param e the byte order of the source data. The Java edition - * of Minecraft uses Big Endian, the Pocket edition uses Little Endian - * @throw input_error on failure - */ -NBT_EXPORT std::pair<std::string, std::unique_ptr<tag>> read_tag(std::istream& is, endian::endian e = endian::big); - -/** - * @brief Helper class for reading NBT tags from input streams - * - * Can be reused to read multiple tags - */ -class NBT_EXPORT stream_reader -{ -public: - /** - * @param is the stream to read from - * @param e the byte order of the source data. The Java edition - * of Minecraft uses Big Endian, the Pocket edition uses Little Endian - */ - explicit stream_reader(std::istream& is, endian::endian e = endian::big) noexcept; - - ///Returns the stream - std::istream& get_istr() const; - ///Returns the byte order - endian::endian get_endian() const; - - /** - * @brief Reads a named tag from the stream, making sure that it is a compound - * @throw input_error on failure, or if the tag in the stream is not a compound - */ - std::pair<std::string, std::unique_ptr<tag_compound>> read_compound(); - - /** - * @brief Reads a named tag from the stream - * @throw input_error on failure - */ - std::pair<std::string, std::unique_ptr<tag>> read_tag(); - - /** - * @brief Reads a tag of the given type without name from the stream - * @throw input_error on failure - */ - std::unique_ptr<tag> read_payload(tag_type type); - - /** - * @brief Reads a tag type from the stream - * @param allow_end whether to consider tag_type::End valid - * @throw input_error on failure - */ - tag_type read_type(bool allow_end = false); - - /** - * @brief Reads a binary number from the stream - * - * On failure, will set the failbit on the stream. - */ - template<class T> - void read_num(T& x); - - /** - * @brief Reads an NBT string from the stream - * - * An NBT string consists of two bytes indicating the length, followed by - * the characters encoded in modified UTF-8. - * @throw input_error on failure - */ - std::string read_string(); - -private: - std::istream& is; - int depth = 0; - const endian::endian endian; -}; - -template<class T> -void stream_reader::read_num(T& x) -{ - endian::read(is, x, endian); -} - -} -} + namespace io + { + + /// Exception that gets thrown when reading is not successful + class NBT_EXPORT input_error : public std::runtime_error + { + using std::runtime_error::runtime_error; + }; + + /** + * @brief Reads a named tag from the stream, making sure that it is a + * compound + * @param is the stream to read from + * @param e the byte order of the source data. The Java edition + * of Minecraft uses Big Endian, the Pocket edition uses Little Endian + * @throw input_error on failure, or if the tag in the stream is not a + * compound + */ + NBT_EXPORT std::pair<std::string, std::unique_ptr<tag_compound>> + read_compound(std::istream& is, endian::endian e = endian::big); + + /** + * @brief Reads a named tag from the stream + * @param is the stream to read from + * @param e the byte order of the source data. The Java edition + * of Minecraft uses Big Endian, the Pocket edition uses Little Endian + * @throw input_error on failure + */ + NBT_EXPORT std::pair<std::string, std::unique_ptr<tag>> + read_tag(std::istream& is, endian::endian e = endian::big); + + /** + * @brief Helper class for reading NBT tags from input streams + * + * Can be reused to read multiple tags + */ + class NBT_EXPORT stream_reader + { + public: + /** + * @param is the stream to read from + * @param e the byte order of the source data. The Java edition + * of Minecraft uses Big Endian, the Pocket edition uses Little + * Endian + */ + explicit stream_reader(std::istream& is, + endian::endian e = endian::big) noexcept; + + /// Returns the stream + std::istream& get_istr() const; + /// Returns the byte order + endian::endian get_endian() const; + + /** + * @brief Reads a named tag from the stream, making sure that it is + * a compound + * @throw input_error on failure, or if the tag in the stream is not + * a compound + */ + std::pair<std::string, std::unique_ptr<tag_compound>> + read_compound(); + + /** + * @brief Reads a named tag from the stream + * @throw input_error on failure + */ + std::pair<std::string, std::unique_ptr<tag>> read_tag(); + + /** + * @brief Reads a tag of the given type without name from the stream + * @throw input_error on failure + */ + std::unique_ptr<tag> read_payload(tag_type type); + + /** + * @brief Reads a tag type from the stream + * @param allow_end whether to consider tag_type::End valid + * @throw input_error on failure + */ + tag_type read_type(bool allow_end = false); + + /** + * @brief Reads a binary number from the stream + * + * On failure, will set the failbit on the stream. + */ + template <class T> void read_num(T& x); + + /** + * @brief Reads an NBT string from the stream + * + * An NBT string consists of two bytes indicating the length, + * followed by the characters encoded in modified UTF-8. + * @throw input_error on failure + */ + std::string read_string(); + + private: + std::istream& is; + int depth = 0; + const endian::endian endian; + }; + + template <class T> void stream_reader::read_num(T& x) + { + endian::read(is, x, endian); + } + + } // namespace io +} // namespace nbt #endif // STREAM_READER_H_INCLUDED diff --git a/include/io/stream_writer.h b/include/io/stream_writer.h index 32a01c89c9..04f039948c 100644 --- a/include/io/stream_writer.h +++ b/include/io/stream_writer.h @@ -33,95 +33,110 @@ namespace nbt { -namespace io -{ - -/* Not sure if that is even needed -///Exception that gets thrown when writing is not successful -class output_error : public std::runtime_error -{ - using std::runtime_error::runtime_error; -};*/ - -/** - * @brief Writes a named tag into the stream, including the tag type - * @param key the name of the tag - * @param t the tag - * @param os the stream to write to - * @param e the byte order of the written data. The Java edition - * of Minecraft uses Big Endian, the Pocket edition uses Little Endian - */ -NBT_EXPORT void write_tag(const std::string& key, const tag& t, std::ostream& os, endian::endian e = endian::big); - -/** - * @brief Helper class for writing NBT tags to output streams - * - * Can be reused to write multiple tags - */ -class NBT_EXPORT stream_writer -{ -public: - ///Maximum length of an NBT string (16 bit unsigned) - static constexpr size_t max_string_len = UINT16_MAX; - ///Maximum length of an NBT list or array (32 bit signed) - static constexpr uint32_t max_array_len = INT32_MAX; - - /** - * @param os the stream to write to - * @param e the byte order of the written data. The Java edition - * of Minecraft uses Big Endian, the Pocket edition uses Little Endian - */ - explicit stream_writer(std::ostream& os, endian::endian e = endian::big) noexcept: - os(os), endian(e) - {} - - ///Returns the stream - std::ostream& get_ostr() const { return os; } - ///Returns the byte order - endian::endian get_endian() const { return endian; } - - /** - * @brief Writes a named tag into the stream, including the tag type - */ - void write_tag(const std::string& key, const tag& t); - - /** - * @brief Writes the given tag's payload into the stream - */ - void write_payload(const tag& t) { t.write_payload(*this); } - - /** - * @brief Writes a tag type to the stream - */ - void write_type(tag_type tt) { write_num(static_cast<int8_t>(tt)); } - - /** - * @brief Writes a binary number to the stream - */ - template<class T> - void write_num(T x); - - /** - * @brief Writes an NBT string to the stream - * - * An NBT string consists of two bytes indicating the length, followed by - * the characters encoded in modified UTF-8. - * @throw std::length_error if the string is too long for NBT - */ - void write_string(const std::string& str); - -private: - std::ostream& os; - const endian::endian endian; -}; - -template<class T> -void stream_writer::write_num(T x) -{ - endian::write(os, x, endian); -} - -} -} + namespace io + { + + /* Not sure if that is even needed + ///Exception that gets thrown when writing is not successful + class output_error : public std::runtime_error + { + using std::runtime_error::runtime_error; + };*/ + + /** + * @brief Writes a named tag into the stream, including the tag type + * @param key the name of the tag + * @param t the tag + * @param os the stream to write to + * @param e the byte order of the written data. The Java edition + * of Minecraft uses Big Endian, the Pocket edition uses Little Endian + */ + NBT_EXPORT void write_tag(const std::string& key, const tag& t, + std::ostream& os, + endian::endian e = endian::big); + + /** + * @brief Helper class for writing NBT tags to output streams + * + * Can be reused to write multiple tags + */ + class NBT_EXPORT stream_writer + { + public: + /// Maximum length of an NBT string (16 bit unsigned) + static constexpr size_t max_string_len = UINT16_MAX; + /// Maximum length of an NBT list or array (32 bit signed) + static constexpr uint32_t max_array_len = INT32_MAX; + + /** + * @param os the stream to write to + * @param e the byte order of the written data. The Java edition + * of Minecraft uses Big Endian, the Pocket edition uses Little + * Endian + */ + explicit stream_writer(std::ostream& os, + endian::endian e = endian::big) noexcept + : os(os), endian(e) + { + } + + /// Returns the stream + std::ostream& get_ostr() const + { + return os; + } + /// Returns the byte order + endian::endian get_endian() const + { + return endian; + } + + /** + * @brief Writes a named tag into the stream, including the tag type + */ + void write_tag(const std::string& key, const tag& t); + + /** + * @brief Writes the given tag's payload into the stream + */ + void write_payload(const tag& t) + { + t.write_payload(*this); + } + + /** + * @brief Writes a tag type to the stream + */ + void write_type(tag_type tt) + { + write_num(static_cast<int8_t>(tt)); + } + + /** + * @brief Writes a binary number to the stream + */ + template <class T> void write_num(T x); + + /** + * @brief Writes an NBT string to the stream + * + * An NBT string consists of two bytes indicating the length, + * followed by the characters encoded in modified UTF-8. + * @throw std::length_error if the string is too long for NBT + */ + void write_string(const std::string& str); + + private: + std::ostream& os; + const endian::endian endian; + }; + + template <class T> void stream_writer::write_num(T x) + { + endian::write(os, x, endian); + } + + } // namespace io +} // namespace nbt #endif // STREAM_WRITER_H_INCLUDED diff --git a/include/io/zlib_streambuf.h b/include/io/zlib_streambuf.h index e8eea1822f..91a660b9f2 100644 --- a/include/io/zlib_streambuf.h +++ b/include/io/zlib_streambuf.h @@ -16,37 +16,36 @@ namespace zlib { -///Exception thrown in case zlib encounters a problem -class NBT_EXPORT zlib_error : public std::runtime_error -{ -public: - const int errcode; - - zlib_error(const char* msg, int errcode): - std::runtime_error(msg - ? std::string(zError(errcode)) + ": " + msg - : zError(errcode)), - errcode(errcode) - {} -}; - -///Base class for deflate_streambuf and inflate_streambuf -class zlib_streambuf : public std::streambuf -{ -protected: - std::vector<char> in; - std::vector<char> out; - z_stream zstr; - - explicit zlib_streambuf(size_t bufsize): - in(bufsize), out(bufsize) - { - zstr.zalloc = Z_NULL; - zstr.zfree = Z_NULL; - zstr.opaque = Z_NULL; - } -}; - -} + /// Exception thrown in case zlib encounters a problem + class NBT_EXPORT zlib_error : public std::runtime_error + { + public: + const int errcode; + + zlib_error(const char* msg, int errcode) + : std::runtime_error(msg ? std::string(zError(errcode)) + ": " + msg + : zError(errcode)), + errcode(errcode) + { + } + }; + + /// Base class for deflate_streambuf and inflate_streambuf + class zlib_streambuf : public std::streambuf + { + protected: + std::vector<char> in; + std::vector<char> out; + z_stream zstr; + + explicit zlib_streambuf(size_t bufsize) : in(bufsize), out(bufsize) + { + zstr.zalloc = Z_NULL; + zstr.zfree = Z_NULL; + zstr.opaque = Z_NULL; + } + }; + +} // namespace zlib #endif // ZLIB_STREAMBUF_H_INCLUDED |
