32#ifndef STRINGMAPPER_H_
33#define STRINGMAPPER_H_
41#include <drain/RegExp.h>
42#include <drain/Sprinter.h>
43#include <drain/String.h>
47#include "VariableFormatter.h"
63 Stringlet(
const std::string & s =
"",
bool isVariable =
false) : std::string(s), isVar(isVariable) {
71 bool isVariable()
const {
return isVar; };
74 void setVariable(
bool isVariable=
true) { isVar = isVariable; };
77 void setLiteral(
const std::string &s) { assign(s); isVar =
false; };
91std::ostream & operator<<(std::ostream & ostr,
const Stringlet & s) {
93 return ostr <<
"${" << (
const std::string &) s <<
"}";
95 return ostr << (
const std::string &) s;
113 // Return false, if variable not found.
114 // Then, further processors may handle the variable tag (remove, change, leave it).
116 bool handle(const std::string & key, const std::map<std::string,T> & variables, std::ostream & ostr) const {
118 drain::Logger mout(__FILE__, __FUNCTION__);
120 std::string k,format;
121 drain::StringTools::split2(key, k, format, '|');
122 // mout.attention("split '", key, "' to ", k, " + ", format);
124 const typename std::map<std::string,T>::const_iterator it = variables.find(k);
125 if (it == variables.end()) {
131 iosFormat.copyTo(ostr);
132 //vostr.width(width);
133 //vstd::cerr << __FILE__ << " assign -> " << stringlet << std::endl;
134 //vstd::cerr << __FILE__ << " assign <---- " << mit->second << std::endl;
139 // mout.attention("delegating '", k, "' to formatVariable: ", format);
140 return formatVariable(k, variables, format, ostr);
147 // NOTE: must return false, if not found. Then, further processors may handle the variable tag (remove, change, leave it).
149 bool formatVariable(const std::string & key, const std::map<std::string,T> & variables, const std::string & format, std::ostream & ostr) const {
151 drain::Logger mout(__FILE__, __FUNCTION__);
154 const char firstChar = format.at(0);
155 const char lastChar = format.at(format.size()-1);
157 if (firstChar == ':'){
159 // mout.attention("substring extraction:", format);
162 drain::MapTools::get(variables, key, s);
164 std::vector<size_t> v;
165 drain::StringTools::split(format, v, ':');
167 size_t count = s.size();
175 if (pos >= s.size()){
176 mout.warn("index ", pos, " greater than size (", s.size(), ") of string value '", s, "' of '", key, "'");
179 count = std::min(count, s.size()-pos);
180 ostr << s.substr(v[1], count);
183 mout.warn("unsupported formatting '", format, "' for variable '", key, "'");
184 mout.advice("use :startpos or :startpos:count for substring extraction");
189 else if (firstChar == '%'){
191 // mout.attention("string formatting: ", format);
193 //else if (format.find('%') != std::string::npos){
195 drain::MapTools::get(variables, key, s);
197 const size_t BUFFER_SIZE = 256;
198 char buffer[BUFFER_SIZE];
204 n = std::sprintf(buffer, format.c_str(), s.c_str());
207 n = std::sprintf(buffer, format.c_str(), s.at(0)); // ?
210 mout.unimplemented("pointer type: ", format);
221 double d = NAN; //nand();
222 drain::MapTools::get(variables, key, d);
224 n = std::sprintf(buffer, format.c_str(), d);
235 drain::MapTools::get(variables, key, i);
237 n = std::sprintf(buffer, format.c_str(), i);
241 mout.warn("formatting '", format, "' requested for '", key, "' : unsupported type key: ", lastChar);
245 if (n > BUFFER_SIZE){
246 mout.fail("formatting with '", format, "' exceeded buffer size (", BUFFER_SIZE, ')');
249 // mout.warn("time formatting '", format, "' requested for '", k, "' not ending with 'time' or 'date'!");
287 const std::string & format =
"",
288 const std::string & validChars =
"[a-zA-Z0-9_]+",
290 ): formatting(formatting)
292 setValidChars(validChars);
293 regExp.setFlags(REG_EXTENDED);
311 StringMapper & setValidChars(
const std::string & chars){
312 this->validChars = chars;
329 if (this->formatting != formatting){
330 this->formatting = formatting;
334 this->formatting = formatting;
364 std::ostream &
toStream(std::ostream & ostr)
const {
381 for (
const Stringlet & stringlet: *
this){
383 if (stringlet.isVariable()){
385 if (formatter.handle(stringlet, variables, ostr)){
394 ostr << (char)replace;
421 toStream(s, m, replaceChar, formatter);
431 void expand(
const std::map<std::string,T> &m,
bool clear=
false) {
432 for (StringMapper::iterator it = begin(); it != end(); it++){
433 if (it->isVariable()){
434 typename std::map<std::string, T >::const_iterator mit = m.find(*it);
438 it->setLiteral(
Variable(mit->second).toStr());
451 std::ostream &
debug(std::ostream & ostr,
const std::map<std::string,T> &m )
const {
452 ostr <<
"StringMapper '"<<
"', RegExp='" << regExp <<
"', " << size() <<
" segments:\n";
454 for (StringMapper::const_iterator it = begin(); it != end(); it++){
457 if (it->isVariable()){
459 typename std::map<std::string, T >::const_iterator mit = m.find(*it);
461 ostr <<
"\"" << mit->second <<
"\"";
466 ostr <<
"'"<< *it <<
"'";
480 std::stringstream sstr;
481 sstr <<
"^(.*)\\$\\{(" << validChars;
483 sstr <<
"(\\|[^}]*)?";
487 regExp.setExpression(sstr.str());
492 std::string validChars;
501std::ostream & operator<<(std::ostream & ostr,
const StringMapper & strmap){
502 return strmap.toStream(ostr);
static std::ostream & sequenceToStream(std::ostream &ostr, const T &x, const SprinterLayout &layout)
Convenience: if sequence type (array, list, set, map) not given, assume array.
Definition Sprinter.h:321
static const SprinterLayout emptyLayout
Simply concatenate values without punctuation.
Definition Sprinter.h:206
A tool for expanding variables embedded in a std::string to literals.
Definition StringMapper.h:275
bool isLiteral() const
Return true, if all the elements are literal.
Definition StringMapper.cpp:114
StringMapper(const StringMapper &mapper)
Copy constructor copies the parsed string and the regExp.
Definition StringMapper.h:306
StringMapper(const std::string &format="", const std::string &validChars="[a-zA-Z0-9_]+", bool formatting=true)
Default constructor.
Definition StringMapper.h:286
static std::string & convertEscaped(std::string &s)
Interpret commond special chars tab '\t' and newline ' '.
Definition StringMapper.cpp:42
StringMapper & parse(const std::string &s, bool convertEscaped=false)
Converts a std::string containing variables like in "Hello, ${NAME}!" to a list of StringLet's.
Definition StringMapper.cpp:53
void expand(const std::map< std::string, T > &m, bool clear=false)
Expands the variables in StringMapper, turning expanded variables to constants.
Definition StringMapper.h:431
std::ostream & toStream(std::ostream &ostr, const std::map< std::string, T > &variables, int replace=0, const VariableFormatter< T > &formatter=VariableFormatter< T >()) const
Expands the variables in the last.
Definition StringMapper.h:379
std::ostream & debug(std::ostream &ostr, const std::map< std::string, T > &m) const
Dumps the list of StringLet's.
Definition StringMapper.h:451
StringMapper(const RegExp ®exp, bool formatting=true)
Initialize with the given RegExp // REMOVE!
Definition StringMapper.h:300
StringMapper & enableFormatting(bool formatting)
Enable variable formatting, followed by pipe '|'.
Definition StringMapper.h:328
std::ostream & toStream(std::ostream &ostr) const
Output a concatenated chain of stringlets: literals as such and variables surrounded with "${" and "}...
Definition StringMapper.h:364
std::string toStr(const std::map< std::string, T > &m, int replaceChar=-1, const VariableFormatter< T > &formatter=VariableFormatter< T >()) const
Expands the variables in the last parsed std::string to a std::string.
Definition StringMapper.h:419
A helper class for StringMapper.
Definition StringMapper.h:59
Stringlet(const Stringlet &s)
Copy constructor.
Definition StringMapper.h:67
Definition DataSelector.cpp:1277
DRAIN_VARIABLE Variable
Value container supporting dynamic type.
Definition Variable.h:63