1 /*========================================================================= 2 3 Program: GDCM (Grassroots DICOM). A DICOM library 4 5 Copyright (c) 2006-2011 Mathieu Malaterre 6 All rights reserved. 7 See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. 8 9 This software is distributed WITHOUT ANY WARRANTY; without even 10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 11 PURPOSE. See the above copyright notice for more information. 12 13 =========================================================================*/ 14 #include "gdcmFilenameGenerator.h" 15 #include "gdcmTrace.h" 16 17 #include <cstring> // strchr 18 #include <stdio.h> // snprintf 19 #ifdef _WIN32 20 #define snprintf _snprintf 21 #endif 22 23 namespace gdcm 24 { 25 26 //----------------------------------------------------------------------------- GetNumberOfFilenames() const27FilenameGenerator::SizeType FilenameGenerator::GetNumberOfFilenames() const 28 { 29 return Filenames.size(); 30 } 31 32 //----------------------------------------------------------------------------- SetNumberOfFilenames(SizeType nfiles)33void FilenameGenerator::SetNumberOfFilenames(SizeType nfiles) 34 { 35 Filenames.resize( nfiles ); 36 } 37 38 //----------------------------------------------------------------------------- GetFilename(SizeType n) const39const char * FilenameGenerator::GetFilename(SizeType n) const 40 { 41 if( n < Filenames.size() ) 42 return Filenames[n].c_str(); 43 return nullptr; 44 } 45 46 //----------------------------------------------------------------------------- Generate()47bool FilenameGenerator::Generate() 48 { 49 if( Pattern.empty() && Prefix.empty() ) 50 { 51 return false; 52 } 53 else if( Pattern.empty() && !Prefix.empty() ) // no pattern but a prefix 54 { 55 const SizeType numfiles = Filenames.size(); 56 for( SizeType i = 0; i < numfiles; ++i) 57 { 58 std::ostringstream os; 59 os << Prefix; 60 os << i; 61 Filenames[i] = os.str(); 62 } 63 return true; 64 } 65 else if( !Pattern.empty() ) 66 { 67 std::string::size_type pat_len = Pattern.size(); 68 const SizeType padding = 10; // FIXME is this large enough for all cases ? 69 const SizeType internal_len = pat_len + padding; 70 const SizeType numfiles = Filenames.size(); 71 if( numfiles == 0 ) 72 { 73 gdcmDebugMacro( "Need to specify the number of files" ); 74 // I am pretty sure this is an error: 75 return false; 76 } 77 const char *pattern = Pattern.c_str(); 78 int num_percent = 0; 79 while( (pattern = strchr( pattern, '%')) ) 80 { 81 ++pattern; 82 ++num_percent; 83 } 84 if ( num_percent != 1 ) 85 { 86 // Bug: what if someone wants to output file such as %%%02 ... oh well 87 gdcmDebugMacro( "No more than one % in string formating please" ); 88 return false; 89 } 90 bool success = true; 91 char *internal = new char[internal_len]; 92 for( SizeType i = 0; i < numfiles && success; ++i) 93 { 94 int res = snprintf( internal, internal_len, Pattern.c_str(), i ); 95 assert( res >= 0 ); 96 success = (SizeType)res < internal_len; 97 if( Pattern.empty() ) 98 { 99 Filenames[i] = internal; 100 } 101 else 102 { 103 Filenames[i] = Prefix + internal; 104 } 105 //assert( Filenames[i].size() == res ); // upon success only 106 } 107 delete[] internal; 108 if( !success ) 109 { 110 Filenames.clear(); 111 // invalidate size too ?? 112 } 113 return success; 114 } 115 return false; 116 } 117 118 } // namespace gdcm 119