diff options
| author | Marijn Tamis <[email protected]> | 2018-05-03 18:22:48 +0200 |
|---|---|---|
| committer | Marijn Tamis <[email protected]> | 2018-05-03 18:22:48 +0200 |
| commit | ca32c59a58d37c1822e185a2d5f3d0d3e8943593 (patch) | |
| tree | b06b9eec03f34344ef8fc31aa147b2714d3962ee /NvCloth/samples/external/assimp-4.1.0/contrib/openddlparser/code/OpenDDLParser.cpp | |
| parent | Forced rename of platform folders in cmake dir. Git didn't pick this up before. (diff) | |
| download | nvcloth-ca32c59a58d37c1822e185a2d5f3d0d3e8943593.tar.xz nvcloth-ca32c59a58d37c1822e185a2d5f3d0d3e8943593.zip | |
NvCloth 1.1.4 Release. (24070740)
Diffstat (limited to 'NvCloth/samples/external/assimp-4.1.0/contrib/openddlparser/code/OpenDDLParser.cpp')
| -rw-r--r-- | NvCloth/samples/external/assimp-4.1.0/contrib/openddlparser/code/OpenDDLParser.cpp | 1025 |
1 files changed, 1025 insertions, 0 deletions
diff --git a/NvCloth/samples/external/assimp-4.1.0/contrib/openddlparser/code/OpenDDLParser.cpp b/NvCloth/samples/external/assimp-4.1.0/contrib/openddlparser/code/OpenDDLParser.cpp new file mode 100644 index 0000000..caa2813 --- /dev/null +++ b/NvCloth/samples/external/assimp-4.1.0/contrib/openddlparser/code/OpenDDLParser.cpp @@ -0,0 +1,1025 @@ +/*----------------------------------------------------------------------------------------------- +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 <memory> +#include <math.h> + +#ifdef _WIN32 +# include <windows.h> +#endif // _WIN32 + + +BEGIN_ODDLPARSER_NS + +static const char *Version = "0.4.0"; + +namespace Grammar { + static const char *OpenBracketToken = "{"; + static const char *CloseBracketToken = "}"; + static const char *OpenPropertyToken = "("; + static const char *ClosePropertyToken = ")"; + static const char *OpenArrayToken = "["; + static const char *CloseArrayToken = "]"; + static const char *BoolTrue = "true"; + static const char *BoolFalse = "false"; + static const char *CommaSeparator = ","; + + static const char *PrimitiveTypeToken[ 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 ) { + delete m_context; + m_context=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; + } + delete id; + + Name *name_(ddl_nullptr); + in = OpenDDLParser::parseName(in, end, &name_); + std::unique_ptr<Name> name(name_); + if( ddl_nullptr != name && ddl_nullptr != node ) { + const std::string nodeName( name->m_id->m_buffer ); + node->setName( nodeName ); + } + + + std::unique_ptr<Property> first; + in = lookForNextToken(in, end); + if (*in == Grammar::OpenPropertyToken[0]) { + in++; + std::unique_ptr<Property> prop, prev; + while (*in != Grammar::ClosePropertyToken[0] && in != end) { + Property *prop_(ddl_nullptr); + in = OpenDDLParser::parseProperty(in, end, &prop_); + prop.reset(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 = std::move(prop); + } + if (ddl_nullptr != prev) { + prev->m_next = prop.release(); + } + prev = std::move(prop); + } + } + ++in; + } + + // set the properties + if (first && ddl_nullptr != node) { + node->setProperties(first.release()); + } + } + + 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 == *Grammar::OpenBracketToken) { + // loop over all children ( data and nodes ) + do { + in = parseStructureBody( in, end, error ); + if(in == ddl_nullptr){ + return ddl_nullptr; + } + } while ( *in != *Grammar::CloseBracketToken); + ++in; + } else { + ++in; + logInvalidTokenError( in, std::string( Grammar::OpenBracketToken ), m_logCallback ); + 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 (isCommentOpenTag(c, end)) { + ++readIdx; + while (!isCommentCloseTag(&buffer[readIdx], end)) { + ++readIdx; + } + ++readIdx; + ++readIdx; + } else if( !isComment<char>( c, end ) && !isNewLine( *c ) ) { + newBuffer.push_back( buffer[ readIdx ] ); + } else { + if( isComment<char>( c, end ) ) { + ++readIdx; + // skip the comment and the rest of the line + while( !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 ); + *id = new Text( start, len ); + + 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 = static_cast<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; + } + } + } else { + delete id; + } + } + + return in; +} + +char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type, Value **data, + size_t &numValues, Reference **refs, size_t &numRefs ) { + *data = 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 |