Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 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 11557976 : Parameterised::Parameterised() {}
34 :
35 :
36 240434 : Parameterised::Parameterised(const Parameterised::Map& mapArg) :
37 240434 : myMap(mapArg) {
38 240434 : }
39 :
40 :
41 32386875 : Parameterised::~Parameterised() {}
42 :
43 :
44 : void
45 4997568 : Parameterised::setParameter(const std::string& key, const std::string& value) {
46 4997568 : myMap[key] = value;
47 4997568 : }
48 :
49 :
50 : void
51 80805 : Parameterised::unsetParameter(const std::string& key) {
52 : myMap.erase(key);
53 80805 : }
54 :
55 :
56 : void
57 2270881 : Parameterised::updateParameters(const Parameterised::Map& mapArg) {
58 2312598 : for (const auto& keyValue : mapArg) {
59 41717 : setParameter(keyValue.first, keyValue.second);
60 : }
61 2270881 : }
62 :
63 :
64 : void
65 5505 : Parameterised::mergeParameters(const Parameterised::Map& mapArg, const std::string separator, bool uniqueValues) {
66 7210 : for (const auto& keyValue : mapArg) {
67 1705 : if (hasParameter(keyValue.first)) {
68 : bool append = true;
69 883 : if (uniqueValues) {
70 1766 : 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 822 : setParameter(keyValue.first, keyValue.second);
79 : }
80 : }
81 5505 : }
82 :
83 : bool
84 392538936 : Parameterised::hasParameter(const std::string& key) const {
85 392538936 : return myMap.find(key) != myMap.end();
86 : }
87 :
88 :
89 : const std::string
90 6796757 : Parameterised::getParameter(const std::string& key, const std::string defaultValue) const {
91 : const auto i = myMap.find(key);
92 6796757 : if (i != myMap.end()) {
93 : return i->second;
94 : }
95 : return defaultValue;
96 : }
97 :
98 :
99 : double
100 89845 : Parameterised::getDouble(const std::string& key, const double defaultValue) const {
101 : const auto i = myMap.find(key);
102 89845 : if (i != myMap.end()) {
103 : try {
104 3532 : 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 : void
118 1616906 : Parameterised::clearParameter() {
119 : myMap.clear();
120 1616906 : }
121 :
122 :
123 : const Parameterised::Map&
124 8437352 : Parameterised::getParametersMap() const {
125 8437352 : return myMap;
126 : }
127 :
128 :
129 : std::string
130 0 : Parameterised::getParametersStr(const std::string kvsep, const std::string sep) const {
131 : std::string result;
132 : // Generate an string using configurable seperatrs, default: "key1=value1|key2=value2|...|keyN=valueN"
133 : bool addSep = false;
134 0 : for (const auto& keyValue : myMap) {
135 0 : if (addSep) {
136 : result += sep;
137 : }
138 0 : result += keyValue.first + kvsep + keyValue.second;
139 : addSep = true;
140 : }
141 0 : return result;
142 : }
143 :
144 :
145 : void
146 1198239 : Parameterised::setParameters(const Parameterised& params) {
147 1198239 : myMap = params.getParametersMap();
148 1198239 : }
149 :
150 :
151 : void
152 0 : Parameterised::setParameters(const std::vector<std::pair<std::string, std::string> >& params) {
153 : myMap.clear();
154 0 : for (const auto& keyValue : params) {
155 0 : myMap[keyValue.first] = keyValue.second;
156 : }
157 0 : }
158 :
159 :
160 : void
161 773 : Parameterised::setParametersStr(const std::string& paramsString, const std::string kvsep, const std::string sep) {
162 : // clear parameters
163 : myMap.clear();
164 : // separate value in a vector of string using | as separator
165 1546 : std::vector<std::string> parameters = StringTokenizer(paramsString, sep).getVector();
166 : // iterate over all values
167 779 : for (const auto& keyValue : parameters) {
168 : // obtain key and value and save it in myParameters
169 12 : std::vector<std::string> keyValueStr = StringTokenizer(keyValue, kvsep).getVector();
170 6 : setParameter(keyValueStr.front(), keyValueStr.back());
171 6 : }
172 773 : }
173 :
174 :
175 : void
176 1168291 : Parameterised::writeParams(OutputDevice& device) const {
177 : // iterate over all parameters and write it
178 1235720 : for (const auto& keyValue : myMap) {
179 67429 : device.openTag(SUMO_TAG_PARAM);
180 67429 : device.writeAttr(SUMO_ATTR_KEY, StringUtils::escapeXML(keyValue.first));
181 67429 : device.writeAttr(SUMO_ATTR_VALUE, StringUtils::escapeXML(keyValue.second));
182 134858 : device.closeTag();
183 : }
184 1168291 : }
185 :
186 :
187 : bool
188 0 : Parameterised::areParametersValid(const std::string& value, bool report, const std::string kvsep, const std::string sep) {
189 0 : std::vector<std::string> parameters = StringTokenizer(value, sep).getVector();
190 : // first check if parsed parameters are valid
191 0 : for (const auto& keyValueStr : parameters) {
192 : // check if parameter is valid
193 0 : if (!isParameterValid(keyValueStr, kvsep, sep)) {
194 : // report depending of flag
195 0 : if (report) {
196 0 : WRITE_WARNINGF(TL("Invalid format of parameter (%)"), keyValueStr);
197 : }
198 : return false;
199 : }
200 : }
201 : // all ok, then return true
202 : return true;
203 0 : }
204 :
205 :
206 : bool
207 0 : Parameterised::areAttributesValid(const std::string& value, bool report, const std::string kvsep, const std::string sep) {
208 0 : std::vector<std::string> parameters = StringTokenizer(value, sep).getVector();
209 : // first check if parsed parameters are valid
210 0 : for (const auto& keyValueStr : parameters) {
211 : // check if parameter is valid
212 0 : if (isParameterValid(keyValueStr, kvsep, sep)) {
213 : // separate key and value
214 0 : const auto attr = StringTokenizer(value, kvsep).getVector().front();
215 : // get first letter
216 0 : const auto letter = StringTokenizer(value, kvsep).getVector().front().front();
217 : // check key
218 0 : if (!((letter >= 'a') && (letter <= 'z')) && !((letter >= 'A') && (letter <= 'Z'))) {
219 : // report depending of flag
220 0 : if (report) {
221 0 : WRITE_WARNINGF(TL("Invalid format of attribute '%'. Attribute must start with a letter"), attr);
222 : }
223 : return false;
224 : }
225 : } else {
226 : // report depending of flag
227 0 : if (report) {
228 0 : WRITE_WARNINGF(TL("Invalid format of attribute (%)"), keyValueStr);
229 : }
230 0 : return false;
231 : }
232 : }
233 : // all ok, then return true
234 : return true;
235 0 : }
236 :
237 : // ===========================================================================
238 : // private
239 : // ===========================================================================
240 :
241 : bool
242 0 : Parameterised::isParameterValid(const std::string& value, const std::string& kvsep, const std::string& sep) {
243 0 : if (value.find(sep) != std::string::npos || value.find(kvsep) == std::string::npos) {
244 0 : return false;
245 : }
246 : // separate key and value
247 0 : std::vector<std::string> keyValueStr = StringTokenizer(value, kvsep).getVector();
248 : // Check that keyValue size is exactly 2 (key, value)
249 0 : if (keyValueStr.size() == 2) {
250 : // check if key and value contains valid characters
251 0 : if (SUMOXMLDefinitions::isValidParameterKey(keyValueStr.front()) == false) {
252 : return false;
253 : } else {
254 : // key=value valid, then return true
255 : return true;
256 : }
257 : } else {
258 : // invalid format
259 : return false;
260 : }
261 0 : }
262 :
263 : /****************************************************************************/
|