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() const27 FilenameGenerator::SizeType FilenameGenerator::GetNumberOfFilenames() const
28 {
29   return Filenames.size();
30 }
31 
32 //-----------------------------------------------------------------------------
SetNumberOfFilenames(SizeType nfiles)33 void FilenameGenerator::SetNumberOfFilenames(SizeType nfiles)
34 {
35   Filenames.resize( nfiles );
36 }
37 
38 //-----------------------------------------------------------------------------
GetFilename(SizeType n) const39 const 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()47 bool 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