SUMO - Simulation of Urban MObility
StringUtils.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
17 // Some static methods for string processing
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 
26 #include <string>
27 #include <iostream>
28 #include <cstdio>
29 #include <cstring>
30 #include <xercesc/util/TransService.hpp>
31 #include <xercesc/util/TranscodingException.hpp>
33 #include <utils/common/ToString.h>
34 #include "StringUtils.h"
35 
36 
37 // ===========================================================================
38 // static member definitions
39 // ===========================================================================
40 std::string StringUtils::emptyString;
41 
42 
43 // ===========================================================================
44 // method definitions
45 // ===========================================================================
46 std::string
47 StringUtils::prune(const std::string& str) {
48  const std::string::size_type endpos = str.find_last_not_of(" \t\n\r");
49  if (std::string::npos != endpos) {
50  const int startpos = (int)str.find_first_not_of(" \t\n\r");
51  return str.substr(startpos, endpos - startpos + 1);
52  }
53  return "";
54 }
55 
56 
57 std::string
58 StringUtils::to_lower_case(std::string str) {
59  for (int i = 0; i < (int)str.length(); i++) {
60  if (str[i] >= 'A' && str[i] <= 'Z') {
61  str[i] = str[i] + 'a' - 'A';
62  }
63  }
64  return str;
65 }
66 
67 
68 std::string
69 StringUtils::latin1_to_utf8(std::string str) {
70  // inspired by http://stackoverflow.com/questions/4059775/convert-iso-8859-1-strings-to-utf-8-in-c-c
71  std::string result;
72  for (int i = 0; i < (int)str.length(); i++) {
73  const unsigned char c = str[i];
74  if (c < 128) {
75  result += c;
76  } else {
77  result += (char)(0xc2 + (c > 0xbf));
78  result += (char)((c & 0x3f) + 0x80);
79  }
80  }
81  return result;
82 }
83 
84 
85 std::string
86 StringUtils::convertUmlaute(std::string str) {
87  str = replace(str, "\xE4", "ae");
88  str = replace(str, "\xC4", "Ae");
89  str = replace(str, "\xF6", "oe");
90  str = replace(str, "\xD6", "Oe");
91  str = replace(str, "\xFC", "ue");
92  str = replace(str, "\xDC", "Ue");
93  str = replace(str, "\xDF", "ss");
94  str = replace(str, "\xC9", "E");
95  str = replace(str, "\xE9", "e");
96  str = replace(str, "\xC8", "E");
97  str = replace(str, "\xE8", "e");
98  return str;
99 }
100 
101 
102 
103 std::string
104 StringUtils::replace(std::string str, const char* what,
105  const char* by) {
106  const std::string what_tmp(what);
107  const std::string by_tmp(by);
108  std::string::size_type idx = str.find(what);
109  const int what_len = (int)what_tmp.length();
110  if (what_len > 0) {
111  const int by_len = (int)by_tmp.length();
112  while (idx != std::string::npos) {
113  str = str.replace(idx, what_len, by);
114  idx = str.find(what, idx + by_len);
115  }
116  }
117  return str;
118 }
119 
120 
121 std::string
123  std::ostringstream oss;
124  if (time < 0) {
125  oss << "-";
126  time = -time;
127  }
128  char buffer[10];
129  sprintf(buffer, "%02i:", (time / 3600));
130  oss << buffer;
131  time = time % 3600;
132  sprintf(buffer, "%02i:", (time / 60));
133  oss << buffer;
134  time = time % 60;
135  sprintf(buffer, "%02i", time);
136  oss << buffer;
137  return oss.str();
138 }
139 
140 
141 bool
142 StringUtils::startsWith(const std::string& str, const std::string prefix) {
143  return str.compare(0, prefix.length(), prefix) == 0;
144 }
145 
146 
147 bool
148 StringUtils::endsWith(const std::string& str, const std::string suffix) {
149  if (str.length() >= suffix.length()) {
150  return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0;
151  } else {
152  return false;
153  }
154 }
155 
156 
157 std::string
158 StringUtils::escapeXML(const std::string& orig, const bool maskDoubleHyphen) {
159  std::string result = replace(orig, "&", "&amp;");
160  result = replace(result, ">", "&gt;");
161  result = replace(result, "<", "&lt;");
162  result = replace(result, "\"", "&quot;");
163  if (maskDoubleHyphen) {
164  result = replace(result, "--", "&#45;&#45;");
165  }
166  for (char invalid = '\1'; invalid < ' '; invalid++) {
167  result = replace(result, std::string(1, invalid).c_str(), "");
168  }
169  return replace(result, "'", "&apos;");
170 }
171 
172 
173 std::string
174 StringUtils::urlEncode(const std::string& toEncode, const std::string encodeWhich) {
175  std::ostringstream out;
176 
177  for (int i = 0; i < (int)toEncode.length(); ++i) {
178  const char t = toEncode.at(i);
179 
180  if ((encodeWhich != "" && encodeWhich.find(t) == std::string::npos) ||
181  (encodeWhich == "" &&
182  ((t >= 45 && t <= 57) || // hyphen, period, slash, 0-9
183  (t >= 65 && t <= 90) || // A-Z
184  t == 95 || // underscore
185  (t >= 97 && t <= 122) || // a-z
186  t == 126)) // tilde
187  ) {
188  out << toEncode.at(i);
189  } else {
190  out << charToHex(toEncode.at(i));
191  }
192  }
193 
194  return out.str();
195 }
196 
197 
198 std::string
199 StringUtils::urlDecode(const std::string& toDecode) {
200  std::ostringstream out;
201 
202  for (int i = 0; i < (int)toDecode.length(); ++i) {
203  if (toDecode.at(i) == '%') {
204  std::string str(toDecode.substr(i + 1, 2));
205  out << hexToChar(str);
206  i += 2;
207  } else {
208  out << toDecode.at(i);
209  }
210  }
211 
212  return out.str();
213 }
214 
215 std::string
216 StringUtils::charToHex(unsigned char c) {
217  short i = c;
218 
219  std::stringstream s;
220 
221  s << "%" << std::setw(2) << std::setfill('0') << std::hex << i;
222 
223  return s.str();
224 }
225 
226 
227 unsigned char
228 StringUtils::hexToChar(const std::string& str) {
229  short c = 0;
230 
231  if (!str.empty()) {
232  std::istringstream in(str);
233 
234  in >> std::hex >> c;
235 
236  if (in.fail()) {
237  throw std::runtime_error("stream decode failure");
238  }
239  }
240 
241  return static_cast<unsigned char>(c);
242 }
243 
244 
245 int
246 StringUtils::toInt(const std::string& sData) {
247  long long int result = toLong(sData);
248  if (result > std::numeric_limits<int>::max() || result < std::numeric_limits<int>::min()) {
249  throw NumberFormatException(toString(result) + " int overflow");
250  }
251  return (int)result;
252 }
253 
254 
255 int
256 StringUtils::toIntSecure(const std::string& sData, int def) {
257  if (sData.length() == 0) {
258  return def;
259  }
260  return toInt(sData);
261 }
262 
263 
264 long long int
265 StringUtils::toLong(const std::string& sData) {
266  const char* const data = sData.c_str();
267  if (data == 0 || data[0] == 0) {
268  throw EmptyData();
269  }
270  char* end;
271 #ifdef _MSC_VER
272  long long int ret = _strtoi64(data, &end, 10);
273 #else
274  long long int ret = strtoll(data, &end, 10);
275 #endif
276  if (errno == ERANGE) {
277  errno = 0;
278  throw NumberFormatException("(long long integer range) " + sData);
279  }
280  if ((int)(end - data) != (int)strlen(data)) {
281  throw NumberFormatException("(long long integer format) " + sData);
282  }
283  return ret;
284 }
285 
286 
287 int
288 StringUtils::hexToInt(const std::string& sData) {
289  if (sData.length() == 0) {
290  throw EmptyData();
291  }
292  size_t idx = 0;
293  int result;
294  try {
295  if (sData[0] == '#') { // for html color codes
296  result = std::stoi(sData.substr(1), &idx, 16);
297  idx++;
298  } else {
299  result = std::stoi(sData, &idx, 16);
300  }
301  } catch (...) {
302  throw NumberFormatException("(hex integer format) " + sData);
303  }
304  if (idx != sData.length()) {
305  throw NumberFormatException("(hex integer format) " + sData);
306  }
307  return result;
308 }
309 
310 
311 double
312 StringUtils::toDouble(const std::string& sData) {
313  if (sData.size() == 0) {
314  throw EmptyData();
315  }
316  try {
317  size_t idx = 0;
318  const double result = std::stod(sData, &idx);
319  if (idx != sData.size()) {
320  throw NumberFormatException("(double format) " + sData);
321  } else {
322  return result;
323  }
324  } catch (...) {
325  // invalid_argument or out_of_range
326  throw NumberFormatException("(double) " + sData);
327  }
328 }
329 
330 
331 double
332 StringUtils::toDoubleSecure(const std::string& sData, const double def) {
333  if (sData.length() == 0) {
334  return def;
335  }
336  return toDouble(sData);
337 }
338 
339 
340 bool
341 StringUtils::toBool(const std::string& sData) {
342  if (sData.length() == 0) {
343  throw EmptyData();
344  }
345  std::string s = sData;
346  // Don't use std::transform(..., ::tolower) due a C4244 Warning in MSVC17
347  for (int i = 0; i < (int)s.length(); i++) {
348  s[i] = (char)::tolower((char)s[i]);
349  }
350  if (s == "1" || s == "yes" || s == "true" || s == "on" || s == "x" || s == "t") {
351  return true;
352  } else if (s == "0" || s == "no" || s == "false" || s == "off" || s == "-" || s == "f") {
353  return false;
354  } else {
355  throw BoolFormatException(s);
356  }
357 }
358 
359 
360 std::string
361 StringUtils::transcode(const XMLCh* const data, int length) {
362  if (data == 0) {
363  throw EmptyData();
364  }
365  if (length == 0) {
366  return "";
367  }
368 #if _XERCES_VERSION < 30100
369  char* t = XERCES_CPP_NAMESPACE::XMLString::transcode(data);
370  std::string result(t);
371  XERCES_CPP_NAMESPACE::XMLString::release(&t);
372  return result;
373 #else
374  try {
375  XERCES_CPP_NAMESPACE::TranscodeToStr utf8(data, "UTF-8");
376  return reinterpret_cast<const char*>(utf8.str());
377  } catch (XERCES_CPP_NAMESPACE::TranscodingException&) {
378  return "?";
379  }
380 #endif
381 }
382 
383 
384 /****************************************************************************/
static unsigned char hexToChar(const std::string &str)
static bool endsWith(const std::string &str, const std::string suffix)
Checks whether a given string ends with the suffix.
static int toIntSecure(const std::string &sData, int def)
converts a string into the integer value described by it
static std::string toTimeString(int time)
Builds a time string (hh:mm:ss) from the given seconds.
static std::string latin1_to_utf8(std::string str)
Transfers from Latin 1 (ISO-8859-1) to UTF-8.
Definition: StringUtils.cpp:69
static std::string urlEncode(const std::string &url, const std::string encodeWhich="")
static bool toBool(const std::string &sData)
converts a string into the bool value described by it by calling the char-type converter ...
static std::string transcode(const XMLCh *const data)
converts a 0-terminated XMLCh* array (usually UTF-16, stemming from Xerces) into std::string in UTF-8...
Definition: StringUtils.h:133
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter ...
static int toInt(const std::string &sData)
converts a string into the integer 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.
static std::string convertUmlaute(std::string str)
Converts german "Umlaute" to their latin-version.
Definition: StringUtils.cpp:86
static std::string emptyString
An empty string.
Definition: StringUtils.h:80
static std::string replace(std::string str, const char *what, const char *by)
static std::string to_lower_case(std::string str)
Transfers the content to lower case.
Definition: StringUtils.cpp:58
static std::string prune(const std::string &str)
Removes trailing and leading whitechars.
Definition: StringUtils.cpp:47
static long long int toLong(const std::string &sData)
converts a string into the long value described by it by calling the char-type converter, which
static std::string urlDecode(const std::string &encoded)
static std::string charToHex(unsigned char c)
static double toDoubleSecure(const std::string &sData, const double def)
converts a string into the integer value described by it
static int hexToInt(const std::string &sData)
converts a string with a hex value into the integer value described by it by calling the char-type co...