summaryrefslogtreecommitdiff
path: root/libnbtplusplus/include/io
diff options
context:
space:
mode:
Diffstat (limited to 'libnbtplusplus/include/io')
-rw-r--r--libnbtplusplus/include/io/izlibstream.h107
-rw-r--r--libnbtplusplus/include/io/ozlibstream.h120
-rw-r--r--libnbtplusplus/include/io/stream_reader.h150
-rw-r--r--libnbtplusplus/include/io/stream_writer.h142
-rw-r--r--libnbtplusplus/include/io/zlib_streambuf.h51
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