in api/model.cpp [1142:1217]
void Model::processExclusions( ComboCollection& vecCombo )
{
// Sort every parameter's collection of combinations to prepare for set intersection
for( vector<Parameter*>::iterator ip = m_parameters.begin(); ip != m_parameters.end(); ++ip )
{
( *ip )->SortCombinations();
}
for( ExclusionCollection::iterator iexcl = m_exclusions.begin(); iexcl != m_exclusions.end(); ++iexcl )
{
// paranoia; shouldn't happen
assert( !iexcl->empty() );
if( iexcl->empty() ) continue;
// form the intersection of the combinations associated with each of the
// parameters that make up this exclusion
ComboCollection intersection;
Exclusion::iterator iexclterm = iexcl->begin();
Parameter* sourceParam = iexclterm->first;
ComboCollection::const_iterator posCandidate = sourceParam->GetCombinationBegin();
while( true )
{
// We're going around and around...
if( iexcl->end() == ++iexclterm )
{
iexclterm = iexcl->begin();
}
if( iexclterm->first == sourceParam )
{
intersection.push_back( *posCandidate );
if( ++posCandidate == sourceParam->GetCombinationEnd() ) break;
}
// find next >= in this param
ComboCollection::const_iterator posLB = lower_bound( iexclterm->first->GetCombinationBegin(),
iexclterm->first->GetCombinationEnd(),
*posCandidate, CombinationPtrSortPred() );
if( iexclterm->first->GetCombinationEnd() == posLB ) break;
// if >, reset candidate and source
if( *posLB != *posCandidate )
{
posCandidate = posLB;
sourceParam = iexclterm->first;
}
}
// If the result is empty, make a new combination from the exclusion,
// mark all of its members satisfied, and make sure all the parameters in the new
// combination still have sorted combination collections.
if( intersection.empty() )
{
Combination *pNewCombo = new Combination( this );
int size = 1;
for( Exclusion::iterator ix = iexcl->begin(); ix != iexcl->end(); ++ix )
{
pNewCombo->PushParameter( ( ix->first ) );
ix->first->LinkCombination( pNewCombo );
ix->first->SortCombinations();
size *= ix->first->GetValueCount();
}
// Set size of combination's bit vector
pNewCombo->SetMapSize( size, COVERED );
vecCombo.push_back( pNewCombo );
intersection.push_back( pNewCombo );
}
for( ComboCollection::iterator ic = intersection.begin(); ic != intersection.end(); ++ic )
{
// all exclusions must be applied to the combo and not just the current one
for( ExclusionCollection::iterator ie = m_exclusions.begin(); ie != m_exclusions.end(); ++ie )
{
( *ic )->ApplyExclusion( const_cast<Exclusion&> ( *ie ) );
}
}
}
}