1 /* =========================================================================
2 * @author Ricardo Montano-Barrera (@javeriana.edu.co)
3 * @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
4 * =========================================================================
6 #include <cpPlugins/Utils/ExpandTemplates.h>
11 // -------------------------------------------------------------------------
12 cpPlugins::Utils::ExpandTemplates::
17 // -------------------------------------------------------------------------
18 cpPlugins::Utils::ExpandTemplates::
23 // -------------------------------------------------------------------------
24 void cpPlugins::Utils::ExpandTemplates::
25 Parse( const std::string& filename )
27 // Load file in a string buffer
28 std::ifstream input( filename.c_str( ) );
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( ) ) );
36 TStringsMapQueue patterns;
38 Self::_ReadLines( &buffer, patterns, lines );
41 Self::_ParsePatterns( patterns, this->m_Patterns );
44 this->m_Lines.clear( );
45 for( std::string line: lines )
46 Self::_Expand( this->m_Lines, line, this->m_Patterns );
49 // -------------------------------------------------------------------------
50 void cpPlugins::Utils::ExpandTemplates::
51 Save( const std::string& filename )
54 std::stringstream buffer;
55 for( std::string line: this->m_Lines )
56 buffer << line << std::endl;
58 // Save buffer to file
59 std::ofstream output( filename.c_str( ) );
61 throw std::runtime_error( "Unable to save file \"" + filename + "\"" );
62 output << buffer.str( );
66 // -------------------------------------------------------------------------
67 std::string cpPlugins::Utils::ExpandTemplates::
68 _Replace( const std::string& s, const std::string& f, const std::string& t )
71 size_t p = r.find( f );
72 while( p != std::string::npos )
74 r.replace( p, f.length( ), t );
81 // -------------------------------------------------------------------------
82 void cpPlugins::Utils::ExpandTemplates::
83 _ReadLines( std::istream* str, TStringsMapQueue& patterns, TStrings& lines )
86 while( std::getline( *str, line ) )
88 std::size_t f = line.find_first_not_of( " \t\r\n" );
89 if( f != std::string::npos )
91 if( line[ f ] == '@' )
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 ) );
100 while( std::getline( v, t, ';' ) )
101 m.second.push_back( t );
105 lines.push_back( line );
108 lines.push_back( line );
113 // -------------------------------------------------------------------------
114 void cpPlugins::Utils::ExpandTemplates::
115 _ParsePatterns( TStringsMapQueue& q, TStringsMap& patterns )
118 while( q.size( ) > 0 )
120 TStringsMapValue p = q.front( );
123 bool requeue = false;
125 for( std::string v: p.second )
127 size_t s = v.find( "@" );
128 if( s != std::string::npos )
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 ) );
145 if( new_v.size( ) > 0 )
150 patterns.insert( p );
155 // -------------------------------------------------------------------------
156 void cpPlugins::Utils::ExpandTemplates::
158 TStrings& expands, const std::string& line, const TStringsMap& patterns
161 size_t s = line.find( "@" );
162 if( s != std::string::npos )
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 );
175 expands.push_back( line );