bool CModelData::readParamSet()

in cli/mparser.cpp [272:422]


bool CModelData::readParamSet( wstring& line )
{
    const wstring STD_MSG = L"Submodel definition is incorrect: " + line;

    wstringstream ist( line );

    // it's always in a form of { paramName1 @ N, paramName2 @ N, ... } @ N but "@ N" is optional

    wstring s;
    ist >> s;

    wstring::iterator next = line.begin();

    // {
    wstring::iterator begin = findFirstNonWhitespace( next, line.end() );
    if( begin == line.end() || *begin != SET_BEGIN )
    {
        PrintMessage( InputDataError, STD_MSG.data() );
        return( false );
    }
    ++begin;

    // find }
    wstring::iterator end;
    end = find( begin, line.end(), SET_END );
    if ( end == line.end() )
    {
        PrintMessage( InputDataError, STD_MSG.data() );
        return( false );
    }

    // params in the middle
    wstring setp;
    setp.assign( begin, end );
    setp = trim( setp );
    if ( setp.empty() )
    {
        PrintMessage( InputDataError, STD_MSG.data() );
        return( false );
    }

    //
    // Two attempts to resolve submodel names:
    // 1. Use a comma as a separator
    // 2. If 1 fails to produce matching names, use ModelData.ValuesDelim as a separator
    //

    // first figure out whether "," or a delimiter specified by /d option applies
    wstrings setParams;
    
    split( setp, SET_SEP, setParams );
    transform( setParams.begin(), setParams.end(), setParams.begin(), trim );

    wstrings unmatched;
    getUnmatchedParameterNames( setParams, unmatched );

    if( !unmatched.empty() )
    {
        setParams.clear();
        unmatched.clear();
        split( setp, ValuesDelim, setParams );
        transform( setParams.begin(), setParams.end(), setParams.begin(), trim );

        getUnmatchedParameterNames( setParams, unmatched );
        if( !unmatched.empty() )
        {
            PrintMessage( InputDataWarning, L"Submodel defintion", trim( line ).data(), L"contains unknown parameter. Skipping..." );
            return( true ); // just a warning so don't exit
        }
    }

    // remove duplicates
    sort( setParams.begin(), setParams.end(), stringCaseInsensitiveLess );
    wstrings::iterator newEnd = unique( setParams.begin(), setParams.end(), stringCaseInsensitiveEquals );
    if( setParams.end() != newEnd )
    {
        PrintMessage( InputDataWarning, L"Submodel defintion", trim( line ).data(), L"contains duplicate parameters. Removing duplicates..." );
        setParams.erase( newEnd, setParams.end() );
    }

    CModelSubmodel submodel;

    // match to names, set up the structure
    for( auto & cparam : setParams )
    {
        bool found = false;
        unsigned int index = 0;
        for( auto & param : Parameters )
        {
            if ( 0 == stringCompare( cparam, param.Name, CaseSensitive ))
            {
                found = true;
                break;
            }
            ++index;
        }
        // at this point we should always match the name
        assert( found );

        submodel.Parameters.push_back( index );
    }

    // @
    ++end;
    wstring::iterator at = findFirstNonWhitespace( end, line.end() );
    
    // anything other than @, quit
    if ( at != line.end() && *at != SET_ORDER )
    {
        PrintMessage( InputDataError, STD_MSG.data() );
        return( false );
    }

    if (  at == line.end() )
    {
        // if this is the end then order will be assigned later
        NOOP
    }
    else
    {
        ++at;

        // number
        wstring numberText;
        numberText.assign( at, line.end() );

        double number;
        bool ret = stringToNumber( numberText, number );
        
        int order = 0;
        if( ret )
        {
            order = static_cast<int> (number);
            if( order <= 0 )
            {
                order = 0;
                ret = false;
            }
        }
        if ( !ret )
        {
            PrintMessage( InputDataError, STD_MSG.data() );
            return( false );
        }

        submodel.Order = order;
    }

    Submodels.push_back( submodel );
    return ( true );
}