Loading...
Searching...
No Matches
VariableFormatter.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31
32#ifndef VARIABLE_FORMATTER_H_
33#define VARIABLE_FORMATTER_H_
34
35#include <drain/Log.h>
36#include <map>
37#include <list>
38#include <iterator>
39#include <sstream>
40
41#include <drain/Convert.h>
42#include <drain/RegExp.h>
43#include <drain/StringTools.h>
44// #include <drain/VariableAssign.h>
45#include <drain/SmartMapTools.h>
46//#include "Variable.h"
47
48#include "IosFormat.h"
49//#include "MapTools.h"
50
51//#include "Sprinter.h"
52#include "Time.h"
53
54namespace drain {
55
56
58
70template <class T=std::string>
72
73public:
74
75 inline virtual
77
78 IosFormat iosFormat;
79
80 typedef std::map<std::string,T> map_t;
81
83
87 virtual
88 bool handle(const std::string & key, const map_t & variables, std::ostream & ostr) const {
89
90 drain::Logger mout(__FILE__, __FUNCTION__);
91
92 std::string k,format;
93 drain::StringTools::split2(key, k, format, '|');
94 // mout.attention("split '", key, "' to ", k, " + ", format);
95
96 const typename std::map<std::string,T>::const_iterator it = variables.find(k);
97 if (it == variables.end()) {
98 // Don't format.
99 return false;
100 }
101
102 const T & value = it->second;
103 if (format.empty()){
104 iosFormat.copyTo(ostr);
105 // vostr.width(width);
106 // vstd::cerr << __FILE__ << " assign -> " << stringlet << std::endl;
107 // vstd::cerr << __FILE__ << " assign <---- " << mit->second << std::endl;
108 ostr << value;
109 return true;
110 }
111 else {
112 // mout.attention("delegating '", k, "' to formatVariable: ", format);
113 // return formatVariable(k, variables, format, ostr);
114 return formatVariable(k, value, format, ostr);
115 }
116
117 }
118
119
121
126 // NOTE: must return false, if not found. Then, further processors may handle the variable tag (remove, change, leave it).
127 virtual
128 bool formatVariable(const std::string & key, const T & value, const std::string & format, std::ostream & ostr) const {
129 // drain::Logger mout(__FILE__, __FUNCTION__);
130 // Default implementation discards \c key.
131 return formatValue(value, format, ostr);
132 }
133
135 virtual inline
136 bool formatVariable(const std::string & key, const T & value, const std::string & format, std::string & str) const final {
137 std::stringstream sstr;
138 const bool result = formatVariable(key, value, format, sstr);
139 str = sstr.str();
140 return result;
141 }
142
143
145
159 static
160 bool formatValue(const T & value, const std::string & format, std::ostream & ostr) {
161
162 drain::Logger mout(__FILE__, __FUNCTION__);
163
164 if (format.empty()){
165 ostr << value;
166 return true;
167 }
168
169 const char firstChar = format.at(0);
170 const char lastChar = format.at(format.size()-1);
171
172 if (firstChar == ':'){
173
174 mout.attention<LOG_DEBUG>("substring extraction: ", format);
175
176 std::string s;
177 drain::Convert::convert(value, s);
178 //drain::StringTools::import(variable, s);
179
180 std::vector<size_t> v;
181 drain::StringTools::split(format, v, ':');
182 size_t pos = 0;
183 size_t count = s.size();
184
185 switch (v.size()) {
186 case 3:
187 count = v[2];
188 // no break
189 case 2:
190 pos = v[1];
191 if (pos >= s.size()){
192 mout.warn("index ", pos, " greater than size (", s.size(), ") of string value '", s, "' of '", value, "'");
193 return true;
194 }
195 count = std::min(count, s.size()-pos);
196 ostr << s.substr(v[1], count);
197 break;
198 default:
199 mout.warn("unsupported formatting '", format, "' for variable '", value, "'");
200 mout.advice("use :startpos or :startpos:count for substring extraction");
201 }
202 return true;
203
204 }
205 else if (firstChar == '%'){
206
207 mout.attention<LOG_DEBUG>("string formatting: ", format);
208
209 //else if (format.find('%') != std::string::npos){
210 //drain::MapTools::get(variables, key, s);
211
212 const size_t BUFFER_SIZE = 256;
213 char buffer[BUFFER_SIZE];
214 buffer[0] = '\0';
215 size_t n = 0;
216
217 switch (lastChar){
218 case 's':
219 {
220 std::string s;
221 drain::Convert::convert(value, s);
222 // drain::StringTools::import(variable, s);
223 n = std::sprintf(buffer, format.c_str(), s.c_str());
224 }
225 break;
226 case 'c':
227 {
228 std::string s;
229 drain::Convert::convert(value, s);
230 //drain::StringTools::import(variable, s);
231 n = std::sprintf(buffer, format.c_str(), s.at(0)); // ?
232 }
233 break;
234 case 'p':
235 mout.unimplemented("pointer type: ", format);
236 break;
237 case 'f':
238 case 'F':
239 case 'e':
240 case 'E':
241 case 'a':
242 case 'A':
243 case 'g':
244 case 'G':
245 {
246 double d = NAN; //nand()
247 drain::Convert::convert(value, d);
248 // drain::StringTools::import(variable, d);
249 //drain::MapTools::get(variables, key, d);
250 // ostr << d << "=>"; // debugging
251 n = std::sprintf(buffer, format.c_str(), d);
252 }
253 break;
254 case 'd':
255 case 'i':
256 case 'o':
257 case 'u':
258 case 'x':
259 case 'X':
260 {
261 int i = 0;
262 drain::Convert::convert(value, i);
263 // drain::convertAny(variable, i);
264 // drain::StringTools::import(variable, i);
265 // drain::MapTools::get(variables, key, i);
266 // ostr << i << "=>"; // debugging
267 n = std::sprintf(buffer, format.c_str(), i);
268 }
269 break;
270 default:
271 mout.warn("formatting '", format, "' requested for '", value, "' : unsupported type key: '", lastChar, "'");
272 return false; // could be also true, if seen as handled this way?
273 }
274
275 ostr << buffer;
276 if (n > BUFFER_SIZE){
277 mout.fail("formatting with '", format, "' exceeded buffer size (", BUFFER_SIZE, ')');
278 }
279
280 // mout.warn("time formatting '", format, "' requested for '", k, "' not ending with 'time' or 'date'!");
281 }
282
283 return true;
284 }
285
286
287
288};
289
290/*
291inline
292std::ostream & operator<<(std::ostream & ostr, const StringMapper & strmap){
293 return strmap.toStream(ostr);
294}
295*/
296
297
298} // NAMESPACE
299
300#endif /* STRINGMAPPER_H_ */
301
302// Drain
static void convert(const T1 &src, T2 &dst)
General case: dispatch to Converter<T1> traits.
Definition Convert.h:130
Stores precision, fillChar and fieldWidth applied by STD streams.
Definition IosFormat.h:45
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:313
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:431
Logger & fail(const TT &... args)
Possible error, but execution can continue. Special type of Logger::warn().
Definition Log.h:454
Logger & attention(const TT &... args)
Possible error, but execution can continue. Special type of Logger::warn().
Definition Log.h:477
Logger & unimplemented(const TT &... args)
Feature to be done. Special type of Logger::note().
Definition Log.h:512
static bool split2(const std::string &s, T1 &first, T2 &second, const C &separators, const std::string &trimChars=" \t\n")
Splits and trims a given std::string to a std Sequence.
static void split(const std::string &s, T &sequence, const C &separators, const std::string &trimChars=" \t\n")
Splits and trims a given std::string to a std Sequence.
Definition StringTools.h:487
Formats variables to output stream.
Definition VariableFormatter.h:71
static bool formatValue(const T &value, const std::string &format, std::ostream &ostr)
Given a value, print it formatted to stream.
Definition VariableFormatter.h:160
virtual bool formatVariable(const std::string &key, const T &value, const std::string &format, std::ostream &ostr) const
Given a key, retrieve an associated value from the map and print the value formatted into a stream.
Definition VariableFormatter.h:128
virtual bool handle(const std::string &key, const map_t &variables, std::ostream &ostr) const
Searches given key in a map, and if found, processes (formats) the value to ostream....
Definition VariableFormatter.h:88
virtual bool formatVariable(const std::string &key, const T &value, const std::string &format, std::string &str) const final
Checks if variables have ODIM names (keys), and apply special formatting (currently with time stamps)
Definition VariableFormatter.h:136
Definition DataSelector.cpp:1277