diff options
Diffstat (limited to 'libnbtplusplus/include/io')
| -rw-r--r-- | libnbtplusplus/include/io/izlibstream.h | 107 | ||||
| -rw-r--r-- | libnbtplusplus/include/io/ozlibstream.h | 120 | ||||
| -rw-r--r-- | libnbtplusplus/include/io/stream_reader.h | 150 | ||||
| -rw-r--r-- | libnbtplusplus/include/io/stream_writer.h | 142 | ||||
| -rw-r--r-- | libnbtplusplus/include/io/zlib_streambuf.h | 51 |
5 files changed, 570 insertions, 0 deletions
diff --git a/libnbtplusplus/include/io/izlibstream.h b/libnbtplusplus/include/io/izlibstream.h new file mode 100644 index 0000000000..c2a8e59b04 --- /dev/null +++ b/libnbtplusplus/include/io/izlibstream.h @@ -0,0 +1,107 @@ +/* + * SPDX-FileCopyrightText: 2013, 2015 ljfa-ag <ljfa-ag@web.de> + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +/* + * libnbt++ - A library for the Minecraft Named Binary Tag format. + * Copyright (C) 2013, 2015 ljfa-ag + * + * This file is part of libnbt++. + * + * libnbt++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libnbt++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libnbt++. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef IZLIBSTREAM_H_INCLUDED +#define IZLIBSTREAM_H_INCLUDED + +#include "io/zlib_streambuf.h" +#include <istream> +#include <zlib.h> + +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; + + ///@return the wrapped istream + std::istream& get_istr() const + { + return is; + } + + private: + std::istream& is; + bool stream_end; + + 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(); + } + + private: + inflate_streambuf buf; + }; + +} // namespace zlib + +#endif // IZLIBSTREAM_H_INCLUDED diff --git a/libnbtplusplus/include/io/ozlibstream.h b/libnbtplusplus/include/io/ozlibstream.h new file mode 100644 index 0000000000..f04f33deef --- /dev/null +++ b/libnbtplusplus/include/io/ozlibstream.h @@ -0,0 +1,120 @@ +/* + * SPDX-FileCopyrightText: 2013, 2015 ljfa-ag <ljfa-ag@web.de> + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +/* + * libnbt++ - A library for the Minecraft Named Binary Tag format. + * Copyright (C) 2013, 2015 ljfa-ag + * + * This file is part of libnbt++. + * + * libnbt++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libnbt++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libnbt++. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef OZLIBSTREAM_H_INCLUDED +#define OZLIBSTREAM_H_INCLUDED + +#include "io/zlib_streambuf.h" +#include <ostream> +#include <zlib.h> + +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; + + ///@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; + + void deflate_chunk(int flush = Z_NO_FLUSH); + + 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(); + } + + /// Finishes compression and writes all pending data to the output + void close(); + + private: + deflate_streambuf buf; + }; + +} // namespace zlib + +#endif // OZLIBSTREAM_H_INCLUDED diff --git a/libnbtplusplus/include/io/stream_reader.h b/libnbtplusplus/include/io/stream_reader.h new file mode 100644 index 0000000000..05f8d99c92 --- /dev/null +++ b/libnbtplusplus/include/io/stream_reader.h @@ -0,0 +1,150 @@ +/* + * SPDX-FileCopyrightText: 2013, 2015 ljfa-ag <ljfa-ag@web.de> + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +/* + * libnbt++ - A library for the Minecraft Named Binary Tag format. + * Copyright (C) 2013, 2015 ljfa-ag + * + * This file is part of libnbt++. + * + * libnbt++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libnbt++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libnbt++. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef STREAM_READER_H_INCLUDED +#define STREAM_READER_H_INCLUDED + +#include "endian_str.h" +#include "tag.h" +#include "tag_compound.h" +#include <iosfwd> +#include <memory> +#include <stdexcept> +#include <utility> + +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 +} // namespace nbt + +#endif // STREAM_READER_H_INCLUDED diff --git a/libnbtplusplus/include/io/stream_writer.h b/libnbtplusplus/include/io/stream_writer.h new file mode 100644 index 0000000000..04f039948c --- /dev/null +++ b/libnbtplusplus/include/io/stream_writer.h @@ -0,0 +1,142 @@ +/* + * SPDX-FileCopyrightText: 2013, 2015 ljfa-ag <ljfa-ag@web.de> + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +/* + * libnbt++ - A library for the Minecraft Named Binary Tag format. + * Copyright (C) 2013, 2015 ljfa-ag + * + * This file is part of libnbt++. + * + * libnbt++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libnbt++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libnbt++. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef STREAM_WRITER_H_INCLUDED +#define STREAM_WRITER_H_INCLUDED + +#include "tag.h" +#include "endian_str.h" +#include <iosfwd> +#include <string> + +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 +} // namespace nbt + +#endif // STREAM_WRITER_H_INCLUDED diff --git a/libnbtplusplus/include/io/zlib_streambuf.h b/libnbtplusplus/include/io/zlib_streambuf.h new file mode 100644 index 0000000000..91a660b9f2 --- /dev/null +++ b/libnbtplusplus/include/io/zlib_streambuf.h @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2013, 2015 ljfa-ag <ljfa-ag@web.de> + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#ifndef ZLIB_STREAMBUF_H_INCLUDED +#define ZLIB_STREAMBUF_H_INCLUDED + +#include <stdexcept> +#include <streambuf> +#include <vector> +#include <zlib.h> +#include "nbt_export.h" + +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; + } + }; + +} // namespace zlib + +#endif // ZLIB_STREAMBUF_H_INCLUDED |
