MapReader.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31 #ifndef MAPREADER_H_
32 #define MAPREADER_H_
33 
34 #include <iostream>
35 #include <fstream>
36 
37 #include <map>
38 
39 #include <drain/RegExp.h>
40 
41 // using namespace std;
42 
43 
44 namespace drain
45 {
46 
47 // consider changing back *m => &m ?
48 
50 
55 template <class K, class V>
56 class MapReader
57 {
58 public:
59 
61  std::string trimChars;
62 
63  // If "limited", does not allow adding new entries but changes only.
64  bool limited;
65 
66 
67  MapReader() : limited(false), m(defaultMap) {};
68 
69  MapReader(std::map<K,V> &target) : limited(false), m(&target) {
70 
71  trimChars = " \t";
72  // WAS lazy hyphen in the leading characters
73  //std::string regExpString = "^[ \t]*([a-zA-Z][a-zA-Z0-9_]*)[ \t]*=(.*)$";
74 
75  // Indices for the essential patterns in the following regexps
76  //KEY = 1;
77  //VALUE = 3;
78 
79  // Mpeura 2009/07
80  //configLineParser.setExpression("^[ \t]*([a-zA-Z][a-zA-Z0-9_\\.]*)[ \t]*(=(.*))?$");
81  //commandLineParser.setExpression("^\\-\\-?([a-zA-Z][a-zA-Z0-9_\\.]*)(=(.*))?$"); // Must preserve position 1 and 3!
82  setKeySyntax("[a-zA-Z][a-zA-Z0-9_\\.]*");
83 
84  //std::string regExpString = "^([a-z]*)$";
85  //setRegExp(regExpString);
86  //cout << lineParser.test("ksm=kks") << endl;
87  };
88 
89  virtual ~MapReader(){};
90 
91  void setMap(std::map<K,V> &target){
92  m = &target;
93  }
94 
96  void setKeySyntax(const std::string & regExp){
97  configLineParser.setExpression(std::string("^[ \t]*(")+regExp+")[ \t]*(=(.*))?$");
98  commandLineParser.setExpression(std::string("^\\-\\-?(")+regExp+")(=(.*))?$"); // Must preserve position 1 and 3!
99  }
100 
101  //std::string regexpString;
102  //drain::RegExp commandLineOptionParser;
103 
104  void trim(std::string &s){
105  std::string::size_type pos1 = s.find_first_not_of(trimChars);
106  std::string::size_type pos2 = s.find_last_not_of(trimChars);
107  if (pos1 != std::string::npos)
108  s = s.substr(pos1,pos2-pos1 + 1);
109  else
110  s = "";
111  }
112 
113 
114  // PAH
115  /*
116  bool setRegExp(const std::string &regExpString){
117  return ( configLineParser.setExpression(regExpString) );
118  }
119  */
120 
125  void read(const std::string &filename){ // replace with "readFile" or drain::InputFile()
126  std::ifstream ifstr;
127  ifstr.open(filename.c_str());
128  read(ifstr);
129  ifstr.close();
130  }
131 
135  void read(std::istream &istr = std::cin){
136  std::string line;
137  while (getline(istr,line)){
138  //cout << "MapReader::read istr: " << line << '\n';
139  readConfigEntry(line);
140  }
141  }
142 
146  void readConfigEntry(const std::string &line){ //const char *line){
147  readEntry(line,configLineParser);
148  }
149 
153  void readCommandLineEntry(const std::string &s){ //const char *line){
154  readEntry(s,commandLineParser);
155  }
156 
157  void readPendingCommandLineArgument(const std::string &s){
158  value = s;
159  trim(value);
160  (*m)[key] = value;
161  argumentRegistered = true;
162  }
163 
164 
168  void readEntry(const std::string &line, drain::RegExp &regExp){ //const char *line){
169 
170  regExp.execute(line);
171 
172  const std::vector<std::string> &result = regExp.result;
173 
174  //std::string::size_type s = result.size();
175 
176  /*
177  cout << "readEntry, size=" << s << '\n';
178  for (unsigned int i = 0; i < s; ++i) {
179  cout << i << ' ' << result[i] << '\n';
180  }
181  */
182  //cout << "VALUE=" << VALUE << result[VALUE] << '\n';
183  //cout << "KEY=" << KEY << result[KEY] << '\n';
184  //cout << "***** readEntry, size=" << s << '\n';
185 
186 
187  // If matches --xxxxxxx
188  if (!result.empty()){
189 
190  key = result[1];
191  trim(key);
192 
193  /*
194  if ((limited)&&(m->find(key) != m->end())){
195  throw "Closed map has not key " + key;
196  }
197  */
198 
199  if (!result[2].empty()){// At least '=' found
200  value = result[3];
201  trim(value);
202  (*m)[key] = value;
203  argumentRegistered = true;
204  }
205  else {
206  value = "";
207  argumentRegistered = false; // user is hinted to use readPendingArgument now.
208  }
209  }
210  else { // loose argument
211  key="";
212  value = line;
213  trim(value);
214  argumentRegistered = true;
215  }
216 
217 
218 
219  }
220 
225  void read(int argc, char **argv){
226  for (int i = 1; i < argc; ++i) {
227  readCommandLineEntry(argv[i]);
228  }
229 
230  }
231 
232 
233 
234  inline const std::string &getKey(){return key;};
235  inline const std::string &getValue(){return value;};
236 
237  //inline bool pendingArgument(){return !hasArgument;};
238  inline bool hasArgument(){return argumentRegistered;};
239 
240 protected:
241  std::map<K,V> *m;
242  std::map<K,V> defaultMap;
243 
244  // For configuration file options
245  drain::RegExp configLineParser;
246 
247  // For command line options
248  drain::RegExp commandLineParser;
249 
250  std::string key;
251  std::string value;
252 
253  // change to "pending argument" etc
254  bool argumentRegistered;
255  //int KEY;
256  //int VALUE;
257 
258 };
259 
260 } //namespace
261 
262 #endif /*MAPREADER_H_*/
263 
264 // Drain
General utility for reading text entries of type KEY=VALUE into a map.
Definition: MapReader.h:57
void read(std::istream &istr=std::cin)
Definition: MapReader.h:135
void readConfigEntry(const std::string &line)
Definition: MapReader.h:146
void readEntry(const std::string &line, drain::RegExp &regExp)
Definition: MapReader.h:168
void setKeySyntax(const std::string &regExp)
Defines the std::strings recognized (accepted) as keys. By default: [a-zA-Z][a-zA-Z0-9_\....
Definition: MapReader.h:96
std::string trimChars
Leading and trailing characters to be pruned.
Definition: MapReader.h:61
void read(const std::string &filename)
Definition: MapReader.h:125
void readCommandLineEntry(const std::string &s)
Definition: MapReader.h:153
void read(int argc, char **argv)
Definition: MapReader.h:225
Definition: RegExp.h:58
const std::vector< std::string > & result
Public interface for the result.
Definition: RegExp.h:107
int execute(const std::string &str, T &result) const
Apply regexp matching in a string. Returns 0 on success, REG_NOMATCH on failure.
Definition: RegExp.h:187
Definition: DataSelector.cpp:1277