<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkArchetypeSeriesFileNames.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef _itkArchetypeSeriesFileNames_h
#define _itkArchetypeSeriesFileNames_h

#ifdef _MSC_VER
#pragma warning ( disable : 4786 )
#endif


#include "itkArchetypeSeriesFileNames.h"
#include "itkRegularExpressionSeriesFileNames.h"
#include <itksys/SystemTools.hxx>
#include <stdio.h>
#include <algorithm>

namespace itk
{

ArchetypeSeriesFileNames
::ArchetypeSeriesFileNames() : m_Archetype("")
{
}

void
ArchetypeSeriesFileNames
::SetArchetype( const std::string &archetype )
{
  if (archetype != m_Archetype)
    {
    m_Archetype = archetype;
    this->Modified();
    m_ArchetypeMTime.Modified();
    }
}

ArchetypeSeriesFileNames::VectorSizeType
ArchetypeSeriesFileNames
::GetNumberOfGroupings()
{
  if (m_ScanTime < m_ArchetypeMTime)
    {
    this->Scan();
    }

  return m_Groupings.size();
}


const std::vector<std::string> &
ArchetypeSeriesFileNames
::GetFileNames( VectorSizeType group)
{
  if (m_ScanTime < m_ArchetypeMTime)
    {
    this->Scan();
    }

  if (group < m_Groupings.size())
    {
    m_FileNames = m_Groupings[group];
    }
  else
    {
    m_FileNames.clear();
    }

  return m_FileNames;
}


void
ArchetypeSeriesFileNames
::Scan()
{
  // For each group of contiguous numbers in m_Archetype, create a
  // regular expression that is identical to m_Archetype except that
  // it replaces that group of numbers with the pattern ([0-9]+).
  // Each of these new strings will then be passed into a
  // RegularExpressionSeriesFileNames to generate the list of those
  // files that fit that pattern.

  m_Groupings.clear();

  std::string unixArchetype = m_Archetype;
  itksys::SystemTools::ConvertToUnixSlashes(unixArchetype);

  if (itksys::SystemTools::FileIsDirectory( unixArchetype.c_str() ))
    {
    return;
    }

  // Parse the fileNameName and fileNamePath
  std::string origFileName = itksys::SystemTools::GetFilenameName( unixArchetype.c_str() );
  std::string fileNamePath = itksys::SystemTools::GetFilenamePath( unixArchetype.c_str() );
  std::string pathPrefix;

  // "Clean" the filename by escaping any special characters with backslashes.
  // This allows us to pass in filenames that include these special characters.
  std::string fileName;
  for( unsigned int j = 0; j < origFileName.length(); j++ )
    {
    char oneChar = origFileName[j];
    if( oneChar == '^' ||
        oneChar == '$' ||
        oneChar == '.' ||
        oneChar == '[' ||
        oneChar == ']' ||
        oneChar == '-' ||
        oneChar == '*' ||
        oneChar == '+' ||
        oneChar == '?' ||
        oneChar == '(' ||
        oneChar == ')' )
      {
      fileName += "\\";
      }
    fileName += oneChar;
    }
    
  // If there is no "/" in the name, the directory is not specified.
  // In that case, use the default ".".  This is necessary for the RegularExpressionSeriesFileNames.
  if (fileNamePath == "")
    {
    fileNamePath = ".";
    pathPrefix = "./";
    }
  else
    {
    pathPrefix = "";
    }

  StringVectorType regExpFileNameVector;
  std::string regExpString = "([0-9]+)";
  IntVectorType numGroupStart;
  IntVectorType numGroupLength;
  int sIndex;
  std::string::iterator sit;
  for (sit = fileName.begin(); sit < fileName.end(); sit++)
    {
    // If the element is a number, find its starting index and length.
    if ((*sit) >= '0' && (*sit) <= '9')
      {
      sIndex = sit - fileName.begin();
      numGroupStart.push_back( sIndex );
      
      // Loop to one past the end of the group of numbers.
      while ( sit != fileName.end() && (*sit) >= '0' && (*sit) <= '9' )
        {
        ++sit;
        }
      
      if( sit == fileName.end() )
        {
        break;
        }
        
      numGroupLength.push_back( (sit - fileName.begin()) - sIndex );
      }
    }

  // Create a set of regular expressions, one for each group of
  // numbers in m_FileName. We walk the regular expression groups
  // from right to left since numbers at the end of filenames are more
  // likely to be image numbers.
  // It is also necessary to walk backward so that the numGroupStart
  // indices remain correct since the length of numbers we are replacing may
  // be different from the length of regExpString.
  IntVectorType::reverse_iterator numGroupLengthItr = numGroupLength.rbegin();
  IntVectorType::reverse_iterator numGroupStartItr  = numGroupStart.rbegin();
  while( numGroupLengthItr != numGroupLength.rend() &&
         numGroupStartItr != numGroupStart.rend() )
    {
    std::string regExpFileName = fileName;
    <commit_msg>BUG: Fix contributed by <NAME>. Related to series of filenames      that are terminated in numeric strings.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkArchetypeSeriesFileNames.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef _itkArchetypeSeriesFileNames_h
#define _itkArchetypeSeriesFileNames_h

#ifdef _MSC_VER
#pragma warning ( disable : 4786 )
#endif


#include "itkArchetypeSeriesFileNames.h"
#include "itkRegularExpressionSeriesFileNames.h"
#include <itksys/SystemTools.hxx>
#include <stdio.h>
#include <algorithm>

namespace itk
{

ArchetypeSeriesFileNames
::ArchetypeSeriesFileNames() : m_Archetype("")
{
}

void
ArchetypeSeriesFileNames
::SetArchetype( const std::string &archetype )
{
  if (archetype != m_Archetype)
    {
    m_Archetype = archetype;
    this->Modified();
    m_ArchetypeMTime.Modified();
    }
}

ArchetypeSeriesFileNames::VectorSizeType
ArchetypeSeriesFileNames
::GetNumberOfGroupings()
{
  if (m_ScanTime < m_ArchetypeMTime)
    {
    this->Scan();
    }

  return m_Groupings.size();
}


const std::vector<std::string> &
ArchetypeSeriesFileNames
::GetFileNames( VectorSizeType group)
{
  if (m_ScanTime < m_ArchetypeMTime)
    {
    this->Scan();
    }

  if (group < m_Groupings.size())
    {
    m_FileNames = m_Groupings[group];
    }
  else
    {
    m_FileNames.clear();
    }

  return m_FileNames;
}


void
ArchetypeSeriesFileNames
::Scan()
{
  // For each group of contiguous numbers in m_Archetype, create a
  // regular expression that is identical to m_Archetype except that
  // it replaces that group of numbers with the pattern ([0-9]+).
  // Each of these new strings will then be passed into a
  // RegularExpressionSeriesFileNames to generate the list of those
  // files that fit that pattern.

  m_Groupings.clear();

  std::string unixArchetype = m_Archetype;
  itksys::SystemTools::ConvertToUnixSlashes(unixArchetype);

  if (itksys::SystemTools::FileIsDirectory( unixArchetype.c_str() ))
    {
    return;
    }

  // Parse the fileNameName and fileNamePath
  std::string origFileName = itksys::SystemTools::GetFilenameName( unixArchetype.c_str() );
  std::string fileNamePath = itksys::SystemTools::GetFilenamePath( unixArchetype.c_str() );
  std::string pathPrefix;

  // "Clean" the filename by escaping any special characters with backslashes.
  // This allows us to pass in filenames that include these special characters.
  std::string fileName;
  for( unsigned int j = 0; j < origFileName.length(); j++ )
    {
    char oneChar = origFileName[j];
    if( oneChar == '^' ||
        oneChar == '$' ||
        oneChar == '.' ||
        oneChar == '[' ||
        oneChar == ']' ||
        oneChar == '-' ||
        oneChar == '*' ||
        oneChar == '+' ||
        oneChar == '?' ||
        oneChar == '(' ||
        oneChar == ')' )
      {
      fileName += "\\";
      }
    fileName += oneChar;
    }
    
  // If there is no "/" in the name, the directory is not specified.
  // In that case, use the default ".".  This is necessary for the RegularExpressionSeriesFileNames.
  if (fileNamePath == "")
    {
    fileNamePath = ".";
    pathPrefix = "./";
    }
  else
    {
    pathPrefix = "";
    }

  StringVectorType regExpFileNameVector;
  std::string regExpString = "([0-9]+)";
  IntVectorType numGroupStart;
  IntVectorType numGroupLength;
  int sIndex;
  std::string::iterator sit;
  for (sit = fileName.begin(); sit < fileName.end(); sit++)
    {
    // If the element is a number, find its starting index and length.
    if ((*sit) >= '0' && (*sit) <= '9')
      {
      sIndex = sit - fileName.begin();
      numGroupStart.push_back( sIndex );
      
      // Loop to one past the end of the group of numbers.
      while ( sit != fileName.end() && (*sit) >= '0' && (*sit) <= '9' )
        {
        ++sit;
        }
      
      numGroupLength.push_back( (sit - fileName.begin()) - sIndex );
        
      if( sit == fileName.end() )
        {
        break;
        }
      }
    }

  // Create a set of regular expressions, one for each group of
  // numbers in m_FileName. We walk the regular expression groups
  // from right to left since numbers at the end of filenames are more
  // likely to be image numbers.
  // It is also necessary to walk backward so that the numGroupStart
  // indices remain correct since the length of numbers we are replacing may
  // be different from the length of regExpString.
  IntVectorType::reverse_iterator numGroupLengthItr = numGroupLength.rbegin();
  IntVectorType::reverse_iterator numGroupStartItr  = numGroupStart.rbegin();
  while( numGroupLengthItr != numGroupLength.rend() &&
         numGroupStartItr != numGroupStart.rend() )
    {
    std::string regExpFileName = fileName;
    
{'fraction_non_alphanumeric': 0.1401985111662531, 'fraction_numerical': 0.0024813895781637717, 'mean_word_length': 3.1500990099009902, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4318042', 'n_tokens_mistral': 3240, 'n_tokens_neox': 3159, 'n_words': 879}