]> Creatis software - cpPlugins.git/blob - lib/cpPlugins/Utils/ExpandTemplates.cxx
...
[cpPlugins.git] / lib / cpPlugins / Utils / ExpandTemplates.cxx
1 /* =========================================================================
2  * @author Ricardo Montano-Barrera  (@javeriana.edu.co)
3  * @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
4  * =========================================================================
5  */
6 #include <cpPlugins/Utils/ExpandTemplates.h>
7 #include <fstream>
8 #include <sstream>
9 #include <stdexcept>
10
11 // -------------------------------------------------------------------------
12 cpPlugins::Utils::ExpandTemplates::
13 ExpandTemplates( )
14 {
15 }
16
17 // -------------------------------------------------------------------------
18 cpPlugins::Utils::ExpandTemplates::
19 ~ExpandTemplates( )
20 {
21 }
22
23 // -------------------------------------------------------------------------
24 void cpPlugins::Utils::ExpandTemplates::
25 Parse( const std::string& filename )
26 {
27   // Load file in a string buffer
28   std::ifstream input( filename.c_str( ) );
29   if( !input )
30     throw std::runtime_error( "Unable to parse file \"" + filename + "\"" );
31   typedef std::istreambuf_iterator< char > _TIt;
32   std::istringstream buffer( std::string( ( _TIt( input ) ), _TIt( ) ) );
33   input.close( );
34
35   // Read line by line
36   TStringsMapQueue patterns;
37   TStrings lines;
38   Self::_ReadLines( &buffer, patterns, lines );
39
40   // Parse patterns
41   Self::_ParsePatterns( patterns, this->m_Patterns );
42
43   // Expand lines
44   this->m_Lines.clear( );
45   for( std::string line: lines )
46     Self::_Expand( this->m_Lines, line, this->m_Patterns );
47 }
48
49 // -------------------------------------------------------------------------
50 void cpPlugins::Utils::ExpandTemplates::
51 Save( const std::string& filename )
52 {
53   // Fill buffer
54   std::stringstream buffer;
55   for( std::string line: this->m_Lines )
56     buffer << line << std::endl;
57
58   // Save buffer to file
59   std::ofstream output( filename.c_str( ) );
60   if( !output )
61     throw std::runtime_error( "Unable to save file \"" + filename + "\"" );
62   output << buffer.str( );
63   output.close( );
64 }
65
66 // -------------------------------------------------------------------------
67 std::string cpPlugins::Utils::ExpandTemplates::
68 _Replace( const std::string& s, const std::string& f, const std::string& t )
69 {
70   std::string r = s;
71   size_t p = r.find( f );
72   while( p != std::string::npos )
73   {
74     r.replace( p, f.length( ), t );
75     p = r.find( f );
76
77   } // elihw
78   return( r );
79 }
80
81 // -------------------------------------------------------------------------
82 void cpPlugins::Utils::ExpandTemplates::
83 _ReadLines( std::istream* str, TStringsMapQueue& patterns, TStrings& lines )
84 {
85   std::string line;
86   while( std::getline( *str, line ) )
87   {
88     std::size_t f = line.find_first_not_of( " \t\r\n" );
89     if( f != std::string::npos )
90     {
91       if( line[ f ] == '@' )
92       {
93         // New injection mark
94         std::string mark;
95         std::size_t s = line.find( "=" );
96         mark = line.substr( f, s ) + "@";
97         TStringsMapValue m( mark, TStrings( ) );
98         std::istringstream v( line.substr( s + 1 ) );
99         std::string t;
100         while( std::getline( v, t, ';' ) )
101           m.second.push_back( t );
102         patterns.push( m );
103       }
104       else
105         lines.push_back( line );
106     }
107     else
108       lines.push_back( line );
109
110   } // elihw
111 }
112
113 // -------------------------------------------------------------------------
114 void cpPlugins::Utils::ExpandTemplates::
115 _ParsePatterns( TStringsMapQueue& q, TStringsMap& patterns )
116 {
117   patterns.clear( );
118   while( q.size( ) > 0 )
119   {
120     TStringsMapValue p = q.front( );
121     q.pop( );
122
123     bool requeue = false;
124     TStrings new_v;
125     for( std::string v: p.second )
126     {
127       size_t s = v.find( "@" );
128       if( s != std::string::npos )
129       {
130         size_t e = v.find( "@", s + 1 );
131         if( e == std::string::npos )
132           throw std::runtime_error( "Invalid syntax: " + v );
133         std::string m = v.substr( s, e - s + 1 );
134         TStringsMap::const_iterator pIt = patterns.find( m );
135         if( pIt != patterns.end( ) )
136           for( std::string w: pIt->second )
137             new_v.push_back( Self::_Replace( v, m, w ) );
138         requeue = true;
139
140       } // fi
141
142     } // rof
143     if( requeue )
144     {
145       if( new_v.size( ) > 0 )
146         p.second = new_v;
147       q.push( p );
148     }
149     else
150       patterns.insert( p );
151
152   } // elihw
153 }
154
155 // -------------------------------------------------------------------------
156 void cpPlugins::Utils::ExpandTemplates::
157 _Expand(
158   TStrings& expands, const std::string& line, const TStringsMap& patterns
159   )
160 {
161   size_t s = line.find( "@" );
162   if( s != std::string::npos )
163   {
164     size_t e = line.find( "@", s + 1 );
165     if( e == std::string::npos )
166       throw std::runtime_error( "Invalid syntax: " + line );
167     std::string mark = line.substr( s, e - s + 1 );
168     TStringsMap::const_iterator pIt = patterns.find( mark );
169     if( pIt == patterns.end( ) )
170       throw std::runtime_error( "Unknown mark: " + mark );
171     for( std::string value: pIt->second )
172       Self::_Expand( expands, Self::_Replace( line, mark, value ), patterns );
173   }
174   else
175     expands.push_back( line );
176 }
177
178 // eof - $RCSfile$