MRPT  2.0.4
string_utils.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "system-precomp.h" // Precompiled headers
11 
12 #include <mrpt/core/format.h>
13 #include <mrpt/system/os.h> // strncmp(),...
15 #include <algorithm>
16 #include <cmath> // abs
17 #include <cstring>
18 #include <deque>
19 #include <vector>
20 
21 using std::string;
22 
23 /*---------------------------------------------------------------
24  lowerCase
25  ---------------------------------------------------------------*/
26 string mrpt::system::lowerCase(const string& str)
27 {
28  string outStr(str);
29 
30  std::transform(
31  outStr.begin(), outStr.end(), // In
32  outStr.begin(), // Out
33  (int (*)(int))tolower);
34  return outStr;
35 }
36 
37 /*---------------------------------------------------------------
38  upperCase
39  ---------------------------------------------------------------*/
40 string mrpt::system::upperCase(const string& str)
41 {
42  string outStr(str);
43  std::transform(
44  outStr.begin(), outStr.end(), // In
45  outStr.begin(), // Out
46  (int (*)(int))toupper);
47  return outStr;
48 }
49 
50 /*---------------------------------------------------------------
51  encodeUTF8
52 
53  Author: Marius Bancila
54  http://www.codeguru.com/cpp/misc/misc/multi-lingualsupport/article.php/c10451/
55 ---------------------------------------------------------------*/
56 #define MASKBITS 0x3F
57 #define MASKBYTE 0x80
58 #define MASK2BYTES 0xC0
59 #define MASK3BYTES 0xE0
60 #define MASK4BYTES 0xF0
61 #define MASK5BYTES 0xF8
62 #define MASK6BYTES 0xFC
63 
65  const std::vector<uint16_t>& input, std::string& output)
66 {
67  output = ""; // output.clear(); VC6...
68  output.reserve(input.size());
69  for (unsigned short i : input)
70  {
71  // 0xxxxxxx
72  if (i < 0x80)
73  {
74  output += (char)i;
75  }
76  // 110xxxxx 10xxxxxx
77  else if (i < 0x800)
78  {
79  output += (char)(MASK2BYTES | i >> 6);
80  output += (char)(MASKBYTE | (i & MASKBITS));
81  }
82  // 1110xxxx 10xxxxxx 10xxxxxx
83  /*else if(input[i] < 0x10000)
84  {
85  output.push_back((char)(MASK3BYTES | input[i] >> 12));
86  output.push_back((char)(MASKBYTE | input[i] >> 6 & MASKBITS));
87  output.push_back((char)(MASKBYTE | input[i] & MASKBITS));
88  }*/
89  }
90 }
91 
92 /*---------------------------------------------------------------
93  decodeUTF8
94 
95  Author: Marius Bancila
96  http://www.codeguru.com/cpp/misc/misc/multi-lingualsupport/article.php/c10451/
97 ---------------------------------------------------------------*/
99  const std::string& input, std::vector<uint16_t>& output)
100 {
101  output.clear();
102  output.reserve(input.size());
103  for (size_t i = 0; i < input.size();)
104  {
105  uint16_t ch = 0;
106 
107  // 1110xxxx 10xxxxxx 10xxxxxx
108  if ((input[i] & MASK3BYTES) == MASK3BYTES)
109  {
110  ch = ((input[i] & 0x0F) << 12) | ((input[i + 1] & MASKBITS) << 6) |
111  (input[i + 2] & MASKBITS);
112  i += 3;
113  }
114  // 110xxxxx 10xxxxxx
115  else if ((input[i] & MASK2BYTES) == MASK2BYTES)
116  {
117  ch = ((input[i] & 0x1F) << 6) | (input[i + 1] & MASKBITS);
118  i += 2;
119  }
120  // 0xxxxxxx
121  else if (uint8_t(input[i]) < MASKBYTE)
122  {
123  ch = input[i];
124  i += 1;
125  }
126  output.push_back(ch);
127  }
128 }
129 
130 /** This function implements formatting with the appropriate SI metric unit
131  prefix:
132  1e-12->'p', 1e-9->'n', 1e-6->'u', 1e-3->'m',
133  1->'',
134  1e3->'K', 1e6->'M', 1e9->'G', 1e12->'T'
135  */
137  const double val, int nDecimalDigits, bool middle_space)
138 {
139  char prefix;
140  double mult;
141  const double aVal = std::abs(val);
142 
143  if (aVal >= 1e12)
144  {
145  mult = 1e-12;
146  prefix = 'T';
147  }
148  else if (aVal >= 1e9)
149  {
150  mult = 1e-9;
151  prefix = 'G';
152  }
153  else if (aVal >= 1e6)
154  {
155  mult = 1e-6;
156  prefix = 'M';
157  }
158  else if (aVal >= 1e3)
159  {
160  mult = 1e-3;
161  prefix = 'K';
162  }
163  else if (aVal >= 1)
164  {
165  mult = 1;
166  prefix = ' ';
167  }
168  else if (aVal >= 1e-3)
169  {
170  mult = 1e+3;
171  prefix = 'm';
172  }
173  else if (aVal >= 1e-6)
174  {
175  mult = 1e+6;
176  prefix = 'u';
177  }
178  else if (aVal >= 1e-9)
179  {
180  mult = 1e+9;
181  prefix = 'n';
182  }
183  else
184  {
185  mult = 1e+12;
186  prefix = 'p';
187  }
188 
189  return mrpt::format(
190  middle_space ? "%.*f %c" : "%.*f%c", nDecimalDigits, val * mult,
191  prefix);
192 }
193 
194 /*---------------------------------------------------------------
195  strtok
196 ---------------------------------------------------------------*/
198  char* str, const char* strDelimit, char** context) noexcept
199 {
200 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
201  // Use a secure version in Visual Studio 2005:
202  return ::strtok_s(str, strDelimit, context);
203 #else
204 #ifdef HAVE_STRTOK_R
205  // POSIX safe version:
206  return ::strtok_r(str, strDelimit, context);
207 #else
208  // Use standard version:
209  return ::strtok(str, strDelimit);
210 #endif
211 #endif
212 }
213 
214 template <class CONTAINER>
216  const std::string& inString, const std::string& inDelimiters,
217  CONTAINER& outTokens, bool skipBlankTokens) noexcept
218 {
219  outTokens.clear();
220 
221  const size_t len = inString.size();
222  bool prev_was_delim = true;
223  std::string cur_token;
224  for (size_t pos = 0; pos <= len; pos++) // the "<=" is intentional!!
225  {
226  char c = '\0';
227  bool cur_is_delim;
228  if (pos == len)
229  {
230  // end of string.
231  cur_is_delim = true;
232  }
233  else
234  {
235  // Regular string char:
236  c = inString[pos];
237  cur_is_delim = (inDelimiters.find(c) != string::npos);
238  }
239  if (cur_is_delim)
240  {
241  if (prev_was_delim)
242  {
243  if (!skipBlankTokens) outTokens.push_back(std::string());
244  }
245  else
246  {
247  outTokens.push_back(cur_token);
248  }
249  cur_token.clear();
250  }
251  else
252  {
253  cur_token.push_back(c);
254  }
255  prev_was_delim = cur_is_delim;
256  }
257 }
258 
259 // Explicit instantiations, to be exported in the library:
260 template void mrpt::system::tokenize<std::deque<std::string>>(
261  const std::string& inString, const std::string& inDelimiters,
262  std::deque<std::string>& outTokens, bool skipBlankTokens) noexcept;
263 template void mrpt::system::tokenize<std::vector<std::string>>(
264  const std::string& inString, const std::string& inDelimiters,
265  std::vector<std::string>& outTokens, bool skipBlankTokens) noexcept;
266 
267 /*---------------------------------------------------------------
268  trim
269 ---------------------------------------------------------------*/
270 std::string mrpt::system::trim(const std::string& str)
271 {
272  if (str.empty())
273  {
274  return std::string();
275  }
276  else
277  {
278  size_t s = str.find_first_not_of(" \t");
279  size_t e = str.find_last_not_of(" \t");
280  if (s == std::string::npos || e == std::string::npos)
281  return std::string();
282  else
283  return str.substr(s, e - s + 1);
284  }
285 }
286 
287 /*---------------------------------------------------------------
288  rightPad
289 ---------------------------------------------------------------*/
291  const std::string& str, const size_t total_len, bool truncate_if_larger)
292 {
293  std::string r = str;
294  if (r.size() < total_len || truncate_if_larger) r.resize(total_len, ' ');
295  return r;
296 }
297 
298 /** Return true if the two strings are equal (case sensitive) \sa StrCmpI */
299 bool mrpt::system::strCmp(const std::string& s1, const std::string& s2)
300 {
301  return !mrpt::system::os::_strcmp(s1.c_str(), s2.c_str());
302 }
303 
304 /** Return true if the two strings are equal (case insensitive) \sa StrCmp */
305 bool mrpt::system::strCmpI(const std::string& s1, const std::string& s2)
306 {
307  return !mrpt::system::os::_strcmpi(s1.c_str(), s2.c_str());
308 }
309 
310 /** Return true if "str" starts with "subStr" (case sensitive) \sa strStartsI
311  */
312 bool mrpt::system::strStarts(const std::string& s1, const std::string& s2)
313 {
315  s1.c_str(), s2.c_str(),
316  s2.size()); // if s1 is shorter it's not a problem
317 }
318 
319 /** Return true if "str" starts with "subStr" (case insensitive) \sa strStarts
320  */
321 bool mrpt::system::strStartsI(const std::string& s1, const std::string& s2)
322 {
324  s1.c_str(), s2.c_str(),
325  s2.size()); // if s1 is shorter it's not a problem
326 }
327 
328 template <typename STRING_LIST>
330  const STRING_LIST& lst, std::string& outText, const std::string& newline)
331 {
332  const size_t lenNL = newline.size();
333 
334  // 1) Compute overall length, including 2 chars per new-line:
335  size_t totalLen = lst.size() * lenNL;
336  for (const auto& s : lst) totalLen += s.size();
337 
338  outText.resize(totalLen);
339 
340  // 2) Copy the text out:
341  size_t curPos = 0;
342  for (const auto& s : lst)
343  {
345  &outText[curPos], totalLen, s.c_str(), s.size());
346  curPos += s.size();
347  for (const auto& sNL : newline) outText[curPos++] = sNL;
348  }
349 }
350 
352  const std::vector<std::string>& lst, std::string& outText,
353  const std::string& newLine)
354 {
355  impl_stringListAsString(lst, outText, newLine);
356 }
357 
359  const std::deque<std::string>& lst, std::string& outText,
360  const std::string& newLine)
361 {
362  impl_stringListAsString(lst, outText, newLine);
363 }
#define MASKBITS
std::string std::string format(std::string_view fmt, ARGS &&... args)
Definition: format.h:26
int _strncmp(const char *str, const char *subStr, size_t count) noexcept
An OS-independent version of strncmp.
Definition: os.cpp:347
bool strStartsI(const std::string &str, const std::string &subStr)
Return true if "str" starts with "subStr" (case insensitive)
int _strnicmp(const char *str, const char *subStr, size_t count) noexcept
An OS-independent version of strnicmp.
Definition: os.cpp:355
void decodeUTF8(const std::string &strUTF8, std::vector< uint16_t > &out_uniStr)
Decodes a UTF-8 string into an UNICODE string.
bool strCmp(const std::string &s1, const std::string &s2)
Return true if the two strings are equal (case sensitive)
void stringListAsString(const std::vector< std::string > &lst, std::string &out, const std::string &newline="\")
Convert a string list to one single string with new-lines.
void encodeUTF8(const std::vector< uint16_t > &input, std::string &output)
Encodes a 2-bytes UNICODE string into a UTF-8 string.
void tokenize(const std::string &inString, const std::string &inDelimiters, OUT_CONTAINER &outTokens, bool skipBlankTokens=true) noexcept
Tokenizes a string according to a set of delimiting characters.
std::string lowerCase(const std::string &str)
Returns an lower-case version of a string.
char * strtok(char *str, const char *strDelimit, char **context) noexcept
An OS-independent method for tokenizing a string.
#define MASK3BYTES
int val
Definition: mrpt_jpeglib.h:957
#define MASKBYTE
std::string unitsFormat(const double val, int nDecimalDigits=2, bool middle_space=true)
This function implements formatting with the appropriate SI metric unit prefix: 1e-12->&#39;p&#39;, 1e-9->&#39;n&#39;, 1e-6->&#39;u&#39;, 1e-3->&#39;m&#39;, 1->&#39;&#39;, 1e3->&#39;K&#39;, 1e6->&#39;M&#39;, 1e9->&#39;G&#39;, 1e12->&#39;T&#39;.
std::string upperCase(const std::string &str)
Returns a upper-case version of a string.
bool strStarts(const std::string &str, const std::string &subStr)
Return true if "str" starts with "subStr" (case sensitive)
std::string trim(const std::string &str)
Removes leading and trailing spaces.
std::string rightPad(const std::string &str, const size_t total_len, bool truncate_if_larger=false)
Enlarge the string with spaces up to the given length.
static void impl_stringListAsString(const STRING_LIST &lst, std::string &outText, const std::string &newline)
bool strCmpI(const std::string &s1, const std::string &s2)
Return true if the two strings are equal (case insensitive)
#define MASK2BYTES
int _strcmp(const char *str1, const char *str2) noexcept
An OS-independent version of strcmp.
Definition: os.cpp:323
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
int _strcmpi(const char *str1, const char *str2) noexcept
An OS-independent version of strcmpi.
Definition: os.cpp:331



Page generated by Doxygen 1.8.14 for MRPT 2.0.4 Git: 33de1d0ad Sat Jun 20 11:02:42 2020 +0200 at sáb jun 20 17:35:17 CEST 2020