bool FileSequenceParameter::valueValid( const Object *value, std::string *reason ) const { /// we can't call PathParameter::valueValid() because that would do existence checking on /// our path specifier with the # characters in it, and that would yield the wrong results /// so we call StringParameter.valueValid and do the rest ourselves. if ( !StringParameter::valueValid( value ) ) { return false; } const StringData *stringDataValue = assertedStaticCast<const StringData>( value ); const std::string &stringValue = stringDataValue->readable(); if ( allowEmptyString() && !stringValue.size() ) { return true; } if ( ! boost::regex_match( stringValue, FileSequence::fileNameValidator() ) ) { if ( reason ) { *reason = "Value must contain one sequence of at least one # character to specify frame number."; } return false; } FileSequencePtr fileSequence = nullptr; try { fileSequence = new FileSequence( stringValue ); } catch ( Exception &e ) { if ( reason ) { *reason = "Not a valid file sequence specification"; } return false; } assert( fileSequence ); if ( m_extensions.size() ) { std::string ext = boost::filesystem::extension( boost::filesystem::path( fileSequence->getFileName() ) ); if ( ext.size() && ext[0] == '.' ) { ext = ext.substr( 1, ext.size() - 1 ); } if ( std::find( m_extensions.begin(), m_extensions.end(), ext ) == m_extensions.end() ) { if ( reason ) { *reason = "File sequence extension not valid"; } return false; } } if ( mustExist() ) { FileSequencePtr s = nullptr; ls( fileSequence->getFileName(), s, m_minSequenceSize ); if ( !s ) { if ( reason ) { *reason = "File sequence does not exist"; } return false; } } else if ( mustNotExist() ) { FileSequencePtr s = nullptr; ls( fileSequence->getFileName(), s, m_minSequenceSize ); if ( s ) { if ( reason ) { *reason = "File sequence already exists"; } return false; } } return true; }
void IECore::ls( const std::string &sequencePath, FileSequencePtr &sequence, size_t minSequenceSize ) { sequence = 0; boost::smatch matches; bool m = boost::regex_match( sequencePath, matches, FileSequence::fileNameValidator() ); if ( !m ) { return; } const std::string paddingStr( matches[2].first, matches[2].second ); const unsigned padding = paddingStr.size(); std::vector< std::string > files; boost::filesystem::path dir = boost::filesystem::path( sequencePath ).branch_path(); std::string baseSequencePath = boost::filesystem::path( sequencePath ).filename().string(); const std::string::size_type first = baseSequencePath.find_first_of( '#' ); assert( first != std::string::npos ); const std::string prefix = baseSequencePath.substr( 0, first ); const std::string::size_type last = baseSequencePath.find_last_of( '#' ); assert( last != std::string::npos ); const std::string suffix = baseSequencePath.substr( last + 1, baseSequencePath.size() - last - 1 ); boost::filesystem::path dirToCheck( dir ); if ( dirToCheck.string() == "" ) { dirToCheck = "."; } boost::filesystem::directory_iterator end; for ( boost::filesystem::directory_iterator it( dirToCheck ); it != end; ++it ) { const std::string fileName = it->path().filename().string(); if ( fileName.size() >= std::min( prefix.size(), suffix.size() ) && fileName.substr( 0, prefix.size() ) == prefix && fileName.substr( fileName.size() - suffix.size(), suffix.size() ) == suffix ) { files.push_back( ( dir / boost::filesystem::path( fileName ) ).string() ); } } std::vector< FileSequencePtr > sequences; findSequences( files, sequences, minSequenceSize ); for ( std::vector< FileSequencePtr >::iterator it = sequences.begin(); it != sequences.end() ; ++it ) { if ( (*it)->getPadding() == padding ) { sequence = *it; return; } // Also accept frame ranges with number of digits greater than the padding. if ( (*it)->getPadding() == 1 && (*it)->getFrameList()->typeId() == FrameRangeTypeId ) { FrameRangePtr fr = staticPointerCast< FrameRange >( (*it)->getFrameList() ); FrameList::Frame startFrame, endFrame; startFrame = fr->getStart(); endFrame = fr->getEnd(); // if goes through 0 then this is a no. if ( !(startFrame < 0 && endFrame > 0) ) { unsigned int startDigits = 1; if ( startFrame > 0 ) startDigits = static_cast<unsigned int>(floor(log10( static_cast<double>(abs(startFrame)) ))) + 1; if ( startDigits >= padding ) { sequence = *it; sequence->setPadding( padding ); return; } } } } }
void IECore::ls( const std::string &sequencePath, FileSequencePtr &sequence, size_t minSequenceSize ) { sequence = nullptr; boost::smatch matches; bool m = boost::regex_match( sequencePath, matches, FileSequence::fileNameValidator() ); if ( !m ) { return; } const std::string paddingStr( matches[2].first, matches[2].second ); const unsigned padding = paddingStr.size(); std::vector< std::string > files; boost::filesystem::path dir = boost::filesystem::path( sequencePath ).parent_path(); std::string baseSequencePath = boost::filesystem::path( sequencePath ).PATH_TO_STRING; const std::string::size_type first = baseSequencePath.find_first_of( '#' ); assert( first != std::string::npos ); const std::string prefix = baseSequencePath.substr( 0, first ); const std::string::size_type last = baseSequencePath.find_last_of( '#' ); assert( last != std::string::npos ); const std::string suffix = baseSequencePath.substr( last + 1, baseSequencePath.size() - last - 1 ); boost::filesystem::path dirToCheck( dir ); if ( dirToCheck.string() == "" ) { dirToCheck = "."; } boost::filesystem::directory_iterator end; for ( boost::filesystem::directory_iterator it( dirToCheck ); it != end; ++it ) { const std::string fileName = it->path().PATH_TO_STRING; if ( fileName.size() >= std::min( prefix.size(), suffix.size() ) && fileName.substr( 0, prefix.size() ) == prefix && fileName.substr( fileName.size() - suffix.size(), suffix.size() ) == suffix ) { files.push_back( ( dir / boost::filesystem::path( fileName ) ).string() ); } } std::vector< FileSequencePtr > sequences; findSequences( files, sequences, minSequenceSize ); for ( std::vector< FileSequencePtr >::iterator it = sequences.begin(); it != sequences.end() ; ++it ) { if ( (*it)->getPadding() == padding ) { sequence = *it; return; } // Also accept frame ranges with number of digits greater than the padding. if ( (*it)->getPadding() == 1 ) { FrameList::Frame startFrame, endFrame; if( FrameRange *fr = runTimeCast<FrameRange>( (*it)->getFrameList() ) ) { // Can do a quick validation if the range is a FrameRange, by looking at the start and end only startFrame = fr->getStart(); endFrame = fr->getEnd(); } else { // Otherwise, have to get the full list std::vector<FrameList::Frame> frames; (*it)->getFrameList()->asList(frames); // I know that there will be at least one frame, since the file sequence was found startFrame = frames[ 0 ]; endFrame = frames[ 0 ]; for ( unsigned i=0; i < frames.size(); i++ ) { if ( frames[ i ] < startFrame ) { startFrame = frames[ i ]; } else if ( frames[ i ] > endFrame ) { endFrame = frames[ i ]; } } } // if goes through 0 then this is a no. if ( !(startFrame < 0 && endFrame > 0) ) { unsigned int startDigits = 1; if ( startFrame > 0 ) startDigits = static_cast<unsigned int>(floor(log10( static_cast<double>(std::abs(startFrame)) ))) + 1; if ( startDigits >= padding ) { sequence = *it; sequence->setPadding( padding ); return; } } } } }