diff options
Diffstat (limited to 'src/3rdparty/assimp/contrib/openddlparser/code')
5 files changed, 2282 insertions, 0 deletions
diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/DDLNode.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/DDLNode.cpp new file mode 100644 index 000000000..0cc95bdfc --- /dev/null +++ b/src/3rdparty/assimp/contrib/openddlparser/code/DDLNode.cpp @@ -0,0 +1,209 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2015 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( ddl_nullptr == ptr ) { + return; + } + + T *current( ddl_nullptr ); + while( ptr ) { + current = ptr; + ptr = ptr->m_next; + delete current; + } +} + +static void releaseReferencedNames( Reference *ref ) { + if( ddl_nullptr == ref ) { + return; + } + + delete ref; +} + +DDLNode::DDLNode( const std::string &type, const std::string &name, size_t idx, DDLNode *parent ) +: m_type( type ) +, m_name( name ) +, m_parent( parent ) +, m_children() +, m_properties( ddl_nullptr ) +, m_value( ddl_nullptr ) +, m_dtArrayList( ddl_nullptr ) +, m_references( ddl_nullptr ) +, m_idx( idx ) { + if( m_parent ) { + m_parent->m_children.push_back( this ); + } +} + +DDLNode::~DDLNode() { + releaseDataType<Property>( m_properties ); + releaseDataType<Value>( m_value ); + releaseReferencedNames( m_references ); + + delete m_dtArrayList; + m_dtArrayList = ddl_nullptr; + if( s_allocatedNodes[ m_idx ] == this ) { + s_allocatedNodes[ m_idx ] = ddl_nullptr; + } +} + +void DDLNode::attachParent( DDLNode *parent ) { + if( m_parent == parent ) { + return; + } + + m_parent = parent; + if( ddl_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 = ddl_nullptr; + } +} + +DDLNode *DDLNode::getParent() const { + return m_parent; +} + +const DDLNode::DllNodeList &DDLNode::getChildNodeList() const { + return m_children; +} + +void DDLNode::setType( const std::string &type ) { + m_type = type; +} + +const std::string &DDLNode::getType() const { + return m_type; +} + +void DDLNode::setName( const std::string &name ) { + m_name = name; +} + +const std::string &DDLNode::getName() const { + return m_name; +} + +void DDLNode::setProperties( Property *prop ) { + m_properties = prop; +} + +Property *DDLNode::getProperties() const { + return m_properties; +} + +bool DDLNode::hasProperty( const std::string &name ) { + const Property *prop( findPropertyByName( name ) ); + return ( ddl_nullptr != prop ); +} + +bool DDLNode::hasProperties() const { + return( ddl_nullptr != m_properties ); +} + +Property *DDLNode::findPropertyByName( const std::string &name ) { + if( name.empty() ) { + return ddl_nullptr; + } + + if( ddl_nullptr == m_properties ) { + return ddl_nullptr; + } + + Property *current( m_properties ); + while( ddl_nullptr != current ) { + int res = strncmp( current->m_key->m_buffer, name.c_str(), name.size() ); + if( 0 == res ) { + return current; + } + current = current->m_next; + } + + return ddl_nullptr; +} + +void DDLNode::setValue( Value *val ) { + m_value = val; +} + +Value *DDLNode::getValue() const { + return m_value; +} + +void DDLNode::setDataArrayList( DataArrayList *dtArrayList ) { + m_dtArrayList = dtArrayList; +} + +DataArrayList *DDLNode::getDataArrayList() const { + return m_dtArrayList; +} + +void DDLNode::setReferences( Reference *refs ) { + m_references = refs; +} + +Reference *DDLNode::getReferences() const { + return m_references; +} + +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/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp new file mode 100644 index 000000000..13a96f7a8 --- /dev/null +++ b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp @@ -0,0 +1,186 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2015 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/OpenDDLCommon.h> +#include <openddlparser/DDLNode.h> + +BEGIN_ODDLPARSER_NS + +Text::Text( const char *buffer, size_t numChars ) +: m_capacity( 0 ) +, m_len( 0 ) +, m_buffer( ddl_nullptr ) { + set( buffer, numChars ); +} + +Text::~Text() { + clear(); +} + +void Text::clear() { + delete[] m_buffer; + m_buffer = ddl_nullptr; + m_capacity = 0; + m_len = 0; +} + +void Text::set( const char *buffer, size_t numChars ) { + clear(); + if( numChars > 0 ) { + m_len = numChars; + m_capacity = m_len + 1; + m_buffer = new char[ m_capacity ]; + strncpy( m_buffer, buffer, numChars ); + m_buffer[ numChars ] = '\0'; + } +} + +bool Text::operator == ( const std::string &name ) const { + if( m_len != name.size() ) { + return false; + } + const int res( strncmp( m_buffer, name.c_str(), name.size() ) ); + + return ( 0 == res ); +} + +bool Text::operator == ( const Text &rhs ) const { + if( m_len != rhs.m_len ) { + return false; + } + + const int res( strncmp( m_buffer, rhs.m_buffer, m_len ) ); + + return ( 0 == res ); +} + +Name::Name( NameType type, Text *id ) +: m_type( type ) +, m_id( id ) { + // empty +} + +Name::~Name() { + delete m_id; + m_id = ddl_nullptr; +} + +Reference::Reference() +: m_numRefs( 0 ) +, m_referencedName( ddl_nullptr ) { + // empty +} + +Reference::Reference( size_t numrefs, Name **names ) +: m_numRefs( numrefs ) +, m_referencedName( ddl_nullptr ) { + if ( numrefs > 0 ) { + m_referencedName = new Name *[ numrefs ]; + for ( size_t i = 0; i < numrefs; i++ ) { + Name *name = new Name( names[ i ]->m_type, names[ i ]->m_id ); + m_referencedName[ i ] = name; + } + } +} + +Reference::~Reference() { + for( size_t i = 0; i < m_numRefs; i++ ) { + delete m_referencedName[ i ]; + } + m_numRefs = 0; + m_referencedName = ddl_nullptr; +} + +size_t Reference::sizeInBytes() { + if ( 0 == m_numRefs ) { + return 0; + } + + size_t size( 0 ); + for ( size_t i = 0; i < m_numRefs; i++ ) { + Name *name( m_referencedName[ i ] ); + if ( ddl_nullptr != name ) { + size += name->m_id->m_len; + } + } + + return size; +} + +Property::Property( Text *id ) +: m_key( id ) +, m_value( ddl_nullptr ) +, m_ref( ddl_nullptr ) +, m_next( ddl_nullptr ) { + // empty +} + +Property::~Property() { + m_key = ddl_nullptr; + m_value = ddl_nullptr; + m_ref = ddl_nullptr;; + m_next = ddl_nullptr;; +} + +DataArrayList::DataArrayList() +: m_numItems( 0 ) +, m_dataList( ddl_nullptr ) +, m_next( ddl_nullptr ) { + // empty +} + +DataArrayList::~DataArrayList() { + // empty +} + +size_t DataArrayList::size() { + size_t result( 0 ); + if ( ddl_nullptr == m_next ) { + if ( m_dataList != ddl_nullptr ) { + result = 1; + } + return result; + } + + DataArrayList *n( m_next ); + while( ddl_nullptr != n ) { + result++; + n = n->m_next; + } + return result; +} + +Context::Context() +: m_root( ddl_nullptr ) { + // empty +} + +Context::~Context() { + clear(); +} + +void Context::clear() { + delete m_root; + m_root = ddl_nullptr; +} + +END_ODDLPARSER_NS diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLExport.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLExport.cpp new file mode 100644 index 000000000..2e73ea470 --- /dev/null +++ b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLExport.cpp @@ -0,0 +1,439 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2015 Kim Kulling + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-----------------------------------------------------------------------------------------------*/ +#include <openddlparser/OpenDDLExport.h> +#include <openddlparser/DDLNode.h> +#include <openddlparser/Value.h> +#include <openddlparser/OpenDDLParser.h> + +#include <sstream> + +BEGIN_ODDLPARSER_NS + +StreamFormatterBase::StreamFormatterBase() { + +} + +StreamFormatterBase::~StreamFormatterBase() { + +} + +std::string StreamFormatterBase::format( const std::string &statement ) { + std::string tmp( statement ); + return tmp; +} + +IOStreamBase::IOStreamBase( StreamFormatterBase *formatter ) +: m_formatter( formatter ) +, m_file( ddl_nullptr ) { + if (ddl_nullptr == m_formatter) { + m_formatter = new StreamFormatterBase; + } +} + +IOStreamBase::~IOStreamBase() { + delete m_formatter; + m_formatter = ddl_nullptr; +} + +bool IOStreamBase::open( const std::string &name ) { + m_file = ::fopen( name.c_str(), "a" ); + if (m_file == ddl_nullptr) { + return false; + } + + return true; +} + +bool IOStreamBase::close() { + if (ddl_nullptr == m_file) { + return false; + } + + ::fclose( m_file ); + m_file = ddl_nullptr; + + return true; +} + +size_t IOStreamBase::write( const std::string &statement ) { + if (ddl_nullptr == m_file) { + return 0; + } + std::string formatStatement = m_formatter->format( statement ); + return ::fwrite( formatStatement.c_str(), sizeof( char ), formatStatement.size(), m_file ); +} + +struct DDLNodeIterator { + const DDLNode::DllNodeList &m_childs; + size_t m_idx; + + DDLNodeIterator( const DDLNode::DllNodeList &childs ) + : m_childs( childs ) + , m_idx( 0 ) { + // empty + } + + ~DDLNodeIterator() { + // empty + } + + bool getNext( DDLNode **node ) { + if( m_childs.size() > (m_idx+1) ) { + m_idx++; + *node = m_childs[ m_idx ]; + return true; + } + + return false; + } + +private: + DDLNodeIterator() ddl_no_copy; + DDLNodeIterator &operator = ( const DDLNodeIterator & ) ddl_no_copy; +}; + +static void writeLineEnd( std::string &statement ) { + statement += "\n"; +} + +OpenDDLExport::OpenDDLExport( IOStreamBase *stream ) +: m_stream( stream ) { + if (ddl_nullptr == m_stream) { + m_stream = new IOStreamBase(); + } +} + +OpenDDLExport::~OpenDDLExport() { + if (ddl_nullptr != m_stream) { + m_stream->close(); + } + delete m_stream; +} + +bool OpenDDLExport::exportContext( Context *ctx, const std::string &filename ) { + if( ddl_nullptr == ctx ) { + return false; + } + + DDLNode *root( ctx->m_root ); + if ( ddl_nullptr == root ) { + return true; + } + + if (!filename.empty()) { + if (!m_stream->open( filename )) { + return false; + } + } + + const bool retValue( handleNode( root ) ); + + return retValue; +} + +bool OpenDDLExport::handleNode( DDLNode *node ) { + if( ddl_nullptr == node ) { + return true; + } + + const DDLNode::DllNodeList &childs = node->getChildNodeList(); + if( childs.empty() ) { + return true; + } + DDLNode *current( ddl_nullptr ); + DDLNodeIterator it( childs ); + std::string statement; + bool success( true ); + while( it.getNext( ¤t ) ) { + if( ddl_nullptr != current ) { + success |= writeNode( current, statement ); + if( !handleNode( current ) ) { + success = false; + } + } + } + + return success; +} + +bool OpenDDLExport::writeToStream( const std::string &statement ) { + if (ddl_nullptr == m_stream ) { + return false; + } + + if ( !statement.empty()) { + m_stream->write( statement ); + } + + return true; +} + +bool OpenDDLExport::writeNode( DDLNode *node, std::string &statement ) { + bool success( true ); + writeNodeHeader( node, statement ); + if (node->hasProperties()) { + success |= writeProperties( node, statement ); + } + writeLineEnd( statement ); + + statement = "}"; + DataArrayList *al( node->getDataArrayList() ); + if ( ddl_nullptr != al ) { + writeValueType( al->m_dataList->m_type, al->m_numItems, statement ); + writeValueArray( al, statement ); + } + Value *v( node->getValue() ); + if (ddl_nullptr != v ) { + writeValueType( v->m_type, 1, statement ); + statement = "{"; + writeLineEnd( statement ); + writeValue( v, statement ); + statement = "}"; + writeLineEnd( statement ); + } + statement = "}"; + writeLineEnd( statement ); + + writeToStream( statement ); + + return true; +} + +bool OpenDDLExport::writeNodeHeader( DDLNode *node, std::string &statement ) { + if (ddl_nullptr == node) { + return false; + } + + statement += node->getType(); + const std::string &name( node->getName() ); + if ( !name.empty() ) { + statement += " "; + statement += "$"; + statement += name; + } + + return true; +} + +bool OpenDDLExport::writeProperties( DDLNode *node, std::string &statement ) { + if ( ddl_nullptr == node ) { + return false; + } + + Property *prop( node->getProperties() ); + // if no properties are there, return + if ( ddl_nullptr == prop ) { + return true; + } + + if ( ddl_nullptr != prop ) { + // for instance (attrib = "position", bla=2) + statement += "("; + bool first( true ); + while ( ddl_nullptr != prop ) { + if (!first) { + statement += ", "; + } else { + first = false; + } + statement += std::string( prop->m_key->m_buffer ); + statement += " = "; + writeValue( prop->m_value, statement ); + prop = prop->m_next; + } + + statement += ")"; + } + + return true; +} + +bool OpenDDLExport::writeValueType( Value::ValueType type, size_t numItems, std::string &statement ) { + if ( Value::ddl_types_max == type) { + return false; + } + + const std::string typeStr( getTypeToken( type ) ); + statement += typeStr; + // if we have an array to write + if ( numItems > 1 ) { + statement += "["; + char buffer[ 256 ]; + ::memset( buffer, '\0', 256 * sizeof( char ) ); + sprintf( buffer, "%d", int(numItems) ); + statement += buffer; + statement += "]"; + } + + return true; +} + +bool OpenDDLExport::writeValue( Value *val, std::string &statement ) { + if (ddl_nullptr == val) { + return false; + } + + switch ( val->m_type ) { + case Value::ddl_bool: + if ( true == val->getBool() ) { + statement += "true"; + } else { + statement += "false"; + } + break; + case Value::ddl_int8: + { + std::stringstream stream; + const int i = static_cast<int>( val->getInt8() ); + stream << i; + statement += stream.str(); + } + break; + case Value::ddl_int16: + { + std::stringstream stream; + char buffer[ 256 ]; + ::memset( buffer, '\0', 256 * sizeof( char ) ); + sprintf( buffer, "%d", val->getInt16() ); + statement += buffer; + } + break; + case Value::ddl_int32: + { + std::stringstream stream; + char buffer[ 256 ]; + ::memset( buffer, '\0', 256 * sizeof( char ) ); + const int i = static_cast< int >( val->getInt32() ); + sprintf( buffer, "%d", i ); + statement += buffer; + } + break; + case Value::ddl_int64: + { + std::stringstream stream; + const int i = static_cast< int >( val->getInt64() ); + stream << i; + statement += stream.str(); + } + break; + case Value::ddl_unsigned_int8: + { + std::stringstream stream; + const int i = static_cast< unsigned int >( val->getUnsignedInt8() ); + stream << i; + statement += stream.str(); + } + break; + case Value::ddl_unsigned_int16: + { + std::stringstream stream; + const int i = static_cast< unsigned int >( val->getUnsignedInt16() ); + stream << i; + statement += stream.str(); + } + break; + case Value::ddl_unsigned_int32: + { + std::stringstream stream; + const int i = static_cast< unsigned int >( val->getUnsignedInt32() ); + stream << i; + statement += stream.str(); + } + break; + case Value::ddl_unsigned_int64: + { + std::stringstream stream; + const int i = static_cast< unsigned int >( val->getUnsignedInt64() ); + stream << i; + statement += stream.str(); + } + break; + case Value::ddl_half: + break; + case Value::ddl_float: + { + std::stringstream stream; + stream << val->getFloat(); + statement += stream.str(); + } + break; + case Value::ddl_double: + { + std::stringstream stream; + stream << val->getDouble(); + statement += stream.str(); + } + break; + case Value::ddl_string: + { + std::stringstream stream; + stream << val->getString(); + statement += "\""; + statement += stream.str(); + statement += "\""; + } + break; + case Value::ddl_ref: + break; + case Value::ddl_none: + case Value::ddl_types_max: + default: + break; + } + + return true; +} + +bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement ) { + if (ddl_nullptr == al) { + return false; + } + + if (0 == al->m_numItems) { + return true; + } + + DataArrayList *nextDataArrayList = al ; + Value *nextValue( nextDataArrayList->m_dataList ); + while (ddl_nullptr != nextDataArrayList) { + if (ddl_nullptr != nextDataArrayList) { + statement += "{ "; + nextValue = nextDataArrayList->m_dataList; + size_t idx( 0 ); + while (ddl_nullptr != nextValue) { + if (idx > 0) { + statement += ", "; + } + writeValue( nextValue, statement ); + nextValue = nextValue->m_next; + idx++; + } + statement += " }"; + } + nextDataArrayList = nextDataArrayList->m_next; + } + + return true; +} + +END_ODDLPARSER_NS diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLParser.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLParser.cpp new file mode 100644 index 000000000..6f471be36 --- /dev/null +++ b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLParser.cpp @@ -0,0 +1,1008 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2015 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 <openddlparser/OpenDDLExport.h> + +#include <cassert> +#include <iostream> +#include <sstream> +#include <algorithm> +#include <math.h> + +#ifdef _WIN32 +# include <windows.h> +#endif // _WIN32 + + +BEGIN_ODDLPARSER_NS + +static const char *Version = "0.3.0"; + +namespace Grammar { + static const char *OpenBracketToken = "{"; + static const char *CloseBracketToken = "}"; + static const char *OpenPropertyToken = "("; + static const char *ClosePropertyToken = ")"; + static const char *OpenArrayToken = "["; + static const char *CloseArrayToken = "]"; + static const char *BoolTrue = "true"; + static const char *BoolFalse = "false"; + static const char *CommaSeparator = ","; + + static const char* PrimitiveTypeToken[ Value::ddl_types_max ] = { + "bool", + "int8", + "int16", + "int32", + "int64", + "unsigned_int8", + "unsigned_int16", + "unsigned_int32", + "unsigned_int64", + "half", + "float", + "double", + "string", + "ref" + }; +} // Namespace Grammar + +const char *getTypeToken( Value::ValueType type ) { + return Grammar::PrimitiveTypeToken[ type ]; +} + +static void logInvalidTokenError( char *in, const std::string &exp, OpenDDLParser::logCallback callback ) { + std::stringstream stream; + stream << "Invalid token \"" << *in << "\"" << " expected \"" << exp << "\"" << std::endl; + std::string full(in); + std::string part(full.substr(0,50)); + stream << part; + 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 bool isUnsignedIntegerType( Value::ValueType integerType ) { + if( integerType != Value::ddl_unsigned_int8 && integerType != Value::ddl_unsigned_int16 && + integerType != Value::ddl_unsigned_int32 && integerType != Value::ddl_unsigned_int64 ) { + return false; + } + + return true; +} + +static DDLNode *createDDLNode( Text *id, OpenDDLParser *parser ) { + if( ddl_nullptr == id || ddl_nullptr == parser ) { + return ddl_nullptr; + } + + const std::string type( id->m_buffer ); + DDLNode *parent( parser->top() ); + DDLNode *node = DDLNode::create( type, "", parent ); + + 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_buffer() +, m_stack() +, m_context( ddl_nullptr ) { + // empty +} + +OpenDDLParser::OpenDDLParser( const char *buffer, size_t len ) +: m_logCallback( &logMessage ) +, m_buffer() +, m_context( ddl_nullptr ) { + if( 0 != len ) { + setBuffer( buffer, len ); + } +} + +OpenDDLParser::~OpenDDLParser() { + clear(); +} + +void OpenDDLParser::setLogCallback( logCallback callback ) { + if( ddl_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( const char *buffer, size_t len ) { + clear(); + if( 0 == len ) { + return; + } + + m_buffer.resize( len ); + ::memcpy(&m_buffer[ 0 ], buffer, len ); +} + +void OpenDDLParser::setBuffer( const std::vector<char> &buffer ) { + clear(); + m_buffer.resize( buffer.size() ); + std::copy( buffer.begin(), buffer.end(), m_buffer.begin() ); +} + +const char *OpenDDLParser::getBuffer() const { + if( m_buffer.empty() ) { + return ddl_nullptr; + } + + return &m_buffer[ 0 ]; +} + +size_t OpenDDLParser::getBufferSize() const { + return m_buffer.size(); +} + +void OpenDDLParser::clear() { + m_buffer.resize( 0 ); + if( ddl_nullptr != m_context ) { + m_context->m_root = ddl_nullptr; + } + + DDLNode::releaseNodes(); +} + +bool OpenDDLParser::parse() { + if( m_buffer.empty() ) { + return false; + } + + normalizeBuffer( m_buffer ); + + m_context = new Context; + m_context->m_root = DDLNode::create( "root", "", ddl_nullptr ); + pushNode( m_context->m_root ); + + // do the main parsing + char *current( &m_buffer[ 0 ] ); + char *end( &m_buffer[ m_buffer.size() - 1 ] + 1 ); + size_t pos( current - &m_buffer[ 0 ] ); + while( pos < m_buffer.size() ) { + current = parseNextNode( current, end ); + if(current==ddl_nullptr) { + return false; + } + pos = current - &m_buffer[ 0 ]; + } + return true; +} + +bool OpenDDLParser::exportContext( Context *ctx, const std::string &filename ) { + if( ddl_nullptr == ctx ) { + return false; + } + + OpenDDLExport myExporter; + return myExporter.exportContext( ctx, filename ); +} + +char *OpenDDLParser::parseNextNode( char *in, char *end ) { + in = parseHeader( in, end ); + in = parseStructure( in, end ); + + return in; +} + +#ifdef DEBUG_HEADER_NAME +static void dumpId( Identifier *id ) { + if( ddl_nullptr != id ) { + if ( ddl_nullptr != id->m_text.m_buffer ) { + std::cout << id->m_text.m_buffer << std::endl; + } + } +} +#endif + +char *OpenDDLParser::parseHeader( char *in, char *end ) { + if( ddl_nullptr == in || in == end ) { + return in; + } + + Text *id( ddl_nullptr ); + in = OpenDDLParser::parseIdentifier( in, end, &id ); + +#ifdef DEBUG_HEADER_NAME + dumpId( id ); +#endif // DEBUG_HEADER_NAME + + in = lookForNextToken( in, end ); + if( ddl_nullptr != id ) { + // store the node + DDLNode *node( createDDLNode( id, this ) ); + if( ddl_nullptr != node ) { + pushNode( node ); + } else { + std::cerr << "nullptr returned by creating DDLNode." << std::endl; + } + + Name *name(ddl_nullptr); + in = OpenDDLParser::parseName(in, end, &name); + if( ddl_nullptr != name && ddl_nullptr != node ) { + const std::string nodeName( name->m_id->m_buffer ); + node->setName( nodeName ); + } + + Property *first(ddl_nullptr); + in = lookForNextToken(in, end); + if (*in == Grammar::OpenPropertyToken[0]) { + in++; + Property *prop(ddl_nullptr), *prev(ddl_nullptr); + while (*in != Grammar::ClosePropertyToken[0] && in != end) { + in = OpenDDLParser::parseProperty(in, end, &prop); + in = lookForNextToken(in, end); + + if (*in != Grammar::CommaSeparator[0] && *in != Grammar::ClosePropertyToken[0]) { + logInvalidTokenError(in, Grammar::ClosePropertyToken, m_logCallback); + return ddl_nullptr; + } + + if (ddl_nullptr != prop && *in != Grammar::CommaSeparator[0]) { + if (ddl_nullptr == first) { + first = prop; + } + if (ddl_nullptr != prev) { + prev->m_next = prop; + } + prev = prop; + } + } + in++; + } + + // set the properties + if (ddl_nullptr != first && ddl_nullptr != node) { + node->setProperties(first); + } + } + + return in; +} + +char *OpenDDLParser::parseStructure( char *in, char *end ) { + if( ddl_nullptr == in || in == end ) { + return in; + } + + bool error( false ); + in = lookForNextToken( in, end ); + if( *in == '{' ) { + // loop over all children ( data and nodes ) + do { + in = parseStructureBody( in, end, error ); + if(in == ddl_nullptr){ + return ddl_nullptr; + } + } while ( *in != '}' ); + in++; + } else { + in++; + logInvalidTokenError( in, std::string( Grammar::OpenBracketToken ), m_logCallback ); + error = true; + return ddl_nullptr; + } + in = lookForNextToken( in, end ); + + // pop node from stack after successful parsing + if( !error ) { + popNode(); + } + + return in; +} + +static void setNodeValues( DDLNode *currentNode, Value *values ) { + if( ddl_nullptr != values ){ + if( ddl_nullptr != currentNode ) { + currentNode->setValue( values ); + } + } +} + +static void setNodeReferences( DDLNode *currentNode, Reference *refs ) { + if( ddl_nullptr != refs ) { + if( ddl_nullptr != currentNode ) { + currentNode->setReferences( refs ); + } + } +} + +static void setNodeDataArrayList( DDLNode *currentNode, DataArrayList *dtArrayList ) { + if( ddl_nullptr != dtArrayList ) { + if( ddl_nullptr != currentNode ) { + currentNode->setDataArrayList( dtArrayList ); + } + } +} + +char *OpenDDLParser::parseStructureBody( char *in, char *end, bool &error ) { + if( !isNumeric( *in ) && !isCharacter( *in ) ) { + in++; + } + + in = lookForNextToken( in, end ); + Value::ValueType type( Value::ddl_none ); + size_t arrayLen( 0 ); + in = OpenDDLParser::parsePrimitiveDataType( in, end, type, arrayLen ); + if( Value::ddl_none != type ) { + // parse a primitive data type + in = lookForNextToken( in, end ); + if( *in == Grammar::OpenBracketToken[ 0 ] ) { + Reference *refs( ddl_nullptr ); + DataArrayList *dtArrayList( ddl_nullptr ); + Value *values( ddl_nullptr ); + if( 1 == arrayLen ) { + size_t numRefs( 0 ), numValues( 0 ); + in = parseDataList( in, end, type, &values, numValues, &refs, numRefs ); + setNodeValues( top(), values ); + setNodeReferences( top(), refs ); + } else if( arrayLen > 1 ) { + in = parseDataArrayList( in, end, type, &dtArrayList ); + setNodeDataArrayList( top(), dtArrayList ); + } else { + std::cerr << "0 for array is invalid." << std::endl; + error = true; + } + } + + in = lookForNextToken( in, end ); + if( *in != '}' ) { + logInvalidTokenError( in, std::string( Grammar::CloseBracketToken ), m_logCallback ); + return ddl_nullptr; + } else { + //in++; + } + } else { + // parse a complex data type + in = parseNextNode( in, end ); + } + + return in; +} + +void OpenDDLParser::pushNode( DDLNode *node ) { + if( ddl_nullptr == node ) { + return; + } + + m_stack.push_back( node ); +} + +DDLNode *OpenDDLParser::popNode() { + if( m_stack.empty() ) { + return ddl_nullptr; + } + + DDLNode *topNode( top() ); + m_stack.pop_back(); + + return topNode; +} + +DDLNode *OpenDDLParser::top() { + if( m_stack.empty() ) { + return ddl_nullptr; + } + + DDLNode *top( m_stack.back() ); + return top; +} + +DDLNode *OpenDDLParser::getRoot() const { + if( ddl_nullptr == m_context ) { + return ddl_nullptr; + } + + return m_context->m_root; +} + +Context *OpenDDLParser::getContext() const { + return m_context; +} + +void OpenDDLParser::normalizeBuffer( std::vector<char> &buffer) { + if( buffer.empty() ) { + return; + } + + std::vector<char> newBuffer; + const size_t len( buffer.size() ); + char *end( &buffer[ len-1 ] + 1 ); + for( size_t readIdx = 0; readIdx<len; ++readIdx ) { + char *c( &buffer[readIdx] ); + // check for a comment + if( !isComment<char>( c, end ) && !isNewLine( *c ) ) { + newBuffer.push_back( buffer[ readIdx ] ); + } else { + if( isComment<char>( c, end ) ) { + ++readIdx; + // skip the comment and the rest of the line + while( !isEndofLine( buffer[ readIdx ] ) ) { + ++readIdx; + } + } + } + } + buffer = newBuffer; +} + +char *OpenDDLParser::parseName( char *in, char *end, Name **name ) { + *name = ddl_nullptr; + if( ddl_nullptr == in || in == end ) { + return in; + } + + // ignore blanks + in = lookForNextToken( in, end ); + if( *in != '$' && *in != '%' ) { + return in; + } + + NameType ntype( GlobalName ); + if( *in == '%' ) { + ntype = LocalName; + } + in++; + Name *currentName( ddl_nullptr ); + Text *id( ddl_nullptr ); + in = parseIdentifier( in, end, &id ); + if( id ) { + currentName = new Name( ntype, id ); + if( currentName ) { + *name = currentName; + } + } + + return in; +} + +char *OpenDDLParser::parseIdentifier( char *in, char *end, Text **id ) { + *id = ddl_nullptr; + if( ddl_nullptr == in || in == end ) { + return in; + } + + // ignore blanks + in = lookForNextToken( 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 ) && !isNewLine( *in ) && ( in != end ) && *in != Grammar::OpenPropertyToken[ 0 ] && *in != Grammar::ClosePropertyToken[ 0 ] && *in != '$' ) { + ++in; + ++idLen; + } + + const size_t len( idLen ); + Text *newId = new Text( start, len ); + *id = newId; + + return in; +} + +char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueType &type, size_t &len ) { + type = Value::ddl_none; + len = 0; + if( ddl_nullptr == in || in == end ) { + return in; + } + + size_t prim_len( 0 ); + for( unsigned int i = 0; i < Value::ddl_types_max; i++ ) { + prim_len = strlen( Grammar::PrimitiveTypeToken[ i ] ); + if( 0 == strncmp( in, Grammar::PrimitiveTypeToken[ i ], prim_len ) ) { + type = ( Value::ValueType ) i; + break; + } + } + + if( Value::ddl_none == type ) { + in = lookForNextToken( in, end ); + return in; + } else { + in += prim_len; + } + + bool ok( true ); + if( *in == Grammar::OpenArrayToken[ 0 ] ) { + ok = false; + in++; + char *start( in ); + while ( in != end ) { + in++; + if( *in == Grammar::CloseArrayToken[ 0 ] ) { + len = ::atoi( start ); + ok = true; + in++; + break; + } + } + } else { + len = 1; + } + if( !ok ) { + type = Value::ddl_none; + } + + return in; +} + +char *OpenDDLParser::parseReference( char *in, char *end, std::vector<Name*> &names ) { + if( ddl_nullptr == in || in == end ) { + return in; + } + + Name *nextName( ddl_nullptr ); + in = parseName( in, end, &nextName ); + if( nextName ) { + names.push_back( nextName ); + } + while( Grammar::CommaSeparator[ 0 ] == *in ) { + in = getNextSeparator( in, end ); + if( Grammar::CommaSeparator[ 0 ] == *in ) { + in = parseName( in, end, &nextName ); + if( nextName ) { + names.push_back( nextName ); + } + } else { + break; + } + } + + return in; +} + +char *OpenDDLParser::parseBooleanLiteral( char *in, char *end, Value **boolean ) { + *boolean = ddl_nullptr; + if( ddl_nullptr == in || in == end ) { + return in; + } + + in = lookForNextToken( in, end ); + char *start( in ); + size_t len( 0 ); + while( !isSeparator( *in ) && in != end ) { + in++; + len++; + } + len++; + int res = ::strncmp( Grammar::BoolTrue, start, strlen( Grammar::BoolTrue ) ); + if( 0 != res ) { + res = ::strncmp( Grammar::BoolFalse, start, strlen( Grammar::BoolFalse ) ); + if( 0 != res ) { + *boolean = ddl_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 = ddl_nullptr; + if( ddl_nullptr == in || in == end ) { + return in; + } + + if( !(isIntegerType( integerType ) || isUnsignedIntegerType(integerType)) ) { + return in; + } + + in = lookForNextToken( in, end ); + char *start( in ); + while( !isSeparator( *in ) && in != end ) { + in++; + } + + if( isNumeric( *start ) ) { +#ifdef OPENDDL_NO_USE_CPP11 + const int64 value( atol( start ) ); // maybe not really 64bit as atoll is but exists without c++11 + const uint64 uvalue( strtoul( start,ddl_nullptr,10 ) ); +#else + const int64 value( atoll( start ) ); + const uint64 uvalue( strtoull( start,ddl_nullptr,10 ) ); +#endif + *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; + case Value::ddl_unsigned_int8: + ( *integer )->setUnsignedInt8( (uint8) uvalue ); + break; + case Value::ddl_unsigned_int16: + ( *integer )->setUnsignedInt16( ( uint16 ) uvalue ); + break; + case Value::ddl_unsigned_int32: + ( *integer )->setUnsignedInt32( ( uint32 ) uvalue ); + break; + case Value::ddl_unsigned_int64: + ( *integer )->setUnsignedInt64( ( uint64 ) uvalue ); + break; + default: + break; + } + } + + return in; +} + +char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating, Value::ValueType floatType) { + *floating = ddl_nullptr; + if( ddl_nullptr == in || in == end ) { + return in; + } + + in = lookForNextToken( in, end ); + char *start( in ); + while( !isSeparator( *in ) && in != end ) { + in++; + } + + // parse the float value + bool ok( false ); + if ( isHexLiteral( start, end ) ) { + parseHexaLiteral( start, end, floating ); + return in; + } + + if( isNumeric( *start ) ) { + ok = true; + } else { + if( *start == '-' ) { + if( isNumeric( *(start+1) ) ) { + ok = true; + } + } + } + + if( ok ) { + if(floatType == Value::ddl_double) + { + const double value( atof( start ) ); + *floating = ValueAllocator::allocPrimData( Value::ddl_double ); + ( *floating )->setDouble( value ); + } else { + 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 = ddl_nullptr; + if( ddl_nullptr == in || in == end ) { + return in; + } + + in = lookForNextToken( in, end ); + size_t len( 0 ); + char *start( in ); + if( *start == '\"' ) { + start++; + in++; + while( *in != '\"' && in != end ) { + in++; + len++; + } + + *stringData = ValueAllocator::allocPrimData( Value::ddl_string, len ); + ::strncpy( ( char* ) ( *stringData )->m_data, start, len ); + ( *stringData )->m_data[len] = '\0'; + in++; + } + + return in; +} + +static void createPropertyWithData( Text *id, Value *primData, Property **prop ) { + if( ddl_nullptr != primData ) { + ( *prop ) = new Property( id ); + ( *prop )->m_value = primData; + } +} + +char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) { + *data = ddl_nullptr; + if( ddl_nullptr == in || in == end ) { + return in; + } + + in = lookForNextToken( in, end ); + if( *in != '0' ) { + return in; + } + + in++; + if( *in != 'x' && *in != 'X' ) { + return in; + } + + in++; + bool ok( true ); + char *start( in ); + int pos( 0 ); + while( !isSeparator( *in ) && in != end ) { + if( ( *in < '0' && *in > '9' ) || ( *in < 'a' && *in > 'f' ) || ( *in < 'A' && *in > 'F' ) ) { + ok = false; + break; + } + pos++; + in++; + } + + if( !ok ) { + return in; + } + + int value( 0 ); + while( pos > 0 ) { + int v = hex2Decimal( *start ); + pos--; + value = ( value << 4 ) | v; + start++; + } + + *data = ValueAllocator::allocPrimData( Value::ddl_unsigned_int64 ); + if( ddl_nullptr != *data ) { + ( *data )->setUnsignedInt64( value ); + } + + return in; +} + +char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) { + *prop = ddl_nullptr; + if( ddl_nullptr == in || in == end ) { + return in; + } + + in = lookForNextToken( in, end ); + Text *id( ddl_nullptr ); + in = parseIdentifier( in, end, &id ); + if( ddl_nullptr != id ) { + in = lookForNextToken( in, end ); + if( *in == '=' ) { + in++; + in = getNextToken( in, end ); + Value *primData( ddl_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::ValueType type, Value **data, + size_t &numValues, Reference **refs, size_t &numRefs ) { + *data = ddl_nullptr; + numValues = numRefs = 0; + if( ddl_nullptr == in || in == end ) { + return in; + } + + in = lookForNextToken( in, end ); + if( *in == '{' ) { + in++; + Value *current( ddl_nullptr ), *prev( ddl_nullptr ); + while( '}' != *in ) { + current = ddl_nullptr; + in = lookForNextToken( in, end ); + if ( Value::ddl_ref == type ) { + std::vector<Name*> names; + in = parseReference( in, end, names ); + if ( !names.empty() ) { + Reference *ref = new Reference( names.size(), &names[ 0 ] ); + *refs = ref; + numRefs = names.size(); + } + } else if ( Value::ddl_none == type ) { + 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 ); + } + } else { + switch(type){ + case Value::ddl_int8: + case Value::ddl_int16: + case Value::ddl_int32: + case Value::ddl_int64: + case Value::ddl_unsigned_int8: + case Value::ddl_unsigned_int16: + case Value::ddl_unsigned_int32: + case Value::ddl_unsigned_int64: + in = parseIntegerLiteral( in, end, ¤t, type); + break; + case Value::ddl_half: + case Value::ddl_float: + case Value::ddl_double: + in = parseFloatingLiteral( in, end, ¤t, type); + break; + case Value::ddl_string: + in = parseStringLiteral( in, end, ¤t ); + break; + default: + break; + } + } + + if( ddl_nullptr != current ) { + if( ddl_nullptr == *data ) { + *data = current; + prev = current; + } else { + prev->setNext( current ); + prev = current; + } + numValues++; + } + + in = getNextSeparator( in, end ); + if( ',' != *in && Grammar::CloseBracketToken[ 0 ] != *in && !isSpace( *in ) ) { + break; + } + } + in++; + } + + return in; +} + +static DataArrayList *createDataArrayList( Value *currentValue, size_t numValues, + Reference *refs, size_t numRefs ) { + DataArrayList *dataList( new DataArrayList ); + dataList->m_dataList = currentValue; + dataList->m_numItems = numValues; + dataList->m_refs = refs; + dataList->m_numRefs = numRefs; + + return dataList; +} + +char *OpenDDLParser::parseDataArrayList( char *in, char *end,Value::ValueType type, + DataArrayList **dataArrayList ) { + if ( ddl_nullptr == dataArrayList ) { + return in; + } + + *dataArrayList = ddl_nullptr; + if( ddl_nullptr == in || in == end ) { + return in; + } + + in = lookForNextToken( in, end ); + if( *in == Grammar::OpenBracketToken[ 0 ] ) { + in++; + Value *currentValue( ddl_nullptr ); + Reference *refs( ddl_nullptr ); + DataArrayList *prev( ddl_nullptr ), *currentDataList( ddl_nullptr ); + do { + size_t numRefs( 0 ), numValues( 0 ); + currentValue = ddl_nullptr; + + in = parseDataList( in, end, type, ¤tValue, numValues, &refs, numRefs ); + if( ddl_nullptr != currentValue || 0 != numRefs ) { + if( ddl_nullptr == prev ) { + *dataArrayList = createDataArrayList( currentValue, numValues, refs, numRefs ); + prev = *dataArrayList; + } else { + currentDataList = createDataArrayList( currentValue, numValues, refs, numRefs ); + if( ddl_nullptr != prev ) { + prev->m_next = currentDataList; + prev = currentDataList; + } + } + } + } while( Grammar::CommaSeparator[ 0 ] == *in && in != end ); + in = lookForNextToken( in, end ); + in++; + } + + return in; +} + +const char *OpenDDLParser::getVersion() { + return Version; +} + +END_ODDLPARSER_NS diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/Value.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/Value.cpp new file mode 100644 index 000000000..3e251c508 --- /dev/null +++ b/src/3rdparty/assimp/contrib/openddlparser/code/Value.cpp @@ -0,0 +1,440 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2015 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 + +static Value::Iterator end( ddl_nullptr ); + +Value::Iterator::Iterator() +: m_start( ddl_nullptr ) +, m_current( ddl_nullptr ) { + // empty +} + +Value::Iterator::Iterator( Value *start ) +: m_start( start ) +, m_current( start ) { + // empty +} + +Value::Iterator::Iterator( const Iterator &rhs ) +: m_start( rhs.m_start ) +, m_current( rhs.m_current ) { + // empty +} + +Value::Iterator::~Iterator() { + // empty +} + +bool Value::Iterator::hasNext() const { + if( ddl_nullptr == m_current ) { + return false; + } + return ( ddl_nullptr != m_current->getNext() ); +} + +Value *Value::Iterator::getNext() { + if( !hasNext() ) { + return ddl_nullptr; + } + + Value *v( m_current->getNext() ); + m_current = v; + + return v; +} + +const Value::Iterator Value::Iterator::operator++( int ) { + if( ddl_nullptr == m_current ) { + return end; + } + + m_current = m_current->getNext(); + Iterator inst( m_current ); + + return inst; +} + +Value::Iterator &Value::Iterator::operator++( ) { + if( ddl_nullptr == m_current ) { + return end; + } + + m_current = m_current->getNext(); + + return *this; +} + +bool Value::Iterator::operator == ( const Iterator &rhs ) const { + return ( m_current == rhs.m_current ); +} + +Value *Value::Iterator::operator->( ) const { + if(ddl_nullptr == m_current ) { + return ddl_nullptr; + } + return m_current; +} + +Value::Value( ValueType type ) +: m_type( type ) +, m_size( 0 ) +, m_data( ddl_nullptr ) +, m_next( ddl_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 ( *m_data == 1 ); +} + +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 ); + int16 i; + ::memcpy( &i, m_data, m_size ); + return i; +} + +void Value::setInt32( int32 value ) { + assert( ddl_int32 == m_type ); + ::memcpy( m_data, &value, m_size ); +} + +int32 Value::getInt32() { + assert( ddl_int32 == m_type ); + int32 i; + ::memcpy( &i, m_data, m_size ); + return i; +} + +void Value::setInt64( int64 value ) { + assert( ddl_int64 == m_type ); + ::memcpy( m_data, &value, m_size ); +} + +int64 Value::getInt64() { + assert( ddl_int64 == m_type ); + int64 i; + ::memcpy( &i, m_data, m_size ); + return i; +} + +void Value::setUnsignedInt8( uint8 value ) { + assert( ddl_unsigned_int8 == m_type ); + ::memcpy( m_data, &value, m_size ); +} + +uint8 Value::getUnsignedInt8() const { + assert( ddl_unsigned_int8 == m_type ); + uint8 i; + ::memcpy( &i, m_data, m_size ); + return i; +} + +void Value::setUnsignedInt16( uint16 value ) { + assert( ddl_unsigned_int16 == m_type ); + ::memcpy( m_data, &value, m_size ); +} + +uint16 Value::getUnsignedInt16() const { + assert( ddl_unsigned_int16 == m_type ); + uint16 i; + ::memcpy( &i, m_data, m_size ); + return i; +} + +void Value::setUnsignedInt32( uint32 value ) { + assert( ddl_unsigned_int32 == m_type ); + ::memcpy( m_data, &value, m_size ); +} + +uint32 Value::getUnsignedInt32() const { + assert( ddl_unsigned_int32 == m_type ); + uint32 i; + ::memcpy( &i, m_data, m_size ); + return i; +} + +void Value::setUnsignedInt64( uint64 value ) { + assert( ddl_unsigned_int64 == m_type ); + ::memcpy( m_data, &value, m_size ); +} + +uint64 Value::getUnsignedInt64() const { + assert( ddl_unsigned_int64 == m_type ); + uint64 i; + ::memcpy( &i, m_data, m_size ); + return i; +} + +void Value::setFloat( float value ) { + assert( ddl_float == m_type ); + ::memcpy( m_data, &value, m_size ); +} + +float Value::getFloat() const { + if( m_type == ddl_float ) { + float v; + ::memcpy( &v, m_data, m_size ); + return ( float ) v; + } else { + float tmp; + ::memcpy( &tmp, m_data, 4 ); + return ( float ) tmp; + } +} + +void Value::setDouble( double value ) { + assert( ddl_double == m_type ); + ::memcpy( m_data, &value, m_size ); +} + +double Value::getDouble() const { + if ( m_type == ddl_double ) { + double v; + ::memcpy( &v, m_data, m_size ); + return ( float ) v; + } + else { + double tmp; + ::memcpy( &tmp, m_data, 4 ); + return ( double ) tmp; + } +} + +void Value::setString( const std::string &str ) { + assert( ddl_string == m_type ); + ::memcpy( m_data, str.c_str(), str.size() ); + m_data[ str.size() ] = '\0'; +} + +const char *Value::getString() const { + assert( ddl_string == m_type ); + return (const char*) m_data; +} + +void Value::setRef( Reference *ref ) { + assert( ddl_ref == m_type ); + + if ( ddl_nullptr != ref ) { + const size_t sizeInBytes( ref->sizeInBytes() ); + if ( sizeInBytes > 0 ) { + if ( ddl_nullptr != m_data ) { + delete [] m_data; + } + + m_data = new unsigned char[ sizeof( Reference ) ]; + Reference *myRef = ( Reference * ) m_data; + myRef->m_numRefs = ref->m_numRefs; + myRef->m_referencedName = new Name *[ myRef->m_numRefs ]; + for ( size_t i = 0; i < myRef->m_numRefs; i++ ) { + myRef->m_referencedName[ i ] = new Name( ref->m_referencedName[ i ]->m_type, ref->m_referencedName[ i ]->m_id ); + } + } + } +} + +Reference *Value::getRef() const { + assert( ddl_ref == m_type ); + + return (Reference*) m_data; +} + +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 << getString() << 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; +} + +size_t Value::size(){ + size_t result=1; + Value *n=m_next; + while( n!=ddl_nullptr) { + result++; + n=n->m_next; + } + return result; +} + +Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) { + if( type == Value::ddl_none || Value::ddl_types_max == type ) { + return ddl_nullptr; + } + + Value *data = new Value( type ); + data->m_type = type; + switch( type ) { + case Value::ddl_bool: + data->m_size = sizeof( bool ); + break; + case Value::ddl_int8: + data->m_size = sizeof( int8 ); + break; + case Value::ddl_int16: + data->m_size = sizeof( int16 ); + break; + case Value::ddl_int32: + data->m_size = sizeof( int32 ); + break; + case Value::ddl_int64: + data->m_size = sizeof( int64 ); + break; + case Value::ddl_unsigned_int8: + data->m_size = sizeof( uint8 ); + break; + case Value::ddl_unsigned_int16: + data->m_size = sizeof( uint16 ); + break; + case Value::ddl_unsigned_int32: + data->m_size = sizeof( uint32 ); + break; + case Value::ddl_unsigned_int64: + data->m_size = sizeof( uint64 ); + 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 ) { + size_t len1( len ); + if( Value::ddl_string == type ) { + len1++; + } + data->m_size *= len1; + data->m_data = new unsigned char[ data->m_size ]; + } + + return data; +} + +void ValueAllocator::releasePrimData( Value **data ) { + if( !data ) { + return; + } + + delete *data; + *data = ddl_nullptr; +} + +END_ODDLPARSER_NS |