Eclipse SUMO - Simulation of Urban MObility
Parameterised.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
18 // A super class for objects with additional parameters
19 /****************************************************************************/
20 #include <config.h>
25 
26 #include "Parameterised.h"
27 
28 
29 // ===========================================================================
30 // method definitions
31 // ===========================================================================
32 
34 
35 
37  myMap(mapArg) {
38 }
39 
40 
42 
43 
44 void
45 Parameterised::setParameter(const std::string& key, const std::string& value) {
46  myMap[key] = value;
47 }
48 
49 
50 void
51 Parameterised::unsetParameter(const std::string& key) {
52  myMap.erase(key);
53 }
54 
55 
56 void
58  for (const auto& keyValue : mapArg) {
59  setParameter(keyValue.first, keyValue.second);
60  }
61 }
62 
63 
64 void
65 Parameterised::mergeParameters(const Parameterised::Map& mapArg, const std::string separator, bool uniqueValues) {
66  for (const auto& keyValue : mapArg) {
67  if (hasParameter(keyValue.first)) {
68  bool append = true;
69  if (uniqueValues) {
70  if (getParameter(keyValue.first) == keyValue.second) {
71  append = false;
72  }
73  }
74  if (append) {
75  setParameter(keyValue.first, getParameter(keyValue.first) + separator + keyValue.second);
76  }
77  } else {
78  setParameter(keyValue.first, keyValue.second);
79  }
80  }
81 }
82 
83 bool
84 Parameterised::hasParameter(const std::string& key) const {
85  return myMap.find(key) != myMap.end();
86 }
87 
88 
89 const std::string
90 Parameterised::getParameter(const std::string& key, const std::string defaultValue) const {
91  const auto i = myMap.find(key);
92  if (i != myMap.end()) {
93  return i->second;
94  }
95  return defaultValue;
96 }
97 
98 
99 double
100 Parameterised::getDouble(const std::string& key, const double defaultValue) const {
101  const auto i = myMap.find(key);
102  if (i != myMap.end()) {
103  try {
104  return StringUtils::toDouble(i->second);
105  } catch (NumberFormatException&) {
106  WRITE_WARNINGF(TL("Invalid conversion from string to double (%)"), i->second);
107  return defaultValue;
108  } catch (EmptyData&) {
109  WRITE_WARNING(TL("Invalid conversion from string to double (empty value)"));
110  return defaultValue;
111  }
112  }
113  return defaultValue;
114 }
115 
116 
117 std::vector<double>
118 Parameterised::getDoubles(const std::string& key, std::vector<double> defaultValue) const {
119  const auto i = myMap.find(key);
120  if (i != myMap.end()) {
121  try {
122  std::vector<double> result;
123  for (const std::string& s : StringTokenizer(i->second).getVector()) {
124  result.push_back(StringUtils::toDouble(s));
125  }
126  return result;
127  } catch (NumberFormatException&) {
128  WRITE_WARNINGF(TL("Invalid conversion from string to doubles (%)"), i->second);
129  return defaultValue;
130  } catch (EmptyData&) {
131  WRITE_WARNING(TL("Invalid conversion from string to doubles (empty value)"));
132  return defaultValue;
133  }
134  }
135  return defaultValue;
136 }
137 
138 void
140  myMap.clear();
141 }
142 
143 
144 const Parameterised::Map&
146  return myMap;
147 }
148 
149 
150 std::string
151 Parameterised::getParametersStr(const std::string kvsep, const std::string sep) const {
152  std::string result;
153  // Generate an string using configurable seperatrs, default: "key1=value1|key2=value2|...|keyN=valueN"
154  bool addSep = false;
155  for (const auto& keyValue : myMap) {
156  if (addSep) {
157  result += sep;
158  }
159  result += keyValue.first + kvsep + keyValue.second;
160  addSep = true;
161  }
162  return result;
163 }
164 
165 
166 void
168  myMap = params.getParametersMap();
169 }
170 
171 
172 void
173 Parameterised::setParametersStr(const std::string& paramsString, const std::string kvsep, const std::string sep) {
174  // clear parameters
175  myMap.clear();
176  // separate value in a vector of string using | as separator
177  std::vector<std::string> parameters = StringTokenizer(paramsString, sep).getVector();
178  // iterate over all values
179  for (const auto& keyValue : parameters) {
180  // obtain key and value and save it in myParameters
181  std::vector<std::string> keyValueStr = StringTokenizer(keyValue, kvsep).getVector();
182  setParameter(keyValueStr.front(), keyValueStr.back());
183  }
184 }
185 
186 
187 void
189  // iterate over all parameters and write it
190  for (const auto& keyValue : myMap) {
191  device.openTag(SUMO_TAG_PARAM);
192  device.writeAttr(SUMO_ATTR_KEY, StringUtils::escapeXML(keyValue.first));
193  device.writeAttr(SUMO_ATTR_VALUE, StringUtils::escapeXML(keyValue.second));
194  device.closeTag();
195  }
196 }
197 
198 
199 bool
200 Parameterised::areParametersValid(const std::string& value, bool report, const std::string kvsep, const std::string sep) {
201  std::vector<std::string> parameters = StringTokenizer(value, sep).getVector();
202  // first check if parsed parameters are valid
203  for (const auto& keyValueStr : parameters) {
204  // check if parameter is valid
205  if (!isParameterValid(keyValueStr, kvsep, sep)) {
206  // report depending of flag
207  if (report) {
208  WRITE_WARNINGF(TL("Invalid format of parameter (%)"), keyValueStr);
209  }
210  return false;
211  }
212  }
213  // all ok, then return true
214  return true;
215 }
216 
217 
218 bool
219 Parameterised::areAttributesValid(const std::string& value, bool report, const std::string kvsep, const std::string sep) {
220  std::vector<std::string> parameters = StringTokenizer(value, sep).getVector();
221  // first check if parsed parameters are valid
222  for (const auto& keyValueStr : parameters) {
223  // check if parameter is valid
224  if (isParameterValid(keyValueStr, kvsep, sep)) {
225  // separate key and value
226  const auto attr = StringTokenizer(value, kvsep).getVector().front();
227  // get first letter
228  const auto letter = StringTokenizer(value, kvsep).getVector().front().front();
229  // check key
230  if (!((letter >= 'a') && (letter <= 'z')) && !((letter >= 'A') && (letter <= 'Z'))) {
231  // report depending of flag
232  if (report) {
233  WRITE_WARNINGF(TL("Invalid format of attribute '%'. Attribute must start with a letter"), attr);
234  }
235  return false;
236  }
237  } else {
238  // report depending of flag
239  if (report) {
240  WRITE_WARNINGF(TL("Invalid format of attribute (%)"), keyValueStr);
241  }
242  return false;
243  }
244  }
245  // all ok, then return true
246  return true;
247 }
248 
249 // ===========================================================================
250 // private
251 // ===========================================================================
252 
253 bool
254 Parameterised::isParameterValid(const std::string& value, const std::string& kvsep, const std::string& sep) {
255  if (value.find(sep) != std::string::npos || value.find(kvsep) == std::string::npos) {
256  return false;
257  }
258  // separate key and value
259  std::vector<std::string> keyValueStr = StringTokenizer(value, kvsep).getVector();
260  // Check that keyValue size is exactly 2 (key, value)
261  if (keyValueStr.size() == 2) {
262  // check if key and value contains valid characters
263  if (SUMOXMLDefinitions::isValidParameterKey(keyValueStr.front()) == false) {
264  return false;
265  } else {
266  // key=value valid, then return true
267  return true;
268  }
269  } else {
270  // invalid format
271  return false;
272  }
273 }
274 
275 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
@ SUMO_TAG_PARAM
parameter associated to a certain key
@ SUMO_ATTR_VALUE
@ SUMO_ATTR_KEY
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
An upper class for objects with additional parameters.
Definition: Parameterised.h:41
std::vector< double > getDoubles(const std::string &key, std::vector< double > defaultValue=std::vector< double >()) const
Returns the value for a given key converted to a list of doubles.
static bool areAttributesValid(const std::string &value, bool report=false, const std::string kvsep="=", const std::string sep="|")
check if given string can be parsed to an attributes map "key1=value1|key2=value2|....
static bool isParameterValid(const std::string &value, const std::string &kvsep, const std::string &sep)
check if given string can be parsed to a parameter of type "key=value"
Parameterised::Map myMap
The key->value map.
static bool areParametersValid(const std::string &value, bool report=false, const std::string kvsep="=", const std::string sep="|")
check if given string can be parsed to a parameters map "key1=value1|key2=value2|....
void unsetParameter(const std::string &key)
Removes a parameter.
bool hasParameter(const std::string &key) const
Returns whether the parameter is set.
std::map< std::string, std::string > Map
parameters map
Definition: Parameterised.h:45
double getDouble(const std::string &key, const double defaultValue) const
Returns the value for a given key converted to a double.
Parameterised()
Default constructor.
void setParameters(const Parameterised &params)
set the inner key/value map in map<string, string> format
void mergeParameters(const Parameterised::Map &mapArg, const std::string separator=" ", bool uniqueValues=true)
Adds or appends all given parameters from the map.
void setParametersStr(const std::string &paramsString, const std::string kvsep="=", const std::string sep="|")
set the inner key/value map in string format "key1=value1|key2=value2|...|keyN=valueN"
virtual ~Parameterised()
Destructor.
void clearParameter()
Clears the parameter map.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
const Parameterised::Map & getParametersMap() const
Returns the inner key/value map.
void writeParams(OutputDevice &device) const
write Params in the given outputdevice
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
std::string getParametersStr(const std::string kvsep="=", const std::string sep="|") const
Returns the inner key/value map in string format "key1=value1|key2=value2|...|keyN=valueN".
void updateParameters(const Parameterised::Map &mapArg)
Adds or updates all given parameters from the map.
static bool isValidParameterKey(const std::string &value)
whether the given string is a valid key for a parameter
std::vector< std::string > getVector()
return vector of strings
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.