Mantid
Loading...
Searching...
No Matches
ParseKeyValueString.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
9
10#include <QStringList>
11#include <boost/algorithm/string.hpp>
12#include <boost/tokenizer.hpp>
13
14#include <vector>
15
17
18namespace {
19void appendKeyValuePair(const std::pair<std::string, std::string> &kvp, const bool quoteValues,
20 std::ostringstream &resultStream) {
21 if (quoteValues)
22 resultStream << kvp.first << "='" << kvp.second << '\'';
23 else
24 resultStream << kvp.first << "=" << kvp.second;
25}
26
33void trimQuotes(QString &value, const char quote, const char escape) {
34
35 // If size is less than 2, nothing to trim (we must have matching
36 // quotes at start/end)
37 if (value.size() < 2)
38 return;
39
40 // Must have matching start/end quotes to trim
41 if (value.startsWith(quote) && value.endsWith(quote)) {
42
43 // Check the final quote is not escaped by a backslash (the
44 // first character can't be an escape as we've already checked
45 // it's a quote mark)
46 if (value.size() < 3 || value.at(value.size() - 2) != escape) {
47 // Ok, trim it
48 value.remove(0, 1);
49 value.remove(value.size() - 1, 1);
50 }
51 }
52}
53} // unnamed namespace
54
61 // Remember original value
62 const auto valueIn = value;
63
64 // Trim whitespace
65 value = value.trimmed();
66
67 // Trim double/single quotes
68 trimQuotes(value, '"', '\\');
69 trimQuotes(value, '\'', '\\');
70
71 // If trimming was done, recurse to remove any nested quotes/whitespace
72 if (value.size() > 0 && value != valueIn)
74}
75
81void trimWhitespaceQuotesAndEmptyValues(QStringList &values) {
82 for (auto &value : values)
84
85 values.removeAll("");
86}
87
96std::map<std::string, std::string> parseKeyValueString(const std::string &str, const std::string &separator) {
97 /*
98 This is a bad example of using a tokenizer, and
99 Mantid::Kernel::StringTokenizer should
100 ideally be used for this (see LoadProcessedNexus, Fit1D or others for
101 examples)
102
103 The reason we must use boost::tokenizer here is that passing a list of
104 separators is not
105 yet possible with Mantid::Kernel::StringTokenizer.
106 */
107 boost::tokenizer<boost::escaped_list_separator<char>> tok(
108 str, boost::escaped_list_separator<char>("\\", separator, "\"'"));
109 std::map<std::string, std::string> kvp;
110
111 for (const auto &it : tok) {
112 std::vector<std::string> valVec;
113 boost::split(valVec, it, boost::is_any_of("="));
114
115 if (valVec.size() > 1) {
116 // We split on all '='s. The first delimits the key, the rest are assumed
117 // to be part of the value
118 std::string key = valVec[0];
119 // Drop the key from the values vector
120 valVec.begin() = valVec.erase(valVec.begin());
121 // Join the remaining sections,
122 std::string value = boost::algorithm::join(valVec, "=");
123
124 // Remove any unwanted whitespace
125 boost::trim(key);
126 boost::trim(value);
127
128 if (key.empty() || value.empty())
129 throw std::runtime_error("Invalid key value pair, '" + it + "'");
130
131 kvp[key] = value;
132 } else {
133 throw std::runtime_error("Invalid key value pair, '" + it + "'");
134 }
135 }
136 return kvp;
137}
138
147std::map<QString, QString> parseKeyValueQString(const QString &qstr, const std::string &separator) {
148 /*
149 This is a bad example of using a tokenizer, and
150 Mantid::Kernel::StringTokenizer should
151 ideally be used for this (see LoadProcessedNexus, Fit1D or others for
152 examples)
153
154 The reason we must use boost::tokenizer here is that passing a list of
155 separators is not
156 yet possible with Mantid::Kernel::StringTokenizer.
157 */
158 auto str = qstr.toStdString();
159 boost::tokenizer<boost::escaped_list_separator<char>> tok(
160 str, boost::escaped_list_separator<char>("\\", separator, "\"'"));
161 std::map<QString, QString> kvp;
162
163 for (const auto &it : tok) {
164 auto keyValueString = QString::fromStdString(it);
165 auto valVec = keyValueString.split("=");
166
167 if (valVec.size() > 1) {
168 // We split on all '='s. The first delimits the key, the rest are assumed
169 // to be part of the value
170 auto key = valVec[0].trimmed();
171 // Drop the key from the values vector
172 valVec.removeFirst();
173 // Join the remaining sections
174 auto value = valVec.join("=").trimmed();
175
176 if (key.isEmpty() || value.isEmpty())
177 throw std::runtime_error("Invalid key value pair, '" + it + "'");
178
179 kvp[key] = value;
180 } else {
181 throw std::runtime_error("Invalid key value pair, '" + it + "'");
182 }
183 }
184 return kvp;
185}
186
189QString convertMapToString(const std::map<QString, QString> &optionsMap, const char separator, const bool quoteValues) {
190 QString result;
191 bool first = true;
192
193 for (auto &kvp : optionsMap) {
194 if (kvp.second.isEmpty())
195 continue;
196
197 if (!first)
198 result += separator;
199 else
200 first = false;
201
202 const auto key = kvp.first;
203 auto value = kvp.second;
204
205 if (quoteValues)
206 value = "'" + value + "'";
207
208 result += key + "=" + value;
209 }
210
211 return result;
212}
213
216std::string convertMapToString(const std::map<std::string, std::string> &optionsMap, const char separator,
217 const bool quoteValues) {
218 std::string result;
219 bool first = true;
220
221 for (auto &kvp : optionsMap) {
222 if (kvp.second.empty())
223 continue;
224
225 if (!first)
226 result += separator;
227 else
228 first = false;
229
230 const auto key = kvp.first;
231 auto value = kvp.second;
232
233 if (quoteValues)
234 value = "'" + value + "'";
235
236 result += key + "=" + value;
237 }
238
239 return result;
240}
241
242std::string optionsToString(std::map<std::string, std::string> const &options, const bool quoteValues,
243 const std::string &separator) {
244 if (!options.empty()) {
245 std::ostringstream resultStream;
246 auto optionsKvpIt = options.cbegin();
247
248 auto const &firstKvp = (*optionsKvpIt);
249 appendKeyValuePair(firstKvp, quoteValues, resultStream);
250 ++optionsKvpIt;
251
252 for (; optionsKvpIt != options.cend(); ++optionsKvpIt) {
253 auto kvp = (*optionsKvpIt);
254 resultStream << separator;
255 appendKeyValuePair(kvp, quoteValues, resultStream);
256 }
257
258 return resultStream.str();
259 } else {
260 return std::string();
261 }
262}
263
265 auto props = options.getDeclaredPropertyNames();
266 if (props.empty()) {
267 return std::string();
268 }
269 auto result = std::string(props[0] + std::string("=") + options.getPropertyValue(props[0]));
270 return std::accumulate(++props.cbegin(), props.cend(), result, [&options](auto const &result, auto const &prop) {
271 return result + std::string(";") + prop + std::string("=") + options.getPropertyValue(prop);
272 });
273}
274} // namespace MantidQt::MantidWidgets
double value
The value of the point.
Definition: FitMW.cpp:51
virtual std::vector< std::string > getDeclaredPropertyNames() const noexcept=0
Get the list of managed property names.
virtual std::string getPropertyValue(const std::string &name) const =0
Get the value of a property as a string.
QString EXPORT_OPT_MANTIDQT_COMMON convertMapToString(const std::map< QString, QString > &optionsMap, const char separator=',', const bool quoteValues=true)
Convert an options map to a string.
void trimWhitespaceQuotesAndEmptyValues(QStringList &values)
Trim whitespace and quotes from the start/end for all strings in the given list, and subsequently rem...
std::map< std::string, std::string > DLLExport parseKeyValueString(const std::string &str, const std::string &separator=",")
Parses a string in the format ‘a = 1,b=2, c = "1,2,3,4", d = 5.0, e='a,b,c’` into a map of key/value ...
std::map< QString, QString > DLLExport parseKeyValueQString(const QString &str, const std::string &separator=",")
Parses a string in the format ‘a = 1,b=2, c = "1,2,3,4", d = 5.0, e='a,b,c’` into a map of key/value ...
std::string EXPORT_OPT_MANTIDQT_COMMON convertAlgPropsToString(MantidQt::API::IAlgorithmRuntimeProps const &options)
void trimWhitespaceAndQuotes(const QString &valueIn)
std::string EXPORT_OPT_MANTIDQT_COMMON optionsToString(std::map< std::string, std::string > const &options, const bool quoteValues=true, const std::string &separator=", ")