std::vector<std::string> DebuggerVisitor::perform(Schema* s) { std::vector<std::string> buf; BOOST_ASSERT(0 != s); buf.push_back("\tDBS: " + s->toString()); SequenceMap sequences = s->sequences(); for (SequenceMapConstIterator i = sequences.begin(); i != sequences.end(); ++i) { std::vector<std::string> tmp = i->second->visit(this); buf.insert(buf.end(), tmp.begin(), tmp.end()); } TableMap tables = s->tables(); for(TableMapConstIterator i = tables.begin(); i != tables.end(); ++i) { std::vector<std::string> tmp = i->second->visit(this); buf.insert(buf.end(), tmp.begin(), tmp.end()); } return buf; }
void IECore::findSequences( const std::vector< std::string > &names, std::vector< FileSequencePtr > &sequences, size_t minSequenceSize ) { sequences.clear(); /// this matches names of the form $prefix$frameNumber$suffix /// placing each of those in a group of the resulting match. /// both $prefix and $suffix may be the empty string and $frameNumber /// may be preceded by a minus sign. /// It also matches file extensions with 3 or 4 characters that contain numbers (for example: CR2, MP3 ) boost::regex matchExpression( std::string( "^([^#]*?)(-?[0-9]+)([^0-9#]*|[^0-9#]*\\.[a-zA-Z]{2,3}[0-9])$" ) ); /// build a mapping from ($prefix, $suffix) to a list of $frameNumbers typedef std::vector< std::string > Frames; typedef std::map< std::pair< std::string, std::string >, Frames > SequenceMap; SequenceMap sequenceMap; for ( std::vector< std::string >::const_iterator it = names.begin(); it != names.end(); ++it ) { boost::smatch matches; if ( boost::regex_match( *it, matches, matchExpression ) ) { sequenceMap[ SequenceMap::key_type( std::string( matches[1].first, matches[1].second ), std::string( matches[3].first, matches[3].second ) ) ].push_back( std::string( matches[2].first, matches[2].second ) ); } } for ( SequenceMap::const_iterator it = sequenceMap.begin(); it != sequenceMap.end(); ++it ) { const SequenceMap::key_type &fixes = it->first; const Frames &frames = it->second; // todo: could be more efficient by writing a custom comparison function that uses indexes // into the const Frames vector rather than duplicating the strings and sorting them directly Frames sortedFrames = frames; std::sort( sortedFrames.begin(), sortedFrames.end() ); /// in diabolical cases the elements of frames may not all have the same padding /// so we'll sort them out into padded and unpadded frame sequences here, by creating /// a map of padding->list of frames. unpadded things will be considered to have a padding /// of 1. typedef std::vector< FrameList::Frame > NumericFrames; typedef std::map< unsigned int, NumericFrames > PaddingToFramesMap; PaddingToFramesMap paddingToFrames; for ( Frames::const_iterator fIt = sortedFrames.begin(); fIt != sortedFrames.end(); ++fIt ) { std::string frame = *fIt; int sign = 1; assert( frame.size() ); if ( *frame.begin() == '-' ) { frame = frame.substr( 1, frame.size() - 1 ); sign = -1; } if ( *frame.begin() == '0' || paddingToFrames.find( frame.size() ) != paddingToFrames.end() ) { paddingToFrames[ frame.size() ].push_back( sign * boost::lexical_cast<FrameList::Frame>( frame ) ); } else { paddingToFrames[ 1 ].push_back( sign * boost::lexical_cast<FrameList::Frame>( frame ) ); } } for ( PaddingToFramesMap::iterator pIt = paddingToFrames.begin(); pIt != paddingToFrames.end(); ++pIt ) { const PaddingToFramesMap::key_type &padding = pIt->first; NumericFrames &numericFrames = pIt->second; std::sort( numericFrames.begin(), numericFrames.end() ); FrameListPtr frameList = frameListFromList( numericFrames ); std::vector< FrameList::Frame > expandedFrameList; frameList->asList( expandedFrameList ); /// remove any sequences with less than the given minimum. if ( expandedFrameList.size() >= minSequenceSize ) { std::string frameTemplate; for ( PaddingToFramesMap::key_type i = 0; i < padding; i++ ) { frameTemplate += "#"; } sequences.push_back( new FileSequence( fixes.first + frameTemplate + fixes.second, frameList ) ); } } } }