GH-1047 parse world files and integrate MCEdit with world page
This commit is contained in:
		| @@ -118,6 +118,11 @@ include_directories(${PACK200_INCLUDE_DIR}) | ||||
| add_subdirectory(depends/rainbow) | ||||
| include_directories(${RAINBOW_INCLUDE_DIR}) | ||||
|  | ||||
| # Add color thingy | ||||
| add_subdirectory(depends/libnbtplusplus) | ||||
| include_directories(${LIBNBTPP_INCLUDE_DIR}) | ||||
| include_directories(${LIBNBTPP_BIN_INCLUDE_DIR}) | ||||
|  | ||||
| ######## MultiMC Libs ######## | ||||
|  | ||||
| # Add the util library. | ||||
|   | ||||
| @@ -19,7 +19,12 @@ | ||||
| #include "dialogs/ModEditDialogCommon.h" | ||||
| #include <QEvent> | ||||
| #include <QKeyEvent> | ||||
| #include <QClipboard> | ||||
| #include <QMessageBox> | ||||
| #include <QTreeView> | ||||
|  | ||||
|  | ||||
| #include "MultiMC.h" | ||||
|  | ||||
| WorldListPage::WorldListPage(BaseInstance *inst, std::shared_ptr<WorldList> worlds, QString id, | ||||
| 							 QString iconName, QString displayName, QString helpPage, | ||||
| @@ -28,8 +33,20 @@ WorldListPage::WorldListPage(BaseInstance *inst, std::shared_ptr<WorldList> worl | ||||
| { | ||||
| 	ui->setupUi(this); | ||||
| 	ui->tabWidget->tabBar()->hide(); | ||||
| 	ui->worldTreeView->setModel(m_worlds.get()); | ||||
| 	QSortFilterProxyModel * proxy = new QSortFilterProxyModel(this); | ||||
| 	proxy->setSourceModel(m_worlds.get()); | ||||
| 	ui->worldTreeView->setSortingEnabled(true); | ||||
| 	ui->worldTreeView->setModel(proxy); | ||||
| 	ui->worldTreeView->installEventFilter(this); | ||||
|  | ||||
| 	auto head = ui->worldTreeView->header(); | ||||
|  | ||||
| 	head->setSectionResizeMode(0, QHeaderView::Stretch); | ||||
| 	head->setSectionResizeMode(1, QHeaderView::ResizeToContents); | ||||
| 	connect(ui->worldTreeView->selectionModel(), | ||||
| 			SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, | ||||
| 			SLOT(worldChanged(const QModelIndex &, const QModelIndex &))); | ||||
| 	worldChanged(QModelIndex(), QModelIndex()); | ||||
| } | ||||
|  | ||||
| void WorldListPage::opened() | ||||
| @@ -79,12 +96,12 @@ bool WorldListPage::eventFilter(QObject *obj, QEvent *ev) | ||||
| 		return worldListFilter(keyEvent); | ||||
| 	return QWidget::eventFilter(obj, ev); | ||||
| } | ||||
|  | ||||
| void WorldListPage::on_rmWorldBtn_clicked() | ||||
| { | ||||
| 	int first, last; | ||||
| 	auto list = ui->worldTreeView->selectionModel()->selectedRows(); | ||||
| 	auto proxiedIndex = getSelectedWorld(); | ||||
|  | ||||
| 	if (!lastfirst(list, first, last)) | ||||
| 	if(!proxiedIndex.isValid()) | ||||
| 		return; | ||||
|  | ||||
| 	auto result = QMessageBox::question(this, | ||||
| @@ -98,7 +115,7 @@ void WorldListPage::on_rmWorldBtn_clicked() | ||||
| 		return; | ||||
| 	} | ||||
| 	m_worlds->stopWatching(); | ||||
| 	m_worlds->deleteWorlds(first, last); | ||||
| 	m_worlds->deleteWorld(proxiedIndex.row()); | ||||
| 	m_worlds->startWatching(); | ||||
| } | ||||
|  | ||||
| @@ -106,3 +123,80 @@ void WorldListPage::on_viewFolderBtn_clicked() | ||||
| { | ||||
| 	openDirInDefaultProgram(m_worlds->dir().absolutePath(), true); | ||||
| } | ||||
|  | ||||
| QModelIndex WorldListPage::getSelectedWorld() | ||||
| { | ||||
| 	auto index = ui->worldTreeView->selectionModel()->currentIndex(); | ||||
|  | ||||
| 	auto proxy = (QSortFilterProxyModel *) ui->worldTreeView->model(); | ||||
| 	return proxy->mapToSource(index); | ||||
| } | ||||
|  | ||||
| void WorldListPage::on_copySeedBtn_clicked() | ||||
| { | ||||
| 	QModelIndex index = getSelectedWorld(); | ||||
|  | ||||
| 	if (!index.isValid()) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 	int64_t seed = m_worlds->data(index, WorldList::SeedRole).toLongLong(); | ||||
| 	MMC->clipboard()->setText(QString::number(seed)); | ||||
| } | ||||
|  | ||||
| void WorldListPage::on_mcEditBtn_clicked() | ||||
| { | ||||
| 	const QString mceditPath = MMC->settings()->get("MCEditPath").toString(); | ||||
|  | ||||
| 	QModelIndex index = getSelectedWorld(); | ||||
|  | ||||
| 	if (!index.isValid()) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	auto fullPath = m_worlds->data(index, WorldList::FolderRole).toString(); | ||||
|  | ||||
| #ifdef Q_OS_OSX | ||||
| 	QProcess *process = new QProcess(); | ||||
| 	connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), process, SLOT(deleteLater())); | ||||
| 	process->setProgram(mceditPath); | ||||
| 	process->setArguments(QStringList() << fullPath); | ||||
| 	process->start(); | ||||
| #else | ||||
| 	QDir mceditDir(mceditPath); | ||||
| 	QString program; | ||||
| 	#ifdef Q_OS_LINUX | ||||
| 	if (mceditDir.exists("mcedit.py")) | ||||
| 	{ | ||||
| 		program = mceditDir.absoluteFilePath("mcedit.py"); | ||||
| 	} | ||||
| 	else if (mceditDir.exists("mcedit.sh")) | ||||
| 	{ | ||||
| 		program = mceditDir.absoluteFilePath("mcedit.sh"); | ||||
| 	} | ||||
| 	#elif defined(Q_OS_WIN32) | ||||
| 	if (mceditDir.exists("mcedit.exe")) | ||||
| 	{ | ||||
| 		program = mceditDir.absoluteFilePath("mcedit.exe"); | ||||
| 	} | ||||
| 	else if (mceditDir.exists("mcedit2.exe")) | ||||
| 	{ | ||||
| 		program = mceditDir.absoluteFilePath("mcedit2.exe"); | ||||
| 	} | ||||
| 	#endif | ||||
| 	if(program.size()) | ||||
| 	{ | ||||
| 		QProcess::startDetached(program, QStringList() << fullPath, mceditPath); | ||||
| 	} | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void WorldListPage::worldChanged(const QModelIndex ¤t, const QModelIndex &previous) | ||||
| { | ||||
| 	QModelIndex index = getSelectedWorld(); | ||||
| 	bool enable = index.isValid(); | ||||
| 	ui->copySeedBtn->setEnabled(enable); | ||||
| 	ui->mcEditBtn->setEnabled(enable); | ||||
| 	ui->rmWorldBtn->setEnabled(enable); | ||||
| } | ||||
|   | ||||
| @@ -66,6 +66,9 @@ protected: | ||||
| protected: | ||||
| 	BaseInstance *m_inst; | ||||
|  | ||||
| private: | ||||
| 	QModelIndex getSelectedWorld(); | ||||
|  | ||||
| private: | ||||
| 	Ui::WorldListPage *ui; | ||||
| 	std::shared_ptr<WorldList> m_worlds; | ||||
| @@ -75,6 +78,9 @@ private: | ||||
| 	QString m_helpName; | ||||
|  | ||||
| private slots: | ||||
| 	void on_copySeedBtn_clicked(); | ||||
| 	void on_mcEditBtn_clicked(); | ||||
| 	void on_rmWorldBtn_clicked(); | ||||
| 	void on_viewFolderBtn_clicked(); | ||||
| 	void worldChanged(const QModelIndex ¤t, const QModelIndex &previous); | ||||
| }; | ||||
|   | ||||
| @@ -1,94 +1,125 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <ui version="4.0"> | ||||
|     <class>WorldListPage</class> | ||||
|     <widget class="QWidget" name="WorldListPage"> | ||||
|         <property name="geometry"> | ||||
|             <rect> | ||||
|                 <x>0</x> | ||||
|                 <y>0</y> | ||||
|                 <width>723</width> | ||||
|                 <height>532</height> | ||||
|             </rect> | ||||
|         </property> | ||||
|         <property name="windowTitle"> | ||||
|             <string>Mods</string> | ||||
|         </property> | ||||
|         <layout class="QVBoxLayout" name="verticalLayout"> | ||||
|             <property name="leftMargin"> | ||||
|                 <number>0</number> | ||||
|             </property> | ||||
|             <property name="topMargin"> | ||||
|                 <number>0</number> | ||||
|             </property> | ||||
|             <property name="rightMargin"> | ||||
|                 <number>0</number> | ||||
|             </property> | ||||
|             <property name="bottomMargin"> | ||||
|                 <number>0</number> | ||||
|             </property> | ||||
|             <item> | ||||
|                 <widget class="QTabWidget" name="tabWidget"> | ||||
|                     <property name="currentIndex"> | ||||
|                         <number>0</number> | ||||
|                     </property> | ||||
|                     <widget class="QWidget" name="tab"> | ||||
|                         <attribute name="title"> | ||||
|                             <string>Tab 1</string> | ||||
|                         </attribute> | ||||
|                         <layout class="QGridLayout" name="gridLayout"> | ||||
|                             <item row="0" column="0"> | ||||
|                                 <widget class="QTreeView" name="worldTreeView"> | ||||
|                                     <property name="sizePolicy"> | ||||
|                                         <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||||
|                                             <horstretch>0</horstretch> | ||||
|                                             <verstretch>0</verstretch> | ||||
|                                         </sizepolicy> | ||||
|                                     </property> | ||||
|                                     <property name="acceptDrops"> | ||||
|                                         <bool>true</bool> | ||||
|                                     </property> | ||||
|                                     <property name="dragDropMode"> | ||||
|                                         <enum>QAbstractItemView::DropOnly</enum> | ||||
|                                     </property> | ||||
|                                 </widget> | ||||
|                             </item> | ||||
|                             <item row="0" column="1"> | ||||
|                                 <layout class="QVBoxLayout" name="verticalLayout_2"> | ||||
|                                     <item> | ||||
|                                         <widget class="QPushButton" name="rmWorldBtn"> | ||||
|                                             <property name="text"> | ||||
|                                                 <string>&Remove</string> | ||||
|                                             </property> | ||||
|                                         </widget> | ||||
|                                     </item> | ||||
|                                     <item> | ||||
|                                         <spacer name="verticalSpacer"> | ||||
|                                             <property name="orientation"> | ||||
|                                                 <enum>Qt::Vertical</enum> | ||||
|                                             </property> | ||||
|                                             <property name="sizeHint" stdset="0"> | ||||
|                                                 <size> | ||||
|                                                     <width>20</width> | ||||
|                                                     <height>40</height> | ||||
|                                                 </size> | ||||
|                                             </property> | ||||
|                                         </spacer> | ||||
|                                     </item> | ||||
|                                     <item> | ||||
|                                         <widget class="QPushButton" name="viewFolderBtn"> | ||||
|                                             <property name="text"> | ||||
|                                                 <string>&View Folder</string> | ||||
|                                             </property> | ||||
|                                         </widget> | ||||
|                                     </item> | ||||
|                                 </layout> | ||||
|                             </item> | ||||
|                         </layout> | ||||
|                     </widget> | ||||
|                 </widget> | ||||
|             </item> | ||||
|  <class>WorldListPage</class> | ||||
|  <widget class="QWidget" name="WorldListPage"> | ||||
|   <property name="geometry"> | ||||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>723</width> | ||||
|     <height>532</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="windowTitle"> | ||||
|    <string>Mods</string> | ||||
|   </property> | ||||
|   <layout class="QVBoxLayout" name="verticalLayout"> | ||||
|    <property name="leftMargin"> | ||||
|     <number>0</number> | ||||
|    </property> | ||||
|    <property name="topMargin"> | ||||
|     <number>0</number> | ||||
|    </property> | ||||
|    <property name="rightMargin"> | ||||
|     <number>0</number> | ||||
|    </property> | ||||
|    <property name="bottomMargin"> | ||||
|     <number>0</number> | ||||
|    </property> | ||||
|    <item> | ||||
|     <widget class="QTabWidget" name="tabWidget"> | ||||
|      <property name="currentIndex"> | ||||
|       <number>0</number> | ||||
|      </property> | ||||
|      <widget class="QWidget" name="tab"> | ||||
|       <attribute name="title"> | ||||
|        <string>Tab 1</string> | ||||
|       </attribute> | ||||
|       <layout class="QGridLayout" name="gridLayout"> | ||||
|        <item row="0" column="0"> | ||||
|         <widget class="QTreeView" name="worldTreeView"> | ||||
|          <property name="sizePolicy"> | ||||
|           <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||||
|            <horstretch>0</horstretch> | ||||
|            <verstretch>0</verstretch> | ||||
|           </sizepolicy> | ||||
|          </property> | ||||
|          <property name="acceptDrops"> | ||||
|           <bool>true</bool> | ||||
|          </property> | ||||
|          <property name="dragDropMode"> | ||||
|           <enum>QAbstractItemView::DropOnly</enum> | ||||
|          </property> | ||||
|          <property name="sortingEnabled"> | ||||
|           <bool>true</bool> | ||||
|          </property> | ||||
|          <property name="allColumnsShowFocus"> | ||||
|           <bool>true</bool> | ||||
|          </property> | ||||
|          <attribute name="headerStretchLastSection"> | ||||
|           <bool>false</bool> | ||||
|          </attribute> | ||||
|         </widget> | ||||
|        </item> | ||||
|        <item row="0" column="1"> | ||||
|         <layout class="QVBoxLayout" name="verticalLayout_2"> | ||||
|          <item> | ||||
|           <widget class="QPushButton" name="mcEditBtn"> | ||||
|            <property name="text"> | ||||
|             <string>MCEdit</string> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item> | ||||
|           <widget class="QPushButton" name="copySeedBtn"> | ||||
|            <property name="text"> | ||||
|             <string>Copy Seed</string> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item> | ||||
|           <widget class="QPushButton" name="rmWorldBtn"> | ||||
|            <property name="text"> | ||||
|             <string>&Remove</string> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item> | ||||
|           <spacer name="verticalSpacer"> | ||||
|            <property name="orientation"> | ||||
|             <enum>Qt::Vertical</enum> | ||||
|            </property> | ||||
|            <property name="sizeHint" stdset="0"> | ||||
|             <size> | ||||
|              <width>20</width> | ||||
|              <height>40</height> | ||||
|             </size> | ||||
|            </property> | ||||
|           </spacer> | ||||
|          </item> | ||||
|          <item> | ||||
|           <widget class="QPushButton" name="viewFolderBtn"> | ||||
|            <property name="text"> | ||||
|             <string>&View Folder</string> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|         </layout> | ||||
|        </item> | ||||
|       </layout> | ||||
|      </widget> | ||||
|     </widget> | ||||
|     <resources/> | ||||
|     <connections/> | ||||
|    </item> | ||||
|   </layout> | ||||
|  </widget> | ||||
|  <tabstops> | ||||
|   <tabstop>tabWidget</tabstop> | ||||
|   <tabstop>worldTreeView</tabstop> | ||||
|   <tabstop>mcEditBtn</tabstop> | ||||
|   <tabstop>copySeedBtn</tabstop> | ||||
|   <tabstop>rmWorldBtn</tabstop> | ||||
|   <tabstop>viewFolderBtn</tabstop> | ||||
|  </tabstops> | ||||
|  <resources/> | ||||
|  <connections/> | ||||
| </ui> | ||||
|   | ||||
							
								
								
									
										50
									
								
								depends/libnbtplusplus/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								depends/libnbtplusplus/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| cmake_minimum_required(VERSION 3.2) | ||||
| project(libnbt++ VERSION 2.1) | ||||
|  | ||||
| add_definitions(-std=c++11) | ||||
| include_directories(include) | ||||
|  | ||||
| set(nbt_sources | ||||
| 	src/endian_str.cpp | ||||
| 	src/tag.cpp | ||||
| 	src/tag_array.cpp | ||||
| 	src/tag_compound.cpp | ||||
| 	src/tag_list.cpp | ||||
| 	src/tag_string.cpp | ||||
| 	src/value.cpp | ||||
| 	src/value_initializer.cpp | ||||
|  | ||||
| 	src/io/stream_reader.cpp | ||||
| 	src/io/stream_writer.cpp | ||||
|  | ||||
| 	src/text/json_formatter.cpp | ||||
|  | ||||
| 	include/value_initializer.h | ||||
| 	include/tag.h | ||||
| 	include/io | ||||
| 	include/io/stream_writer.h | ||||
| 	include/io/stream_reader.h | ||||
| 	include/crtp_tag.h | ||||
| 	include/tag_string.h | ||||
| 	include/value.h | ||||
| 	include/tag_primitive.h | ||||
| 	include/tag_list.h | ||||
| 	include/tagfwd.h | ||||
| 	include/make_unique.h | ||||
| 	include/primitive_detail.h | ||||
| 	include/endian_str.h | ||||
| 	include/tag_compound.h | ||||
| 	include/nbt_tags.h | ||||
| 	include/nbt_visitor.h | ||||
| 	include/text | ||||
| 	include/text/json_formatter.h | ||||
| 	include/tag_array.h | ||||
| ) | ||||
|  | ||||
| set(LIBNBTPP_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include" PARENT_SCOPE) | ||||
| set(LIBNBTPP_BIN_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}" PARENT_SCOPE) | ||||
|  | ||||
| add_library(nbt++ SHARED ${nbt_sources}) | ||||
| generate_export_header(nbt++) | ||||
|  | ||||
| include_directories(${CMAKE_CURRENT_BINARY_DIR}) | ||||
							
								
								
									
										674
									
								
								depends/libnbtplusplus/COPYING
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										674
									
								
								depends/libnbtplusplus/COPYING
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,674 @@ | ||||
|                     GNU GENERAL PUBLIC LICENSE | ||||
|                        Version 3, 29 June 2007 | ||||
|  | ||||
|  Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> | ||||
|  Everyone is permitted to copy and distribute verbatim copies | ||||
|  of this license document, but changing it is not allowed. | ||||
|  | ||||
|                             Preamble | ||||
|  | ||||
|   The GNU General Public License is a free, copyleft license for | ||||
| software and other kinds of works. | ||||
|  | ||||
|   The licenses for most software and other practical works are designed | ||||
| to take away your freedom to share and change the works.  By contrast, | ||||
| the GNU General Public License is intended to guarantee your freedom to | ||||
| share and change all versions of a program--to make sure it remains free | ||||
| software for all its users.  We, the Free Software Foundation, use the | ||||
| GNU General Public License for most of our software; it applies also to | ||||
| any other work released this way by its authors.  You can apply it to | ||||
| your programs, too. | ||||
|  | ||||
|   When we speak of free software, we are referring to freedom, not | ||||
| price.  Our General Public Licenses are designed to make sure that you | ||||
| have the freedom to distribute copies of free software (and charge for | ||||
| them if you wish), that you receive source code or can get it if you | ||||
| want it, that you can change the software or use pieces of it in new | ||||
| free programs, and that you know you can do these things. | ||||
|  | ||||
|   To protect your rights, we need to prevent others from denying you | ||||
| these rights or asking you to surrender the rights.  Therefore, you have | ||||
| certain responsibilities if you distribute copies of the software, or if | ||||
| you modify it: responsibilities to respect the freedom of others. | ||||
|  | ||||
|   For example, if you distribute copies of such a program, whether | ||||
| gratis or for a fee, you must pass on to the recipients the same | ||||
| freedoms that you received.  You must make sure that they, too, receive | ||||
| or can get the source code.  And you must show them these terms so they | ||||
| know their rights. | ||||
|  | ||||
|   Developers that use the GNU GPL protect your rights with two steps: | ||||
| (1) assert copyright on the software, and (2) offer you this License | ||||
| giving you legal permission to copy, distribute and/or modify it. | ||||
|  | ||||
|   For the developers' and authors' protection, the GPL clearly explains | ||||
| that there is no warranty for this free software.  For both users' and | ||||
| authors' sake, the GPL requires that modified versions be marked as | ||||
| changed, so that their problems will not be attributed erroneously to | ||||
| authors of previous versions. | ||||
|  | ||||
|   Some devices are designed to deny users access to install or run | ||||
| modified versions of the software inside them, although the manufacturer | ||||
| can do so.  This is fundamentally incompatible with the aim of | ||||
| protecting users' freedom to change the software.  The systematic | ||||
| pattern of such abuse occurs in the area of products for individuals to | ||||
| use, which is precisely where it is most unacceptable.  Therefore, we | ||||
| have designed this version of the GPL to prohibit the practice for those | ||||
| products.  If such problems arise substantially in other domains, we | ||||
| stand ready to extend this provision to those domains in future versions | ||||
| of the GPL, as needed to protect the freedom of users. | ||||
|  | ||||
|   Finally, every program is threatened constantly by software patents. | ||||
| States should not allow patents to restrict development and use of | ||||
| software on general-purpose computers, but in those that do, we wish to | ||||
| avoid the special danger that patents applied to a free program could | ||||
| make it effectively proprietary.  To prevent this, the GPL assures that | ||||
| patents cannot be used to render the program non-free. | ||||
|  | ||||
|   The precise terms and conditions for copying, distribution and | ||||
| modification follow. | ||||
|  | ||||
|                        TERMS AND CONDITIONS | ||||
|  | ||||
|   0. Definitions. | ||||
|  | ||||
|   "This License" refers to version 3 of the GNU General Public License. | ||||
|  | ||||
|   "Copyright" also means copyright-like laws that apply to other kinds of | ||||
| works, such as semiconductor masks. | ||||
|  | ||||
|   "The Program" refers to any copyrightable work licensed under this | ||||
| License.  Each licensee is addressed as "you".  "Licensees" and | ||||
| "recipients" may be individuals or organizations. | ||||
|  | ||||
|   To "modify" a work means to copy from or adapt all or part of the work | ||||
| in a fashion requiring copyright permission, other than the making of an | ||||
| exact copy.  The resulting work is called a "modified version" of the | ||||
| earlier work or a work "based on" the earlier work. | ||||
|  | ||||
|   A "covered work" means either the unmodified Program or a work based | ||||
| on the Program. | ||||
|  | ||||
|   To "propagate" a work means to do anything with it that, without | ||||
| permission, would make you directly or secondarily liable for | ||||
| infringement under applicable copyright law, except executing it on a | ||||
| computer or modifying a private copy.  Propagation includes copying, | ||||
| distribution (with or without modification), making available to the | ||||
| public, and in some countries other activities as well. | ||||
|  | ||||
|   To "convey" a work means any kind of propagation that enables other | ||||
| parties to make or receive copies.  Mere interaction with a user through | ||||
| a computer network, with no transfer of a copy, is not conveying. | ||||
|  | ||||
|   An interactive user interface displays "Appropriate Legal Notices" | ||||
| to the extent that it includes a convenient and prominently visible | ||||
| feature that (1) displays an appropriate copyright notice, and (2) | ||||
| tells the user that there is no warranty for the work (except to the | ||||
| extent that warranties are provided), that licensees may convey the | ||||
| work under this License, and how to view a copy of this License.  If | ||||
| the interface presents a list of user commands or options, such as a | ||||
| menu, a prominent item in the list meets this criterion. | ||||
|  | ||||
|   1. Source Code. | ||||
|  | ||||
|   The "source code" for a work means the preferred form of the work | ||||
| for making modifications to it.  "Object code" means any non-source | ||||
| form of a work. | ||||
|  | ||||
|   A "Standard Interface" means an interface that either is an official | ||||
| standard defined by a recognized standards body, or, in the case of | ||||
| interfaces specified for a particular programming language, one that | ||||
| is widely used among developers working in that language. | ||||
|  | ||||
|   The "System Libraries" of an executable work include anything, other | ||||
| than the work as a whole, that (a) is included in the normal form of | ||||
| packaging a Major Component, but which is not part of that Major | ||||
| Component, and (b) serves only to enable use of the work with that | ||||
| Major Component, or to implement a Standard Interface for which an | ||||
| implementation is available to the public in source code form.  A | ||||
| "Major Component", in this context, means a major essential component | ||||
| (kernel, window system, and so on) of the specific operating system | ||||
| (if any) on which the executable work runs, or a compiler used to | ||||
| produce the work, or an object code interpreter used to run it. | ||||
|  | ||||
|   The "Corresponding Source" for a work in object code form means all | ||||
| the source code needed to generate, install, and (for an executable | ||||
| work) run the object code and to modify the work, including scripts to | ||||
| control those activities.  However, it does not include the work's | ||||
| System Libraries, or general-purpose tools or generally available free | ||||
| programs which are used unmodified in performing those activities but | ||||
| which are not part of the work.  For example, Corresponding Source | ||||
| includes interface definition files associated with source files for | ||||
| the work, and the source code for shared libraries and dynamically | ||||
| linked subprograms that the work is specifically designed to require, | ||||
| such as by intimate data communication or control flow between those | ||||
| subprograms and other parts of the work. | ||||
|  | ||||
|   The Corresponding Source need not include anything that users | ||||
| can regenerate automatically from other parts of the Corresponding | ||||
| Source. | ||||
|  | ||||
|   The Corresponding Source for a work in source code form is that | ||||
| same work. | ||||
|  | ||||
|   2. Basic Permissions. | ||||
|  | ||||
|   All rights granted under this License are granted for the term of | ||||
| copyright on the Program, and are irrevocable provided the stated | ||||
| conditions are met.  This License explicitly affirms your unlimited | ||||
| permission to run the unmodified Program.  The output from running a | ||||
| covered work is covered by this License only if the output, given its | ||||
| content, constitutes a covered work.  This License acknowledges your | ||||
| rights of fair use or other equivalent, as provided by copyright law. | ||||
|  | ||||
|   You may make, run and propagate covered works that you do not | ||||
| convey, without conditions so long as your license otherwise remains | ||||
| in force.  You may convey covered works to others for the sole purpose | ||||
| of having them make modifications exclusively for you, or provide you | ||||
| with facilities for running those works, provided that you comply with | ||||
| the terms of this License in conveying all material for which you do | ||||
| not control copyright.  Those thus making or running the covered works | ||||
| for you must do so exclusively on your behalf, under your direction | ||||
| and control, on terms that prohibit them from making any copies of | ||||
| your copyrighted material outside their relationship with you. | ||||
|  | ||||
|   Conveying under any other circumstances is permitted solely under | ||||
| the conditions stated below.  Sublicensing is not allowed; section 10 | ||||
| makes it unnecessary. | ||||
|  | ||||
|   3. Protecting Users' Legal Rights From Anti-Circumvention Law. | ||||
|  | ||||
|   No covered work shall be deemed part of an effective technological | ||||
| measure under any applicable law fulfilling obligations under article | ||||
| 11 of the WIPO copyright treaty adopted on 20 December 1996, or | ||||
| similar laws prohibiting or restricting circumvention of such | ||||
| measures. | ||||
|  | ||||
|   When you convey a covered work, you waive any legal power to forbid | ||||
| circumvention of technological measures to the extent such circumvention | ||||
| is effected by exercising rights under this License with respect to | ||||
| the covered work, and you disclaim any intention to limit operation or | ||||
| modification of the work as a means of enforcing, against the work's | ||||
| users, your or third parties' legal rights to forbid circumvention of | ||||
| technological measures. | ||||
|  | ||||
|   4. Conveying Verbatim Copies. | ||||
|  | ||||
|   You may convey verbatim copies of the Program's source code as you | ||||
| receive it, in any medium, provided that you conspicuously and | ||||
| appropriately publish on each copy an appropriate copyright notice; | ||||
| keep intact all notices stating that this License and any | ||||
| non-permissive terms added in accord with section 7 apply to the code; | ||||
| keep intact all notices of the absence of any warranty; and give all | ||||
| recipients a copy of this License along with the Program. | ||||
|  | ||||
|   You may charge any price or no price for each copy that you convey, | ||||
| and you may offer support or warranty protection for a fee. | ||||
|  | ||||
|   5. Conveying Modified Source Versions. | ||||
|  | ||||
|   You may convey a work based on the Program, or the modifications to | ||||
| produce it from the Program, in the form of source code under the | ||||
| terms of section 4, provided that you also meet all of these conditions: | ||||
|  | ||||
|     a) The work must carry prominent notices stating that you modified | ||||
|     it, and giving a relevant date. | ||||
|  | ||||
|     b) The work must carry prominent notices stating that it is | ||||
|     released under this License and any conditions added under section | ||||
|     7.  This requirement modifies the requirement in section 4 to | ||||
|     "keep intact all notices". | ||||
|  | ||||
|     c) You must license the entire work, as a whole, under this | ||||
|     License to anyone who comes into possession of a copy.  This | ||||
|     License will therefore apply, along with any applicable section 7 | ||||
|     additional terms, to the whole of the work, and all its parts, | ||||
|     regardless of how they are packaged.  This License gives no | ||||
|     permission to license the work in any other way, but it does not | ||||
|     invalidate such permission if you have separately received it. | ||||
|  | ||||
|     d) If the work has interactive user interfaces, each must display | ||||
|     Appropriate Legal Notices; however, if the Program has interactive | ||||
|     interfaces that do not display Appropriate Legal Notices, your | ||||
|     work need not make them do so. | ||||
|  | ||||
|   A compilation of a covered work with other separate and independent | ||||
| works, which are not by their nature extensions of the covered work, | ||||
| and which are not combined with it such as to form a larger program, | ||||
| in or on a volume of a storage or distribution medium, is called an | ||||
| "aggregate" if the compilation and its resulting copyright are not | ||||
| used to limit the access or legal rights of the compilation's users | ||||
| beyond what the individual works permit.  Inclusion of a covered work | ||||
| in an aggregate does not cause this License to apply to the other | ||||
| parts of the aggregate. | ||||
|  | ||||
|   6. Conveying Non-Source Forms. | ||||
|  | ||||
|   You may convey a covered work in object code form under the terms | ||||
| of sections 4 and 5, provided that you also convey the | ||||
| machine-readable Corresponding Source under the terms of this License, | ||||
| in one of these ways: | ||||
|  | ||||
|     a) Convey the object code in, or embodied in, a physical product | ||||
|     (including a physical distribution medium), accompanied by the | ||||
|     Corresponding Source fixed on a durable physical medium | ||||
|     customarily used for software interchange. | ||||
|  | ||||
|     b) Convey the object code in, or embodied in, a physical product | ||||
|     (including a physical distribution medium), accompanied by a | ||||
|     written offer, valid for at least three years and valid for as | ||||
|     long as you offer spare parts or customer support for that product | ||||
|     model, to give anyone who possesses the object code either (1) a | ||||
|     copy of the Corresponding Source for all the software in the | ||||
|     product that is covered by this License, on a durable physical | ||||
|     medium customarily used for software interchange, for a price no | ||||
|     more than your reasonable cost of physically performing this | ||||
|     conveying of source, or (2) access to copy the | ||||
|     Corresponding Source from a network server at no charge. | ||||
|  | ||||
|     c) Convey individual copies of the object code with a copy of the | ||||
|     written offer to provide the Corresponding Source.  This | ||||
|     alternative is allowed only occasionally and noncommercially, and | ||||
|     only if you received the object code with such an offer, in accord | ||||
|     with subsection 6b. | ||||
|  | ||||
|     d) Convey the object code by offering access from a designated | ||||
|     place (gratis or for a charge), and offer equivalent access to the | ||||
|     Corresponding Source in the same way through the same place at no | ||||
|     further charge.  You need not require recipients to copy the | ||||
|     Corresponding Source along with the object code.  If the place to | ||||
|     copy the object code is a network server, the Corresponding Source | ||||
|     may be on a different server (operated by you or a third party) | ||||
|     that supports equivalent copying facilities, provided you maintain | ||||
|     clear directions next to the object code saying where to find the | ||||
|     Corresponding Source.  Regardless of what server hosts the | ||||
|     Corresponding Source, you remain obligated to ensure that it is | ||||
|     available for as long as needed to satisfy these requirements. | ||||
|  | ||||
|     e) Convey the object code using peer-to-peer transmission, provided | ||||
|     you inform other peers where the object code and Corresponding | ||||
|     Source of the work are being offered to the general public at no | ||||
|     charge under subsection 6d. | ||||
|  | ||||
|   A separable portion of the object code, whose source code is excluded | ||||
| from the Corresponding Source as a System Library, need not be | ||||
| included in conveying the object code work. | ||||
|  | ||||
|   A "User Product" is either (1) a "consumer product", which means any | ||||
| tangible personal property which is normally used for personal, family, | ||||
| or household purposes, or (2) anything designed or sold for incorporation | ||||
| into a dwelling.  In determining whether a product is a consumer product, | ||||
| doubtful cases shall be resolved in favor of coverage.  For a particular | ||||
| product received by a particular user, "normally used" refers to a | ||||
| typical or common use of that class of product, regardless of the status | ||||
| of the particular user or of the way in which the particular user | ||||
| actually uses, or expects or is expected to use, the product.  A product | ||||
| is a consumer product regardless of whether the product has substantial | ||||
| commercial, industrial or non-consumer uses, unless such uses represent | ||||
| the only significant mode of use of the product. | ||||
|  | ||||
|   "Installation Information" for a User Product means any methods, | ||||
| procedures, authorization keys, or other information required to install | ||||
| and execute modified versions of a covered work in that User Product from | ||||
| a modified version of its Corresponding Source.  The information must | ||||
| suffice to ensure that the continued functioning of the modified object | ||||
| code is in no case prevented or interfered with solely because | ||||
| modification has been made. | ||||
|  | ||||
|   If you convey an object code work under this section in, or with, or | ||||
| specifically for use in, a User Product, and the conveying occurs as | ||||
| part of a transaction in which the right of possession and use of the | ||||
| User Product is transferred to the recipient in perpetuity or for a | ||||
| fixed term (regardless of how the transaction is characterized), the | ||||
| Corresponding Source conveyed under this section must be accompanied | ||||
| by the Installation Information.  But this requirement does not apply | ||||
| if neither you nor any third party retains the ability to install | ||||
| modified object code on the User Product (for example, the work has | ||||
| been installed in ROM). | ||||
|  | ||||
|   The requirement to provide Installation Information does not include a | ||||
| requirement to continue to provide support service, warranty, or updates | ||||
| for a work that has been modified or installed by the recipient, or for | ||||
| the User Product in which it has been modified or installed.  Access to a | ||||
| network may be denied when the modification itself materially and | ||||
| adversely affects the operation of the network or violates the rules and | ||||
| protocols for communication across the network. | ||||
|  | ||||
|   Corresponding Source conveyed, and Installation Information provided, | ||||
| in accord with this section must be in a format that is publicly | ||||
| documented (and with an implementation available to the public in | ||||
| source code form), and must require no special password or key for | ||||
| unpacking, reading or copying. | ||||
|  | ||||
|   7. Additional Terms. | ||||
|  | ||||
|   "Additional permissions" are terms that supplement the terms of this | ||||
| License by making exceptions from one or more of its conditions. | ||||
| Additional permissions that are applicable to the entire Program shall | ||||
| be treated as though they were included in this License, to the extent | ||||
| that they are valid under applicable law.  If additional permissions | ||||
| apply only to part of the Program, that part may be used separately | ||||
| under those permissions, but the entire Program remains governed by | ||||
| this License without regard to the additional permissions. | ||||
|  | ||||
|   When you convey a copy of a covered work, you may at your option | ||||
| remove any additional permissions from that copy, or from any part of | ||||
| it.  (Additional permissions may be written to require their own | ||||
| removal in certain cases when you modify the work.)  You may place | ||||
| additional permissions on material, added by you to a covered work, | ||||
| for which you have or can give appropriate copyright permission. | ||||
|  | ||||
|   Notwithstanding any other provision of this License, for material you | ||||
| add to a covered work, you may (if authorized by the copyright holders of | ||||
| that material) supplement the terms of this License with terms: | ||||
|  | ||||
|     a) Disclaiming warranty or limiting liability differently from the | ||||
|     terms of sections 15 and 16 of this License; or | ||||
|  | ||||
|     b) Requiring preservation of specified reasonable legal notices or | ||||
|     author attributions in that material or in the Appropriate Legal | ||||
|     Notices displayed by works containing it; or | ||||
|  | ||||
|     c) Prohibiting misrepresentation of the origin of that material, or | ||||
|     requiring that modified versions of such material be marked in | ||||
|     reasonable ways as different from the original version; or | ||||
|  | ||||
|     d) Limiting the use for publicity purposes of names of licensors or | ||||
|     authors of the material; or | ||||
|  | ||||
|     e) Declining to grant rights under trademark law for use of some | ||||
|     trade names, trademarks, or service marks; or | ||||
|  | ||||
|     f) Requiring indemnification of licensors and authors of that | ||||
|     material by anyone who conveys the material (or modified versions of | ||||
|     it) with contractual assumptions of liability to the recipient, for | ||||
|     any liability that these contractual assumptions directly impose on | ||||
|     those licensors and authors. | ||||
|  | ||||
|   All other non-permissive additional terms are considered "further | ||||
| restrictions" within the meaning of section 10.  If the Program as you | ||||
| received it, or any part of it, contains a notice stating that it is | ||||
| governed by this License along with a term that is a further | ||||
| restriction, you may remove that term.  If a license document contains | ||||
| a further restriction but permits relicensing or conveying under this | ||||
| License, you may add to a covered work material governed by the terms | ||||
| of that license document, provided that the further restriction does | ||||
| not survive such relicensing or conveying. | ||||
|  | ||||
|   If you add terms to a covered work in accord with this section, you | ||||
| must place, in the relevant source files, a statement of the | ||||
| additional terms that apply to those files, or a notice indicating | ||||
| where to find the applicable terms. | ||||
|  | ||||
|   Additional terms, permissive or non-permissive, may be stated in the | ||||
| form of a separately written license, or stated as exceptions; | ||||
| the above requirements apply either way. | ||||
|  | ||||
|   8. Termination. | ||||
|  | ||||
|   You may not propagate or modify a covered work except as expressly | ||||
| provided under this License.  Any attempt otherwise to propagate or | ||||
| modify it is void, and will automatically terminate your rights under | ||||
| this License (including any patent licenses granted under the third | ||||
| paragraph of section 11). | ||||
|  | ||||
|   However, if you cease all violation of this License, then your | ||||
| license from a particular copyright holder is reinstated (a) | ||||
| provisionally, unless and until the copyright holder explicitly and | ||||
| finally terminates your license, and (b) permanently, if the copyright | ||||
| holder fails to notify you of the violation by some reasonable means | ||||
| prior to 60 days after the cessation. | ||||
|  | ||||
|   Moreover, your license from a particular copyright holder is | ||||
| reinstated permanently if the copyright holder notifies you of the | ||||
| violation by some reasonable means, this is the first time you have | ||||
| received notice of violation of this License (for any work) from that | ||||
| copyright holder, and you cure the violation prior to 30 days after | ||||
| your receipt of the notice. | ||||
|  | ||||
|   Termination of your rights under this section does not terminate the | ||||
| licenses of parties who have received copies or rights from you under | ||||
| this License.  If your rights have been terminated and not permanently | ||||
| reinstated, you do not qualify to receive new licenses for the same | ||||
| material under section 10. | ||||
|  | ||||
|   9. Acceptance Not Required for Having Copies. | ||||
|  | ||||
|   You are not required to accept this License in order to receive or | ||||
| run a copy of the Program.  Ancillary propagation of a covered work | ||||
| occurring solely as a consequence of using peer-to-peer transmission | ||||
| to receive a copy likewise does not require acceptance.  However, | ||||
| nothing other than this License grants you permission to propagate or | ||||
| modify any covered work.  These actions infringe copyright if you do | ||||
| not accept this License.  Therefore, by modifying or propagating a | ||||
| covered work, you indicate your acceptance of this License to do so. | ||||
|  | ||||
|   10. Automatic Licensing of Downstream Recipients. | ||||
|  | ||||
|   Each time you convey a covered work, the recipient automatically | ||||
| receives a license from the original licensors, to run, modify and | ||||
| propagate that work, subject to this License.  You are not responsible | ||||
| for enforcing compliance by third parties with this License. | ||||
|  | ||||
|   An "entity transaction" is a transaction transferring control of an | ||||
| organization, or substantially all assets of one, or subdividing an | ||||
| organization, or merging organizations.  If propagation of a covered | ||||
| work results from an entity transaction, each party to that | ||||
| transaction who receives a copy of the work also receives whatever | ||||
| licenses to the work the party's predecessor in interest had or could | ||||
| give under the previous paragraph, plus a right to possession of the | ||||
| Corresponding Source of the work from the predecessor in interest, if | ||||
| the predecessor has it or can get it with reasonable efforts. | ||||
|  | ||||
|   You may not impose any further restrictions on the exercise of the | ||||
| rights granted or affirmed under this License.  For example, you may | ||||
| not impose a license fee, royalty, or other charge for exercise of | ||||
| rights granted under this License, and you may not initiate litigation | ||||
| (including a cross-claim or counterclaim in a lawsuit) alleging that | ||||
| any patent claim is infringed by making, using, selling, offering for | ||||
| sale, or importing the Program or any portion of it. | ||||
|  | ||||
|   11. Patents. | ||||
|  | ||||
|   A "contributor" is a copyright holder who authorizes use under this | ||||
| License of the Program or a work on which the Program is based.  The | ||||
| work thus licensed is called the contributor's "contributor version". | ||||
|  | ||||
|   A contributor's "essential patent claims" are all patent claims | ||||
| owned or controlled by the contributor, whether already acquired or | ||||
| hereafter acquired, that would be infringed by some manner, permitted | ||||
| by this License, of making, using, or selling its contributor version, | ||||
| but do not include claims that would be infringed only as a | ||||
| consequence of further modification of the contributor version.  For | ||||
| purposes of this definition, "control" includes the right to grant | ||||
| patent sublicenses in a manner consistent with the requirements of | ||||
| this License. | ||||
|  | ||||
|   Each contributor grants you a non-exclusive, worldwide, royalty-free | ||||
| patent license under the contributor's essential patent claims, to | ||||
| make, use, sell, offer for sale, import and otherwise run, modify and | ||||
| propagate the contents of its contributor version. | ||||
|  | ||||
|   In the following three paragraphs, a "patent license" is any express | ||||
| agreement or commitment, however denominated, not to enforce a patent | ||||
| (such as an express permission to practice a patent or covenant not to | ||||
| sue for patent infringement).  To "grant" such a patent license to a | ||||
| party means to make such an agreement or commitment not to enforce a | ||||
| patent against the party. | ||||
|  | ||||
|   If you convey a covered work, knowingly relying on a patent license, | ||||
| and the Corresponding Source of the work is not available for anyone | ||||
| to copy, free of charge and under the terms of this License, through a | ||||
| publicly available network server or other readily accessible means, | ||||
| then you must either (1) cause the Corresponding Source to be so | ||||
| available, or (2) arrange to deprive yourself of the benefit of the | ||||
| patent license for this particular work, or (3) arrange, in a manner | ||||
| consistent with the requirements of this License, to extend the patent | ||||
| license to downstream recipients.  "Knowingly relying" means you have | ||||
| actual knowledge that, but for the patent license, your conveying the | ||||
| covered work in a country, or your recipient's use of the covered work | ||||
| in a country, would infringe one or more identifiable patents in that | ||||
| country that you have reason to believe are valid. | ||||
|  | ||||
|   If, pursuant to or in connection with a single transaction or | ||||
| arrangement, you convey, or propagate by procuring conveyance of, a | ||||
| covered work, and grant a patent license to some of the parties | ||||
| receiving the covered work authorizing them to use, propagate, modify | ||||
| or convey a specific copy of the covered work, then the patent license | ||||
| you grant is automatically extended to all recipients of the covered | ||||
| work and works based on it. | ||||
|  | ||||
|   A patent license is "discriminatory" if it does not include within | ||||
| the scope of its coverage, prohibits the exercise of, or is | ||||
| conditioned on the non-exercise of one or more of the rights that are | ||||
| specifically granted under this License.  You may not convey a covered | ||||
| work if you are a party to an arrangement with a third party that is | ||||
| in the business of distributing software, under which you make payment | ||||
| to the third party based on the extent of your activity of conveying | ||||
| the work, and under which the third party grants, to any of the | ||||
| parties who would receive the covered work from you, a discriminatory | ||||
| patent license (a) in connection with copies of the covered work | ||||
| conveyed by you (or copies made from those copies), or (b) primarily | ||||
| for and in connection with specific products or compilations that | ||||
| contain the covered work, unless you entered into that arrangement, | ||||
| or that patent license was granted, prior to 28 March 2007. | ||||
|  | ||||
|   Nothing in this License shall be construed as excluding or limiting | ||||
| any implied license or other defenses to infringement that may | ||||
| otherwise be available to you under applicable patent law. | ||||
|  | ||||
|   12. No Surrender of Others' Freedom. | ||||
|  | ||||
|   If conditions are imposed on you (whether by court order, agreement or | ||||
| otherwise) that contradict the conditions of this License, they do not | ||||
| excuse you from the conditions of this License.  If you cannot convey a | ||||
| covered work so as to satisfy simultaneously your obligations under this | ||||
| License and any other pertinent obligations, then as a consequence you may | ||||
| not convey it at all.  For example, if you agree to terms that obligate you | ||||
| to collect a royalty for further conveying from those to whom you convey | ||||
| the Program, the only way you could satisfy both those terms and this | ||||
| License would be to refrain entirely from conveying the Program. | ||||
|  | ||||
|   13. Use with the GNU Affero General Public License. | ||||
|  | ||||
|   Notwithstanding any other provision of this License, you have | ||||
| permission to link or combine any covered work with a work licensed | ||||
| under version 3 of the GNU Affero General Public License into a single | ||||
| combined work, and to convey the resulting work.  The terms of this | ||||
| License will continue to apply to the part which is the covered work, | ||||
| but the special requirements of the GNU Affero General Public License, | ||||
| section 13, concerning interaction through a network will apply to the | ||||
| combination as such. | ||||
|  | ||||
|   14. Revised Versions of this License. | ||||
|  | ||||
|   The Free Software Foundation may publish revised and/or new versions of | ||||
| the GNU General Public License from time to time.  Such new versions will | ||||
| be similar in spirit to the present version, but may differ in detail to | ||||
| address new problems or concerns. | ||||
|  | ||||
|   Each version is given a distinguishing version number.  If the | ||||
| Program specifies that a certain numbered version of the GNU General | ||||
| Public License "or any later version" applies to it, you have the | ||||
| option of following the terms and conditions either of that numbered | ||||
| version or of any later version published by the Free Software | ||||
| Foundation.  If the Program does not specify a version number of the | ||||
| GNU General Public License, you may choose any version ever published | ||||
| by the Free Software Foundation. | ||||
|  | ||||
|   If the Program specifies that a proxy can decide which future | ||||
| versions of the GNU General Public License can be used, that proxy's | ||||
| public statement of acceptance of a version permanently authorizes you | ||||
| to choose that version for the Program. | ||||
|  | ||||
|   Later license versions may give you additional or different | ||||
| permissions.  However, no additional obligations are imposed on any | ||||
| author or copyright holder as a result of your choosing to follow a | ||||
| later version. | ||||
|  | ||||
|   15. Disclaimer of Warranty. | ||||
|  | ||||
|   THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY | ||||
| APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT | ||||
| HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY | ||||
| OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, | ||||
| THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||||
| PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM | ||||
| IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF | ||||
| ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | ||||
|  | ||||
|   16. Limitation of Liability. | ||||
|  | ||||
|   IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | ||||
| WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS | ||||
| THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY | ||||
| GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE | ||||
| USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF | ||||
| DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD | ||||
| PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), | ||||
| EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF | ||||
| SUCH DAMAGES. | ||||
|  | ||||
|   17. Interpretation of Sections 15 and 16. | ||||
|  | ||||
|   If the disclaimer of warranty and limitation of liability provided | ||||
| above cannot be given local legal effect according to their terms, | ||||
| reviewing courts shall apply local law that most closely approximates | ||||
| an absolute waiver of all civil liability in connection with the | ||||
| Program, unless a warranty or assumption of liability accompanies a | ||||
| copy of the Program in return for a fee. | ||||
|  | ||||
|                      END OF TERMS AND CONDITIONS | ||||
|  | ||||
|             How to Apply These Terms to Your New Programs | ||||
|  | ||||
|   If you develop a new program, and you want it to be of the greatest | ||||
| possible use to the public, the best way to achieve this is to make it | ||||
| free software which everyone can redistribute and change under these terms. | ||||
|  | ||||
|   To do so, attach the following notices to the program.  It is safest | ||||
| to attach them to the start of each source file to most effectively | ||||
| state the exclusion of warranty; and each file should have at least | ||||
| the "copyright" line and a pointer to where the full notice is found. | ||||
|  | ||||
|     <one line to give the program's name and a brief idea of what it does.> | ||||
|     Copyright (C) <year>  <name of author> | ||||
|  | ||||
|     This program is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| Also add information on how to contact you by electronic and paper mail. | ||||
|  | ||||
|   If the program does terminal interaction, make it output a short | ||||
| notice like this when it starts in an interactive mode: | ||||
|  | ||||
|     <program>  Copyright (C) <year>  <name of author> | ||||
|     This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | ||||
|     This is free software, and you are welcome to redistribute it | ||||
|     under certain conditions; type `show c' for details. | ||||
|  | ||||
| The hypothetical commands `show w' and `show c' should show the appropriate | ||||
| parts of the General Public License.  Of course, your program's commands | ||||
| might be different; for a GUI interface, you would use an "about box". | ||||
|  | ||||
|   You should also get your employer (if you work as a programmer) or school, | ||||
| if any, to sign a "copyright disclaimer" for the program, if necessary. | ||||
| For more information on this, and how to apply and follow the GNU GPL, see | ||||
| <http://www.gnu.org/licenses/>. | ||||
|  | ||||
|   The GNU General Public License does not permit incorporating your program | ||||
| into proprietary programs.  If your program is a subroutine library, you | ||||
| may consider it more useful to permit linking proprietary applications with | ||||
| the library.  If this is what you want to do, use the GNU Lesser General | ||||
| Public License instead of this License.  But first, please read | ||||
| <http://www.gnu.org/philosophy/why-not-lgpl.html>. | ||||
							
								
								
									
										165
									
								
								depends/libnbtplusplus/COPYING.LESSER
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								depends/libnbtplusplus/COPYING.LESSER
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | ||||
|                    GNU LESSER GENERAL PUBLIC LICENSE | ||||
|                        Version 3, 29 June 2007 | ||||
|  | ||||
|  Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> | ||||
|  Everyone is permitted to copy and distribute verbatim copies | ||||
|  of this license document, but changing it is not allowed. | ||||
|  | ||||
|  | ||||
|   This version of the GNU Lesser General Public License incorporates | ||||
| the terms and conditions of version 3 of the GNU General Public | ||||
| License, supplemented by the additional permissions listed below. | ||||
|  | ||||
|   0. Additional Definitions. | ||||
|  | ||||
|   As used herein, "this License" refers to version 3 of the GNU Lesser | ||||
| General Public License, and the "GNU GPL" refers to version 3 of the GNU | ||||
| General Public License. | ||||
|  | ||||
|   "The Library" refers to a covered work governed by this License, | ||||
| other than an Application or a Combined Work as defined below. | ||||
|  | ||||
|   An "Application" is any work that makes use of an interface provided | ||||
| by the Library, but which is not otherwise based on the Library. | ||||
| Defining a subclass of a class defined by the Library is deemed a mode | ||||
| of using an interface provided by the Library. | ||||
|  | ||||
|   A "Combined Work" is a work produced by combining or linking an | ||||
| Application with the Library.  The particular version of the Library | ||||
| with which the Combined Work was made is also called the "Linked | ||||
| Version". | ||||
|  | ||||
|   The "Minimal Corresponding Source" for a Combined Work means the | ||||
| Corresponding Source for the Combined Work, excluding any source code | ||||
| for portions of the Combined Work that, considered in isolation, are | ||||
| based on the Application, and not on the Linked Version. | ||||
|  | ||||
|   The "Corresponding Application Code" for a Combined Work means the | ||||
| object code and/or source code for the Application, including any data | ||||
| and utility programs needed for reproducing the Combined Work from the | ||||
| Application, but excluding the System Libraries of the Combined Work. | ||||
|  | ||||
|   1. Exception to Section 3 of the GNU GPL. | ||||
|  | ||||
|   You may convey a covered work under sections 3 and 4 of this License | ||||
| without being bound by section 3 of the GNU GPL. | ||||
|  | ||||
|   2. Conveying Modified Versions. | ||||
|  | ||||
|   If you modify a copy of the Library, and, in your modifications, a | ||||
| facility refers to a function or data to be supplied by an Application | ||||
| that uses the facility (other than as an argument passed when the | ||||
| facility is invoked), then you may convey a copy of the modified | ||||
| version: | ||||
|  | ||||
|    a) under this License, provided that you make a good faith effort to | ||||
|    ensure that, in the event an Application does not supply the | ||||
|    function or data, the facility still operates, and performs | ||||
|    whatever part of its purpose remains meaningful, or | ||||
|  | ||||
|    b) under the GNU GPL, with none of the additional permissions of | ||||
|    this License applicable to that copy. | ||||
|  | ||||
|   3. Object Code Incorporating Material from Library Header Files. | ||||
|  | ||||
|   The object code form of an Application may incorporate material from | ||||
| a header file that is part of the Library.  You may convey such object | ||||
| code under terms of your choice, provided that, if the incorporated | ||||
| material is not limited to numerical parameters, data structure | ||||
| layouts and accessors, or small macros, inline functions and templates | ||||
| (ten or fewer lines in length), you do both of the following: | ||||
|  | ||||
|    a) Give prominent notice with each copy of the object code that the | ||||
|    Library is used in it and that the Library and its use are | ||||
|    covered by this License. | ||||
|  | ||||
|    b) Accompany the object code with a copy of the GNU GPL and this license | ||||
|    document. | ||||
|  | ||||
|   4. Combined Works. | ||||
|  | ||||
|   You may convey a Combined Work under terms of your choice that, | ||||
| taken together, effectively do not restrict modification of the | ||||
| portions of the Library contained in the Combined Work and reverse | ||||
| engineering for debugging such modifications, if you also do each of | ||||
| the following: | ||||
|  | ||||
|    a) Give prominent notice with each copy of the Combined Work that | ||||
|    the Library is used in it and that the Library and its use are | ||||
|    covered by this License. | ||||
|  | ||||
|    b) Accompany the Combined Work with a copy of the GNU GPL and this license | ||||
|    document. | ||||
|  | ||||
|    c) For a Combined Work that displays copyright notices during | ||||
|    execution, include the copyright notice for the Library among | ||||
|    these notices, as well as a reference directing the user to the | ||||
|    copies of the GNU GPL and this license document. | ||||
|  | ||||
|    d) Do one of the following: | ||||
|  | ||||
|        0) Convey the Minimal Corresponding Source under the terms of this | ||||
|        License, and the Corresponding Application Code in a form | ||||
|        suitable for, and under terms that permit, the user to | ||||
|        recombine or relink the Application with a modified version of | ||||
|        the Linked Version to produce a modified Combined Work, in the | ||||
|        manner specified by section 6 of the GNU GPL for conveying | ||||
|        Corresponding Source. | ||||
|  | ||||
|        1) Use a suitable shared library mechanism for linking with the | ||||
|        Library.  A suitable mechanism is one that (a) uses at run time | ||||
|        a copy of the Library already present on the user's computer | ||||
|        system, and (b) will operate properly with a modified version | ||||
|        of the Library that is interface-compatible with the Linked | ||||
|        Version. | ||||
|  | ||||
|    e) Provide Installation Information, but only if you would otherwise | ||||
|    be required to provide such information under section 6 of the | ||||
|    GNU GPL, and only to the extent that such information is | ||||
|    necessary to install and execute a modified version of the | ||||
|    Combined Work produced by recombining or relinking the | ||||
|    Application with a modified version of the Linked Version. (If | ||||
|    you use option 4d0, the Installation Information must accompany | ||||
|    the Minimal Corresponding Source and Corresponding Application | ||||
|    Code. If you use option 4d1, you must provide the Installation | ||||
|    Information in the manner specified by section 6 of the GNU GPL | ||||
|    for conveying Corresponding Source.) | ||||
|  | ||||
|   5. Combined Libraries. | ||||
|  | ||||
|   You may place library facilities that are a work based on the | ||||
| Library side by side in a single library together with other library | ||||
| facilities that are not Applications and are not covered by this | ||||
| License, and convey such a combined library under terms of your | ||||
| choice, if you do both of the following: | ||||
|  | ||||
|    a) Accompany the combined library with a copy of the same work based | ||||
|    on the Library, uncombined with any other library facilities, | ||||
|    conveyed under the terms of this License. | ||||
|  | ||||
|    b) Give prominent notice with the combined library that part of it | ||||
|    is a work based on the Library, and explaining where to find the | ||||
|    accompanying uncombined form of the same work. | ||||
|  | ||||
|   6. Revised Versions of the GNU Lesser General Public License. | ||||
|  | ||||
|   The Free Software Foundation may publish revised and/or new versions | ||||
| of the GNU Lesser General Public License from time to time. Such new | ||||
| versions will be similar in spirit to the present version, but may | ||||
| differ in detail to address new problems or concerns. | ||||
|  | ||||
|   Each version is given a distinguishing version number. If the | ||||
| Library as you received it specifies that a certain numbered version | ||||
| of the GNU Lesser General Public License "or any later version" | ||||
| applies to it, you have the option of following the terms and | ||||
| conditions either of that published version or of any later version | ||||
| published by the Free Software Foundation. If the Library as you | ||||
| received it does not specify a version number of the GNU Lesser | ||||
| General Public License, you may choose any version of the GNU Lesser | ||||
| General Public License ever published by the Free Software Foundation. | ||||
|  | ||||
|   If the Library as you received it specifies that a proxy can decide | ||||
| whether future versions of the GNU Lesser General Public License shall | ||||
| apply, that proxy's public statement of acceptance of any version is | ||||
| permanent authorization for you to choose that version for the | ||||
| Library. | ||||
							
								
								
									
										60
									
								
								depends/libnbtplusplus/PRD.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								depends/libnbtplusplus/PRD.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| # libnbt++2 Product Requirements Document | ||||
|  | ||||
| ### Purpose | ||||
| Provide a C++ interface for working with NBT data, particularly originating | ||||
| from Minecraft. | ||||
|  | ||||
| ### Scope | ||||
| External Minecraft utilities that read or manipulate parts of savefiles, | ||||
| such as: | ||||
| - (Graphical) NBT editors | ||||
| - Inventory editors | ||||
| - Tools for reading or changing world metadata | ||||
| - Map editors and visualizers | ||||
|  | ||||
| ### Definitions, Acronyms and Abbreviations | ||||
| - **libnbt++1:** The predecessor of libnbt++2. | ||||
| - **Minecraft:** A sandbox voxel world game written in Java, developed by | ||||
|   Mojang. | ||||
| - **Mojang's implementation:** The NBT library written in Java that Mojang | ||||
|   uses in Minecraft. | ||||
| - **NBT:** Named Binary Tag. A binary serialization format used by Minecraft. | ||||
| - **Tag:** A data unit in NBT. Can be a number, string, array, list or | ||||
|   compound. | ||||
|  | ||||
| ### Product Functions | ||||
| - /RF10/ Reading and writing NBT data files/streams with or without | ||||
|   compression. | ||||
| - /RF20/ Representing NBT data in memory and allowing programs to read or | ||||
|   manipulate it in all the ways that Mojang's implementation and libnbt++1 | ||||
|   provide. | ||||
| - /RF30/ A shorter syntax than in libnbt++1 and preferrably also Mojang's | ||||
|   implementation. | ||||
| - /RF35/ Typesafe operations (no possibly unwanted implicit casts), in case | ||||
|   of incompatible types exceptions should be thrown. | ||||
| - /RF40/ The need for insecure operations and manual memory management should | ||||
|   be minimized; references and `std::unique_ptr` should be preferred before | ||||
|   raw pointers. | ||||
| - /RF55/ A wrapper for tags that provides syntactic sugar is preferred | ||||
|   before raw `std::unique_ptr` values. | ||||
| - /RF50/ Move semantics are preferred before copy semantics. | ||||
| - /RF55/ Copying tags should be possible, but only in an explicit manner. | ||||
| - /RF60/ Checked conversions are preferred, unchecked conversions may be | ||||
|   possible but discouraged. | ||||
|  | ||||
| ### Product Performance | ||||
| - /RP10/ All operations on (not too large) NBT data should not be slower | ||||
|   than their counterparts in Mojang's implementation. | ||||
| - /RP20/ The library must be able to handle all possible NBT data that | ||||
|   Mojang's implementation can create and handle. | ||||
| - /RP30/ Often used operations on large Lists, Compounds and Arrays must | ||||
|   be of at most O(log n) time complexity if reasonable. Other operations | ||||
|   should be at most O(n). | ||||
|  | ||||
| ### Quality Requirements | ||||
| - Functionality: good | ||||
| - Reliability: normal | ||||
| - Usability: very good | ||||
| - Efficiency: good | ||||
| - Changeability: normal | ||||
| - Transferability: normal | ||||
							
								
								
									
										15
									
								
								depends/libnbtplusplus/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								depends/libnbtplusplus/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| # libnbt++ 2 (WIP) | ||||
|  | ||||
| libnbt++ is a free C++ library for Minecraft's file format Named Binary Tag | ||||
| (NBT). It can read and write compressed and uncompressed NBT files and | ||||
| provides a code interface for working with NBT data. | ||||
|  | ||||
| ---------- | ||||
|  | ||||
| libnbt++2 is a remake of the old libnbt++ library with the goal of making it | ||||
| more easily usable and fixing some problems. The old libnbt++ especially | ||||
| suffered from a very convoluted syntax and boilerplate code needed to work | ||||
| with NBT data. | ||||
|  | ||||
|  | ||||
| Forked from https://github.com/ljfa-ag/libnbtplusplus at commit 3b7d44aa0b84f9c208d906f4d10517e36220ee80 | ||||
							
								
								
									
										66
									
								
								depends/libnbtplusplus/include/crtp_tag.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								depends/libnbtplusplus/include/crtp_tag.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef CRTP_TAG_H_INCLUDED | ||||
| #define CRTP_TAG_H_INCLUDED | ||||
|  | ||||
| #include "tag.h" | ||||
| #include "nbt_visitor.h" | ||||
| #include "make_unique.h" | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
|     template<class Sub> | ||||
|     class NBT___EXPORT crtp_tag : public tag | ||||
|     { | ||||
|     public: | ||||
|         //Pure virtual destructor to make the class abstract | ||||
|         virtual ~crtp_tag() noexcept = 0; | ||||
|  | ||||
|         tag_type get_type() const noexcept override final { return Sub::type; }; | ||||
|  | ||||
|         std::unique_ptr<tag> clone() const& override final { return make_unique<Sub>(sub_this()); } | ||||
|         std::unique_ptr<tag> move_clone() && override final { return make_unique<Sub>(std::move(sub_this())); } | ||||
|  | ||||
|         tag& assign(tag&& rhs) override final { return sub_this() = dynamic_cast<Sub&&>(rhs); } | ||||
|  | ||||
|         void accept(nbt_visitor& visitor) override final { visitor.visit(sub_this()); } | ||||
|         void accept(const_nbt_visitor& visitor) const override final { visitor.visit(sub_this()); } | ||||
|  | ||||
|     private: | ||||
|         bool equals(const tag& rhs) const override final { return sub_this() == static_cast<const Sub&>(rhs); } | ||||
|  | ||||
|         Sub& sub_this() { return static_cast<Sub&>(*this); } | ||||
|         const Sub& sub_this() const { return static_cast<const Sub&>(*this); } | ||||
|     }; | ||||
|  | ||||
|     template<class Sub> | ||||
|     crtp_tag<Sub>::~crtp_tag() noexcept {} | ||||
|  | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // CRTP_TAG_H_INCLUDED | ||||
							
								
								
									
										113
									
								
								depends/libnbtplusplus/include/endian_str.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								depends/libnbtplusplus/include/endian_str.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,113 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef ENDIAN_STR_H_INCLUDED | ||||
| #define ENDIAN_STR_H_INCLUDED | ||||
|  | ||||
| #include <cstdint> | ||||
| #include <iosfwd> | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| /** | ||||
|  * @brief Reading and writing numbers from and to streams | ||||
|  * in binary format with different byte orders. | ||||
|  */ | ||||
| namespace endian | ||||
| { | ||||
|  | ||||
| enum endian { little, big }; | ||||
|  | ||||
| ///Reads number from stream in specified endian | ||||
| template<class T> | ||||
| NBT___EXPORT void read(std::istream& is, T& x, endian e); | ||||
|  | ||||
| ///Reads number from stream in little endian | ||||
| NBT___EXPORT void read_little(std::istream& is, uint8_t& x); | ||||
| NBT___EXPORT void read_little(std::istream& is, uint16_t& x); | ||||
| NBT___EXPORT void read_little(std::istream& is, uint32_t& x); | ||||
| NBT___EXPORT void read_little(std::istream& is, uint64_t& x); | ||||
| NBT___EXPORT void read_little(std::istream& is, int8_t& x); | ||||
| NBT___EXPORT void read_little(std::istream& is, int16_t& x); | ||||
| NBT___EXPORT void read_little(std::istream& is, int32_t& x); | ||||
| NBT___EXPORT void read_little(std::istream& is, int64_t& x); | ||||
| NBT___EXPORT void read_little(std::istream& is, float& x); | ||||
| NBT___EXPORT void read_little(std::istream& is, double& x); | ||||
|  | ||||
| ///Reads number from stream in big endian | ||||
| NBT___EXPORT void read_big(std::istream& is, uint8_t& x); | ||||
| NBT___EXPORT void read_big(std::istream& is, uint16_t& x); | ||||
| NBT___EXPORT void read_big(std::istream& is, uint32_t& x); | ||||
| NBT___EXPORT void read_big(std::istream& is, uint64_t& x); | ||||
| NBT___EXPORT void read_big(std::istream& is, int8_t& x); | ||||
| NBT___EXPORT void read_big(std::istream& is, int16_t& x); | ||||
| NBT___EXPORT void read_big(std::istream& is, int32_t& x); | ||||
| NBT___EXPORT void read_big(std::istream& is, int64_t& x); | ||||
| NBT___EXPORT void read_big(std::istream& is, float& x); | ||||
| NBT___EXPORT void read_big(std::istream& is, double& x); | ||||
|  | ||||
| ///Writes number to stream in specified endian | ||||
| template<class T> | ||||
| NBT___EXPORT void write(std::ostream& os, T x, endian e); | ||||
|  | ||||
| ///Writes number to stream in little endian | ||||
| NBT___EXPORT void write_little(std::ostream& os, uint8_t x); | ||||
| NBT___EXPORT void write_little(std::ostream& os, uint16_t x); | ||||
| NBT___EXPORT void write_little(std::ostream& os, uint32_t x); | ||||
| NBT___EXPORT void write_little(std::ostream& os, uint64_t x); | ||||
| NBT___EXPORT void write_little(std::ostream& os, int8_t x); | ||||
| NBT___EXPORT void write_little(std::ostream& os, int16_t x); | ||||
| NBT___EXPORT void write_little(std::ostream& os, int32_t x); | ||||
| NBT___EXPORT void write_little(std::ostream& os, int64_t x); | ||||
| NBT___EXPORT void write_little(std::ostream& os, float x); | ||||
| NBT___EXPORT void write_little(std::ostream& os, double x); | ||||
|  | ||||
| ///Writes number to stream in big endian | ||||
| NBT___EXPORT void write_big(std::ostream& os, uint8_t x); | ||||
| NBT___EXPORT void write_big(std::ostream& os, uint16_t x); | ||||
| NBT___EXPORT void write_big(std::ostream& os, uint32_t x); | ||||
| NBT___EXPORT void write_big(std::ostream& os, uint64_t x); | ||||
| NBT___EXPORT void write_big(std::ostream& os, int8_t x); | ||||
| NBT___EXPORT void write_big(std::ostream& os, int16_t x); | ||||
| NBT___EXPORT void write_big(std::ostream& os, int32_t x); | ||||
| NBT___EXPORT void write_big(std::ostream& os, int64_t x); | ||||
| NBT___EXPORT void write_big(std::ostream& os, float x); | ||||
| NBT___EXPORT void write_big(std::ostream& os, double x); | ||||
|  | ||||
| template<class T> | ||||
| NBT___EXPORT void read(std::istream& is, T& x, endian e) | ||||
| { | ||||
|     if(e == little) | ||||
|         read_little(is, x); | ||||
|     else | ||||
|         read_big(is, x); | ||||
| } | ||||
|  | ||||
| template<class T> | ||||
| NBT___EXPORT void write(std::ostream& os, T x, endian e) | ||||
| { | ||||
|     if(e == little) | ||||
|         write_little(os, x); | ||||
|     else | ||||
|         write_big(os, x); | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // ENDIAN_STR_H_INCLUDED | ||||
							
								
								
									
										138
									
								
								depends/libnbtplusplus/include/io/stream_reader.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								depends/libnbtplusplus/include/io/stream_reader.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,138 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef STREAM_READER_H_INCLUDED | ||||
| #define STREAM_READER_H_INCLUDED | ||||
|  | ||||
| #include "endian_str.h" | ||||
| #include "tag.h" | ||||
| #include "tag_compound.h" | ||||
| #include <iosfwd> | ||||
| #include <memory> | ||||
| #include <stdexcept> | ||||
| #include <utility> | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
| namespace io | ||||
| { | ||||
|  | ||||
| ///Exception that gets thrown when reading is not successful | ||||
| class NBT___EXPORT input_error : public std::runtime_error | ||||
| { | ||||
|     using std::runtime_error::runtime_error; | ||||
| }; | ||||
|  | ||||
| /** | ||||
| * @brief Reads a named tag from the stream, making sure that it is a compound | ||||
| * @param is the stream to read from | ||||
| * @param e the byte order of the source data. The Java edition | ||||
| * of Minecraft uses Big Endian, the Pocket edition uses Little Endian | ||||
| * @throw input_error on failure, or if the tag in the stream is not a compound | ||||
| */ | ||||
| NBT___EXPORT std::pair<std::string, std::unique_ptr<tag_compound>> read_compound(std::istream& is, endian::endian e = endian::big); | ||||
|  | ||||
| /** | ||||
| * @brief Reads a named tag from the stream | ||||
| * @param is the stream to read from | ||||
| * @param e the byte order of the source data. The Java edition | ||||
| * of Minecraft uses Big Endian, the Pocket edition uses Little Endian | ||||
| * @throw input_error on failure | ||||
| */ | ||||
| NBT___EXPORT std::pair<std::string, std::unique_ptr<tag>> read_tag(std::istream& is, endian::endian e = endian::big); | ||||
|  | ||||
| /** | ||||
|  * @brief Helper class for reading NBT tags from input streams | ||||
|  * | ||||
|  * Can be reused to read multiple tags | ||||
|  */ | ||||
| class NBT___EXPORT stream_reader | ||||
| { | ||||
| public: | ||||
|     /** | ||||
|      * @param is the stream to read from | ||||
|      * @param e the byte order of the source data. The Java edition | ||||
|      * of Minecraft uses Big Endian, the Pocket edition uses Little Endian | ||||
|      */ | ||||
|     explicit stream_reader(std::istream& is, endian::endian e = endian::big) noexcept; | ||||
|  | ||||
|     ///Returns the stream | ||||
|     std::istream& get_istr() const; | ||||
|     ///Returns the byte order | ||||
|     endian::endian get_endian() const; | ||||
|  | ||||
|     /** | ||||
|      * @brief Reads a named tag from the stream, making sure that it is a compound | ||||
|      * @throw input_error on failure, or if the tag in the stream is not a compound | ||||
|      */ | ||||
|     std::pair<std::string, std::unique_ptr<tag_compound>> read_compound(); | ||||
|  | ||||
|     /** | ||||
|      * @brief Reads a named tag from the stream | ||||
|      * @throw input_error on failure | ||||
|      */ | ||||
|     std::pair<std::string, std::unique_ptr<tag>> read_tag(); | ||||
|  | ||||
|     /** | ||||
|      * @brief Reads a tag of the given type without name from the stream | ||||
|      * @throw input_error on failure | ||||
|      */ | ||||
|     std::unique_ptr<tag> read_payload(tag_type type); | ||||
|  | ||||
|     /** | ||||
|      * @brief Reads a tag type from the stream | ||||
|      * @param allow_end whether to consider tag_type::End valid | ||||
|      * @throw input_error on failure | ||||
|      */ | ||||
|     tag_type read_type(bool allow_end = false); | ||||
|  | ||||
|     /** | ||||
|      * @brief Reads a binary number from the stream | ||||
|      * | ||||
|      * On failure, will set the failbit on the stream. | ||||
|      */ | ||||
|     template<class T> | ||||
|     void read_num(T& x); | ||||
|  | ||||
|     /** | ||||
|      * @brief Reads an NBT string from the stream | ||||
|      * | ||||
|      * An NBT string consists of two bytes indicating the length, followed by | ||||
|      * the characters encoded in modified UTF-8. | ||||
|      * @throw input_error on failure | ||||
|      */ | ||||
|     std::string read_string(); | ||||
|  | ||||
| private: | ||||
|     std::istream& is; | ||||
|     const endian::endian endian; | ||||
| }; | ||||
|  | ||||
| template<class T> | ||||
| void stream_reader::read_num(T& x) | ||||
| { | ||||
|     endian::read(is, x, endian); | ||||
| } | ||||
|  | ||||
| } | ||||
| } | ||||
|  | ||||
| #endif // STREAM_READER_H_INCLUDED | ||||
							
								
								
									
										122
									
								
								depends/libnbtplusplus/include/io/stream_writer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								depends/libnbtplusplus/include/io/stream_writer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef STREAM_WRITER_H_INCLUDED | ||||
| #define STREAM_WRITER_H_INCLUDED | ||||
|  | ||||
| #include "tag.h" | ||||
| #include "endian_str.h" | ||||
| #include <iosfwd> | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
| namespace io | ||||
| { | ||||
|  | ||||
| /* Not sure if that is even needed | ||||
| ///Exception that gets thrown when writing is not successful | ||||
| class output_error : public std::runtime_error | ||||
| { | ||||
|     using std::runtime_error::runtime_error; | ||||
| };*/ | ||||
|  | ||||
| /** | ||||
| * @brief Writes a named tag into the stream, including the tag type | ||||
| * @param key the name of the tag | ||||
| * @param t the tag | ||||
| * @param os the stream to write to | ||||
| * @param e the byte order of the written data. The Java edition | ||||
| * of Minecraft uses Big Endian, the Pocket edition uses Little Endian | ||||
| */ | ||||
| NBT___EXPORT void write_tag(const std::string& key, const tag& t, std::ostream& os, endian::endian e = endian::big); | ||||
|  | ||||
| /** | ||||
|  * @brief Helper class for writing NBT tags to output streams | ||||
|  * | ||||
|  * Can be reused to write multiple tags | ||||
|  */ | ||||
| class NBT___EXPORT stream_writer | ||||
| { | ||||
| public: | ||||
|     ///Maximum length of an NBT string (16 bit unsigned) | ||||
|     static constexpr size_t max_string_len = UINT16_MAX; | ||||
|     ///Maximum length of an NBT list or array (32 bit signed) | ||||
|     static constexpr uint32_t max_array_len = INT32_MAX; | ||||
|  | ||||
|     /** | ||||
|      * @param os the stream to write to | ||||
|      * @param e the byte order of the written data. The Java edition | ||||
|      * of Minecraft uses Big Endian, the Pocket edition uses Little Endian | ||||
|      */ | ||||
|     explicit stream_writer(std::ostream& os, endian::endian e = endian::big) noexcept: | ||||
|         os(os), endian(e) | ||||
|     {} | ||||
|  | ||||
|     ///Returns the stream | ||||
|     std::ostream& get_ostr() const { return os; } | ||||
|     ///Returns the byte order | ||||
|     endian::endian get_endian() const { return endian; } | ||||
|  | ||||
|     /** | ||||
|      * @brief Writes a named tag into the stream, including the tag type | ||||
|      */ | ||||
|     void write_tag(const std::string& key, const tag& t); | ||||
|  | ||||
|     /** | ||||
|      * @brief Writes the given tag's payload into the stream | ||||
|      */ | ||||
|     void write_payload(const tag& t) { t.write_payload(*this); } | ||||
|  | ||||
|     /** | ||||
|      * @brief Writes a tag type to the stream | ||||
|      */ | ||||
|     void write_type(tag_type tt) { write_num(static_cast<int8_t>(tt)); } | ||||
|  | ||||
|     /** | ||||
|      * @brief Writes a binary number to the stream | ||||
|      */ | ||||
|     template<class T> | ||||
|     void write_num(T x); | ||||
|  | ||||
|     /** | ||||
|      * @brief Writes an NBT string to the stream | ||||
|      * | ||||
|      * An NBT string consists of two bytes indicating the length, followed by | ||||
|      * the characters encoded in modified UTF-8. | ||||
|      * @throw std::length_error if the string is too long for NBT | ||||
|      */ | ||||
|     void write_string(const std::string& str); | ||||
|  | ||||
| private: | ||||
|     std::ostream& os; | ||||
|     const endian::endian endian; | ||||
| }; | ||||
|  | ||||
| template<class T> | ||||
| void stream_writer::write_num(T x) | ||||
| { | ||||
|     endian::write(os, x, endian); | ||||
| } | ||||
|  | ||||
| } | ||||
| } | ||||
|  | ||||
| #endif // STREAM_WRITER_H_INCLUDED | ||||
							
								
								
									
										37
									
								
								depends/libnbtplusplus/include/make_unique.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								depends/libnbtplusplus/include/make_unique.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef MAKE_UNIQUE_H_INCLUDED | ||||
| #define MAKE_UNIQUE_H_INCLUDED | ||||
|  | ||||
| #include <memory> | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| ///Creates a new object of type T and returns a std::unique_ptr to it | ||||
| template<class T, class... Args> | ||||
| std::unique_ptr<T> make_unique(Args&&... args) | ||||
| { | ||||
|     return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // MAKE_UNIQUE_H_INCLUDED | ||||
							
								
								
									
										29
									
								
								depends/libnbtplusplus/include/nbt_tags.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								depends/libnbtplusplus/include/nbt_tags.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef NBT_TAGS_H_INCLUDED | ||||
| #define NBT_TAGS_H_INCLUDED | ||||
|  | ||||
| #include "tag_primitive.h" | ||||
| #include "tag_string.h" | ||||
| #include "tag_array.h" | ||||
| #include "tag_list.h" | ||||
| #include "tag_compound.h" | ||||
|  | ||||
| #endif // NBT_TAGS_H_INCLUDED | ||||
							
								
								
									
										82
									
								
								depends/libnbtplusplus/include/nbt_visitor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								depends/libnbtplusplus/include/nbt_visitor.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef NBT_VISITOR_H_INCLUDED | ||||
| #define NBT_VISITOR_H_INCLUDED | ||||
|  | ||||
| #include "tagfwd.h" | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| /** | ||||
|  * @brief Base class for visitors of tags | ||||
|  * | ||||
|  * Implementing the Visitor pattern | ||||
|  */ | ||||
| class NBT___EXPORT nbt_visitor | ||||
| { | ||||
| public: | ||||
|     virtual ~nbt_visitor() noexcept = 0; //Abstract class | ||||
|  | ||||
|     virtual void visit(tag_byte&) {} | ||||
|     virtual void visit(tag_short&) {} | ||||
|     virtual void visit(tag_int&) {} | ||||
|     virtual void visit(tag_long&) {} | ||||
|     virtual void visit(tag_float&) {} | ||||
|     virtual void visit(tag_double&) {} | ||||
|     virtual void visit(tag_byte_array&) {} | ||||
|     virtual void visit(tag_string&) {} | ||||
|     virtual void visit(tag_list&) {} | ||||
|     virtual void visit(tag_compound&) {} | ||||
|     virtual void visit(tag_int_array&) {} | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * @brief Base class for visitors of constant tags | ||||
|  * | ||||
|  * Implementing the Visitor pattern | ||||
|  */ | ||||
| class NBT___EXPORT const_nbt_visitor | ||||
| { | ||||
| public: | ||||
|     virtual ~const_nbt_visitor() noexcept = 0; //Abstract class | ||||
|  | ||||
|     virtual void visit(const tag_byte&) {} | ||||
|     virtual void visit(const tag_short&) {} | ||||
|     virtual void visit(const tag_int&) {} | ||||
|     virtual void visit(const tag_long&) {} | ||||
|     virtual void visit(const tag_float&) {} | ||||
|     virtual void visit(const tag_double&) {} | ||||
|     virtual void visit(const tag_byte_array&) {} | ||||
|     virtual void visit(const tag_string&) {} | ||||
|     virtual void visit(const tag_list&) {} | ||||
|     virtual void visit(const tag_compound&) {} | ||||
|     virtual void visit(const tag_int_array&) {} | ||||
| }; | ||||
|  | ||||
| inline nbt_visitor::~nbt_visitor() noexcept {} | ||||
|  | ||||
| inline const_nbt_visitor::~const_nbt_visitor() noexcept {} | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // NBT_VISITOR_H_INCLUDED | ||||
							
								
								
									
										46
									
								
								depends/libnbtplusplus/include/primitive_detail.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								depends/libnbtplusplus/include/primitive_detail.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef PRIMITIVE_DETAIL_H_INCLUDED | ||||
| #define PRIMITIVE_DETAIL_H_INCLUDED | ||||
|  | ||||
| #include <type_traits> | ||||
|  | ||||
| ///@cond | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|     ///Meta-struct that holds the tag_type value for a specific primitive type | ||||
|     template<class T> struct get_primitive_type | ||||
|     { static_assert(sizeof(T) != sizeof(T), "Invalid type paramter for tag_primitive, can only use types that NBT uses"); }; | ||||
|  | ||||
|     template<> struct get_primitive_type<int8_t>  : public std::integral_constant<tag_type, tag_type::Byte> {}; | ||||
|     template<> struct get_primitive_type<int16_t> : public std::integral_constant<tag_type, tag_type::Short> {}; | ||||
|     template<> struct get_primitive_type<int32_t> : public std::integral_constant<tag_type, tag_type::Int> {}; | ||||
|     template<> struct get_primitive_type<int64_t> : public std::integral_constant<tag_type, tag_type::Long> {}; | ||||
|     template<> struct get_primitive_type<float>   : public std::integral_constant<tag_type, tag_type::Float> {}; | ||||
|     template<> struct get_primitive_type<double>  : public std::integral_constant<tag_type, tag_type::Double> {}; | ||||
| } | ||||
|  | ||||
| } | ||||
| ///@endcond | ||||
|  | ||||
| #endif // PRIMITIVE_DETAIL_H_INCLUDED | ||||
							
								
								
									
										159
									
								
								depends/libnbtplusplus/include/tag.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								depends/libnbtplusplus/include/tag.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef TAG_H_INCLUDED | ||||
| #define TAG_H_INCLUDED | ||||
|  | ||||
| #include <cstdint> | ||||
| #include <iosfwd> | ||||
| #include <memory> | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| ///Tag type values used in the binary format | ||||
| enum class tag_type : int8_t | ||||
| { | ||||
|     End = 0, | ||||
|     Byte = 1, | ||||
|     Short = 2, | ||||
|     Int = 3, | ||||
|     Long = 4, | ||||
|     Float = 5, | ||||
|     Double = 6, | ||||
|     Byte_Array = 7, | ||||
|     String = 8, | ||||
|     List = 9, | ||||
|     Compound = 10, | ||||
|     Int_Array = 11, | ||||
|     Null = -1   ///< Used to denote empty @ref value s | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * @brief Returns whether the given number falls within the range of valid tag types | ||||
|  * @param allow_end whether to consider tag_type::End (0) valid | ||||
|  */ | ||||
| NBT___EXPORT bool is_valid_type(int type, bool allow_end = false); | ||||
|  | ||||
| //Forward declarations | ||||
| class nbt_visitor; | ||||
| class const_nbt_visitor; | ||||
| namespace io | ||||
| { | ||||
|     class stream_reader; | ||||
|     class stream_writer; | ||||
| } | ||||
|  | ||||
| ///Base class for all NBT tag classes | ||||
| class NBT___EXPORT tag | ||||
| { | ||||
| public: | ||||
|     //Virtual destructor | ||||
|     virtual ~tag() noexcept {} | ||||
|  | ||||
|     ///Returns the type of the tag | ||||
|     virtual tag_type get_type() const noexcept = 0; | ||||
|  | ||||
|     //Polymorphic clone methods | ||||
|     virtual std::unique_ptr<tag> clone() const& = 0; | ||||
|     virtual std::unique_ptr<tag> move_clone() && = 0; | ||||
|     std::unique_ptr<tag> clone() &&; | ||||
|  | ||||
|     /** | ||||
|      * @brief Returns a reference to the tag as an instance of T | ||||
|      * @throw std::bad_cast if the tag is not of type T | ||||
|      */ | ||||
|     template<class T> | ||||
|     T& as(); | ||||
|     template<class T> | ||||
|     const T& as() const; | ||||
|  | ||||
|     /** | ||||
|      * @brief Move-assigns the given tag if the class is the same | ||||
|      * @throw std::bad_cast if @c rhs is not the same type as @c *this | ||||
|      */ | ||||
|     virtual tag& assign(tag&& rhs) = 0; | ||||
|  | ||||
|     /** | ||||
|      * @brief Calls the appropriate overload of @c visit() on the visitor with | ||||
|      * @c *this as argument | ||||
|      * | ||||
|      * Implementing the Visitor pattern | ||||
|      */ | ||||
|     virtual void accept(nbt_visitor& visitor) = 0; | ||||
|     virtual void accept(const_nbt_visitor& visitor) const = 0; | ||||
|  | ||||
|     /** | ||||
|      * @brief Reads the tag's payload from the stream | ||||
|      * @throw io::stream_reader::input_error on failure | ||||
|      */ | ||||
|     virtual void read_payload(io::stream_reader& reader) = 0; | ||||
|  | ||||
|     /** | ||||
|      * @brief Writes the tag's payload into the stream | ||||
|      */ | ||||
|     virtual void write_payload(io::stream_writer& writer) const = 0; | ||||
|  | ||||
|     /** | ||||
|      * @brief Default-constructs a new tag of the given type | ||||
|      * @throw std::invalid_argument if the type is not valid (e.g. End or Null) | ||||
|      */ | ||||
|     static std::unique_ptr<tag> create(tag_type type); | ||||
|  | ||||
|     friend bool operator==(const tag& lhs, const tag& rhs); | ||||
|     friend bool operator!=(const tag& lhs, const tag& rhs); | ||||
|  | ||||
| private: | ||||
|     /** | ||||
|      * @brief Checks for equality to a tag of the same type | ||||
|      * @param rhs an instance of the same class as @c *this | ||||
|      */ | ||||
|     virtual bool equals(const tag& rhs) const = 0; | ||||
| }; | ||||
|  | ||||
| ///Output operator for tag types | ||||
| NBT___EXPORT std::ostream& operator<<(std::ostream& os, tag_type tt); | ||||
|  | ||||
| /** | ||||
|  * @brief Output operator for tags | ||||
|  * | ||||
|  * Uses @ref text::json_formatter | ||||
|  * @relates tag | ||||
|  */ | ||||
| NBT___EXPORT std::ostream& operator<<(std::ostream& os, const tag& t); | ||||
|  | ||||
| template<class T> | ||||
| T& tag::as() | ||||
| { | ||||
|     static_assert(std::is_base_of<tag, T>::value, "T must be a subclass of tag"); | ||||
|     return dynamic_cast<T&>(*this); | ||||
| } | ||||
|  | ||||
| template<class T> | ||||
| const T& tag::as() const | ||||
| { | ||||
|     static_assert(std::is_base_of<tag, T>::value, "T must be a subclass of tag"); | ||||
|     return dynamic_cast<const T&>(*this); | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // TAG_H_INCLUDED | ||||
							
								
								
									
										131
									
								
								depends/libnbtplusplus/include/tag_array.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								depends/libnbtplusplus/include/tag_array.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef TAG_ARRAY_H_INCLUDED | ||||
| #define TAG_ARRAY_H_INCLUDED | ||||
|  | ||||
| #include "crtp_tag.h" | ||||
| #include <type_traits> | ||||
| #include <vector> | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| ///@cond | ||||
| namespace detail | ||||
| { | ||||
|     ///Meta-struct that holds the tag_type value for a specific array type | ||||
|     template<class T> struct get_array_type | ||||
|     { static_assert(sizeof(T) != sizeof(T), "Invalid type paramter for tag_primitive, can only use byte or int"); }; | ||||
|  | ||||
|     template<> struct get_array_type<int8_t>  : public std::integral_constant<tag_type, tag_type::Byte_Array> {}; | ||||
|     template<> struct get_array_type<int32_t> : public std::integral_constant<tag_type, tag_type::Int_Array> {}; | ||||
| } | ||||
| ///@cond | ||||
|  | ||||
| /** | ||||
|  * @brief Tag that contains an array of byte or int values | ||||
|  * | ||||
|  * Common class for tag_byte_array and tag_int_array. | ||||
|  */ | ||||
| template<class T> | ||||
| class NBT___EXPORT tag_array final : public detail::crtp_tag<tag_array<T>> | ||||
| { | ||||
| public: | ||||
|     //Iterator types | ||||
|     typedef typename std::vector<T>::iterator iterator; | ||||
|     typedef typename std::vector<T>::const_iterator const_iterator; | ||||
|  | ||||
|     ///The type of the contained values | ||||
|     typedef T value_type; | ||||
|  | ||||
|     ///The type of the tag | ||||
|     static constexpr tag_type type = detail::get_array_type<T>::value; | ||||
|  | ||||
|     ///Constructs an empty array | ||||
|     tag_array() {} | ||||
|  | ||||
|     ///Constructs an array with the given values | ||||
|     tag_array(std::initializer_list<T> init): data(init) {} | ||||
|     tag_array(std::vector<T>&& vec) noexcept: data(std::move(vec)) {} | ||||
|  | ||||
|     ///Returns a reference to the vector that contains the values | ||||
|     std::vector<T>& get() { return data; } | ||||
|     const std::vector<T>& get() const { return data; } | ||||
|  | ||||
|     /** | ||||
|      * @brief Accesses a value by index with bounds checking | ||||
|      * @throw std::out_of_range if the index is out of range | ||||
|      */ | ||||
|     T& at(size_t i); | ||||
|     T at(size_t i) const; | ||||
|  | ||||
|     /** | ||||
|      * @brief Accesses a value by index | ||||
|      * | ||||
|      * No bounds checking is performed. | ||||
|      */ | ||||
|     T& operator[](size_t i) { return data[i]; } | ||||
|     T operator[](size_t i) const { return data[i]; } | ||||
|  | ||||
|     ///Appends a value at the end of the array | ||||
|     void push_back(T val) { data.push_back(val); } | ||||
|  | ||||
|     ///Removes the last element from the array | ||||
|     void pop_back() { data.pop_back(); } | ||||
|  | ||||
|     ///Returns the number of values in the array | ||||
|     size_t size() const { return data.size(); } | ||||
|  | ||||
|     ///Erases all values from the array. | ||||
|     void clear() { data.clear(); } | ||||
|  | ||||
|     //Iterators | ||||
|     iterator begin() { return data.begin(); } | ||||
|     iterator end()   { return data.end(); } | ||||
|     const_iterator begin() const  { return data.begin(); } | ||||
|     const_iterator end() const    { return data.end(); } | ||||
|     const_iterator cbegin() const { return data.cbegin(); } | ||||
|     const_iterator cend() const   { return data.cend(); } | ||||
|  | ||||
|     void read_payload(io::stream_reader& reader) override; | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      * @throw std::length_error if the array is too large for NBT | ||||
|      */ | ||||
|     void write_payload(io::stream_writer& writer) const override; | ||||
|  | ||||
| private: | ||||
|     std::vector<T> data; | ||||
| }; | ||||
|  | ||||
| template<class T> bool operator==(const tag_array<T>& lhs, const tag_array<T>& rhs) | ||||
| { return lhs.get() == rhs.get(); } | ||||
| template<class T> bool operator!=(const tag_array<T>& lhs, const tag_array<T>& rhs) | ||||
| { return !(lhs == rhs); } | ||||
|  | ||||
| //Typedefs that should be used instead of the template tag_array. | ||||
| typedef tag_array<int8_t> tag_byte_array; | ||||
| typedef tag_array<int32_t> tag_int_array; | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // TAG_ARRAY_H_INCLUDED | ||||
							
								
								
									
										144
									
								
								depends/libnbtplusplus/include/tag_compound.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								depends/libnbtplusplus/include/tag_compound.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef TAG_COMPOUND_H_INCLUDED | ||||
| #define TAG_COMPOUND_H_INCLUDED | ||||
|  | ||||
| #include "crtp_tag.h" | ||||
| #include "value_initializer.h" | ||||
| #include <map> | ||||
| #include <string> | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| ///Tag that contains multiple unordered named tags of arbitrary types | ||||
| class NBT___EXPORT tag_compound final : public detail::crtp_tag<tag_compound> | ||||
| { | ||||
|     typedef std::map<std::string, value> map_t_; | ||||
|  | ||||
| public: | ||||
|     //Iterator types | ||||
|     typedef map_t_::iterator iterator; | ||||
|     typedef map_t_::const_iterator const_iterator; | ||||
|  | ||||
|     ///The type of the tag | ||||
|     static constexpr tag_type type = tag_type::Compound; | ||||
|  | ||||
|     ///Constructs an empty compound | ||||
|     tag_compound() {} | ||||
|  | ||||
|     ///Constructs a compound with the given key-value pairs | ||||
|     tag_compound(std::initializer_list<std::pair<std::string, value_initializer>> init); | ||||
|  | ||||
|     /** | ||||
|      * @brief Accesses a tag by key with bounds checking | ||||
|      * | ||||
|      * Returns a value to the tag with the specified key, or throws an | ||||
|      * exception if it does not exist. | ||||
|      * @throw std::out_of_range if given key does not exist | ||||
|      */ | ||||
|     value& at(const std::string& key); | ||||
|     const value& at(const std::string& key) const; | ||||
|  | ||||
|     /** | ||||
|      * @brief Accesses a tag by key | ||||
|      * | ||||
|      * Returns a value to the tag with the specified key. If it does not exist, | ||||
|      * creates a new uninitialized entry under the key. | ||||
|      */ | ||||
|     value& operator[](const std::string& key) { return tags[key]; } | ||||
|  | ||||
|     /** | ||||
|      * @brief Inserts or assigns a tag | ||||
|      * | ||||
|      * If the given key already exists, assigns the tag to it. | ||||
|      * Otherwise, it is inserted under the given key. | ||||
|      * @return a pair of the iterator to the value and a bool indicating | ||||
|      * whether the key did not exist | ||||
|      */ | ||||
|     std::pair<iterator, bool> put(const std::string& key, value_initializer&& val); | ||||
|  | ||||
|     /** | ||||
|      * @brief Inserts a tag if the key does not exist | ||||
|      * @return a pair of the iterator to the value with the key and a bool | ||||
|      * indicating whether the value was actually inserted | ||||
|      */ | ||||
|     std::pair<iterator, bool> insert(const std::string& key, value_initializer&& val); | ||||
|  | ||||
|     /** | ||||
|      * @brief Constructs and assigns or inserts a tag into the compound | ||||
|      * | ||||
|      * Constructs a new tag of type @c T with the given args and inserts | ||||
|      * or assigns it to the given key. | ||||
|      * @note Unlike std::map::emplace, this will overwrite existing values | ||||
|      * @return a pair of the iterator to the value and a bool indicating | ||||
|      * whether the key did not exist | ||||
|      */ | ||||
|     template<class T, class... Args> | ||||
|     std::pair<iterator, bool> emplace(const std::string& key, Args&&... args); | ||||
|  | ||||
|     /** | ||||
|      * @brief Erases a tag from the compound | ||||
|      * @return true if a tag was erased | ||||
|      */ | ||||
|     bool erase(const std::string& key); | ||||
|  | ||||
|     ///Returns true if the given key exists in the compound | ||||
|     bool has_key(const std::string& key) const; | ||||
|     ///Returns true if the given key exists and the tag has the given type | ||||
|     bool has_key(const std::string& key, tag_type type) const; | ||||
|  | ||||
|     ///Returns the number of tags in the compound | ||||
|     size_t size() const { return tags.size(); } | ||||
|  | ||||
|     ///Erases all tags from the compound | ||||
|     void clear() { tags.clear(); } | ||||
|  | ||||
|     //Iterators | ||||
|     iterator begin() { return tags.begin(); } | ||||
|     iterator end()   { return tags.end(); } | ||||
|     const_iterator begin() const  { return tags.begin(); } | ||||
|     const_iterator end() const    { return tags.end(); } | ||||
|     const_iterator cbegin() const { return tags.cbegin(); } | ||||
|     const_iterator cend() const   { return tags.cend(); } | ||||
|  | ||||
|     void read_payload(io::stream_reader& reader) override; | ||||
|     void write_payload(io::stream_writer& writer) const override; | ||||
|  | ||||
|     friend bool operator==(const tag_compound& lhs, const tag_compound& rhs) | ||||
|     { return lhs.tags == rhs.tags; } | ||||
|     friend bool operator!=(const tag_compound& lhs, const tag_compound& rhs) | ||||
|     { return !(lhs == rhs); } | ||||
|  | ||||
| private: | ||||
|     map_t_ tags; | ||||
| }; | ||||
|  | ||||
| template<class T, class... Args> | ||||
| std::pair<tag_compound::iterator, bool> tag_compound::emplace(const std::string& key, Args&&... args) | ||||
| { | ||||
|     return put(key, value(make_unique<T>(std::forward<Args>(args)...))); | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // TAG_COMPOUND_H_INCLUDED | ||||
							
								
								
									
										224
									
								
								depends/libnbtplusplus/include/tag_list.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								depends/libnbtplusplus/include/tag_list.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,224 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef TAG_LIST_H_INCLUDED | ||||
| #define TAG_LIST_H_INCLUDED | ||||
|  | ||||
| #include "crtp_tag.h" | ||||
| #include "tagfwd.h" | ||||
| #include "value_initializer.h" | ||||
| #include <stdexcept> | ||||
| #include <vector> | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| /** | ||||
|  * @brief Tag that contains multiple unnamed tags of the same type | ||||
|  * | ||||
|  * All the tags contained in the list have the same type, which can be queried | ||||
|  * with el_type(). The types of the values contained in the list should not | ||||
|  * be changed to mismatch the element type. | ||||
|  * | ||||
|  * If the list is empty, the type can be undetermined, in which case el_type() | ||||
|  * will return tag_type::Null. The type will then be set when the first tag | ||||
|  * is added to the list. | ||||
|  */ | ||||
| class NBT___EXPORT tag_list final : public detail::crtp_tag<tag_list> | ||||
| { | ||||
| public: | ||||
|     //Iterator types | ||||
|     typedef std::vector<value>::iterator iterator; | ||||
|     typedef std::vector<value>::const_iterator const_iterator; | ||||
|  | ||||
|     ///The type of the tag | ||||
|     static constexpr tag_type type = tag_type::List; | ||||
|  | ||||
|     /** | ||||
|      * @brief Constructs a list of type T with the given values | ||||
|      * | ||||
|      * Example: @code tag_list::of<tag_byte>({3, 4, 5}) @endcode | ||||
|      * @param init list of values from which the elements are constructed | ||||
|      */ | ||||
|     template<class T> | ||||
|     static tag_list of(std::initializer_list<T> init); | ||||
|  | ||||
|     /** | ||||
|      * @brief Constructs an empty list | ||||
|      * | ||||
|      * The content type is determined when the first tag is added. | ||||
|      */ | ||||
|     tag_list(): tag_list(tag_type::Null) {} | ||||
|  | ||||
|     ///Constructs an empty list with the given content type | ||||
|     explicit tag_list(tag_type type): el_type_(type) {} | ||||
|  | ||||
|     ///Constructs a list with the given contents | ||||
|     tag_list(std::initializer_list<int8_t> init); | ||||
|     tag_list(std::initializer_list<int16_t> init); | ||||
|     tag_list(std::initializer_list<int32_t> init); | ||||
|     tag_list(std::initializer_list<int64_t> init); | ||||
|     tag_list(std::initializer_list<float> init); | ||||
|     tag_list(std::initializer_list<double> init); | ||||
|     tag_list(std::initializer_list<std::string> init); | ||||
|     tag_list(std::initializer_list<tag_byte_array> init); | ||||
|     tag_list(std::initializer_list<tag_list> init); | ||||
|     tag_list(std::initializer_list<tag_compound> init); | ||||
|     tag_list(std::initializer_list<tag_int_array> init); | ||||
|  | ||||
|     /** | ||||
|      * @brief Constructs a list with the given contents | ||||
|      * @throw std::invalid_argument if the tags are not all of the same type | ||||
|      */ | ||||
|     tag_list(std::initializer_list<value> init); | ||||
|  | ||||
|     /** | ||||
|      * @brief Accesses a tag by index with bounds checking | ||||
|      * | ||||
|      * Returns a value to the tag at the specified index, or throws an | ||||
|      * exception if it is out of range. | ||||
|      * @throw std::out_of_range if the index is out of range | ||||
|      */ | ||||
|     value& at(size_t i); | ||||
|     const value& at(size_t i) const; | ||||
|  | ||||
|     /** | ||||
|      * @brief Accesses a tag by index | ||||
|      * | ||||
|      * Returns a value to the tag at the specified index. No bounds checking | ||||
|      * is performed. | ||||
|      */ | ||||
|     value& operator[](size_t i) { return tags[i]; } | ||||
|     const value& operator[](size_t i) const { return tags[i]; } | ||||
|  | ||||
|     /** | ||||
|      * @brief Assigns a value at the given index | ||||
|      * @throw std::invalid_argument if the type of the value does not match the list's | ||||
|      * content type | ||||
|      * @throw std::out_of_range if the index is out of range | ||||
|      */ | ||||
|     void set(size_t i, value&& val); | ||||
|  | ||||
|     /** | ||||
|      * @brief Appends the tag to the end of the list | ||||
|      * @throw std::invalid_argument if the type of the tag does not match the list's | ||||
|      * content type | ||||
|      */ | ||||
|     void push_back(value_initializer&& val); | ||||
|  | ||||
|     /** | ||||
|      * @brief Constructs and appends a tag to the end of the list | ||||
|      * @throw std::invalid_argument if the type of the tag does not match the list's | ||||
|      * content type | ||||
|      */ | ||||
|     template<class T, class... Args> | ||||
|     void emplace_back(Args&&... args); | ||||
|  | ||||
|     ///Removes the last element of the list | ||||
|     void pop_back() { tags.pop_back(); } | ||||
|  | ||||
|     ///Returns the content type of the list, or tag_type::Null if undetermined | ||||
|     tag_type el_type() const { return el_type_; } | ||||
|  | ||||
|     ///Returns the number of tags in the list | ||||
|     size_t size() const { return tags.size(); } | ||||
|  | ||||
|     ///Erases all tags from the list. Preserves the content type. | ||||
|     void clear() { tags.clear(); } | ||||
|  | ||||
|     /** | ||||
|      * @brief Erases all tags from the list and changes the content type. | ||||
|      * @param type the new content type. Can be tag_type::Null to leave it undetermined. | ||||
|      */ | ||||
|     void reset(tag_type type = tag_type::Null); | ||||
|  | ||||
|     //Iterators | ||||
|     iterator begin() { return tags.begin(); } | ||||
|     iterator end()   { return tags.end(); } | ||||
|     const_iterator begin() const  { return tags.begin(); } | ||||
|     const_iterator end() const    { return tags.end(); } | ||||
|     const_iterator cbegin() const { return tags.cbegin(); } | ||||
|     const_iterator cend() const   { return tags.cend(); } | ||||
|  | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      * In case of a list of tag_end, the content type will be undetermined. | ||||
|      */ | ||||
|     void read_payload(io::stream_reader& reader) override; | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      * In case of a list of undetermined content type, the written type will be tag_end. | ||||
|      * @throw std::length_error if the list is too long for NBT | ||||
|      */ | ||||
|     void write_payload(io::stream_writer& writer) const override; | ||||
|  | ||||
|     /** | ||||
|      * @brief Equality comparison for lists | ||||
|      * | ||||
|      * Lists are considered equal if their content types and the contained tags | ||||
|      * are equal. | ||||
|      */ | ||||
|     NBT___EXPORT friend bool operator==(const tag_list& lhs, const tag_list& rhs); | ||||
|     NBT___EXPORT friend bool operator!=(const tag_list& lhs, const tag_list& rhs); | ||||
|  | ||||
| private: | ||||
|     std::vector<value> tags; | ||||
|     tag_type el_type_; | ||||
|  | ||||
|     /** | ||||
|      * Internally used initialization function that initializes the list with | ||||
|      * tags of type T, with the constructor arguments of each T given by il. | ||||
|      * @param il list of values that are, one by one, given to a constructor of T | ||||
|      */ | ||||
|     template<class T, class Arg> | ||||
|     void init(std::initializer_list<Arg> il); | ||||
| }; | ||||
|  | ||||
| template<class T> | ||||
| tag_list tag_list::of(std::initializer_list<T> il) | ||||
| { | ||||
|     tag_list result; | ||||
|     result.init<T, T>(il); | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| template<class T, class... Args> | ||||
| void tag_list::emplace_back(Args&&... args) | ||||
| { | ||||
|     if(el_type_ == tag_type::Null) //set content type if undetermined | ||||
|         el_type_ = T::type; | ||||
|     else if(el_type_ != T::type) | ||||
|         throw std::invalid_argument("The tag type does not match the list's content type"); | ||||
|     tags.emplace_back(make_unique<T>(std::forward<Args>(args)...)); | ||||
| } | ||||
|  | ||||
| template<class T, class Arg> | ||||
| void tag_list::init(std::initializer_list<Arg> init) | ||||
| { | ||||
|     el_type_ = T::type; | ||||
|     tags.reserve(init.size()); | ||||
|     for(const Arg& arg: init) | ||||
|         tags.emplace_back(make_unique<T>(arg)); | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // TAG_LIST_H_INCLUDED | ||||
							
								
								
									
										102
									
								
								depends/libnbtplusplus/include/tag_primitive.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								depends/libnbtplusplus/include/tag_primitive.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef TAG_PRIMITIVE_H_INCLUDED | ||||
| #define TAG_PRIMITIVE_H_INCLUDED | ||||
|  | ||||
| #include "crtp_tag.h" | ||||
| #include "primitive_detail.h" | ||||
| #include "io/stream_reader.h" | ||||
| #include "io/stream_writer.h" | ||||
| #include <istream> | ||||
| #include <sstream> | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| /** | ||||
|  * @brief Tag that contains an integral or floating-point value | ||||
|  * | ||||
|  * Common class for tag_byte, tag_short, tag_int, tag_long, tag_float and tag_double. | ||||
|  */ | ||||
| template<class T> | ||||
| class tag_primitive final : public detail::crtp_tag<tag_primitive<T>> | ||||
| { | ||||
| public: | ||||
|     ///The type of the value | ||||
|     typedef T value_type; | ||||
|  | ||||
|     ///The type of the tag | ||||
|     static constexpr tag_type type = detail::get_primitive_type<T>::value; | ||||
|  | ||||
|     //Constructor | ||||
|     constexpr tag_primitive(T val = 0) noexcept: value(val) {} | ||||
|  | ||||
|     //Getters | ||||
|     operator T&() { return value; } | ||||
|     constexpr operator T() const { return value; } | ||||
|     constexpr T get() const { return value; } | ||||
|  | ||||
|     //Setters | ||||
|     tag_primitive& operator=(T val) { value = val; return *this; } | ||||
|     void set(T val) { value = val; } | ||||
|  | ||||
|     void read_payload(io::stream_reader& reader) override; | ||||
|     void write_payload(io::stream_writer& writer) const override; | ||||
|  | ||||
| private: | ||||
|     T value; | ||||
| }; | ||||
|  | ||||
| template<class T> bool operator==(const tag_primitive<T>& lhs, const tag_primitive<T>& rhs) | ||||
| { return lhs.get() == rhs.get(); } | ||||
| template<class T> bool operator!=(const tag_primitive<T>& lhs, const tag_primitive<T>& rhs) | ||||
| { return !(lhs == rhs); } | ||||
|  | ||||
| //Typedefs that should be used instead of the template tag_primitive. | ||||
| typedef tag_primitive<int8_t> tag_byte; | ||||
| typedef tag_primitive<int16_t> tag_short; | ||||
| typedef tag_primitive<int32_t> tag_int; | ||||
| typedef tag_primitive<int64_t> tag_long; | ||||
| typedef tag_primitive<float> tag_float; | ||||
| typedef tag_primitive<double> tag_double; | ||||
|  | ||||
| template<class T> | ||||
| void tag_primitive<T>::read_payload(io::stream_reader& reader) | ||||
| { | ||||
|     reader.read_num(value); | ||||
|     if(!reader.get_istr()) | ||||
|     { | ||||
|         std::ostringstream str; | ||||
|         str << "Error reading tag_" << type; | ||||
|         throw io::input_error(str.str()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| template<class T> | ||||
| void tag_primitive<T>::write_payload(io::stream_writer& writer) const | ||||
| { | ||||
|     writer.write_num(value); | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // TAG_PRIMITIVE_H_INCLUDED | ||||
							
								
								
									
										74
									
								
								depends/libnbtplusplus/include/tag_string.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								depends/libnbtplusplus/include/tag_string.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef TAG_STRING_H_INCLUDED | ||||
| #define TAG_STRING_H_INCLUDED | ||||
|  | ||||
| #include "crtp_tag.h" | ||||
| #include <string> | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| ///Tag that contains a UTF-8 string | ||||
| class NBT___EXPORT tag_string final : public detail::crtp_tag<tag_string> | ||||
| { | ||||
| public: | ||||
|     ///The type of the tag | ||||
|     static constexpr tag_type type = tag_type::String; | ||||
|  | ||||
|     //Constructors | ||||
|     tag_string() {} | ||||
|     tag_string(const std::string& str): value(str) {} | ||||
|     tag_string(std::string&& str) noexcept: value(std::move(str)) {} | ||||
|     tag_string(const char* str): value(str) {} | ||||
|  | ||||
|     //Getters | ||||
|     operator std::string&() { return value; } | ||||
|     operator const std::string&() const { return value; } | ||||
|     const std::string& get() const { return value; } | ||||
|  | ||||
|     //Setters | ||||
|     tag_string& operator=(const std::string& str) { value = str; return *this; } | ||||
|     tag_string& operator=(std::string&& str)      { value = std::move(str); return *this; } | ||||
|     tag_string& operator=(const char* str)        { value = str; return *this; } | ||||
|     void set(const std::string& str)              { value = str; } | ||||
|     void set(std::string&& str)                   { value = std::move(str); } | ||||
|  | ||||
|     void read_payload(io::stream_reader& reader) override; | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      * @throw std::length_error if the string is too long for NBT | ||||
|      */ | ||||
|     void write_payload(io::stream_writer& writer) const override; | ||||
|  | ||||
| private: | ||||
|     std::string value; | ||||
| }; | ||||
|  | ||||
| inline bool operator==(const tag_string& lhs, const tag_string& rhs) | ||||
| { return lhs.get() == rhs.get(); } | ||||
| inline bool operator!=(const tag_string& lhs, const tag_string& rhs) | ||||
| { return !(lhs == rhs); } | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // TAG_STRING_H_INCLUDED | ||||
							
								
								
									
										51
									
								
								depends/libnbtplusplus/include/tagfwd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								depends/libnbtplusplus/include/tagfwd.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| /** @file | ||||
|  * @brief Provides forward declarations for all tag classes | ||||
|  */ | ||||
| #ifndef TAGFWD_H_INCLUDED | ||||
| #define TAGFWD_H_INCLUDED | ||||
| #include <cstdint> | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| class tag; | ||||
|  | ||||
| template<class T> class tag_primitive; | ||||
| typedef tag_primitive<int8_t> tag_byte; | ||||
| typedef tag_primitive<int16_t> tag_short; | ||||
| typedef tag_primitive<int32_t> tag_int; | ||||
| typedef tag_primitive<int64_t> tag_long; | ||||
| typedef tag_primitive<float> tag_float; | ||||
| typedef tag_primitive<double> tag_double; | ||||
|  | ||||
| class tag_string; | ||||
|  | ||||
| template<class T> class tag_array; | ||||
| typedef tag_array<int8_t> tag_byte_array; | ||||
| typedef tag_array<int32_t> tag_int_array; | ||||
|  | ||||
| class tag_list; | ||||
| class tag_compound; | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // TAGFWD_H_INCLUDED | ||||
							
								
								
									
										47
									
								
								depends/libnbtplusplus/include/text/json_formatter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								depends/libnbtplusplus/include/text/json_formatter.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef JSON_FORMATTER_H_INCLUDED | ||||
| #define JSON_FORMATTER_H_INCLUDED | ||||
|  | ||||
| #include "tagfwd.h" | ||||
| #include <ostream> | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
| namespace text | ||||
| { | ||||
|  | ||||
| /** | ||||
|  * @brief Prints tags in a JSON-like syntax into a stream | ||||
|  * | ||||
|  * @todo Make it configurable and able to produce actual standard-conformant JSON | ||||
|  */ | ||||
| class NBT___EXPORT json_formatter | ||||
| { | ||||
| public: | ||||
|     void print(std::ostream& os, const tag& t) const; | ||||
| }; | ||||
|  | ||||
| } | ||||
| } | ||||
|  | ||||
| #endif // JSON_FORMATTER_H_INCLUDED | ||||
							
								
								
									
										223
									
								
								depends/libnbtplusplus/include/value.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								depends/libnbtplusplus/include/value.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,223 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef TAG_REF_PROXY_H_INCLUDED | ||||
| #define TAG_REF_PROXY_H_INCLUDED | ||||
|  | ||||
| #include "tag.h" | ||||
| #include <string> | ||||
| #include <type_traits> | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| /** | ||||
|  * @brief Contains an NBT value of fixed type | ||||
|  * | ||||
|  * This class is a convenience wrapper for @c std::unique_ptr<tag>. | ||||
|  * A value can contain any kind of tag or no tag (nullptr) and provides | ||||
|  * operations for handling tags of which the type is not known at compile time. | ||||
|  * Assignment or the set method on a value with no tag will fill in the value. | ||||
|  * | ||||
|  * The rationale for the existance of this class is to provide a type-erasured | ||||
|  * means of storing tags, especially when they are contained in tag_compound | ||||
|  * or tag_list. The alternative would be directly using @c std::unique_ptr<tag> | ||||
|  * and @c tag&, which is how it was done in libnbt++1. The main drawback is that | ||||
|  * it becomes very cumbersome to deal with tags of unknown type. | ||||
|  * | ||||
|  * For example, in this case it would not be possible to allow a syntax like | ||||
|  * <tt>compound["foo"] = 42</tt>. If the key "foo" does not exist beforehand, | ||||
|  * the left hand side could not have any sensible value if it was of type | ||||
|  * @c tag&. | ||||
|  * Firstly, the compound tag would have to create a new tag_int there, but it | ||||
|  * cannot know that the new tag is going to be assigned an integer. | ||||
|  * Also, if the type was @c tag& and it allowed assignment of integers, that | ||||
|  * would mean the tag base class has assignments and conversions like this. | ||||
|  * Which means that all other tag classes would inherit them from the base | ||||
|  * class, even though it does not make any sense to allow converting a | ||||
|  * tag_compound into an integer. Attempts like this should be caught at | ||||
|  * compile time. | ||||
|  * | ||||
|  * This is why all the syntactic sugar for tags is contained in the value class | ||||
|  * while the tag class only contains common operations for all tag types. | ||||
|  */ | ||||
| class NBT___EXPORT value | ||||
| { | ||||
| public: | ||||
|     //Constructors | ||||
|     value() noexcept {} | ||||
|     explicit value(std::unique_ptr<tag>&& t) noexcept: tag_(std::move(t)) {} | ||||
|     explicit value(tag&& t); | ||||
|  | ||||
|     //Moving | ||||
|     value(value&&) noexcept = default; | ||||
|     value& operator=(value&&) noexcept = default; | ||||
|  | ||||
|     //Copying | ||||
|     explicit value(const value& rhs); | ||||
|     value& operator=(const value& rhs); | ||||
|  | ||||
|     /** | ||||
|      * @brief Assigns the given value to the tag if the type matches | ||||
|      * @throw std::bad_cast if the type of @c t is not the same as the type | ||||
|      * of this value | ||||
|      */ | ||||
|     value& operator=(tag&& t); | ||||
|     void set(tag&& t); | ||||
|  | ||||
|     //Conversion to tag | ||||
|     /** | ||||
|      * @brief Returns the contained tag | ||||
|      * | ||||
|      * If the value is uninitialized, the behavior is undefined. | ||||
|      */ | ||||
|     operator tag&() { return get(); } | ||||
|     operator const tag&() const { return get(); } | ||||
|     tag& get() { return *tag_; } | ||||
|     const tag& get() const { return *tag_; } | ||||
|  | ||||
|     /** | ||||
|      * @brief Returns a reference to the contained tag as an instance of T | ||||
|      * @throw std::bad_cast if the tag is not of type T | ||||
|      */ | ||||
|     template<class T> | ||||
|     T& as(); | ||||
|     template<class T> | ||||
|     const T& as() const; | ||||
|  | ||||
|     //Assignment of primitives and string | ||||
|     /** | ||||
|      * @brief Assigns the given value to the tag if the type is compatible | ||||
|      * @throw std::bad_cast if the value is not convertible to the tag type | ||||
|      * via a widening conversion | ||||
|      */ | ||||
|     value& operator=(int8_t val); | ||||
|     value& operator=(int16_t val); | ||||
|     value& operator=(int32_t val); | ||||
|     value& operator=(int64_t val); | ||||
|     value& operator=(float val); | ||||
|     value& operator=(double val); | ||||
|  | ||||
|     /** | ||||
|      * @brief Assigns the given string to the tag if it is a tag_string | ||||
|      * @throw std::bad_cast if the contained tag is not a tag_string | ||||
|      */ | ||||
|     value& operator=(const std::string& str); | ||||
|     value& operator=(std::string&& str); | ||||
|  | ||||
|     //Conversions to primitives and string | ||||
|     /** | ||||
|      * @brief Returns the contained value if the type is compatible | ||||
|      * @throw std::bad_cast if the tag type is not convertible to the desired | ||||
|      * type via a widening conversion | ||||
|      */ | ||||
|     explicit operator int8_t() const; | ||||
|     explicit operator int16_t() const; | ||||
|     explicit operator int32_t() const; | ||||
|     explicit operator int64_t() const; | ||||
|     explicit operator float() const; | ||||
|     explicit operator double() const; | ||||
|  | ||||
|     /** | ||||
|      * @brief Returns the contained string if the type is tag_string | ||||
|      * | ||||
|      * If the value is uninitialized, the behavior is undefined. | ||||
|      * @throw std::bad_cast if the tag type is not tag_string | ||||
|      */ | ||||
|     explicit operator const std::string&() const; | ||||
|  | ||||
|     ///Returns true if the value is not uninitialized | ||||
|     explicit operator bool() const { return tag_ != nullptr; } | ||||
|  | ||||
|     /** | ||||
|      * @brief In case of a tag_compound, accesses a tag by key with bounds checking | ||||
|      * | ||||
|      * If the value is uninitialized, the behavior is undefined. | ||||
|      * @throw std::bad_cast if the tag type is not tag_compound | ||||
|      * @throw std::out_of_range if given key does not exist | ||||
|      * @sa tag_compound::at | ||||
|      */ | ||||
|     value& at(const std::string& key); | ||||
|     const value& at(const std::string& key) const; | ||||
|  | ||||
|     /** | ||||
|      * @brief In case of a tag_compound, accesses a tag by key | ||||
|      * | ||||
|      * If the value is uninitialized, the behavior is undefined. | ||||
|      * @throw std::bad_cast if the tag type is not tag_compound | ||||
|      * @sa tag_compound::operator[] | ||||
|      */ | ||||
|     value& operator[](const std::string& key); | ||||
|     value& operator[](const char* key); //need this overload because of conflict with built-in operator[] | ||||
|  | ||||
|     /** | ||||
|      * @brief In case of a tag_list, accesses a tag by index with bounds checking | ||||
|      * | ||||
|      * If the value is uninitialized, the behavior is undefined. | ||||
|      * @throw std::bad_cast if the tag type is not tag_list | ||||
|      * @throw std::out_of_range if the index is out of range | ||||
|      * @sa tag_list::at | ||||
|      */ | ||||
|     value& at(size_t i); | ||||
|     const value& at(size_t i) const; | ||||
|  | ||||
|     /** | ||||
|      * @brief In case of a tag_list, accesses a tag by index | ||||
|      * | ||||
|      * No bounds checking is performed. If the value is uninitialized, the | ||||
|      * behavior is undefined. | ||||
|      * @throw std::bad_cast if the tag type is not tag_list | ||||
|      * @sa tag_list::operator[] | ||||
|      */ | ||||
|     value& operator[](size_t i); | ||||
|     const value& operator[](size_t i) const; | ||||
|  | ||||
|     ///Returns a reference to the underlying std::unique_ptr<tag> | ||||
|     std::unique_ptr<tag>& get_ptr() { return tag_; } | ||||
|     const std::unique_ptr<tag>& get_ptr() const { return tag_; } | ||||
|     ///Resets the underlying std::unique_ptr<tag> to a different value | ||||
|     void set_ptr(std::unique_ptr<tag>&& t) { tag_ = std::move(t); } | ||||
|  | ||||
|     ///@sa tag::get_type | ||||
|     tag_type get_type() const; | ||||
|  | ||||
|     NBT___EXPORT friend bool operator==(const value& lhs, const value& rhs); | ||||
|     NBT___EXPORT friend bool operator!=(const value& lhs, const value& rhs); | ||||
|  | ||||
| private: | ||||
|     std::unique_ptr<tag> tag_; | ||||
| }; | ||||
|  | ||||
| template<class T> | ||||
| T& value::as() | ||||
| { | ||||
|     return tag_->as<T>(); | ||||
| } | ||||
|  | ||||
| template<class T> | ||||
| const T& value::as() const | ||||
| { | ||||
|     return tag_->as<T>(); | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // TAG_REF_PROXY_H_INCLUDED | ||||
							
								
								
									
										67
									
								
								depends/libnbtplusplus/include/value_initializer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								depends/libnbtplusplus/include/value_initializer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #ifndef VALUE_INITIALIZER_H_INCLUDED | ||||
| #define VALUE_INITIALIZER_H_INCLUDED | ||||
|  | ||||
| #include "value.h" | ||||
|  | ||||
| #include "nbt++_export.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| /** | ||||
|  * @brief Helper class for implicitly constructing value objects | ||||
|  * | ||||
|  * This type is a subclass of @ref value. However the only difference to value | ||||
|  * is that this class has additional constructors which allow implicit | ||||
|  * conversion of various types to value objects. These constructors are not | ||||
|  * part of the value class itself because implicit conversions like this | ||||
|  * (especially from @c tag&& to @c value) can cause problems and ambiguities | ||||
|  * in some cases. | ||||
|  * | ||||
|  * value_initializer is especially useful as function parameter type, it will | ||||
|  * allow convenient conversion of various values to tags on function call. | ||||
|  * | ||||
|  * As value_initializer objects are in no way different than value objects, | ||||
|  * they can just be converted to value after construction. | ||||
|  */ | ||||
| class NBT___EXPORT value_initializer : public value | ||||
| { | ||||
| public: | ||||
|     value_initializer(std::unique_ptr<tag>&& t) noexcept: value(std::move(t)) {} | ||||
|     value_initializer(std::nullptr_t) noexcept          : value(nullptr) {} | ||||
|     value_initializer(value&& val) noexcept             : value(std::move(val)) {} | ||||
|     value_initializer(tag&& t)                          : value(std::move(t)) {} | ||||
|  | ||||
|     value_initializer(int8_t val); | ||||
|     value_initializer(int16_t val); | ||||
|     value_initializer(int32_t val); | ||||
|     value_initializer(int64_t val); | ||||
|     value_initializer(float val); | ||||
|     value_initializer(double val); | ||||
|     value_initializer(const std::string& str); | ||||
|     value_initializer(std::string&& str); | ||||
|     value_initializer(const char* str); | ||||
| }; | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // VALUE_INITIALIZER_H_INCLUDED | ||||
							
								
								
									
										284
									
								
								depends/libnbtplusplus/src/endian_str.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								depends/libnbtplusplus/src/endian_str.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,284 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include "endian_str.h" | ||||
| #include <climits> | ||||
| #include <cstring> | ||||
| #include <iostream> | ||||
|  | ||||
| static_assert(CHAR_BIT == 8, "Assuming that a byte has 8 bits"); | ||||
| static_assert(sizeof(float) == 4, "Assuming that a float is 4 byte long"); | ||||
| static_assert(sizeof(double) == 8, "Assuming that a double is 8 byte long"); | ||||
|  | ||||
| namespace endian | ||||
| { | ||||
|  | ||||
| namespace //anonymous | ||||
| { | ||||
|     void pun_int_to_float(float& f, uint32_t i) | ||||
|     { | ||||
|         //Yes we need to do it this way to avoid undefined behavior | ||||
|         memcpy(&f, &i, 4); | ||||
|     } | ||||
|  | ||||
|     uint32_t pun_float_to_int(float f) | ||||
|     { | ||||
|         uint32_t ret; | ||||
|         memcpy(&ret, &f, 4); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     void pun_int_to_double(double& d, uint64_t i) | ||||
|     { | ||||
|         memcpy(&d, &i, 8); | ||||
|     } | ||||
|  | ||||
|     uint64_t pun_double_to_int(double f) | ||||
|     { | ||||
|         uint64_t ret; | ||||
|         memcpy(&ret, &f, 8); | ||||
|         return ret; | ||||
|     } | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| void read_little(std::istream& is, uint8_t& x) | ||||
| { | ||||
|     is.get(reinterpret_cast<char&>(x)); | ||||
| } | ||||
|  | ||||
| void read_little(std::istream& is, uint16_t& x) | ||||
| { | ||||
|     uint8_t tmp[2]; | ||||
|     is.read(reinterpret_cast<char*>(tmp), 2); | ||||
|     x =  uint16_t(tmp[0]) | ||||
|       | (uint16_t(tmp[1]) << 8); | ||||
| } | ||||
|  | ||||
| void read_little(std::istream& is, uint32_t& x) | ||||
| { | ||||
|     uint8_t tmp[4]; | ||||
|     is.read(reinterpret_cast<char*>(tmp), 4); | ||||
|     x =  uint32_t(tmp[0]) | ||||
|       | (uint32_t(tmp[1]) << 8) | ||||
|       | (uint32_t(tmp[2]) << 16) | ||||
|       | (uint32_t(tmp[3]) << 24); | ||||
| } | ||||
|  | ||||
| void read_little(std::istream& is, uint64_t& x) | ||||
| { | ||||
|     uint8_t tmp[8]; | ||||
|     is.read(reinterpret_cast<char*>(tmp), 8); | ||||
|     x =  uint64_t(tmp[0]) | ||||
|       | (uint64_t(tmp[1]) << 8) | ||||
|       | (uint64_t(tmp[2]) << 16) | ||||
|       | (uint64_t(tmp[3]) << 24) | ||||
|       | (uint64_t(tmp[4]) << 32) | ||||
|       | (uint64_t(tmp[5]) << 40) | ||||
|       | (uint64_t(tmp[6]) << 48) | ||||
|       | (uint64_t(tmp[7]) << 56); | ||||
| } | ||||
|  | ||||
| void read_little(std::istream& is, int8_t & x) { read_little(is, reinterpret_cast<uint8_t &>(x)); } | ||||
| void read_little(std::istream& is, int16_t& x) { read_little(is, reinterpret_cast<uint16_t&>(x)); } | ||||
| void read_little(std::istream& is, int32_t& x) { read_little(is, reinterpret_cast<uint32_t&>(x)); } | ||||
| void read_little(std::istream& is, int64_t& x) { read_little(is, reinterpret_cast<uint64_t&>(x)); } | ||||
|  | ||||
| void read_little(std::istream& is, float& x) | ||||
| { | ||||
|     uint32_t tmp; | ||||
|     read_little(is, tmp); | ||||
|     pun_int_to_float(x, tmp); | ||||
| } | ||||
|  | ||||
| void read_little(std::istream& is, double& x) | ||||
| { | ||||
|     uint64_t tmp; | ||||
|     read_little(is, tmp); | ||||
|     pun_int_to_double(x, tmp); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| void read_big(std::istream& is, uint8_t& x) | ||||
| { | ||||
|     is.read(reinterpret_cast<char*>(&x), 1); | ||||
| } | ||||
|  | ||||
| void read_big(std::istream& is, uint16_t& x) | ||||
| { | ||||
|     uint8_t tmp[2]; | ||||
|     is.read(reinterpret_cast<char*>(tmp), 2); | ||||
|     x =  uint16_t(tmp[1]) | ||||
|       | (uint16_t(tmp[0]) << 8); | ||||
| } | ||||
|  | ||||
| void read_big(std::istream& is, uint32_t& x) | ||||
| { | ||||
|     uint8_t tmp[4]; | ||||
|     is.read(reinterpret_cast<char*>(tmp), 4); | ||||
|     x =  uint32_t(tmp[3]) | ||||
|       | (uint32_t(tmp[2]) << 8) | ||||
|       | (uint32_t(tmp[1]) << 16) | ||||
|       | (uint32_t(tmp[0]) << 24); | ||||
| } | ||||
|  | ||||
| void read_big(std::istream& is, uint64_t& x) | ||||
| { | ||||
|     uint8_t tmp[8]; | ||||
|     is.read(reinterpret_cast<char*>(tmp), 8); | ||||
|     x =  uint64_t(tmp[7]) | ||||
|       | (uint64_t(tmp[6]) << 8) | ||||
|       | (uint64_t(tmp[5]) << 16) | ||||
|       | (uint64_t(tmp[4]) << 24) | ||||
|       | (uint64_t(tmp[3]) << 32) | ||||
|       | (uint64_t(tmp[2]) << 40) | ||||
|       | (uint64_t(tmp[1]) << 48) | ||||
|       | (uint64_t(tmp[0]) << 56); | ||||
| } | ||||
|  | ||||
| void read_big(std::istream& is, int8_t & x) { read_big(is, reinterpret_cast<uint8_t &>(x)); } | ||||
| void read_big(std::istream& is, int16_t& x) { read_big(is, reinterpret_cast<uint16_t&>(x)); } | ||||
| void read_big(std::istream& is, int32_t& x) { read_big(is, reinterpret_cast<uint32_t&>(x)); } | ||||
| void read_big(std::istream& is, int64_t& x) { read_big(is, reinterpret_cast<uint64_t&>(x)); } | ||||
|  | ||||
| void read_big(std::istream& is, float& x) | ||||
| { | ||||
|     uint32_t tmp; | ||||
|     read_big(is, tmp); | ||||
|     pun_int_to_float(x, tmp); | ||||
| } | ||||
|  | ||||
| void read_big(std::istream& is, double& x) | ||||
| { | ||||
|     uint64_t tmp; | ||||
|     read_big(is, tmp); | ||||
|     pun_int_to_double(x, tmp); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| void write_little(std::ostream& os, uint8_t x) | ||||
| { | ||||
|     os.put(x); | ||||
| } | ||||
|  | ||||
| void write_little(std::ostream& os, uint16_t x) | ||||
| { | ||||
|     uint8_t tmp[2] { | ||||
|         uint8_t(x), | ||||
|         uint8_t(x >> 8)}; | ||||
|     os.write(reinterpret_cast<const char*>(tmp), 2); | ||||
| } | ||||
|  | ||||
| void write_little(std::ostream& os, uint32_t x) | ||||
| { | ||||
|     uint8_t tmp[4] { | ||||
|         uint8_t(x), | ||||
|         uint8_t(x >> 8), | ||||
|         uint8_t(x >> 16), | ||||
|         uint8_t(x >> 24)}; | ||||
|     os.write(reinterpret_cast<const char*>(tmp), 4); | ||||
| } | ||||
|  | ||||
| void write_little(std::ostream& os, uint64_t x) | ||||
| { | ||||
|     uint8_t tmp[8] { | ||||
|         uint8_t(x), | ||||
|         uint8_t(x >> 8), | ||||
|         uint8_t(x >> 16), | ||||
|         uint8_t(x >> 24), | ||||
|         uint8_t(x >> 32), | ||||
|         uint8_t(x >> 40), | ||||
|         uint8_t(x >> 48), | ||||
|         uint8_t(x >> 56)}; | ||||
|     os.write(reinterpret_cast<const char*>(tmp), 8); | ||||
| } | ||||
|  | ||||
| void write_little(std::ostream& os, int8_t  x) { write_little(os, static_cast<uint8_t >(x)); } | ||||
| void write_little(std::ostream& os, int16_t x) { write_little(os, static_cast<uint16_t>(x)); } | ||||
| void write_little(std::ostream& os, int32_t x) { write_little(os, static_cast<uint32_t>(x)); } | ||||
| void write_little(std::ostream& os, int64_t x) { write_little(os, static_cast<uint64_t>(x)); } | ||||
|  | ||||
| void write_little(std::ostream& os, float x) | ||||
| { | ||||
|     write_little(os, pun_float_to_int(x)); | ||||
| } | ||||
|  | ||||
| void write_little(std::ostream& os, double x) | ||||
| { | ||||
|     write_little(os, pun_double_to_int(x)); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| void write_big(std::ostream& os, uint8_t x) | ||||
| { | ||||
|     os.put(x); | ||||
| } | ||||
|  | ||||
| void write_big(std::ostream& os, uint16_t x) | ||||
| { | ||||
|     uint8_t tmp[2] { | ||||
|         uint8_t(x >> 8), | ||||
|         uint8_t(x)}; | ||||
|     os.write(reinterpret_cast<const char*>(tmp), 2); | ||||
| } | ||||
|  | ||||
| void write_big(std::ostream& os, uint32_t x) | ||||
| { | ||||
|     uint8_t tmp[4] { | ||||
|         uint8_t(x >> 24), | ||||
|         uint8_t(x >> 16), | ||||
|         uint8_t(x >> 8), | ||||
|         uint8_t(x)}; | ||||
|     os.write(reinterpret_cast<const char*>(tmp), 4); | ||||
| } | ||||
|  | ||||
| void write_big(std::ostream& os, uint64_t x) | ||||
| { | ||||
|     uint8_t tmp[8] { | ||||
|         uint8_t(x >> 56), | ||||
|         uint8_t(x >> 48), | ||||
|         uint8_t(x >> 40), | ||||
|         uint8_t(x >> 32), | ||||
|         uint8_t(x >> 24), | ||||
|         uint8_t(x >> 16), | ||||
|         uint8_t(x >> 8), | ||||
|         uint8_t(x)}; | ||||
|     os.write(reinterpret_cast<const char*>(tmp), 8); | ||||
| } | ||||
|  | ||||
| void write_big(std::ostream& os, int8_t  x) { write_big(os, static_cast<uint8_t >(x)); } | ||||
| void write_big(std::ostream& os, int16_t x) { write_big(os, static_cast<uint16_t>(x)); } | ||||
| void write_big(std::ostream& os, int32_t x) { write_big(os, static_cast<uint32_t>(x)); } | ||||
| void write_big(std::ostream& os, int64_t x) { write_big(os, static_cast<uint64_t>(x)); } | ||||
|  | ||||
| void write_big(std::ostream& os, float x) | ||||
| { | ||||
|     write_big(os, pun_float_to_int(x)); | ||||
| } | ||||
|  | ||||
| void write_big(std::ostream& os, double x) | ||||
| { | ||||
|     write_big(os, pun_double_to_int(x)); | ||||
| } | ||||
|  | ||||
| } | ||||
							
								
								
									
										110
									
								
								depends/libnbtplusplus/src/io/stream_reader.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								depends/libnbtplusplus/src/io/stream_reader.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include "io/stream_reader.h" | ||||
| #include "make_unique.h" | ||||
| #include "tag_compound.h" | ||||
| #include <istream> | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
| namespace io | ||||
| { | ||||
|  | ||||
| std::pair<std::string, std::unique_ptr<tag_compound>> read_compound(std::istream& is, endian::endian e) | ||||
| { | ||||
|     return stream_reader(is, e).read_compound(); | ||||
| } | ||||
|  | ||||
| std::pair<std::string, std::unique_ptr<tag>> read_tag(std::istream& is, endian::endian e) | ||||
| { | ||||
|     return stream_reader(is, e).read_tag(); | ||||
| } | ||||
|  | ||||
| stream_reader::stream_reader(std::istream& is, endian::endian e) noexcept: | ||||
|     is(is), endian(e) | ||||
| {} | ||||
|  | ||||
| std::istream& stream_reader::get_istr() const | ||||
| { | ||||
|     return is; | ||||
| } | ||||
|  | ||||
| endian::endian stream_reader::get_endian() const | ||||
| { | ||||
|     return endian; | ||||
| } | ||||
|  | ||||
| std::pair<std::string, std::unique_ptr<tag_compound>> stream_reader::read_compound() | ||||
| { | ||||
|     if(read_type() != tag_type::Compound) | ||||
|     { | ||||
|         is.setstate(std::ios::failbit); | ||||
|         throw input_error("Tag is not a compound"); | ||||
|     } | ||||
|     std::string key = read_string(); | ||||
|     auto comp = make_unique<tag_compound>(); | ||||
|     comp->read_payload(*this); | ||||
|     return {std::move(key), std::move(comp)}; | ||||
| } | ||||
|  | ||||
| std::pair<std::string, std::unique_ptr<tag>> stream_reader::read_tag() | ||||
| { | ||||
|     tag_type type = read_type(); | ||||
|     std::string key = read_string(); | ||||
|     std::unique_ptr<tag> t = read_payload(type); | ||||
|     return {std::move(key), std::move(t)}; | ||||
| } | ||||
|  | ||||
| std::unique_ptr<tag> stream_reader::read_payload(tag_type type) | ||||
| { | ||||
|     std::unique_ptr<tag> t = tag::create(type); | ||||
|     t->read_payload(*this); | ||||
|     return t; | ||||
| } | ||||
|  | ||||
| tag_type stream_reader::read_type(bool allow_end) | ||||
| { | ||||
|     int type = is.get(); | ||||
|     if(!is) | ||||
|         throw input_error("Error reading tag type"); | ||||
|     if(!is_valid_type(type, allow_end)) | ||||
|     { | ||||
|         is.setstate(std::ios::failbit); | ||||
|         throw input_error("Invalid tag type: " + std::to_string(type)); | ||||
|     } | ||||
|     return static_cast<tag_type>(type); | ||||
| } | ||||
|  | ||||
| std::string stream_reader::read_string() | ||||
| { | ||||
|     uint16_t len; | ||||
|     read_num(len); | ||||
|     if(!is) | ||||
|         throw input_error("Error reading string"); | ||||
|  | ||||
|     std::string ret(len, '\0'); | ||||
|     is.read(&ret[0], len); //C++11 allows us to do this | ||||
|     if(!is) | ||||
|         throw input_error("Error reading string"); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| } | ||||
| } | ||||
							
								
								
									
										54
									
								
								depends/libnbtplusplus/src/io/stream_writer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								depends/libnbtplusplus/src/io/stream_writer.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include "io/stream_writer.h" | ||||
| #include <sstream> | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
| namespace io | ||||
| { | ||||
|  | ||||
| void write_tag(const std::string& key, const tag& t, std::ostream& os, endian::endian e) | ||||
| { | ||||
|     stream_writer(os, e).write_tag(key, t); | ||||
| } | ||||
|  | ||||
| void stream_writer::write_tag(const std::string& key, const tag& t) | ||||
| { | ||||
|     write_type(t.get_type()); | ||||
|     write_string(key); | ||||
|     write_payload(t); | ||||
| } | ||||
|  | ||||
| void stream_writer::write_string(const std::string& str) | ||||
| { | ||||
|     if(str.size() > max_string_len) | ||||
|     { | ||||
|         os.setstate(std::ios::failbit); | ||||
|         std::ostringstream sstr; | ||||
|         sstr << "String is too long for NBT (" << str.size() << " > " << max_string_len << ")"; | ||||
|         throw std::length_error(sstr.str()); | ||||
|     } | ||||
|     write_num(static_cast<uint16_t>(str.size())); | ||||
|     os.write(str.data(), str.size()); | ||||
| } | ||||
|  | ||||
| } | ||||
| } | ||||
							
								
								
									
										105
									
								
								depends/libnbtplusplus/src/tag.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								depends/libnbtplusplus/src/tag.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include "tag.h" | ||||
| #include "nbt_tags.h" | ||||
| #include "text/json_formatter.h" | ||||
| #include <limits> | ||||
| #include <ostream> | ||||
| #include <stdexcept> | ||||
| #include <typeinfo> | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| static_assert(std::numeric_limits<float>::is_iec559 && std::numeric_limits<double>::is_iec559, | ||||
|     "The floating point values for NBT must conform to IEC 559/IEEE 754"); | ||||
|  | ||||
| bool is_valid_type(int type, bool allow_end) | ||||
| { | ||||
|     return (allow_end ? 0 : 1) <= type && type <= 11; | ||||
| } | ||||
|  | ||||
| std::unique_ptr<tag> tag::clone() && | ||||
| { | ||||
|     return std::move(*this).move_clone(); | ||||
| } | ||||
|  | ||||
| std::unique_ptr<tag> tag::create(tag_type type) | ||||
| { | ||||
|     switch(type) | ||||
|     { | ||||
|     case tag_type::Byte:        return make_unique<tag_byte>(); | ||||
|     case tag_type::Short:       return make_unique<tag_short>(); | ||||
|     case tag_type::Int:         return make_unique<tag_int>(); | ||||
|     case tag_type::Long:        return make_unique<tag_long>(); | ||||
|     case tag_type::Float:       return make_unique<tag_float>(); | ||||
|     case tag_type::Double:      return make_unique<tag_double>(); | ||||
|     case tag_type::Byte_Array:  return make_unique<tag_byte_array>(); | ||||
|     case tag_type::String:      return make_unique<tag_string>(); | ||||
|     case tag_type::List:        return make_unique<tag_list>(); | ||||
|     case tag_type::Compound:    return make_unique<tag_compound>(); | ||||
|     case tag_type::Int_Array:   return make_unique<tag_int_array>(); | ||||
|  | ||||
|     default: throw std::invalid_argument("Invalid tag type"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| bool operator==(const tag& lhs, const tag& rhs) | ||||
| { | ||||
|     if(typeid(lhs) != typeid(rhs)) | ||||
|         return false; | ||||
|     return lhs.equals(rhs); | ||||
| } | ||||
|  | ||||
| bool operator!=(const tag& lhs, const tag& rhs) | ||||
| { | ||||
|     return !(lhs == rhs); | ||||
| } | ||||
|  | ||||
| std::ostream& operator<<(std::ostream& os, tag_type tt) | ||||
| { | ||||
|     switch(tt) | ||||
|     { | ||||
|     case tag_type::End:         return os << "end"; | ||||
|     case tag_type::Byte:        return os << "byte"; | ||||
|     case tag_type::Short:       return os << "short"; | ||||
|     case tag_type::Int:         return os << "int"; | ||||
|     case tag_type::Long:        return os << "long"; | ||||
|     case tag_type::Float:       return os << "float"; | ||||
|     case tag_type::Double:      return os << "double"; | ||||
|     case tag_type::Byte_Array:  return os << "byte_array"; | ||||
|     case tag_type::String:      return os << "string"; | ||||
|     case tag_type::List:        return os << "list"; | ||||
|     case tag_type::Compound:    return os << "compound"; | ||||
|     case tag_type::Int_Array:   return os << "int_array"; | ||||
|     case tag_type::Null:        return os << "null"; | ||||
|  | ||||
|     default:                    return os << "invalid"; | ||||
|     } | ||||
| } | ||||
|  | ||||
| std::ostream& operator<<(std::ostream& os, const tag& t) | ||||
| { | ||||
|     static const text::json_formatter formatter; | ||||
|     formatter.print(os, t); | ||||
|     return os; | ||||
| } | ||||
|  | ||||
| } | ||||
							
								
								
									
										110
									
								
								depends/libnbtplusplus/src/tag_array.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								depends/libnbtplusplus/src/tag_array.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include "tag_array.h" | ||||
| #include "io/stream_reader.h" | ||||
| #include "io/stream_writer.h" | ||||
| #include <istream> | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| template<class T> | ||||
| T& tag_array<T>::at(size_t i) | ||||
| { | ||||
|     return data.at(i); | ||||
| } | ||||
|  | ||||
| template<class T> | ||||
| T tag_array<T>::at(size_t i) const | ||||
| { | ||||
|     return data.at(i); | ||||
| } | ||||
|  | ||||
| //Slightly different between byte_array and int_array | ||||
| //Reading | ||||
| template<> | ||||
| void tag_array<int8_t>::read_payload(io::stream_reader& reader) | ||||
| { | ||||
|     int32_t length; | ||||
|     reader.read_num(length); | ||||
|     if(length < 0) | ||||
|         reader.get_istr().setstate(std::ios::failbit); | ||||
|     if(!reader.get_istr()) | ||||
|         throw io::input_error("Error reading length of tag_byte_array"); | ||||
|  | ||||
|     data.resize(length); | ||||
|     reader.get_istr().read(reinterpret_cast<char*>(data.data()), length); | ||||
|     if(!reader.get_istr()) | ||||
|         throw io::input_error("Error reading contents of tag_byte_array"); | ||||
| } | ||||
|  | ||||
| template<> | ||||
| void tag_array<int32_t>::read_payload(io::stream_reader& reader) | ||||
| { | ||||
|     int32_t length; | ||||
|     reader.read_num(length); | ||||
|     if(length < 0) | ||||
|         reader.get_istr().setstate(std::ios::failbit); | ||||
|     if(!reader.get_istr()) | ||||
|         throw io::input_error("Error reading length of tag_int_array"); | ||||
|  | ||||
|     data.clear(); | ||||
|     data.reserve(length); | ||||
|     for(int32_t i = 0; i < length; ++i) | ||||
|     { | ||||
|         int32_t val; | ||||
|         reader.read_num(val); | ||||
|         data.push_back(val); | ||||
|     } | ||||
|     if(!reader.get_istr()) | ||||
|         throw io::input_error("Error reading contents of tag_int_array"); | ||||
| } | ||||
|  | ||||
| //Writing | ||||
| template<> | ||||
| void tag_array<int8_t>::write_payload(io::stream_writer& writer) const | ||||
| { | ||||
|     if(size() > io::stream_writer::max_array_len) | ||||
|     { | ||||
|         writer.get_ostr().setstate(std::ios::failbit); | ||||
|         throw std::length_error("Byte array is too large for NBT"); | ||||
|     } | ||||
|     writer.write_num(static_cast<int32_t>(size())); | ||||
|     writer.get_ostr().write(reinterpret_cast<const char*>(data.data()), data.size()); | ||||
| } | ||||
|  | ||||
| template<> | ||||
| void tag_array<int32_t>::write_payload(io::stream_writer& writer) const | ||||
| { | ||||
|     if(size() > io::stream_writer::max_array_len) | ||||
|     { | ||||
|         writer.get_ostr().setstate(std::ios::failbit); | ||||
|         throw std::length_error("Int array is too large for NBT"); | ||||
|     } | ||||
|     writer.write_num(static_cast<int32_t>(size())); | ||||
|     for(int32_t i: data) | ||||
|         writer.write_num(i); | ||||
| } | ||||
|  | ||||
| //Enforce template instantiations | ||||
| template class tag_array<int8_t>; | ||||
| template class tag_array<int32_t>; | ||||
|  | ||||
| } | ||||
							
								
								
									
										109
									
								
								depends/libnbtplusplus/src/tag_compound.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								depends/libnbtplusplus/src/tag_compound.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include "tag_compound.h" | ||||
| #include "io/stream_reader.h" | ||||
| #include "io/stream_writer.h" | ||||
| #include <istream> | ||||
| #include <sstream> | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| tag_compound::tag_compound(std::initializer_list<std::pair<std::string, value_initializer>> init) | ||||
| { | ||||
|     for(const auto& pair: init) | ||||
|         tags.emplace(std::move(pair.first), std::move(pair.second)); | ||||
| } | ||||
|  | ||||
| value& tag_compound::at(const std::string& key) | ||||
| { | ||||
|     return tags.at(key); | ||||
| } | ||||
|  | ||||
| const value& tag_compound::at(const std::string& key) const | ||||
| { | ||||
|     return tags.at(key); | ||||
| } | ||||
|  | ||||
| std::pair<tag_compound::iterator, bool> tag_compound::put(const std::string& key, value_initializer&& val) | ||||
| { | ||||
|     auto it = tags.find(key); | ||||
|     if(it != tags.end()) | ||||
|     { | ||||
|         it->second = std::move(val); | ||||
|         return {it, false}; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         return tags.emplace(key, std::move(val)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| std::pair<tag_compound::iterator, bool> tag_compound::insert(const std::string& key, value_initializer&& val) | ||||
| { | ||||
|     return tags.emplace(key, std::move(val)); | ||||
| } | ||||
|  | ||||
| bool tag_compound::erase(const std::string& key) | ||||
| { | ||||
|     return tags.erase(key) != 0; | ||||
| } | ||||
|  | ||||
| bool tag_compound::has_key(const std::string& key) const | ||||
| { | ||||
|     return tags.find(key) != tags.end(); | ||||
| } | ||||
|  | ||||
| bool tag_compound::has_key(const std::string& key, tag_type type) const | ||||
| { | ||||
|     auto it = tags.find(key); | ||||
|     return it != tags.end() && it->second.get_type() == type; | ||||
| } | ||||
|  | ||||
| void tag_compound::read_payload(io::stream_reader& reader) | ||||
| { | ||||
|     clear(); | ||||
|     tag_type tt; | ||||
|     while((tt = reader.read_type(true)) != tag_type::End) | ||||
|     { | ||||
|         std::string key; | ||||
|         try | ||||
|         { | ||||
|             key = reader.read_string(); | ||||
|         } | ||||
|         catch(io::input_error& ex) | ||||
|         { | ||||
|             std::ostringstream str; | ||||
|             str << "Error reading key of tag_" << tt; | ||||
|             throw io::input_error(str.str()); | ||||
|         } | ||||
|         auto tptr = reader.read_payload(tt); | ||||
|         tags.emplace(std::move(key), value(std::move(tptr))); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void tag_compound::write_payload(io::stream_writer& writer) const | ||||
| { | ||||
|     for(const auto& pair: tags) | ||||
|         writer.write_tag(pair.first, pair.second); | ||||
|     writer.write_type(tag_type::End); | ||||
| } | ||||
|  | ||||
| } | ||||
							
								
								
									
										150
									
								
								depends/libnbtplusplus/src/tag_list.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								depends/libnbtplusplus/src/tag_list.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include "tag_list.h" | ||||
| #include "nbt_tags.h" | ||||
| #include "io/stream_reader.h" | ||||
| #include "io/stream_writer.h" | ||||
| #include <istream> | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| tag_list::tag_list(std::initializer_list<int8_t>         il) { init<tag_byte>(il); } | ||||
| tag_list::tag_list(std::initializer_list<int16_t>        il) { init<tag_short>(il); } | ||||
| tag_list::tag_list(std::initializer_list<int32_t>        il) { init<tag_int>(il); } | ||||
| tag_list::tag_list(std::initializer_list<int64_t>        il) { init<tag_long>(il); } | ||||
| tag_list::tag_list(std::initializer_list<float>          il) { init<tag_float>(il); } | ||||
| tag_list::tag_list(std::initializer_list<double>         il) { init<tag_double>(il); } | ||||
| tag_list::tag_list(std::initializer_list<std::string>    il) { init<tag_string>(il); } | ||||
| tag_list::tag_list(std::initializer_list<tag_byte_array> il) { init<tag_byte_array>(il); } | ||||
| tag_list::tag_list(std::initializer_list<tag_list>       il) { init<tag_list>(il); } | ||||
| tag_list::tag_list(std::initializer_list<tag_compound>   il) { init<tag_compound>(il); } | ||||
| tag_list::tag_list(std::initializer_list<tag_int_array>  il) { init<tag_int_array>(il); } | ||||
|  | ||||
| tag_list::tag_list(std::initializer_list<value> init) | ||||
| { | ||||
|     if(init.size() == 0) | ||||
|         el_type_ = tag_type::Null; | ||||
|     else | ||||
|     { | ||||
|         el_type_ = init.begin()->get_type(); | ||||
|         for(const value& val: init) | ||||
|         { | ||||
|             if(!val || val.get_type() != el_type_) | ||||
|                 throw std::invalid_argument("The values are not all the same type"); | ||||
|         } | ||||
|         tags.assign(init.begin(), init.end()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| value& tag_list::at(size_t i) | ||||
| { | ||||
|     return tags.at(i); | ||||
| } | ||||
|  | ||||
| const value& tag_list::at(size_t i) const | ||||
| { | ||||
|     return tags.at(i); | ||||
| } | ||||
|  | ||||
| void tag_list::set(size_t i, value&& val) | ||||
| { | ||||
|     if(val.get_type() != el_type_) | ||||
|         throw std::invalid_argument("The tag type does not match the list's content type"); | ||||
|     tags.at(i) = std::move(val); | ||||
| } | ||||
|  | ||||
| void tag_list::push_back(value_initializer&& val) | ||||
| { | ||||
|     if(!val) //don't allow null values | ||||
|         throw std::invalid_argument("The value must not be null"); | ||||
|     if(el_type_ == tag_type::Null) //set content type if undetermined | ||||
|         el_type_ = val.get_type(); | ||||
|     else if(el_type_ != val.get_type()) | ||||
|         throw std::invalid_argument("The tag type does not match the list's content type"); | ||||
|     tags.push_back(std::move(val)); | ||||
| } | ||||
|  | ||||
| void tag_list::reset(tag_type type) | ||||
| { | ||||
|     clear(); | ||||
|     el_type_ = type; | ||||
| } | ||||
|  | ||||
| void tag_list::read_payload(io::stream_reader& reader) | ||||
| { | ||||
|     tag_type lt = reader.read_type(true); | ||||
|  | ||||
|     int32_t length; | ||||
|     reader.read_num(length); | ||||
|     if(length < 0) | ||||
|         reader.get_istr().setstate(std::ios::failbit); | ||||
|     if(!reader.get_istr()) | ||||
|         throw io::input_error("Error reading length of tag_list"); | ||||
|  | ||||
|     if(lt != tag_type::End) | ||||
|     { | ||||
|         reset(lt); | ||||
|         tags.reserve(length); | ||||
|  | ||||
|         for(int32_t i = 0; i < length; ++i) | ||||
|             tags.emplace_back(reader.read_payload(lt)); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         //In case of tag_end, ignore the length and leave the type undetermined | ||||
|         reset(tag_type::Null); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void tag_list::write_payload(io::stream_writer& writer) const | ||||
| { | ||||
|     if(size() > io::stream_writer::max_array_len) | ||||
|     { | ||||
|         writer.get_ostr().setstate(std::ios::failbit); | ||||
|         throw std::length_error("List is too large for NBT"); | ||||
|     } | ||||
|     writer.write_type(el_type_ != tag_type::Null | ||||
|                       ? el_type_ | ||||
|                       : tag_type::End); | ||||
|     writer.write_num(static_cast<int32_t>(size())); | ||||
|     for(const auto& val: tags) | ||||
|     { | ||||
|         //check if the value is of the correct type | ||||
|         if(val.get_type() != el_type_) | ||||
|         { | ||||
|             writer.get_ostr().setstate(std::ios::failbit); | ||||
|             throw std::logic_error("The tags in the list do not all match the content type"); | ||||
|         } | ||||
|         writer.write_payload(val); | ||||
|     } | ||||
| } | ||||
|  | ||||
| bool operator==(const tag_list& lhs, const tag_list& rhs) | ||||
| { | ||||
|     return lhs.el_type_ == rhs.el_type_ && lhs.tags == rhs.tags; | ||||
| } | ||||
|  | ||||
| bool operator!=(const tag_list& lhs, const tag_list& rhs) | ||||
| { | ||||
|     return !(lhs == rhs); | ||||
| } | ||||
|  | ||||
| } | ||||
							
								
								
									
										44
									
								
								depends/libnbtplusplus/src/tag_string.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								depends/libnbtplusplus/src/tag_string.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include "tag_string.h" | ||||
| #include "io/stream_reader.h" | ||||
| #include "io/stream_writer.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| void tag_string::read_payload(io::stream_reader& reader) | ||||
| { | ||||
|     try | ||||
|     { | ||||
|         value = reader.read_string(); | ||||
|     } | ||||
|     catch(io::input_error& ex) | ||||
|     { | ||||
|         throw io::input_error("Error reading tag_string"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void tag_string::write_payload(io::stream_writer& writer) const | ||||
| { | ||||
|     writer.write_string(value); | ||||
| } | ||||
|  | ||||
| } | ||||
							
								
								
									
										195
									
								
								depends/libnbtplusplus/src/text/json_formatter.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								depends/libnbtplusplus/src/text/json_formatter.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,195 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include "text/json_formatter.h" | ||||
| #include "nbt_tags.h" | ||||
| #include "nbt_visitor.h" | ||||
| #include <cmath> | ||||
| #include <iomanip> | ||||
| #include <limits> | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
| namespace text | ||||
| { | ||||
|  | ||||
| namespace //anonymous | ||||
| { | ||||
|     ///Helper class which uses the Visitor pattern to pretty-print tags | ||||
|     class json_fmt_visitor : public const_nbt_visitor | ||||
|     { | ||||
|     public: | ||||
|         json_fmt_visitor(std::ostream& os, const json_formatter& fmt): | ||||
|             os(os) | ||||
|         {} | ||||
|  | ||||
|         void visit(const tag_byte& b) override | ||||
|         { os << static_cast<int>(b.get()) << "b"; } //We don't want to print a character | ||||
|  | ||||
|         void visit(const tag_short& s) override | ||||
|         { os << s.get() << "s"; } | ||||
|  | ||||
|         void visit(const tag_int& i) override | ||||
|         { os << i.get(); } | ||||
|  | ||||
|         void visit(const tag_long& l) override | ||||
|         { os << l.get() << "l"; } | ||||
|  | ||||
|         void visit(const tag_float& f) override | ||||
|         { | ||||
|             write_float(f.get()); | ||||
|             os << "f"; | ||||
|         } | ||||
|  | ||||
|         void visit(const tag_double& d) override | ||||
|         { | ||||
|             write_float(d.get()); | ||||
|             os << "d"; | ||||
|         } | ||||
|  | ||||
|         void visit(const tag_byte_array& ba) override | ||||
|         { os << "[" << ba.size() << " bytes]"; } | ||||
|  | ||||
|         void visit(const tag_string& s) override | ||||
|         { os << '"' << s.get() << '"'; } //TODO: escape special characters | ||||
|  | ||||
|         void visit(const tag_list& l) override | ||||
|         { | ||||
|             //Wrap lines for lists of lists or compounds. | ||||
|             //Lists of other types can usually be on one line without problem. | ||||
|             const bool break_lines = l.size() > 0 && | ||||
|                 (l.el_type() == tag_type::List || l.el_type() == tag_type::Compound); | ||||
|  | ||||
|             os << "["; | ||||
|             if(break_lines) | ||||
|             { | ||||
|                 os << "\n"; | ||||
|                 ++indent_lvl; | ||||
|                 for(unsigned int i = 0; i < l.size(); ++i) | ||||
|                 { | ||||
|                     indent(); | ||||
|                     if(l[i]) | ||||
|                         l[i].get().accept(*this); | ||||
|                     else | ||||
|                         write_null(); | ||||
|                     if(i != l.size()-1) | ||||
|                         os << ","; | ||||
|                     os << "\n"; | ||||
|                 } | ||||
|                 --indent_lvl; | ||||
|                 indent(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 for(unsigned int i = 0; i < l.size(); ++i) | ||||
|                 { | ||||
|                     if(l[i]) | ||||
|                         l[i].get().accept(*this); | ||||
|                     else | ||||
|                         write_null(); | ||||
|                     if(i != l.size()-1) | ||||
|                         os << ", "; | ||||
|                 } | ||||
|             } | ||||
|             os << "]"; | ||||
|         } | ||||
|  | ||||
|         void visit(const tag_compound& c) override | ||||
|         { | ||||
|             if(c.size() == 0) //No line breaks inside empty compounds please | ||||
|             { | ||||
|                 os << "{}"; | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             os << "{\n"; | ||||
|             ++indent_lvl; | ||||
|             unsigned int i = 0; | ||||
|             for(const auto& kv: c) | ||||
|             { | ||||
|                 indent(); | ||||
|                 os << kv.first << ": "; | ||||
|                 if(kv.second) | ||||
|                     kv.second.get().accept(*this); | ||||
|                 else | ||||
|                     write_null(); | ||||
|                 if(i != c.size()-1) | ||||
|                     os << ","; | ||||
|                 os << "\n"; | ||||
|                 ++i; | ||||
|             } | ||||
|             --indent_lvl; | ||||
|             indent(); | ||||
|             os << "}"; | ||||
|         } | ||||
|  | ||||
|         void visit(const tag_int_array& ia) override | ||||
|         { | ||||
|             os << "["; | ||||
|             for(unsigned int i = 0; i < ia.size(); ++i) | ||||
|             { | ||||
|                 os << ia[i]; | ||||
|                 if(i != ia.size()-1) | ||||
|                     os << ", "; | ||||
|             } | ||||
|             os << "]"; | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         const std::string indent_str = "  "; | ||||
|  | ||||
|         std::ostream& os; | ||||
|         int indent_lvl = 0; | ||||
|  | ||||
|         void indent() | ||||
|         { | ||||
|             for(int i = 0; i < indent_lvl; ++i) | ||||
|                 os << indent_str; | ||||
|         } | ||||
|  | ||||
|         template<class T> | ||||
|         void write_float(T val, int precision = std::numeric_limits<T>::max_digits10) | ||||
|         { | ||||
|             if(std::isfinite(val)) | ||||
|                 os << std::setprecision(precision) << val; | ||||
|             else if(std::isinf(val)) | ||||
|             { | ||||
|                 if(std::signbit(val)) | ||||
|                     os << "-"; | ||||
|                 os << "Infinity"; | ||||
|             } | ||||
|             else | ||||
|                 os << "NaN"; | ||||
|         } | ||||
|  | ||||
|         void write_null() | ||||
|         { | ||||
|             os << "null"; | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| void json_formatter::print(std::ostream& os, const tag& t) const | ||||
| { | ||||
|     json_fmt_visitor v(os, *this); | ||||
|     t.accept(v); | ||||
| } | ||||
|  | ||||
| } | ||||
| } | ||||
							
								
								
									
										376
									
								
								depends/libnbtplusplus/src/value.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										376
									
								
								depends/libnbtplusplus/src/value.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,376 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include "value.h" | ||||
| #include "nbt_tags.h" | ||||
| #include <typeinfo> | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| value::value(tag&& t): | ||||
|     tag_(std::move(t).move_clone()) | ||||
| {} | ||||
|  | ||||
| value::value(const value& rhs): | ||||
|     tag_(rhs.tag_ ? rhs.tag_->clone() : nullptr) | ||||
| {} | ||||
|  | ||||
| value& value::operator=(const value& rhs) | ||||
| { | ||||
|     if(this != &rhs) | ||||
|     { | ||||
|         tag_ = rhs.tag_ ? rhs.tag_->clone() : nullptr; | ||||
|     } | ||||
|     return *this; | ||||
| } | ||||
|  | ||||
| value& value::operator=(tag&& t) | ||||
| { | ||||
|     set(std::move(t)); | ||||
|     return *this; | ||||
| } | ||||
|  | ||||
| void value::set(tag&& t) | ||||
| { | ||||
|     if(tag_) | ||||
|         tag_->assign(std::move(t)); | ||||
|     else | ||||
|         tag_ = std::move(t).move_clone(); | ||||
| } | ||||
|  | ||||
| //Primitive assignment | ||||
| //FIXME: Make this less copypaste! | ||||
| value& value::operator=(int8_t val) | ||||
| { | ||||
|     if(!tag_) | ||||
|         set(tag_byte(val)); | ||||
|     else switch(tag_->get_type()) | ||||
|     { | ||||
|     case tag_type::Byte: | ||||
|         static_cast<tag_byte&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Short: | ||||
|         static_cast<tag_short&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Int: | ||||
|         static_cast<tag_int&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Long: | ||||
|         static_cast<tag_long&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Float: | ||||
|         static_cast<tag_float&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Double: | ||||
|         static_cast<tag_double&>(*tag_).set(val); | ||||
|         break; | ||||
|  | ||||
|     default: | ||||
|         throw std::bad_cast(); | ||||
|     } | ||||
|     return *this; | ||||
| } | ||||
|  | ||||
| value& value::operator=(int16_t val) | ||||
| { | ||||
|     if(!tag_) | ||||
|         set(tag_short(val)); | ||||
|     else switch(tag_->get_type()) | ||||
|     { | ||||
|     case tag_type::Short: | ||||
|         static_cast<tag_short&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Int: | ||||
|         static_cast<tag_int&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Long: | ||||
|         static_cast<tag_long&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Float: | ||||
|         static_cast<tag_float&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Double: | ||||
|         static_cast<tag_double&>(*tag_).set(val); | ||||
|         break; | ||||
|  | ||||
|     default: | ||||
|         throw std::bad_cast(); | ||||
|     } | ||||
|     return *this; | ||||
| } | ||||
|  | ||||
| value& value::operator=(int32_t val) | ||||
| { | ||||
|     if(!tag_) | ||||
|         set(tag_int(val)); | ||||
|     else switch(tag_->get_type()) | ||||
|     { | ||||
|     case tag_type::Int: | ||||
|         static_cast<tag_int&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Long: | ||||
|         static_cast<tag_long&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Float: | ||||
|         static_cast<tag_float&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Double: | ||||
|         static_cast<tag_double&>(*tag_).set(val); | ||||
|         break; | ||||
|  | ||||
|     default: | ||||
|         throw std::bad_cast(); | ||||
|     } | ||||
|     return *this; | ||||
| } | ||||
|  | ||||
| value& value::operator=(int64_t val) | ||||
| { | ||||
|     if(!tag_) | ||||
|         set(tag_long(val)); | ||||
|     else switch(tag_->get_type()) | ||||
|     { | ||||
|     case tag_type::Long: | ||||
|         static_cast<tag_long&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Float: | ||||
|         static_cast<tag_float&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Double: | ||||
|         static_cast<tag_double&>(*tag_).set(val); | ||||
|         break; | ||||
|  | ||||
|     default: | ||||
|         throw std::bad_cast(); | ||||
|     } | ||||
|     return *this; | ||||
| } | ||||
|  | ||||
| value& value::operator=(float val) | ||||
| { | ||||
|     if(!tag_) | ||||
|         set(tag_float(val)); | ||||
|     else switch(tag_->get_type()) | ||||
|     { | ||||
|     case tag_type::Float: | ||||
|         static_cast<tag_float&>(*tag_).set(val); | ||||
|         break; | ||||
|     case tag_type::Double: | ||||
|         static_cast<tag_double&>(*tag_).set(val); | ||||
|         break; | ||||
|  | ||||
|     default: | ||||
|         throw std::bad_cast(); | ||||
|     } | ||||
|     return *this; | ||||
| } | ||||
|  | ||||
| value& value::operator=(double val) | ||||
| { | ||||
|     if(!tag_) | ||||
|         set(tag_double(val)); | ||||
|     else switch(tag_->get_type()) | ||||
|     { | ||||
|     case tag_type::Double: | ||||
|         static_cast<tag_double&>(*tag_).set(val); | ||||
|         break; | ||||
|  | ||||
|     default: | ||||
|         throw std::bad_cast(); | ||||
|     } | ||||
|     return *this; | ||||
| } | ||||
|  | ||||
| //Primitive conversion | ||||
| value::operator int8_t() const | ||||
| { | ||||
|     switch(tag_->get_type()) | ||||
|     { | ||||
|     case tag_type::Byte: | ||||
|         return static_cast<tag_byte&>(*tag_).get(); | ||||
|  | ||||
|     default: | ||||
|         throw std::bad_cast(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| value::operator int16_t() const | ||||
| { | ||||
|     switch(tag_->get_type()) | ||||
|     { | ||||
|     case tag_type::Byte: | ||||
|         return static_cast<tag_byte&>(*tag_).get(); | ||||
|     case tag_type::Short: | ||||
|         return static_cast<tag_short&>(*tag_).get(); | ||||
|  | ||||
|     default: | ||||
|         throw std::bad_cast(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| value::operator int32_t() const | ||||
| { | ||||
|     switch(tag_->get_type()) | ||||
|     { | ||||
|     case tag_type::Byte: | ||||
|         return static_cast<tag_byte&>(*tag_).get(); | ||||
|     case tag_type::Short: | ||||
|         return static_cast<tag_short&>(*tag_).get(); | ||||
|     case tag_type::Int: | ||||
|         return static_cast<tag_int&>(*tag_).get(); | ||||
|  | ||||
|     default: | ||||
|         throw std::bad_cast(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| value::operator int64_t() const | ||||
| { | ||||
|     switch(tag_->get_type()) | ||||
|     { | ||||
|     case tag_type::Byte: | ||||
|         return static_cast<tag_byte&>(*tag_).get(); | ||||
|     case tag_type::Short: | ||||
|         return static_cast<tag_short&>(*tag_).get(); | ||||
|     case tag_type::Int: | ||||
|         return static_cast<tag_int&>(*tag_).get(); | ||||
|     case tag_type::Long: | ||||
|         return static_cast<tag_long&>(*tag_).get(); | ||||
|  | ||||
|     default: | ||||
|         throw std::bad_cast(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| value::operator float() const | ||||
| { | ||||
|     switch(tag_->get_type()) | ||||
|     { | ||||
|     case tag_type::Byte: | ||||
|         return static_cast<tag_byte&>(*tag_).get(); | ||||
|     case tag_type::Short: | ||||
|         return static_cast<tag_short&>(*tag_).get(); | ||||
|     case tag_type::Int: | ||||
|         return static_cast<tag_int&>(*tag_).get(); | ||||
|     case tag_type::Long: | ||||
|         return static_cast<tag_long&>(*tag_).get(); | ||||
|     case tag_type::Float: | ||||
|         return static_cast<tag_float&>(*tag_).get(); | ||||
|  | ||||
|     default: | ||||
|         throw std::bad_cast(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| value::operator double() const | ||||
| { | ||||
|     switch(tag_->get_type()) | ||||
|     { | ||||
|     case tag_type::Byte: | ||||
|         return static_cast<tag_byte&>(*tag_).get(); | ||||
|     case tag_type::Short: | ||||
|         return static_cast<tag_short&>(*tag_).get(); | ||||
|     case tag_type::Int: | ||||
|         return static_cast<tag_int&>(*tag_).get(); | ||||
|     case tag_type::Long: | ||||
|         return static_cast<tag_long&>(*tag_).get(); | ||||
|     case tag_type::Float: | ||||
|         return static_cast<tag_float&>(*tag_).get(); | ||||
|     case tag_type::Double: | ||||
|         return static_cast<tag_double&>(*tag_).get(); | ||||
|  | ||||
|     default: | ||||
|         throw std::bad_cast(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| value& value::operator=(std::string&& str) | ||||
| { | ||||
|     if(!tag_) | ||||
|         set(tag_string(std::move(str))); | ||||
|     else | ||||
|         dynamic_cast<tag_string&>(*tag_).set(std::move(str)); | ||||
|     return *this; | ||||
| } | ||||
|  | ||||
| value::operator const std::string&() const | ||||
| { | ||||
|     return dynamic_cast<tag_string&>(*tag_).get(); | ||||
| } | ||||
|  | ||||
| value& value::at(const std::string& key) | ||||
| { | ||||
|     return dynamic_cast<tag_compound&>(*tag_).at(key); | ||||
| } | ||||
|  | ||||
| const value& value::at(const std::string& key) const | ||||
| { | ||||
|     return dynamic_cast<const tag_compound&>(*tag_).at(key); | ||||
| } | ||||
|  | ||||
| value& value::operator[](const std::string& key) | ||||
| { | ||||
|     return dynamic_cast<tag_compound&>(*tag_)[key]; | ||||
| } | ||||
|  | ||||
| value& value::operator[](const char* key) | ||||
| { | ||||
|     return (*this)[std::string(key)]; | ||||
| } | ||||
|  | ||||
| value& value::at(size_t i) | ||||
| { | ||||
|     return dynamic_cast<tag_list&>(*tag_).at(i); | ||||
| } | ||||
|  | ||||
| const value& value::at(size_t i) const | ||||
| { | ||||
|     return dynamic_cast<const tag_list&>(*tag_).at(i); | ||||
| } | ||||
|  | ||||
| value& value::operator[](size_t i) | ||||
| { | ||||
|     return dynamic_cast<tag_list&>(*tag_)[i]; | ||||
| } | ||||
|  | ||||
| const value& value::operator[](size_t i) const | ||||
| { | ||||
|     return dynamic_cast<const tag_list&>(*tag_)[i]; | ||||
| } | ||||
|  | ||||
| tag_type value::get_type() const | ||||
| { | ||||
|     return tag_ ? tag_->get_type() : tag_type::Null; | ||||
| } | ||||
|  | ||||
| bool operator==(const value& lhs, const value& rhs) | ||||
| { | ||||
|     if(lhs.tag_ != nullptr && rhs.tag_ != nullptr) | ||||
|         return *lhs.tag_ == *rhs.tag_; | ||||
|     else | ||||
|         return lhs.tag_ == nullptr && rhs.tag_ == nullptr; | ||||
| } | ||||
|  | ||||
| bool operator!=(const value& lhs, const value& rhs) | ||||
| { | ||||
|     return !(lhs == rhs); | ||||
| } | ||||
|  | ||||
| } | ||||
							
								
								
									
										36
									
								
								depends/libnbtplusplus/src/value_initializer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								depends/libnbtplusplus/src/value_initializer.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include "value_initializer.h" | ||||
| #include "nbt_tags.h" | ||||
|  | ||||
| namespace nbt | ||||
| { | ||||
|  | ||||
| value_initializer::value_initializer(int8_t val)            : value(tag_byte(val)) {} | ||||
| value_initializer::value_initializer(int16_t val)           : value(tag_short(val)) {} | ||||
| value_initializer::value_initializer(int32_t val)           : value(tag_int(val)) {} | ||||
| value_initializer::value_initializer(int64_t val)           : value(tag_long(val)) {} | ||||
| value_initializer::value_initializer(float val)             : value(tag_float(val)) {} | ||||
| value_initializer::value_initializer(double val)            : value(tag_double(val)) {} | ||||
| value_initializer::value_initializer(const std::string& str): value(tag_string(str)) {} | ||||
| value_initializer::value_initializer(std::string&& str)     : value(tag_string(std::move(str))) {} | ||||
| value_initializer::value_initializer(const char* str)       : value(tag_string(str)) {} | ||||
|  | ||||
| } | ||||
							
								
								
									
										22
									
								
								depends/libnbtplusplus/test/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								depends/libnbtplusplus/test/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| enable_testing() | ||||
| include_directories(${libnbt++_SOURCE_DIR}/include) | ||||
| include_directories(${CXXTEST_INCLUDE_DIR}) | ||||
|  | ||||
| CXXTEST_ADD_TEST(nbttest nbttest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/nbttest.h) | ||||
| target_link_libraries(nbttest nbt++) | ||||
|  | ||||
| CXXTEST_ADD_TEST(endian_str_test endian_str_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/endian_str_test.h) | ||||
| target_link_libraries(endian_str_test nbt++) | ||||
|  | ||||
| CXXTEST_ADD_TEST(read_test read_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/read_test.h) | ||||
| target_link_libraries(read_test nbt++) | ||||
| add_custom_command(TARGET read_test POST_BUILD | ||||
|     COMMAND ${CMAKE_COMMAND} -E | ||||
|     copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/testfiles ${CMAKE_CURRENT_BINARY_DIR}) | ||||
|  | ||||
| CXXTEST_ADD_TEST(write_test write_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/write_test.h) | ||||
| target_link_libraries(write_test nbt++) | ||||
|  | ||||
| add_executable(format_test format_test.cpp) | ||||
| target_link_libraries(format_test nbt++) | ||||
| add_test(format_test format_test) | ||||
							
								
								
									
										175
									
								
								depends/libnbtplusplus/test/endian_str_test.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								depends/libnbtplusplus/test/endian_str_test.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include <cxxtest/TestSuite.h> | ||||
| #include "endian_str.h" | ||||
| #include <cstdlib> | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
|  | ||||
| using namespace endian; | ||||
|  | ||||
| class endian_str_test : public CxxTest::TestSuite | ||||
| { | ||||
| public: | ||||
|     void test_uint() | ||||
|     { | ||||
|         std::stringstream str(std::ios::in | std::ios::out | std::ios::binary); | ||||
|  | ||||
|         write_little(str, uint8_t (0x01)); | ||||
|         write_little(str, uint16_t(0x0102)); | ||||
|         write       (str, uint32_t(0x01020304), endian::little); | ||||
|         write_little(str, uint64_t(0x0102030405060708)); | ||||
|  | ||||
|         write_big   (str, uint8_t (0x09)); | ||||
|         write_big   (str, uint16_t(0x090A)); | ||||
|         write_big   (str, uint32_t(0x090A0B0C)); | ||||
|         write       (str, uint64_t(0x090A0B0C0D0E0F10), endian::big); | ||||
|  | ||||
|         std::string expected{ | ||||
|             1, | ||||
|             2, 1, | ||||
|             4, 3, 2, 1, | ||||
|             8, 7, 6, 5, 4, 3, 2, 1, | ||||
|  | ||||
|             9, | ||||
|             9, 10, | ||||
|             9, 10, 11, 12, | ||||
|             9, 10, 11, 12, 13, 14, 15, 16 | ||||
|         }; | ||||
|         TS_ASSERT_EQUALS(str.str(), expected); | ||||
|  | ||||
|         uint8_t  u8; | ||||
|         uint16_t u16; | ||||
|         uint32_t u32; | ||||
|         uint64_t u64; | ||||
|  | ||||
|         read_little(str, u8); | ||||
|         TS_ASSERT_EQUALS(u8, 0x01); | ||||
|         read_little(str, u16); | ||||
|         TS_ASSERT_EQUALS(u16, 0x0102); | ||||
|         read_little(str, u32); | ||||
|         TS_ASSERT_EQUALS(u32, 0x01020304u); | ||||
|         read(str, u64, endian::little); | ||||
|         TS_ASSERT_EQUALS(u64, 0x0102030405060708u); | ||||
|  | ||||
|         read_big(str, u8); | ||||
|         TS_ASSERT_EQUALS(u8, 0x09); | ||||
|         read_big(str, u16); | ||||
|         TS_ASSERT_EQUALS(u16, 0x090A); | ||||
|         read(str, u32, endian::big); | ||||
|         TS_ASSERT_EQUALS(u32, 0x090A0B0Cu); | ||||
|         read_big(str, u64); | ||||
|         TS_ASSERT_EQUALS(u64, 0x090A0B0C0D0E0F10u); | ||||
|  | ||||
|         TS_ASSERT(str); //Check if stream has failed | ||||
|     } | ||||
|  | ||||
|     void test_sint() | ||||
|     { | ||||
|         std::stringstream str(std::ios::in | std::ios::out | std::ios::binary); | ||||
|  | ||||
|         write_little(str, int8_t (-0x01)); | ||||
|         write_little(str, int16_t(-0x0102)); | ||||
|         write_little(str, int32_t(-0x01020304)); | ||||
|         write       (str, int64_t(-0x0102030405060708), endian::little); | ||||
|  | ||||
|         write_big   (str, int8_t (-0x09)); | ||||
|         write_big   (str, int16_t(-0x090A)); | ||||
|         write       (str, int32_t(-0x090A0B0C), endian::big); | ||||
|         write_big   (str, int64_t(-0x090A0B0C0D0E0F10)); | ||||
|  | ||||
|         std::string expected{ //meh, stupid narrowing conversions | ||||
|             '\xFF', | ||||
|             '\xFE', '\xFE', | ||||
|             '\xFC', '\xFC', '\xFD', '\xFE', | ||||
|             '\xF8', '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', | ||||
|  | ||||
|             '\xF7', | ||||
|             '\xF6', '\xF6', | ||||
|             '\xF6', '\xF5', '\xF4', '\xF4', | ||||
|             '\xF6', '\xF5', '\xF4', '\xF3', '\xF2', '\xF1', '\xF0', '\xF0' | ||||
|         }; | ||||
|         TS_ASSERT_EQUALS(str.str(), expected); | ||||
|  | ||||
|         int8_t  i8; | ||||
|         int16_t i16; | ||||
|         int32_t i32; | ||||
|         int64_t i64; | ||||
|  | ||||
|         read_little(str, i8); | ||||
|         TS_ASSERT_EQUALS(i8, -0x01); | ||||
|         read_little(str, i16); | ||||
|         TS_ASSERT_EQUALS(i16, -0x0102); | ||||
|         read(str, i32, endian::little); | ||||
|         TS_ASSERT_EQUALS(i32, -0x01020304); | ||||
|         read_little(str, i64); | ||||
|         TS_ASSERT_EQUALS(i64, -0x0102030405060708); | ||||
|  | ||||
|         read_big(str, i8); | ||||
|         TS_ASSERT_EQUALS(i8, -0x09); | ||||
|         read_big(str, i16); | ||||
|         TS_ASSERT_EQUALS(i16, -0x090A); | ||||
|         read_big(str, i32); | ||||
|         TS_ASSERT_EQUALS(i32, -0x090A0B0C); | ||||
|         read(str, i64, endian::big); | ||||
|         TS_ASSERT_EQUALS(i64, -0x090A0B0C0D0E0F10); | ||||
|  | ||||
|         TS_ASSERT(str); //Check if stream has failed | ||||
|     } | ||||
|  | ||||
|     void test_float() | ||||
|     { | ||||
|         std::stringstream str(std::ios::in | std::ios::out | std::ios::binary); | ||||
|  | ||||
|         //C99 has hexadecimal floating point literals, C++ doesn't... | ||||
|         const float fconst = std::stof("-0xCDEF01p-63"); //-1.46325e-012 | ||||
|         const double dconst = std::stod("-0x1DEF0102030405p-375"); //-1.09484e-097 | ||||
|         //We will be assuming IEEE 754 here | ||||
|  | ||||
|         write_little(str, fconst); | ||||
|         write_little(str, dconst); | ||||
|         write_big   (str, fconst); | ||||
|         write_big   (str, dconst); | ||||
|  | ||||
|         std::string expected{ | ||||
|             '\x01', '\xEF', '\xCD', '\xAB', | ||||
|             '\x05', '\x04', '\x03', '\x02', '\x01', '\xEF', '\xCD', '\xAB', | ||||
|  | ||||
|             '\xAB', '\xCD', '\xEF', '\x01', | ||||
|             '\xAB', '\xCD', '\xEF', '\x01', '\x02', '\x03', '\x04', '\x05' | ||||
|         }; | ||||
|         TS_ASSERT_EQUALS(str.str(), expected); | ||||
|  | ||||
|         float f; | ||||
|         double d; | ||||
|  | ||||
|         read_little(str, f); | ||||
|         TS_ASSERT_EQUALS(f, fconst); | ||||
|         read_little(str, d); | ||||
|         TS_ASSERT_EQUALS(d, dconst); | ||||
|  | ||||
|         read_big(str, f); | ||||
|         TS_ASSERT_EQUALS(f, fconst); | ||||
|         read_big(str, d); | ||||
|         TS_ASSERT_EQUALS(d, dconst); | ||||
|  | ||||
|         TS_ASSERT(str); //Check if stream has failed | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										81
									
								
								depends/libnbtplusplus/test/format_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								depends/libnbtplusplus/test/format_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| //#include "text/json_formatter.h" | ||||
| //#include "io/stream_reader.h" | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <limits> | ||||
| #include "nbt_tags.h" | ||||
|  | ||||
| using namespace nbt; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     //TODO: Write that into a file | ||||
|     tag_compound comp{ | ||||
|         {"byte", tag_byte(-128)}, | ||||
|         {"short", tag_short(-32768)}, | ||||
|         {"int", tag_int(-2147483648)}, | ||||
|         {"long", tag_long(-9223372036854775808U)}, | ||||
|  | ||||
|         {"float 1", 1.618034f}, | ||||
|         {"float 2", 6.626070e-34f}, | ||||
|         {"float 3", 2.273737e+29f}, | ||||
|         {"float 4", -std::numeric_limits<float>::infinity()}, | ||||
|         {"float 5", std::numeric_limits<float>::quiet_NaN()}, | ||||
|  | ||||
|         {"double 1", 3.141592653589793}, | ||||
|         {"double 2", 1.749899444387479e-193}, | ||||
|         {"double 3", 2.850825855152578e+175}, | ||||
|         {"double 4", -std::numeric_limits<double>::infinity()}, | ||||
|         {"double 5", std::numeric_limits<double>::quiet_NaN()}, | ||||
|  | ||||
|         {"string 1", "Hello World! \u00E4\u00F6\u00FC\u00DF"}, | ||||
|         {"string 2", "String with\nline breaks\tand tabs"}, | ||||
|  | ||||
|         {"byte array", tag_byte_array{12, 13, 14, 15, 16}}, | ||||
|         {"int array", tag_int_array{0x0badc0de, -0x0dedbeef, 0x1badbabe}}, | ||||
|  | ||||
|         {"list (empty)", tag_list::of<tag_byte_array>({})}, | ||||
|         {"list (float)", tag_list{2.0f, 1.0f, 0.5f, 0.25f}}, | ||||
|         {"list (list)", tag_list::of<tag_list>({ | ||||
|             {}, | ||||
|             {4, 5, 6}, | ||||
|             {tag_compound{{"egg", "ham"}}, tag_compound{{"foo", "bar"}}} | ||||
|         })}, | ||||
|         {"list (compound)", tag_list::of<tag_compound>({ | ||||
|             {{"created-on", 42}, {"names", tag_list{"Compound", "tag", "#0"}}}, | ||||
|             {{"created-on", 45}, {"names", tag_list{"Compound", "tag", "#1"}}} | ||||
|         })}, | ||||
|  | ||||
|         {"compound (empty)", tag_compound()}, | ||||
|         {"compound (nested)", tag_compound{ | ||||
|             {"key", "value"}, | ||||
|             {"key with \u00E4\u00F6\u00FC", tag_byte(-1)}, | ||||
|             {"key with\nnewline and\ttab", tag_compound{}} | ||||
|         }}, | ||||
|  | ||||
|         {"null", nullptr} | ||||
|     }; | ||||
|  | ||||
|     std::cout << "----- default operator<<:\n"; | ||||
|     std::cout << comp; | ||||
|     std::cout << "\n-----" << std::endl; | ||||
| } | ||||
							
								
								
									
										476
									
								
								depends/libnbtplusplus/test/nbttest.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										476
									
								
								depends/libnbtplusplus/test/nbttest.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,476 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include <cxxtest/TestSuite.h> | ||||
| #include "nbt_tags.h" | ||||
| #include "nbt_visitor.h" | ||||
| #include <algorithm> | ||||
| #include <set> | ||||
| #include <stdexcept> | ||||
|  | ||||
| using namespace nbt; | ||||
|  | ||||
| class nbttest : public CxxTest::TestSuite | ||||
| { | ||||
| public: | ||||
|     void test_tag() | ||||
|     { | ||||
|         TS_ASSERT(!is_valid_type(-1)); | ||||
|         TS_ASSERT(!is_valid_type(0)); | ||||
|         TS_ASSERT(is_valid_type(0, true)); | ||||
|         TS_ASSERT(is_valid_type(1)); | ||||
|         TS_ASSERT(is_valid_type(5, false)); | ||||
|         TS_ASSERT(is_valid_type(7, true)); | ||||
|         TS_ASSERT(is_valid_type(11)); | ||||
|         TS_ASSERT(!is_valid_type(12)); | ||||
|  | ||||
|         //looks like TS_ASSERT_EQUALS can't handle abstract classes... | ||||
|         TS_ASSERT(*tag::create(tag_type::Byte) == tag_byte()); | ||||
|         TS_ASSERT_THROWS(tag::create(tag_type::Null), std::invalid_argument); | ||||
|         TS_ASSERT_THROWS(tag::create(tag_type::End), std::invalid_argument); | ||||
|  | ||||
|         tag_string tstr("foo"); | ||||
|         auto cl = tstr.clone(); | ||||
|         TS_ASSERT_EQUALS(tstr.get(), "foo"); | ||||
|         TS_ASSERT(tstr == *cl); | ||||
|  | ||||
|         cl = std::move(tstr).clone(); | ||||
|         TS_ASSERT(*cl == tag_string("foo")); | ||||
|         TS_ASSERT(*cl != tag_string("bar")); | ||||
|  | ||||
|         cl = std::move(*cl).move_clone(); | ||||
|         TS_ASSERT(*cl == tag_string("foo")); | ||||
|  | ||||
|         tstr.assign(tag_string("bar")); | ||||
|         TS_ASSERT_THROWS(tstr.assign(tag_int(6)), std::bad_cast); | ||||
|         TS_ASSERT_EQUALS(tstr.get(), "bar"); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(&tstr.as<tag_string>(), &tstr); | ||||
|         TS_ASSERT_THROWS(tstr.as<tag_byte_array>(), std::bad_cast); | ||||
|     } | ||||
|  | ||||
|     void test_get_type() | ||||
|     { | ||||
|         TS_ASSERT_EQUALS(tag_byte().get_type()      , tag_type::Byte); | ||||
|         TS_ASSERT_EQUALS(tag_short().get_type()     , tag_type::Short); | ||||
|         TS_ASSERT_EQUALS(tag_int().get_type()       , tag_type::Int); | ||||
|         TS_ASSERT_EQUALS(tag_long().get_type()      , tag_type::Long); | ||||
|         TS_ASSERT_EQUALS(tag_float().get_type()     , tag_type::Float); | ||||
|         TS_ASSERT_EQUALS(tag_double().get_type()    , tag_type::Double); | ||||
|         TS_ASSERT_EQUALS(tag_byte_array().get_type(), tag_type::Byte_Array); | ||||
|         TS_ASSERT_EQUALS(tag_string().get_type()    , tag_type::String); | ||||
|         TS_ASSERT_EQUALS(tag_list().get_type()      , tag_type::List); | ||||
|         TS_ASSERT_EQUALS(tag_compound().get_type()  , tag_type::Compound); | ||||
|         TS_ASSERT_EQUALS(tag_int_array().get_type() , tag_type::Int_Array); | ||||
|     } | ||||
|  | ||||
|     void test_tag_primitive() | ||||
|     { | ||||
|         tag_int tag(6); | ||||
|         TS_ASSERT_EQUALS(tag.get(), 6); | ||||
|         int& ref = tag; | ||||
|         ref = 12; | ||||
|         TS_ASSERT(tag == 12); | ||||
|         TS_ASSERT(tag != 6); | ||||
|         tag.set(24); | ||||
|         TS_ASSERT_EQUALS(ref, 24); | ||||
|         tag = 7; | ||||
|         TS_ASSERT_EQUALS(static_cast<int>(tag), 7); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(tag, tag_int(7)); | ||||
|         TS_ASSERT_DIFFERS(tag_float(2.5), tag_float(-2.5)); | ||||
|         TS_ASSERT_DIFFERS(tag_float(2.5), tag_double(2.5)); | ||||
|  | ||||
|         TS_ASSERT(tag_double() == 0.0); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(tag_byte(INT8_MAX).get(), INT8_MAX); | ||||
|         TS_ASSERT_EQUALS(tag_byte(INT8_MIN).get(), INT8_MIN); | ||||
|         TS_ASSERT_EQUALS(tag_short(INT16_MAX).get(), INT16_MAX); | ||||
|         TS_ASSERT_EQUALS(tag_short(INT16_MIN).get(), INT16_MIN); | ||||
|         TS_ASSERT_EQUALS(tag_int(INT32_MAX).get(), INT32_MAX); | ||||
|         TS_ASSERT_EQUALS(tag_int(INT32_MIN).get(), INT32_MIN); | ||||
|         TS_ASSERT_EQUALS(tag_long(INT64_MAX).get(), INT64_MAX); | ||||
|         TS_ASSERT_EQUALS(tag_long(INT64_MIN).get(), INT64_MIN); | ||||
|     } | ||||
|  | ||||
|     void test_tag_string() | ||||
|     { | ||||
|         tag_string tag("foo"); | ||||
|         TS_ASSERT_EQUALS(tag.get(), "foo"); | ||||
|         std::string& ref = tag; | ||||
|         ref = "bar"; | ||||
|         TS_ASSERT_EQUALS(tag.get(), "bar"); | ||||
|         TS_ASSERT_DIFFERS(tag.get(), "foo"); | ||||
|         tag.set("baz"); | ||||
|         TS_ASSERT_EQUALS(ref, "baz"); | ||||
|         tag = "quux"; | ||||
|         TS_ASSERT_EQUALS("quux", static_cast<std::string>(tag)); | ||||
|         std::string str("foo"); | ||||
|         tag = str; | ||||
|         TS_ASSERT_EQUALS(tag.get(),str); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(tag_string(str).get(), "foo"); | ||||
|         TS_ASSERT_EQUALS(tag_string().get(), ""); | ||||
|     } | ||||
|  | ||||
|     void test_tag_compound() | ||||
|     { | ||||
|         tag_compound comp{ | ||||
|             {"foo", int16_t(12)}, | ||||
|             {"bar", "baz"}, | ||||
|             {"baz", -2.0}, | ||||
|             {"list", tag_list{16, 17}} | ||||
|         }; | ||||
|  | ||||
|         //Test assignments and conversions, and exceptions on bad conversions | ||||
|         TS_ASSERT_EQUALS(comp["foo"].get_type(), tag_type::Short); | ||||
|         TS_ASSERT_EQUALS(static_cast<int32_t>(comp["foo"]), 12); | ||||
|         TS_ASSERT_EQUALS(static_cast<int16_t>(comp.at("foo")), int16_t(12)); | ||||
|         TS_ASSERT(comp["foo"] == tag_short(12)); | ||||
|         TS_ASSERT_THROWS(static_cast<int8_t>(comp["foo"]), std::bad_cast); | ||||
|         TS_ASSERT_THROWS(static_cast<std::string>(comp["foo"]), std::bad_cast); | ||||
|  | ||||
|         TS_ASSERT_THROWS(comp["foo"] = 32, std::bad_cast); | ||||
|         comp["foo"] = int8_t(32); | ||||
|         TS_ASSERT_EQUALS(static_cast<int16_t>(comp["foo"]), 32); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(comp["bar"].get_type(), tag_type::String); | ||||
|         TS_ASSERT_EQUALS(static_cast<std::string>(comp["bar"]), "baz"); | ||||
|         TS_ASSERT_THROWS(static_cast<int>(comp["bar"]), std::bad_cast); | ||||
|  | ||||
|         TS_ASSERT_THROWS(comp["bar"] = -128, std::bad_cast); | ||||
|         comp["bar"] = "barbaz"; | ||||
|         TS_ASSERT_EQUALS(static_cast<std::string>(comp["bar"]), "barbaz"); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(comp["baz"].get_type(), tag_type::Double); | ||||
|         TS_ASSERT_EQUALS(static_cast<double>(comp["baz"]), -2.0); | ||||
|         TS_ASSERT_THROWS(static_cast<float>(comp["baz"]), std::bad_cast); | ||||
|  | ||||
|         //Test nested access | ||||
|         comp["quux"] = tag_compound{{"Hello", "World"}, {"zero", 0}}; | ||||
|         TS_ASSERT_EQUALS(comp.at("quux").get_type(), tag_type::Compound); | ||||
|         TS_ASSERT_EQUALS(static_cast<std::string>(comp["quux"].at("Hello")), "World"); | ||||
|         TS_ASSERT_EQUALS(static_cast<std::string>(comp["quux"]["Hello"]), "World"); | ||||
|         TS_ASSERT(comp["list"][1] == tag_int(17)); | ||||
|  | ||||
|         TS_ASSERT_THROWS(comp.at("nothing"), std::out_of_range); | ||||
|  | ||||
|         //Test equality comparisons | ||||
|         tag_compound comp2{ | ||||
|             {"foo", int16_t(32)}, | ||||
|             {"bar", "barbaz"}, | ||||
|             {"baz", -2.0}, | ||||
|             {"quux", tag_compound{{"Hello", "World"}, {"zero", 0}}}, | ||||
|             {"list", tag_list{16, 17}} | ||||
|         }; | ||||
|         TS_ASSERT(comp == comp2); | ||||
|         TS_ASSERT(comp != dynamic_cast<const tag_compound&>(comp2["quux"].get())); | ||||
|         TS_ASSERT(comp != comp2["quux"]); | ||||
|         TS_ASSERT(dynamic_cast<const tag_compound&>(comp["quux"].get()) == comp2["quux"]); | ||||
|  | ||||
|         //Test whether begin() through end() goes through all the keys and their | ||||
|         //values.  The order of iteration is irrelevant there. | ||||
|         std::set<std::string> keys{"bar", "baz", "foo", "list", "quux"}; | ||||
|         TS_ASSERT_EQUALS(comp2.size(), keys.size()); | ||||
|         unsigned int i = 0; | ||||
|         for(const std::pair<const std::string, value>& val: comp2) | ||||
|         { | ||||
|             TS_ASSERT_LESS_THAN(i, comp2.size()); | ||||
|             TS_ASSERT(keys.count(val.first)); | ||||
|             TS_ASSERT(val.second == comp2[val.first]); | ||||
|             ++i; | ||||
|         } | ||||
|         TS_ASSERT_EQUALS(i, comp2.size()); | ||||
|  | ||||
|         //Test erasing and has_key | ||||
|         TS_ASSERT_EQUALS(comp.erase("nothing"), false); | ||||
|         TS_ASSERT(comp.has_key("quux")); | ||||
|         TS_ASSERT(comp.has_key("quux", tag_type::Compound)); | ||||
|         TS_ASSERT(!comp.has_key("quux", tag_type::List)); | ||||
|         TS_ASSERT(!comp.has_key("quux", tag_type::Null)); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(comp.erase("quux"), true); | ||||
|         TS_ASSERT(!comp.has_key("quux")); | ||||
|         TS_ASSERT(!comp.has_key("quux", tag_type::Compound)); | ||||
|         TS_ASSERT(!comp.has_key("quux", tag_type::Null)); | ||||
|  | ||||
|         comp.clear(); | ||||
|         TS_ASSERT(comp == tag_compound{}); | ||||
|  | ||||
|         //Test inserting values | ||||
|         TS_ASSERT_EQUALS(comp.put("abc", tag_double(6.0)).second, true); | ||||
|         TS_ASSERT_EQUALS(comp.put("abc", tag_long(-28)).second, false); | ||||
|         TS_ASSERT_EQUALS(comp.insert("ghi", tag_string("world")).second, true); | ||||
|         TS_ASSERT_EQUALS(comp.insert("abc", tag_string("hello")).second, false); | ||||
|         TS_ASSERT_EQUALS(comp.emplace<tag_string>("def", "ghi").second, true); | ||||
|         TS_ASSERT_EQUALS(comp.emplace<tag_byte>("def", 4).second, false); | ||||
|         TS_ASSERT((comp == tag_compound{ | ||||
|             {"abc", tag_long(-28)}, | ||||
|             {"def", tag_byte(4)}, | ||||
|             {"ghi", tag_string("world")} | ||||
|         })); | ||||
|     } | ||||
|  | ||||
|     void test_value() | ||||
|     { | ||||
|         value val1; | ||||
|         value val2(make_unique<tag_int>(42)); | ||||
|         value val3(tag_int(42)); | ||||
|  | ||||
|         TS_ASSERT(!val1 && val2 && val3); | ||||
|         TS_ASSERT(val1 == val1); | ||||
|         TS_ASSERT(val1 != val2); | ||||
|         TS_ASSERT(val2 == val3); | ||||
|         TS_ASSERT(val3 == val3); | ||||
|  | ||||
|         value valstr(tag_string("foo")); | ||||
|         TS_ASSERT_EQUALS(static_cast<std::string>(valstr), "foo"); | ||||
|         valstr = "bar"; | ||||
|         TS_ASSERT_THROWS(valstr = 5, std::bad_cast); | ||||
|         TS_ASSERT_EQUALS(static_cast<std::string>(valstr), "bar"); | ||||
|         TS_ASSERT(valstr.as<tag_string>() == "bar"); | ||||
|         TS_ASSERT_EQUALS(&valstr.as<tag>(), &valstr.get()); | ||||
|         TS_ASSERT_THROWS(valstr.as<tag_float>(), std::bad_cast); | ||||
|  | ||||
|         val1 = int64_t(42); | ||||
|         TS_ASSERT(val2 != val1); | ||||
|  | ||||
|         TS_ASSERT_THROWS(val2 = int64_t(12), std::bad_cast); | ||||
|         TS_ASSERT_EQUALS(static_cast<int64_t>(val2), 42); | ||||
|         tag_int* ptr = dynamic_cast<tag_int*>(val2.get_ptr().get()); | ||||
|         TS_ASSERT(*ptr == 42); | ||||
|         val2 = 52; | ||||
|         TS_ASSERT_EQUALS(static_cast<int32_t>(val2), 52); | ||||
|         TS_ASSERT(*ptr == 52); | ||||
|  | ||||
|         TS_ASSERT_THROWS(val1["foo"], std::bad_cast); | ||||
|         TS_ASSERT_THROWS(val1.at("foo"), std::bad_cast); | ||||
|  | ||||
|         val3 = 52; | ||||
|         TS_ASSERT(val2 == val3); | ||||
|         TS_ASSERT(val2.get_ptr() != val3.get_ptr()); | ||||
|  | ||||
|         val3 = std::move(val2); | ||||
|         TS_ASSERT(val3 == tag_int(52)); | ||||
|         TS_ASSERT(!val2); | ||||
|  | ||||
|         tag_int& tag = dynamic_cast<tag_int&>(val3.get()); | ||||
|         TS_ASSERT(tag == tag_int(52)); | ||||
|         tag = 21; | ||||
|         TS_ASSERT_EQUALS(static_cast<int32_t>(val3), 21); | ||||
|         val1.set_ptr(std::move(val3.get_ptr())); | ||||
|         TS_ASSERT(val1.as<tag_int>() == 21); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(val1.get_type(), tag_type::Int); | ||||
|         TS_ASSERT_EQUALS(val2.get_type(), tag_type::Null); | ||||
|         TS_ASSERT_EQUALS(val3.get_type(), tag_type::Null); | ||||
|  | ||||
|         val2 = val1; | ||||
|         val1 = val3; | ||||
|         TS_ASSERT(!val1 && val2 && !val3); | ||||
|         TS_ASSERT(val1.get_ptr() == nullptr); | ||||
|         TS_ASSERT(val2.get() == tag_int(21)); | ||||
|         TS_ASSERT(value(val1) == val1); | ||||
|         TS_ASSERT(value(val2) == val2); | ||||
|         val1 = val1; | ||||
|         val2 = val2; | ||||
|         TS_ASSERT(!val1); | ||||
|         TS_ASSERT(val1 == value_initializer(nullptr)); | ||||
|         TS_ASSERT(val2 == tag_int(21)); | ||||
|  | ||||
|         val3 = tag_short(2); | ||||
|         TS_ASSERT_THROWS(val3 = tag_string("foo"), std::bad_cast); | ||||
|         TS_ASSERT(val3.get() == tag_short(2)); | ||||
|  | ||||
|         val2.set_ptr(make_unique<tag_string>("foo")); | ||||
|         TS_ASSERT(val2 == tag_string("foo")); | ||||
|     } | ||||
|  | ||||
|     void test_tag_list() | ||||
|     { | ||||
|         tag_list list; | ||||
|         TS_ASSERT_EQUALS(list.el_type(), tag_type::Null); | ||||
|         TS_ASSERT_THROWS(list.push_back(value(nullptr)), std::invalid_argument); | ||||
|  | ||||
|         list.emplace_back<tag_string>("foo"); | ||||
|         TS_ASSERT_EQUALS(list.el_type(), tag_type::String); | ||||
|         list.push_back(tag_string("bar")); | ||||
|         TS_ASSERT_THROWS(list.push_back(tag_int(42)), std::invalid_argument); | ||||
|         TS_ASSERT_THROWS(list.emplace_back<tag_compound>(), std::invalid_argument); | ||||
|  | ||||
|         TS_ASSERT((list == tag_list{"foo", "bar"})); | ||||
|         TS_ASSERT(list[0] == tag_string("foo")); | ||||
|         TS_ASSERT_EQUALS(static_cast<std::string>(list.at(1)), "bar"); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(list.size(), 2u); | ||||
|         TS_ASSERT_THROWS(list.at(2), std::out_of_range); | ||||
|         TS_ASSERT_THROWS(list.at(-1), std::out_of_range); | ||||
|  | ||||
|         list.set(1, value(tag_string("baz"))); | ||||
|         TS_ASSERT_THROWS(list.set(1, value(nullptr)), std::invalid_argument); | ||||
|         TS_ASSERT_THROWS(list.set(1, value(tag_int(-42))), std::invalid_argument); | ||||
|         TS_ASSERT_EQUALS(static_cast<std::string>(list[1]), "baz"); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(list.size(), 2u); | ||||
|         tag_string values[] = {"foo", "baz"}; | ||||
|         TS_ASSERT_EQUALS(list.end() - list.begin(), int(list.size())); | ||||
|         TS_ASSERT(std::equal(list.begin(), list.end(), values)); | ||||
|  | ||||
|         list.pop_back(); | ||||
|         TS_ASSERT(list == tag_list{"foo"}); | ||||
|         TS_ASSERT(list == tag_list::of<tag_string>({"foo"})); | ||||
|         TS_ASSERT(tag_list::of<tag_string>({"foo"}) == tag_list{"foo"}); | ||||
|         TS_ASSERT((list != tag_list{2, 3, 5, 7})); | ||||
|  | ||||
|         list.clear(); | ||||
|         TS_ASSERT_EQUALS(list.size(), 0u); | ||||
|         TS_ASSERT_EQUALS(list.el_type(), tag_type::String) | ||||
|         TS_ASSERT_THROWS(list.push_back(tag_short(25)), std::invalid_argument); | ||||
|         TS_ASSERT_THROWS(list.push_back(value(nullptr)), std::invalid_argument); | ||||
|  | ||||
|         list.reset(); | ||||
|         TS_ASSERT_EQUALS(list.el_type(), tag_type::Null); | ||||
|         list.emplace_back<tag_int>(17); | ||||
|         TS_ASSERT_EQUALS(list.el_type(), tag_type::Int); | ||||
|  | ||||
|         list.reset(tag_type::Float); | ||||
|         TS_ASSERT_EQUALS(list.el_type(), tag_type::Float); | ||||
|         list.emplace_back<tag_float>(17.0f); | ||||
|         TS_ASSERT(list == tag_list({17.0f})); | ||||
|  | ||||
|         TS_ASSERT(tag_list() != tag_list(tag_type::Int)); | ||||
|         TS_ASSERT(tag_list() == tag_list()); | ||||
|         TS_ASSERT(tag_list(tag_type::Short) != tag_list(tag_type::Int)); | ||||
|         TS_ASSERT(tag_list(tag_type::Short) == tag_list(tag_type::Short)); | ||||
|  | ||||
|         tag_list short_list = tag_list::of<tag_short>({25, 36}); | ||||
|         TS_ASSERT_EQUALS(short_list.el_type(), tag_type::Short); | ||||
|         TS_ASSERT((short_list == tag_list{int16_t(25), int16_t(36)})); | ||||
|         TS_ASSERT((short_list != tag_list{25, 36})); | ||||
|         TS_ASSERT((short_list == tag_list{value(tag_short(25)), value(tag_short(36))})); | ||||
|  | ||||
|         TS_ASSERT_THROWS((tag_list{value(tag_byte(4)), value(tag_int(5))}), std::invalid_argument); | ||||
|         TS_ASSERT_THROWS((tag_list{value(nullptr), value(tag_int(6))}), std::invalid_argument); | ||||
|         TS_ASSERT_THROWS((tag_list{value(tag_int(7)), value(tag_int(8)), value(nullptr)}), std::invalid_argument); | ||||
|         TS_ASSERT_EQUALS((tag_list(std::initializer_list<value>{})).el_type(), tag_type::Null); | ||||
|         TS_ASSERT_EQUALS((tag_list{2, 3, 5, 7}).el_type(), tag_type::Int); | ||||
|     } | ||||
|  | ||||
|     void test_tag_byte_array() | ||||
|     { | ||||
|         std::vector<int8_t> vec{1, 2, 127, -128}; | ||||
|         tag_byte_array arr{1, 2, 127, -128}; | ||||
|         TS_ASSERT_EQUALS(arr.size(), 4u); | ||||
|         TS_ASSERT(arr.at(0) == 1 && arr[1] == 2 && arr[2] == 127 && arr.at(3) == -128); | ||||
|         TS_ASSERT_THROWS(arr.at(-1), std::out_of_range); | ||||
|         TS_ASSERT_THROWS(arr.at(4), std::out_of_range); | ||||
|  | ||||
|         TS_ASSERT(arr.get() == vec); | ||||
|         TS_ASSERT(arr == tag_byte_array(std::vector<int8_t>(vec))); | ||||
|  | ||||
|         arr.push_back(42); | ||||
|         vec.push_back(42); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(arr.size(), 5u); | ||||
|         TS_ASSERT_EQUALS(arr.end() - arr.begin(), int(arr.size())); | ||||
|         TS_ASSERT(std::equal(arr.begin(), arr.end(), vec.begin())); | ||||
|  | ||||
|         arr.pop_back(); | ||||
|         arr.pop_back(); | ||||
|         TS_ASSERT_EQUALS(arr.size(), 3u); | ||||
|         TS_ASSERT((arr == tag_byte_array{1, 2, 127})); | ||||
|         TS_ASSERT((arr != tag_int_array{1, 2, 127})); | ||||
|         TS_ASSERT((arr != tag_byte_array{1, 2, -1})); | ||||
|  | ||||
|         arr.clear(); | ||||
|         TS_ASSERT(arr == tag_byte_array()); | ||||
|     } | ||||
|  | ||||
|     void test_tag_int_array() | ||||
|     { | ||||
|         std::vector<int32_t> vec{100, 200, INT32_MAX, INT32_MIN}; | ||||
|         tag_int_array arr{100, 200, INT32_MAX, INT32_MIN}; | ||||
|         TS_ASSERT_EQUALS(arr.size(), 4u); | ||||
|         TS_ASSERT(arr.at(0) == 100 && arr[1] == 200 && arr[2] == INT32_MAX && arr.at(3) == INT32_MIN); | ||||
|         TS_ASSERT_THROWS(arr.at(-1), std::out_of_range); | ||||
|         TS_ASSERT_THROWS(arr.at(4), std::out_of_range); | ||||
|  | ||||
|         TS_ASSERT(arr.get() == vec); | ||||
|         TS_ASSERT(arr == tag_int_array(std::vector<int32_t>(vec))); | ||||
|  | ||||
|         arr.push_back(42); | ||||
|         vec.push_back(42); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(arr.size(), 5u); | ||||
|         TS_ASSERT_EQUALS(arr.end() - arr.begin(), int(arr.size())); | ||||
|         TS_ASSERT(std::equal(arr.begin(), arr.end(), vec.begin())); | ||||
|  | ||||
|         arr.pop_back(); | ||||
|         arr.pop_back(); | ||||
|         TS_ASSERT_EQUALS(arr.size(), 3u); | ||||
|         TS_ASSERT((arr == tag_int_array{100, 200, INT32_MAX})); | ||||
|         TS_ASSERT((arr != tag_int_array{100, -56, -1})); | ||||
|  | ||||
|         arr.clear(); | ||||
|         TS_ASSERT(arr == tag_int_array()); | ||||
|     } | ||||
|  | ||||
|     void test_visitor() | ||||
|     { | ||||
|         struct : public nbt_visitor | ||||
|         { | ||||
|             tag_type visited = tag_type::Null; | ||||
|  | ||||
|             void visit(tag_byte& tag)       { visited = tag_type::Byte; } | ||||
|             void visit(tag_short& tag)      { visited = tag_type::Short; } | ||||
|             void visit(tag_int& tag)        { visited = tag_type::Int; } | ||||
|             void visit(tag_long& tag)       { visited = tag_type::Long; } | ||||
|             void visit(tag_float& tag)      { visited = tag_type::Float; } | ||||
|             void visit(tag_double& tag)     { visited = tag_type::Double; } | ||||
|             void visit(tag_byte_array& tag) { visited = tag_type::Byte_Array; } | ||||
|             void visit(tag_string& tag)     { visited = tag_type::String; } | ||||
|             void visit(tag_list& tag)       { visited = tag_type::List; } | ||||
|             void visit(tag_compound& tag)   { visited = tag_type::Compound; } | ||||
|             void visit(tag_int_array& tag)  { visited = tag_type::Int_Array; } | ||||
|         } v; | ||||
|  | ||||
|         tag_byte().accept(v); | ||||
|         TS_ASSERT_EQUALS(v.visited, tag_type::Byte); | ||||
|         tag_short().accept(v); | ||||
|         TS_ASSERT_EQUALS(v.visited, tag_type::Short); | ||||
|         tag_int().accept(v); | ||||
|         TS_ASSERT_EQUALS(v.visited, tag_type::Int); | ||||
|         tag_long().accept(v); | ||||
|         TS_ASSERT_EQUALS(v.visited, tag_type::Long); | ||||
|         tag_float().accept(v); | ||||
|         TS_ASSERT_EQUALS(v.visited, tag_type::Float); | ||||
|         tag_double().accept(v); | ||||
|         TS_ASSERT_EQUALS(v.visited, tag_type::Double); | ||||
|         tag_byte_array().accept(v); | ||||
|         TS_ASSERT_EQUALS(v.visited, tag_type::Byte_Array); | ||||
|         tag_string().accept(v); | ||||
|         TS_ASSERT_EQUALS(v.visited, tag_type::String); | ||||
|         tag_list().accept(v); | ||||
|         TS_ASSERT_EQUALS(v.visited, tag_type::List); | ||||
|         tag_compound().accept(v); | ||||
|         TS_ASSERT_EQUALS(v.visited, tag_type::Compound); | ||||
|         tag_int_array().accept(v); | ||||
|         TS_ASSERT_EQUALS(v.visited, tag_type::Int_Array); | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										216
									
								
								depends/libnbtplusplus/test/read_test.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								depends/libnbtplusplus/test/read_test.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,216 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include <cxxtest/TestSuite.h> | ||||
| #include "io/stream_reader.h" | ||||
| #include "nbt_tags.h" | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
|  | ||||
| using namespace nbt; | ||||
|  | ||||
| class read_test : public CxxTest::TestSuite | ||||
| { | ||||
| public: | ||||
|     void test_stream_reader_big() | ||||
|     { | ||||
|         std::string input{ | ||||
|             1, //tag_type::Byte | ||||
|             0, //tag_type::End | ||||
|             11, //tag_type::Int_Array | ||||
|  | ||||
|             0x0a, 0x0b, 0x0c, 0x0d, //0x0a0b0c0d in Big Endian | ||||
|  | ||||
|             0x00, 0x06, //String length in Big Endian | ||||
|             'f', 'o', 'o', 'b', 'a', 'r', | ||||
|  | ||||
|             0 //tag_type::End (invalid with allow_end = false) | ||||
|         }; | ||||
|         std::istringstream is(input); | ||||
|         nbt::io::stream_reader reader(is); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(&reader.get_istr(), &is); | ||||
|         TS_ASSERT_EQUALS(reader.get_endian(), endian::big); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(reader.read_type(), tag_type::Byte); | ||||
|         TS_ASSERT_EQUALS(reader.read_type(true), tag_type::End); | ||||
|         TS_ASSERT_EQUALS(reader.read_type(false), tag_type::Int_Array); | ||||
|  | ||||
|         int32_t i; | ||||
|         reader.read_num(i); | ||||
|         TS_ASSERT_EQUALS(i, 0x0a0b0c0d); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(reader.read_string(), "foobar"); | ||||
|  | ||||
|         TS_ASSERT_THROWS(reader.read_type(false), io::input_error); | ||||
|         TS_ASSERT(!is); | ||||
|         is.clear(); | ||||
|  | ||||
|         //Test for invalid tag type 12 | ||||
|         is.str("\x0c"); | ||||
|         TS_ASSERT_THROWS(reader.read_type(), io::input_error); | ||||
|         TS_ASSERT(!is); | ||||
|         is.clear(); | ||||
|  | ||||
|         //Test for unexpcted EOF on numbers (input too short for int32_t) | ||||
|         is.str("\x03\x04"); | ||||
|         reader.read_num(i); | ||||
|         TS_ASSERT(!is); | ||||
|     } | ||||
|  | ||||
|     void test_stream_reader_little() | ||||
|     { | ||||
|         std::string input{ | ||||
|             0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, //0x0d0c0b0a09080706 in Little Endian | ||||
|  | ||||
|             0x06, 0x00, //String length in Little Endian | ||||
|             'f', 'o', 'o', 'b', 'a', 'r', | ||||
|  | ||||
|             0x10, 0x00, //String length (intentionally too large) | ||||
|             'a', 'b', 'c', 'd' //unexpected EOF | ||||
|         }; | ||||
|         std::istringstream is(input); | ||||
|         nbt::io::stream_reader reader(is, endian::little); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(reader.get_endian(), endian::little); | ||||
|  | ||||
|         int64_t i; | ||||
|         reader.read_num(i); | ||||
|         TS_ASSERT_EQUALS(i, 0x0d0c0b0a09080706); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(reader.read_string(), "foobar"); | ||||
|  | ||||
|         TS_ASSERT_THROWS(reader.read_string(), io::input_error); | ||||
|         TS_ASSERT(!is); | ||||
|     } | ||||
|  | ||||
|     //Tests if comp equals an extended variant of Notch's bigtest NBT | ||||
|     void verify_bigtest_structure(const tag_compound& comp) | ||||
|     { | ||||
|         TS_ASSERT_EQUALS(comp.size(), 13u); | ||||
|  | ||||
|         TS_ASSERT(comp.at("byteTest") == tag_byte(127)); | ||||
|         TS_ASSERT(comp.at("shortTest") == tag_short(32767)); | ||||
|         TS_ASSERT(comp.at("intTest") == tag_int(2147483647)); | ||||
|         TS_ASSERT(comp.at("longTest") == tag_long(9223372036854775807)); | ||||
|         TS_ASSERT(comp.at("floatTest") == tag_float(std::stof("0xff1832p-25"))); //0.4982315 | ||||
|         TS_ASSERT(comp.at("doubleTest") == tag_double(std::stod("0x1f8f6bbbff6a5ep-54"))); //0.493128713218231 | ||||
|  | ||||
|         //From bigtest.nbt: "the first 1000 values of (n*n*255+n*7)%100, starting with n=0 (0, 62, 34, 16, 8, ...)" | ||||
|         tag_byte_array byteArrayTest; | ||||
|         for(int n = 0; n < 1000; ++n) | ||||
|             byteArrayTest.push_back((n*n*255 + n*7) % 100); | ||||
|         TS_ASSERT(comp.at("byteArrayTest (the first 1000 values of (n*n*255+n*7)%100, starting with n=0 (0, 62, 34, 16, 8, ...))") == byteArrayTest); | ||||
|  | ||||
|         TS_ASSERT(comp.at("stringTest") == tag_string("HELLO WORLD THIS IS A TEST STRING \u00C5\u00C4\u00D6!")); | ||||
|  | ||||
|         TS_ASSERT(comp.at("listTest (compound)") == tag_list::of<tag_compound>({ | ||||
|             {{"created-on", tag_long(1264099775885)}, {"name", "Compound tag #0"}}, | ||||
|             {{"created-on", tag_long(1264099775885)}, {"name", "Compound tag #1"}} | ||||
|         })); | ||||
|         TS_ASSERT(comp.at("listTest (long)") == tag_list::of<tag_long>({11, 12, 13, 14, 15})); | ||||
|         TS_ASSERT(comp.at("listTest (end)") == tag_list()); | ||||
|  | ||||
|         TS_ASSERT((comp.at("nested compound test") == tag_compound{ | ||||
|             {"egg", tag_compound{{"value", 0.5f},  {"name", "Eggbert"}}}, | ||||
|             {"ham", tag_compound{{"value", 0.75f}, {"name", "Hampus"}}} | ||||
|         })); | ||||
|  | ||||
|         TS_ASSERT(comp.at("intArrayTest") == tag_int_array( | ||||
|             {0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f})); | ||||
|     } | ||||
|  | ||||
|     void test_read_bigtest() | ||||
|     { | ||||
|         //Uses an extended variant of Notch's original bigtest file | ||||
|         std::ifstream file("bigtest_uncompr", std::ios::binary); | ||||
|         TS_ASSERT(file); | ||||
|  | ||||
|         auto pair = nbt::io::read_compound(file); | ||||
|         TS_ASSERT_EQUALS(pair.first, "Level"); | ||||
|         verify_bigtest_structure(*pair.second); | ||||
|     } | ||||
|  | ||||
|     void test_read_littletest() | ||||
|     { | ||||
|         //Same as bigtest, but little endian | ||||
|         std::ifstream file("littletest_uncompr", std::ios::binary); | ||||
|         TS_ASSERT(file); | ||||
|  | ||||
|         auto pair = nbt::io::read_compound(file, endian::little); | ||||
|         TS_ASSERT_EQUALS(pair.first, "Level"); | ||||
|         TS_ASSERT_EQUALS(pair.second->get_type(), tag_type::Compound); | ||||
|         verify_bigtest_structure(*pair.second); | ||||
|     } | ||||
|  | ||||
|     void test_read_errors() | ||||
|     { | ||||
|         std::ifstream file; | ||||
|         nbt::io::stream_reader reader(file); | ||||
|  | ||||
|         //EOF within a tag_double payload | ||||
|         file.open("errortest_eof1", std::ios::binary); | ||||
|         TS_ASSERT(file); | ||||
|         TS_ASSERT_THROWS(reader.read_tag(), io::input_error); | ||||
|         TS_ASSERT(!file); | ||||
|  | ||||
|         //EOF within a key in a compound | ||||
|         file.close(); | ||||
|         file.open("errortest_eof2", std::ios::binary); | ||||
|         TS_ASSERT(file); | ||||
|         TS_ASSERT_THROWS(reader.read_tag(), io::input_error); | ||||
|         TS_ASSERT(!file); | ||||
|  | ||||
|         //Missing tag_end | ||||
|         file.close(); | ||||
|         file.open("errortest_noend", std::ios::binary); | ||||
|         TS_ASSERT(file); | ||||
|         TS_ASSERT_THROWS(reader.read_tag(), io::input_error); | ||||
|         TS_ASSERT(!file); | ||||
|  | ||||
|         //Negative list length | ||||
|         file.close(); | ||||
|         file.open("errortest_neg_length", std::ios::binary); | ||||
|         TS_ASSERT(file); | ||||
|         TS_ASSERT_THROWS(reader.read_tag(), io::input_error); | ||||
|         TS_ASSERT(!file); | ||||
|     } | ||||
|  | ||||
|     void test_read_misc() | ||||
|     { | ||||
|         std::ifstream file; | ||||
|         nbt::io::stream_reader reader(file); | ||||
|  | ||||
|         //Toplevel tag other than compound | ||||
|         file.open("toplevel_string", std::ios::binary); | ||||
|         TS_ASSERT(file); | ||||
|         TS_ASSERT_THROWS(reader.read_compound(), io::input_error); | ||||
|         TS_ASSERT(!file); | ||||
|  | ||||
|         //Rewind and try again with read_tag | ||||
|         file.clear(); | ||||
|         TS_ASSERT(file.seekg(0)); | ||||
|         auto pair = reader.read_tag(); | ||||
|         TS_ASSERT_EQUALS(pair.first, "Test (toplevel tag_string)"); | ||||
|         TS_ASSERT(*pair.second == tag_string( | ||||
|             "Even though unprovided for by NBT, the library should also handle " | ||||
|             "the case where the file consists of something else than tag_compound")); | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/bigtest.nbt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/bigtest.nbt
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/bigtest_uncompr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/bigtest_uncompr
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/errortest_eof1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/errortest_eof1
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/errortest_eof2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/errortest_eof2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/errortest_neg_length
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/errortest_neg_length
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/errortest_noend
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/errortest_noend
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/level.dat.2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/level.dat.2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/littletest_uncompr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/littletest_uncompr
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/toplevel_string
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								depends/libnbtplusplus/test/testfiles/toplevel_string
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										248
									
								
								depends/libnbtplusplus/test/write_test.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								depends/libnbtplusplus/test/write_test.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,248 @@ | ||||
| /* | ||||
|  * libnbt++ - A library for the Minecraft Named Binary Tag format. | ||||
|  * Copyright (C) 2013, 2015  ljfa-ag | ||||
|  * | ||||
|  * This file is part of libnbt++. | ||||
|  * | ||||
|  * libnbt++ is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libnbt++ is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with libnbt++.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include <cxxtest/TestSuite.h> | ||||
| #include "io/stream_writer.h" | ||||
| #include "io/stream_reader.h" | ||||
| #include "nbt_tags.h" | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
|  | ||||
| using namespace nbt; | ||||
|  | ||||
| class read_test : public CxxTest::TestSuite | ||||
| { | ||||
| public: | ||||
|     void test_stream_writer_big() | ||||
|     { | ||||
|         std::ostringstream os; | ||||
|         nbt::io::stream_writer writer(os); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(&writer.get_ostr(), &os); | ||||
|         TS_ASSERT_EQUALS(writer.get_endian(), endian::big); | ||||
|  | ||||
|         writer.write_type(tag_type::End); | ||||
|         writer.write_type(tag_type::Long); | ||||
|         writer.write_type(tag_type::Int_Array); | ||||
|  | ||||
|         writer.write_num(int64_t(0x0102030405060708)); | ||||
|  | ||||
|         writer.write_string("foobar"); | ||||
|  | ||||
|         TS_ASSERT(os); | ||||
|         std::string expected{ | ||||
|             0, //tag_type::End | ||||
|             4, //tag_type::Long | ||||
|             11, //tag_type::Int_Array | ||||
|  | ||||
|             0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, //0x0102030405060708 in Big Endian | ||||
|  | ||||
|             0x00, 0x06, //string length in Big Endian | ||||
|             'f', 'o', 'o', 'b', 'a', 'r' | ||||
|         }; | ||||
|         TS_ASSERT_EQUALS(os.str(), expected); | ||||
|  | ||||
|         //too long for NBT | ||||
|         TS_ASSERT_THROWS(writer.write_string(std::string(65536, '.')), std::length_error); | ||||
|         TS_ASSERT(!os); | ||||
|     } | ||||
|  | ||||
|     void test_stream_writer_little() | ||||
|     { | ||||
|         std::ostringstream os; | ||||
|         nbt::io::stream_writer writer(os, endian::little); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(writer.get_endian(), endian::little); | ||||
|  | ||||
|         writer.write_num(int32_t(0x0a0b0c0d)); | ||||
|  | ||||
|         writer.write_string("foobar"); | ||||
|  | ||||
|         TS_ASSERT(os); | ||||
|         std::string expected{ | ||||
|             0x0d, 0x0c, 0x0b, 0x0a, //0x0a0b0c0d in Little Endian | ||||
|  | ||||
|             0x06, 0x00, //string length in Little Endian | ||||
|             'f', 'o', 'o', 'b', 'a', 'r' | ||||
|         }; | ||||
|         TS_ASSERT_EQUALS(os.str(), expected); | ||||
|  | ||||
|         TS_ASSERT_THROWS(writer.write_string(std::string(65536, '.')), std::length_error); | ||||
|         TS_ASSERT(!os); | ||||
|     } | ||||
|  | ||||
|     void test_write_payload_big() | ||||
|     { | ||||
|         std::ostringstream os; | ||||
|         nbt::io::stream_writer writer(os); | ||||
|  | ||||
|         //tag_primitive | ||||
|         writer.write_payload(tag_byte(127)); | ||||
|         writer.write_payload(tag_short(32767)); | ||||
|         writer.write_payload(tag_int(2147483647)); | ||||
|         writer.write_payload(tag_long(9223372036854775807)); | ||||
|  | ||||
|         //Same values as in endian_str_test | ||||
|         writer.write_payload(tag_float(std::stof("-0xCDEF01p-63"))); | ||||
|         writer.write_payload(tag_double(std::stod("-0x1DEF0102030405p-375"))); | ||||
|  | ||||
|         TS_ASSERT_EQUALS(os.str(), (std::string{ | ||||
|             '\x7F', | ||||
|             '\x7F', '\xFF', | ||||
|             '\x7F', '\xFF', '\xFF', '\xFF', | ||||
|             '\x7F', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF', | ||||
|  | ||||
|             '\xAB', '\xCD', '\xEF', '\x01', | ||||
|             '\xAB', '\xCD', '\xEF', '\x01', '\x02', '\x03', '\x04', '\x05' | ||||
|         })); | ||||
|         os.str(""); //clear and reuse the stream | ||||
|  | ||||
|         //tag_string | ||||
|         writer.write_payload(tag_string("barbaz")); | ||||
|         TS_ASSERT_EQUALS(os.str(), (std::string{ | ||||
|             0x00, 0x06, //string length in Big Endian | ||||
|             'b', 'a', 'r', 'b', 'a', 'z' | ||||
|         })); | ||||
|         TS_ASSERT_THROWS(writer.write_payload(tag_string(std::string(65536, '.'))), std::length_error); | ||||
|         TS_ASSERT(!os); | ||||
|         os.clear(); | ||||
|  | ||||
|         //tag_byte_array | ||||
|         os.str(""); | ||||
|         writer.write_payload(tag_byte_array{0, 1, 127, -128, -127}); | ||||
|         TS_ASSERT_EQUALS(os.str(), (std::string{ | ||||
|             0x00, 0x00, 0x00, 0x05, //length in Big Endian | ||||
|             0, 1, 127, -128, -127 | ||||
|         })); | ||||
|         os.str(""); | ||||
|  | ||||
|         //tag_int_array | ||||
|         writer.write_payload(tag_int_array{0x01020304, 0x05060708, 0x090a0b0c}); | ||||
|         TS_ASSERT_EQUALS(os.str(), (std::string{ | ||||
|             0x00, 0x00, 0x00, 0x03, //length in Big Endian | ||||
|             0x01, 0x02, 0x03, 0x04, | ||||
|             0x05, 0x06, 0x07, 0x08, | ||||
|             0x09, 0x0a, 0x0b, 0x0c | ||||
|         })); | ||||
|         os.str(""); | ||||
|  | ||||
|         //tag_list | ||||
|         writer.write_payload(tag_list()); //empty list with undetermined type, should be written as list of tag_end | ||||
|         writer.write_payload(tag_list(tag_type::Int)); //empty list of tag_int | ||||
|         writer.write_payload(tag_list{ //nested list | ||||
|             tag_list::of<tag_short>({0x3456, 0x789a}), | ||||
|             tag_list::of<tag_byte>({0x0a, 0x0b, 0x0c, 0x0d}) | ||||
|         }); | ||||
|         TS_ASSERT_EQUALS(os.str(), (std::string{ | ||||
|             0, //tag_type::End | ||||
|             0x00, 0x00, 0x00, 0x00, //length | ||||
|  | ||||
|             3, //tag_type::Int | ||||
|             0x00, 0x00, 0x00, 0x00, //length | ||||
|  | ||||
|             9, //tag_type::List | ||||
|             0x00, 0x00, 0x00, 0x02, //length | ||||
|             //list 0 | ||||
|             2, //tag_type::Short | ||||
|             0x00, 0x00, 0x00, 0x02, //length | ||||
|             '\x34', '\x56', | ||||
|             '\x78', '\x9a', | ||||
|             //list 1 | ||||
|             1, //tag_type::Byte | ||||
|             0x00, 0x00, 0x00, 0x04, //length | ||||
|             0x0a, | ||||
|             0x0b, | ||||
|             0x0c, | ||||
|             0x0d | ||||
|         })); | ||||
|         os.str(""); | ||||
|  | ||||
|         //tag_compound | ||||
|         /* Testing if writing compounds works properly is problematic because the | ||||
|         order of the tags is not guaranteed. However with only two tags in a | ||||
|         compound we only have two possible orderings. | ||||
|         See below for a more thorough test that uses writing and re-reading. */ | ||||
|         writer.write_payload(tag_compound{}); | ||||
|         writer.write_payload(tag_compound{ | ||||
|             {"foo", "quux"}, | ||||
|             {"bar", tag_int(0x789abcde)} | ||||
|         }); | ||||
|  | ||||
|         std::string endtag{0x00}; | ||||
|         std::string subtag1{ | ||||
|             8, //tag_type::String | ||||
|             0x00, 0x03, //key length | ||||
|             'f', 'o', 'o', | ||||
|             0x00, 0x04, //string length | ||||
|             'q', 'u', 'u', 'x' | ||||
|         }; | ||||
|         std::string subtag2{ | ||||
|             3, //tag_type::Int | ||||
|             0x00, 0x03, //key length | ||||
|             'b', 'a', 'r', | ||||
|             '\x78', '\x9A', '\xBC', '\xDE' | ||||
|         }; | ||||
|  | ||||
|         TS_ASSERT(os.str() == endtag + subtag1 + subtag2 + endtag | ||||
|                || os.str() == endtag + subtag2 + subtag1 + endtag); | ||||
|  | ||||
|         //Now for write_tag: | ||||
|         os.str(""); | ||||
|         writer.write_tag("foo", tag_string("quux")); | ||||
|         TS_ASSERT_EQUALS(os.str(), subtag1); | ||||
|         TS_ASSERT(os); | ||||
|  | ||||
|         //too long key for NBT | ||||
|         TS_ASSERT_THROWS(writer.write_tag(std::string(65536, '.'), tag_long(-1)), std::length_error); | ||||
|         TS_ASSERT(!os); | ||||
|     } | ||||
|  | ||||
|     void test_write_bigtest() | ||||
|     { | ||||
|         /* Like already stated above, because no order is guaranteed for | ||||
|         tag_compound, we cannot simply test it by writing into a stream and directly | ||||
|         comparing the output to a reference value. | ||||
|         Instead, we assume that reading already works correctly and re-read the | ||||
|         written tag. | ||||
|         Smaller-grained tests are already done above. */ | ||||
|         std::ifstream file("bigtest_uncompr", std::ios::binary); | ||||
|         const auto orig_pair = io::read_compound(file); | ||||
|         std::stringstream sstr; | ||||
|  | ||||
|         //Write into stream in Big Endian | ||||
|         io::write_tag(orig_pair.first, *orig_pair.second, sstr); | ||||
|         TS_ASSERT(sstr); | ||||
|  | ||||
|         //Read from stream in Big Endian and compare | ||||
|         auto written_pair = io::read_compound(sstr); | ||||
|         TS_ASSERT_EQUALS(orig_pair.first, written_pair.first); | ||||
|         TS_ASSERT(*orig_pair.second == *written_pair.second); | ||||
|  | ||||
|         sstr.str(""); //Reset and reuse stream | ||||
|         //Write into stream in Little Endian | ||||
|         io::write_tag(orig_pair.first, *orig_pair.second, sstr, endian::little); | ||||
|         TS_ASSERT(sstr); | ||||
|  | ||||
|         //Read from stream in Little Endian and compare | ||||
|         written_pair = io::read_compound(sstr, endian::little); | ||||
|         TS_ASSERT_EQUALS(orig_pair.first, written_pair.first); | ||||
|         TS_ASSERT(*orig_pair.second == *written_pair.second); | ||||
|     } | ||||
| }; | ||||
| @@ -329,7 +329,7 @@ else(UNIX) | ||||
| endif(UNIX) | ||||
|  | ||||
| # Link | ||||
| target_link_libraries(MultiMC_logic xz-embedded unpack200 iconfix libUtil LogicalGui ${QUAZIP_LIBRARIES} | ||||
| target_link_libraries(MultiMC_logic xz-embedded unpack200 iconfix libUtil LogicalGui ${QUAZIP_LIBRARIES} nbt++ | ||||
| 	Qt5::Core Qt5::Xml Qt5::Widgets Qt5::Network Qt5::Concurrent | ||||
| 		 ${ZLIB_LIBRARIES} ${MultiMC_LINK_ADDITIONAL_LIBS}) | ||||
|  | ||||
|   | ||||
| @@ -15,9 +15,16 @@ | ||||
|  | ||||
| #include <QDir> | ||||
| #include <QString> | ||||
| #include <QDebug> | ||||
| #include "World.h" | ||||
| #include <pathutils.h> | ||||
|  | ||||
| #include "GZip.h" | ||||
| #include <sstream> | ||||
| #include <io/stream_reader.h> | ||||
| #include <tag_string.h> | ||||
| #include <tag_primitive.h> | ||||
|  | ||||
| World::World(const QFileInfo &file) | ||||
| { | ||||
| 	repath(file); | ||||
| @@ -26,8 +33,117 @@ World::World(const QFileInfo &file) | ||||
| void World::repath(const QFileInfo &file) | ||||
| { | ||||
| 	m_file = file; | ||||
| 	m_name = file.fileName(); | ||||
| 	is_valid = file.isDir() && QDir(file.filePath()).exists("level.dat"); | ||||
| 	m_folderName = file.fileName(); | ||||
| 	QDir worldDir(file.filePath()); | ||||
| 	is_valid = file.isDir() && worldDir.exists("level.dat"); | ||||
| 	if(!is_valid) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	auto fullFilePath = worldDir.absoluteFilePath("level.dat"); | ||||
| 	QFile f(fullFilePath); | ||||
| 	is_valid = f.open(QIODevice::ReadOnly); | ||||
| 	if(!is_valid) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	QByteArray output; | ||||
| 	is_valid = GZip::inflate(f.readAll(), output); | ||||
| 	if(!is_valid) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 	f.close(); | ||||
|  | ||||
| 	auto read_string = [](nbt::value& parent, const char * name, const QString & fallback = QString()) -> QString | ||||
| 	{ | ||||
| 		try | ||||
| 		{ | ||||
| 			auto &namedValue = parent.at(name); | ||||
| 			if(namedValue.get_type() != nbt::tag_type::String) | ||||
| 			{ | ||||
| 				return fallback; | ||||
| 			} | ||||
| 			auto & tag_str = namedValue.as<nbt::tag_string>(); | ||||
| 			return QString::fromStdString(tag_str.get()); | ||||
| 		} | ||||
| 		catch(std::out_of_range e) | ||||
| 		{ | ||||
| 			// fallback for old world formats | ||||
| 			return fallback; | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	auto read_long = [](nbt::value& parent, const char * name, const int64_t & fallback = 0) -> int64_t | ||||
| 	{ | ||||
| 		try | ||||
| 		{ | ||||
| 			auto &namedValue = parent.at(name); | ||||
| 			if(namedValue.get_type() != nbt::tag_type::Long) | ||||
| 			{ | ||||
| 				return fallback; | ||||
| 			} | ||||
| 			auto & tag_str = namedValue.as<nbt::tag_long>(); | ||||
| 			return tag_str.get(); | ||||
| 		} | ||||
| 		catch(std::out_of_range e) | ||||
| 		{ | ||||
| 			// fallback for old world formats | ||||
| 			return fallback; | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	try | ||||
| 	{ | ||||
| 		std::istringstream foo(std::string(output.constData(), output.size())); | ||||
| 		auto pair = nbt::io::read_compound(foo); | ||||
| 		is_valid  = pair.first == ""; | ||||
|  | ||||
| 		if(!is_valid) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
| 		std::ostringstream ostr; | ||||
| 		is_valid = pair.second != nullptr; | ||||
| 		if(!is_valid) | ||||
| 		{ | ||||
| 			qDebug() << "FAIL~!!!"; | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		auto &val = pair.second->at("Data"); | ||||
| 		is_valid = val.get_type() == nbt::tag_type::Compound; | ||||
| 		if(!is_valid) | ||||
| 			return; | ||||
|  | ||||
| 		m_actualName = read_string(val, "LevelName", m_folderName); | ||||
|  | ||||
|  | ||||
| 		int64_t temp = read_long(val, "LastPlayed", 0); | ||||
| 		if(temp == 0) | ||||
| 		{ | ||||
| 			QFileInfo finfo(fullFilePath); | ||||
| 			m_lastPlayed = finfo.lastModified(); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			m_lastPlayed = QDateTime::fromMSecsSinceEpoch(temp); | ||||
| 		} | ||||
|  | ||||
| 		m_randomSeed = read_long(val, "RandomSeed", 0); | ||||
|  | ||||
| 		qDebug() << "World Name:" << m_actualName; | ||||
| 		qDebug() << "Last Played:" << m_lastPlayed.toString(); | ||||
| 		qDebug() << "Seed:" << m_randomSeed; | ||||
| 	} | ||||
| 	catch (nbt::io::input_error e) | ||||
| 	{ | ||||
| 		qWarning() << "Unable to load" << m_folderName << ":" << e.what(); | ||||
| 		is_valid = false; | ||||
| 		return; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| bool World::replace(World &with) | ||||
| @@ -37,7 +153,7 @@ bool World::replace(World &with) | ||||
| 	bool success = copyPath(with.m_file.filePath(), m_file.path()); | ||||
| 	if (success) | ||||
| 	{ | ||||
| 		m_name = with.m_name; | ||||
| 		m_folderName = with.m_folderName; | ||||
| 		m_file.refresh(); | ||||
| 	} | ||||
| 	return success; | ||||
| @@ -64,9 +180,9 @@ bool World::destroy() | ||||
|  | ||||
| bool World::operator==(const World &other) const | ||||
| { | ||||
| 	return is_valid == other.is_valid && name() == other.name(); | ||||
| 	return is_valid == other.is_valid && folderName() == other.folderName(); | ||||
| } | ||||
| bool World::strongCompare(const World &other) const | ||||
| { | ||||
| 	return is_valid == other.is_valid && name() == other.name(); | ||||
| 	return is_valid == other.is_valid && folderName() == other.folderName(); | ||||
| } | ||||
|   | ||||
| @@ -15,20 +15,33 @@ | ||||
|  | ||||
| #pragma once | ||||
| #include <QFileInfo> | ||||
| #include <QDateTime> | ||||
|  | ||||
| class World | ||||
| { | ||||
| public: | ||||
| 	World(const QFileInfo &file); | ||||
| 	QString folderName() const | ||||
| 	{ | ||||
| 		return m_folderName; | ||||
| 	} | ||||
| 	QString name() const | ||||
| 	{ | ||||
| 		return m_name; | ||||
| 		return m_actualName; | ||||
| 	} | ||||
| 	QDateTime lastPlayed() const | ||||
| 	{ | ||||
| 		return m_lastPlayed; | ||||
| 	} | ||||
| 	int64_t seed() const | ||||
| 	{ | ||||
| 		return m_randomSeed; | ||||
| 	} | ||||
| 	bool isValid() const | ||||
| 	{ | ||||
| 		return is_valid; | ||||
| 	} | ||||
| // 	// delete all the files of this world | ||||
| 	// delete all the files of this world | ||||
| 	bool destroy(); | ||||
| 	// replace this world with a copy of the other | ||||
| 	bool replace(World &with); | ||||
| @@ -42,6 +55,9 @@ public: | ||||
| protected: | ||||
|  | ||||
| 	QFileInfo m_file; | ||||
| 	QString m_name; | ||||
| 	bool is_valid; | ||||
| 	QString m_folderName; | ||||
| 	QString m_actualName; | ||||
| 	QDateTime m_lastPlayed; | ||||
| 	int64_t m_randomSeed = 0; | ||||
| 	bool is_valid = false; | ||||
| }; | ||||
|   | ||||
| @@ -66,7 +66,7 @@ void WorldList::internalSort(QList<World> &what) | ||||
| { | ||||
| 	auto predicate = [](const World &left, const World &right) | ||||
| 	{ | ||||
| 		return left.name().localeAwareCompare(right.name()) < 0; | ||||
| 		return left.folderName().localeAwareCompare(right.folderName()) < 0; | ||||
| 	}; | ||||
| 	std::sort(what.begin(), what.end(), predicate); | ||||
| } | ||||
| @@ -142,7 +142,7 @@ bool WorldList::deleteWorlds(int first, int last) | ||||
|  | ||||
| int WorldList::columnCount(const QModelIndex &parent) const | ||||
| { | ||||
| 	return 1; | ||||
| 	return 2; | ||||
| } | ||||
|  | ||||
| QVariant WorldList::data(const QModelIndex &index, int role) const | ||||
| @@ -156,20 +156,42 @@ QVariant WorldList::data(const QModelIndex &index, int role) const | ||||
| 	if (row < 0 || row >= worlds.size()) | ||||
| 		return QVariant(); | ||||
|  | ||||
| 	auto & world = worlds[row]; | ||||
| 	switch (role) | ||||
| 	{ | ||||
| 	case Qt::DisplayRole: | ||||
| 		switch (column) | ||||
| 		{ | ||||
| 		case NameColumn: | ||||
| 			return worlds[row].name(); | ||||
| 			return world.name(); | ||||
|  | ||||
| 		case LastPlayedColumn: | ||||
| 			return world.lastPlayed(); | ||||
|  | ||||
| 		default: | ||||
| 			return QVariant(); | ||||
| 		} | ||||
|  | ||||
| 	case Qt::ToolTipRole: | ||||
| 		return worlds[row].name(); | ||||
| 	{ | ||||
| 		return world.folderName(); | ||||
| 	} | ||||
| 	case FolderRole: | ||||
| 	{ | ||||
| 		return QDir::toNativeSeparators(dir().absoluteFilePath(world.folderName())); | ||||
| 	} | ||||
| 	case SeedRole: | ||||
| 	{ | ||||
| 		return qVariantFromValue<qlonglong>(world.seed()); | ||||
| 	} | ||||
| 	case NameRole: | ||||
| 	{ | ||||
| 		return world.name(); | ||||
| 	} | ||||
| 	case LastPlayedRole: | ||||
| 	{ | ||||
| 		return world.lastPlayed(); | ||||
| 	} | ||||
| 	default: | ||||
| 		return QVariant(); | ||||
| 	} | ||||
| @@ -184,6 +206,8 @@ QVariant WorldList::headerData(int section, Qt::Orientation orientation, int rol | ||||
| 		{ | ||||
| 		case NameColumn: | ||||
| 			return tr("Name"); | ||||
| 		case LastPlayedColumn: | ||||
| 			return tr("Last Played"); | ||||
| 		default: | ||||
| 			return QVariant(); | ||||
| 		} | ||||
| @@ -193,6 +217,8 @@ QVariant WorldList::headerData(int section, Qt::Orientation orientation, int rol | ||||
| 		{ | ||||
| 		case NameColumn: | ||||
| 			return tr("The name of the world."); | ||||
| 		case LastPlayedColumn: | ||||
| 			return tr("Date and time the world was last played."); | ||||
| 		default: | ||||
| 			return QVariant(); | ||||
| 		} | ||||
|   | ||||
| @@ -21,79 +21,93 @@ | ||||
| #include <QAbstractListModel> | ||||
| #include "minecraft/World.h" | ||||
|  | ||||
| #include "multimc_logic_export.h" | ||||
|  | ||||
| class QFileSystemWatcher; | ||||
|  | ||||
| class WorldList : public QAbstractListModel | ||||
| class MULTIMC_LOGIC_EXPORT WorldList : public QAbstractListModel | ||||
| { | ||||
|     Q_OBJECT | ||||
| 	Q_OBJECT | ||||
| public: | ||||
|     enum Columns { | ||||
|         NameColumn | ||||
|     }; | ||||
| 	enum Columns | ||||
| 	{ | ||||
| 		NameColumn, | ||||
| 		LastPlayedColumn | ||||
| 	}; | ||||
|  | ||||
|     WorldList ( const QString &dir ); | ||||
| 	enum Roles | ||||
| 	{ | ||||
| 		FolderRole = Qt::UserRole + 1, | ||||
| 		SeedRole, | ||||
| 		NameRole, | ||||
| 		LastPlayedRole | ||||
| 	}; | ||||
|  | ||||
|     virtual QVariant data ( const QModelIndex &index, int role = Qt::DisplayRole ) const; | ||||
| 	WorldList(const QString &dir); | ||||
|  | ||||
|     virtual int rowCount ( const QModelIndex &parent = QModelIndex() ) const { | ||||
|         return size(); | ||||
|     } | ||||
|     ; | ||||
|     virtual QVariant headerData ( int section, Qt::Orientation orientation, | ||||
|                                   int role = Qt::DisplayRole ) const; | ||||
|     virtual int columnCount ( const QModelIndex &parent ) const; | ||||
| 	virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; | ||||
|  | ||||
|     size_t size() const { | ||||
|         return worlds.size(); | ||||
|     } | ||||
|     ; | ||||
|     bool empty() const { | ||||
|         return size() == 0; | ||||
|     } | ||||
|     World &operator[] ( size_t index ) { | ||||
|         return worlds[index]; | ||||
|     } | ||||
| 	virtual int rowCount(const QModelIndex &parent = QModelIndex()) const | ||||
| 	{ | ||||
| 		return size(); | ||||
| 	}; | ||||
| 	virtual QVariant headerData(int section, Qt::Orientation orientation, | ||||
| 								int role = Qt::DisplayRole) const; | ||||
| 	virtual int columnCount(const QModelIndex &parent) const; | ||||
|  | ||||
|     /// Reloads the mod list and returns true if the list changed. | ||||
|     virtual bool update(); | ||||
| 	size_t size() const | ||||
| 	{ | ||||
| 		return worlds.size(); | ||||
| 	}; | ||||
| 	bool empty() const | ||||
| 	{ | ||||
| 		return size() == 0; | ||||
| 	} | ||||
| 	World &operator[](size_t index) | ||||
| 	{ | ||||
| 		return worlds[index]; | ||||
| 	} | ||||
|  | ||||
|     /// Deletes the mod at the given index. | ||||
|     virtual bool deleteWorld ( int index ); | ||||
| 	/// Reloads the mod list and returns true if the list changed. | ||||
| 	virtual bool update(); | ||||
|  | ||||
|     /// Deletes all the selected mods | ||||
|     virtual bool deleteWorlds ( int first, int last ); | ||||
| 	/// Deletes the mod at the given index. | ||||
| 	virtual bool deleteWorld(int index); | ||||
|  | ||||
|     /// get data for drag action | ||||
|     virtual QMimeData *mimeData ( const QModelIndexList &indexes ) const; | ||||
|     /// get the supported mime types | ||||
|     virtual QStringList mimeTypes() const; | ||||
| 	/// Deletes all the selected mods | ||||
| 	virtual bool deleteWorlds(int first, int last); | ||||
|  | ||||
|     void startWatching(); | ||||
|     void stopWatching(); | ||||
| 	/// get data for drag action | ||||
| 	virtual QMimeData *mimeData(const QModelIndexList &indexes) const; | ||||
| 	/// get the supported mime types | ||||
| 	virtual QStringList mimeTypes() const; | ||||
|  | ||||
|     virtual bool isValid(); | ||||
| 	void startWatching(); | ||||
| 	void stopWatching(); | ||||
|  | ||||
|     QDir dir() { | ||||
|         return m_dir; | ||||
|     } | ||||
| 	virtual bool isValid(); | ||||
|  | ||||
|     const QList<World> & allWorlds() { | ||||
|         return worlds; | ||||
|     } | ||||
| 	QDir dir() const | ||||
| 	{ | ||||
| 		return m_dir; | ||||
| 	} | ||||
|  | ||||
| 	const QList<World> &allWorlds() const | ||||
| 	{ | ||||
| 		return worlds; | ||||
| 	} | ||||
|  | ||||
| private: | ||||
|     void internalSort ( QList<World> & what ); | ||||
|     private | ||||
| slots: | ||||
|     void directoryChanged ( QString path ); | ||||
| 	void internalSort(QList<World> &what); | ||||
| private slots: | ||||
| 	void directoryChanged(QString path); | ||||
|  | ||||
| signals: | ||||
|     void changed(); | ||||
| 	void changed(); | ||||
|  | ||||
| protected: | ||||
|     QFileSystemWatcher *m_watcher; | ||||
|     bool is_watching; | ||||
|     QDir m_dir; | ||||
|     QList<World> worlds; | ||||
| 	QFileSystemWatcher *m_watcher; | ||||
| 	bool is_watching; | ||||
| 	QDir m_dir; | ||||
| 	QList<World> worlds; | ||||
| }; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user