From e6a030ba6988010d70d72cd3ac0dd076a5878763 Mon Sep 17 00:00:00 2001 From: gentlegiantJGC Date: Tue, 26 Nov 2024 17:22:02 +0000 Subject: [PATCH] Cmake (#93) * Add dll export marker This is needed to export functions from from the shared library. * Removed get_source and get_include functions * Migrated to pyproject.toml * Update MANIFEST.in * Added cmake files * Refactored setup.py to call cmake * Bumped version in readme * Added verbose logging when installing * Removed unused optional * Removed unused import * Renamed extension * Added __init__.py * Reformatted * Moved future to the beginning * Added errors if compiling fails --- .github/workflows/python-unittests.yml | 2 +- CMakeLists.txt | 56 + MANIFEST.in | 5 +- README.md | 2 +- pyproject.toml | 68 +- setup.cfg | 66 - setup.py | 88 +- src/amulet_nbt/__init__.py | 2044 +++++++++++++++++ src/amulet_nbt/__init__.pyi | 6 - src/amulet_nbt/amulet_coreConfig.cmake | 13 + .../cpp/nbt_encoding/binary/read_binary.cpp | 11 +- .../cpp/nbt_encoding/binary/write_binary.cpp | 57 +- .../cpp/nbt_encoding/string/read_string.cpp | 18 +- .../cpp/nbt_encoding/string/write_string.cpp | 79 +- src/amulet_nbt/cpp/string_encoding/mutf8.cpp | 12 +- src/amulet_nbt/cpp/string_encoding/utf8.cpp | 20 +- src/amulet_nbt/cpp/tag/copy.cpp | 7 +- src/amulet_nbt/cpp/tag/eq.cpp | 29 +- src/amulet_nbt/include/amulet_nbt/dll.hpp | 11 + .../amulet_nbt/nbt_encoding/binary.hpp | 68 +- .../amulet_nbt/nbt_encoding/string.hpp | 109 +- .../include/amulet_nbt/pybind/encoding.hpp | 1 + .../include/amulet_nbt/string_encoding.hpp | 30 +- .../include/amulet_nbt/tag/copy.hpp | 7 +- src/amulet_nbt/include/amulet_nbt/tag/eq.hpp | 29 +- src/amulet_nbt/pybind/amulet_nbt.cpp | 113 +- tests/test_amulet_nbt/test_metadata.py | 7 - 27 files changed, 2503 insertions(+), 455 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 setup.cfg create mode 100644 src/amulet_nbt/__init__.py create mode 100644 src/amulet_nbt/amulet_coreConfig.cmake create mode 100644 src/amulet_nbt/include/amulet_nbt/dll.hpp diff --git a/.github/workflows/python-unittests.yml b/.github/workflows/python-unittests.yml index 29615b9e..93a4d2f0 100644 --- a/.github/workflows/python-unittests.yml +++ b/.github/workflows/python-unittests.yml @@ -28,6 +28,6 @@ jobs: shell: bash run: | python -m pip install --upgrade pip - pip install .[dev] + pip install -vvvv .[dev] - name: Test with unittest run: python -m unittest discover -v -s tests diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..9a0f879a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,56 @@ +cmake_minimum_required(VERSION 3.13) + +project(amulet_nbt LANGUAGES CXX) +set(SRC_INSTALL_DIR "." CACHE PATH "The path to the src directory to install into.") + +# Set C++20 +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +# Set platform variables +if (WIN32) + # set windows 7 as the minimum version + add_definitions(-D_WIN32_WINNT=0x0601) +elseif(APPLE) + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15") +else() + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +endif() + +# Add pybind11 +find_package(pybind11 CONFIG REQUIRED) + +# Add implementation +add_library(amulet_nbt SHARED) +target_compile_definitions(amulet_nbt PRIVATE ExportAmuletNBT) +target_include_directories(amulet_nbt PUBLIC "src/amulet_nbt/include") +target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/nbt_encoding/binary/read_binary.cpp") +target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/nbt_encoding/binary/write_binary.cpp") +target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/nbt_encoding/string/read_string.cpp") +target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/nbt_encoding/string/write_string.cpp") +target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/string_encoding/mutf8.cpp") +target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/string_encoding/utf8.cpp") +target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/tag/copy.cpp") +target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/tag/eq.cpp") + +# Add python extension +pybind11_add_module(_amulet_nbt) +target_compile_definitions(_amulet_nbt PRIVATE PYBIND11_DETAILED_ERROR_MESSAGES) +target_link_libraries(_amulet_nbt PRIVATE amulet_nbt) +target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/amulet_nbt.cpp") +target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/bnbt.cpp") +target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/encoding.cpp") +target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/snbt.cpp") +target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_abc_tag.cpp") +target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_array_tag.cpp") +target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_compound_tag.cpp") +target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_float_tag.cpp") +target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_int_tag.cpp") +target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_list_tag.cpp") +target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_named_tag.cpp") +target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_string_tag.cpp") + +# Install +install(TARGETS amulet_nbt DESTINATION "${SRC_INSTALL_DIR}/amulet_nbt") +install(TARGETS _amulet_nbt DESTINATION "${SRC_INSTALL_DIR}/amulet_nbt") diff --git a/MANIFEST.in b/MANIFEST.in index 303049bb..151ca5af 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,5 @@ +recursive-include src/amulet_nbt *.cpp *.hpp *Config.cmake + +include CMakeLists.txt + prune tests -recursive-include src *.pyi py.typed *.py *.cpp *.hpp diff --git a/README.md b/README.md index db919485..819b7618 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ SNBT (or Stringified-NBT) is the JSON like format used in Java commands. Run this command to install from PyPi. -`pip install amulet-nbt~=3.0` +`pip install amulet-nbt~=4.0` ## Documentation diff --git a/pyproject.toml b/pyproject.toml index d6536fc9..3597bc34 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,6 +3,72 @@ requires = [ "setuptools >= 42", "wheel", "versioneer", - "pybind11 ~= 2.12", + "pybind11[global] == 2.13.6", ] build-backend = "setuptools.build_meta" + +[project] +name = "amulet-nbt" +authors = [ + {name = "James Clare"}, + {name = "Ben Gothard"}, +] +description = "Read and write Minecraft NBT and SNBT data." +dynamic = ["version", "readme"] +requires-python = ">=3.11" +classifiers = [ + "Programming Language :: Python :: 3", + "Operating System :: OS Independent", +] +dependencies = [ + "amulet-compiler-target == 1.0", + "numpy >= 1.17, < 3.0" +] + +[project.optional-dependencies] +docs = [ + "Sphinx>=1.7.4", + "sphinx-autodoc-typehints>=1.3.0", + "sphinx_rtd_theme>=0.3.1", +] +dev = [ + "black>=22.3", + "pre_commit>=1.11.1", + "mypy", + "types-pyinstaller", + "wheel", + "versioneer", + "pybind11[global] == 2.13.6", +] + +[project.urls] +Homepage = "https://www.amuletmc.com" +Repository = "https://github.com/Amulet-Team/Amulet-NBT" +Issues = "https://github.com/Amulet-Team/Amulet-NBT/issues" + +[tool.setuptools] +include-package-data = false + +[tool.setuptools.package-data] +"*" = [ + "*Config.cmake", + "**/*.hpp", + "**/*.dll", + "**/*.so", + "**/*.dylib", + "**/*.lib", +] + +[tool.setuptools.dynamic] +readme = {file = ["README.md"], content-type = "text/markdown"} + +[project.entry-points.pyinstaller40] +hook-dirs = "amulet_nbt.__pyinstaller:get_hook_dirs" + +[tool.versioneer] +VCS = "git" +style = "pep440" +versionfile_source = "src/amulet_nbt/_version.py" +versionfile_build = "amulet_nbt/_version.py" +tag_prefix = "" +parentdir_prefix = "amulet_nbt-" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index fd98d9e7..00000000 --- a/setup.cfg +++ /dev/null @@ -1,66 +0,0 @@ -[metadata] -name = amulet-nbt -url = https://www.amuletmc.com -author = James Clare, Ben Gothard -author_email = amuleteditor@gmail.com -classifiers= - Programming Language :: Python :: 3 - Operating System :: OS Independent -description = Read and write Minecraft NBT and SNBT data. -long_description = file: README.md -long_description_content_type = text/markdown -platforms = any - - -[options] -package_dir= - =src -packages = find_namespace: -zip_safe = False -python_requires = ~=3.11 -install_requires = - numpy >= 1.17, < 3.0 - -[options.packages.find] -where=src - -[options.package_data] -amulet_nbt = - *.pyi - py.typed - *.pyd - *.so - *.dylib - **/*.hpp - cpp/**/*.cpp - - -[options.extras_require] -docs = - Sphinx>=1.7.4 - sphinx-autodoc-typehints>=1.3.0 - sphinx_rtd_theme>=0.3.1 -dev = - black>=22.3 - pre_commit>=1.11.1 - mypy - types-pyinstaller - pybind11~=2.13 - - -[options.entry_points] -pyinstaller40 = - hook-dirs = amulet_nbt.__pyinstaller:get_hook_dirs - - -# See the docstring in versioneer.py for instructions. Note that you must -# re-run 'versioneer.py setup' after changing this section, and commit the -# resulting files. - -[versioneer] -VCS = git -style = pep440 -versionfile_source = src/amulet_nbt/_version.py -versionfile_build = amulet_nbt/_version.py -tag_prefix = -parentdir_prefix = amulet_nbt- diff --git a/setup.py b/setup.py index 35317858..c7b6e50a 100644 --- a/setup.py +++ b/setup.py @@ -1,43 +1,63 @@ -from setuptools import setup, Extension -import versioneer -import sysconfig -from distutils import ccompiler +import os +import subprocess import sys +from pathlib import Path import pybind11 -import glob -if (sysconfig.get_config_var("CXX") or ccompiler.get_default_compiler()).split()[ - 0 -] == "msvc": - CompileArgs = ["/std:c++20"] -else: - CompileArgs = ["-std=c++20"] +from setuptools import setup, Extension, Command +from setuptools.command.build_ext import build_ext + +import versioneer + + +# https://github.com/pybind/cmake_example/blob/master/setup.py +class CMakeExtension(Extension): + def __init__(self, name: str, sourcedir: str = "") -> None: + super().__init__(name, sources=[]) + self.sourcedir = os.fspath(Path(sourcedir).resolve()) + + +cmdclass: dict[str, type[Command]] = versioneer.get_cmdclass() + + +class CMakeBuild(cmdclass.get("build_ext", build_ext)): + def build_extension(self, ext): + ext_fullpath = Path.cwd() / self.get_ext_fullpath("") + src_dir = ext_fullpath.parent.resolve() + + platform_args = [] + if sys.platform == "win32": + platform_args.extend(["-G", "Visual Studio 17 2022"]) + if sys.maxsize > 2**32: + platform_args.extend(["-A", "x64"]) + else: + platform_args.extend(["-A", "Win32"]) + platform_args.extend(["-T", "v143"]) + + if subprocess.run( + [ + "cmake", + *platform_args, + f"-DPYTHON_EXECUTABLE={sys.executable}", + f"-Dpybind11_DIR={pybind11.get_cmake_dir().replace(os.sep, '/')}", + f"-DCMAKE_INSTALL_PREFIX=install", + f"-DSRC_INSTALL_DIR={src_dir}", + "-B", + "build", + ] + ).returncode: + raise RuntimeError("Error configuring amulet_nbt") + if subprocess.run(["cmake", "--build", "build", "--config", "Release"]).returncode: + raise RuntimeError("Error installing amulet_nbt") + if subprocess.run(["cmake", "--install", "build", "--config", "Release"]).returncode: + raise RuntimeError("Error installing amulet_nbt") + -if sys.platform == "darwin": - CompileArgs.append("-mmacosx-version-min=10.13") +cmdclass["build_ext"] = CMakeBuild setup( version=versioneer.get_version(), - cmdclass=versioneer.get_cmdclass(), - libraries=[ - ( - "amulet_nbt", - dict( - sources=glob.glob("src/amulet_nbt/cpp/**/*.cpp", recursive=True), - include_dirs=["src/amulet_nbt/include"], - cflags=CompileArgs, - ), - ) - ], - ext_modules=[ - Extension( - name="amulet_nbt.__init__", - sources=glob.glob("src/amulet_nbt/pybind/**/*.cpp", recursive=True), - include_dirs=["src/amulet_nbt/include", pybind11.get_include()], - libraries=["amulet_nbt"], - define_macros=[("PYBIND11_DETAILED_ERROR_MESSAGES", None)], - extra_compile_args=CompileArgs, - ) - ], + cmdclass=cmdclass, + ext_modules=[CMakeExtension("amulet_nbt.__init__")], ) diff --git a/src/amulet_nbt/__init__.py b/src/amulet_nbt/__init__.py new file mode 100644 index 00000000..6b18f442 --- /dev/null +++ b/src/amulet_nbt/__init__.py @@ -0,0 +1,2044 @@ +from __future__ import annotations +from typing import TYPE_CHECKING +from . import _version +import re + +if TYPE_CHECKING: + from typing import ( + Any, + SupportsInt, + SupportsFloat, + Iterator, + Iterable, + overload, + TypeVar, + Self, + Type, + Mapping, + Literal, + TypeAlias, + ClassVar, + Protocol, + ) + from collections.abc import MutableSequence, MutableMapping + import numpy + from numpy.typing import NDArray, ArrayLike + + _T = TypeVar("_T") + + class _Readable(Protocol): + def read(self) -> bytes: ... + + class _Writeable(Protocol): + def write(self, s: bytes) -> Any: ... + + class StringEncoding: + def encode(self, data: bytes) -> bytes: ... + + def decode(self, data: bytes) -> bytes: ... + + mutf8_encoding: StringEncoding + utf8_encoding: StringEncoding + utf8_escape_encoding: StringEncoding + + class EncodingPreset: + pass + + java_encoding: EncodingPreset + bedrock_encoding: EncodingPreset + + class AbstractBaseTag: + """Abstract Base Class for all Tag classes""" + + tag_id: ClassVar[int] + + @property + def py_data(self) -> Any: + """A python representation of the class. Note that the return type is undefined and may change in the future. + + You would be better off using the py_{type} or np_array properties if you require a fixed type. + This is here for convenience to get a python representation under the same property name. + """ + + def to_nbt( + self, + *, + preset: EncodingPreset | None = None, + compressed: bool = True, + little_endian: bool = False, + string_encoding: StringEncoding = mutf8_encoding, + name: str | bytes | None = b"", + ) -> bytes: + """Get the data in binary NBT format. + + :param preset: A class containing endianness and encoding presets. + :param compressed: Should the bytes be compressed with gzip. + :param little_endian: Should the bytes be saved in little endian format. Ignored if preset is defined. + :param string_encoding: The StringEncoding to use. Ignored if preset is defined. + :param name: The root tag name, or `None` for unnamed tag. + :return: The binary NBT representation of the class. + """ + + def save_to( + self, + filepath_or_buffer: str | _Writeable | None = None, + *, + preset: EncodingPreset | None = None, + compressed: bool = True, + little_endian: bool = False, + string_encoding: StringEncoding = mutf8_encoding, + name: str | bytes | None = b"", + ) -> bytes: + """Convert the data to the binary NBT format. Optionally write to a file. + + If filepath_or_buffer is a valid file path in string form the data will be written to that file. + + If filepath_or_buffer is a file like object the bytes will be written to it using .write method. + + :param filepath_or_buffer: A path or writeable object to write the data to. + :param preset: A class containing endianness and encoding presets. + :param compressed: Should the bytes be compressed with gzip. + :param little_endian: Should the bytes be saved in little endian format. Ignored if preset is defined. + :param string_encoding: The StringEncoding to use. Ignored if preset is defined. + :param name: The root tag name, or `None` for unnamed tag. + :return: The binary NBT representation of the class. + """ + + def to_snbt(self, indent: None | str | int = None) -> str: + """Convert the data to the Stringified NBT format. + + :param indent: + If None (the default) the SNBT will be on one line. + If an int will be multi-line SNBT with this many spaces per indentation. + If a string will be multi-line SNBT with this string as the indentation. + :return: The SNBT string. + """ + + def __eq__(self, other: Any) -> bool: + """Check if the instance is equal to another instance. + + This will only return True if the tag type is the same and the data contained is the same. + + >>> from amulet_nbt import ByteTag, ShortTag + >>> tag1 = ByteTag(1) + >>> tag2 = ByteTag(2) + >>> tag3 = ShortTag(1) + >>> tag1 == tag1 # True + >>> tag1 == tag2 # False + >>> tag1 == tag3 # False + """ + + def __repr__(self) -> str: + """A string representation of the object to show how it can be constructed. + + >>> from amulet_nbt import ByteTag + >>> tag = ByteTag(1) + >>> repr(tag) # "ByteTag(1)" + """ + + def __str__(self) -> str: + """A string representation of the object.""" + + def __reduce__(self) -> Any: ... + + def copy(self) -> Self: + """Return a shallow copy of the class""" + + def __copy__(self) -> Self: + """A shallow copy of the class + + >>> import copy + >>> from amulet_nbt import ListTag + >>> tag = ListTag() + >>> tag2 = copy.copy(tag) + """ + + def __deepcopy__(self, memo: dict[int, object] | None = None) -> Self: + """A deep copy of the class + + >>> import copy + >>> from amulet_nbt import ListTag + >>> tag = ListTag() + >>> tag2 = copy.deepcopy(tag) + """ + + class AbstractBaseImmutableTag(AbstractBaseTag): + """Abstract Base Class for all immutable Tag classes""" + + def __hash__(self) -> int: + """A hash of the data in the class.""" + + class AbstractBaseMutableTag(AbstractBaseTag): + """Abstract Base Class for all mutable Tag classes""" + + __hash__ = None # type: ignore + + class AbstractBaseNumericTag(AbstractBaseImmutableTag): + """Abstract Base Class for all numeric Tag classes""" + + def __int__(self) -> int: + """Get a python int representation of the class.""" + + def __float__(self) -> float: + """Get a python float representation of the class.""" + + def __bool__(self) -> bool: + """Get a python bool representation of the class.""" + + def __ge__(self, other: Any) -> bool: + """Check if the tag is greater than or equal to another tag.""" + + def __gt__(self, other: Any) -> bool: + """Check if the tag is greater than another tag.""" + + def __le__(self, other: Any) -> bool: + """Check if the tag is less than or equal to another tag.""" + + def __lt__(self, other: Any) -> bool: + """Check if the tag is less than another tag.""" + + # Types + class AbstractBaseIntTag(AbstractBaseNumericTag): + def __init__(self, value: SupportsInt = 0) -> None: ... + + @property + def py_int(self) -> int: + """A python int representation of the class. + + The returned data is immutable so changes will not mirror the instance. + """ + + class ByteTag(AbstractBaseIntTag): + """ + A 1 byte integer class. + Can Store numbers between -(2^7) and (2^7 - 1) + """ + + class ShortTag(AbstractBaseIntTag): + """ + A 2 byte integer class. + Can Store numbers between -(2^15) and (2^15 - 1) + """ + + class IntTag(AbstractBaseIntTag): + """ + A 4 byte integer class. + Can Store numbers between -(2^31) and (2^31 - 1) + """ + + class LongTag(AbstractBaseIntTag): + """ + An 8 byte integer class. + Can Store numbers between -(2^63) and (2^63 - 1) + """ + + class AbstractBaseFloatTag(AbstractBaseNumericTag): + def __init__(self, value: SupportsFloat = 0): ... + + @property + def py_float(self) -> float: + """A python float representation of the class. + + The returned data is immutable so changes will not mirror the instance. + """ + + class FloatTag(AbstractBaseFloatTag): + """A single precision float class.""" + + class DoubleTag(AbstractBaseFloatTag): + """A double precision float class.""" + + class StringTag(AbstractBaseImmutableTag): + def __init__(self, value: str | bytes | Any = "") -> None: ... + + @property + def py_str(self) -> str: + """The data stored in the class as a python string. + + In some rare cases the data cannot be decoded to a string and this will raise a UnicodeDecodeError. + """ + + @property + def py_bytes(self) -> bytes: + """The bytes stored in the class.""" + + @property + def py_str_or_bytes(self) -> str | bytes: + """If the payload is UTF-8 returns a string else returns bytes.""" + + def __ge__(self, other: Any) -> bool: + """Check if the tag is greater than or equal to another tag.""" + + def __gt__(self, other: Any) -> bool: + """Check if the tag is greater than another tag.""" + + def __le__(self, other: Any) -> bool: + """Check if the tag is less than or equal to another tag.""" + + def __lt__(self, other: Any) -> bool: + """Check if the tag is less than another tag.""" + + AnyNBTT = TypeVar("AnyNBTT", bound=AbstractBaseTag) + + class ListTag(AbstractBaseMutableTag, MutableSequence[AnyNBTT]): + @overload + def __init__(self, value: Iterable[AnyNBTT] = ()) -> None: ... + + @overload + def __init__( + self, value: Iterable[AnyNBTT] = (), element_tag_id: int = 1 + ) -> None: ... + + @property + def py_list(self) -> list[AnyNBTT]: + """A python list representation of the class. + + The returned list is a shallow copy of the class, meaning changes will not mirror the instance. + Use the public API to modify the internal data. + """ + + @property + def element_tag_id(self) -> int: + """The numerical id of the element type in this list. + + Will be an int in the range 0-12. + """ + + @property + def element_class( + self, + ) -> ( + None + | Type[ByteTag] + | Type[ShortTag] + | Type[IntTag] + | Type[LongTag] + | Type[FloatTag] + | Type[DoubleTag] + | Type[StringTag] + | Type[ByteArrayTag] + | Type[ListTag] + | Type[CompoundTag] + | Type[IntArrayTag] + | Type[LongArrayTag] + ): + """The python class for the tag type contained in this list or None if the list tag is in the 0 state.""" + + def get_byte(self, index: int) -> ByteTag: ... + + def get_short(self, index: int) -> ShortTag: ... + + def get_int(self, index: int) -> IntTag: ... + + def get_long(self, index: int) -> LongTag: ... + + def get_float(self, index: int) -> FloatTag: ... + + def get_double(self, index: int) -> DoubleTag: ... + + def get_string(self, index: int) -> StringTag: ... + + def get_list(self, index: int) -> ListTag: ... + + def get_compound(self, index: int) -> CompoundTag: ... + + def get_byte_array(self, index: int) -> ByteArrayTag: ... + + def get_int_array(self, index: int) -> IntArrayTag: ... + + def get_long_array(self, index: int) -> LongArrayTag: ... + + def insert(self, index: int, value: AnyNBTT) -> None: ... + + @overload + def __getitem__(self, index: int) -> AnyNBTT: ... + + @overload + def __getitem__(self, index: slice) -> list[AnyNBTT]: ... + + @overload + def __setitem__(self, index: int, value: AnyNBTT) -> None: ... + + @overload + def __setitem__( + self, index: slice, value: Iterable[AbstractBaseTag] + ) -> None: ... + + @overload + def __delitem__(self, index: int) -> None: ... + + @overload + def __delitem__(self, index: slice) -> None: ... + + def __len__(self) -> int: + pass + + _TagT = TypeVar("_TagT", bound=AbstractBaseTag) + + class CompoundTag(AbstractBaseMutableTag, MutableMapping[str | bytes, AnyNBT]): + def __init__( + self, + value: ( + Mapping[str | bytes, AnyNBT | AbstractBaseTag] + | Iterable[tuple[str | bytes, AnyNBT | AbstractBaseTag]] + | Mapping[str, AnyNBT | AbstractBaseTag] + | Mapping[bytes, AnyNBT | AbstractBaseTag] + ) = (), + **kwvals: AnyNBT, + ): ... + + @property + def py_dict(self) -> dict[str, AnyNBT]: + """A shallow copy of the CompoundTag as a python dictionary.""" + + @overload + def get(self, key: str | bytes) -> AnyNBT | None: ... + + @overload + def get(self, key: str | bytes, default: _T) -> AnyNBT | _T: ... + + @overload + def get(self, key: str | bytes, *, cls: Type[_TagT]) -> _TagT | None: ... + + @overload + def get(self, key: str | bytes, default: _T, cls: Type[_TagT]) -> _TagT | _T: + """Get an item from the CompoundTag. + + :param key: The key to get + :param default: The value to return if the key does not exist or the type is wrong. + :param cls: The class that the stored tag must inherit from. If the type is incorrect default is returned. + :return: The tag stored in the CompoundTag if the type is correct else default. + :raises: KeyError if the key does not exist. + :raises: TypeError if the stored type is not a subclass of cls. + """ + + @classmethod + def fromkeys(cls, keys: Iterable[str | bytes], value: AnyNBT) -> Self: ... + + @overload + def get_byte(self, key: str | bytes) -> ByteTag | None: ... + + @overload + def get_byte(self, key: str | bytes, default: None) -> ByteTag | None: ... + + @overload + def get_byte(self, key: str | bytes, default: ByteTag) -> ByteTag: ... + + @overload + def get_byte( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> ByteTag | None: ... + + @overload + def get_byte( + self, key: str | bytes, default: ByteTag, raise_errors: Literal[False] + ) -> ByteTag: ... + + @overload + def get_byte( + self, key: str | bytes, default: ByteTag | None, raise_errors: Literal[True] + ) -> ByteTag: ... + + @overload + def get_byte( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> ByteTag | None: ... + + @overload + def get_byte( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> ByteTag: ... + + @overload + def get_short(self, key: str | bytes) -> ShortTag | None: ... + + @overload + def get_short(self, key: str | bytes, default: None) -> ShortTag | None: ... + + @overload + def get_short(self, key: str | bytes, default: ShortTag) -> ShortTag: ... + + @overload + def get_short( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> ShortTag | None: ... + + @overload + def get_short( + self, key: str | bytes, default: ShortTag, raise_errors: Literal[False] + ) -> ShortTag: ... + + @overload + def get_short( + self, + key: str | bytes, + default: ShortTag | None, + raise_errors: Literal[True], + ) -> ShortTag: ... + + @overload + def get_short( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> ShortTag | None: ... + + @overload + def get_short( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> ShortTag: ... + + @overload + def get_int(self, key: str | bytes) -> IntTag | None: ... + + @overload + def get_int(self, key: str | bytes, default: None) -> IntTag | None: ... + + @overload + def get_int(self, key: str | bytes, default: IntTag) -> IntTag: ... + + @overload + def get_int( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> IntTag | None: ... + + @overload + def get_int( + self, key: str | bytes, default: IntTag, raise_errors: Literal[False] + ) -> IntTag: ... + + @overload + def get_int( + self, key: str | bytes, default: IntTag | None, raise_errors: Literal[True] + ) -> IntTag: ... + + @overload + def get_int( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> IntTag | None: ... + + @overload + def get_int( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> IntTag: ... + + @overload + def get_long(self, key: str | bytes) -> LongTag | None: ... + + @overload + def get_long(self, key: str | bytes, default: None) -> LongTag | None: ... + + @overload + def get_long(self, key: str | bytes, default: LongTag) -> LongTag: ... + + @overload + def get_long( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> LongTag | None: ... + + @overload + def get_long( + self, key: str | bytes, default: LongTag, raise_errors: Literal[False] + ) -> LongTag: ... + + @overload + def get_long( + self, key: str | bytes, default: LongTag | None, raise_errors: Literal[True] + ) -> LongTag: ... + + @overload + def get_long( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> LongTag | None: ... + + @overload + def get_long( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> LongTag: ... + + @overload + def get_float(self, key: str | bytes) -> FloatTag | None: ... + + @overload + def get_float(self, key: str | bytes, default: None) -> FloatTag | None: ... + + @overload + def get_float(self, key: str | bytes, default: FloatTag) -> FloatTag: ... + + @overload + def get_float( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> FloatTag | None: ... + + @overload + def get_float( + self, key: str | bytes, default: FloatTag, raise_errors: Literal[False] + ) -> FloatTag: ... + + @overload + def get_float( + self, + key: str | bytes, + default: FloatTag | None, + raise_errors: Literal[True], + ) -> FloatTag: ... + + @overload + def get_float( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> FloatTag | None: ... + + @overload + def get_float( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> FloatTag: ... + + @overload + def get_double(self, key: str | bytes) -> DoubleTag | None: ... + + @overload + def get_double(self, key: str | bytes, default: None) -> DoubleTag | None: ... + + @overload + def get_double(self, key: str | bytes, default: DoubleTag) -> DoubleTag: ... + + @overload + def get_double( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> DoubleTag | None: ... + + @overload + def get_double( + self, key: str | bytes, default: DoubleTag, raise_errors: Literal[False] + ) -> DoubleTag: ... + + @overload + def get_double( + self, + key: str | bytes, + default: DoubleTag | None, + raise_errors: Literal[True], + ) -> DoubleTag: ... + + @overload + def get_double( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> DoubleTag | None: ... + + @overload + def get_double( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> DoubleTag: ... + + @overload + def get_byte_array(self, key: str | bytes) -> ByteArrayTag | None: ... + + @overload + def get_byte_array( + self, key: str | bytes, default: None + ) -> ByteArrayTag | None: ... + + @overload + def get_byte_array( + self, key: str | bytes, default: ByteArrayTag + ) -> ByteArrayTag: ... + + @overload + def get_byte_array( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> ByteArrayTag | None: ... + + @overload + def get_byte_array( + self, key: str | bytes, default: ByteArrayTag, raise_errors: Literal[False] + ) -> ByteArrayTag: ... + + @overload + def get_byte_array( + self, + key: str | bytes, + default: ByteArrayTag | None, + raise_errors: Literal[True], + ) -> ByteArrayTag: ... + + @overload + def get_byte_array( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> ByteArrayTag | None: ... + + @overload + def get_byte_array( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> ByteArrayTag: ... + + @overload + def get_string(self, key: str | bytes) -> StringTag | None: ... + + @overload + def get_string(self, key: str | bytes, default: None) -> StringTag | None: ... + + @overload + def get_string(self, key: str | bytes, default: StringTag) -> StringTag: ... + + @overload + def get_string( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> StringTag | None: ... + + @overload + def get_string( + self, key: str | bytes, default: StringTag, raise_errors: Literal[False] + ) -> StringTag: ... + + @overload + def get_string( + self, + key: str | bytes, + default: StringTag | None, + raise_errors: Literal[True], + ) -> StringTag: ... + + @overload + def get_string( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> StringTag | None: ... + + @overload + def get_string( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> StringTag: ... + + @overload + def get_list(self, key: str | bytes) -> ListTag | None: ... + + @overload + def get_list(self, key: str | bytes, default: None) -> ListTag | None: ... + + @overload + def get_list(self, key: str | bytes, default: ListTag) -> ListTag: ... + + @overload + def get_list( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> ListTag | None: ... + + @overload + def get_list( + self, key: str | bytes, default: ListTag, raise_errors: Literal[False] + ) -> ListTag: ... + + @overload + def get_list( + self, key: str | bytes, default: ListTag | None, raise_errors: Literal[True] + ) -> ListTag: ... + + @overload + def get_list( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> ListTag | None: ... + + @overload + def get_list( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> ListTag: ... + + @overload + def get_compound(self, key: str | bytes) -> CompoundTag | None: ... + + @overload + def get_compound( + self, key: str | bytes, default: None + ) -> CompoundTag | None: ... + + @overload + def get_compound( + self, key: str | bytes, default: CompoundTag + ) -> CompoundTag: ... + + @overload + def get_compound( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> CompoundTag | None: ... + + @overload + def get_compound( + self, key: str | bytes, default: CompoundTag, raise_errors: Literal[False] + ) -> CompoundTag: ... + + @overload + def get_compound( + self, + key: str | bytes, + default: CompoundTag | None, + raise_errors: Literal[True], + ) -> CompoundTag: ... + + @overload + def get_compound( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> CompoundTag | None: ... + + @overload + def get_compound( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> CompoundTag: ... + + @overload + def get_int_array(self, key: str | bytes) -> IntArrayTag | None: ... + + @overload + def get_int_array( + self, key: str | bytes, default: None + ) -> IntArrayTag | None: ... + + @overload + def get_int_array( + self, key: str | bytes, default: IntArrayTag + ) -> IntArrayTag: ... + + @overload + def get_int_array( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> IntArrayTag | None: ... + + @overload + def get_int_array( + self, key: str | bytes, default: IntArrayTag, raise_errors: Literal[False] + ) -> IntArrayTag: ... + + @overload + def get_int_array( + self, + key: str | bytes, + default: IntArrayTag | None, + raise_errors: Literal[True], + ) -> IntArrayTag: ... + + @overload + def get_int_array( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> IntArrayTag | None: ... + + @overload + def get_int_array( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> IntArrayTag: ... + + @overload + def get_long_array(self, key: str | bytes) -> LongArrayTag | None: ... + + @overload + def get_long_array( + self, key: str | bytes, default: None + ) -> LongArrayTag | None: ... + + @overload + def get_long_array( + self, key: str | bytes, default: LongArrayTag + ) -> LongArrayTag: ... + + @overload + def get_long_array( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> LongArrayTag | None: ... + + @overload + def get_long_array( + self, key: str | bytes, default: LongArrayTag, raise_errors: Literal[False] + ) -> LongArrayTag: ... + + @overload + def get_long_array( + self, + key: str | bytes, + default: LongArrayTag | None, + raise_errors: Literal[True], + ) -> LongArrayTag: ... + + @overload + def get_long_array( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> LongArrayTag | None: ... + + @overload + def get_long_array( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> LongArrayTag: ... + + def setdefault_byte( + self, key: str | bytes, default: ByteTag | None = None + ) -> ByteTag: ... + + def setdefault_short( + self, key: str | bytes, default: ShortTag | None = None + ) -> ShortTag: ... + + def setdefault_int( + self, key: str | bytes, default: IntTag | None = None + ) -> IntTag: ... + + def setdefault_long( + self, key: str | bytes, default: LongTag | None = None + ) -> LongTag: ... + + def setdefault_float( + self, key: str | bytes, default: FloatTag | None = None + ) -> FloatTag: ... + + def setdefault_double( + self, key: str | bytes, default: DoubleTag | None = None + ) -> DoubleTag: ... + + def setdefault_string( + self, key: str | bytes, default: StringTag | None = None + ) -> StringTag: ... + + def setdefault_list( + self, key: str | bytes, default: ListTag | None = None + ) -> ListTag: ... + + def setdefault_compound( + self, key: str | bytes, default: CompoundTag | None = None + ) -> CompoundTag: ... + + def setdefault_byte_array( + self, key: str | bytes, default: ByteArrayTag | None = None + ) -> ByteArrayTag: ... + + def setdefault_int_array( + self, key: str | bytes, default: IntArrayTag | None = None + ) -> IntArrayTag: ... + + def setdefault_long_array( + self, key: str | bytes, default: LongArrayTag | None = None + ) -> LongArrayTag: ... + + @overload + def pop_byte(self, key: str | bytes) -> ByteTag | None: ... + + @overload + def pop_byte(self, key: str | bytes, default: None) -> ByteTag | None: ... + + @overload + def pop_byte(self, key: str | bytes, default: ByteTag) -> ByteTag: ... + + @overload + def pop_byte( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> ByteTag | None: ... + + @overload + def pop_byte( + self, key: str | bytes, default: ByteTag, raise_errors: Literal[False] + ) -> ByteTag: ... + + @overload + def pop_byte( + self, key: str | bytes, default: ByteTag | None, raise_errors: Literal[True] + ) -> ByteTag: ... + + @overload + def pop_byte( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> ByteTag | None: ... + + @overload + def pop_byte( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> ByteTag: ... + + @overload + def pop_short(self, key: str | bytes) -> ShortTag | None: ... + + @overload + def pop_short(self, key: str | bytes, default: None) -> ShortTag | None: ... + + @overload + def pop_short(self, key: str | bytes, default: ShortTag) -> ShortTag: ... + + @overload + def pop_short( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> ShortTag | None: ... + + @overload + def pop_short( + self, key: str | bytes, default: ShortTag, raise_errors: Literal[False] + ) -> ShortTag: ... + + @overload + def pop_short( + self, + key: str | bytes, + default: ShortTag | None, + raise_errors: Literal[True], + ) -> ShortTag: ... + + @overload + def pop_short( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> ShortTag | None: ... + + @overload + def pop_short( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> ShortTag: ... + + @overload + def pop_int(self, key: str | bytes) -> IntTag | None: ... + + @overload + def pop_int(self, key: str | bytes, default: None) -> IntTag | None: ... + + @overload + def pop_int(self, key: str | bytes, default: IntTag) -> IntTag: ... + + @overload + def pop_int( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> IntTag | None: ... + + @overload + def pop_int( + self, key: str | bytes, default: IntTag, raise_errors: Literal[False] + ) -> IntTag: ... + + @overload + def pop_int( + self, key: str | bytes, default: IntTag | None, raise_errors: Literal[True] + ) -> IntTag: ... + + @overload + def pop_int( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> IntTag | None: ... + + @overload + def pop_int( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> IntTag: ... + + @overload + def pop_long(self, key: str | bytes) -> LongTag | None: ... + + @overload + def pop_long(self, key: str | bytes, default: None) -> LongTag | None: ... + + @overload + def pop_long(self, key: str | bytes, default: LongTag) -> LongTag: ... + + @overload + def pop_long( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> LongTag | None: ... + + @overload + def pop_long( + self, key: str | bytes, default: LongTag, raise_errors: Literal[False] + ) -> LongTag: ... + + @overload + def pop_long( + self, key: str | bytes, default: LongTag | None, raise_errors: Literal[True] + ) -> LongTag: ... + + @overload + def pop_long( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> LongTag | None: ... + + @overload + def pop_long( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> LongTag: ... + + @overload + def pop_float(self, key: str | bytes) -> FloatTag | None: ... + + @overload + def pop_float(self, key: str | bytes, default: None) -> FloatTag | None: ... + + @overload + def pop_float(self, key: str | bytes, default: FloatTag) -> FloatTag: ... + + @overload + def pop_float( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> FloatTag | None: ... + + @overload + def pop_float( + self, key: str | bytes, default: FloatTag, raise_errors: Literal[False] + ) -> FloatTag: ... + + @overload + def pop_float( + self, + key: str | bytes, + default: FloatTag | None, + raise_errors: Literal[True], + ) -> FloatTag: ... + + @overload + def pop_float( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> FloatTag | None: ... + + @overload + def pop_float( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> FloatTag: ... + + @overload + def pop_double(self, key: str | bytes) -> DoubleTag | None: ... + + @overload + def pop_double(self, key: str | bytes, default: None) -> DoubleTag | None: ... + + @overload + def pop_double(self, key: str | bytes, default: DoubleTag) -> DoubleTag: ... + + @overload + def pop_double( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> DoubleTag | None: ... + + @overload + def pop_double( + self, key: str | bytes, default: DoubleTag, raise_errors: Literal[False] + ) -> DoubleTag: ... + + @overload + def pop_double( + self, + key: str | bytes, + default: DoubleTag | None, + raise_errors: Literal[True], + ) -> DoubleTag: ... + + @overload + def pop_double( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> DoubleTag | None: ... + + @overload + def pop_double( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> DoubleTag: ... + + @overload + def pop_byte_array(self, key: str | bytes) -> ByteArrayTag | None: ... + + @overload + def pop_byte_array( + self, key: str | bytes, default: None + ) -> ByteArrayTag | None: ... + + @overload + def pop_byte_array( + self, key: str | bytes, default: ByteArrayTag + ) -> ByteArrayTag: ... + + @overload + def pop_byte_array( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> ByteArrayTag | None: ... + + @overload + def pop_byte_array( + self, key: str | bytes, default: ByteArrayTag, raise_errors: Literal[False] + ) -> ByteArrayTag: ... + + @overload + def pop_byte_array( + self, + key: str | bytes, + default: ByteArrayTag | None, + raise_errors: Literal[True], + ) -> ByteArrayTag: ... + + @overload + def pop_byte_array( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> ByteArrayTag | None: ... + + @overload + def pop_byte_array( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> ByteArrayTag: ... + + @overload + def pop_string(self, key: str | bytes) -> StringTag | None: ... + + @overload + def pop_string(self, key: str | bytes, default: None) -> StringTag | None: ... + + @overload + def pop_string(self, key: str | bytes, default: StringTag) -> StringTag: ... + + @overload + def pop_string( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> StringTag | None: ... + + @overload + def pop_string( + self, key: str | bytes, default: StringTag, raise_errors: Literal[False] + ) -> StringTag: ... + + @overload + def pop_string( + self, + key: str | bytes, + default: StringTag | None, + raise_errors: Literal[True], + ) -> StringTag: ... + + @overload + def pop_string( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> StringTag | None: ... + + @overload + def pop_string( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> StringTag: ... + + @overload + def pop_list(self, key: str | bytes) -> ListTag | None: ... + + @overload + def pop_list(self, key: str | bytes, default: None) -> ListTag | None: ... + + @overload + def pop_list(self, key: str | bytes, default: ListTag) -> ListTag: ... + + @overload + def pop_list( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> ListTag | None: ... + + @overload + def pop_list( + self, key: str | bytes, default: ListTag, raise_errors: Literal[False] + ) -> ListTag: ... + + @overload + def pop_list( + self, key: str | bytes, default: ListTag | None, raise_errors: Literal[True] + ) -> ListTag: ... + + @overload + def pop_list( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> ListTag | None: ... + + @overload + def pop_list( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> ListTag: ... + + @overload + def pop_compound(self, key: str | bytes) -> CompoundTag | None: ... + + @overload + def pop_compound( + self, key: str | bytes, default: None + ) -> CompoundTag | None: ... + + @overload + def pop_compound( + self, key: str | bytes, default: CompoundTag + ) -> CompoundTag: ... + + @overload + def pop_compound( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> CompoundTag | None: ... + + @overload + def pop_compound( + self, key: str | bytes, default: CompoundTag, raise_errors: Literal[False] + ) -> CompoundTag: ... + + @overload + def pop_compound( + self, + key: str | bytes, + default: CompoundTag | None, + raise_errors: Literal[True], + ) -> CompoundTag: ... + + @overload + def pop_compound( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> CompoundTag | None: ... + + @overload + def pop_compound( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> CompoundTag: ... + + @overload + def pop_int_array(self, key: str | bytes) -> IntArrayTag | None: ... + + @overload + def pop_int_array( + self, key: str | bytes, default: None + ) -> IntArrayTag | None: ... + + @overload + def pop_int_array( + self, key: str | bytes, default: IntArrayTag + ) -> IntArrayTag: ... + + @overload + def pop_int_array( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> IntArrayTag | None: ... + + @overload + def pop_int_array( + self, key: str | bytes, default: IntArrayTag, raise_errors: Literal[False] + ) -> IntArrayTag: ... + + @overload + def pop_int_array( + self, + key: str | bytes, + default: IntArrayTag | None, + raise_errors: Literal[True], + ) -> IntArrayTag: ... + + @overload + def pop_int_array( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> IntArrayTag | None: ... + + @overload + def pop_int_array( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> IntArrayTag: ... + + @overload + def pop_long_array(self, key: str | bytes) -> LongArrayTag | None: ... + + @overload + def pop_long_array( + self, key: str | bytes, default: None + ) -> LongArrayTag | None: ... + + @overload + def pop_long_array( + self, key: str | bytes, default: LongArrayTag + ) -> LongArrayTag: ... + + @overload + def pop_long_array( + self, key: str | bytes, default: None, raise_errors: Literal[False] + ) -> LongArrayTag | None: ... + + @overload + def pop_long_array( + self, key: str | bytes, default: LongArrayTag, raise_errors: Literal[False] + ) -> LongArrayTag: ... + + @overload + def pop_long_array( + self, + key: str | bytes, + default: LongArrayTag | None, + raise_errors: Literal[True], + ) -> LongArrayTag: ... + + @overload + def pop_long_array( + self, key: str | bytes, *, raise_errors: Literal[False] + ) -> LongArrayTag | None: ... + + @overload + def pop_long_array( + self, key: str | bytes, *, raise_errors: Literal[True] + ) -> LongArrayTag: ... + + def __setitem__(self, key: str | bytes, value: AnyNBT) -> None: ... + + def __delitem__(self, key: str | bytes) -> None: ... + + def __getitem__(self, key: str | bytes) -> AnyNBT: ... + + def __len__(self) -> int: ... + + def __iter__(self) -> Iterator[str | bytes]: ... + + class AbstractBaseArrayTag(AbstractBaseMutableTag): + def __init__(self, value: Iterable[SupportsInt] = ()) -> None: ... + + @property + def np_array(self) -> numpy.ndarray: + """A numpy array holding the same internal data. + + Changes to the array will also modify the internal state. + """ + + def __len__(self) -> int: + """The length of the array. + + >>> from amulet_nbt import ByteArrayTag + >>> tag = ByteArrayTag([1, 2, 3]) + >>> len(tag) # 3 + """ + + @overload + def __getitem__(self, item: int) -> numpy.int8 | numpy.int32 | numpy.int64: + """Get item(s) from the array. + + This supports the full numpy protocol. + If a numpy array is returned, the array data is the same as the data contained in this class. + + >>> from amulet_nbt import ByteArrayTag + >>> import numpy + >>> tag = ByteArrayTag([1, 2, 3]) + >>> tag[0] # 1 + >>> tag[:1] # numpy.array([1], dtype=numpy.int8) + >>> tag[numpy.array([1, 2])] # numpy.array([2, 3], dtype=int8) + """ + + @overload + def __getitem__( + self, item: slice + ) -> NDArray[numpy.int8 | numpy.int32 | numpy.int64]: ... + + @overload + def __getitem__( + self, item: NDArray[numpy.integer] + ) -> NDArray[numpy.int8 | numpy.int32 | numpy.int64]: ... + + def __iter__(self) -> Iterator[numpy.int8 | numpy.int32 | numpy.int64]: + """Iterate through the items in the array. + + >>> from amulet_nbt import ByteArrayTag + >>> tag = ByteArrayTag([1, 2, 3]) + >>> for num in tag: + >>> pass + >>> iter(tag) + """ + + def __reversed__(self) -> Iterator[numpy.int8 | numpy.int32 | numpy.int64]: + """Iterate through the items in the array in reverse order. + + >>> from amulet_nbt import ByteArrayTag + >>> tag = ByteArrayTag([1, 2, 3]) + >>> for num in reversed(tag): + >>> pass + """ + + def __contains__(self, item: Any) -> bool: + """Check if an item is in the array. + + >>> from amulet_nbt import ByteArrayTag + >>> tag = ByteArrayTag([1, 2, 3]) + >>> 1 in tag # True + """ + + @overload + def __setitem__(self, item: int, value: SupportsInt) -> None: ... + + @overload + def __setitem__( + self, + item: slice, + value: Iterable[SupportsInt], + ) -> None: ... + + @overload + def __setitem__( + self, + item: ArrayLike, + value: Iterable[SupportsInt], + ) -> None: + """Set item(s) in the array. + + This supports the full numpy protocol. + + >>> from amulet_nbt import ByteArrayTag + >>> import numpy + >>> tag = ByteArrayTag([1, 2, 3]) + >>> tag[0] = 10 # [10, 2, 3] + >>> tag[:2] = [4, 5] # [4, 5, 3] + >>> tag[numpy.array([1, 2])] = [6, 7] # [4, 6, 7] + """ + + def __array__( + self, dtype: numpy.dtype | None = None + ) -> NDArray[numpy.int8 | numpy.int32 | numpy.int64]: + """Get a numpy array representation of the stored data. + + >>> from amulet_nbt import ByteArrayTag + >>> import numpy + >>> tag = ByteArrayTag([1, 2, 3]) + >>> arr = numpy.asarray(tag) + """ + + class ByteArrayTag(AbstractBaseArrayTag): + @property + def np_array(self) -> NDArray[numpy.int8]: ... + + def __len__(self) -> int: + """The length of the array. + + >>> from amulet_nbt import ByteArrayTag + >>> tag = ByteArrayTag([1, 2, 3]) + >>> len(tag) # 3 + """ + + @overload + def __getitem__(self, item: int) -> numpy.int8: + """Get item(s) from the array. + + This supports the full numpy protocol. + If a numpy array is returned, the array data is the same as the data contained in this class. + + >>> from amulet_nbt import ByteArrayTag + >>> import numpy + >>> tag = ByteArrayTag([1, 2, 3]) + >>> tag[0] # 1 + >>> tag[:1] # numpy.array([1], dtype=numpy.int8) + >>> tag[numpy.array([1, 2])] # numpy.array([2, 3], dtype=int8) + """ + + @overload + def __getitem__(self, item: slice) -> NDArray[numpy.int8]: ... + + @overload + def __getitem__(self, item: NDArray[numpy.integer]) -> NDArray[numpy.int8]: ... + + def __iter__(self) -> Iterator[numpy.int8]: + """Iterate through the items in the array. + + >>> from amulet_nbt import ByteArrayTag + >>> tag = ByteArrayTag([1, 2, 3]) + >>> for num in tag: + >>> pass + >>> iter(tag) + """ + + def __reversed__(self) -> Iterator[numpy.int8]: + """Iterate through the items in the array in reverse order. + + >>> from amulet_nbt import ByteArrayTag + >>> tag = ByteArrayTag([1, 2, 3]) + >>> for num in reversed(tag): + >>> pass + """ + + def __contains__(self, value: int) -> bool: + """Check if an item is in the array. + + >>> from amulet_nbt import ByteArrayTag + >>> tag = ByteArrayTag([1, 2, 3]) + >>> 1 in tag # True + """ + + @overload + def __setitem__(self, item: int, value: SupportsInt) -> None: ... + + @overload + def __setitem__(self, item: slice, value: Iterable[SupportsInt]) -> None: ... + + @overload + def __setitem__(self, item: ArrayLike, value: Iterable[SupportsInt]) -> None: + """Set item(s) in the array. + + This supports the full numpy protocol. + + >>> from amulet_nbt import ByteArrayTag + >>> import numpy + >>> tag = ByteArrayTag([1, 2, 3]) + >>> tag[0] = 10 # [10, 2, 3] + >>> tag[:2] = [4, 5] # [4, 5, 3] + >>> tag[numpy.array([1, 2])] = [6, 7] # [4, 6, 7] + """ + + def __array__(self, dtype: numpy.dtype | None = None) -> NDArray[numpy.int8]: + """Get a numpy array representation of the stored data. + + >>> from amulet_nbt import ByteArrayTag + >>> import numpy + >>> tag = ByteArrayTag([1, 2, 3]) + >>> arr = numpy.asarray(tag) + """ + + class IntArrayTag(AbstractBaseArrayTag): + @property + def np_array(self) -> NDArray[numpy.int32]: ... + + def __len__(self) -> int: + """The length of the array. + + >>> from amulet_nbt import IntArrayTag + >>> tag = IntArrayTag([1, 2, 3]) + >>> len(tag) # 3 + """ + + @overload + def __getitem__(self, item: int) -> numpy.int32: + """Get item(s) from the array. + + This supports the full numpy protocol. + If a numpy array is returned, the array data is the same as the data contained in this class. + + >>> from amulet_nbt import IntArrayTag + >>> import numpy + >>> tag = IntArrayTag([1, 2, 3]) + >>> tag[0] # 1 + >>> tag[:1] # numpy.array([1], dtype=numpy.int32) + >>> tag[numpy.array([1, 2])] # numpy.array([2, 3], dtype=int32) + """ + + @overload + def __getitem__(self, item: slice) -> NDArray[numpy.int32]: ... + + @overload + def __getitem__(self, item: NDArray[numpy.integer]) -> NDArray[numpy.int32]: ... + + def __iter__(self) -> Iterator[numpy.int32]: + """Iterate through the items in the array. + + >>> from amulet_nbt import IntArrayTag + >>> tag = IntArrayTag([1, 2, 3]) + >>> for num in tag: + >>> pass + >>> iter(tag) + """ + + def __reversed__(self) -> Iterator[numpy.int32]: + """Iterate through the items in the array in reverse order. + + >>> from amulet_nbt import IntArrayTag + >>> tag = IntArrayTag([1, 2, 3]) + >>> for num in reversed(tag): + >>> pass + """ + + def __contains__(self, value: int) -> bool: + """Check if an item is in the array. + + >>> from amulet_nbt import IntArrayTag + >>> tag = IntArrayTag([1, 2, 3]) + >>> 1 in tag # True + """ + + @overload + def __setitem__(self, item: int, value: SupportsInt) -> None: ... + + @overload + def __setitem__(self, item: slice, value: Iterable[SupportsInt]) -> None: ... + + @overload + def __setitem__(self, item: ArrayLike, value: Iterable[SupportsInt]) -> None: + """Set item(s) in the array. + + This supports the full numpy protocol. + + >>> from amulet_nbt import IntArrayTag + >>> import numpy + >>> tag = IntArrayTag([1, 2, 3]) + >>> tag[0] = 10 # [10, 2, 3] + >>> tag[:2] = [4, 5] # [4, 5, 3] + >>> tag[numpy.array([1, 2])] = [6, 7] # [4, 6, 7] + """ + + def __array__(self, dtype: numpy.dtype | None = None) -> NDArray[numpy.int32]: + """Get a numpy array representation of the stored data. + + >>> from amulet_nbt import IntArrayTag + >>> import numpy + >>> tag = IntArrayTag([1, 2, 3]) + >>> arr = numpy.asarray(tag) + """ + + class LongArrayTag(AbstractBaseArrayTag): + @property + def np_array(self) -> NDArray[numpy.int64]: ... + + def __len__(self) -> int: + """The length of the array. + + >>> from amulet_nbt import LongArrayTag + >>> tag = LongArrayTag([1, 2, 3]) + >>> len(tag) # 3 + """ + + @overload + def __getitem__(self, item: int) -> numpy.int64: + """Get item(s) from the array. + + This supports the full numpy protocol. + If a numpy array is returned, the array data is the same as the data contained in this class. + + >>> from amulet_nbt import LongArrayTag + >>> import numpy + >>> tag = LongArrayTag([1, 2, 3]) + >>> tag[0] # 1 + >>> tag[:1] # numpy.array([1], dtype=numpy.int64) + >>> tag[numpy.array([1, 2])] # numpy.array([2, 3], dtype=int64) + """ + + @overload + def __getitem__(self, item: slice) -> NDArray[numpy.int64]: ... + + @overload + def __getitem__(self, item: NDArray[numpy.integer]) -> NDArray[numpy.int64]: ... + + def __iter__(self) -> Iterator[numpy.int64]: + """Iterate through the items in the array. + + >>> from amulet_nbt import LongArrayTag + >>> tag = LongArrayTag([1, 2, 3]) + >>> for num in tag: + >>> pass + >>> iter(tag) + """ + + def __reversed__(self) -> Iterator[numpy.int64]: + """Iterate through the items in the array in reverse order. + + >>> from amulet_nbt import LongArrayTag + >>> tag = LongArrayTag([1, 2, 3]) + >>> for num in reversed(tag): + >>> pass + """ + + def __contains__(self, value: int) -> bool: + """Check if an item is in the array. + + >>> from amulet_nbt import LongArrayTag + >>> tag = LongArrayTag([1, 2, 3]) + >>> 1 in tag # True + """ + + @overload + def __setitem__(self, item: int, value: SupportsInt) -> None: ... + + @overload + def __setitem__(self, item: slice, value: Iterable[SupportsInt]) -> None: ... + + @overload + def __setitem__(self, item: ArrayLike, value: Iterable[SupportsInt]) -> None: + """Set item(s) in the array. + + This supports the full numpy protocol. + + >>> from amulet_nbt import LongArrayTag + >>> import numpy + >>> tag = LongArrayTag([1, 2, 3]) + >>> tag[0] = 10 # [10, 2, 3] + >>> tag[:2] = [4, 5] # [4, 5, 3] + >>> tag[numpy.array([1, 2])] = [6, 7] # [4, 6, 7] + """ + + def __array__(self, dtype: numpy.dtype | None = None) -> NDArray[numpy.int64]: + """Get a numpy array representation of the stored data. + + >>> from amulet_nbt import LongArrayTag + >>> import numpy + >>> tag = LongArrayTag([1, 2, 3]) + >>> arr = numpy.asarray(tag) + """ + + # Alias + TAG_Byte: TypeAlias = ByteTag + TAG_Short: TypeAlias = ShortTag + TAG_Int: TypeAlias = IntTag + TAG_Long: TypeAlias = LongTag + TAG_Float: TypeAlias = FloatTag + TAG_Double: TypeAlias = DoubleTag + TAG_String: TypeAlias = StringTag + TAG_Byte_Array: TypeAlias = ByteArrayTag + TAG_List: TypeAlias = ListTag + TAG_Compound: TypeAlias = CompoundTag + TAG_Int_Array: TypeAlias = IntArrayTag + TAG_Long_Array: TypeAlias = LongArrayTag + + class NamedTag(tuple[str | bytes, AnyNBT]): + def __init__( + self, tag: AbstractBaseTag | AnyNBT | None = None, name: str | bytes = "" + ) -> None: ... + + @property + def tag(self) -> AnyNBT: ... + + @tag.setter + def tag(self, tag: AnyNBT) -> None: ... + + @property + def name(self) -> str | bytes: ... + + @name.setter + def name(self, name: str | bytes) -> None: ... + + def to_nbt( + self, + *, + preset: EncodingPreset | None = None, + compressed: bool = True, + little_endian: bool = False, + string_encoding: StringEncoding = mutf8_encoding, + ) -> bytes: + """Get the data in binary NBT format. + + :param preset: A class containing endianness and encoding presets. + :param compressed: Should the bytes be compressed with gzip. + :param little_endian: Should the bytes be saved in little endian format. Ignored if preset is defined. + :param string_encoding: A function to encode strings to bytes. Ignored if preset is defined. + :return: The binary NBT representation of the class. + """ + + def save_to( + self, + filepath_or_buffer: str | _Writeable | None = None, + *, + preset: EncodingPreset | None = None, + compressed: bool = True, + little_endian: bool = False, + string_encoding: StringEncoding = mutf8_encoding, + ) -> bytes: + """Convert the data to the binary NBT format. Optionally write to a file. + + If filepath_or_buffer is a valid file path in string form the data will be written to that file. + + If filepath_or_buffer is a file like object the bytes will be written to it using .write method. + + :param filepath_or_buffer: A path or writeable object to write the data to. + :param preset: A class containing endianness and encoding presets. + :param compressed: Should the bytes be compressed with gzip. + :param little_endian: Should the bytes be saved in little endian format. Ignored if preset is defined. + :param string_encoding: The StringEncoding to use. Ignored if preset is defined. + :return: The binary NBT representation of the class. + """ + + def to_snbt(self, indent: None | str | int = None) -> str: + """Convert the data to the Stringified NBT format. + + :param indent: + If None (the default) the SNBT will be on one line. + If an int will be multi-line SNBT with this many spaces per indentation. + If a string will be multi-line SNBT with this string as the indentation. + :return: The SNBT string. + """ + + @property + def byte(self) -> ByteTag: ... + + @property + def short(self) -> ShortTag: ... + + @property + def int(self) -> IntTag: ... + + @property + def long(self) -> LongTag: ... + + @property + def float(self) -> FloatTag: ... + + @property + def double(self) -> DoubleTag: ... + + @property + def string(self) -> StringTag: ... + + @property + def list(self) -> ListTag: ... + + @property + def compound(self) -> CompoundTag: ... + + @property + def byte_array(self) -> ByteArrayTag: ... + + @property + def int_array(self) -> IntArrayTag: ... + + @property + def long_array(self) -> LongArrayTag: ... + + class ReadOffset: + offset: int + + @overload + def read_nbt( + filepath_or_buffer: str | bytes | memoryview | _Readable | None, + *, + preset: EncodingPreset | None = None, + named: bool = True, + read_offset: ReadOffset | None = None, + ) -> NamedTag: + """Load one binary NBT object. + + :param filepath_or_buffer: A string path to a file on disk, a bytes or memory view object containing the binary NBT or a file-like object to read the binary data from. + :param preset: The encoding preset. If this is defined little_endian and string_encoding have no effect. + :param named: If the tag to read is named, if not, return NamedTag with empty name. + :param read_offset: Optional ReadOffset object to get read end offset. + :raises: IndexError if the data is not long enough. + """ + + @overload + def read_nbt( + filepath_or_buffer: str | bytes | memoryview | _Readable | None, + *, + compressed: bool = True, + little_endian: bool = False, + string_encoding: StringEncoding = mutf8_encoding, + named: bool = True, + read_offset: ReadOffset | None = None, + ) -> NamedTag: + """Load one binary NBT object. + + :param filepath_or_buffer: A string path to a file on disk, a bytes or memory view object containing the binary NBT or a file-like object to read the binary data from. + :param compressed: Is the binary data gzip compressed. + :param little_endian: Are the numerical values stored as little endian. True for Bedrock, False for Java. + :param string_encoding: The bytes decoder function to parse strings. mutf8_encoding for Java, utf8_escape_encoding for Bedrock. + :param named: If the tag to read is named, if not, return NamedTag with empty name. + :param read_offset: Optional ReadOffset object to get read end offset. + :raises: IndexError if the data is not long enough. + """ + + @overload + def read_nbt_array( + filepath_or_buffer: str | bytes | memoryview | _Readable | None, + *, + count: int = 1, + preset: EncodingPreset | None = None, + named: bool = True, + read_offset: ReadOffset | None = None, + ) -> list[NamedTag]: + """Load an array of binary NBT objects from a contiguous buffer. + + :param filepath_or_buffer: A string path to a file on disk, a bytes or memory view object containing the binary NBT or a file-like object to read the binary data from. + :param count: The number of binary NBT objects to read. Use -1 to exhaust the buffer. + :param preset: The encoding preset. If this is defined little_endian and string_encoding have no effect. + :param named: If the tags to read are named, if not, return NamedTags with empty name. + :param read_offset: Optional ReadOffset object to get read end offset. + :raises: IndexError if the data is not long enough. + """ + + @overload + def read_nbt_array( + filepath_or_buffer: str | bytes | memoryview | _Readable | None, + *, + count: int = 1, + compressed: bool = True, + little_endian: bool = False, + string_encoding: StringEncoding = mutf8_encoding, + named: bool = True, + read_offset: ReadOffset | None = None, + ) -> list[NamedTag]: + """Load an array of binary NBT objects from a contiguous buffer. + + :param filepath_or_buffer: A string path to a file on disk, a bytes or memory view object containing the binary NBT or a file-like object to read the binary data from. + :param count: The number of binary NBT objects to read. Use -1 to exhaust the buffer. + :param compressed: Is the binary data gzip compressed. This only supports the whole buffer compressed as one. + :param little_endian: Are the numerical values stored as little endian. True for Bedrock, False for Java. + :param string_encoding: The bytes decoder function to parse strings. mutf8.decode_modified_utf8 for Java, amulet_nbt.utf8_escape_decoder for Bedrock. + :param named: If the tags to read are named, if not, return NamedTags with empty name. + :param read_offset: Optional ReadOffset object to get read end offset. + :raises: IndexError if the data is not long enough. + """ + + def read_snbt(snbt: str) -> AnyNBT: + """ + Load Stringified NBT into a tag. + """ + + +__version__ = _version.get_versions()["version"] +__major__ = int(re.match(r"\d+", __version__).group()) + + +def _init() -> None: + import os + import sys + import ctypes + + if sys.platform == "win32": + lib_path = os.path.join(os.path.dirname(__file__), "amulet_nbt.dll") + elif sys.platform == "darwin": + lib_path = os.path.join(os.path.dirname(__file__), "libamulet_nbt.dylib") + elif sys.platform == "linux": + lib_path = os.path.join(os.path.dirname(__file__), "libamulet_nbt.so") + else: + raise RuntimeError(f"Unsupported platform {sys.platform}") + + # Load the shared library + ctypes.cdll.LoadLibrary(lib_path) + + from ._amulet_nbt import init + + init(sys.modules[__name__]) + + +_init() + + +__all__ = [ + "__version__", + "__major__", + "AbstractBaseTag", + "AbstractBaseImmutableTag", + "AbstractBaseMutableTag", + "AbstractBaseNumericTag", + "AbstractBaseIntTag", + "ByteTag", + "TAG_Byte", + "ShortTag", + "TAG_Short", + "IntTag", + "TAG_Int", + "LongTag", + "TAG_Long", + "AbstractBaseFloatTag", + "FloatTag", + "TAG_Float", + "DoubleTag", + "TAG_Double", + "AbstractBaseArrayTag", + "ByteArrayTag", + "TAG_Byte_Array", + "IntArrayTag", + "TAG_Int_Array", + "LongArrayTag", + "TAG_Long_Array", + "StringTag", + "TAG_String", + "ListTag", + "TAG_List", + "CompoundTag", + "TAG_Compound", + "NamedTag", + "read_nbt", + "read_nbt_array", + "ReadOffset", + "read_snbt", + "SNBTType", + "IntType", + "FloatType", + "NumberType", + "ArrayType", + "AnyNBT", + "StringEncoding", + "mutf8_encoding", + "utf8_encoding", + "utf8_escape_encoding", + "EncodingPreset", + "java_encoding", + "bedrock_encoding", +] + + +SNBTType: TypeAlias = str +IntType: TypeAlias = ByteTag | ShortTag | IntTag | LongTag +FloatType: TypeAlias = FloatTag | DoubleTag +NumberType: TypeAlias = IntType | FloatType +ArrayType: TypeAlias = ByteArrayTag | IntArrayTag | LongArrayTag + +AnyNBT: TypeAlias = NumberType | StringTag | ListTag | CompoundTag | ArrayType diff --git a/src/amulet_nbt/__init__.pyi b/src/amulet_nbt/__init__.pyi index 00d542c2..cd238d37 100644 --- a/src/amulet_nbt/__init__.pyi +++ b/src/amulet_nbt/__init__.pyi @@ -11,7 +11,6 @@ from typing import ( Self, Type, Mapping, - Optional, Literal, TypeAlias, ClassVar, @@ -75,13 +74,8 @@ __all__ = [ "EncodingPreset", "java_encoding", "bedrock_encoding", - "get_include", - "get_source", ] -def get_include() -> str: ... -def get_source() -> str: ... - class _Readable(Protocol): def read(self) -> bytes: ... diff --git a/src/amulet_nbt/amulet_coreConfig.cmake b/src/amulet_nbt/amulet_coreConfig.cmake new file mode 100644 index 00000000..4ee4e53e --- /dev/null +++ b/src/amulet_nbt/amulet_coreConfig.cmake @@ -0,0 +1,13 @@ +if (NOT TARGET amulet_nbt) + message(STATUS "Finding amulet_nbt") + + set(amulet_nbt_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/include") + find_library(amulet_nbt_LIBRARY NAMES amulet_nbt PATHS "${CMAKE_CURRENT_LIST_DIR}") + message(STATUS "amulet_nbt_LIBRARY: ${amulet_nbt_LIBRARY}") + + add_library(amulet_nbt SHARED IMPORTED) + set_target_properties(amulet_nbt PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${amulet_nbt_INCLUDE_DIR}" + IMPORTED_IMPLIB "${amulet_nbt_LIBRARY}" + ) +endif() diff --git a/src/amulet_nbt/cpp/nbt_encoding/binary/read_binary.cpp b/src/amulet_nbt/cpp/nbt_encoding/binary/read_binary.cpp index c8430290..157c51f7 100644 --- a/src/amulet_nbt/cpp/nbt_encoding/binary/read_binary.cpp +++ b/src/amulet_nbt/cpp/nbt_encoding/binary/read_binary.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -164,7 +165,7 @@ inline AmuletNBT::TagNode read_node(AmuletNBT::BinaryReader& reader, std::uint8_ namespace AmuletNBT { - AmuletNBT::NamedTag read_nbt(AmuletNBT::BinaryReader& reader, bool named){ + AMULET_NBT_DLLX AmuletNBT::NamedTag read_nbt(AmuletNBT::BinaryReader& reader, bool named){ std::uint8_t tag_id = reader.readNumeric(); std::string name = named ? read_string_tag(reader) : ""; AmuletNBT::TagNode node = read_node(reader, tag_id); @@ -172,19 +173,19 @@ namespace AmuletNBT { } // Read one (un)named tag from the string at position offset. - AmuletNBT::NamedTag read_nbt(std::string_view raw, std::endian endianness, AmuletNBT::StringDecode string_decode, size_t& offset, bool named){ + AMULET_NBT_DLLX AmuletNBT::NamedTag read_nbt(std::string_view raw, std::endian endianness, AmuletNBT::StringDecode string_decode, size_t& offset, bool named){ AmuletNBT::BinaryReader reader(raw, offset, endianness, string_decode); return read_nbt(reader, named); } // Read one (un)named tag from the string. - AmuletNBT::NamedTag read_nbt(std::string_view raw, std::endian endianness, AmuletNBT::StringDecode string_decode, bool named){ + AMULET_NBT_DLLX AmuletNBT::NamedTag read_nbt(std::string_view raw, std::endian endianness, AmuletNBT::StringDecode string_decode, bool named){ size_t offset = 0; return read_nbt(raw, endianness, string_decode, offset, named); } // Read count (un)named tags from the string at position offset. - std::vector read_nbt_array(std::string_view raw, std::endian endianness, AmuletNBT::StringDecode string_decode, size_t& offset, size_t count, bool named){ + AMULET_NBT_DLLX std::vector read_nbt_array(std::string_view raw, std::endian endianness, AmuletNBT::StringDecode string_decode, size_t& offset, size_t count, bool named){ AmuletNBT::BinaryReader reader(raw, offset, endianness, string_decode); std::vector out; for (size_t i = 0; i < count; i++){ @@ -194,7 +195,7 @@ namespace AmuletNBT { } // Read all (un)named tags from the string at position offset. - std::vector read_nbt_array(std::string_view raw, std::endian endianness, AmuletNBT::StringDecode string_decode, size_t& offset, bool named){ + AMULET_NBT_DLLX std::vector read_nbt_array(std::string_view raw, std::endian endianness, AmuletNBT::StringDecode string_decode, size_t& offset, bool named){ AmuletNBT::BinaryReader reader(raw, offset, endianness, string_decode); std::vector out; while (reader.has_more_data()){ diff --git a/src/amulet_nbt/cpp/nbt_encoding/binary/write_binary.cpp b/src/amulet_nbt/cpp/nbt_encoding/binary/write_binary.cpp index 292d4325..d59bd893 100644 --- a/src/amulet_nbt/cpp/nbt_encoding/binary/write_binary.cpp +++ b/src/amulet_nbt/cpp/nbt_encoding/binary/write_binary.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -219,89 +220,89 @@ inline std::string _write_nbt(const std::optional& name, const T& t } namespace AmuletNBT { - void write_nbt(BinaryWriter& writer, const std::optional& name, const ByteTag& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const std::optional& name, const ByteTag& tag) { write_name_and_tag(writer, name, tag); } - void write_nbt(BinaryWriter& writer, const std::optional& name, const ShortTag& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const std::optional& name, const ShortTag& tag) { write_name_and_tag(writer, name, tag); } - void write_nbt(BinaryWriter& writer, const std::optional& name, const IntTag& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const std::optional& name, const IntTag& tag) { write_name_and_tag(writer, name, tag); } - void write_nbt(BinaryWriter& writer, const std::optional& name, const LongTag& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const std::optional& name, const LongTag& tag) { write_name_and_tag(writer, name, tag); } - void write_nbt(BinaryWriter& writer, const std::optional& name, const FloatTag& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const std::optional& name, const FloatTag& tag) { write_name_and_tag(writer, name, tag); } - void write_nbt(BinaryWriter& writer, const std::optional& name, const DoubleTag& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const std::optional& name, const DoubleTag& tag) { write_name_and_tag(writer, name, tag); } - void write_nbt(BinaryWriter& writer, const std::optional& name, const ByteArrayTag& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const std::optional& name, const ByteArrayTag& tag) { write_name_and_tag(writer, name, tag); } - void write_nbt(BinaryWriter& writer, const std::optional& name, const StringTag& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const std::optional& name, const StringTag& tag) { write_name_and_tag(writer, name, tag); } - void write_nbt(BinaryWriter& writer, const std::optional& name, const ListTag& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const std::optional& name, const ListTag& tag) { write_name_and_tag(writer, name, tag); } - void write_nbt(BinaryWriter& writer, const std::optional& name, const CompoundTag& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const std::optional& name, const CompoundTag& tag) { write_name_and_tag(writer, name, tag); } - void write_nbt(BinaryWriter& writer, const std::optional& name, const IntArrayTag& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const std::optional& name, const IntArrayTag& tag) { write_name_and_tag(writer, name, tag); } - void write_nbt(BinaryWriter& writer, const std::optional& name, const LongArrayTag& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const std::optional& name, const LongArrayTag& tag) { write_name_and_tag(writer, name, tag); } - void write_nbt(BinaryWriter& writer, const std::string& name, const TagNode& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const std::string& name, const TagNode& tag) { write_name_and_tag(writer, name, tag); } - void write_nbt(BinaryWriter& writer, const NamedTag& tag) { + AMULET_NBT_DLLX void write_nbt(BinaryWriter& writer, const NamedTag& tag) { write_name_and_tag(writer, tag.name, tag.tag_node); } - std::string write_nbt(const std::optional& name, const AmuletNBT::ByteTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const AmuletNBT::ByteTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return _write_nbt(name, tag, endianness, string_encode); }; - std::string write_nbt(const std::optional& name, const AmuletNBT::ShortTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const AmuletNBT::ShortTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return _write_nbt(name, tag, endianness, string_encode); }; - std::string write_nbt(const std::optional& name, const AmuletNBT::IntTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const AmuletNBT::IntTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return _write_nbt(name, tag, endianness, string_encode); }; - std::string write_nbt(const std::optional& name, const AmuletNBT::LongTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const AmuletNBT::LongTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return _write_nbt(name, tag, endianness, string_encode); }; - std::string write_nbt(const std::optional& name, const AmuletNBT::FloatTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const AmuletNBT::FloatTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return _write_nbt(name, tag, endianness, string_encode); }; - std::string write_nbt(const std::optional& name, const AmuletNBT::DoubleTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const AmuletNBT::DoubleTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return _write_nbt(name, tag, endianness, string_encode); }; - std::string write_nbt(const std::optional& name, const AmuletNBT::ByteArrayTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const AmuletNBT::ByteArrayTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return _write_nbt(name, tag, endianness, string_encode); }; - std::string write_nbt(const std::optional& name, const AmuletNBT::StringTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const AmuletNBT::StringTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return _write_nbt(name, tag, endianness, string_encode); }; - std::string write_nbt(const std::optional& name, const AmuletNBT::ListTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const AmuletNBT::ListTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return _write_nbt(name, tag, endianness, string_encode); }; - std::string write_nbt(const std::optional& name, const AmuletNBT::CompoundTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const AmuletNBT::CompoundTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return _write_nbt(name, tag, endianness, string_encode); }; - std::string write_nbt(const std::optional& name, const AmuletNBT::IntArrayTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const AmuletNBT::IntArrayTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return _write_nbt(name, tag, endianness, string_encode); }; - std::string write_nbt(const std::optional& name, const AmuletNBT::LongArrayTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const AmuletNBT::LongArrayTag& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return _write_nbt(name, tag, endianness, string_encode); }; - std::string write_nbt(const std::string& name, const AmuletNBT::TagNode& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const std::string& name, const AmuletNBT::TagNode& tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return _write_nbt(name, tag, endianness, string_encode); }; - std::string write_nbt(const AmuletNBT::NamedTag& named_tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ + AMULET_NBT_DLLX std::string write_nbt(const AmuletNBT::NamedTag& named_tag, std::endian endianness, AmuletNBT::StringEncode string_encode){ return write_nbt(named_tag.name, named_tag.tag_node, endianness, string_encode); } } diff --git a/src/amulet_nbt/cpp/nbt_encoding/string/read_string.cpp b/src/amulet_nbt/cpp/nbt_encoding/string/read_string.cpp index 004c2e22..f3b27410 100644 --- a/src/amulet_nbt/cpp/nbt_encoding/string/read_string.cpp +++ b/src/amulet_nbt/cpp/nbt_encoding/string/read_string.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -429,13 +430,14 @@ AmuletNBT::TagNode _read_snbt(const AmuletNBT::CodePointVector& snbt, size_t& in } -AmuletNBT::TagNode AmuletNBT::read_snbt(const AmuletNBT::CodePointVector& snbt){ - size_t index = 0; - return _read_snbt(snbt, index); -} - +namespace AmuletNBT { + AMULET_NBT_DLLX AmuletNBT::TagNode read_snbt(const AmuletNBT::CodePointVector& snbt){ + size_t index = 0; + return _read_snbt(snbt, index); + } -AmuletNBT::TagNode AmuletNBT::read_snbt(std::string_view snbt){ - AmuletNBT::CodePointVector code_points = AmuletNBT::read_utf8_escape(snbt); - return AmuletNBT::read_snbt(code_points); + AMULET_NBT_DLLX AmuletNBT::TagNode read_snbt(std::string_view snbt){ + AmuletNBT::CodePointVector code_points = AmuletNBT::read_utf8_escape(snbt); + return read_snbt(code_points); + } } diff --git a/src/amulet_nbt/cpp/nbt_encoding/string/write_string.cpp b/src/amulet_nbt/cpp/nbt_encoding/string/write_string.cpp index cc758399..64c2b30e 100644 --- a/src/amulet_nbt/cpp/nbt_encoding/string/write_string.cpp +++ b/src/amulet_nbt/cpp/nbt_encoding/string/write_string.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -327,155 +328,155 @@ namespace AmuletNBT { } - std::string write_snbt(const TagNode& tag){ + AMULET_NBT_DLLX std::string write_snbt(const TagNode& tag){ std::string snbt; write_snbt(snbt, tag); return snbt; } - std::string write_snbt(const ByteTag& tag){ + AMULET_NBT_DLLX std::string write_snbt(const ByteTag& tag){ std::string snbt; write_snbt(snbt, tag); return snbt; } - std::string write_snbt(const ShortTag& tag){ + AMULET_NBT_DLLX std::string write_snbt(const ShortTag& tag){ std::string snbt; write_snbt(snbt, tag); return snbt; } - std::string write_snbt(const IntTag& tag){ + AMULET_NBT_DLLX std::string write_snbt(const IntTag& tag){ std::string snbt; write_snbt(snbt, tag); return snbt; } - std::string write_snbt(const LongTag& tag){ + AMULET_NBT_DLLX std::string write_snbt(const LongTag& tag){ std::string snbt; write_snbt(snbt, tag); return snbt; } - std::string write_snbt(const FloatTag& tag){ + AMULET_NBT_DLLX std::string write_snbt(const FloatTag& tag){ std::string snbt; write_snbt(snbt, tag); return snbt; } - std::string write_snbt(const DoubleTag& tag){ + AMULET_NBT_DLLX std::string write_snbt(const DoubleTag& tag){ std::string snbt; write_snbt(snbt, tag); return snbt; } - std::string write_snbt(const ByteArrayTag& tag){ + AMULET_NBT_DLLX std::string write_snbt(const ByteArrayTag& tag){ std::string snbt; write_snbt(snbt, tag); return snbt; } - std::string write_snbt(const StringTag& tag){ + AMULET_NBT_DLLX std::string write_snbt(const StringTag& tag){ std::string snbt; write_snbt(snbt, tag); return snbt; } - std::string write_snbt(const ListTag& tag){ + AMULET_NBT_DLLX std::string write_snbt(const ListTag& tag){ std::string snbt; write_snbt(snbt, tag); return snbt; } - std::string write_snbt(const CompoundTag& tag){ + AMULET_NBT_DLLX std::string write_snbt(const CompoundTag& tag){ std::string snbt; write_snbt(snbt, tag); return snbt; } - std::string write_snbt(const IntArrayTag& tag){ + AMULET_NBT_DLLX std::string write_snbt(const IntArrayTag& tag){ std::string snbt; write_snbt(snbt, tag); return snbt; } - std::string write_snbt(const LongArrayTag& tag){ + AMULET_NBT_DLLX std::string write_snbt(const LongArrayTag& tag){ std::string snbt; write_snbt(snbt, tag); return snbt; } - void write_formatted_snbt(std::string& snbt, const TagNode& tag, const std::string& indent){ + AMULET_NBT_DLLX void write_formatted_snbt(std::string& snbt, const TagNode& tag, const std::string& indent){ return write_formatted_snbt(snbt, tag, indent, 0); } - void write_formatted_snbt(std::string& snbt, const ByteTag& tag, const std::string& indent){ + AMULET_NBT_DLLX void write_formatted_snbt(std::string& snbt, const ByteTag& tag, const std::string& indent){ write_snbt(snbt, tag); } - void write_formatted_snbt(std::string& snbt, const ShortTag& tag, const std::string& indent){ + AMULET_NBT_DLLX void write_formatted_snbt(std::string& snbt, const ShortTag& tag, const std::string& indent){ write_snbt(snbt, tag); } - void write_formatted_snbt(std::string& snbt, const IntTag& tag, const std::string& indent){ + AMULET_NBT_DLLX void write_formatted_snbt(std::string& snbt, const IntTag& tag, const std::string& indent){ write_snbt(snbt, tag); } - void write_formatted_snbt(std::string& snbt, const LongTag& tag, const std::string& indent){ + AMULET_NBT_DLLX void write_formatted_snbt(std::string& snbt, const LongTag& tag, const std::string& indent){ write_snbt(snbt, tag); } - void write_formatted_snbt(std::string& snbt, const FloatTag& tag, const std::string& indent){ + AMULET_NBT_DLLX void write_formatted_snbt(std::string& snbt, const FloatTag& tag, const std::string& indent){ write_snbt(snbt, tag); } - void write_formatted_snbt(std::string& snbt, const DoubleTag& tag, const std::string& indent){ + AMULET_NBT_DLLX void write_formatted_snbt(std::string& snbt, const DoubleTag& tag, const std::string& indent){ write_snbt(snbt, tag); } - void write_formatted_snbt(std::string& snbt, const ByteArrayTag& tag, const std::string& indent){ + AMULET_NBT_DLLX void write_formatted_snbt(std::string& snbt, const ByteArrayTag& tag, const std::string& indent){ write_snbt(snbt, tag); } - void write_formatted_snbt(std::string& snbt, const StringTag& tag, const std::string& indent){ + AMULET_NBT_DLLX void write_formatted_snbt(std::string& snbt, const StringTag& tag, const std::string& indent){ write_snbt(snbt, tag); } - void write_formatted_snbt(std::string& snbt, const ListTag& tag, const std::string& indent){ + AMULET_NBT_DLLX void write_formatted_snbt(std::string& snbt, const ListTag& tag, const std::string& indent){ return write_formatted_snbt(snbt, tag, indent, 0); } - void write_formatted_snbt(std::string& snbt, const CompoundTag& tag, const std::string& indent){ + AMULET_NBT_DLLX void write_formatted_snbt(std::string& snbt, const CompoundTag& tag, const std::string& indent){ return write_formatted_snbt(snbt, tag, indent, 0); } - void write_formatted_snbt(std::string& snbt, const IntArrayTag& tag, const std::string& indent){ + AMULET_NBT_DLLX void write_formatted_snbt(std::string& snbt, const IntArrayTag& tag, const std::string& indent){ write_snbt(snbt, tag); } - void write_formatted_snbt(std::string& snbt, const LongArrayTag& tag, const std::string& indent){ + AMULET_NBT_DLLX void write_formatted_snbt(std::string& snbt, const LongArrayTag& tag, const std::string& indent){ write_snbt(snbt, tag); } - std::string write_formatted_snbt(const TagNode& tag, const std::string& indent){ + AMULET_NBT_DLLX std::string write_formatted_snbt(const TagNode& tag, const std::string& indent){ std::string snbt; write_formatted_snbt(snbt, tag, indent); return snbt; } - std::string write_formatted_snbt(const ByteTag& tag, const std::string& indent){ + AMULET_NBT_DLLX std::string write_formatted_snbt(const ByteTag& tag, const std::string& indent){ return write_snbt(tag); } - std::string write_formatted_snbt(const ShortTag& tag, const std::string& indent){ + AMULET_NBT_DLLX std::string write_formatted_snbt(const ShortTag& tag, const std::string& indent){ return write_snbt(tag); } - std::string write_formatted_snbt(const IntTag& tag, const std::string& indent){ + AMULET_NBT_DLLX std::string write_formatted_snbt(const IntTag& tag, const std::string& indent){ return write_snbt(tag); } - std::string write_formatted_snbt(const LongTag& tag, const std::string& indent){ + AMULET_NBT_DLLX std::string write_formatted_snbt(const LongTag& tag, const std::string& indent){ return write_snbt(tag); } - std::string write_formatted_snbt(const FloatTag& tag, const std::string& indent){ + AMULET_NBT_DLLX std::string write_formatted_snbt(const FloatTag& tag, const std::string& indent){ return write_snbt(tag); } - std::string write_formatted_snbt(const DoubleTag& tag, const std::string& indent){ + AMULET_NBT_DLLX std::string write_formatted_snbt(const DoubleTag& tag, const std::string& indent){ return write_snbt(tag); } - std::string write_formatted_snbt(const ByteArrayTag& tag, const std::string& indent){ + AMULET_NBT_DLLX std::string write_formatted_snbt(const ByteArrayTag& tag, const std::string& indent){ return write_snbt(tag); } - std::string write_formatted_snbt(const StringTag& tag, const std::string& indent){ + AMULET_NBT_DLLX std::string write_formatted_snbt(const StringTag& tag, const std::string& indent){ return write_snbt(tag); } - std::string write_formatted_snbt(const ListTag& tag, const std::string& indent){ + AMULET_NBT_DLLX std::string write_formatted_snbt(const ListTag& tag, const std::string& indent){ std::string snbt; write_formatted_snbt(snbt, tag, indent); return snbt; } - std::string write_formatted_snbt(const CompoundTag& tag, const std::string& indent){ + AMULET_NBT_DLLX std::string write_formatted_snbt(const CompoundTag& tag, const std::string& indent){ std::string snbt; write_formatted_snbt(snbt, tag, indent); return snbt; } - std::string write_formatted_snbt(const IntArrayTag& tag, const std::string& indent){ + AMULET_NBT_DLLX std::string write_formatted_snbt(const IntArrayTag& tag, const std::string& indent){ return write_snbt(tag); } - std::string write_formatted_snbt(const LongArrayTag& tag, const std::string& indent){ + AMULET_NBT_DLLX std::string write_formatted_snbt(const LongArrayTag& tag, const std::string& indent){ return write_snbt(tag); } } diff --git a/src/amulet_nbt/cpp/string_encoding/mutf8.cpp b/src/amulet_nbt/cpp/string_encoding/mutf8.cpp index eb7e5f5f..c33cac62 100644 --- a/src/amulet_nbt/cpp/string_encoding/mutf8.cpp +++ b/src/amulet_nbt/cpp/string_encoding/mutf8.cpp @@ -6,11 +6,13 @@ #include #include #include + +#include #include namespace AmuletNBT { - CodePointVector read_mutf8(std::string_view src) { + AMULET_NBT_DLLX CodePointVector read_mutf8(std::string_view src) { CodePointVector dst; for (size_t index = 0; index < src.size(); index++) { @@ -100,7 +102,7 @@ namespace AmuletNBT { } - void write_mutf8(std::string& dst, const CodePointVector& src) { + AMULET_NBT_DLLX void write_mutf8(std::string& dst, const CodePointVector& src) { for (size_t index = 0; index < src.size(); index++) { const size_t& c = src[index]; if (c == 0) { @@ -136,7 +138,7 @@ namespace AmuletNBT { } } - std::string write_mutf8(const CodePointVector& src) { + AMULET_NBT_DLLX std::string write_mutf8(const CodePointVector& src) { std::string dst; write_mutf8(dst, src); return dst; @@ -144,7 +146,7 @@ namespace AmuletNBT { // Decode a modified utf-8 byte sequence to a regular utf-8 byte sequence - std::string mutf8_to_utf8(std::string_view src) { + AMULET_NBT_DLLX std::string mutf8_to_utf8(std::string_view src) { std::string dst; write_utf8(dst, read_mutf8(src)); return dst; @@ -152,7 +154,7 @@ namespace AmuletNBT { // Encode a regular utf-8 byte sequence to a modified utf-8 byte sequence - std::string utf8_to_mutf8(std::string_view src) { + AMULET_NBT_DLLX std::string utf8_to_mutf8(std::string_view src) { std::string dst; write_mutf8(dst, read_utf8(src)); return dst; diff --git a/src/amulet_nbt/cpp/string_encoding/utf8.cpp b/src/amulet_nbt/cpp/string_encoding/utf8.cpp index 7601a308..a46e6c8e 100644 --- a/src/amulet_nbt/cpp/string_encoding/utf8.cpp +++ b/src/amulet_nbt/cpp/string_encoding/utf8.cpp @@ -6,6 +6,8 @@ #include #include #include + +#include #include const size_t HexChars[16] = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102}; @@ -222,50 +224,50 @@ constexpr void _write_utf8(std::string &dst, const AmuletNBT::CodePointVector& s namespace AmuletNBT{ - CodePointVector read_utf8(std::string_view src) { + AMULET_NBT_DLLX CodePointVector read_utf8(std::string_view src) { return _read_utf8(src); } - void write_utf8(std::string &dst, const CodePointVector& src) { + AMULET_NBT_DLLX void write_utf8(std::string &dst, const CodePointVector& src) { _write_utf8(dst, src); } - std::string write_utf8(const CodePointVector& src) { + AMULET_NBT_DLLX std::string write_utf8(const CodePointVector& src) { std::string dst; _write_utf8(dst, src); return dst; } - CodePointVector read_utf8_escape(std::string_view src) { + AMULET_NBT_DLLX CodePointVector read_utf8_escape(std::string_view src) { return _read_utf8(src); } - void write_utf8_escape(std::string &dst, const CodePointVector& src) { + AMULET_NBT_DLLX void write_utf8_escape(std::string &dst, const CodePointVector& src) { _write_utf8(dst, src); } - std::string write_utf8_escape(const CodePointVector& src) { + AMULET_NBT_DLLX std::string write_utf8_escape(const CodePointVector& src) { std::string dst; _write_utf8(dst, src); return dst; } // Validate a utf-8 byte sequence and convert to itself. - std::string utf8_to_utf8(std::string_view src) { + AMULET_NBT_DLLX std::string utf8_to_utf8(std::string_view src) { std::string dst; write_utf8(dst, read_utf8(src)); return dst; } // Decode a utf-8 escape byte sequence to a regular utf-8 byte sequence - std::string utf8_escape_to_utf8(std::string_view src) { + AMULET_NBT_DLLX std::string utf8_escape_to_utf8(std::string_view src) { std::string dst; write_utf8(dst, read_utf8_escape(src)); return dst; } // Encode a regular utf-8 byte sequence to a utf-8 escape byte sequence - std::string utf8_to_utf8_escape(std::string_view src) { + AMULET_NBT_DLLX std::string utf8_to_utf8_escape(std::string_view src) { std::string dst; write_utf8_escape(dst, read_utf8(src)); return dst; diff --git a/src/amulet_nbt/cpp/tag/copy.cpp b/src/amulet_nbt/cpp/tag/copy.cpp index 793d9a76..a33f87bc 100644 --- a/src/amulet_nbt/cpp/tag/copy.cpp +++ b/src/amulet_nbt/cpp/tag/copy.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -45,7 +46,7 @@ namespace AmuletNBT { return new_tag; } - AmuletNBT::ListTagPtr NBTTag_deep_copy_list(const AmuletNBT::ListTag& tag) { + AMULET_NBT_DLLX AmuletNBT::ListTagPtr NBTTag_deep_copy_list(const AmuletNBT::ListTag& tag) { return std::visit([](auto&& list) { using T = std::decay_t; if constexpr (std::is_same_v) { @@ -60,7 +61,7 @@ namespace AmuletNBT { }, tag); } - AmuletNBT::TagNode NBTTag_deep_copy_node(const AmuletNBT::TagNode& node) { + AMULET_NBT_DLLX AmuletNBT::TagNode NBTTag_deep_copy_node(const AmuletNBT::TagNode& node) { return std::visit([](auto&& tag) -> AmuletNBT::TagNode { using T = std::decay_t; if constexpr (std::is_same_v) { @@ -82,7 +83,7 @@ namespace AmuletNBT { }, node); } - AmuletNBT::CompoundTagPtr NBTTag_deep_copy_compound(const AmuletNBT::CompoundTag& tag) { + AMULET_NBT_DLLX AmuletNBT::CompoundTagPtr NBTTag_deep_copy_compound(const AmuletNBT::CompoundTag& tag) { auto new_tag = std::make_shared(); for (auto& [key, value] : tag) { (*new_tag)[key] = NBTTag_deep_copy_node(value); diff --git a/src/amulet_nbt/cpp/tag/eq.cpp b/src/amulet_nbt/cpp/tag/eq.cpp index b6dcb584..225ad645 100644 --- a/src/amulet_nbt/cpp/tag/eq.cpp +++ b/src/amulet_nbt/cpp/tag/eq.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -16,16 +17,16 @@ namespace AmuletNBT{ - bool NBTTag_eq(const AmuletNBT::ByteTag& a, const AmuletNBT::ByteTag& b){return a == b;}; - bool NBTTag_eq(const AmuletNBT::ShortTag& a, const AmuletNBT::ShortTag& b){return a == b;}; - bool NBTTag_eq(const AmuletNBT::IntTag& a, const AmuletNBT::IntTag& b){return a == b;}; - bool NBTTag_eq(const AmuletNBT::LongTag& a, const AmuletNBT::LongTag& b){return a == b;}; - bool NBTTag_eq(const AmuletNBT::FloatTag& a, const AmuletNBT::FloatTag& b){return a == b;}; - bool NBTTag_eq(const AmuletNBT::DoubleTag& a, const AmuletNBT::DoubleTag& b){return a == b;}; - bool NBTTag_eq(const AmuletNBT::StringTag& a, const AmuletNBT::StringTag& b){return a == b;}; - bool NBTTag_eq(const AmuletNBT::ByteArrayTag& a, const AmuletNBT::ByteArrayTag& b){return a == b;}; - bool NBTTag_eq(const AmuletNBT::IntArrayTag& a, const AmuletNBT::IntArrayTag& b){return a == b;}; - bool NBTTag_eq(const AmuletNBT::LongArrayTag& a, const AmuletNBT::LongArrayTag& b){return a == b;}; + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::ByteTag& a, const AmuletNBT::ByteTag& b){return a == b;}; + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::ShortTag& a, const AmuletNBT::ShortTag& b){return a == b;}; + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::IntTag& a, const AmuletNBT::IntTag& b){return a == b;}; + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::LongTag& a, const AmuletNBT::LongTag& b){return a == b;}; + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::FloatTag& a, const AmuletNBT::FloatTag& b){return a == b;}; + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::DoubleTag& a, const AmuletNBT::DoubleTag& b){return a == b;}; + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::StringTag& a, const AmuletNBT::StringTag& b){return a == b;}; + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::ByteArrayTag& a, const AmuletNBT::ByteArrayTag& b){return a == b;}; + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::IntArrayTag& a, const AmuletNBT::IntArrayTag& b){return a == b;}; + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::LongArrayTag& a, const AmuletNBT::LongArrayTag& b){return a == b;}; template inline bool ListTag_eq(const std::vector& a_vec, const AmuletNBT::ListTag& b){ @@ -50,7 +51,7 @@ namespace AmuletNBT{ return a_vec == b_vec; } } - bool NBTTag_eq(const AmuletNBT::ListTag& a, const AmuletNBT::ListTag& b){ + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::ListTag& a, const AmuletNBT::ListTag& b){ return std::visit([&b](auto&& list) -> bool { using T = std::decay_t; if constexpr (std::is_same_v) { @@ -61,7 +62,7 @@ namespace AmuletNBT{ } }, a); }; - bool NBTTag_eq(const AmuletNBT::CompoundTag& a, const AmuletNBT::CompoundTag& b){ + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::CompoundTag& a, const AmuletNBT::CompoundTag& b){ if (a.size() != b.size()){ // Size does not match return false; @@ -79,7 +80,7 @@ namespace AmuletNBT{ } return true; }; - bool NBTTag_eq(const AmuletNBT::TagNode& a, const AmuletNBT::TagNode& b){ + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::TagNode& a, const AmuletNBT::TagNode& b){ return std::visit([&b](auto&& tag) -> bool { using T = std::decay_t; if (!std::holds_alternative(b)) { @@ -93,7 +94,7 @@ namespace AmuletNBT{ } }, a); }; - bool NBTTag_eq(const AmuletNBT::NamedTag& a, const AmuletNBT::NamedTag& b) { + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::NamedTag& a, const AmuletNBT::NamedTag& b) { return a.name == b.name && NBTTag_eq(a.tag_node, b.tag_node); }; } diff --git a/src/amulet_nbt/include/amulet_nbt/dll.hpp b/src/amulet_nbt/include/amulet_nbt/dll.hpp new file mode 100644 index 00000000..7db46d9c --- /dev/null +++ b/src/amulet_nbt/include/amulet_nbt/dll.hpp @@ -0,0 +1,11 @@ +#ifndef AMULET_NBT_DLLX + #ifdef _WIN32 + #ifdef ExportAmuletNBT + #define AMULET_NBT_DLLX __declspec(dllexport) + #else + #define AMULET_NBT_DLLX __declspec(dllimport) + #endif + #else + #define AMULET_NBT_DLLX + #endif +#endif diff --git a/src/amulet_nbt/include/amulet_nbt/nbt_encoding/binary.hpp b/src/amulet_nbt/include/amulet_nbt/nbt_encoding/binary.hpp index b0f120f2..30ab5761 100644 --- a/src/amulet_nbt/include/amulet_nbt/nbt_encoding/binary.hpp +++ b/src/amulet_nbt/include/amulet_nbt/nbt_encoding/binary.hpp @@ -6,6 +6,8 @@ #include #include #include + +#include #include #include #include @@ -18,39 +20,39 @@ #include namespace AmuletNBT { - NamedTag read_nbt(BinaryReader& reader, bool named = true); - NamedTag read_nbt(std::string_view, std::endian, StringDecode, size_t& offset, bool named = true); - NamedTag read_nbt(std::string_view, std::endian, StringDecode, bool named = true); - std::vector read_nbt_array(std::string_view, std::endian, StringDecode, size_t& offset, bool named = true); - std::vector read_nbt_array(std::string_view, std::endian, StringDecode, size_t& offset, size_t count, bool named); + AMULET_NBT_DLLX NamedTag read_nbt(BinaryReader& reader, bool named = true); + AMULET_NBT_DLLX NamedTag read_nbt(std::string_view, std::endian, StringDecode, size_t& offset, bool named = true); + AMULET_NBT_DLLX NamedTag read_nbt(std::string_view, std::endian, StringDecode, bool named = true); + AMULET_NBT_DLLX std::vector read_nbt_array(std::string_view, std::endian, StringDecode, size_t& offset, bool named = true); + AMULET_NBT_DLLX std::vector read_nbt_array(std::string_view, std::endian, StringDecode, size_t& offset, size_t count, bool named); - void write_nbt(BinaryWriter&, const std::optional& name, const ByteTag&); - void write_nbt(BinaryWriter&, const std::optional& name, const ShortTag&); - void write_nbt(BinaryWriter&, const std::optional& name, const IntTag&); - void write_nbt(BinaryWriter&, const std::optional& name, const LongTag&); - void write_nbt(BinaryWriter&, const std::optional& name, const FloatTag&); - void write_nbt(BinaryWriter&, const std::optional& name, const DoubleTag&); - void write_nbt(BinaryWriter&, const std::optional& name, const ByteArrayTag&); - void write_nbt(BinaryWriter&, const std::optional& name, const StringTag&); - void write_nbt(BinaryWriter&, const std::optional& name, const ListTag&); - void write_nbt(BinaryWriter&, const std::optional& name, const CompoundTag&); - void write_nbt(BinaryWriter&, const std::optional& name, const IntArrayTag&); - void write_nbt(BinaryWriter&, const std::optional& name, const LongArrayTag&); - void write_nbt(BinaryWriter&, const std::string& name, const TagNode&); - void write_nbt(BinaryWriter&, const NamedTag& tag); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const std::optional& name, const ByteTag&); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const std::optional& name, const ShortTag&); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const std::optional& name, const IntTag&); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const std::optional& name, const LongTag&); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const std::optional& name, const FloatTag&); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const std::optional& name, const DoubleTag&); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const std::optional& name, const ByteArrayTag&); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const std::optional& name, const StringTag&); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const std::optional& name, const ListTag&); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const std::optional& name, const CompoundTag&); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const std::optional& name, const IntArrayTag&); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const std::optional& name, const LongArrayTag&); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const std::string& name, const TagNode&); + AMULET_NBT_DLLX void write_nbt(BinaryWriter&, const NamedTag& tag); - std::string write_nbt(const std::optional& name, const ByteTag&, std::endian, StringEncode); - std::string write_nbt(const std::optional& name, const ShortTag&, std::endian, StringEncode); - std::string write_nbt(const std::optional& name, const IntTag&, std::endian, StringEncode); - std::string write_nbt(const std::optional& name, const LongTag&, std::endian, StringEncode); - std::string write_nbt(const std::optional& name, const FloatTag&, std::endian, StringEncode); - std::string write_nbt(const std::optional& name, const DoubleTag&, std::endian, StringEncode); - std::string write_nbt(const std::optional& name, const ByteArrayTag&, std::endian, StringEncode); - std::string write_nbt(const std::optional& name, const StringTag&, std::endian, StringEncode); - std::string write_nbt(const std::optional& name, const ListTag&, std::endian, StringEncode); - std::string write_nbt(const std::optional& name, const CompoundTag&, std::endian, StringEncode); - std::string write_nbt(const std::optional& name, const IntArrayTag&, std::endian, StringEncode); - std::string write_nbt(const std::optional& name, const LongArrayTag&, std::endian, StringEncode); - std::string write_nbt(const std::string& name, const TagNode&, std::endian, StringEncode); - std::string write_nbt(const NamedTag& tag, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const ByteTag&, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const ShortTag&, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const IntTag&, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const LongTag&, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const FloatTag&, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const DoubleTag&, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const ByteArrayTag&, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const StringTag&, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const ListTag&, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const CompoundTag&, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const IntArrayTag&, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const std::optional& name, const LongArrayTag&, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const std::string& name, const TagNode&, std::endian, StringEncode); + AMULET_NBT_DLLX std::string write_nbt(const NamedTag& tag, std::endian, StringEncode); } diff --git a/src/amulet_nbt/include/amulet_nbt/nbt_encoding/string.hpp b/src/amulet_nbt/include/amulet_nbt/nbt_encoding/string.hpp index ed71640a..6d57c974 100644 --- a/src/amulet_nbt/include/amulet_nbt/nbt_encoding/string.hpp +++ b/src/amulet_nbt/include/amulet_nbt/nbt_encoding/string.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -12,63 +13,63 @@ #include namespace AmuletNBT { - void write_snbt(std::string&, const TagNode&); - void write_snbt(std::string&, const ByteTag&); - void write_snbt(std::string&, const ShortTag&); - void write_snbt(std::string&, const IntTag&); - void write_snbt(std::string&, const LongTag&); - void write_snbt(std::string&, const FloatTag&); - void write_snbt(std::string&, const DoubleTag&); - void write_snbt(std::string&, const ByteArrayTag&); - void write_snbt(std::string&, const StringTag&); - void write_snbt(std::string&, const ListTag&); - void write_snbt(std::string&, const CompoundTag&); - void write_snbt(std::string&, const IntArrayTag&); - void write_snbt(std::string&, const LongArrayTag&); + AMULET_NBT_DLLX void write_snbt(std::string&, const TagNode&); + AMULET_NBT_DLLX void write_snbt(std::string&, const ByteTag&); + AMULET_NBT_DLLX void write_snbt(std::string&, const ShortTag&); + AMULET_NBT_DLLX void write_snbt(std::string&, const IntTag&); + AMULET_NBT_DLLX void write_snbt(std::string&, const LongTag&); + AMULET_NBT_DLLX void write_snbt(std::string&, const FloatTag&); + AMULET_NBT_DLLX void write_snbt(std::string&, const DoubleTag&); + AMULET_NBT_DLLX void write_snbt(std::string&, const ByteArrayTag&); + AMULET_NBT_DLLX void write_snbt(std::string&, const StringTag&); + AMULET_NBT_DLLX void write_snbt(std::string&, const ListTag&); + AMULET_NBT_DLLX void write_snbt(std::string&, const CompoundTag&); + AMULET_NBT_DLLX void write_snbt(std::string&, const IntArrayTag&); + AMULET_NBT_DLLX void write_snbt(std::string&, const LongArrayTag&); - std::string write_snbt(const TagNode&); - std::string write_snbt(const ByteTag&); - std::string write_snbt(const ShortTag&); - std::string write_snbt(const IntTag&); - std::string write_snbt(const LongTag&); - std::string write_snbt(const FloatTag&); - std::string write_snbt(const DoubleTag&); - std::string write_snbt(const ByteArrayTag&); - std::string write_snbt(const StringTag&); - std::string write_snbt(const ListTag&); - std::string write_snbt(const CompoundTag&); - std::string write_snbt(const IntArrayTag&); - std::string write_snbt(const LongArrayTag&); + AMULET_NBT_DLLX std::string write_snbt(const TagNode&); + AMULET_NBT_DLLX std::string write_snbt(const ByteTag&); + AMULET_NBT_DLLX std::string write_snbt(const ShortTag&); + AMULET_NBT_DLLX std::string write_snbt(const IntTag&); + AMULET_NBT_DLLX std::string write_snbt(const LongTag&); + AMULET_NBT_DLLX std::string write_snbt(const FloatTag&); + AMULET_NBT_DLLX std::string write_snbt(const DoubleTag&); + AMULET_NBT_DLLX std::string write_snbt(const ByteArrayTag&); + AMULET_NBT_DLLX std::string write_snbt(const StringTag&); + AMULET_NBT_DLLX std::string write_snbt(const ListTag&); + AMULET_NBT_DLLX std::string write_snbt(const CompoundTag&); + AMULET_NBT_DLLX std::string write_snbt(const IntArrayTag&); + AMULET_NBT_DLLX std::string write_snbt(const LongArrayTag&); // Multi-line variants - void write_formatted_snbt(std::string&, const TagNode&, const std::string& indent); - void write_formatted_snbt(std::string&, const ByteTag&, const std::string& indent); - void write_formatted_snbt(std::string&, const ShortTag&, const std::string& indent); - void write_formatted_snbt(std::string&, const IntTag&, const std::string& indent); - void write_formatted_snbt(std::string&, const LongTag&, const std::string& indent); - void write_formatted_snbt(std::string&, const FloatTag&, const std::string& indent); - void write_formatted_snbt(std::string&, const DoubleTag&, const std::string& indent); - void write_formatted_snbt(std::string&, const ByteArrayTag&, const std::string& indent); - void write_formatted_snbt(std::string&, const StringTag&, const std::string& indent); - void write_formatted_snbt(std::string&, const ListTag&, const std::string& indent); - void write_formatted_snbt(std::string&, const CompoundTag&, const std::string& indent); - void write_formatted_snbt(std::string&, const IntArrayTag&, const std::string& indent); - void write_formatted_snbt(std::string&, const LongArrayTag&, const std::string& indent); + AMULET_NBT_DLLX void write_formatted_snbt(std::string&, const TagNode&, const std::string& indent); + AMULET_NBT_DLLX void write_formatted_snbt(std::string&, const ByteTag&, const std::string& indent); + AMULET_NBT_DLLX void write_formatted_snbt(std::string&, const ShortTag&, const std::string& indent); + AMULET_NBT_DLLX void write_formatted_snbt(std::string&, const IntTag&, const std::string& indent); + AMULET_NBT_DLLX void write_formatted_snbt(std::string&, const LongTag&, const std::string& indent); + AMULET_NBT_DLLX void write_formatted_snbt(std::string&, const FloatTag&, const std::string& indent); + AMULET_NBT_DLLX void write_formatted_snbt(std::string&, const DoubleTag&, const std::string& indent); + AMULET_NBT_DLLX void write_formatted_snbt(std::string&, const ByteArrayTag&, const std::string& indent); + AMULET_NBT_DLLX void write_formatted_snbt(std::string&, const StringTag&, const std::string& indent); + AMULET_NBT_DLLX void write_formatted_snbt(std::string&, const ListTag&, const std::string& indent); + AMULET_NBT_DLLX void write_formatted_snbt(std::string&, const CompoundTag&, const std::string& indent); + AMULET_NBT_DLLX void write_formatted_snbt(std::string&, const IntArrayTag&, const std::string& indent); + AMULET_NBT_DLLX void write_formatted_snbt(std::string&, const LongArrayTag&, const std::string& indent); - std::string write_formatted_snbt(const TagNode&, const std::string& indent); - std::string write_formatted_snbt(const ByteTag&, const std::string& indent); - std::string write_formatted_snbt(const ShortTag&, const std::string& indent); - std::string write_formatted_snbt(const IntTag&, const std::string& indent); - std::string write_formatted_snbt(const LongTag&, const std::string& indent); - std::string write_formatted_snbt(const FloatTag&, const std::string& indent); - std::string write_formatted_snbt(const DoubleTag&, const std::string& indent); - std::string write_formatted_snbt(const ByteArrayTag&, const std::string& indent); - std::string write_formatted_snbt(const StringTag&, const std::string& indent); - std::string write_formatted_snbt(const ListTag&, const std::string& indent); - std::string write_formatted_snbt(const CompoundTag&, const std::string& indent); - std::string write_formatted_snbt(const IntArrayTag&, const std::string& indent); - std::string write_formatted_snbt(const LongArrayTag&, const std::string& indent); + AMULET_NBT_DLLX std::string write_formatted_snbt(const TagNode&, const std::string& indent); + AMULET_NBT_DLLX std::string write_formatted_snbt(const ByteTag&, const std::string& indent); + AMULET_NBT_DLLX std::string write_formatted_snbt(const ShortTag&, const std::string& indent); + AMULET_NBT_DLLX std::string write_formatted_snbt(const IntTag&, const std::string& indent); + AMULET_NBT_DLLX std::string write_formatted_snbt(const LongTag&, const std::string& indent); + AMULET_NBT_DLLX std::string write_formatted_snbt(const FloatTag&, const std::string& indent); + AMULET_NBT_DLLX std::string write_formatted_snbt(const DoubleTag&, const std::string& indent); + AMULET_NBT_DLLX std::string write_formatted_snbt(const ByteArrayTag&, const std::string& indent); + AMULET_NBT_DLLX std::string write_formatted_snbt(const StringTag&, const std::string& indent); + AMULET_NBT_DLLX std::string write_formatted_snbt(const ListTag&, const std::string& indent); + AMULET_NBT_DLLX std::string write_formatted_snbt(const CompoundTag&, const std::string& indent); + AMULET_NBT_DLLX std::string write_formatted_snbt(const IntArrayTag&, const std::string& indent); + AMULET_NBT_DLLX std::string write_formatted_snbt(const LongArrayTag&, const std::string& indent); - TagNode read_snbt(const CodePointVector& snbt); - TagNode read_snbt(std::string_view snbt); + AMULET_NBT_DLLX TagNode read_snbt(const CodePointVector& snbt); + AMULET_NBT_DLLX TagNode read_snbt(std::string_view snbt); } diff --git a/src/amulet_nbt/include/amulet_nbt/pybind/encoding.hpp b/src/amulet_nbt/include/amulet_nbt/pybind/encoding.hpp index c2bce61a..71d32f0e 100644 --- a/src/amulet_nbt/include/amulet_nbt/pybind/encoding.hpp +++ b/src/amulet_nbt/include/amulet_nbt/pybind/encoding.hpp @@ -1,6 +1,7 @@ #pragma once #include + #include #include diff --git a/src/amulet_nbt/include/amulet_nbt/string_encoding.hpp b/src/amulet_nbt/include/amulet_nbt/string_encoding.hpp index 6e66d545..acd4ec9b 100644 --- a/src/amulet_nbt/include/amulet_nbt/string_encoding.hpp +++ b/src/amulet_nbt/include/amulet_nbt/string_encoding.hpp @@ -4,26 +4,28 @@ #include #include +#include + namespace AmuletNBT { typedef std::vector CodePointVector; // Functions to convert between code point vector and encoded formats - CodePointVector read_utf8(std::string_view src); - CodePointVector read_utf8_escape(std::string_view src); - CodePointVector read_mutf8(std::string_view src); + AMULET_NBT_DLLX CodePointVector read_utf8(std::string_view src); + AMULET_NBT_DLLX CodePointVector read_utf8_escape(std::string_view src); + AMULET_NBT_DLLX CodePointVector read_mutf8(std::string_view src); - void write_utf8(std::string &dst, const CodePointVector& src); - void write_utf8_escape(std::string &dst, const CodePointVector& src); - void write_mutf8(std::string& dst, const CodePointVector& src); + AMULET_NBT_DLLX void write_utf8(std::string &dst, const CodePointVector& src); + AMULET_NBT_DLLX void write_utf8_escape(std::string &dst, const CodePointVector& src); + AMULET_NBT_DLLX void write_mutf8(std::string& dst, const CodePointVector& src); - std::string write_utf8(const CodePointVector& src); - std::string write_utf8_escape(const CodePointVector& src); - std::string write_mutf8(const CodePointVector& src); + AMULET_NBT_DLLX std::string write_utf8(const CodePointVector& src); + AMULET_NBT_DLLX std::string write_utf8_escape(const CodePointVector& src); + AMULET_NBT_DLLX std::string write_mutf8(const CodePointVector& src); // Functions to convert between the encoded formats. - std::string utf8_to_utf8(std::string_view src); - std::string utf8_escape_to_utf8(std::string_view src); - std::string utf8_to_utf8_escape(std::string_view src); - std::string mutf8_to_utf8(std::string_view src); - std::string utf8_to_mutf8(std::string_view src); + AMULET_NBT_DLLX std::string utf8_to_utf8(std::string_view src); + AMULET_NBT_DLLX std::string utf8_escape_to_utf8(std::string_view src); + AMULET_NBT_DLLX std::string utf8_to_utf8_escape(std::string_view src); + AMULET_NBT_DLLX std::string mutf8_to_utf8(std::string_view src); + AMULET_NBT_DLLX std::string utf8_to_mutf8(std::string_view src); } diff --git a/src/amulet_nbt/include/amulet_nbt/tag/copy.hpp b/src/amulet_nbt/include/amulet_nbt/tag/copy.hpp index 3e1390c9..0b39cb89 100644 --- a/src/amulet_nbt/include/amulet_nbt/tag/copy.hpp +++ b/src/amulet_nbt/include/amulet_nbt/tag/copy.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -45,7 +46,7 @@ namespace AmuletNBT { return std::make_shared(tag); } - AmuletNBT::ListTagPtr NBTTag_deep_copy_list(const AmuletNBT::ListTag& tag); - AmuletNBT::TagNode NBTTag_deep_copy_node(const AmuletNBT::TagNode& tag); - AmuletNBT::CompoundTagPtr NBTTag_deep_copy_compound(const AmuletNBT::CompoundTag& tag); + AMULET_NBT_DLLX AmuletNBT::ListTagPtr NBTTag_deep_copy_list(const AmuletNBT::ListTag& tag); + AMULET_NBT_DLLX AmuletNBT::TagNode NBTTag_deep_copy_node(const AmuletNBT::TagNode& tag); + AMULET_NBT_DLLX AmuletNBT::CompoundTagPtr NBTTag_deep_copy_compound(const AmuletNBT::CompoundTag& tag); } diff --git a/src/amulet_nbt/include/amulet_nbt/tag/eq.hpp b/src/amulet_nbt/include/amulet_nbt/tag/eq.hpp index d8d05bdd..d823024d 100644 --- a/src/amulet_nbt/include/amulet_nbt/tag/eq.hpp +++ b/src/amulet_nbt/include/amulet_nbt/tag/eq.hpp @@ -2,6 +2,7 @@ // All of the NBT equal functions +#include #include #include #include @@ -11,18 +12,18 @@ #include namespace AmuletNBT { - bool NBTTag_eq(const AmuletNBT::ByteTag& a, const AmuletNBT::ByteTag& b); - bool NBTTag_eq(const AmuletNBT::ShortTag& a, const AmuletNBT::ShortTag& b); - bool NBTTag_eq(const AmuletNBT::IntTag& a, const AmuletNBT::IntTag& b); - bool NBTTag_eq(const AmuletNBT::LongTag& a, const AmuletNBT::LongTag& b); - bool NBTTag_eq(const AmuletNBT::FloatTag& a, const AmuletNBT::FloatTag& b); - bool NBTTag_eq(const AmuletNBT::DoubleTag& a, const AmuletNBT::DoubleTag& b); - bool NBTTag_eq(const AmuletNBT::ByteArrayTag& a, const AmuletNBT::ByteArrayTag& b); - bool NBTTag_eq(const AmuletNBT::StringTag& a, const AmuletNBT::StringTag& b); - bool NBTTag_eq(const AmuletNBT::ListTag& a, const AmuletNBT::ListTag& b); - bool NBTTag_eq(const AmuletNBT::CompoundTag& a, const AmuletNBT::CompoundTag& b); - bool NBTTag_eq(const AmuletNBT::IntArrayTag& a, const AmuletNBT::IntArrayTag& b); - bool NBTTag_eq(const AmuletNBT::LongArrayTag& a, const AmuletNBT::LongArrayTag& b); - bool NBTTag_eq(const AmuletNBT::TagNode& a, const AmuletNBT::TagNode& b); - bool NBTTag_eq(const AmuletNBT::NamedTag& a, const AmuletNBT::NamedTag& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::ByteTag& a, const AmuletNBT::ByteTag& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::ShortTag& a, const AmuletNBT::ShortTag& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::IntTag& a, const AmuletNBT::IntTag& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::LongTag& a, const AmuletNBT::LongTag& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::FloatTag& a, const AmuletNBT::FloatTag& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::DoubleTag& a, const AmuletNBT::DoubleTag& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::ByteArrayTag& a, const AmuletNBT::ByteArrayTag& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::StringTag& a, const AmuletNBT::StringTag& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::ListTag& a, const AmuletNBT::ListTag& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::CompoundTag& a, const AmuletNBT::CompoundTag& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::IntArrayTag& a, const AmuletNBT::IntArrayTag& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::LongArrayTag& a, const AmuletNBT::LongArrayTag& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::TagNode& a, const AmuletNBT::TagNode& b); + AMULET_NBT_DLLX bool NBTTag_eq(const AmuletNBT::NamedTag& a, const AmuletNBT::NamedTag& b); } diff --git a/src/amulet_nbt/pybind/amulet_nbt.cpp b/src/amulet_nbt/pybind/amulet_nbt.cpp index 3125c136..8f86d71f 100644 --- a/src/amulet_nbt/pybind/amulet_nbt.cpp +++ b/src/amulet_nbt/pybind/amulet_nbt.cpp @@ -22,7 +22,7 @@ void init_named_tag(py::module&); void init_bnbt(py::module& m); void init_snbt(py::module& m); -void init_amulet_nbt(py::module& m) { +void init_module(py::module& m) { // Convert cast_error to type_error py::register_local_exception_translator([](std::exception_ptr p) { try { @@ -71,113 +71,8 @@ void init_amulet_nbt(py::module& m) { init_bnbt(m); init_snbt(m); - - // Paths - py::object path_join = py::module::import("os.path").attr("join"); - m.def( - "get_include", - [m, path_join](){ - return path_join(m.attr("__path__").attr("__getitem__")(0), py::str("include")); - }, - py::doc("C++ include directory") - ); - m.def( - "get_source", - [m, path_join](){ - return path_join(m.attr("__path__").attr("__getitem__")(0), py::str("cpp")); - }, - py::doc("C++ source directory") - ); - - // NBT types - py::object PyStr = py::module::import("builtins").attr("str"); - m.attr("SNBTType") = PyStr; - m.attr("IntType") = m.attr("ByteTag") | m.attr("ShortTag") | m.attr("IntTag") | m.attr("LongTag"); - m.attr("FloatType") = m.attr("FloatTag") | m.attr("DoubleTag"); - m.attr("NumberType") = m.attr("IntType") | m.attr("FloatType"); - m.attr("ArrayType") = m.attr("ByteArrayTag") | m.attr("IntArrayTag") | m.attr("LongArrayTag"); - m.attr("AnyNBT") = m.attr("NumberType") | m.attr("StringTag") | m.attr("ListTag") | m.attr("CompoundTag") | m.attr("ArrayType"); - - py::list all; - all.append("__version__"); - all.append("__major__"); - all.append("get_include"); - all.append("AbstractBaseTag"); - all.append("AbstractBaseImmutableTag"); - all.append("AbstractBaseMutableTag"); - all.append("AbstractBaseNumericTag"); - all.append("AbstractBaseIntTag"); - all.append("ByteTag"); - all.append("TAG_Byte"); - all.append("ShortTag"); - all.append("TAG_Short"); - all.append("IntTag"); - all.append("TAG_Int"); - all.append("LongTag"); - all.append("TAG_Long"); - all.append("AbstractBaseFloatTag"); - all.append("FloatTag"); - all.append("TAG_Float"); - all.append("DoubleTag"); - all.append("TAG_Double"); - all.append("AbstractBaseArrayTag"); - all.append("ByteArrayTag"); - all.append("TAG_Byte_Array"); - all.append("IntArrayTag"); - all.append("TAG_Int_Array"); - all.append("LongArrayTag"); - all.append("TAG_Long_Array"); - all.append("StringTag"); - all.append("TAG_String"); - all.append("ListTag"); - all.append("TAG_List"); - all.append("CompoundTag"); - all.append("TAG_Compound"); - all.append("NamedTag"); - all.append("read_nbt"); - all.append("read_nbt_array"); - all.append("ReadOffset"); - all.append("read_snbt"); - all.append("SNBTType"); - all.append("IntType"); - all.append("FloatType"); - all.append("NumberType"); - all.append("ArrayType"); - all.append("AnyNBT"); - all.append("StringEncoding"); - all.append("mutf8_encoding"); - all.append("utf8_encoding"); - all.append("utf8_escape_encoding"); - all.append("EncodingPreset"); - all.append("java_encoding"); - all.append("bedrock_encoding"); - m.attr("__all__") = all; - - // Version numbers - // For some reason the package is not initialised and you can't import submodules. - m.def( - "__getattr__", - [m](py::object attr) -> py::object { - if (py::isinstance(attr)) { - std::string name = attr.cast(); - if (name == "__version__") { - m.attr("__version__") = py::module::import("amulet_nbt._version").attr("get_versions")()["version"]; - return m.attr("__version__"); - } - else if (name == "__major__") { - py::object PyInt = py::module::import("builtins").attr("int"); - py::object re_match = py::module::import("re").attr("match"); - py::object version = py::module::import("amulet_nbt._version").attr("get_versions")()["version"]; - m.attr("__major__") = PyInt(re_match("\\d+", version).attr("group")()); - return m.attr("__major__"); - } - } - throw py::attribute_error("module amulet_nbt has no attribute " + py::repr(attr).cast()); - } - ); } -// The compiler requires __init__ and the runtime requires amulet_nbt. -// There may be a better way to do this but defining both seems to work. -PYBIND11_MODULE(__init__, m) { init_amulet_nbt(m); } -PYBIND11_MODULE(amulet_nbt, m) { init_amulet_nbt(m); } +PYBIND11_MODULE(_amulet_nbt, m) { + m.def("init", &init_module); +} diff --git a/tests/test_amulet_nbt/test_metadata.py b/tests/test_amulet_nbt/test_metadata.py index 1457804e..ed2fa45b 100644 --- a/tests/test_amulet_nbt/test_metadata.py +++ b/tests/test_amulet_nbt/test_metadata.py @@ -1,5 +1,4 @@ import unittest -import os import amulet_nbt @@ -8,12 +7,6 @@ def test_version(self) -> None: self.assertIsInstance(amulet_nbt.__version__, str) self.assertIsInstance(amulet_nbt.__major__, int) - def test_paths(self) -> None: - self.assertIsInstance(amulet_nbt.get_include(), str) - self.assertIsInstance(amulet_nbt.get_source(), str) - self.assertTrue(os.path.isdir(amulet_nbt.get_include())) - self.assertTrue(os.path.isdir(amulet_nbt.get_source())) - if __name__ == "__main__": unittest.main()