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; }
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; }
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::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::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::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::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; }
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; }
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::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::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::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::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; }
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; }