I want simple C++ string based template library to replace strings at runtime.
For example, I will use
string template = \"My name is {{name}}\";
If you have a function that replaces all occurrences of a string with another string:
std::string replace_all(std::string str, const std::string &remove, const std::string &insert)
{
std::string::size_type pos = 0;
while ((pos = str.find(remove, pos)) != std::string::npos)
{
str.replace(pos, remove.size(), insert);
pos++;
}
return str;
}
Then you can do this:
std::string pattern = "My name is {{first_name}} {{last_name}} and I live in {{location}}";
std::string str = replace_all(replace_all(replace_all(pattern,
"{{first_name}}", "Homer"),
"{{last_name}}", "Simpson"),
"{{location}}", "Springfield");
You can have a look at Inja. It is a simple, header-only template engine and does what you're asking for. There you can just call
data["name"] = "world";
inja::render("Hello {{ name }}!", data); // Returns "Hello world!"
string skeleton = "My name is {{name}}";
string placeholder = "{{name}}";
string::size_type pos = skeleton.find(placeholder);
while( pos != string::npos ) {
skeleton.replace(pos, placeholder.length(), "Gopalakrishnan");
pos = skeleton.find(placeholder, ++pos);
}
If you are new to C++, adding new libraries (template or otherwise) to your installation will only increase the learning curve. This is something you can do simply, elegantly, and efficiently with the built-in features.
Unlike similar answers, this code makes only one pass over the input and scales well with large dictionaries:
// header
#include <map>
#include <sstream>
typedef std::map< std::string, std::string > subst_map;
// implementation
using namespace std;
string do_substitutions( string const &in, subst_map const &subst ) {
ostringstream out;
size_t pos = 0;
for (;;) {
size_t subst_pos = in.find( "{{", pos );
size_t end_pos = in.find( "}}", subst_pos );
if ( end_pos == string::npos ) break;
out.write( &* in.begin() + pos, subst_pos - pos );
subst_pos += strlen( "{{" );
subst_map::const_iterator subst_it
= subst.find( in.substr( subst_pos, end_pos - subst_pos ) );
if ( subst_it == subst.end() ) throw runtime_error( "undefined substitution" );
out << subst_it->second;
pos = end_pos + strlen( "}}" );
}
out << in.substr( pos, string::npos );
return out.str();
}
// usage
pair< string, string > substitutions_init[] = {
make_pair( "firstname", "homer" ),
make_pair( "lastname", "simpson" )
};
subst_map substitutions
( substitutions_init, substitutions_init + sizeof(substitutions_init)/sizeof(*substitutions_init) );
int main() {
cerr << do_substitutions( "Mr. {{lastname}}, {{firstname}} esquire", substitutions ) << endl;
}