Ver Fonte

add openddl-parser to contrib.

Signed-off-by: Kim Kulling <[email protected]>
Kim Kulling há 10 anos atrás
pai
commit
1ee4c06e4b

+ 1 - 1
.gitignore

@@ -10,7 +10,7 @@ build
 # Output
 bin/
 lib/
-contrib/
+
 
 # Generated
 assimp.pc

+ 1 - 0
CMakeLists.txt

@@ -154,6 +154,7 @@ else(NOT ZLIB_FOUND)
 endif(NOT ZLIB_FOUND)
 INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
 
+add_subdirectory( contrib/openddlparser )
 # Search for unzip
 if (PKG_CONFIG_FOUND)
     PKG_CHECK_MODULES(UNZIP minizip)

+ 0 - 1
code/CMakeLists.txt

@@ -634,7 +634,6 @@ SET( unzip_SRCS
 )
 SOURCE_GROUP( unzip FILES ${unzip_SRCS})
 
-
 # VC2010 fixes
 if(MSVC10)
 	option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )

+ 63 - 0
contrib/openddlparser/CMakeLists.txt

@@ -0,0 +1,63 @@
+CMAKE_MINIMUM_REQUIRED( VERSION 2.6 )
+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 ${CPPCORE_VERSION_MAJOR}.${CPPCORE_VERSION_MINOR}.${CPPCORE_VERSION_PATCH} )
+SET ( PROJECT_VERSION "${OPENDDL_PARSER_VERSION}" )
+
+if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+    find_package(Threads)
+else()
+    add_definitions( -D_CRT_SECURE_NO_WARNINGS )
+endif()
+
+add_definitions( -DOPENDDLPARSER_BUILD )
+add_definitions( -D_VARIADIC_MAX=10 )
+
+INCLUDE_DIRECTORIES(
+    ./
+    include/
+    contrib/gtest-1.7.0/include
+    contrib/gtest-1.7.0/
+)
+
+link_directories(
+    ./
+)
+
+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 -std=c++0x")
+elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++11")
+endif()
+
+SET ( openddl_parser_src
+    code/OpenDDLParser.cpp
+    code/DDLNode.cpp
+    code/Value.cpp
+    include/openddlparser/OpenDDLParser.h
+    include/openddlparser/OpenDDLParserUtils.h
+    include/openddlparser/OpenDDLCommon.h
+    include/openddlparser/DDLNode.h
+    include/openddlparser/Value.h
+    README.md
+)
+ 
+SOURCE_GROUP( code            FILES ${openddl_parser_src} )
+
+ADD_LIBRARY( openddl_parser SHARED
+    ${openddl_parser_src}
+)

+ 111 - 0
contrib/openddlparser/README.md

@@ -0,0 +1,111 @@
+The OpenDDL-Parser
+==================
+
+A simple and fast OpenDDL Parser
+Current build status: [![Build Status](https://travis-ci.org/kimkulling/openddl-parser.png)](https://travis-ci.org/kimkulling/openddl-parser)
+
+Get the source code
+===================
+You can get the code from our git repository, which is located at GitHub. You can clone the repository like:
+
+> git clone https://github.com/kimkulling/openddl-parser.git
+
+Build from 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 toolchain is installed on your machine.
+After installing it you can open a console and type:
+
+> cmake CMakeLists.txt
+
+This command will generate a build environment for your installed build enrironment ( for Visual Studio the project files will be generated, for gcc 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.
+
+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 tree with the following code:
+
+```
+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;
+    }
+}
+
+```
+
+The instance called root contains the data.

+ 162 - 0
contrib/openddlparser/code/DDLNode.cpp

@@ -0,0 +1,162 @@
+/*-----------------------------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/DDLNode.h>
+#include <openddlparser/OpenDDLParser.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;
+    }
+}
+
+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_idx( idx )
+, m_dtArrayList( nullptr ) {
+    if( m_parent ) {
+        m_parent->m_children.push_back( this );
+    }
+}
+
+DDLNode::~DDLNode() {
+    releaseDataType<Property>( m_properties );
+    releaseDataType<Value>( m_value );
+
+    delete m_dtArrayList;
+    m_dtArrayList = nullptr;
+    if( s_allocatedNodes[ m_idx ] == this ) {
+        s_allocatedNodes[ m_idx ] = nullptr;
+    }
+}
+
+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( m_parent ) {
+        std::vector<DDLNode*>::iterator it;
+        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 *first ) {
+    m_properties = first;
+}
+
+Property *DDLNode::getProperties() const {
+    return m_properties;
+}
+
+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;
+}
+
+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( DllNodeList::iterator it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) {
+            if( *it ) {
+                delete *it;
+            }
+        }
+        s_allocatedNodes.clear();
+    }
+}
+
+END_ODDLPARSER_NS

+ 852 - 0
contrib/openddlparser/code/OpenDDLParser.cpp

@@ -0,0 +1,852 @@
+/*-----------------------------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/OpenDDLParser.h>
+
+#include <cassert>
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+
+#ifdef _WIN32
+#  include <windows.h>
+#endif // _WIN32
+
+#define DEBUG_HEADER_NAME 
+
+BEGIN_ODDLPARSER_NS
+
+static const char *Version = "0.1.0";
+
+static const char* PrimitiveTypeToken[ Value::ddl_types_max ] = {
+    "bool",
+    "int8",
+    "int16",
+    "int32",
+    "int64",
+    "unsigned_int8",
+    "unsigned_int16",
+    "unsigned_int32",
+    "unsigned_int64",
+    "half",
+    "float",
+    "double",
+    "string",
+    "ref"
+};
+
+static const char *BoolTrue  = "true";
+static const char *BoolFalse = "false";
+static const char *RefToken  = "ref";
+
+static void logInvalidTokenError( char *in, char *exp, OpenDDLParser::logCallback callback ) {
+    std::stringstream stream;
+    stream << "Invalid token " << *in << ", " << exp << " expected." << std::endl;
+    callback( ddl_error_msg, stream.str() );
+}
+
+static bool isIntegerType( Value::ValueType integerType ) {
+    if( integerType != Value::ddl_int8 && integerType != Value::ddl_int16 && integerType != Value::ddl_int32 && integerType != Value::ddl_int64 ) {
+        return false;
+    }
+
+    return true;
+}
+
+static DDLNode *createDDLNode( Identifier *id, Property *first, OpenDDLParser *parser ) {
+    if( nullptr == id || nullptr == parser ) {
+        return nullptr;
+    }
+
+    const std::string type( id->m_buffer );
+    DDLNode *parent( parser->top() );
+    DDLNode *node = DDLNode::create( type, "", parent );
+    if( nullptr != first ) {
+        node->setProperties( first );
+    }
+
+    return node;
+}
+
+static void logMessage( LogSeverity severity, const std::string &msg ) {
+    std::string log;
+    if( ddl_debug_msg == severity ) {
+        log += "Debug:";
+    } else if( ddl_info_msg == severity ) {
+        log += "Info :";
+    } else if( ddl_warn_msg == severity ) {
+        log += "Warn :";
+    } else if( ddl_error_msg == severity ) {
+        log += "Error:";
+    } else {
+        log += "None :";
+    }
+
+    log += msg;
+    std::cout << log;
+}
+
+OpenDDLParser::OpenDDLParser()
+: m_logCallback( logMessage )
+, m_ownsBuffer( false )
+,m_buffer( nullptr )
+, m_len( 0 )
+, m_stack()
+, m_context( nullptr ) {
+    // empty
+}
+
+OpenDDLParser::OpenDDLParser( char *buffer, size_t len, bool ownsIt )
+: m_logCallback( &logMessage )
+, m_ownsBuffer( false )
+, m_buffer( nullptr )
+, m_len( 0 ) 
+, m_context( nullptr ) {
+    if( 0 != m_len ) {
+        setBuffer( buffer, len, ownsIt );
+    }
+}
+
+OpenDDLParser::~OpenDDLParser() {
+    clear();
+}
+
+void OpenDDLParser::setLogCallback( logCallback callback ) {
+    if( nullptr != callback ) {
+        // install user-specific log callback
+        m_logCallback = callback;
+    } else {
+        // install default log callback
+        m_logCallback = &logMessage;
+    }
+}
+
+OpenDDLParser::logCallback OpenDDLParser::getLogCallback() const {
+    return m_logCallback;
+}
+
+void OpenDDLParser::setBuffer( char *buffer, size_t len, bool ownsIt ) {
+    if( m_buffer && m_ownsBuffer ) {
+        delete[] m_buffer;
+        m_buffer = nullptr;
+        m_len = 0;
+    }
+
+    m_ownsBuffer = ownsIt;
+    if( m_ownsBuffer ) {
+        // when we are owning the buffer we will do a deep copy
+        m_buffer = new char[ len ];
+        m_len = len;
+        ::memcpy( m_buffer, buffer, len );
+    } else {
+        // when we are not owning the buffer, we just do a shallow copy
+        m_buffer = buffer;
+        m_len = len;
+    }
+}
+
+char *OpenDDLParser::getBuffer() const {
+    return m_buffer;
+}
+
+size_t OpenDDLParser::getBufferSize() const {
+    return m_len;
+}
+
+void OpenDDLParser::clear() {
+    if( m_ownsBuffer ) {
+        delete [] m_buffer;
+    }
+    m_buffer = nullptr;
+    m_len = 0;
+
+    if( m_context ) {
+        m_context->m_root = nullptr;
+    }
+
+    DDLNode::releaseNodes();
+}
+
+bool OpenDDLParser::parse() {
+    if( 0 == m_len ) {
+        return false;
+    }
+    
+    normalizeBuffer( m_buffer, m_len );
+
+    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_len - 1 ] + 1 );
+    while( current != end ) {
+        current = parseNextNode( current, end );
+    }
+    return true;
+}
+
+char *OpenDDLParser::parseNextNode( char *in, char *end ) {
+    in = parseHeader( in, end );
+    in = parseStructure( in, end );
+
+    return in;
+}
+
+char *OpenDDLParser::parseHeader( char *in, char *end ) {
+    if( nullptr == in || in == end ) {
+        return in;
+    }
+
+    Identifier *id( nullptr );
+    in = OpenDDLParser::parseIdentifier( in, end, &id );
+
+#ifdef DEBUG_HEADER_NAME    
+    if( id ) {
+        std::cout << id->m_buffer << std::endl;
+    }
+#endif // DEBUG_HEADER_NAME
+
+    in = getNextToken( in, end );
+    Property *first( nullptr );
+    if( nullptr != id ) {
+        if( *in == '(' ) {
+            in++;
+            Property *prop( nullptr ), *prev( nullptr );
+            while( *in != ')' && in != end ) {
+                in = parseProperty( in, end, &prop );
+                in = getNextToken( in, end );
+
+                if( *in != ',' && *in != ')' ) {
+                    logInvalidTokenError( in, ")", m_logCallback );
+                    return in;
+                }
+                if( nullptr != prop && *in != ',' ) {
+                    if( nullptr == first ) {
+                        first = prop;
+                    }
+                    if( nullptr != prev ) {
+                        prev->m_next = prop;
+                    }
+                    prev = prop;
+                }
+            }
+            in++;
+        }
+
+        // store the node
+        DDLNode *node( createDDLNode( id, first, this ) );
+        if( nullptr != node ) {
+            pushNode( node );
+        } else {
+            std::cerr << "nullptr returned by creating DDLNode." << std::endl;
+        }
+
+        Name *name( nullptr );
+        in = OpenDDLParser::parseName( in, end, &name );
+        if( nullptr != name ) {
+            const std::string nodeName( name->m_id->m_buffer );
+            node->setName( nodeName );
+        }
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseStructure( char *in, char *end ) {
+    if( nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = getNextToken( in, end );
+    if( *in == '{' ) {
+        in++;
+        in = getNextToken( in, end );
+        Value::ValueType type( Value::ddl_none );
+        size_t arrayLen( 0 );
+        in = OpenDDLParser::parsePrimitiveDataType( in, end, type, arrayLen );
+        if( Value::ddl_none != type ) {
+            in = getNextToken( in, end );
+            if( *in == '{' ) {
+                DataArrayList *dtArrayList( nullptr );
+                Value *values( nullptr );
+                if( 1 == arrayLen ) {
+                    in = parseDataList( in, end, &values );
+                    if( nullptr != values ){
+                        DDLNode *currentNode( top() );
+                        if( nullptr != currentNode ) {
+                            currentNode->setValue( values );
+                        }
+                    }
+                } else if( arrayLen > 1 ) {
+                    in = parseDataArrayList( in, end, &dtArrayList );
+                    if( nullptr != dtArrayList ) {
+                        DDLNode *currentNode( top() );
+                        if( nullptr != currentNode ) {
+                            currentNode->setDataArrayList( dtArrayList );
+                        }
+                    }
+                } else {
+                    std::cerr << "0 for array is invalid." << std::endl;
+                }
+            }
+
+            in = getNextToken( in, end );
+            if( *in != '}' ) {
+                logInvalidTokenError( in, "}", m_logCallback );
+            }
+        } else {
+            in = parseHeader( in, end );
+            in = parseStructure( in, end );
+        }
+    } else {
+        in++;
+        logInvalidTokenError( in, "{", m_logCallback );
+        return in;
+
+    }
+
+    in++;
+
+    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( char *buffer, size_t len ) {
+    if( nullptr == buffer || 0 == len ) {
+        return;
+    }
+
+    size_t writeIdx( 0 );
+    char *end( &buffer[ len ] + 1 );
+    for( size_t readIdx = 0; readIdx<len; ++readIdx ) {
+        char *c( &buffer[readIdx] );
+        // check for a comment
+        if( !isComment<char>( c, end ) ) {
+            buffer[ writeIdx ] = buffer[ readIdx ];
+            writeIdx++;
+        } else {
+            readIdx++;
+            // skip the comment and the rest of the line
+            while( !isEndofLine( buffer[ readIdx ] ) ) {
+                readIdx++;
+            }
+            buffer[writeIdx] = '\n';
+            writeIdx++;
+        }
+    }
+
+    if( writeIdx < len ) {
+        buffer[ writeIdx ] = '\0';
+    }
+}
+
+char *OpenDDLParser::parseName( char *in, char *end, Name **name ) {
+    *name = nullptr;
+    if( nullptr == in || in == end ) {
+        return in;
+    }
+
+    // ignore blanks
+    in = getNextToken( in, end );
+    if( *in != '$' && *in != '%' ) {
+        return in;
+    }
+
+    NameType ntype( GlobalName );
+    if( *in == '%' ) {
+        ntype = LocalName;
+    }
+
+    Name *currentName( nullptr );
+    Identifier *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, Identifier **id ) {
+    *id = nullptr;
+    if( nullptr == in || in == end ) {
+        return in;
+    }
+
+    // ignore blanks
+    in = getNextToken( in, end );
+    
+    // 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( !isSeparator( *in ) && ( in != end ) && *in != '(' && *in != ')' ) {
+        in++;
+        idLen++;
+    }
+    
+    const size_t len( idLen + 1 );
+    Identifier *newId = new Identifier( len, new char[ len ] );
+    ::strncpy( newId->m_buffer, start, newId->m_len-1 );
+    newId->m_buffer[ newId->m_len - 1 ] = '\0';
+    *id = newId;
+
+    return in;
+}
+
+char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueType &type, size_t &len ) {
+    type = Value::ddl_none;
+    len = 0;
+    if( nullptr == in || in == end ) {
+        return in;
+    }
+
+    for( unsigned int i = 0; i < Value::ddl_types_max; i++ ) {
+        const size_t prim_len( strlen( PrimitiveTypeToken[ i ] ) );
+        if( 0 == strncmp( in, PrimitiveTypeToken[ i ], prim_len ) ) {
+            type = ( Value::ValueType ) i;
+            break;
+        }
+    }
+
+    if( Value::ddl_none == type ) {
+        in = getNextToken( in, end );
+        return in;
+    } else {
+        in += strlen( PrimitiveTypeToken[ type ] );
+    }
+
+    bool ok( true );
+    if( *in == '[' ) {
+        ok = false;
+        in++;
+        char *start( in );
+        while ( in != end ) {
+            in++;
+            if( *in == ']' ) {
+                len = atoi( start );
+                ok = true;
+                in++;
+                break;
+            }
+        }
+    } else {
+        len = 1;
+    }
+    if( !ok ) {
+        type = Value::ddl_none;
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseReference( char *in, char *end, std::vector<Name*> &names ) {
+    if( nullptr == in || in == end ) {
+        return in;
+    }
+
+    if( 0 != strncmp( in, RefToken, strlen( RefToken ) ) ) {
+        return false;
+    } else {
+        const size_t refTokenLen( strlen( RefToken ) );
+        in += refTokenLen;
+    }
+
+    in = getNextToken( in, end );
+    if( '{' != *in ) {
+        return in;
+    } else {
+        in++;
+    }
+
+    in = getNextToken( in, end );
+    Name *nextName( nullptr );
+    in = parseName( in, end, &nextName );
+    if( nextName ) {
+        names.push_back( nextName );
+    }
+    while( '}' != *in ) {
+        in = getNextSeparator( in, end );
+        if( ',' == *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 = getNextToken( in, end );
+    char *start( in );
+    size_t len( 0 );
+    while( !isSeparator( *in ) && in != end ) {
+        in++;
+        len++;
+    }
+    len++;
+    int res = ::strncmp( BoolTrue, start, strlen( BoolTrue ) );
+    if( 0 != res ) {
+        res = ::strncmp( BoolFalse, start, strlen( BoolFalse ) );
+        if( 0 != res ) {
+            *boolean = nullptr;
+            return in;
+        }
+        *boolean = ValueAllocator::allocPrimData( Value::ddl_bool );
+        (*boolean)->setBool( false );
+    } else {
+        *boolean = ValueAllocator::allocPrimData( Value::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 ) ) {
+        return in;
+    }
+
+    in = getNextToken( in, end );
+    char *start( in );
+    while( !isSeparator( *in ) && in != end ) {
+        in++;
+    }
+
+    if( isNumeric( *start ) ) {
+        const int value( atoi( start ) );
+        *integer = ValueAllocator::allocPrimData( integerType );
+        switch( integerType ) {
+            case Value::ddl_int8:
+                    ( *integer )->setInt8( (int8) value );
+                    break;
+            case Value::ddl_int16:
+                    ( *integer )->setInt16( ( int16 ) value );
+                    break;
+            case Value::ddl_int32:
+                    ( *integer )->setInt32( ( int32 ) value );
+                    break;
+            case Value::ddl_int64:
+                    ( *integer )->setInt64( ( int64 ) value );
+                    break;
+            default:
+                break;
+        }
+    } 
+
+    return in;
+}
+
+char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating ) {
+    *floating = nullptr;
+    if( nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = getNextToken( in, end );
+    char *start( in );
+    while( !isSeparator( *in ) && in != end ) {
+        in++;
+    }
+
+    // parse the float value
+    bool ok( false );
+    if( isNumeric( *start ) ) {
+        ok = true;
+    } else {
+        if( *start == '-' ) {
+            if( isNumeric( *(start+1) ) ) {
+                ok = true;
+            }
+        }
+    }
+
+    if( ok ) {
+        const float value( ( float ) atof( start ) );
+        *floating = ValueAllocator::allocPrimData( Value::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 = getNextToken( in, end );
+    size_t len( 0 );
+    char *start( in );
+    if( *start == '\"' ) {
+        start++;
+        in++;
+        while( *in != '\"' && in != end ) {
+            in++;
+            len++;
+        }
+
+        *stringData = ValueAllocator::allocPrimData( Value::ddl_string, len + 1 );
+        ::strncpy( ( char* ) ( *stringData )->m_data, start, len );
+        ( *stringData )->m_data[len] = '\0';
+        in++;
+    }
+
+    return in;
+}
+
+static void createPropertyWithData( Identifier *id, Value *primData, Property **prop ) {
+    if( nullptr != primData ) {
+        ( *prop ) = new Property( id );
+        ( *prop )->m_primData = primData;
+    }
+}
+
+char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
+    *data = nullptr;
+    if( nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = getNextToken( 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 ) {
+        pos--;
+        value += hex2Decimal( *start ) * static_cast<int>( pow( 16.0, pos ) );
+        start++;
+    }
+
+    *data = ValueAllocator::allocPrimData( Value::ddl_int32 );
+    (*data)->setInt32( value );
+
+    return in;
+}
+
+char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) {
+    *prop = nullptr;
+    if( nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = getNextToken( in, end );
+    Identifier *id( nullptr );
+    in = parseIdentifier( in, end, &id );
+    if( nullptr != id ) {
+        in = getNextToken( in, end );
+        if( *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;
+                }
+            }
+        } 
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseDataList( char *in, char *end, Value **data ) {
+    *data = nullptr;
+    if( nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = getNextToken( in, end );
+    if( *in == '{' ) {
+        in++;
+        Value *current( nullptr ), *prev( nullptr );
+        while( '}' != *in ) {
+            current = nullptr;
+            in = getNextToken( in, end );
+            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 );
+            }
+
+            if( nullptr != current ) {
+                if( nullptr == *data ) {
+                    *data = current;
+                    prev = current;
+                } else {
+                    prev->setNext( current );
+                    prev = current;
+                }
+            }
+
+            in = getNextSeparator( in, end );
+            if( ',' != *in && '}' != *in && !isSpace( *in ) ) {
+                break;
+            }
+        }
+        in++;
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseDataArrayList( char *in, char *end, DataArrayList **dataList ) {
+    *dataList = nullptr;
+    if( nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = getNextToken( in, end );
+    if( *in == '{' ) {
+        in++;
+        Value *current( nullptr );
+        DataArrayList *prev( nullptr ), *currentDataList( nullptr );
+        do {
+            in = parseDataList( in, end, &current );
+            if( nullptr != current ) {
+                if( nullptr == prev ) {
+                    *dataList = new DataArrayList;
+                    (*dataList)->m_dataList = current;
+                    prev = *dataList;
+                } else {
+                    currentDataList = new DataArrayList;
+                    if( nullptr != prev ) {
+                        prev->m_next = currentDataList;
+                        prev = currentDataList;
+                    }
+                }
+            }
+        } while( ',' == *in && in != end );
+    }
+
+    return in;
+}
+
+const char *OpenDDLParser::getVersion() {
+    return Version;
+}
+
+END_ODDLPARSER_NS

+ 243 - 0
contrib/openddlparser/code/Value.cpp

@@ -0,0 +1,243 @@
+/*-----------------------------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/Value.h>
+#include <iostream>
+#include <cassert>
+
+BEGIN_ODDLPARSER_NS
+
+Value::Value()
+: m_type( ddl_none )
+, m_size( 0 )
+, m_data( nullptr )
+, m_next( nullptr ) {
+    // empty
+}
+
+Value::~Value() {
+    // empty
+}
+
+void Value::setBool( bool value ) {
+    assert( ddl_bool == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+bool Value::getBool() {
+    assert( ddl_bool == m_type );
+    return ( bool ) ( *m_data );
+}
+
+void Value::setInt8( int8 value ) {
+    assert( ddl_int8 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+int8 Value::getInt8() {
+    assert( ddl_int8 == m_type );
+    return ( int8 ) ( *m_data );
+}
+
+void Value::setInt16( int16 value ) {
+    assert( ddl_int16 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+int16 Value::getInt16() {
+    assert( ddl_int16 == m_type );
+    return ( int16 ) ( *m_data );
+}
+
+void Value::setInt32( int32 value ) {
+    assert( ddl_int32 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+int32 Value::getInt32() {
+    assert( ddl_int32 == m_type );
+    return ( int32 ) ( *m_data );
+}
+
+void Value::setInt64( int64 value ) {
+    assert( ddl_int32 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+int64 Value::getInt64() {
+    return ( int64 ) ( *m_data );
+}
+
+void Value::setFloat( float value ) {
+    assert( ddl_float == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+float Value::getFloat() const {
+    float v;
+    ::memcpy( &v, m_data, m_size );
+    return v;
+}
+
+void Value::setDouble( double value ) {
+    assert( ddl_double == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+double Value::getDouble() const {
+    double v;
+    ::memcpy( &v, m_data, m_size );
+    return v;
+}
+
+void Value::dump() {
+    switch( m_type ) {
+    case ddl_none:
+        std::cout << "None" << std::endl;
+        break;
+    case ddl_bool:
+        std::cout << getBool() << std::endl;
+        break;
+    case ddl_int8:
+        std::cout << getInt8() << std::endl;
+        break;
+    case ddl_int16:
+        std::cout << getInt16() << std::endl;
+        break;
+    case ddl_int32:
+        std::cout << getInt32() << std::endl;
+        break;
+    case ddl_int64:
+        std::cout << getInt64() << std::endl;
+        break;
+    case ddl_unsigned_int8:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_unsigned_int16:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_unsigned_int32:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_unsigned_int64:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_half:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_float:
+        std::cout << getFloat() << std::endl;
+        break;
+    case ddl_double:
+        std::cout << getDouble() << std::endl;
+        break;
+    case ddl_string:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_ref:
+        std::cout << "Not supported" << std::endl;
+        break;
+    default:
+        break;
+    }
+}
+
+void Value::setNext( Value *next ) {
+    m_next = next;
+}
+
+Value *Value::getNext() const {
+    return m_next;
+}
+
+Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
+    if( type == Value::ddl_none || Value::ddl_types_max == type ) {
+        return nullptr;
+    }
+
+    Value *data = new Value;
+    data->m_type = type;
+    switch( type ) {
+        case Value::ddl_bool:
+            data->m_size = sizeof( bool );
+            break;
+        case Value::ddl_int8:
+            data->m_size = sizeof( char );
+            break;
+        case Value::ddl_int16:
+            data->m_size = sizeof( short );
+            break;
+        case Value::ddl_int32:
+            data->m_size = sizeof( int );
+            break;
+        case Value::ddl_int64:
+            data->m_size = sizeof( long );
+            break;
+        case Value::ddl_unsigned_int8:
+            data->m_size = sizeof( unsigned char );
+            break;
+        case Value::ddl_unsigned_int32:
+            data->m_size = sizeof( unsigned int );
+            break;
+        case Value::ddl_unsigned_int64:
+            data->m_size = sizeof( unsigned long );
+            break;
+        case Value::ddl_half:
+            data->m_size = sizeof( short );
+            break;
+        case Value::ddl_float:
+            data->m_size = sizeof( float );
+            break;
+        case Value::ddl_double:
+            data->m_size = sizeof( double );
+            break;
+        case Value::ddl_string:
+            data->m_size = sizeof( char );
+            break;
+        case Value::ddl_ref:
+            data->m_size = sizeof( char );
+            break;
+        case Value::ddl_none:
+        case Value::ddl_types_max:
+        default:
+            break;
+    }
+
+    if( data->m_size ) {
+        data->m_size *= len;
+        data->m_data = new unsigned char[ data->m_size ];
+    }
+
+    return data;
+}
+
+void ValueAllocator::releasePrimData( Value **data ) {
+    if( !data ) {
+        return;
+    }
+
+    delete *data;
+    *data = nullptr;
+}
+
+
+END_ODDLPARSER_NS

+ 87 - 0
contrib/openddlparser/include/openddlparser/DDLNode.h

@@ -0,0 +1,87 @@
+/*-----------------------------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_DDLNODE_H_INC
+#define OPENDDLPARSER_DDLNODE_H_INC
+
+#include <openddlparser/OpenDDLCommon.h>
+
+#include <vector>
+#include <string>
+
+BEGIN_ODDLPARSER_NS
+
+class Value;
+class OpenDDLParser;
+
+struct Identifier;
+struct Reference;
+struct Property;
+struct DataArrayList;
+
+class DLL_ODDLPARSER_EXPORT DDLNode {
+public:
+    friend class OpenDDLParser;
+
+    typedef std::vector<DDLNode*> DllNodeList;
+
+public:
+    ~DDLNode();
+    void attachParent( DDLNode *parent );
+    void detachParent();
+    DDLNode *getParent() const;
+    const DllNodeList &getChildNodeList() const;
+    void setType( const std::string &name );
+    const std::string &getType() const;
+    void setName( const std::string &name );
+    const std::string &getName() const;
+    void setProperties( Property *first );
+    Property *getProperties() const;
+    void setValue( Value *val );
+    Value *getValue() const;
+    void setDataArrayList( DataArrayList  *dtArrayList );
+    DataArrayList *getDataArrayList() const;
+    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 & );
+    DDLNode &operator = ( const DDLNode & );
+    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;
+    size_t m_idx;
+    static DllNodeList s_allocatedNodes;
+};
+
+END_ODDLPARSER_NS
+
+#endif // OPENDDLPARSER_DDLNODE_H_INC

+ 148 - 0
contrib/openddlparser/include/openddlparser/OpenDDLCommon.h

@@ -0,0 +1,148 @@
+/*-----------------------------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
+#define OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
+
+#include <cstddef>
+#include <string.h>
+
+#ifdef _WIN32
+#   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
+
+#define BEGIN_ODDLPARSER_NS namespace ODDLParser {
+#define END_ODDLPARSER_NS   }
+#define USE_ODDLPARSER_NS   using namespace ODDLParser;
+
+BEGIN_ODDLPARSER_NS
+
+class DDLNode;
+class Value;
+
+struct Name;
+struct Identifier;
+struct Reference;
+struct Property;
+struct DataArrayList;
+
+typedef char  int8;
+typedef short int16;
+typedef int   int32;
+typedef long  int64;
+
+enum NameType {
+    GlobalName,
+    LocalName
+};
+
+struct Name {
+    NameType m_type;
+    Identifier *m_id;
+
+    Name( NameType type, Identifier *id )
+        : m_type( type )
+        , m_id( id ) {
+        // empty
+    }
+};
+
+struct Reference {
+    size_t m_numRefs;
+    Name **m_referencedName;
+
+    Reference( size_t numrefs, Name **names )
+        : m_numRefs( numrefs )
+        , m_referencedName( names ) {
+        // empty
+    }
+};
+
+struct Identifier {
+    size_t m_len;
+    char *m_buffer;
+
+    Identifier( size_t len, char *buffer )
+        : m_len( len )
+        , m_buffer( buffer ) {
+        // empty
+    }
+};
+
+struct Property {
+    Identifier *m_id;
+    Value *m_primData;
+    Reference *m_ref;
+    Property *m_next;
+
+    Property( Identifier *id )
+        : m_id( id )
+        , m_primData( nullptr )
+        , m_ref( nullptr )
+        , m_next( nullptr ) {
+        // empty
+    }
+};
+
+struct DataArrayList {
+    size_t m_numItems;
+    Value *m_dataList;
+    DataArrayList *m_next;
+
+    DataArrayList()
+        : m_numItems( 0 )
+        , m_dataList( nullptr )
+        , m_next( nullptr ) {
+        // empty
+    }
+};
+
+struct Context {
+    Property *m_properties;
+    DDLNode *m_root;
+
+    Context()
+    : m_properties( nullptr )
+    , m_root( nullptr ) {
+        // empty
+    }
+};
+
+END_ODDLPARSER_NS
+
+#define ODDL_NO_COPYING( classname ) \
+private: \
+    classname( const classname & ); \
+    classname &operator = ( const classname & );
+
+#endif // OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
+

+ 233 - 0
contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h

@@ -0,0 +1,233 @@
+/*-----------------------------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC
+#define OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC
+
+#include <openddlparser/OpenDDLCommon.h>
+
+BEGIN_ODDLPARSER_NS
+
+template<class T>
+inline
+bool isComment( T *in, T *end ) {
+    if( *in == '/' ) {
+        if( in + 1 != end ) {
+            if( *( in + 1 ) == '/' ) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+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 );
+}
+
+template<class T>
+inline
+bool isSeparator( T in ) {
+    if( isSpace( 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 ) {
+    return ( in >= '0' && in <= '9' );
+    //return ( chartype_table[in] );
+    /*if (in >= '0' &&  in <= '9' )
+    return true;
+
+    return false;*/
+}
+
+template<class T>
+inline
+bool isInteger( T *in, T *end ) {
+    if( in != end ) {
+        if( *in == '-' ) {
+            in++;
+        }
+    }
+
+    bool result( false );
+    while( '}' != *in && ',' != *in && !isSpace( *in ) && 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( !isSpace( *in ) && 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( !isSpace( *in ) && in != end && *in != ',' ) {
+        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 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 = 9999;
+
+inline
+int hex2Decimal( char in ) {
+    if( isNumeric( in ) ) {
+        return (int) 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;
+}
+
+END_ODDLPARSER_NS
+
+#endif // OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC

+ 85 - 0
contrib/openddlparser/include/openddlparser/Value.h

@@ -0,0 +1,85 @@
+/*-----------------------------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_VALUE_H_INC
+#define OPENDDLPARSER_VALUE_H_INC
+
+#include <openddlparser/OpenDDLCommon.h>
+
+BEGIN_ODDLPARSER_NS
+
+class DLL_ODDLPARSER_EXPORT Value {
+public:
+    enum ValueType {
+        ddl_none = -1,
+        ddl_bool = 0,
+        ddl_int8,
+        ddl_int16,
+        ddl_int32,
+        ddl_int64,
+        ddl_unsigned_int8,
+        ddl_unsigned_int16,
+        ddl_unsigned_int32,
+        ddl_unsigned_int64,
+        ddl_half,
+        ddl_float,
+        ddl_double,
+        ddl_string,
+        ddl_ref,
+        ddl_types_max
+    };
+
+    Value();
+    ~Value();
+    void setBool( bool value );
+    bool getBool();
+    void setInt8( int8 value );
+    int8 getInt8();
+    void setInt16( int16 value );
+    int16  getInt16();
+    void setInt32( int32 value );
+    int32  getInt32();
+    void setInt64( int64 value );
+    int64  getInt64();
+    void setFloat( float value );
+    float getFloat() const;
+    void setDouble( double value );
+    double getDouble() const;
+    void dump();
+    void setNext( Value *next );
+    Value *getNext() const;
+
+    ValueType m_type;
+    size_t m_size;
+    unsigned char *m_data;
+    Value *m_next;
+};
+
+struct DLL_ODDLPARSER_EXPORT ValueAllocator {
+    static Value *allocPrimData( Value::ValueType type, size_t len = 1 );
+    static void releasePrimData( Value **data );
+};
+
+END_ODDLPARSER_NS
+
+#endif // OPENDDLPARSER_VALUE_H_INC