//------------------------------------------------------------------------------ void ClassDefinition::bindPropertyImpl( const char * name, const ObjectHandle & pBase, PropertyAccessor & o_PropertyAccessor ) const { if (!*name) { // empty name causes noop return; } // find property operator auto propOperator = name; while (true) { if( !*propOperator || *propOperator == INDEX_OPEN || *propOperator == DOT_OPERATOR ) { break; } propOperator += 1; } auto propName = name; auto propLength = propOperator - propName; auto baseProp = findProperty( propName, propLength ); if (baseProp == nullptr) { // error: property `propName` is not found o_PropertyAccessor.setBaseProperty( nullptr ); return; } o_PropertyAccessor.setObject( pBase ); o_PropertyAccessor.setBaseProperty( baseProp ); assert( strncmp( propName, o_PropertyAccessor.getName(), propLength ) == 0 ); if (!*propOperator) { // no operator, so that's it return; } Variant propVal = o_PropertyAccessor.getValue(); if (*propOperator == INDEX_OPEN) { auto wholeIndex = propOperator; // read "multidimensional" indices without recursive bind (optimization) while (true) { Collection collection; if (!propVal.tryCast( collection )) { // error: index operator is applicable to collections only o_PropertyAccessor.setBaseProperty( nullptr ); return; } // determine key type (heterogeneous keys are not supported yet) const auto begin = collection.begin(); const auto end = collection.end(); if (begin == end) { // error: can't index empty collection o_PropertyAccessor.setBaseProperty( nullptr ); return; } // read key Variant key( begin.key().type() ); { propOperator += 1; // skip INDEX_OPEN FixedMemoryStream dataStream( propOperator ); TextStream stream( dataStream ); stream >> key >> match( INDEX_CLOSE ); if (stream.fail()) { // error: either key can't be read, or it isn't followed by INDEX_CLOSE o_PropertyAccessor.setBaseProperty( nullptr ); return; } // skip key and closing bracket propOperator += stream.seek( 0, std::ios_base::cur ); } auto it = collection.find( key ); // If (it == end), still return a valid property accessor to end, // rather than an invalid property accessor. if (!*propOperator || (it == end)) { // name parsing is completed auto baseProp = std::make_shared< CollectionElementHolder >( collection, it, collection.valueType(), wholeIndex ); // o_PropertyAccessor.setObject(); - keep current base o_PropertyAccessor.setBaseProperty( baseProp ); return; } propVal = it.value(); if (*propOperator == INDEX_OPEN) { continue; } // parse next operator break; } }