diff --git a/.gitignore b/.gitignore index 55995220d..cf0c2a94f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,7 @@ build # Output bin/ lib/ -contrib/ + # Generated assimp.pc diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c8661f55..7c9468b95 100644 --- a/CMakeLists.txt +++ b/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) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 1edaa8725..70034ed66 100644 --- a/code/CMakeLists.txt +++ b/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 ) diff --git a/contrib/openddlparser/CMakeLists.txt b/contrib/openddlparser/CMakeLists.txt new file mode 100644 index 000000000..d551c9857 --- /dev/null +++ b/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} +) diff --git a/contrib/openddlparser/README.md b/contrib/openddlparser/README.md new file mode 100644 index 000000000..195de6932 --- /dev/null +++ b/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 +> /include + +to your include-path and the + +> /lib + +to your lib-folder. Link the openddl.lib to your application. + +Here is a small example how to use the lib: + +```cpp + +#include +#include +#include + +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; igetProperty(); // 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. diff --git a/contrib/openddlparser/code/DDLNode.cpp b/contrib/openddlparser/code/DDLNode.cpp new file mode 100644 index 000000000..30977ca2e --- /dev/null +++ b/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 +#include + +#include + +BEGIN_ODDLPARSER_NS + +DDLNode::DllNodeList DDLNode::s_allocatedNodes; + +template +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( m_properties ); + releaseDataType( 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::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 diff --git a/contrib/openddlparser/code/OpenDDLParser.cpp b/contrib/openddlparser/code/OpenDDLParser.cpp new file mode 100644 index 000000000..675d58511 --- /dev/null +++ b/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 + +#include +#include +#include +#include + +#ifdef _WIN32 +# include +#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( 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( *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 &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( 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 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, ¤t ); + } else if( isFloat( in, end ) ) { + in = parseFloatingLiteral( in, end, ¤t ); + } else if( isStringLiteral( *in ) ) { + in = parseStringLiteral( in, end, ¤t ); + } else if( isHexLiteral( in, end ) ) { + in = parseHexaLiteral( in, end, ¤t ); + } + + 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, ¤t ); + 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 diff --git a/contrib/openddlparser/code/Value.cpp b/contrib/openddlparser/code/Value.cpp new file mode 100644 index 000000000..71e97a566 --- /dev/null +++ b/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 +#include +#include + +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 diff --git a/contrib/openddlparser/include/openddlparser/DDLNode.h b/contrib/openddlparser/include/openddlparser/DDLNode.h new file mode 100644 index 000000000..ceaff3d5e --- /dev/null +++ b/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 + +#include +#include + +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 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 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 diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h b/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h new file mode 100644 index 000000000..490ea46ac --- /dev/null +++ b/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 +#include + +#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 + diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h b/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h new file mode 100644 index 000000000..9e978ade2 --- /dev/null +++ b/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 + +BEGIN_ODDLPARSER_NS + +template +inline +bool isComment( T *in, T *end ) { + if( *in == '/' ) { + if( in + 1 != end ) { + if( *( in + 1 ) == '/' ) { + return true; + } + } + } + return false; +} + +template +inline +bool isUpperCase( T in ) { + return ( in >= 'A' && in <= 'Z' ); +} + +template +inline +bool isLowerCase( T in ) { + return ( in >= 'a' && in <= 'z' ); +} + +template +inline +bool isSpace( const T in ) { + return ( ' ' == in || '\t' == in ); +} + +template +inline +bool isNewLine( const T in ) { + return ( '\n' == in ); +} + +template +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 +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 +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 +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 +inline +bool isCharacter( const T in ) { + return ( in >= 'a' && in <= 'z' || in >= 'A' && in <= 'Z' ); +} + +template +inline +bool isStringLiteral( const T in ) { + return ( in == '\"' ); +} + +template +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 +inline +bool isEndofLine( const T in ) { + return ( '\n' == in ); +} + +template +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 diff --git a/contrib/openddlparser/include/openddlparser/Value.h b/contrib/openddlparser/include/openddlparser/Value.h new file mode 100644 index 000000000..665c407ed --- /dev/null +++ b/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 + +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