From db81b925d776103326128bf629cbdda576a223e7 Mon Sep 17 00:00:00 2001
From: sanine <sanine.not@pm.me>
Date: Sat, 16 Apr 2022 11:55:09 -0500
Subject: move 3rd-party librarys into libs/ and add built-in honeysuckle

---
 libs/assimp/contrib/openddlparser/CMakeLists.txt   |  170 ++++
 libs/assimp/contrib/openddlparser/CREDITS          |   19 +
 libs/assimp/contrib/openddlparser/LICENSE          |   22 +
 libs/assimp/contrib/openddlparser/README.md        |  136 +++
 libs/assimp/contrib/openddlparser/code/DDLNode.cpp |  227 +++++
 .../contrib/openddlparser/code/OpenDDLCommon.cpp   |  200 ++++
 .../contrib/openddlparser/code/OpenDDLExport.cpp   |  361 +++++++
 .../contrib/openddlparser/code/OpenDDLParser.cpp   | 1035 ++++++++++++++++++++
 .../contrib/openddlparser/code/OpenDDLStream.cpp   |   96 ++
 libs/assimp/contrib/openddlparser/code/Value.cpp   |  438 +++++++++
 .../openddlparser/include/openddlparser/DDLNode.h  |  173 ++++
 .../include/openddlparser/OpenDDLCommon.h          |  245 +++++
 .../include/openddlparser/OpenDDLExport.h          |   80 ++
 .../include/openddlparser/OpenDDLParser.h          |  206 ++++
 .../include/openddlparser/OpenDDLParserUtils.h     |  503 ++++++++++
 .../include/openddlparser/OpenDDLStream.h          |   89 ++
 .../include/openddlparser/TPoolAllocator.h         |  226 +++++
 .../openddlparser/include/openddlparser/Value.h    |  273 ++++++
 18 files changed, 4499 insertions(+)
 create mode 100644 libs/assimp/contrib/openddlparser/CMakeLists.txt
 create mode 100644 libs/assimp/contrib/openddlparser/CREDITS
 create mode 100644 libs/assimp/contrib/openddlparser/LICENSE
 create mode 100644 libs/assimp/contrib/openddlparser/README.md
 create mode 100644 libs/assimp/contrib/openddlparser/code/DDLNode.cpp
 create mode 100644 libs/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp
 create mode 100644 libs/assimp/contrib/openddlparser/code/OpenDDLExport.cpp
 create mode 100644 libs/assimp/contrib/openddlparser/code/OpenDDLParser.cpp
 create mode 100644 libs/assimp/contrib/openddlparser/code/OpenDDLStream.cpp
 create mode 100644 libs/assimp/contrib/openddlparser/code/Value.cpp
 create mode 100644 libs/assimp/contrib/openddlparser/include/openddlparser/DDLNode.h
 create mode 100644 libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
 create mode 100644 libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLExport.h
 create mode 100644 libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParser.h
 create mode 100644 libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
 create mode 100644 libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLStream.h
 create mode 100644 libs/assimp/contrib/openddlparser/include/openddlparser/TPoolAllocator.h
 create mode 100644 libs/assimp/contrib/openddlparser/include/openddlparser/Value.h

(limited to 'libs/assimp/contrib/openddlparser')

diff --git a/libs/assimp/contrib/openddlparser/CMakeLists.txt b/libs/assimp/contrib/openddlparser/CMakeLists.txt
new file mode 100644
index 0000000..407f084
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/CMakeLists.txt
@@ -0,0 +1,170 @@
+CMAKE_MINIMUM_REQUIRED( VERSION 3.10 )
+PROJECT( OpenDDL-Parser )
+SET ( OPENDDL_PARSER_VERSION_MAJOR 0 )
+SET ( OPENDDL_PARSER_VERSION_MINOR 1 )
+SET ( OPENDDL_PARSER_VERSION_PATCH 0 )
+SET ( OPENDDL_PARSER_VERSION ${OPENDDL_PARSER_VERSION_MAJOR}.${OPENDDL_PARSER_VERSION_MINOR}.${OPENDDL_PARSER_VERSION_PATCH} )
+SET ( PROJECT_VERSION "${OPENDDL_PARSER_VERSION}" )
+
+option( DDL_DEBUG_OUTPUT        "Set to ON to use output debug texts"                                         OFF )
+option( DDL_STATIC_LIBRARY		"Set to ON to build static libary of OpenDDL Parser."                         ON )
+option( COVERALLS               "Generate coveralls data"                                                     OFF )
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+    find_package(Threads)
+else()
+    add_definitions( -D_CRT_SECURE_NO_WARNINGS )
+endif()
+
+if ( DDL_STATIC_LIBRARY )
+	add_definitions( -DOPENDDL_STATIC_LIBARY )
+endif()
+
+if (MSVC)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING")
+    add_definitions(-DGTEST_HAS_TR1_TUPLE=0)
+endif()
+
+add_definitions( -DOPENDDLPARSER_BUILD )
+add_definitions( -D_VARIADIC_MAX=10 )
+add_definitions( -DGTEST_HAS_PTHREAD=0 )
+if ( DDL_DEBUG_OUTPUT )
+    add_definitions( -DDDL_DEBUG_HEADER_NAME)
+endif()
+
+INCLUDE_DIRECTORIES(
+    ./
+    include/
+    contrib/gtest-1.7.0/include
+    contrib/gtest-1.7.0/
+)
+
+link_directories(
+    ${CMAKE_HOME_DIRECTORY}/lib
+)
+
+SET( CMAKE_MODULE_PATH  ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake )
+SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
+SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
+SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin )
+
+if( WIN32 AND NOT CYGWIN )
+  set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc" )  # Force to always compile with W4
+  if( CMAKE_CXX_FLAGS MATCHES "/W[0-4]" )
+    string( REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" )
+  else()
+    set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4" )
+  endif()
+elseif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+  # Update if necessary
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic ${OPENDDL_CXXFLAGS}")
+elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic ${OPENDDL_CXXFLAGS} -Wwrite-strings")
+endif()
+
+if (COVERALLS)
+    include(Coveralls)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
+endif()
+
+# Include the doc component.
+FIND_PACKAGE( doxygen )
+IF ( DOXYGEN_FOUND )
+    CONFIGURE_FILE( doc/openddlparser_doc.in doc/doxygenfile @ONLY )
+    ADD_CUSTOM_TARGET( doc ALL ${DOXYGEN_EXECUTABLE} doc/doxygenfile
+        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+        COMMENT "Generating API documentation with Doxygen" VERBATIM )
+ENDIF ( DOXYGEN_FOUND )
+
+SET ( openddl_parser_src
+    code/OpenDDLCommon.cpp
+    code/OpenDDLExport.cpp
+    code/OpenDDLParser.cpp
+    code/OpenDDLStream.cpp
+    code/DDLNode.cpp
+    code/Value.cpp
+    include/openddlparser/OpenDDLCommon.h
+    include/openddlparser/OpenDDLExport.h
+    include/openddlparser/OpenDDLParser.h
+    include/openddlparser/OpenDDLParserUtils.h
+    include/openddlparser/OpenDDLStream.h
+    include/openddlparser/DDLNode.h
+    include/openddlparser/Value.h
+    include/openddlparser/TPoolAllocator.h
+    README.md
+)
+ 
+SOURCE_GROUP( code            FILES ${openddl_parser_src} )
+
+if ( DDL_STATIC_LIBRARY )
+	ADD_LIBRARY( openddl_parser STATIC
+		${openddl_parser_src}
+	)
+else()
+	ADD_LIBRARY( openddl_parser SHARED
+		${openddl_parser_src}
+	)
+endif()
+
+SET ( GTEST_PATH contrib/gtest-1.7.0 )
+
+SET ( gtest_src
+    ${GTEST_PATH}/src/gtest-death-test.cc
+    ${GTEST_PATH}/src/gtest-filepath.cc
+    ${GTEST_PATH}/src/gtest-internal-inl.h
+    ${GTEST_PATH}/src/gtest-port.cc
+    ${GTEST_PATH}/src/gtest-printers.cc
+    ${GTEST_PATH}/src/gtest-test-part.cc
+    ${GTEST_PATH}/src/gtest-typed-test.cc
+    ${GTEST_PATH}/src/gtest.cc
+)
+
+SET( openddl_parser_unittest_src  
+    test/UnitTestCommon.h
+    test/DDLNodeTest.cpp
+    test/OpenDDLCommonTest.cpp
+    test/OpenDDLExportTest.cpp
+    test/OpenDDLParserTest.cpp
+    test/OpenDDLParserUtilsTest.cpp
+    test/OpenDDLStreamTest.cpp
+    test/OpenDDLIntegrationTest.cpp
+    test/ValueTest.cpp
+    test/OpenDDLDefectsTest.cpp
+	test/OssFuzzTest.cpp
+    test/main.cpp
+)
+add_definitions(-DOPENDDL_TEST_DATA="${CMAKE_CURRENT_LIST_DIR}/test/TestData")
+
+SOURCE_GROUP( code  FILES ${openddl_parser_unittest_src} )
+SOURCE_GROUP( gtest FILES ${gtest_src} )
+
+ADD_EXECUTABLE( openddl_parser_unittest 
+    ${gtest_src}
+    ${openddl_parser_unittest_src}
+)
+
+target_link_libraries( openddl_parser_unittest openddl_parser ${CMAKE_THREAD_LIBS_INIT} )
+
+SET( openddl_parser_demo_src  
+    demo/main.cpp 
+)
+
+if (COVERALLS)
+    set(COVERAGE_SRCS     ${gtest_src} ${openddl_parser_unittest_src} )
+
+    # Create the coveralls target.
+    coveralls_setup(
+        "${COVERAGE_SRCS}" # The source files.
+        ON                 # If we should upload.
+        "${PROJECT_SOURCE_DIR}/cmake/") # (Optional) Alternate project cmake module path.
+endif()
+
+ADD_EXECUTABLE( openddl_parser_demo
+    ${openddl_parser_demo_src}
+) 
+
+target_link_libraries( openddl_parser_demo openddl_parser )
diff --git a/libs/assimp/contrib/openddlparser/CREDITS b/libs/assimp/contrib/openddlparser/CREDITS
new file mode 100644
index 0000000..d3936af
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/CREDITS
@@ -0,0 +1,19 @@
+===============================================================
+OpenDDL-Parser
+Developers and Contributors
+===============================================================
+
+- Kim Kulling ( kimmi ):
+Founder
+
+- Fredrik Hansson ( FredrikHson ):
+Improvements value interface, serveral bugfixes.
+
+- Henry Read ( henrya2 ):
+Static build option, Interface improvements
+
+- (wise86-android)
+fix several mem-leaks
+
+- Paul Holland ( pkholland ):
+Bugfixes.
diff --git a/libs/assimp/contrib/openddlparser/LICENSE b/libs/assimp/contrib/openddlparser/LICENSE
new file mode 100644
index 0000000..4c1476b
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/libs/assimp/contrib/openddlparser/README.md b/libs/assimp/contrib/openddlparser/README.md
new file mode 100644
index 0000000..a48ea1b
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/README.md
@@ -0,0 +1,136 @@
+The OpenDDL-Parser
+==================
+
+The OpenDDL-Parser is a small and easy to use library for OpenDDL-file-format-parsing. OpenDDL is the shortcut for Open Data Description Language, a data-declaration language introduced by Eric Lengyel. Please check http://openddl.org/ if you want to learn more about it.
+
+Build status
+============
+Linux build status: [![Build Status](https://travis-ci.org/kimkulling/openddl-parser.png)](https://travis-ci.org/kimkulling/openddl-parser)
+Current coverity check status:
+<a href="https://scan.coverity.com/projects/5606">
+  <img alt="Coverity Scan Build Status"
+       src="https://scan.coverity.com/projects/5606/badge.svg"/>
+</a>
+Current test coverage:[![Coverage Status](https://coveralls.io/repos/github/kimkulling/openddl-parser/badge.svg?branch=master)](https://coveralls.io/github/kimkulling/openddl-parser?branch=cpp_coveralls)
+Get the source code
+===================
+You can get the code from our git repository, which is located at GitHub. You can clone the repository with the following command:
+
+> git clone https://github.com/kimkulling/openddl-parser.git
+
+Building the source from the GitHub-Repo
+========================================
+To build the library you need to install cmake first ( see http://www.cmake.org/ for more information ). Make also sure that a compiler tool-chain is installed on your machine.
+After installing it you can open a console and enter:
+
+> cmake CMakeLists.txt
+
+This command will generate a build environment for your preferred build tool ( for Visual-Studio-users the project files will be generated, for gcc-users the makefiles will be generated ).
+When using an IDE open the IDE and run the build. When using GNU-make type in your console:
+
+> make
+
+and that's all.
+
+When using Visual Studio CMake will generate you a solution for ythe library. Just build it there.
+
+Use the library
+===============
+To use the OpenDDL-parser you need to build the lib first. Now add the 
+> <Repo-folder>/include 
+
+to your include-path and the 
+
+> <Repo-folder>/lib
+
+to your lib-folder. Link the openddl.lib to your application. 
+
+Here is a small example how to use the lib:
+
+```cpp
+
+#include <iostream>
+#include <cassert>
+#include <openddlparser/OpenDDLParser.h>
+
+USE_ODDLPARSER_NS;
+
+int main( int argc, char *argv[] ) {
+    if( argc < 3 ) {
+        return 1;
+    }
+
+    char *filename( nullptr );
+    if( 0 == strncmp( FileOption, argv[ 1 ], strlen( FileOption ) ) ) {
+        filename = argv[ 2 ];
+    }
+    std::cout << "file to import: " << filename << std::endl;   
+    if( nullptr == filename ) {
+        std::cerr << "Invalid filename." << std::endl;
+        return Error;
+    }
+
+    FILE *fileStream = fopen( filename, "r+" );
+    if( NULL == filename ) {
+        std::cerr << "Cannot open file " << filename << std::endl;
+        return 1;
+    }
+
+    // obtain file size:
+    fseek( fileStream, 0, SEEK_END );
+    const size_t size( ftell( fileStream ) );   
+    rewind( fileStream );   
+    if( size > 0 ) {
+        char *buffer = new char[ size ];
+        const size_t readSize( fread( buffer, sizeof( char ), size, fileStream ) );
+        assert( readSize == size );
+        OpenDDLParser theParser;
+        theParser.setBuffer( buffer, size );
+        const bool result( theParser.parse() );
+        if( !result ) {
+            std::cerr << "Error while parsing file " << filename << "." << std::endl;
+        }
+    }
+    return 0;
+}
+
+```
+
+How to access the imported data
+===============================
+The data is organized as a tree. You can get the root-node of the tree with the following code:
+
+```cpp
+OpenDDLParser theParser;
+theParser.setBuffer( buffer, size );
+const bool result( theParser.parse() );
+if ( result ) {
+    DDLNode *root = theParser.getRoot();
+    DDLNode::DllNodeList childs = root->getChildNodeList();
+    for ( size_t i=0; i<childs.size(); i++ ) {
+        DDLNode *child = childs[ i ];
+        Property *prop   = child->getProperty(); // to get properties
+        std::string type = child->getType();     // to get the node type
+        Value *values    = child->getValue();    // to get the data;
+        
+        // to loop through all values
+        while ( values != ddl_nullptr ) {
+            int current = values->getInt32();
+            values = value->getNext();
+        }
+    }
+}
+
+```
+
+The node instance called root contains the data.
+
+All data lists are organized as linked lists.
+
+Reference documentation
+=======================
+Please check http://kimkulling.github.io/openddl-parser/doxygen_html/index.html.
+
+Projects using OpenDDL-Parser
+=============================
+- Asset Importer Lib: https://github.com/assimp/assimp .
diff --git a/libs/assimp/contrib/openddlparser/code/DDLNode.cpp b/libs/assimp/contrib/openddlparser/code/DDLNode.cpp
new file mode 100644
index 0000000..724c5d6
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/code/DDLNode.cpp
@@ -0,0 +1,227 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/DDLNode.h>
+#include <openddlparser/OpenDDLParser.h>
+#include <openddlparser/OpenDDLStream.h>
+
+#include <algorithm>
+
+BEGIN_ODDLPARSER_NS
+
+DDLNode::DllNodeList DDLNode::s_allocatedNodes;
+
+template <class T>
+inline static void releaseDataType(T *ptr) {
+    if (nullptr == ptr) {
+        return;
+    }
+
+    T *current(nullptr);
+    while (ptr) {
+        current = ptr;
+        ptr = ptr->m_next;
+        delete current;
+    }
+}
+
+static void releaseReferencedNames(Reference *ref) {
+    if (nullptr == ref) {
+        return;
+    }
+
+    delete ref;
+}
+
+DDLNode::DDLNode(const std::string &type, const std::string &name, size_t idx, DDLNode *parent) :
+        m_type(type),
+        m_name(name),
+        m_parent(parent),
+        m_children(),
+        m_properties(nullptr),
+        m_value(nullptr),
+        m_dtArrayList(nullptr),
+        m_references(nullptr),
+        m_idx(idx) {
+    if (m_parent) {
+        m_parent->m_children.push_back(this);
+    }
+}
+
+DDLNode::~DDLNode() {
+    delete m_properties;
+    delete m_value;
+    releaseReferencedNames(m_references);
+
+    delete m_dtArrayList;
+    m_dtArrayList = nullptr;
+    if (s_allocatedNodes[m_idx] == this) {
+        s_allocatedNodes[m_idx] = nullptr;
+    }
+    for (size_t i = 0; i < m_children.size(); i++) {
+        delete m_children[i];
+    }
+}
+
+void DDLNode::attachParent(DDLNode *parent) {
+    if (m_parent == parent) {
+        return;
+    }
+
+    m_parent = parent;
+    if (nullptr != m_parent) {
+        m_parent->m_children.push_back(this);
+    }
+}
+
+void DDLNode::detachParent() {
+    if (nullptr != m_parent) {
+        DDLNodeIt it = std::find(m_parent->m_children.begin(), m_parent->m_children.end(), this);
+        if (m_parent->m_children.end() != it) {
+            m_parent->m_children.erase(it);
+        }
+        m_parent = nullptr;
+    }
+}
+
+DDLNode *DDLNode::getParent() const {
+    return m_parent;
+}
+
+const DDLNode::DllNodeList &DDLNode::getChildNodeList() const {
+    return m_children;
+}
+
+void DDLNode::setType(const std::string &type) {
+    m_type = type;
+}
+
+const std::string &DDLNode::getType() const {
+    return m_type;
+}
+
+void DDLNode::setName(const std::string &name) {
+    m_name = name;
+}
+
+const std::string &DDLNode::getName() const {
+    return m_name;
+}
+
+void DDLNode::setProperties(Property *prop) {
+    if (m_properties != nullptr)
+        delete m_properties;
+    m_properties = prop;
+}
+
+Property *DDLNode::getProperties() const {
+    return m_properties;
+}
+
+bool DDLNode::hasProperty(const std::string &name) {
+    const Property *prop(findPropertyByName(name));
+    return (nullptr != prop);
+}
+
+bool DDLNode::hasProperties() const {
+    return (nullptr != m_properties);
+}
+
+Property *DDLNode::findPropertyByName(const std::string &name) {
+    if (name.empty()) {
+        return nullptr;
+    }
+
+    if (nullptr == m_properties) {
+        return nullptr;
+    }
+
+    Property *current(m_properties);
+    while (nullptr != current) {
+        int res = strncmp(current->m_key->m_buffer, name.c_str(), name.size());
+        if (0 == res) {
+            return current;
+        }
+        current = current->m_next;
+    }
+
+    return nullptr;
+}
+
+void DDLNode::setValue(Value *val) {
+    m_value = val;
+}
+
+Value *DDLNode::getValue() const {
+    return m_value;
+}
+
+void DDLNode::setDataArrayList(DataArrayList *dtArrayList) {
+    m_dtArrayList = dtArrayList;
+}
+
+DataArrayList *DDLNode::getDataArrayList() const {
+    return m_dtArrayList;
+}
+
+void DDLNode::setReferences(Reference *refs) {
+    m_references = refs;
+}
+
+Reference *DDLNode::getReferences() const {
+    return m_references;
+}
+
+void DDLNode::dump(IOStreamBase &stream) {
+    if (!stream.isOpen()) {
+        return;
+    }
+
+    const std::string &type = this->getType();
+    stream.write("type = " + type);
+    Value::Iterator it(getValue());
+    while (it.hasNext()) {
+        Value *v = it.getNext();
+        v->dump(stream);
+    }
+}
+
+DDLNode *DDLNode::create(const std::string &type, const std::string &name, DDLNode *parent) {
+    const size_t idx(s_allocatedNodes.size());
+    DDLNode *node = new DDLNode(type, name, idx, parent);
+    s_allocatedNodes.push_back(node);
+
+    return node;
+}
+
+void DDLNode::releaseNodes() {
+    if (s_allocatedNodes.size() > 0) {
+        for (DDLNodeIt it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++) {
+            if (*it) {
+                delete *it;
+            }
+        }
+        s_allocatedNodes.clear();
+    }
+}
+
+END_ODDLPARSER_NS
diff --git a/libs/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp b/libs/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp
new file mode 100644
index 0000000..d853efa
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp
@@ -0,0 +1,200 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/DDLNode.h>
+#include <openddlparser/OpenDDLCommon.h>
+#include <openddlparser/Value.h>
+
+BEGIN_ODDLPARSER_NS
+
+Text::Text(const char *buffer, size_t numChars) :
+        m_capacity(0),
+        m_len(0),
+        m_buffer(nullptr) {
+    set(buffer, numChars);
+}
+
+Text::~Text() {
+    clear();
+}
+
+void Text::clear() {
+    delete[] m_buffer;
+    m_buffer = nullptr;
+    m_capacity = 0;
+    m_len = 0;
+}
+
+void Text::set(const char *buffer, size_t numChars) {
+    clear();
+    if (numChars > 0) {
+        m_len = numChars;
+        m_capacity = m_len + 1;
+        m_buffer = new char[m_capacity];
+        strncpy(m_buffer, buffer, numChars);
+        m_buffer[numChars] = '\0';
+    }
+}
+
+bool Text::operator==(const std::string &name) const {
+    if (m_len != name.size()) {
+        return false;
+    }
+    const int res(strncmp(m_buffer, name.c_str(), name.size()));
+
+    return (0 == res);
+}
+
+bool Text::operator==(const Text &rhs) const {
+    if (m_len != rhs.m_len) {
+        return false;
+    }
+
+    const int res(strncmp(m_buffer, rhs.m_buffer, m_len));
+
+    return (0 == res);
+}
+
+Name::Name(NameType type, Text *id) :
+        m_type(type), m_id(id) {
+    // empty
+}
+
+Name::~Name() {
+    delete m_id;
+    m_id = nullptr;
+}
+
+Name::Name(const Name &name) {
+    m_type = name.m_type;
+    m_id = new Text(name.m_id->m_buffer, name.m_id->m_len);
+}
+
+Reference::Reference() :
+        m_numRefs(0), m_referencedName(nullptr) {
+    // empty
+}
+
+Reference::Reference(size_t numrefs, Name **names) :
+        m_numRefs(numrefs), m_referencedName(nullptr) {
+    if (numrefs > 0) {
+        m_referencedName = new Name *[numrefs];
+        for (size_t i = 0; i < numrefs; i++) {
+            m_referencedName[i] = names[i];
+        }
+    }
+}
+Reference::Reference(const Reference &ref) {
+    m_numRefs = ref.m_numRefs;
+    if (m_numRefs != 0) {
+        m_referencedName = new Name *[m_numRefs];
+        for (size_t i = 0; i < m_numRefs; i++) {
+            m_referencedName[i] = new Name(*ref.m_referencedName[i]);
+        }
+    }
+}
+
+Reference::~Reference() {
+    for (size_t i = 0; i < m_numRefs; i++) {
+        delete m_referencedName[i];
+    }
+    m_numRefs = 0;
+    delete[] m_referencedName;
+    m_referencedName = nullptr;
+}
+
+size_t Reference::sizeInBytes() {
+    if (0 == m_numRefs) {
+        return 0;
+    }
+
+    size_t size(0);
+    for (size_t i = 0; i < m_numRefs; i++) {
+        Name *name(m_referencedName[i]);
+        if (nullptr != name) {
+            size += name->m_id->m_len;
+        }
+    }
+
+    return size;
+}
+
+Property::Property(Text *id) :
+        m_key(id), m_value(nullptr), m_ref(nullptr), m_next(nullptr) {
+    // empty
+}
+
+Property::~Property() {
+    delete m_key;
+    if (m_value != nullptr)
+        delete m_value;
+    if (m_ref != nullptr)
+        delete (m_ref);
+    if (m_next != nullptr)
+        delete m_next;
+}
+
+DataArrayList::DataArrayList() :
+        m_numItems(0), m_dataList(nullptr), m_next(nullptr), m_refs(nullptr), m_numRefs(0) {
+    // empty
+}
+
+DataArrayList::~DataArrayList() {
+    delete m_dataList;
+    if (m_next != nullptr)
+        delete m_next;
+    if (m_refs != nullptr)
+        delete m_refs;
+}
+
+size_t DataArrayList::size() {
+    size_t result(0);
+    if (nullptr == m_next) {
+        if (m_dataList != nullptr) {
+            result = 1;
+        }
+        return result;
+    }
+
+    DataArrayList *n(m_next);
+    while (nullptr != n) {
+        result++;
+        n = n->m_next;
+    }
+    return result;
+}
+
+Context::Context() :
+        m_root(nullptr) {
+    // empty
+}
+
+Context::~Context() {
+    clear();
+}
+
+void Context::clear() {
+    delete m_root;
+    m_root = nullptr;
+}
+
+END_ODDLPARSER_NS
diff --git a/libs/assimp/contrib/openddlparser/code/OpenDDLExport.cpp b/libs/assimp/contrib/openddlparser/code/OpenDDLExport.cpp
new file mode 100644
index 0000000..d235b55
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/code/OpenDDLExport.cpp
@@ -0,0 +1,361 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/DDLNode.h>
+#include <openddlparser/OpenDDLExport.h>
+#include <openddlparser/OpenDDLParser.h>
+#include <openddlparser/Value.h>
+
+#include <sstream>
+
+BEGIN_ODDLPARSER_NS
+
+struct DDLNodeIterator {
+    const DDLNode::DllNodeList &m_childs;
+    size_t m_idx;
+
+    DDLNodeIterator(const DDLNode::DllNodeList &childs) :
+            m_childs(childs), m_idx(0) {
+        // empty
+    }
+
+    ~DDLNodeIterator() {
+        // empty
+    }
+
+    bool getNext(DDLNode **node) {
+        if (m_childs.size() > (m_idx + 1)) {
+            m_idx++;
+            *node = m_childs[m_idx];
+            return true;
+        }
+
+        return false;
+    }
+
+private:
+    DDLNodeIterator() ddl_no_copy;
+    DDLNodeIterator &operator=(const DDLNodeIterator &) ddl_no_copy;
+};
+
+static void writeLineEnd(std::string &statement) {
+    statement += "\n";
+}
+
+OpenDDLExport::OpenDDLExport(IOStreamBase *stream) :
+        m_stream(stream) {
+    if (nullptr == m_stream) {
+        m_stream = new IOStreamBase();
+    }
+}
+
+OpenDDLExport::~OpenDDLExport() {
+    if (nullptr != m_stream) {
+        m_stream->close();
+    }
+    delete m_stream;
+}
+
+bool OpenDDLExport::exportContext(Context *ctx, const std::string &filename) {
+    if (nullptr == ctx) {
+        return false;
+    }
+
+    DDLNode *root(ctx->m_root);
+    if (nullptr == root) {
+        return true;
+    }
+
+    if (!filename.empty()) {
+        if (!m_stream->open(filename)) {
+            return false;
+        }
+    }
+
+    const bool retValue(handleNode(root));
+
+    return retValue;
+}
+
+bool OpenDDLExport::handleNode(DDLNode *node) {
+    if (nullptr == node) {
+        return true;
+    }
+
+    const DDLNode::DllNodeList &childs = node->getChildNodeList();
+    if (childs.empty()) {
+        return true;
+    }
+    DDLNode *current(nullptr);
+    DDLNodeIterator it(childs);
+    std::string statement;
+    bool success(true);
+    while (it.getNext(&current)) {
+        if (nullptr != current) {
+            success |= writeNode(current, statement);
+            if (!handleNode(current)) {
+                success = false;
+            }
+        }
+    }
+
+    return success;
+}
+
+bool OpenDDLExport::writeToStream(const std::string &statement) {
+    if (nullptr == m_stream) {
+        return false;
+    }
+
+    if (!statement.empty()) {
+        m_stream->write(statement);
+    }
+
+    return true;
+}
+
+bool OpenDDLExport::writeNode(DDLNode *node, std::string &statement) {
+    writeNodeHeader(node, statement);
+    if (node->hasProperties()) {
+        writeProperties(node, statement);
+    }
+    writeLineEnd(statement);
+
+    statement = "}";
+    DataArrayList *al(node->getDataArrayList());
+    if (nullptr != al) {
+        writeValueType(al->m_dataList->m_type, al->m_numItems, statement);
+        writeValueArray(al, statement);
+    }
+    Value *v(node->getValue());
+    if (nullptr != v) {
+        writeValueType(v->m_type, 1, statement);
+        statement = "{";
+        writeLineEnd(statement);
+        writeValue(v, statement);
+        statement = "}";
+        writeLineEnd(statement);
+    }
+    statement = "}";
+    writeLineEnd(statement);
+
+    writeToStream(statement);
+
+    return true;
+}
+
+bool OpenDDLExport::writeNodeHeader(DDLNode *node, std::string &statement) {
+    if (nullptr == node) {
+        return false;
+    }
+
+    statement += node->getType();
+    const std::string &name(node->getName());
+    if (!name.empty()) {
+        statement += " ";
+        statement += "$";
+        statement += name;
+    }
+
+    return true;
+}
+
+bool OpenDDLExport::writeProperties(DDLNode *node, std::string &statement) {
+    if (nullptr == node) {
+        return false;
+    }
+
+    Property *prop(node->getProperties());
+    // if no properties are there, return
+    if (nullptr == prop) {
+        return true;
+    }
+
+    if (nullptr != prop) {
+        // for instance (attrib = "position", bla=2)
+        statement += "(";
+        bool first(true);
+        while (nullptr != prop) {
+            if (!first) {
+                statement += ", ";
+            } else {
+                first = false;
+            }
+            statement += std::string(prop->m_key->m_buffer);
+            statement += " = ";
+            writeValue(prop->m_value, statement);
+            prop = prop->m_next;
+        }
+
+        statement += ")";
+    }
+
+    return true;
+}
+
+bool OpenDDLExport::writeValueType(Value::ValueType type, size_t numItems, std::string &statement) {
+    if (Value::ValueType::ddl_types_max == type) {
+        return false;
+    }
+
+    const std::string typeStr(getTypeToken(type));
+    statement += typeStr;
+    // if we have an array to write
+    if (numItems > 1) {
+        statement += "[";
+        char buffer[256];
+        ::memset(buffer, '\0', 256 * sizeof(char));
+        sprintf(buffer, "%d", static_cast<int>(numItems));
+        statement += buffer;
+        statement += "]";
+    }
+
+    return true;
+}
+
+bool OpenDDLExport::writeValue(Value *val, std::string &statement) {
+    if (nullptr == val) {
+        return false;
+    }
+
+    switch (val->m_type) {
+        case Value::ValueType::ddl_bool:
+            if (true == val->getBool()) {
+                statement += "true";
+            } else {
+                statement += "false";
+            }
+            break;
+        case Value::ValueType::ddl_int8 : {
+            std::stringstream stream;
+            const int i = static_cast<int>(val->getInt8());
+            stream << i;
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_int16: {
+            std::stringstream stream;
+            char buffer[256];
+            ::memset(buffer, '\0', 256 * sizeof(char));
+            sprintf(buffer, "%d", val->getInt16());
+            statement += buffer;
+        } break;
+        case Value::ValueType::ddl_int32: {
+            std::stringstream stream;
+            char buffer[256];
+            ::memset(buffer, '\0', 256 * sizeof(char));
+            const int i = static_cast<int>(val->getInt32());
+            sprintf(buffer, "%d", i);
+            statement += buffer;
+        } break;
+        case Value::ValueType::ddl_int64: {
+            std::stringstream stream;
+            const int i = static_cast<int>(val->getInt64());
+            stream << i;
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_unsigned_int8: {
+            std::stringstream stream;
+            const int i = static_cast<unsigned int>(val->getUnsignedInt8());
+            stream << i;
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_unsigned_int16: {
+            std::stringstream stream;
+            const int i = static_cast<unsigned int>(val->getUnsignedInt16());
+            stream << i;
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_unsigned_int32: {
+            std::stringstream stream;
+            const int i = static_cast<unsigned int>(val->getUnsignedInt32());
+            stream << i;
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_unsigned_int64: {
+            std::stringstream stream;
+            const int i = static_cast<unsigned int>(val->getUnsignedInt64());
+            stream << i;
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_half:
+            break;
+        case Value::ValueType::ddl_float: {
+            std::stringstream stream;
+            stream << val->getFloat();
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_double: {
+            std::stringstream stream;
+            stream << val->getDouble();
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_string: {
+            std::stringstream stream;
+            stream << val->getString();
+            statement += "\"";
+            statement += stream.str();
+            statement += "\"";
+        } break;
+        case Value::ValueType::ddl_ref:
+            break;
+        case Value::ValueType::ddl_none:
+        case Value::ValueType::ddl_types_max:
+        default:
+            break;
+    }
+
+    return true;
+}
+
+bool OpenDDLExport::writeValueArray(DataArrayList *al, std::string &statement) {
+    if (nullptr == al) {
+        return false;
+    }
+
+    if (0 == al->m_numItems) {
+        return true;
+    }
+
+    DataArrayList *nextDataArrayList = al;
+    Value *nextValue(nextDataArrayList->m_dataList);
+    while (nullptr != nextDataArrayList) {
+        if (nullptr != nextDataArrayList) {
+            statement += "{ ";
+            nextValue = nextDataArrayList->m_dataList;
+            size_t idx(0);
+            while (nullptr != nextValue) {
+                if (idx > 0) {
+                    statement += ", ";
+                }
+                writeValue(nextValue, statement);
+                nextValue = nextValue->m_next;
+                idx++;
+            }
+            statement += " }";
+        }
+        nextDataArrayList = nextDataArrayList->m_next;
+    }
+
+    return true;
+}
+
+END_ODDLPARSER_NS
diff --git a/libs/assimp/contrib/openddlparser/code/OpenDDLParser.cpp b/libs/assimp/contrib/openddlparser/code/OpenDDLParser.cpp
new file mode 100644
index 0000000..e2bef97
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/code/OpenDDLParser.cpp
@@ -0,0 +1,1035 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/OpenDDLExport.h>
+#include <openddlparser/OpenDDLParser.h>
+
+#include <math.h>
+#include <algorithm>
+#include <cassert>
+#include <iostream>
+#include <sstream>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif // _WIN32
+
+BEGIN_ODDLPARSER_NS
+
+static const char *Version = "0.4.0";
+
+namespace Grammar {
+
+static const char *OpenBracketToken = "{";
+static const char *CloseBracketToken = "}";
+static const char *OpenPropertyToken = "(";
+static const char *ClosePropertyToken = ")";
+static const char *OpenArrayToken = "[";
+static const char *CloseArrayToken = "]";
+static const char *BoolTrue = "true";
+static const char *BoolFalse = "false";
+static const char *CommaSeparator = ",";
+
+static const char *PrimitiveTypeToken[(size_t)Value::ValueType::ddl_types_max] = {
+    "bool",
+    "int8",
+    "int16",
+    "int32",
+    "int64",
+    "unsigned_int8",
+    "unsigned_int16",
+    "unsigned_int32",
+    "unsigned_int64",
+    "half",
+    "float",
+    "double",
+    "string",
+    "ref"
+};
+} // Namespace Grammar
+
+const char *getTypeToken(Value::ValueType type) {
+    return Grammar::PrimitiveTypeToken[(size_t)type];
+}
+
+static void logInvalidTokenError(char *in, const std::string &exp, OpenDDLParser::logCallback callback) {
+    if (callback) {
+        std::string full(in);
+        std::string part(full.substr(0, 50));
+        std::stringstream stream;
+        stream << "Invalid token \"" << *in << "\" "
+               << "(expected \"" << exp << "\") "
+               << "in: \"" << part << "\"";
+        callback(ddl_error_msg, stream.str());
+    }
+}
+
+static bool isIntegerType(Value::ValueType integerType) {
+    if (integerType != Value::ValueType::ddl_int8 && integerType != Value::ValueType::ddl_int16 &&
+            integerType != Value::ValueType::ddl_int32 && integerType != Value::ValueType::ddl_int64) {
+        return false;
+    }
+
+    return true;
+}
+
+static bool isUnsignedIntegerType(Value::ValueType integerType) {
+    if (integerType != Value::ValueType::ddl_unsigned_int8 && integerType != Value::ValueType::ddl_unsigned_int16 &&
+            integerType != Value::ValueType::ddl_unsigned_int32 && integerType != Value::ValueType::ddl_unsigned_int64) {
+        return false;
+    }
+
+    return true;
+}
+
+static DDLNode *createDDLNode(Text *id, OpenDDLParser *parser) {
+    if (nullptr == id || nullptr == parser || id->m_buffer == nullptr) {
+        return nullptr;
+    }
+
+    const std::string type(id->m_buffer);
+    DDLNode *parent(parser->top());
+    DDLNode *node = DDLNode::create(type, "", parent);
+
+    return node;
+}
+
+OpenDDLParser::OpenDDLParser() :
+        m_logCallback(nullptr),
+        m_buffer(),
+        m_stack(),
+        m_context(nullptr) {
+    // empty
+}
+
+OpenDDLParser::OpenDDLParser(const char *buffer, size_t len) :
+        m_logCallback(nullptr), m_buffer(), m_context(nullptr) {
+    if (0 != len) {
+        setBuffer(buffer, len);
+    }
+}
+
+OpenDDLParser::~OpenDDLParser() {
+    clear();
+}
+
+void OpenDDLParser::logToStream(FILE *f, LogSeverity severity, const std::string &message) {
+    if (f) {
+        const char *tag = "none";
+        switch (severity) {
+        case ddl_debug_msg: tag = "debug"; break;
+        case ddl_info_msg:  tag = "info";  break;
+        case ddl_warn_msg:  tag = "warn";  break;
+        case ddl_error_msg: tag = "error"; break;
+        }
+        fprintf(f, "OpenDDLParser: (%5s) %s\n", tag, message.c_str());
+    }
+}
+
+OpenDDLParser::logCallback OpenDDLParser::StdLogCallback (FILE *destination) {
+    using namespace std::placeholders;
+    return std::bind(logToStream, destination ? destination : stderr, _1, _2);
+}
+
+void OpenDDLParser::setLogCallback(logCallback callback) {
+    // install user-specific log callback; null = no log callback
+    m_logCallback = callback;
+}
+
+OpenDDLParser::logCallback OpenDDLParser::getLogCallback() const {
+    return m_logCallback;
+}
+
+void OpenDDLParser::setBuffer(const char *buffer, size_t len) {
+    clear();
+    if (0 == len) {
+        return;
+    }
+
+    m_buffer.resize(len);
+    ::memcpy(&m_buffer[0], buffer, len);
+}
+
+void OpenDDLParser::setBuffer(const std::vector<char> &buffer) {
+    clear();
+    m_buffer.resize(buffer.size());
+    std::copy(buffer.begin(), buffer.end(), m_buffer.begin());
+}
+
+const char *OpenDDLParser::getBuffer() const {
+    if (m_buffer.empty()) {
+        return nullptr;
+    }
+
+    return &m_buffer[0];
+}
+
+size_t OpenDDLParser::getBufferSize() const {
+    return m_buffer.size();
+}
+
+void OpenDDLParser::clear() {
+    m_buffer.resize(0);
+    delete m_context;
+    m_context = nullptr;
+}
+
+bool OpenDDLParser::validate() {
+    if (m_buffer.empty()) {
+        return true;
+    }
+
+    if (!isCharacter(m_buffer[0]) && !isNumeric(m_buffer[0])) {
+        return false;
+    }
+
+    return true;
+}
+
+bool OpenDDLParser::parse() {
+    if (m_buffer.empty()) {
+        return false;
+    }
+
+    normalizeBuffer(m_buffer);
+    if (!validate()) {
+        return false;
+    }
+
+    m_context = new Context;
+    m_context->m_root = DDLNode::create("root", "", nullptr);
+    pushNode(m_context->m_root);
+
+    // do the main parsing
+    char *current(&m_buffer[0]);
+    char *end(&m_buffer[m_buffer.size() - 1] + 1);
+    size_t pos(current - &m_buffer[0]);
+    while (pos < m_buffer.size()) {
+        current = parseNextNode(current, end);
+        if (current == nullptr) {
+            return false;
+        }
+        pos = current - &m_buffer[0];
+    }
+    return true;
+}
+
+bool OpenDDLParser::exportContext(Context *ctx, const std::string &filename) {
+    if (nullptr == ctx) {
+        return false;
+    }
+
+    OpenDDLExport myExporter;
+    return myExporter.exportContext(ctx, filename);
+}
+
+char *OpenDDLParser::parseNextNode(char *in, char *end) {
+    in = parseHeader(in, end);
+    in = parseStructure(in, end);
+
+    return in;
+}
+
+#ifdef DEBUG_HEADER_NAME
+static void dumpId(Identifier *id) {
+    if (nullptr != id) {
+        if (nullptr != id->m_text.m_buffer) {
+            std::cout << id->m_text.m_buffer << std::endl;
+        }
+    }
+}
+#endif
+
+char *OpenDDLParser::parseHeader(char *in, char *end) {
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    Text *id(nullptr);
+    in = OpenDDLParser::parseIdentifier(in, end, &id);
+
+#ifdef DEBUG_HEADER_NAME
+    dumpId(id);
+#endif // DEBUG_HEADER_NAME
+
+    in = lookForNextToken(in, end);
+    if (nullptr != id) {
+        // store the node
+        DDLNode *node(createDDLNode(id, this));
+        if (nullptr != node) {
+            pushNode(node);
+        } else {
+            std::cerr << "nullptr returned by creating DDLNode." << std::endl;
+        }
+        delete id;
+
+        Name *name(nullptr);
+        in = OpenDDLParser::parseName(in, end, &name);
+        if (nullptr != name && nullptr != node && nullptr != name->m_id->m_buffer) {
+            const std::string nodeName(name->m_id->m_buffer);
+            node->setName(nodeName);
+            delete name;
+        }
+
+        Property *first(nullptr);
+        in = lookForNextToken(in, end);
+        if (in != end && *in == Grammar::OpenPropertyToken[0]) {
+            in++;
+            Property *prop(nullptr), *prev(nullptr);
+            while (in != end && *in != Grammar::ClosePropertyToken[0]) {
+                in = OpenDDLParser::parseProperty(in, end, &prop);
+                in = lookForNextToken(in, end);
+                if(in == end) {
+                    break;
+                }
+
+                if (*in != Grammar::CommaSeparator[0] && *in != Grammar::ClosePropertyToken[0]) {
+                    logInvalidTokenError(in, Grammar::ClosePropertyToken, m_logCallback);
+                    return nullptr;
+                }
+
+                if (nullptr != prop && *in != Grammar::CommaSeparator[0]) {
+                    if (nullptr == first) {
+                        first = prop;
+                    }
+                    if (nullptr != prev) {
+                        prev->m_next = prop;
+                    }
+                    prev = prop;
+                }
+            }
+            if(in != end) {
+                ++in;
+            }
+        }
+
+        // set the properties
+        if (nullptr != first && nullptr != node) {
+            node->setProperties(first);
+        }
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseStructure(char *in, char *end) {
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    bool error(false);
+    in = lookForNextToken(in, end);
+    if (*in == *Grammar::OpenBracketToken) {
+        // loop over all children ( data and nodes )
+        do {
+            in = parseStructureBody(in, end, error);
+            if (in == nullptr) {
+                return nullptr;
+            }
+        } while (*in != *Grammar::CloseBracketToken);
+        ++in;
+    } else {
+        ++in;
+        logInvalidTokenError(in, std::string(Grammar::OpenBracketToken), m_logCallback);
+        error = true;
+        return nullptr;
+    }
+    in = lookForNextToken(in, end);
+
+    // pop node from stack after successful parsing
+    if (!error) {
+        popNode();
+    }
+
+    return in;
+}
+
+static void setNodeValues(DDLNode *currentNode, Value *values) {
+    if (nullptr != values) {
+        if (nullptr != currentNode) {
+            currentNode->setValue(values);
+        }
+    }
+}
+
+static void setNodeReferences(DDLNode *currentNode, Reference *refs) {
+    if (nullptr != refs) {
+        if (nullptr != currentNode) {
+            currentNode->setReferences(refs);
+        }
+    }
+}
+
+static void setNodeDataArrayList(DDLNode *currentNode, DataArrayList *dtArrayList) {
+    if (nullptr != dtArrayList) {
+        if (nullptr != currentNode) {
+            currentNode->setDataArrayList(dtArrayList);
+        }
+    }
+}
+
+char *OpenDDLParser::parseStructureBody(char *in, char *end, bool &error) {
+    if (!isNumeric(*in) && !isCharacter(*in)) {
+        ++in;
+    }
+
+    in = lookForNextToken(in, end);
+    Value::ValueType type(Value::ValueType::ddl_none);
+    size_t arrayLen(0);
+    in = OpenDDLParser::parsePrimitiveDataType(in, end, type, arrayLen);
+    if (Value::ValueType::ddl_none != type) {
+        // parse a primitive data type
+        in = lookForNextToken(in, end);
+        if (*in == Grammar::OpenBracketToken[0]) {
+            Reference *refs(nullptr);
+            DataArrayList *dtArrayList(nullptr);
+            Value *values(nullptr);
+            if (1 == arrayLen) {
+                size_t numRefs(0), numValues(0);
+                in = parseDataList(in, end, type, &values, numValues, &refs, numRefs);
+                setNodeValues(top(), values);
+                setNodeReferences(top(), refs);
+            } else if (arrayLen > 1) {
+                in = parseDataArrayList(in, end, type, &dtArrayList);
+                setNodeDataArrayList(top(), dtArrayList);
+            } else {
+                std::cerr << "0 for array is invalid." << std::endl;
+                error = true;
+            }
+        }
+
+        in = lookForNextToken(in, end);
+        if (*in != '}') {
+            logInvalidTokenError(in, std::string(Grammar::CloseBracketToken), m_logCallback);
+            return nullptr;
+        } else {
+            //in++;
+        }
+    } else {
+        // parse a complex data type
+        in = parseNextNode(in, end);
+    }
+
+    return in;
+}
+
+void OpenDDLParser::pushNode(DDLNode *node) {
+    if (nullptr == node) {
+        return;
+    }
+
+    m_stack.push_back(node);
+}
+
+DDLNode *OpenDDLParser::popNode() {
+    if (m_stack.empty()) {
+        return nullptr;
+    }
+
+    DDLNode *topNode(top());
+    m_stack.pop_back();
+    return topNode;
+}
+
+DDLNode *OpenDDLParser::top() {
+    if (m_stack.empty()) {
+        return nullptr;
+    }
+
+    DDLNode *top(m_stack.back());
+    return top;
+}
+
+DDLNode *OpenDDLParser::getRoot() const {
+    if (nullptr == m_context) {
+        return nullptr;
+    }
+
+    return m_context->m_root;
+}
+
+Context *OpenDDLParser::getContext() const {
+    return m_context;
+}
+
+void OpenDDLParser::normalizeBuffer(std::vector<char> &buffer) {
+    if (buffer.empty()) {
+        return;
+    }
+
+    std::vector<char> newBuffer;
+    const size_t len(buffer.size());
+    char *end(&buffer[len - 1] + 1);
+    for (size_t readIdx = 0; readIdx < len; ++readIdx) {
+        char *c(&buffer[readIdx]);
+        // check for a comment
+        if (isCommentOpenTag(c, end)) {
+            ++readIdx;
+            while (readIdx < len && !isCommentCloseTag(&buffer[readIdx], end)) {
+                ++readIdx;
+            }
+            ++readIdx;
+        } else if (!isComment<char>(c, end) && !isNewLine(*c)) {
+            newBuffer.push_back(buffer[readIdx]);
+        } else {
+            if (isComment<char>(c, end)) {
+                ++readIdx;
+                // skip the comment and the rest of the line
+                while (readIdx < len && !isEndofLine(buffer[readIdx])) {
+                    ++readIdx;
+                }
+            }
+        }
+    }
+    buffer = newBuffer;
+}
+
+char *OpenDDLParser::parseName(char *in, char *end, Name **name) {
+    *name = nullptr;
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    // ignore blanks
+    in = lookForNextToken(in, end);
+    if (*in != '$' && *in != '%') {
+        return in;
+    }
+
+    NameType ntype(GlobalName);
+    if (*in == '%') {
+        ntype = LocalName;
+    }
+    in++;
+    Name *currentName(nullptr);
+    Text *id(nullptr);
+    in = parseIdentifier(in, end, &id);
+    if (id) {
+        currentName = new Name(ntype, id);
+        if (currentName) {
+            *name = currentName;
+        }
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseIdentifier(char *in, char *end, Text **id) {
+    *id = nullptr;
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    // ignore blanks
+    in = lookForNextToken(in, end);
+    if (in == end) {
+        return in;
+    }
+
+    // staring with a number is forbidden
+    if (isNumeric<const char>(*in)) {
+        return in;
+    }
+
+    // get size of id
+    size_t idLen(0);
+    char *start(in);
+    while ((in != end) && !isSeparator(*in) && !isNewLine(*in) &&
+            *in != Grammar::OpenPropertyToken[0] &&
+            *in != Grammar::ClosePropertyToken[0] &&
+            *in != '$') {
+        ++in;
+        ++idLen;
+    }
+
+    const size_t len(idLen);
+    *id = new Text(start, len);
+
+    return in;
+}
+
+char *OpenDDLParser::parsePrimitiveDataType(char *in, char *end, Value::ValueType &type, size_t &len) {
+    type = Value::ValueType::ddl_none;
+    len = 0;
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    size_t prim_len(0);
+    for (size_t i = 0; i < (size_t) Value::ValueType::ddl_types_max; i++) {
+        prim_len = strlen(Grammar::PrimitiveTypeToken[i]);
+        if (0 == strncmp(in, Grammar::PrimitiveTypeToken[i], prim_len)) {
+            type = static_cast<Value::ValueType>(i);
+            break;
+        }
+    }
+
+    if (Value::ValueType::ddl_none == type) {
+        in = lookForNextToken(in, end);
+        return in;
+    } else {
+        in += prim_len;
+    }
+
+    bool ok(true);
+    if (*in == Grammar::OpenArrayToken[0]) {
+        ok = false;
+        ++in;
+        char *start(in);
+        while (in != end) {
+            ++in;
+            if (*in == Grammar::CloseArrayToken[0]) {
+                len = ::atoi(start);
+                ok = true;
+                ++in;
+                break;
+            }
+        }
+    } else {
+        len = 1;
+    }
+    if (!ok) {
+        type = Value::ValueType::ddl_none;
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseReference(char *in, char *end, std::vector<Name *> &names) {
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    Name *nextName(nullptr);
+    in = parseName(in, end, &nextName);
+    if (nextName) {
+        names.push_back(nextName);
+    }
+    while (Grammar::CommaSeparator[0] == *in) {
+        in = getNextSeparator(in, end);
+        if (Grammar::CommaSeparator[0] == *in) {
+            in = parseName(in, end, &nextName);
+            if (nextName) {
+                names.push_back(nextName);
+            }
+        } else {
+            break;
+        }
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseBooleanLiteral(char *in, char *end, Value **boolean) {
+    *boolean = nullptr;
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    in = lookForNextToken(in, end);
+    char *start(in);
+    size_t len(0);
+    while (!isSeparator(*in) && in != end) {
+        ++in;
+        ++len;
+    }
+    ++len;
+    int res = ::strncmp(Grammar::BoolTrue, start, strlen(Grammar::BoolTrue));
+    if (0 != res) {
+        res = ::strncmp(Grammar::BoolFalse, start, strlen(Grammar::BoolFalse));
+        if (0 != res) {
+            *boolean = nullptr;
+            return in;
+        }
+        *boolean = ValueAllocator::allocPrimData(Value::ValueType::ddl_bool);
+        (*boolean)->setBool(false);
+    } else {
+        *boolean = ValueAllocator::allocPrimData(Value::ValueType::ddl_bool);
+        (*boolean)->setBool(true);
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseIntegerLiteral(char *in, char *end, Value **integer, Value::ValueType integerType) {
+    *integer = nullptr;
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    if (!(isIntegerType(integerType) || isUnsignedIntegerType(integerType))) {
+        return in;
+    }
+
+    in = lookForNextToken(in, end);
+    char *start(in);
+    while (!isSeparator(*in) && in != end) {
+        ++in;
+    }
+
+    if (isNumeric(*start)) {
+#ifdef OPENDDL_NO_USE_CPP11
+        const int64 value(atol(start)); // maybe not really 64bit as atoll is but exists without c++11
+        const uint64 uvalue(strtoul(start, nullptr, 10));
+#else
+        const int64 value(atoll(start));
+        const uint64 uvalue(strtoull(start, nullptr, 10));
+#endif
+        *integer = ValueAllocator::allocPrimData(integerType);
+        switch (integerType) {
+            case Value::ValueType::ddl_int8:
+                (*integer)->setInt8((int8)value);
+                break;
+            case Value::ValueType::ddl_int16:
+                (*integer)->setInt16((int16)value);
+                break;
+            case Value::ValueType::ddl_int32:
+                (*integer)->setInt32((int32)value);
+                break;
+            case Value::ValueType::ddl_int64:
+                (*integer)->setInt64((int64)value);
+                break;
+            case Value::ValueType::ddl_unsigned_int8:
+                (*integer)->setUnsignedInt8((uint8)uvalue);
+                break;
+            case Value::ValueType::ddl_unsigned_int16:
+                (*integer)->setUnsignedInt16((uint16)uvalue);
+                break;
+            case Value::ValueType::ddl_unsigned_int32:
+                (*integer)->setUnsignedInt32((uint32)uvalue);
+                break;
+            case Value::ValueType::ddl_unsigned_int64:
+                (*integer)->setUnsignedInt64((uint64)uvalue);
+                break;
+            default:
+                break;
+        }
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseFloatingLiteral(char *in, char *end, Value **floating, Value::ValueType floatType) {
+    *floating = nullptr;
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    in = lookForNextToken(in, end);
+    char *start(in);
+    while (!isSeparator(*in) && in != end) {
+        ++in;
+    }
+
+    // parse the float value
+    bool ok(false);
+    if (isHexLiteral(start, end)) {
+        parseHexaLiteral(start, end, floating);
+        return in;
+    }
+
+    if (isNumeric(*start)) {
+        ok = true;
+    } else {
+        if (*start == '-') {
+            if (isNumeric(*(start + 1))) {
+                ok = true;
+            }
+        }
+    }
+
+    if (ok) {
+        if (floatType == Value::ValueType::ddl_double) {
+            const double value(atof(start));
+            *floating = ValueAllocator::allocPrimData(Value::ValueType::ddl_double);
+            (*floating)->setDouble(value);
+        } else {
+            const float value((float)atof(start));
+            *floating = ValueAllocator::allocPrimData(Value::ValueType::ddl_float);
+            (*floating)->setFloat(value);
+        }
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseStringLiteral(char *in, char *end, Value **stringData) {
+    *stringData = nullptr;
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    in = lookForNextToken(in, end);
+    size_t len(0);
+    char *start(in);
+    if (*start == '\"') {
+        ++start;
+        ++in;
+        while (*in != '\"' && in != end) {
+            ++in;
+            ++len;
+        }
+
+        *stringData = ValueAllocator::allocPrimData(Value::ValueType::ddl_string, len);
+        ::strncpy((char *)(*stringData)->m_data, start, len);
+        (*stringData)->m_data[len] = '\0';
+        ++in;
+    }
+
+    return in;
+}
+
+static void createPropertyWithData(Text *id, Value *primData, Property **prop) {
+    if (nullptr != primData) {
+        (*prop) = new Property(id);
+        (*prop)->m_value = primData;
+    }
+}
+
+char *OpenDDLParser::parseHexaLiteral(char *in, char *end, Value **data) {
+    *data = nullptr;
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    in = lookForNextToken(in, end);
+    if (*in != '0') {
+        return in;
+    }
+
+    ++in;
+    if (*in != 'x' && *in != 'X') {
+        return in;
+    }
+
+    ++in;
+    bool ok(true);
+    char *start(in);
+    int pos(0);
+    while (!isSeparator(*in) && in != end) {
+        if ((*in < '0' && *in > '9') || (*in < 'a' && *in > 'f') || (*in < 'A' && *in > 'F')) {
+            ok = false;
+            break;
+        }
+        ++pos;
+        ++in;
+    }
+
+    if (!ok) {
+        return in;
+    }
+
+    int value(0);
+    while (pos > 0) {
+        int v = hex2Decimal(*start);
+        --pos;
+        value = (value << 4) | v;
+        ++start;
+    }
+
+    *data = ValueAllocator::allocPrimData(Value::ValueType::ddl_unsigned_int64);
+    if (nullptr != *data) {
+        (*data)->setUnsignedInt64(value);
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseProperty(char *in, char *end, Property **prop) {
+    *prop = nullptr;
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    in = lookForNextToken(in, end);
+    Text *id = nullptr;
+    in = parseIdentifier(in, end, &id);
+    if (nullptr != id) {
+        in = lookForNextToken(in, end);
+        if (in != end && *in == '=') {
+            ++in;
+            in = getNextToken(in, end);
+            Value *primData(nullptr);
+            if (isInteger(in, end)) {
+                in = parseIntegerLiteral(in, end, &primData);
+                createPropertyWithData(id, primData, prop);
+            } else if (isFloat(in, end)) {
+                in = parseFloatingLiteral(in, end, &primData);
+                createPropertyWithData(id, primData, prop);
+            } else if (isStringLiteral(*in)) { // string data
+                in = parseStringLiteral(in, end, &primData);
+                createPropertyWithData(id, primData, prop);
+            } else { // reference data
+                std::vector<Name *> names;
+                in = parseReference(in, end, names);
+                if (!names.empty()) {
+                    Reference *ref = new Reference(names.size(), &names[0]);
+                    (*prop) = new Property(id);
+                    (*prop)->m_ref = ref;
+                }
+            }
+        } else {
+            delete id;
+        }
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseDataList(char *in, char *end, Value::ValueType type, Value **data,
+        size_t &numValues, Reference **refs, size_t &numRefs) {
+    *data = nullptr;
+    numValues = numRefs = 0;
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    in = lookForNextToken(in, end);
+    if (*in == '{') {
+        ++in;
+        Value *current(nullptr), *prev(nullptr);
+        while ('}' != *in) {
+            current = nullptr;
+            in = lookForNextToken(in, end);
+            if (Value::ValueType::ddl_ref == type) {
+                std::vector<Name *> names;
+                in = parseReference(in, end, names);
+                if (!names.empty()) {
+                    Reference *ref = new Reference(names.size(), &names[0]);
+                    *refs = ref;
+                    numRefs = names.size();
+                }
+            } else if (Value::ValueType::ddl_none == type) {
+                if (isInteger(in, end)) {
+                    in = parseIntegerLiteral(in, end, &current);
+                } else if (isFloat(in, end)) {
+                    in = parseFloatingLiteral(in, end, &current);
+                } else if (isStringLiteral(*in)) {
+                    in = parseStringLiteral(in, end, &current);
+                } else if (isHexLiteral(in, end)) {
+                    in = parseHexaLiteral(in, end, &current);
+                }
+            } else {
+                switch (type) {
+                    case Value::ValueType::ddl_int8:
+                    case Value::ValueType::ddl_int16:
+                    case Value::ValueType::ddl_int32:
+                    case Value::ValueType::ddl_int64:
+                    case Value::ValueType::ddl_unsigned_int8:
+                    case Value::ValueType::ddl_unsigned_int16:
+                    case Value::ValueType::ddl_unsigned_int32:
+                    case Value::ValueType::ddl_unsigned_int64:
+                        in = parseIntegerLiteral(in, end, &current, type);
+                        break;
+                    case Value::ValueType::ddl_half:
+                    case Value::ValueType::ddl_float:
+                    case Value::ValueType::ddl_double:
+                        in = parseFloatingLiteral(in, end, &current, type);
+                        break;
+                    case Value::ValueType::ddl_string:
+                        in = parseStringLiteral(in, end, &current);
+                        break;
+                    default:
+                        break;
+                }
+            }
+
+            if (nullptr != current) {
+                if (nullptr == *data) {
+                    *data = current;
+                    prev = current;
+                } else {
+                    prev->setNext(current);
+                    prev = current;
+                }
+                ++numValues;
+            }
+
+            in = getNextSeparator(in, end);
+            if (',' != *in && Grammar::CloseBracketToken[0] != *in && !isSpace(*in)) {
+                break;
+            }
+        }
+        ++in;
+    }
+
+    return in;
+}
+
+static DataArrayList *createDataArrayList(Value *currentValue, size_t numValues,
+        Reference *refs, size_t numRefs) {
+    DataArrayList *dataList(new DataArrayList);
+    dataList->m_dataList = currentValue;
+    dataList->m_numItems = numValues;
+    dataList->m_refs = refs;
+    dataList->m_numRefs = numRefs;
+
+    return dataList;
+}
+
+char *OpenDDLParser::parseDataArrayList(char *in, char *end, Value::ValueType type,
+        DataArrayList **dataArrayList) {
+    if (nullptr == dataArrayList) {
+        return in;
+    }
+
+    *dataArrayList = nullptr;
+    if (nullptr == in || in == end) {
+        return in;
+    }
+
+    in = lookForNextToken(in, end);
+    if (*in == Grammar::OpenBracketToken[0]) {
+        ++in;
+        Value *currentValue(nullptr);
+        Reference *refs(nullptr);
+        DataArrayList *prev(nullptr), *currentDataList(nullptr);
+        do {
+            size_t numRefs(0), numValues(0);
+            currentValue = nullptr;
+
+            in = parseDataList(in, end, type, &currentValue, numValues, &refs, numRefs);
+            if (nullptr != currentValue || 0 != numRefs) {
+                if (nullptr == prev) {
+                    *dataArrayList = createDataArrayList(currentValue, numValues, refs, numRefs);
+                    prev = *dataArrayList;
+                } else {
+                    currentDataList = createDataArrayList(currentValue, numValues, refs, numRefs);
+                    if (nullptr != prev) {
+                        prev->m_next = currentDataList;
+                        prev = currentDataList;
+                    }
+                }
+            }
+        } while (Grammar::CommaSeparator[0] == *in && in != end);
+        in = lookForNextToken(in, end);
+        ++in;
+    }
+
+    return in;
+}
+
+const char *OpenDDLParser::getVersion() {
+    return Version;
+}
+
+END_ODDLPARSER_NS
diff --git a/libs/assimp/contrib/openddlparser/code/OpenDDLStream.cpp b/libs/assimp/contrib/openddlparser/code/OpenDDLStream.cpp
new file mode 100644
index 0000000..1a38dfa
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/code/OpenDDLStream.cpp
@@ -0,0 +1,96 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/OpenDDLStream.h>
+
+BEGIN_ODDLPARSER_NS
+
+StreamFormatterBase::StreamFormatterBase() {
+    // empty
+}
+
+StreamFormatterBase::~StreamFormatterBase() {
+    // empty
+}
+
+std::string StreamFormatterBase::format(const std::string &statement) {
+    std::string tmp(statement);
+    return tmp;
+}
+
+IOStreamBase::IOStreamBase(StreamFormatterBase *formatter) :
+        m_formatter(formatter),
+        m_file(nullptr) {
+    if (nullptr == m_formatter) {
+        m_formatter = new StreamFormatterBase;
+    }
+}
+
+IOStreamBase::~IOStreamBase() {
+    delete m_formatter;
+    m_formatter = nullptr;
+}
+
+bool IOStreamBase::open(const std::string &name) {
+    m_file = ::fopen(name.c_str(), "a");
+    if (m_file == nullptr) {
+        return false;
+    }
+
+    return true;
+}
+
+bool IOStreamBase::close() {
+    if (nullptr == m_file) {
+        return false;
+    }
+
+    ::fclose(m_file);
+    m_file = nullptr;
+
+    return true;
+}
+
+bool IOStreamBase::isOpen() const {
+    return (nullptr != m_file);
+}
+
+size_t IOStreamBase::read(size_t sizeToRead, std::string &statement) {
+    if (nullptr == m_file) {
+        return 0;
+    }
+
+    statement.resize(sizeToRead);
+    const size_t readBytes = ::fread(&statement[0], 1, sizeToRead, m_file);
+
+    return readBytes;
+}
+
+size_t IOStreamBase::write(const std::string &statement) {
+    if (nullptr == m_file) {
+        return 0;
+    }
+    std::string formatStatement = m_formatter->format(statement);
+    return ::fwrite(formatStatement.c_str(), sizeof(char), formatStatement.size(), m_file);
+}
+
+END_ODDLPARSER_NS
diff --git a/libs/assimp/contrib/openddlparser/code/Value.cpp b/libs/assimp/contrib/openddlparser/code/Value.cpp
new file mode 100644
index 0000000..5a8aa39
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/code/Value.cpp
@@ -0,0 +1,438 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/OpenDDLStream.h>
+#include <openddlparser/Value.h>
+
+#include <cassert>
+
+BEGIN_ODDLPARSER_NS
+
+static Value::Iterator end(nullptr);
+
+Value::Iterator::Iterator() :
+        m_start(nullptr),
+        m_current(nullptr) {
+    // empty
+}
+
+Value::Iterator::Iterator(Value *start) :
+        m_start(start),
+        m_current(start) {
+    // empty
+}
+
+Value::Iterator::Iterator(const Iterator &rhs) :
+        m_start(rhs.m_start),
+        m_current(rhs.m_current) {
+    // empty
+}
+
+Value::Iterator::~Iterator() {
+    // empty
+}
+
+bool Value::Iterator::hasNext() const {
+    if (nullptr == m_current) {
+        return false;
+    }
+    return (nullptr != m_current->getNext());
+}
+
+Value *Value::Iterator::getNext() {
+    if (!hasNext()) {
+        return nullptr;
+    }
+
+    Value *v(m_current->getNext());
+    m_current = v;
+
+    return v;
+}
+
+const Value::Iterator Value::Iterator::operator++(int) {
+    if (nullptr == m_current) {
+        return end;
+    }
+
+    m_current = m_current->getNext();
+    Iterator inst(m_current);
+
+    return inst;
+}
+
+Value::Iterator &Value::Iterator::operator++() {
+    if (nullptr == m_current) {
+        return end;
+    }
+
+    m_current = m_current->getNext();
+
+    return *this;
+}
+
+bool Value::Iterator::operator==(const Iterator &rhs) const {
+    return (m_current == rhs.m_current);
+}
+
+Value *Value::Iterator::operator->() const {
+    if (nullptr == m_current) {
+        return nullptr;
+    }
+    return m_current;
+}
+
+Value::Value(ValueType type) :
+        m_type(type),
+        m_size(0),
+        m_data(nullptr),
+        m_next(nullptr) {
+    // empty
+}
+
+Value::~Value() {
+    if (m_data != nullptr) {
+        if (m_type == ValueType::ddl_ref) {
+            Reference *tmp = (Reference *)m_data;
+            if (tmp != nullptr) {
+                delete tmp;
+            }
+        } else {
+            delete[] m_data;
+        }
+    }
+    delete m_next;
+}
+
+void Value::setBool(bool value) {
+    assert(ValueType::ddl_bool == m_type);
+    ::memcpy(m_data, &value, m_size);
+}
+
+bool Value::getBool() {
+    assert(ValueType::ddl_bool == m_type);
+    return (*m_data == 1);
+}
+
+void Value::setInt8(int8 value) {
+    assert(ValueType::ddl_int8 == m_type);
+    ::memcpy(m_data, &value, m_size);
+}
+
+int8 Value::getInt8() {
+    assert(ValueType::ddl_int8 == m_type);
+    return (int8)(*m_data);
+}
+
+void Value::setInt16(int16 value) {
+    assert(ValueType::ddl_int16 == m_type);
+    ::memcpy(m_data, &value, m_size);
+}
+
+int16 Value::getInt16() {
+    assert(ValueType::ddl_int16 == m_type);
+    int16 i;
+    ::memcpy(&i, m_data, m_size);
+    return i;
+}
+
+void Value::setInt32(int32 value) {
+    assert(ValueType::ddl_int32 == m_type);
+    ::memcpy(m_data, &value, m_size);
+}
+
+int32 Value::getInt32() {
+    assert(ValueType::ddl_int32 == m_type);
+    int32 i;
+    ::memcpy(&i, m_data, m_size);
+    return i;
+}
+
+void Value::setInt64(int64 value) {
+    assert(ValueType::ddl_int64 == m_type);
+    ::memcpy(m_data, &value, m_size);
+}
+
+int64 Value::getInt64() {
+    assert(ValueType::ddl_int64 == m_type);
+    int64 i;
+    ::memcpy(&i, m_data, m_size);
+    return i;
+}
+
+void Value::setUnsignedInt8(uint8 value) {
+    assert(ValueType::ddl_unsigned_int8 == m_type);
+    ::memcpy(m_data, &value, m_size);
+}
+
+uint8 Value::getUnsignedInt8() const {
+    assert(ValueType::ddl_unsigned_int8 == m_type);
+    uint8 i;
+    ::memcpy(&i, m_data, m_size);
+    return i;
+}
+
+void Value::setUnsignedInt16(uint16 value) {
+    assert(ValueType::ddl_unsigned_int16 == m_type);
+    ::memcpy(m_data, &value, m_size);
+}
+
+uint16 Value::getUnsignedInt16() const {
+    assert(ValueType::ddl_unsigned_int16 == m_type);
+    uint16 i;
+    ::memcpy(&i, m_data, m_size);
+    return i;
+}
+
+void Value::setUnsignedInt32(uint32 value) {
+    assert(ValueType::ddl_unsigned_int32 == m_type);
+    ::memcpy(m_data, &value, m_size);
+}
+
+uint32 Value::getUnsignedInt32() const {
+    assert(ValueType::ddl_unsigned_int32 == m_type);
+    uint32 i;
+    ::memcpy(&i, m_data, m_size);
+    return i;
+}
+
+void Value::setUnsignedInt64(uint64 value) {
+    assert(ValueType::ddl_unsigned_int64 == m_type);
+    ::memcpy(m_data, &value, m_size);
+}
+
+uint64 Value::getUnsignedInt64() const {
+    assert(ValueType::ddl_unsigned_int64 == m_type);
+    uint64 i;
+    ::memcpy(&i, m_data, m_size);
+    return i;
+}
+
+void Value::setFloat(float value) {
+    assert(ValueType::ddl_float == m_type);
+    ::memcpy(m_data, &value, m_size);
+}
+
+float Value::getFloat() const {
+    if (m_type == ValueType::ddl_float) {
+        float v;
+        ::memcpy(&v, m_data, m_size);
+        return (float)v;
+    } else {
+        float tmp;
+        ::memcpy(&tmp, m_data, 4);
+        return (float)tmp;
+    }
+}
+
+void Value::setDouble(double value) {
+    assert(ValueType::ddl_double == m_type);
+    ::memcpy(m_data, &value, m_size);
+}
+
+double Value::getDouble() const {
+    if (m_type == ValueType::ddl_double) {
+        double v;
+        ::memcpy(&v, m_data, m_size);
+        return (float)v;
+    } else {
+        double tmp;
+        ::memcpy(&tmp, m_data, 4);
+        return (double)tmp;
+    }
+}
+
+void Value::setString(const std::string &str) {
+    assert(ValueType::ddl_string == m_type);
+    ::memcpy(m_data, str.c_str(), str.size());
+    m_data[str.size()] = '\0';
+}
+
+const char *Value::getString() const {
+    assert(ValueType::ddl_string == m_type);
+    return (const char *)m_data;
+}
+
+void Value::setRef(Reference *ref) {
+    assert(ValueType::ddl_ref == m_type);
+
+    if (nullptr != ref) {
+        const size_t sizeInBytes(ref->sizeInBytes());
+        if (sizeInBytes > 0) {
+            if (nullptr != m_data) {
+                delete[] m_data;
+            }
+
+            m_data = (unsigned char *)new Reference(*ref);
+        }
+    }
+}
+
+Reference *Value::getRef() const {
+    assert(ValueType::ddl_ref == m_type);
+
+    return (Reference *)m_data;
+}
+
+void Value::dump(IOStreamBase &stream) {
+    switch (m_type) {
+        case ValueType::ddl_none:
+            stream.write("None\n");
+            break;
+        case ValueType::ddl_bool:
+            stream.write(std::to_string(getBool()) + "\n");
+            break;
+        case ValueType::ddl_int8:
+            stream.write(std::to_string(getInt8()) + "\n");
+            break;
+        case ValueType::ddl_int16:
+            stream.write(std::to_string(getInt16()) + "\n");
+            break;
+        case ValueType::ddl_int32:
+            stream.write(std::to_string(getInt32()) + "\n");
+            break;
+        case ValueType::ddl_int64:
+            stream.write(std::to_string(getInt64()) + "\n");
+            break;
+        case ValueType::ddl_unsigned_int8:
+            stream.write("Not supported\n");
+            break;
+        case ValueType::ddl_unsigned_int16:
+            stream.write("Not supported\n");
+            break;
+        case ValueType::ddl_unsigned_int32:
+            stream.write("Not supported\n");
+            break;
+        case ValueType::ddl_unsigned_int64:
+            stream.write("Not supported\n");
+            break;
+        case ValueType::ddl_half:
+            stream.write("Not supported\n");
+            break;
+        case ValueType::ddl_float:
+            stream.write(std::to_string(getFloat()) + "\n");
+            break;
+        case ValueType::ddl_double:
+            stream.write(std::to_string(getDouble()) + "\n");
+            break;
+        case ValueType::ddl_string:
+            stream.write(std::string(getString()) + "\n");
+            break;
+        case ValueType::ddl_ref:
+            stream.write("Not supported\n");
+            break;
+        default:
+            break;
+    }
+}
+
+void Value::setNext(Value *next) {
+    m_next = next;
+}
+
+Value *Value::getNext() const {
+    return m_next;
+}
+
+size_t Value::size() const {
+    size_t result = 1;
+    Value *n = m_next;
+    while (n != nullptr) {
+        result++;
+        n = n->m_next;
+    }
+    return result;
+}
+
+Value *ValueAllocator::allocPrimData(Value::ValueType type, size_t len) {
+    if (type == Value::ValueType::ddl_none || Value::ValueType::ddl_types_max == type) {
+        return nullptr;
+    }
+
+    Value *data = new Value(type);
+    switch (type) {
+        case Value::ValueType::ddl_bool:
+            data->m_size = sizeof(bool);
+            break;
+        case Value::ValueType::ddl_int8:
+            data->m_size = sizeof(int8);
+            break;
+        case Value::ValueType::ddl_int16:
+            data->m_size = sizeof(int16);
+            break;
+        case Value::ValueType::ddl_int32:
+            data->m_size = sizeof(int32);
+            break;
+        case Value::ValueType::ddl_int64:
+            data->m_size = sizeof(int64);
+            break;
+        case Value::ValueType::ddl_unsigned_int8:
+            data->m_size = sizeof(uint8);
+            break;
+        case Value::ValueType::ddl_unsigned_int16:
+            data->m_size = sizeof(uint16);
+            break;
+        case Value::ValueType::ddl_unsigned_int32:
+            data->m_size = sizeof(uint32);
+            break;
+        case Value::ValueType::ddl_unsigned_int64:
+            data->m_size = sizeof(uint64);
+            break;
+        case Value::ValueType::ddl_half:
+            data->m_size = sizeof(short);
+            break;
+        case Value::ValueType::ddl_float:
+            data->m_size = sizeof(float);
+            break;
+        case Value::ValueType::ddl_double:
+            data->m_size = sizeof(double);
+            break;
+        case Value::ValueType::ddl_string:
+            data->m_size = sizeof(char) * (len + 1);
+            break;
+        case Value::ValueType::ddl_ref:
+            data->m_size = 0;
+            break;
+        case Value::ValueType::ddl_none:
+        case Value::ValueType::ddl_types_max:
+        default:
+            break;
+    }
+
+    if (data->m_size) {
+        data->m_data = new unsigned char[data->m_size];
+        ::memset(data->m_data, 0, data->m_size);
+    }
+
+    return data;
+}
+
+void ValueAllocator::releasePrimData(Value **data) {
+    if (!data) {
+        return;
+    }
+
+    delete *data;
+    *data = nullptr;
+}
+
+END_ODDLPARSER_NS
diff --git a/libs/assimp/contrib/openddlparser/include/openddlparser/DDLNode.h b/libs/assimp/contrib/openddlparser/include/openddlparser/DDLNode.h
new file mode 100644
index 0000000..593a5f1
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/include/openddlparser/DDLNode.h
@@ -0,0 +1,173 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/OpenDDLCommon.h>
+
+#include <string>
+#include <vector>
+
+BEGIN_ODDLPARSER_NS
+
+// Forward declarations
+class IOStreamBase;
+class Value;
+class OpenDDLParser;
+
+struct Identifier;
+struct Reference;
+struct Property;
+struct DataArrayList;
+
+///
+/// @ingroup    OpenDDLParser
+///	@brief      This class represents one single instance in the object tree of the parsed OpenDDL-file.
+///
+/// A DDLNode represents one leaf in the OpenDDL-node tree. It can have one parent node and multiple children.
+/// You can assign special properties to a single DDLNode instance.
+///	A node instance can store values via a linked list. You can get the first value from the DDLNode.
+/// A node can store data-array-lists and references as well.
+///
+class DLL_ODDLPARSER_EXPORT DDLNode {
+public:
+    friend class OpenDDLParser;
+
+    /// @brief  The child-node-list type.
+    typedef std::vector<DDLNode *> DllNodeList;
+
+    /// @brief  The child-node-list iterator.
+    typedef std::vector<DDLNode *>::iterator DDLNodeIt;
+
+public:
+    ///	@brief  The class destructor.
+    ~DDLNode();
+
+    ///	@brief  Will attach a parent node instance, an older one will be released.
+    /// @param  parent      [in] The parent node instance.
+    void attachParent(DDLNode *parent);
+
+    /// @brief  Will try to detach a parent node instance, if there is any.
+    void detachParent();
+
+    ///	@brief  Returns the assigned parent node instance, will return ddl_nullptr id no parent is assigned.
+    /// @return The parent node instance.
+    DDLNode *getParent() const;
+
+    ///	@brief  Returns the child node list.
+    /// @return The list of child nodes.
+    const DllNodeList &getChildNodeList() const;
+
+    /// Set the type of the DDLNode instance.
+    /// @param  type    [in] The type.
+    void setType(const std::string &type);
+
+    /// @brief  Returns the type of the DDLNode instance.
+    /// @return The type of the DDLNode instance.
+    const std::string &getType() const;
+
+    /// Set the name of the DDLNode instance.
+    /// @param  name        [in] The name.
+    void setName(const std::string &name);
+
+    /// @brief  Returns the name of the DDLNode instance.
+    /// @return The name of the DDLNode instance.
+    const std::string &getName() const;
+
+    /// @brief  Set a new property set.
+    ///	@param  prop        [in] The first element of the property set.
+    void setProperties(Property *prop);
+
+    ///	@brief  Returns the first element of the assigned property set.
+    ///	@return The first property of the assigned property set.
+    Property *getProperties() const;
+
+    ///	@brief  Looks for a given property.
+    /// @param  name        [in] The name for the property to look for.
+    /// @return true, if a corresponding property is assigned to the node, false if not.
+    bool hasProperty(const std::string &name);
+
+    ///	@brief  Will return true, if any properties are assigned to the node instance.
+    ///	@return True, if properties are assigned.
+    bool hasProperties() const;
+
+    ///	@brief  Search for a given property and returns it. Will return ddl_nullptr if no property was found.
+    /// @param  name        [in] The name for the property to look for.
+    /// @return The property or ddl_nullptr if no property was found.
+    Property *findPropertyByName(const std::string &name);
+
+    /// @brief  Set a new value set.
+    /// @param  val         [in] The first value instance of the value set.
+    void setValue(Value *val);
+
+    ///	@brief  Returns the first element of the assigned value set.
+    ///	@return The first property of the assigned value set.
+    Value *getValue() const;
+
+    /// @brief  Set a new DataArrayList.
+    /// @param  dtArrayList [in] The DataArrayList instance.
+    void setDataArrayList(DataArrayList *dtArrayList);
+
+    ///	@brief  Returns the DataArrayList.
+    ///	@return The DataArrayList.
+    DataArrayList *getDataArrayList() const;
+
+    /// @brief  Set a new Reference set.
+    /// @param  refs        [in] The first value instance of the Reference set.
+    void setReferences(Reference *refs);
+
+    ///	@brief  Returns the first element of the assigned Reference set.
+    ///	@return The first property of the assigned Reference set.
+    Reference *getReferences() const;
+
+    /// @brief  Will dump the node into the stream.
+    /// @param  stream      [in] The stream to write to.
+    void dump(IOStreamBase &stream);
+
+    ///	@brief  The creation method.
+    /// @param  type        [in] The DDLNode type.
+    ///	@param  name        [in] The name for the new DDLNode instance.
+    /// @param  parent      [in] The parent node instance or ddl_nullptr if no parent node is there.
+    /// @return The new created node instance.
+    static DDLNode *create(const std::string &type, const std::string &name, DDLNode *parent = nullptr);
+
+private:
+    DDLNode(const std::string &type, const std::string &name, size_t idx, DDLNode *parent = nullptr);
+    DDLNode();
+    DDLNode(const DDLNode &) ddl_no_copy;
+    DDLNode &operator=(const DDLNode &) ddl_no_copy;
+    static void releaseNodes();
+
+private:
+    std::string m_type;
+    std::string m_name;
+    DDLNode *m_parent;
+    std::vector<DDLNode *> m_children;
+    Property *m_properties;
+    Value *m_value;
+    DataArrayList *m_dtArrayList;
+    Reference *m_references;
+    size_t m_idx;
+    static DllNodeList s_allocatedNodes;
+};
+
+END_ODDLPARSER_NS
diff --git a/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h b/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
new file mode 100644
index 0000000..6ccc83b
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
@@ -0,0 +1,245 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <cstddef>
+#include <string>
+#include <vector>
+
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32
+#include <inttypes.h>
+#endif
+
+#if defined(_MSC_VER) && !defined(OPENDDL_STATIC_LIBARY)
+
+#define TAG_DLL_EXPORT __declspec(dllexport)
+#define TAG_DLL_IMPORT __declspec(dllimport)
+#ifdef OPENDDLPARSER_BUILD
+#define DLL_ODDLPARSER_EXPORT TAG_DLL_EXPORT
+#else
+#define DLL_ODDLPARSER_EXPORT TAG_DLL_IMPORT
+#endif // OPENDDLPARSER_BUILD
+#pragma warning(disable : 4251)
+#else
+#define DLL_ODDLPARSER_EXPORT
+#endif // _WIN32
+
+// Namespace declarations, override this to avoid any conflicts
+#define BEGIN_ODDLPARSER_NS namespace ODDLParser {
+#define END_ODDLPARSER_NS } // namespace ODDLParser
+#define USE_ODDLPARSER_NS using namespace ODDLParser;
+
+BEGIN_ODDLPARSER_NS
+
+// We will use C++11 optional
+#ifndef OPENDDL_NO_USE_CPP11
+// All C++11 constructs
+#define nullptr nullptr
+#define ddl_override override
+#define ddl_final final
+#define ddl_no_copy = delete
+#else
+// Fall-back for older compilers
+#define nullptr NULL
+#define ddl_override
+#define ddl_final
+#define ddl_no_copy
+#endif // OPENDDL_NO_USE_CPP11
+
+// Forward declarations
+class DDLNode;
+class Value;
+
+struct Name;
+struct Identifier;
+struct Reference;
+struct Property;
+struct DataArrayList;
+
+// Platform-specific typedefs
+#ifdef _WIN32
+typedef signed __int64 int64_impl;
+typedef unsigned __int64 uint64_impl;
+#else
+typedef int64_t int64_impl;
+typedef uint64_t uint64_impl;
+#endif
+
+// OpenDDL-specific data typedefs
+using int8 = signed char; ///< Signed integer, 1 byte
+using int16 = signed short; ///< Signed integer, 2 byte
+using int32 = signed int; ///< Signed integer, 4 byte
+using int64 = int64_impl; ///< Signed integer, 8 byte
+using uint8 = unsigned char; ///< Unsigned integer, 1 byte
+using uint16 = unsigned short ; ///< Unsigned integer, 2 byte
+using uint32 = unsigned int; ///< Unsigned integer, 4 byte
+using uint64 = uint64_impl ; ///< Unsigned integer, 8 byte
+
+///	@brief  Stores a text.
+///
+/// A text is stored in a simple character buffer. Texts buffer can be
+/// greater than the number of stored characters in them.
+struct DLL_ODDLPARSER_EXPORT Text {
+    size_t m_capacity; ///< The capacity of the text.
+    size_t m_len; ///< The length of the text.
+    char *m_buffer; ///< The buffer with the text.
+
+    ///	@brief  The constructor with a given text buffer.
+    /// @param  buffer      [in] The buffer.
+    /// @param  numChars    [in] The number of characters in the buffer.
+    Text(const char *buffer, size_t numChars);
+
+    ///	@brief  The destructor.
+    ~Text();
+
+    ///	@brief  Clears the text.
+    void clear();
+
+    ///	@brief  Set a new text.
+    /// @param  buffer      [in] The buffer.
+    /// @param  numChars    [in] The number of characters in the buffer.
+    void set(const char *buffer, size_t numChars);
+
+    ///	@brief  The compare operator for std::strings.
+    bool operator==(const std::string &name) const;
+
+    ///	@brief  The compare operator for Texts.
+    bool operator==(const Text &rhs) const;
+
+private:
+    Text(const Text &) ddl_no_copy;
+    Text &operator=(const Text &) ddl_no_copy;
+};
+
+///	@brief  Description of the type of a name.
+enum NameType {
+    GlobalName, ///< Name is global.
+    LocalName ///< Name is local.
+};
+
+///	@brief  Stores an OpenDDL-specific name
+struct DLL_ODDLPARSER_EXPORT Name {
+    NameType m_type; ///< The type of the name ( @see NameType ).
+    Text *m_id; ///< The id.
+
+    ///	@brief  The constructor with the type and the id.
+    ///	@param  type    [in] The name type.
+    ///	@param  id      [in] The id.
+    Name(NameType type, Text *id);
+    Name(const Name &name);
+    ///	@brief  The destructor.
+    ~Name();
+
+private:
+    Name &operator=(const Name &) ddl_no_copy;
+};
+
+///	@brief  Stores a bundle of references.
+struct DLL_ODDLPARSER_EXPORT Reference {
+    size_t m_numRefs; ///< The number of stored references.
+    Name **m_referencedName; ///< The reference names.
+
+    ///	@brief  The default constructor.
+    Reference();
+    Reference(const Reference &ref);
+    ///	@brief  The constructor with an array of ref names.
+    /// @param  numrefs     [in] The number of ref names.
+    /// @param  names       [in] The ref names.
+    Reference(size_t numrefs, Name **names);
+
+    ///	@brief  The destructor.
+    ~Reference();
+
+    /// @brief  Returns the size in bytes to store one deep reference copy.
+    /// @return The size on bytes.
+    size_t sizeInBytes();
+
+private:
+    Reference &operator=(const Reference &) ddl_no_copy;
+};
+
+///	@brief  Stores a property list.
+struct DLL_ODDLPARSER_EXPORT Property {
+    Text *m_key; ///< The identifier / key of the property.
+    Value *m_value; ///< The value assigned to its key / id ( ddl_nullptr if none ).
+    Reference *m_ref; ///< References assigned to its key / id ( ddl_nullptr if none ).
+    Property *m_next; ///< The next property ( ddl_nullptr if none ).
+
+    ///	@brief  The default constructor.
+    Property();
+
+    ///	@brief  The constructor for initialization.
+    /// @param  id      [in] The identifier
+    Property(Text *id);
+
+    ///	@brief  The destructor.
+    ~Property();
+
+private:
+    Property(const Property &) ddl_no_copy;
+    Property &operator=(const Property &) ddl_no_copy;
+};
+
+///	@brief  Stores a data array list.
+struct DLL_ODDLPARSER_EXPORT DataArrayList {
+    size_t m_numItems; ///< The number of items in the list.
+    Value *m_dataList; ///< The data list ( a Value ).
+    DataArrayList *m_next; ///< The next data array list ( ddl_nullptr if last ).
+    Reference *m_refs;
+    size_t m_numRefs;
+
+    ///	@brief  The default constructor for initialization.
+    DataArrayList();
+
+    ///	@brief  The destructor.
+    ~DataArrayList();
+
+    /// @brief  Gets the length of the array
+    size_t size();
+
+private:
+    DataArrayList(const DataArrayList &) ddl_no_copy;
+    DataArrayList &operator=(const DataArrayList &) ddl_no_copy;
+};
+
+///	@brief  Stores the context of a parsed OpenDDL declaration.
+struct DLL_ODDLPARSER_EXPORT Context {
+    DDLNode *m_root; ///< The root node of the OpenDDL node tree.
+
+    ///	@brief  Constructor for initialization.
+    Context();
+
+    ///	@brief  Destructor.
+    ~Context();
+
+    ///	@brief  Clears the whole node tree.
+    void clear();
+
+private:
+    Context(const Context &) ddl_no_copy;
+    Context &operator=(const Context &) ddl_no_copy;
+};
+
+END_ODDLPARSER_NS
diff --git a/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLExport.h b/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLExport.h
new file mode 100644
index 0000000..9452535
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLExport.h
@@ -0,0 +1,80 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/OpenDDLCommon.h>
+#include <openddlparser/OpenDDLStream.h>
+#include <openddlparser/Value.h>
+
+BEGIN_ODDLPARSER_NS
+
+// Forward declarations
+class IOStreamBase;
+
+//-------------------------------------------------------------------------------------------------
+///
+/// @ingroup    OpenDDLParser
+///	@brief      This class represents the OpenDDLExporter.
+///
+//-------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT OpenDDLExport {
+public:
+    ///	@brief  The class constructor
+    OpenDDLExport(IOStreamBase *stream = nullptr);
+
+    ///	@brief  The class destructor.
+    ~OpenDDLExport();
+
+    ///	@brief  Export the data of a parser context.
+    /// @param  ctx         [in] Pointer to the context.
+    /// @param  filename    [in] The filename for the export.
+    /// @return True in case of success, false in case of an error.
+    bool exportContext(Context *ctx, const std::string &filename);
+
+    ///	@brief  Handles a node export.
+    /// @param  node        [in] The node to handle with.
+    /// @return True in case of success, false in case of an error.
+    bool handleNode(DDLNode *node);
+
+    ///	@brief  Writes the statement to the stream.
+    /// @param  statement   [in]  The content to write.
+    /// @return True in case of success, false in case of an error.
+    bool writeToStream(const std::string &statement);
+
+protected:
+    bool writeNode(DDLNode *node, std::string &statement);
+    bool writeNodeHeader(DDLNode *node, std::string &statement);
+    bool writeProperties(DDLNode *node, std::string &statement);
+    bool writeValueType(Value::ValueType type, size_t numItems, std::string &statement);
+    bool writeValue(Value *val, std::string &statement);
+    bool writeValueArray(DataArrayList *al, std::string &statement);
+
+private:
+    OpenDDLExport(const OpenDDLExport &) ddl_no_copy;
+    OpenDDLExport &operator=(const OpenDDLExport &) ddl_no_copy;
+
+private:
+    IOStreamBase *m_stream;
+};
+
+END_ODDLPARSER_NS
diff --git a/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParser.h b/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParser.h
new file mode 100644
index 0000000..3fbb4b6
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParser.h
@@ -0,0 +1,206 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/DDLNode.h>
+#include <openddlparser/OpenDDLCommon.h>
+#include <openddlparser/OpenDDLParserUtils.h>
+#include <openddlparser/Value.h>
+
+#include <string>
+#include <vector>
+#include <functional>
+
+BEGIN_ODDLPARSER_NS
+
+class DDLNode;
+class Value;
+
+struct Identifier;
+struct Reference;
+struct Property;
+
+template <class T>
+inline bool isEmbeddedCommentOpenTag(T *in, T *end) {
+    if (in == '/' && in + 1 == '*') {
+        return true;
+    }
+
+    return false;
+}
+
+///	@brief  Utility function to search for the next token or the end of the buffer.
+/// @param  in      [in] The start position in the buffer.
+/// @param  end     [in] The end position in the buffer.
+///	@return Pointer showing to the next token or the end of the buffer.
+///	@detail Will not increase buffer when already a valid buffer was found.
+template <class T>
+inline T *lookForNextToken(T *in, T *end) {
+    while ((in != end) && (isSpace(*in) || isNewLine(*in) || ',' == *in)) {
+        ++in;
+    }
+    return in;
+}
+
+///	@brief  Utility function to go for the next token or the end of the buffer.
+/// @param  in      [in] The start position in the buffer.
+/// @param  end     [in] The end position in the buffer.
+///	@return Pointer showing to the next token or the end of the buffer.
+///	@detail Will  increase buffer by a minimum of one.
+template <class T>
+inline T *getNextToken(T *in, T *end) {
+    T *tmp(in);
+    in = lookForNextToken(in, end);
+    if (tmp == in) {
+        ++in;
+    }
+    return in;
+}
+
+///	@brief  Defines the log severity.
+enum LogSeverity {
+    ddl_debug_msg = 0, ///< Debug message, for debugging
+    ddl_info_msg, ///< Info messages, normal mode
+    ddl_warn_msg, ///< Parser warnings
+    ddl_error_msg ///< Parser errors
+};
+
+DLL_ODDLPARSER_EXPORT const char *getTypeToken(Value::ValueType type);
+
+//-------------------------------------------------------------------------------------------------
+///	@class		OpenDDLParser
+///	@ingroup	OpenDDLParser
+
+///
+///	@brief  This is the main API for the OpenDDL-parser.
+///
+/// Use instances of this class to manage the parsing and handling of your parser contexts.
+//-------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT OpenDDLParser {
+public:
+    ///	@brief  The log callback function.
+    typedef std::function<void (LogSeverity severity, const std::string &msg)> logCallback;
+
+public:
+    ///	@brief  The default class constructor.
+    OpenDDLParser();
+
+    ///	@brief  The class constructor.
+    ///	@param  buffer      [in] The buffer
+    ///	@param  len         [in] Size of the buffer
+    OpenDDLParser(const char *buffer, size_t len);
+
+    ///	@brief  The class destructor.
+    ~OpenDDLParser();
+
+    ///	@brief  Setter for an own log callback function.
+    /// @param  callback    [in] The own callback.
+    void setLogCallback(logCallback callback);
+
+    ///	@brief  Getter for the log callback.
+    /// @return The current log callback.
+    logCallback getLogCallback() const;
+
+    /// @brief  A default log callback that writes to a FILE.
+    /// @param  destination [in] Output stream. NULL will use stderr.
+    /// @return A callback that you can pass to setLogCallback.
+    static logCallback StdLogCallback(FILE *destination = nullptr);
+
+    ///	@brief  Assigns a new buffer to parse.
+    ///	@param  buffer      [in] The buffer
+    ///	@param  len         [in] Size of the buffer
+    void setBuffer(const char *buffer, size_t len);
+
+    ///	@brief  Assigns a new buffer to parse.
+    /// @param  buffer      [in] The buffer as a std::vector.
+    void setBuffer(const std::vector<char> &buffer);
+
+    ///	@brief  Returns the buffer pointer.
+    /// @return The buffer pointer.
+    const char *getBuffer() const;
+
+    /// @brief  Returns the size of the buffer.
+    /// @return The buffer size.
+    size_t getBufferSize() const;
+
+    ///	@brief  Clears all parser data, including buffer and active context.
+    void clear();
+
+    bool validate();
+
+    ///	@brief  Starts the parsing of the OpenDDL-file.
+    /// @return True in case of success, false in case of an error.
+    /// @remark In case of errors check log.
+    bool parse();
+
+    
+    bool exportContext(Context *ctx, const std::string &filename);
+
+    ///	@brief  Returns the root node.
+    /// @return The root node.
+    DDLNode *getRoot() const;
+
+    ///	@brief  Returns the parser context, only available in case of a succeeded parsing.
+    /// @return Pointer to the active context or ddl_nullptr.
+    Context *getContext() const;
+
+public: // parser helpers
+    char *parseNextNode(char *current, char *end);
+    char *parseHeader(char *in, char *end);
+    char *parseStructure(char *in, char *end);
+    char *parseStructureBody(char *in, char *end, bool &error);
+    void pushNode(DDLNode *node);
+    DDLNode *popNode();
+    DDLNode *top();
+    static void normalizeBuffer(std::vector<char> &buffer);
+    static char *parseName(char *in, char *end, Name **name);
+    static char *parseIdentifier(char *in, char *end, Text **id);
+    static char *parsePrimitiveDataType(char *in, char *end, Value::ValueType &type, size_t &len);
+    static char *parseReference(char *in, char *end, std::vector<Name *> &names);
+    static char *parseBooleanLiteral(char *in, char *end, Value **boolean);
+    static char *parseIntegerLiteral(char *in, char *end, Value **integer, Value::ValueType integerType = Value::ValueType::ddl_int32);
+    static char *parseFloatingLiteral(char *in, char *end, Value **floating, Value::ValueType floatType = Value::ValueType::ddl_float);
+    static char *parseStringLiteral(char *in, char *end, Value **stringData);
+    static char *parseHexaLiteral(char *in, char *end, Value **data);
+    static char *parseProperty(char *in, char *end, Property **prop);
+    static char *parseDataList(char *in, char *end, Value::ValueType type, Value **data, size_t &numValues, Reference **refs, size_t &numRefs);
+    static char *parseDataArrayList(char *in, char *end, Value::ValueType type, DataArrayList **dataList);
+    static const char *getVersion();
+
+private:
+    OpenDDLParser(const OpenDDLParser &) ddl_no_copy;
+    OpenDDLParser &operator=(const OpenDDLParser &) ddl_no_copy;
+
+private:
+    logCallback m_logCallback;
+    std::vector<char> m_buffer;
+
+    typedef std::vector<DDLNode *> DDLNodeStack;
+    DDLNodeStack m_stack;
+    Context *m_context;
+
+    ///	@brief  Callback for StdLogCallback(). Not meant to be called directly.
+    static void logToStream (FILE *, LogSeverity, const std::string &);
+};
+
+END_ODDLPARSER_NS
diff --git a/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h b/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
new file mode 100644
index 0000000..42ad675
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
@@ -0,0 +1,503 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/OpenDDLCommon.h>
+
+BEGIN_ODDLPARSER_NS
+
+template <class T>
+inline bool isUpperCase(T in) {
+    return (in >= 'A' && in <= 'Z');
+}
+
+template <class T>
+inline bool isLowerCase(T in) {
+    return (in >= 'a' && in <= 'z');
+}
+
+template <class T>
+inline bool isSpace(const T in) {
+    return (' ' == in || '\t' == in);
+}
+
+template <class T>
+inline bool isNewLine(const T in) {
+    return ('\n' == in || ('\r' == in));
+}
+
+template <class T>
+inline bool isSeparator(T in) {
+    if (isSpace(in) || ',' == in || '{' == in || '}' == in || '[' == in || '(' == in || ')' == in) {
+        return true;
+    }
+    return false;
+}
+
+static const unsigned char chartype_table[256] = {
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 0-15
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 16-31
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 32-47
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    0,
+    0,
+    0,
+    0,
+    0, // 48-63
+
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 64-79
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 80-95
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 96-111
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 112-127
+
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // > 127
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+};
+
+template <class T>
+inline bool isNumeric(const T in) {
+    size_t idx = static_cast<size_t>(in);
+    return idx < sizeof(chartype_table) && (chartype_table[idx] == 1);
+}
+
+template <class T>
+inline bool isNotEndOfToken(T *in, T *end) {
+    return ('}' != *in && ',' != *in && !isSpace(*in) && ')' != *in && in != end);
+}
+
+template <class T>
+inline bool isInteger(T *in, T *end) {
+    if (in != end) {
+        if (*in == '-') {
+            ++in;
+        }
+    }
+
+    bool result(false);
+    while (isNotEndOfToken(in, end)) {
+        result = isNumeric(*in);
+        if (!result) {
+            break;
+        }
+        ++in;
+    }
+
+    return result;
+}
+
+template <class T>
+inline bool isFloat(T *in, T *end) {
+    if (in != end) {
+        if (*in == '-') {
+            ++in;
+        }
+    }
+
+    // check for <1>.0f
+    bool result(false);
+    while (isNotEndOfToken(in, end)) {
+        if (*in == '.') {
+            result = true;
+            break;
+        }
+        result = isNumeric(*in);
+        if (!result) {
+            return false;
+        }
+        ++in;
+    }
+
+    // check for 1<.>0f
+    if (*in == '.') {
+        ++in;
+    } else {
+        return false;
+    }
+
+    // check for 1.<0>f
+    while (isNotEndOfToken(in, end)) {
+        result = isNumeric(*in);
+        if (!result) {
+            return false;
+        }
+        ++in;
+    }
+
+    return result;
+}
+
+template <class T>
+inline bool isCharacter(const T in) {
+    return ((in >= 'a' && in <= 'z') || (in >= 'A' && in <= 'Z'));
+}
+
+template <class T>
+inline bool isStringLiteral(const T in) {
+    return (in == '\"');
+}
+
+template <class T>
+inline bool isHexLiteral(T *in, T *end) {
+    if (*in == '0') {
+        if (in + 1 != end) {
+            if (*(in + 1) == 'x' || *(in + 1) == 'X') {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+template <class T>
+inline bool isReference(T *in, T *end) {
+    if (*in == 'r') {
+        if (*(in + 1) == 'e') {
+            if (*(in + 2) == 'f') {
+                if ((in + 2) != end) {
+                    return true;
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
+template <class T>
+inline bool isEndofLine(const T in) {
+    return ('\n' == in);
+}
+
+template <class T>
+inline static T *getNextSeparator(T *in, T *end) {
+    while (!isSeparator(*in) || in == end) {
+        ++in;
+    }
+    return in;
+}
+
+static const int ErrorHex2Decimal = 9999999;
+
+inline int hex2Decimal(char in) {
+    if (isNumeric(in)) {
+        return (in - 48);
+    }
+
+    char hexCodeLower('a'), hexCodeUpper('A');
+    for (int i = 0; i < 16; i++) {
+        if (in == hexCodeLower + i || in == hexCodeUpper + i) {
+            return (i + 10);
+        }
+    }
+
+    return ErrorHex2Decimal;
+}
+
+template <class T>
+inline bool isComment(T *in, T *end) {
+    if (*in == '/') {
+        if (in + 1 != end) {
+            if (*(in + 1) == '/') {
+                char *drive((in + 2));
+                if ((isUpperCase<T>(*drive) || isLowerCase<T>(*drive)) && *(drive + 1) == '/') {
+                    return false;
+                } else {
+                    return true;
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
+template <class T>
+inline bool isCommentOpenTag(T *in, T *end) {
+    if (*in == '/') {
+        if (in + 1 != end) {
+            if (*(in + 1) == '*') {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+template <class T>
+inline bool isCommentCloseTag(T *in, T *end) {
+    if (*in == '*') {
+        if (in + 1 != end) {
+            if (*(in + 1) == '/') {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+END_ODDLPARSER_NS
diff --git a/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLStream.h b/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLStream.h
new file mode 100644
index 0000000..93bde5f
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/include/openddlparser/OpenDDLStream.h
@@ -0,0 +1,89 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/OpenDDLCommon.h>
+
+BEGIN_ODDLPARSER_NS
+
+//-------------------------------------------------------------------------------------------------
+/// @ingroup    IOStreamBase
+///	@brief      This class represents the stream to write out.
+//-------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT StreamFormatterBase {
+public:
+    /// @brief  The class constructor.
+    StreamFormatterBase();
+
+    /// @brief  The class destructor, virtual.
+    virtual ~StreamFormatterBase();
+
+    /// @brief  Will format the string and return the new formatted result.
+    /// @param  statement   [in] The string to reformat.
+    /// @return The reformatted result.
+    virtual std::string format(const std::string &statement);
+};
+
+//-------------------------------------------------------------------------------------------------
+/// @ingroup    IOStreamBase
+///	@brief      This class represents the stream to write out.
+//-------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT IOStreamBase {
+public:
+    /// @brief  The class constructor with the formatter.
+    /// @param  formatter   [in] The formatter to use.
+    explicit IOStreamBase(StreamFormatterBase *formatter = nullptr);
+
+    /// @brief  The class destructor, virtual.
+    virtual ~IOStreamBase();
+
+    /// @brief  Will open the stream.
+    /// @param  name        [in] The name for the stream.
+    /// @return true, if the stream was opened successfully, false if not.
+    virtual bool open(const std::string &name);
+
+    /// @brief  Will close the stream.
+    /// @return true, if the stream was closed successfully, false if not.
+    virtual bool close();
+
+    /// @brief  Returns true, if the stream is open.
+    /// @return true, if the stream is open, false if not.
+    virtual bool isOpen() const;
+
+    /// @brief  Will read a string from the stream.
+    /// @param  sizeToRead  [in] The size to read in bytes.
+    /// @param  statement   [out] The read statements.
+    /// @return The bytes read from the stream.
+    virtual size_t read(size_t sizeToRead, std::string &statement);
+
+    /// @brief  Will write a string into the stream.
+    /// @param  statement  [in] The string to write.
+    /// @return The bytes written into the stream.
+    virtual size_t write(const std::string &statement);
+
+private:
+    StreamFormatterBase *m_formatter;
+    FILE *m_file;
+};
+
+END_ODDLPARSER_NS
diff --git a/libs/assimp/contrib/openddlparser/include/openddlparser/TPoolAllocator.h b/libs/assimp/contrib/openddlparser/include/openddlparser/TPoolAllocator.h
new file mode 100644
index 0000000..6076c73
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/include/openddlparser/TPoolAllocator.h
@@ -0,0 +1,226 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2019 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/OpenDDLCommon.h>
+#include <string>
+
+BEGIN_ODDLPARSER_NS
+
+//-------------------------------------------------------------------------------------------------
+///	@class		TPoolAllocator
+///	@ingroup	CPPCore
+///
+///	@brief  This class implements a simple pool-based allocation scheme.
+/// Initially you have to define its size. Each allocation will be done from this initially created
+/// pool. You have to release all pooled instances after the usage.
+/// This allocation scheme is fast and does no call any new-calls during the lifetime of the
+/// allocator.
+//-------------------------------------------------------------------------------------------------
+template <class T>
+class TPoolAllocator {
+public:
+    TPoolAllocator();
+    TPoolAllocator(size_t numItems);
+    ~TPoolAllocator();
+    T *alloc();
+    void release();
+    void reserve(size_t size);
+    void clear();
+    size_t capacity() const;
+    size_t reservedMem() const;
+    size_t freeMem() const;
+    void dumpAllocations(std::string &allocs);
+    void resize(size_t growSize);
+
+    CPPCORE_NONE_COPYING(TPoolAllocator)
+
+private:
+    struct Pool {
+        size_t m_poolsize;
+        T *m_pool;
+        size_t m_currentIdx;
+        Pool *m_next;
+
+        Pool() :
+                m_poolsize(0u), m_pool(nullptr), m_currentIdx(0u), m_next(nullptr) {
+            // empty
+        }
+
+        Pool(size_t numItems, Pool *prev) :
+                m_poolsize(numItems), m_pool(nullptr), m_currentIdx(0u), m_next(prev) {
+            m_pool = new T[m_poolsize];
+        }
+
+        ~Pool() {
+            delete[] m_pool;
+            m_pool = nullptr;
+        }
+
+        CPPCORE_NONE_COPYING(Pool)
+    };
+
+    Pool *getFreePool() {
+        Pool *current(m_freeList);
+        if (nullptr != m_freeList) {
+            m_freeList = m_freeList->m_next;
+        }
+        return current;
+    }
+
+    Pool *m_first;
+    Pool *m_current;
+    Pool *m_freeList;
+    size_t m_capacity;
+};
+
+template <class T>
+inline TPoolAllocator<T>::TPoolAllocator() :
+        m_first(nullptr), m_current(nullptr), m_freeList(nullptr), m_capacity(0L) {
+    // empty
+}
+
+template <class T>
+inline TPoolAllocator<T>::TPoolAllocator(size_t numItems) :
+        m_first(nullptr), m_current(nullptr), m_freeList(nullptr), m_capacity(0L) {
+    m_first = new Pool(numItems);
+    m_capacity += numItems;
+    m_current = m_first;
+}
+
+template <class T>
+inline TPoolAllocator<T>::~TPoolAllocator() {
+    clear();
+}
+
+template <class T>
+inline T *TPoolAllocator<T>::alloc() {
+    if (nullptr == m_current) {
+        return nullptr;
+    }
+
+    if (m_current->m_currentIdx == m_current->m_poolsize) {
+        resize(m_current->m_poolsize);
+    }
+
+    T *ptr(&m_current->m_pool[m_current->m_currentIdx]);
+    m_current->m_currentIdx++;
+
+    return ptr;
+}
+
+template <class T>
+inline void TPoolAllocator<T>::release() {
+    if (nullptr == m_current) {
+        return;
+    }
+
+    Pool *current(m_first);
+    while (nullptr != current) {
+        current->m_currentIdx = 0;
+        current = current->m_next;
+    }
+    m_freeList = m_first->m_next;
+    m_current = m_first;
+}
+
+template <class T>
+inline void TPoolAllocator<T>::reserve(size_t size) {
+    clear();
+
+    m_first = new Pool(size, nullptr);
+    m_current = m_first;
+
+    m_current->m_pool = new T[size];
+    m_current->m_poolsize = size;
+
+    m_capacity = size;
+}
+
+template <class T>
+inline void TPoolAllocator<T>::clear() {
+    if (nullptr == m_current) {
+        return;
+    }
+
+    Pool *next(m_first);
+    while (nullptr != next) {
+        Pool *current = next;
+        next = current->m_next;
+        delete current;
+    }
+    m_current = nullptr;
+    m_freeList = nullptr;
+}
+
+template <class T>
+inline size_t TPoolAllocator<T>::capacity() const {
+    return m_capacity;
+}
+
+template <class T>
+inline size_t TPoolAllocator<T>::reservedMem() const {
+    return m_capacity * sizeof(T);
+}
+
+template <class T>
+inline size_t TPoolAllocator<T>::freeMem() const {
+    if (nullptr == m_current) {
+        return 0L;
+    }
+
+    return (m_current->m_poolsize - m_current->m_currentIdx);
+}
+
+template <class T>
+inline void TPoolAllocator<T>::dumpAllocations(std::string &allocs) {
+    allocs.clear();
+    allocs += "Number allocations = ";
+    allocs += std::to_string(m_current->m_currentIdx);
+    allocs += "\n";
+}
+
+template <class T>
+inline void TPoolAllocator<T>::resize(size_t growSize) {
+    if (nullptr != m_current) {
+        if (growSize < m_current->m_poolsize) {
+            return;
+        }
+    }
+
+    if (nullptr == m_first) {
+        m_first = new Pool(growSize, nullptr);
+        m_current = m_first;
+        m_capacity += m_current->m_poolsize;
+    } else {
+        Pool *pool = getFreePool();
+        if (nullptr == pool) {
+            pool = new Pool(growSize, nullptr);
+            m_capacity += growSize;
+        }
+        m_current->m_next = pool;
+        m_current = m_current->m_next;
+    }
+}
+
+END_ODDLPARSER_NS
\ No newline at end of file
diff --git a/libs/assimp/contrib/openddlparser/include/openddlparser/Value.h b/libs/assimp/contrib/openddlparser/include/openddlparser/Value.h
new file mode 100644
index 0000000..75af781
--- /dev/null
+++ b/libs/assimp/contrib/openddlparser/include/openddlparser/Value.h
@@ -0,0 +1,273 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2020 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/OpenDDLCommon.h>
+
+#include <string>
+
+BEGIN_ODDLPARSER_NS
+
+// Forward declarations
+struct ValueAllocator;
+
+class IOStreamBase;
+
+///------------------------------------------------------------------------------------------------
+///	@brief  This class implements a value.
+///
+///	Values are used to store data types like boolean, integer, floats, double and many mode. To get
+///	an overview please check the enum VylueType ( @see Value::ValueType ).
+/// Values can be single items or lists of items. They are implemented as linked lists.
+///------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT Value {
+    friend struct ValueAllocator;
+
+public:
+    ///	@brief  This class implements an iterator through a Value list.
+    ///
+    /// When getting a new value you need to know how to iterate through it. The Value::Iterator
+    /// will help you here:
+    ///	@code
+    /// Value *val = node->getValue();
+    /// Value::Iterator it( val );
+    /// while( it.hasNext() ) {
+    ///     Value v( it.getNext );
+    /// }
+    /// @endcode
+    class DLL_ODDLPARSER_EXPORT Iterator {
+    public:
+        ///	@brief  The default class constructor.
+        Iterator();
+
+        ///	@brief  The class constructor with the start value.
+        /// @param  start   [in] The first value for iteration,
+        Iterator( Value *start );
+
+        Iterator( const Iterator &rhs );
+
+        ///	@brief  The class destructor.
+        ~Iterator();
+
+        ///	@brief  Will return true, if another value is in the list.
+        /// @return true if another value is there.
+        bool hasNext() const;
+
+        ///	@brief  Returns the next item and moves the iterator to it.
+        ///	@return The next value, is ddl_nullptr in case of being the last item.
+        Value *getNext();
+
+        ///	@brief  The post-increment operator.
+        const Iterator operator++( int );
+
+        ///	@brief  The pre-increment operator.
+        Iterator &operator++( );
+
+        ///	@brief  The compare operator.
+        /// @param  rhs [in] The instance to compare.
+        /// @return true if equal.
+        bool operator == ( const Iterator &rhs ) const;
+
+        /// @brief  The * operator.
+        /// @return The instance or ddl_nullptr if end of list is reached.
+        Value *operator->( ) const;
+
+    private:
+        Value *m_start;
+        Value *m_current;
+
+    private:
+        Iterator &operator = ( const Iterator & );
+    };
+
+    ///	@brief  This enum describes the data type stored in the value.
+    enum class ValueType {
+        ddl_none = -1,          ///< Nothing specified
+        ddl_bool = 0,           ///< A boolean type
+        ddl_int8,               ///< Integer type, 8 bytes
+        ddl_int16,              ///< Integer type, 16 bytes
+        ddl_int32,              ///< Integer type, 32 bytes
+        ddl_int64,              ///< Integer type, 64 bytes
+        ddl_unsigned_int8,      ///< Unsigned integer type, 8 bytes
+        ddl_unsigned_int16,     ///< Unsigned integer type, 16 bytes
+        ddl_unsigned_int32,     ///< Unsigned integer type, 32 bytes
+        ddl_unsigned_int64,     ///< Unsigned integer type, 64 bytes
+        ddl_half,               ///< Half data type.
+        ddl_float,              ///< float data type
+        ddl_double,             ///< Double data type.
+        ddl_string,             ///< String data type.
+        ddl_ref,                ///< Reference, used to define references to other data definitions.
+        ddl_types_max           ///< Upper limit.
+    };
+
+    ///	@brief  The class constructor.
+    /// @param  type        [in] The value type.
+    Value( ValueType type );
+
+    ///	@brief  The class destructor.
+    ~Value();
+
+    ///	@brief  Assigns a boolean to the value.
+    /// @param  value       [in9 The value.
+    void setBool( bool value );
+
+    ///	@brief  Returns the boolean value.
+    /// @return The boolean value.
+    bool getBool();
+
+    ///	@brief  Assigns a int8 to the value.
+    /// @param  value       [in] The value.
+    void setInt8( int8 value );
+
+    ///	@brief  Returns the int8 value.
+    /// @return The int8 value.
+    int8 getInt8();
+
+    ///	@brief  Assigns a int16 to the value.
+    /// @param  value       [in] The value.
+    void setInt16( int16 value );
+
+    ///	@brief  Returns the int16 value.
+    /// @return The int16 value.
+    int16 getInt16();
+
+    ///	@brief  Assigns a int32 to the value.
+    /// @param  value       [in] The value.
+    void setInt32( int32 value );
+
+    ///	@brief  Returns the int16 value.
+    /// @return The int32 value.
+    int32 getInt32();
+
+    ///	@brief  Assigns a int64 to the value.
+    /// @param  value       [in] The value.
+    void setInt64( int64 value );
+
+    ///	@brief  Returns the int16 value.
+    /// @return The int64 value.
+    int64 getInt64();
+
+    ///	@brief  Assigns a unsigned int8 to the value.
+    /// @param  value       [in] The value.
+    void setUnsignedInt8( uint8 value );
+
+    ///	@brief  Returns the unsigned int8 value.
+    /// @return The unsigned int8 value.
+    uint8 getUnsignedInt8() const;
+
+    ///	@brief  Assigns a unsigned int16 to the value.
+    /// @param  value       [in] The value.
+    void setUnsignedInt16( uint16 value );
+
+    ///	@brief  Returns the unsigned int16 value.
+    /// @return The unsigned int16 value.
+    uint16 getUnsignedInt16() const;
+
+    ///	@brief  Assigns a unsigned int32 to the value.
+    /// @param  value       [in] The value.
+    void setUnsignedInt32( uint32 value );
+
+    ///	@brief  Returns the unsigned int8 value.
+    /// @return The unsigned int32 value.
+    uint32 getUnsignedInt32() const;
+
+    ///	@brief  Assigns a unsigned int64 to the value.
+    /// @param  value       [in] The value.
+    void setUnsignedInt64( uint64 value );
+
+    ///	@brief  Returns the unsigned int64 value.
+    /// @return The unsigned int64 value.
+    uint64 getUnsignedInt64() const;
+
+    ///	@brief  Assigns a float to the value.
+    /// @param  value       [in] The value.
+    void setFloat( float value );
+
+    ///	@brief  Returns the float value.
+    /// @return The float value.
+    float getFloat() const;
+
+    ///	@brief  Assigns a double to the value.
+    /// @param  value       [in] The value.
+    void setDouble( double value );
+
+    ///	@brief  Returns the double value.
+    /// @return The double value.
+    double getDouble() const;
+
+    ///	@brief  Assigns a std::string to the value.
+    /// @param  str         [in] The value.
+    void setString( const std::string &str );
+
+    ///	@brief  Returns the std::string value.
+    /// @return The std::string value.
+    const char *getString() const;
+
+    /// @brief  Set the reference.
+    /// @param  ref     [in] Pointer showing to the reference.
+    void setRef( Reference *ref );
+
+    /// @brief  Returns the pointer showing to the reference.
+    /// @return Pointer showing to the reference.
+    Reference *getRef() const;
+
+    ///	@brief  Dumps the value.
+    /// @param  stream  [in] The stream to write in.
+    void dump( IOStreamBase &stream );
+
+    ///	@brief  Assigns the next value.
+    ///	@param  next        [n] The next value.
+    void setNext( Value *next );
+
+    ///	@brief  Returns the next value.
+    /// @return The next value.s
+    Value *getNext() const;
+
+    /// @brief  Gets the length of the array.
+    /// @return The number of items in the array.
+    size_t size() const;
+
+    ValueType m_type;
+    size_t m_size;
+    unsigned char *m_data;
+    Value *m_next;
+
+private:
+    Value &operator =( const Value & ) ddl_no_copy;
+    Value( const Value  & ) ddl_no_copy;
+};
+
+///------------------------------------------------------------------------------------------------
+///	@brief  This class implements the value allocator.
+///------------------------------------------------------------------------------------------------
+struct DLL_ODDLPARSER_EXPORT ValueAllocator {
+    static Value *allocPrimData( Value::ValueType type, size_t len = 1 );
+    static void releasePrimData( Value **data );
+
+private:
+    ValueAllocator() ddl_no_copy;
+    ValueAllocator( const ValueAllocator  & ) ddl_no_copy;
+    ValueAllocator &operator = ( const ValueAllocator & ) ddl_no_copy;
+};
+
+END_ODDLPARSER_NS
-- 
cgit v1.2.1