#include #include #include #include #include #include #include #include #include #include #include // ------------------------------------------------------------------------- typedef std::set< std::string > TSet; typedef std::map< std::string, TSet > TInstances; typedef std::vector< std::string > TVector; // ------------------------------------------------------------------------- TVector Tokenize( const std::string& str, const std::string& delims ); TSet Combine( const TSet& X, const TSet& Y ); void Replace( std::string& str, const std::string& sub, const std::string& nsub ); // ------------------------------------------------------------------------- int main( int argc, char* argv[] ) { if( argc < 5 ) { std::cerr << "Usage: " << argv[ 0 ] << " input_definitions dir library_name header_filename" << std::endl; return( 1 ); } // fi std::string input_definitions_file_name = argv[ 1 ]; std::string dir = argv[ 2 ]; std::string library_name = argv[ 3 ]; std::string head_fname = argv[ 4 ]; // Load file into a buffer std::ifstream file_stream( input_definitions_file_name.c_str( ) ); if( !file_stream ) { std::cerr << "Error opening file: \"" << input_definitions_file_name << "\"" << std::endl; return( 1 ); } // fi std::string buf; file_stream.seekg( 0, std::ios::end ); buf.reserve( file_stream.tellg( ) ); file_stream.seekg( 0, std::ios::beg ); buf.assign( ( std::istreambuf_iterator< char >( file_stream ) ), std::istreambuf_iterator< char >( ) ); file_stream.close( ); std::istringstream input_str( buf ); // Process file std::string line; TVector incl, first_incl; TInstances instances; TVector classes; while( std::getline( input_str, line ) ) { if( line[ 0 ] == 'f' ) { first_incl.push_back( line.substr( line.find_first_not_of( ' ', 1 ) ) ); } else if( line[ 0 ] == 'i' ) { incl.push_back( line.substr( line.find_first_not_of( ' ', 1 ) ) ); } else if( line[ 0 ] == 'c' ) { classes.push_back( line.substr( line.find_first_not_of( ' ', 1 ) ) ); } else if( line[ 0 ] == 'a' ) { TVector tokens = Tokenize( line, "=" ); // Get argument name TVector arg_tokens = Tokenize( tokens[ 0 ], " " ); std::string arg = arg_tokens[ 0 ]; unsigned int i = 0; while( arg[ 0 ] != '#' && i < arg_tokens.size( ) ) arg = arg_tokens[ ++i ]; // Get values TVector values_tokens = Tokenize( tokens[ 1 ], ";" ); for( auto t = values_tokens.begin( ); t != values_tokens.end( ); ++t ) { std::string value = t->substr( t->find_first_not_of( ' ' ) ); unsigned int value_len = value.size( ); while( value[ value_len - 1 ] == ' ' && value_len > 0 ) value_len--; value = value.substr( 0, value_len ); if( value == "#integers" ) { instances[ arg ].insert( "char" ); instances[ arg ].insert( "short" ); instances[ arg ].insert( "int" ); instances[ arg ].insert( "long" ); instances[ arg ].insert( "unsigned char" ); instances[ arg ].insert( "unsigned short" ); instances[ arg ].insert( "unsigned int" ); instances[ arg ].insert( "unsigned long" ); } else if( value == "#integers_ptr" ) { instances[ arg ].insert( "char*" ); instances[ arg ].insert( "short*" ); instances[ arg ].insert( "int*" ); instances[ arg ].insert( "long*" ); instances[ arg ].insert( "unsigned char*" ); instances[ arg ].insert( "unsigned short*" ); instances[ arg ].insert( "unsigned int*" ); instances[ arg ].insert( "unsigned long*" ); } else if( value == "#floats" ) { instances[ arg ].insert( "double" ); instances[ arg ].insert( "float" ); } else if( value == "#floats_ptr" ) { instances[ arg ].insert( "double*" ); instances[ arg ].insert( "float*" ); } else if( value == "#all_dims" ) { instances[ arg ].insert( "1" ); instances[ arg ].insert( "2" ); instances[ arg ].insert( "3" ); instances[ arg ].insert( "4" ); } else if( value == "#all_visual_dims" ) { instances[ arg ].insert( "2" ); instances[ arg ].insert( "3" ); } else instances[ arg ].insert( value ); } // rof } // fi } // elihw // Span all possible types TVector all_real_classes; for( auto clsIt = classes.begin( ); clsIt != classes.end( ); ++clsIt ) { // Extract types std::string name = clsIt->substr( clsIt->find_first_not_of( " " ) ); std::string tok = name; auto sharpPos = tok.find_first_of( "#" ); TInstances li; while( sharpPos != std::string::npos ) { tok = tok.substr( sharpPos ); auto spacePos = tok.find_first_of( " " ); auto arg = tok.substr( 0, spacePos ); auto aIt = instances.find( arg ); if( aIt != instances.end( ) ) li[ arg ] = aIt->second; tok = tok.substr( spacePos ); sharpPos = tok.find_first_of( "#" ); } // eliwh if( li.size( ) > 0 ) { // Combine types TSet combs; if( li.size( ) > 1 ) { auto iIt = li.begin( ); auto jIt = iIt; jIt++; for( ; jIt != li.end( ); ++iIt, ++jIt ) { if( iIt == li.begin( ) ) combs = Combine( iIt->second, jIt->second ); else combs = Combine( combs, jIt->second ); } // rof } else combs = li.begin( )->second; // Write instantiations for( auto combIt = combs.begin( ); combIt != combs.end( ); ++combIt ) { char* buffer = new char[ combIt->size( ) + 1 ]; std::strcpy( buffer, combIt->c_str( ) ); buffer[ combIt->size( ) ] = '\0'; char* tok = std::strtok( buffer, "#" ); std::map< std::string, std::string > real_instance; for( auto lIt = li.begin( ); lIt != li.end( ); ++lIt ) { real_instance[ lIt->first ] = std::string( tok ); tok = std::strtok( NULL, "#" ); } // rof delete buffer; std::string real_name = name; auto riIt = real_instance.begin( ); for( ; riIt != real_instance.end( ); ++riIt ) Replace( real_name, riIt->first, riIt->second ); all_real_classes.push_back( real_name ); } // rof } else all_real_classes.push_back( name ); } // rof // Write files std::ofstream out_str( head_fname.c_str( ) ); if( !out_str ) { std::cerr << "Error opening file \"" << head_fname << "\"" << std::endl; return( 1 ); } // fi out_str << "#ifndef __" << dir << "__" << library_name << "__H__" << std::endl; out_str << "#define __" << dir << "__" << library_name << "__H__" << std::endl << std::endl; out_str << "#include <" << dir << "/" << library_name << "_Export.h>" << std::endl; // First incl for( auto inclIt = first_incl.begin( ); inclIt != first_incl.end( ); ++inclIt ) out_str << "#include <" << *inclIt << ">" << std::endl; out_str << std::endl; std::string base_name = dir + std::string( "_" ) + library_name; out_str << std::endl << "#ifdef " << base_name << "_EXPORTS" << std::endl << "# undef ITK_MANUAL_INSTANTIATION" << std::endl << "# define " << base_name << "_PREFIX template class " << base_name << "_EXPORT" << std::endl << "#else" << std::endl << "# define ITK_MANUAL_INSTANTIATION" << std::endl << "# define " << base_name << "_PREFIX extern template class" << std::endl << "#endif" << std::endl << std::endl; // Incl for( auto inclIt = incl.begin( ); inclIt != incl.end( ); ++inclIt ) out_str << "#include <" << *inclIt << ">" << std::endl; out_str << std::endl; // All classes for( auto clsIt = all_real_classes.begin( ); clsIt != all_real_classes.end( ); ++clsIt ) out_str << base_name << "_PREFIX " << *clsIt << ";" << std::endl; out_str << std::endl; out_str << "#endif // __" << dir << "__" << library_name << "__H__" << std::endl; out_str << std::endl << "// eof" << std::endl; out_str.close( ); return( 0 ); } // ------------------------------------------------------------------------- TVector Tokenize( const std::string& str, const std::string& delims ) { TVector tokens; if( str.size( ) > 0 ) { char* buffer = new char[ str.size( ) + 1 ]; std::strcpy( buffer, str.c_str( ) ); buffer[ str.size( ) ] = '\0'; char* it = std::strtok( buffer, delims.c_str( ) ); while( it != NULL ) { tokens.push_back( std::string( it ) ); it = std::strtok( NULL, delims.c_str( ) ); } // elihw delete buffer; } // fi return( tokens ); } // ------------------------------------------------------------------------- TSet Combine( const TSet& X, const TSet& Y ) { TSet Z; for( auto xIt = X.begin( ); xIt != X.end( ); ++xIt ) { for( auto yIt = Y.begin( ); yIt != Y.end( ); ++yIt ) { std::stringstream val; val << *xIt << "#" << *yIt; Z.insert( val.str( ) ); } // rof } // rof return( Z ); } // ------------------------------------------------------------------------- void Replace( std::string& str, const std::string& sub, const std::string& nsub ) { size_t index = 0; while( true ) { index = str.find( sub, index ); if( index == std::string::npos ) break; str.replace( index, sub.size( ), nsub ); index += sub.size( ); } // elihw } // eof - $RCSfile$