Line data Source code
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 : /****************************************************************************/
14 : /// @file Parameterised.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @date Sept 2002
17 : ///
18 : // A super class for objects with additional parameters
19 : /****************************************************************************/
20 : #include <config.h>
21 : #include <utils/common/MsgHandler.h>
22 : #include <utils/common/StringUtils.h>
23 : #include <utils/common/StringTokenizer.h>
24 : #include <utils/iodevices/OutputDevice.h>
25 :
26 : #include "Parameterised.h"
27 :
28 :
29 : // ===========================================================================
30 : // method definitions
31 : // ===========================================================================
32 :
33 11619770 : Parameterised::Parameterised() {}
34 :
35 :
36 231784 : Parameterised::Parameterised(const Parameterised::Map& mapArg) :
37 231784 : myMap(mapArg) {
38 231784 : }
39 :
40 :
41 30364164 : Parameterised::~Parameterised() {}
42 :
43 :
44 : void
45 4921504 : Parameterised::setParameter(const std::string& key, const std::string& value) {
46 4921504 : myMap[key] = value;
47 4921504 : }
48 :
49 :
50 : void
51 72125 : Parameterised::unsetParameter(const std::string& key) {
52 : myMap.erase(key);
53 72125 : }
54 :
55 :
56 : void
57 2410808 : Parameterised::updateParameters(const Parameterised::Map& mapArg) {
58 2445672 : for (const auto& keyValue : mapArg) {
59 34864 : setParameter(keyValue.first, keyValue.second);
60 : }
61 2410808 : }
62 :
63 :
64 : void
65 5416 : Parameterised::mergeParameters(const Parameterised::Map& mapArg, const std::string separator, bool uniqueValues) {
66 7107 : for (const auto& keyValue : mapArg) {
67 1691 : if (hasParameter(keyValue.first)) {
68 : bool append = true;
69 877 : if (uniqueValues) {
70 1754 : if (getParameter(keyValue.first) == keyValue.second) {
71 : append = false;
72 : }
73 : }
74 : if (append) {
75 36 : setParameter(keyValue.first, getParameter(keyValue.first) + separator + keyValue.second);
76 : }
77 : } else {
78 814 : setParameter(keyValue.first, keyValue.second);
79 : }
80 : }
81 5416 : }
82 :
83 : bool
84 448472137 : Parameterised::hasParameter(const std::string& key) const {
85 448472137 : return myMap.find(key) != myMap.end();
86 : }
87 :
88 :
89 : const std::string
90 9841933 : Parameterised::getParameter(const std::string& key, const std::string defaultValue) const {
91 : const auto i = myMap.find(key);
92 9841933 : if (i != myMap.end()) {
93 : return i->second;
94 : }
95 : return defaultValue;
96 : }
97 :
98 :
99 : double
100 9650541 : Parameterised::getDouble(const std::string& key, const double defaultValue) const {
101 : const auto i = myMap.find(key);
102 9650541 : if (i != myMap.end()) {
103 : try {
104 3416 : return StringUtils::toDouble(i->second);
105 0 : } catch (NumberFormatException&) {
106 0 : WRITE_WARNINGF(TL("Invalid conversion from string to double (%)"), i->second);
107 : return defaultValue;
108 0 : } catch (EmptyData&) {
109 0 : WRITE_WARNING(TL("Invalid conversion from string to double (empty value)"));
110 : return defaultValue;
111 0 : }
112 : }
113 : return defaultValue;
114 : }
115 :
116 :
117 : std::vector<double>
118 0 : Parameterised::getDoubles(const std::string& key, std::vector<double> defaultValue) const {
119 : const auto i = myMap.find(key);
120 0 : if (i != myMap.end()) {
121 : try {
122 : std::vector<double> result;
123 0 : for (const std::string& s : StringTokenizer(i->second).getVector()) {
124 0 : result.push_back(StringUtils::toDouble(s));
125 0 : }
126 : return result;
127 0 : } catch (NumberFormatException&) {
128 0 : WRITE_WARNINGF(TL("Invalid conversion from string to doubles (%)"), i->second);
129 : return defaultValue;
130 0 : } catch (EmptyData&) {
131 0 : WRITE_WARNING(TL("Invalid conversion from string to doubles (empty value)"));
132 : return defaultValue;
133 0 : }
134 : }
135 : return defaultValue;
136 : }
137 :
138 : void
139 1737900 : Parameterised::clearParameter() {
140 : myMap.clear();
141 1737900 : }
142 :
143 :
144 : const Parameterised::Map&
145 8195375 : Parameterised::getParametersMap() const {
146 8195375 : return myMap;
147 : }
148 :
149 :
150 : std::string
151 0 : 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 0 : for (const auto& keyValue : myMap) {
156 0 : if (addSep) {
157 : result += sep;
158 : }
159 0 : result += keyValue.first + kvsep + keyValue.second;
160 : addSep = true;
161 : }
162 0 : return result;
163 : }
164 :
165 :
166 : void
167 1150553 : Parameterised::setParameters(const Parameterised& params) {
168 1150553 : myMap = params.getParametersMap();
169 1150553 : }
170 :
171 :
172 : void
173 632 : 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 1264 : std::vector<std::string> parameters = StringTokenizer(paramsString, sep).getVector();
178 : // iterate over all values
179 638 : for (const auto& keyValue : parameters) {
180 : // obtain key and value and save it in myParameters
181 12 : std::vector<std::string> keyValueStr = StringTokenizer(keyValue, kvsep).getVector();
182 6 : setParameter(keyValueStr.front(), keyValueStr.back());
183 6 : }
184 632 : }
185 :
186 :
187 : void
188 975621 : Parameterised::writeParams(OutputDevice& device) const {
189 : // iterate over all parameters and write it
190 1031073 : for (const auto& keyValue : myMap) {
191 55452 : device.openTag(SUMO_TAG_PARAM);
192 55452 : device.writeAttr(SUMO_ATTR_KEY, StringUtils::escapeXML(keyValue.first));
193 55452 : device.writeAttr(SUMO_ATTR_VALUE, StringUtils::escapeXML(keyValue.second));
194 110904 : device.closeTag();
195 : }
196 975621 : }
197 :
198 :
199 : bool
200 0 : Parameterised::areParametersValid(const std::string& value, bool report, const std::string kvsep, const std::string sep) {
201 0 : std::vector<std::string> parameters = StringTokenizer(value, sep).getVector();
202 : // first check if parsed parameters are valid
203 0 : for (const auto& keyValueStr : parameters) {
204 : // check if parameter is valid
205 0 : if (!isParameterValid(keyValueStr, kvsep, sep)) {
206 : // report depending of flag
207 0 : if (report) {
208 0 : WRITE_WARNINGF(TL("Invalid format of parameter (%)"), keyValueStr);
209 : }
210 : return false;
211 : }
212 : }
213 : // all ok, then return true
214 : return true;
215 0 : }
216 :
217 :
218 : bool
219 0 : Parameterised::areAttributesValid(const std::string& value, bool report, const std::string kvsep, const std::string sep) {
220 0 : std::vector<std::string> parameters = StringTokenizer(value, sep).getVector();
221 : // first check if parsed parameters are valid
222 0 : for (const auto& keyValueStr : parameters) {
223 : // check if parameter is valid
224 0 : if (isParameterValid(keyValueStr, kvsep, sep)) {
225 : // separate key and value
226 0 : const auto attr = StringTokenizer(value, kvsep).getVector().front();
227 : // get first letter
228 0 : const auto letter = StringTokenizer(value, kvsep).getVector().front().front();
229 : // check key
230 0 : if (!((letter >= 'a') && (letter <= 'z')) && !((letter >= 'A') && (letter <= 'Z'))) {
231 : // report depending of flag
232 0 : if (report) {
233 0 : 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 0 : if (report) {
240 0 : WRITE_WARNINGF(TL("Invalid format of attribute (%)"), keyValueStr);
241 : }
242 0 : return false;
243 : }
244 : }
245 : // all ok, then return true
246 : return true;
247 0 : }
248 :
249 : // ===========================================================================
250 : // private
251 : // ===========================================================================
252 :
253 : bool
254 0 : Parameterised::isParameterValid(const std::string& value, const std::string& kvsep, const std::string& sep) {
255 0 : if (value.find(sep) != std::string::npos || value.find(kvsep) == std::string::npos) {
256 0 : return false;
257 : }
258 : // separate key and value
259 0 : std::vector<std::string> keyValueStr = StringTokenizer(value, kvsep).getVector();
260 : // Check that keyValue size is exactly 2 (key, value)
261 0 : if (keyValueStr.size() == 2) {
262 : // check if key and value contains valid characters
263 0 : 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 0 : }
274 :
275 : /****************************************************************************/
|