]> Creatis software - cpPlugins.git/blob - bash/HostCreator.cxx
...
[cpPlugins.git] / bash / HostCreator.cxx
1 #include <iostream>
2 #include <map>
3 #include <sstream>
4 #include <utility>
5 #include <vector>
6 #include <bash/Config.h>
7
8 // -------------------------------------------------------------------------
9 typedef std::pair< std::string, std::string > TPair;
10 typedef std::map< std::string, TPair >        TInfo;
11
12 // -------------------------------------------------------------------------
13 bool is_valid_class( const std::string& str )
14 {
15   return( str.find( "cpPluginsObject" ) != std::string::npos );
16 }
17
18 // -------------------------------------------------------------------------
19 void process_header( TInfo& info, const std::string& file_name )
20 {
21   std::string buffer;
22   if( !( cpPlugins_bash::Read( buffer, file_name ) ) )
23     return;
24
25   auto prev_pos = std::string::npos;
26   prev_pos = 0;
27   auto pos = buffer.find( "cpPluginsObject" );
28   while( pos != std::string::npos )
29   {
30     // Get class names
31     auto op = buffer.find( "(", pos );
32     auto cl = buffer.find( ")", pos );
33     std::vector< std::string > tokens;
34     cpPlugins_bash::Tokenize(
35       tokens,
36       buffer.substr( op + 1, cl - op - 2 ),
37       ",\n "
38       );
39
40     std::string namespace_name = "";
41     auto preamble = buffer.substr( prev_pos, pos );
42     auto napos = preamble.find( "namespace" );
43     while( napos != std::string::npos )
44     {
45       auto enapos = preamble.find( "{", napos + 1 );
46       auto tmp = preamble.substr( napos, enapos - napos + 1 );
47       std::vector< std::string > tokens2;
48       cpPlugins_bash::Tokenize( tokens2, tmp, " \n\t{" );
49       namespace_name = tokens2.back( );
50       napos = preamble.find( "namespace", napos + 1 );
51
52     } // elihw
53
54     auto class_name = tokens[ 0 ];
55     auto superclass_name = tokens[ 1 ];
56     auto category_name = tokens[ 2 ];
57     if( info.find( class_name ) == info.end( ) )
58       info[ class_name ] = TPair( category_name, namespace_name );
59     prev_pos = pos;
60     pos = buffer.find( "cpPluginsObject", pos + 1 );
61
62   } // elihw
63 }
64
65 // -------------------------------------------------------------------------
66 int main( int argc, char* argv[] )
67 {
68   if( argc < 4 )
69   {
70     std::cerr
71       << "Usage: " << argv[ 0 ]
72       << " plugins_name output_file header_file_0.h header_file_0.h ..."
73       << std::endl;
74     return( 1 );
75
76   } // fi
77   std::string plugins_name = argv[ 1 ];
78   std::string output_filename = argv[ 2 ];
79
80   // Parse all header files
81   TInfo info;
82   for( int i = 3; i < argc; ++i )
83     process_header( info, argv[ i ] );
84   if( info.size( ) == 0 )
85   {
86     std::cerr << "ERROR: No valid input headers." << std::endl;
87     return( 1 );
88
89   } // fi
90
91   // Prepare prefixes
92 #if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
93   std::string export_prefix = "__declspec(dllexport)";
94 #else // defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
95   std::string export_prefix = "__attribute__((visibility(\"default\")))";
96 #endif // defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
97
98   // Output data
99   std::stringstream out;
100
101   // Include section
102   out
103     << "#include <map>" << std::endl
104     << "#include <string>" << std::endl
105     << "#include <vector>" << std::endl
106     << "#include <itkLightObject.h>" << std::endl
107     << std::endl;
108   for( int i = 3; i < argc; ++i )
109     out << "#include \"" << argv[ i ] << "\"" <<std::endl;
110   out << std::endl;
111
112   // Common header section
113   out
114     << "// -------------------------------------------------------------------------" << std::endl
115     << "std::map< std::string, itk::LightObject::Pointer > "
116     << plugins_name << "_Data;" << std::endl
117     << std::endl
118     << "// -------------------------------------------------------------------------" << std::endl
119     << "extern \"C\" void __attribute__ ((constructor))" << std::endl
120     << plugins_name << "_Init( )" << std::endl
121     << "{" << std::endl
122     << "}" << std::endl
123     << std::endl
124     << "// -------------------------------------------------------------------------" << std::endl
125     << "extern \"C\" void __attribute__ ((destructor))" << std::endl
126     << plugins_name << "_Finish( )" << std::endl
127     << "{" << std::endl
128     << "  // " << plugins_name << "_Data.clear( );" << std::endl
129     << "}" << std::endl
130     << std::endl
131     << "// -------------------------------------------------------------------------" << std::endl
132     << "extern \"C\" " << export_prefix << std::endl
133     << "void " << plugins_name << "_LoadContents( )" << std::endl
134     << "{" << std::endl
135     << "  if( " << plugins_name << "_Data.size( ) == 0 )" << std::endl
136     << "  {" << std::endl
137     << "    std::string sep = \"@\";" << std::endl;
138
139   // Classes
140   int id = 1;
141   for( auto iIt = info.begin( ); iIt != info.end( ); ++iIt, ++id )
142   {
143     std::string class_name = iIt->second.second;
144     if( class_name != "" )
145       class_name += std::string( "::" );
146     class_name += iIt->first;
147     out
148       << "    " << class_name << "::Pointer ptr" << id << " =" << std::endl
149       << "      " << class_name << "::New( );" << std::endl
150       << "    std::string id" << id << " = ptr" << id << "->GetClassName( )"
151       << " + sep + ptr" << id << "->GetClassCategory( );" << std::endl
152       << "    " << plugins_name << "_Data[ id" << id << " ] = ptr" << id << ";"
153       << std::endl;
154
155   } // rof
156
157   // Remaining header
158   out
159     << std::endl << "  } // fi" << std::endl << "}" << std::endl << std::endl
160     << "// -------------------------------------------------------------------------" << std::endl
161     << "extern \"C\" " << export_prefix << std::endl
162     << "void cpPlugins_Contents( std::vector< std::string >* c )" << std::endl
163     << "{" << std::endl
164     << "  " << plugins_name << "_LoadContents( );" << std::endl
165     << "  for( auto d : " << plugins_name << "_Data )" << std::endl
166     << "    c->push_back( d.first );" << std::endl
167     << "}" << std::endl
168     << std::endl
169     << "// -------------------------------------------------------------------------" << std::endl
170     << "extern \"C\" " << export_prefix << std::endl
171     << "void cpPlugins_Creator( itk::LightObject::Pointer& ptr, const std::string& c, const std::string& f )" << std::endl
172     << "{" << std::endl
173     << "  " << plugins_name << "_LoadContents( );" << std::endl
174     << "  ptr = NULL;" << std::endl
175     << "  std::string id = f + \"@\" + c;" << std::endl
176     << "  auto fIt = " << plugins_name << "_Data.find( id );" << std::endl
177     << "  if( fIt != " << plugins_name << "_Data.end( ) )" << std::endl
178     << "    ptr = fIt->second->CreateAnother( );" << std::endl
179     << "}" << std::endl << std::endl
180     << "// eof - $Automatic generated file$"
181     << std::endl;
182
183   // Real write
184   if( !( cpPlugins_bash::Write( out.str( ), output_filename ) ) )
185   {
186     std::cerr << "ERROR: Could not write file." << std::endl;
187     return( 1 );
188
189   } // fi
190   return( 0 );
191 }
192
193 // eof - $RCSfile$