]> Creatis software - cpPlugins.git/blob - appli/bash/cpPlugins_CreateInstances.cxx
...
[cpPlugins.git] / appli / bash / cpPlugins_CreateInstances.cxx
1 #include <algorithm>
2 #include <cstring>
3 #include <iostream>
4 #include <iterator>
5 #include <fstream>
6 #include <map>
7 #include <set>
8 #include <sstream>
9 #include <streambuf>
10 #include <string>
11 #include <vector>
12
13 // -------------------------------------------------------------------------
14 typedef std::set< std::string >       TSet;
15 typedef std::map< std::string, TSet > TInstances;
16 typedef std::vector< std::string >    TVector;
17
18 // -------------------------------------------------------------------------
19 TVector Tokenize( const std::string& str, const std::string& delims );
20 TSet Combine( const TSet& X, const TSet& Y );
21 void Replace(
22   std::string& str, const std::string& sub, const std::string& nsub
23   );
24
25 // -------------------------------------------------------------------------
26 int main( int argc, char* argv[] )
27 {
28   if( argc < 5 )
29   {
30     std::cerr
31       << "Usage: " << argv[ 0 ]
32       << " input_definitions dir library_name header_filename"
33       << std::endl;
34     return( 1 );
35
36   } // fi
37   std::string input_definitions_file_name = argv[ 1 ];
38   std::string dir = argv[ 2 ];
39   std::string library_name = argv[ 3 ];
40   std::string head_fname = argv[ 4 ];
41
42   // Load file into a buffer
43   std::ifstream file_stream( input_definitions_file_name.c_str( ) );
44   if( !file_stream )
45   {
46     std::cerr
47       << "Error opening file: \""
48       << input_definitions_file_name << "\""
49       << std::endl;
50     return( 1 );
51
52   } // fi
53   std::string buf;
54   file_stream.seekg( 0, std::ios::end );
55   buf.reserve( file_stream.tellg( ) );
56   file_stream.seekg( 0, std::ios::beg );
57   buf.assign(
58     ( std::istreambuf_iterator< char >( file_stream ) ),
59     std::istreambuf_iterator< char >( )
60     );
61   file_stream.close( );
62   std::istringstream input_str( buf );
63
64   // Process file
65   std::string line;
66   TVector incl, first_incl;
67   TInstances instances;
68   TVector classes;
69   while( std::getline( input_str, line ) )
70   {
71     if( line[ 0 ] == 'f' )
72     {
73       first_incl.push_back( line.substr( line.find_first_not_of( ' ', 1 ) ) );
74     }
75     else if( line[ 0 ] == 'i' )
76     {
77       incl.push_back( line.substr( line.find_first_not_of( ' ', 1 ) ) );
78     }
79     else if( line[ 0 ] == 'c' )
80     {
81       classes.push_back( line.substr( line.find_first_not_of( ' ', 1 ) ) );
82     }
83     else if( line[ 0 ] == 'a' )
84     {
85       TVector tokens = Tokenize( line, "=" );
86
87       // Get argument name
88       TVector arg_tokens = Tokenize( tokens[ 0 ], " " );
89       std::string arg = arg_tokens[ 0 ];
90       unsigned int i = 0;
91       while( arg[ 0 ] != '#' && i < arg_tokens.size( ) )
92         arg = arg_tokens[ ++i ];
93
94       // Get values
95       TVector values_tokens = Tokenize( tokens[ 1 ], ";" );
96       for( auto t = values_tokens.begin( ); t != values_tokens.end( ); ++t )
97       {
98         std::string value = t->substr( t->find_first_not_of( ' ' ) );
99         unsigned int value_len = value.size( );
100         while( value[ value_len - 1 ] == ' ' && value_len > 0 )
101           value_len--;
102         value = value.substr( 0, value_len );
103
104         if( value == "#integers" )
105         {
106           instances[ arg ].insert( "char" );
107           instances[ arg ].insert( "short" );
108           instances[ arg ].insert( "int" );
109           instances[ arg ].insert( "long" );
110           instances[ arg ].insert( "unsigned char" );
111           instances[ arg ].insert( "unsigned short" );
112           instances[ arg ].insert( "unsigned int" );
113           instances[ arg ].insert( "unsigned long" );
114         }
115         else if( value == "#integers_ptr" )
116         {
117           instances[ arg ].insert( "char*" );
118           instances[ arg ].insert( "short*" );
119           instances[ arg ].insert( "int*" );
120           instances[ arg ].insert( "long*" );
121           instances[ arg ].insert( "unsigned char*" );
122           instances[ arg ].insert( "unsigned short*" );
123           instances[ arg ].insert( "unsigned int*" );
124           instances[ arg ].insert( "unsigned long*" );
125         }
126         else if( value == "#floats" )
127         {
128           instances[ arg ].insert( "double" );
129           instances[ arg ].insert( "float" );
130         }
131         else if( value == "#floats_ptr" )
132         {
133           instances[ arg ].insert( "double*" );
134           instances[ arg ].insert( "float*" );
135         }
136         else if( value == "#all_dims" )
137         {
138           instances[ arg ].insert( "1" );
139           instances[ arg ].insert( "2" );
140           instances[ arg ].insert( "3" );
141           instances[ arg ].insert( "4" );
142         }
143         else if( value == "#all_visual_dims" )
144         {
145           instances[ arg ].insert( "2" );
146           instances[ arg ].insert( "3" );
147         }
148         else
149           instances[ arg ].insert( value );
150
151       } // rof
152
153     } // fi
154
155   } // elihw
156
157   // Span all possible types
158   TVector all_real_classes;
159   for( auto clsIt = classes.begin( ); clsIt != classes.end( ); ++clsIt )
160   {
161     // Extract types
162     std::string name = clsIt->substr( clsIt->find_first_not_of( " " ) );
163     std::string tok = name;
164     auto sharpPos = tok.find_first_of( "#" );
165     TInstances li;
166     while( sharpPos != std::string::npos )
167     {
168       tok = tok.substr( sharpPos );
169       auto spacePos = tok.find_first_of( " " );
170       auto arg = tok.substr( 0, spacePos );
171       auto aIt = instances.find( arg );
172       if( aIt != instances.end( ) )
173         li[ arg ] = aIt->second;
174       tok = tok.substr( spacePos );
175       sharpPos = tok.find_first_of( "#" );
176
177     } // eliwh
178     if( li.size( ) > 0 )
179     {
180       // Combine types
181       TSet combs;
182       if( li.size( ) > 1 )
183       {
184         auto iIt = li.begin( );
185         auto jIt = iIt;
186         jIt++;
187         for( ; jIt != li.end( ); ++iIt, ++jIt )
188         {
189           if( iIt == li.begin( ) )
190             combs = Combine( iIt->second, jIt->second );
191           else
192             combs = Combine( combs, jIt->second );
193
194         } // rof
195       }
196       else
197         combs = li.begin( )->second;
198
199       // Write instantiations
200       for( auto combIt = combs.begin( ); combIt != combs.end( ); ++combIt )
201       {
202         char* buffer = new char[ combIt->size( ) + 1 ];
203         std::strcpy( buffer, combIt->c_str( ) );
204         buffer[ combIt->size( ) ] = '\0';
205         char* tok = std::strtok( buffer, "#" );
206         std::map< std::string, std::string > real_instance;
207         for( auto lIt = li.begin( ); lIt != li.end( ); ++lIt )
208         {
209           real_instance[ lIt->first ] = std::string( tok );
210           tok = std::strtok( NULL, "#" );
211
212         } // rof
213         delete buffer;
214
215         std::string real_name = name;
216         auto riIt = real_instance.begin( );
217         for( ; riIt != real_instance.end( ); ++riIt )
218           Replace( real_name, riIt->first, riIt->second );
219         all_real_classes.push_back( real_name );
220
221       } // rof
222     }
223     else
224       all_real_classes.push_back( name );
225
226   } // rof
227
228   // Write files
229   std::ofstream out_str( head_fname.c_str( ) );
230   if( !out_str )
231   {
232     std::cerr << "Error opening file \"" << head_fname << "\"" << std::endl;
233     return( 1 );
234
235   } // fi
236
237   out_str << "#ifndef __" << dir << "__" << library_name << "__H__" << std::endl;
238   out_str << "#define __" << dir << "__" << library_name << "__H__" << std::endl << std::endl;
239   out_str << "#include <" << dir << "/" << library_name << "_Export.h>" << std::endl;
240
241   // First incl
242   for( auto inclIt = first_incl.begin( ); inclIt != first_incl.end( ); ++inclIt )
243     out_str
244       << "#include <" << *inclIt << ">" << std::endl;
245   out_str << std::endl;
246
247   std::string base_name = dir + std::string( "_" ) + library_name;
248   out_str
249     << std::endl
250     << "#ifdef " << base_name << "_EXPORTS" << std::endl
251     << "#  undef  ITK_MANUAL_INSTANTIATION" << std::endl
252     << "#  define " << base_name << "_PREFIX template class " << base_name << "_EXPORT" << std::endl
253     << "#else" << std::endl
254     << "#  define ITK_MANUAL_INSTANTIATION" << std::endl
255     << "#  define " << base_name << "_PREFIX extern template class" << std::endl
256     << "#endif" << std::endl << std::endl;
257
258   // Incl
259   for( auto inclIt = incl.begin( ); inclIt != incl.end( ); ++inclIt )
260     out_str
261       << "#include <" << *inclIt << ">" << std::endl;
262   out_str << std::endl;
263
264   // All classes
265   for( auto clsIt = all_real_classes.begin( ); clsIt != all_real_classes.end( ); ++clsIt )
266     out_str
267       << base_name << "_PREFIX " << *clsIt << ";" << std::endl;
268   out_str << std::endl;
269
270   out_str << "#endif // __" << dir << "__" << library_name << "__H__" << std::endl;
271   out_str << std::endl << "// eof" << std::endl;
272
273   out_str.close( );
274
275   return( 0 );
276 }
277
278 // -------------------------------------------------------------------------
279 TVector Tokenize( const std::string& str, const std::string& delims )
280 {
281   TVector tokens;
282   if( str.size( ) > 0 )
283   {
284     char* buffer = new char[ str.size( ) + 1 ];
285     std::strcpy( buffer, str.c_str( ) );
286     buffer[ str.size( ) ] = '\0';
287     char* it = std::strtok( buffer, delims.c_str( ) );
288     while( it != NULL )
289     {
290       tokens.push_back( std::string( it ) );
291       it = std::strtok( NULL, delims.c_str( ) );
292
293     } // elihw
294     delete buffer;
295
296   } // fi
297   return( tokens );
298 }
299
300 // -------------------------------------------------------------------------
301 TSet Combine( const TSet& X, const TSet& Y )
302 {
303   TSet Z;
304   for( auto xIt = X.begin( ); xIt != X.end( ); ++xIt )
305   {
306     for( auto yIt = Y.begin( ); yIt != Y.end( ); ++yIt )
307     {
308       std::stringstream val;
309       val << *xIt << "#" << *yIt;
310       Z.insert( val.str( ) );
311
312     } // rof
313
314   } // rof
315   return( Z );
316 }
317
318 // -------------------------------------------------------------------------
319 void Replace(
320   std::string& str, const std::string& sub, const std::string& nsub
321   )
322 {
323   size_t index = 0;
324   while( true )
325   {
326     index = str.find( sub,  index );
327     if( index == std::string::npos ) break;
328     str.replace( index, sub.size( ), nsub );
329     index += sub.size( );
330
331   } // elihw
332 }
333
334 // eof - $RCSfile$