• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OpenLightingProject / ola / 11783254300

11 Nov 2024 05:23PM UTC coverage: 45.767% (+0.09%) from 45.677%
11783254300

push

github

web-flow
Merge pull request #1978 from DMXControl/add_nodle_r4s

Add DMXControl Projects e.V. Nodle R4S

7798 of 17938 branches covered (43.47%)

0 of 1 new or added line in 1 file covered. (0.0%)

721 existing lines in 11 files now uncovered.

22344 of 48821 relevant lines covered (45.77%)

64.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.93
/common/utils/StringUtils.cpp
1
/*
2
 * This library is free software; you can redistribute it and/or
3
 * modify it under the terms of the GNU Lesser General Public
4
 * License as published by the Free Software Foundation; either
5
 * version 2.1 of the License, or (at your option) any later version.
6
 *
7
 * This library is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10
 * Lesser General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU Lesser General Public
13
 * License along with this library; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
 *
16
 * StringUtils.cpp
17
 * Random String functions.
18
 * Copyright (C) 2005 Simon Newton
19
 */
20

21
#define __STDC_LIMIT_MACROS  // for UINT8_MAX & friends
22
#include <errno.h>
23
#include <stdint.h>
24
#include <stdlib.h>
25
#include <algorithm>
26
#include <functional>
27
#include <iomanip>
28
#include <iostream>
29
#include <sstream>
30
#include <string>
31
#include <vector>
32
#include "ola/StringUtils.h"
33
#include "ola/base/Macro.h"
34

35
namespace ola {
36

37
using std::endl;
38
using std::ostringstream;
39
using std::string;
40
using std::vector;
41

42
void StringSplit(const string &input,
488✔
43
                 vector<string> *tokens,
44
                 const string &delimiters) {
45
  string::size_type start_offset = 0;
488✔
46
  string::size_type end_offset = 0;
488✔
47

48
  while (1) {
25,832✔
49
    end_offset = input.find_first_of(delimiters, start_offset);
25,832✔
50
    if (end_offset == string::npos) {
25,832✔
51
      tokens->push_back(
976✔
52
          input.substr(start_offset, input.size() - start_offset));
488✔
53
      return;
488✔
54
    }
55
    tokens->push_back(input.substr(start_offset, end_offset - start_offset));
50,688✔
56
    start_offset = (end_offset + 1 > input.size()) ?
25,344✔
57
                   string::npos : (end_offset + 1);
58
  }
59
}
60

61
void StringTrim(string *input) {
63✔
62
  string characters_to_trim = " \n\r\t";
63✔
63
  string::size_type start = input->find_first_not_of(characters_to_trim);
63✔
64
  string::size_type end = input->find_last_not_of(characters_to_trim);
63✔
65

66
  if (start == string::npos) {
63✔
67
    input->clear();
63✔
68
  } else {
69
    *input = input->substr(start, end - start + 1);
64✔
70
  }
71
}
63✔
72

73
void ShortenString(string *input) {
15✔
74
  size_t index = input->find(static_cast<char>(0));
15✔
75
  if (index != string::npos) {
15✔
76
    input->erase(index);
1✔
77
  }
78
}
15✔
79

80
bool StringBeginsWith(const string &s, const string &prefix) {
10✔
81
  if (s.length() >= prefix.length()) {
10✔
82
    return (0 == s.compare(0, prefix.length(), prefix));
10✔
83
  } else {
84
    return false;
85
  }
86
}
87

88
bool StringEndsWith(const string &s, const string &suffix) {
147✔
89
  if (s.length() >= suffix.length()) {
147✔
90
    return
142✔
91
      0 == s.compare(s.length() - suffix.length(), suffix.length(), suffix);
142✔
92
  } else {
93
    return false;
94
  }
95
}
96

97
bool StripPrefix(string *s, const string &prefix) {
5✔
98
  if (StringBeginsWith(*s, prefix)) {
5✔
99
    *s = s->substr(prefix.length());
4✔
100
    return true;
4✔
101
  } else {
102
    return false;
103
  }
104
}
105

106
bool StripSuffix(string *s, const string &suffix) {
116✔
107
  if (StringEndsWith(*s, suffix)) {
116✔
108
    *s = s->substr(0, s->length() - suffix.length());
11✔
109
    return true;
11✔
110
  } else {
111
    return false;
112
  }
113
}
114

115
string IntToHexString(unsigned int i, unsigned int width) {
×
116
  strings::_ToHex<unsigned int> v = strings::_ToHex<unsigned int>(
×
117
      i, static_cast<int>(width), true);
×
118
  ostringstream str;
×
119
  str << v;
×
120
  return str.str();
×
121
}
×
122

123
bool StringToBool(const string &value, bool *output) {
55✔
124
  string lc_value(value);
55✔
125
  ToLower(&lc_value);
55✔
126
  if ((lc_value == "true") || (lc_value == "t") || (lc_value == "1")) {
151✔
127
    *output = true;
11✔
128
    return true;
11✔
129
  } else if ((lc_value == "false") || (lc_value == "f") || (lc_value == "0")) {
96✔
130
    *output = false;
22✔
131
    return true;
22✔
132
  }
133
  return false;
134
}
55✔
135

136
bool StringToBoolTolerant(const string &value, bool *output) {
30✔
137
  if (StringToBool(value, output)) {
30✔
138
    return true;
139
  } else {
140
    string lc_value(value);
18✔
141
    ToLower(&lc_value);
18✔
142
    if ((lc_value == "on") || (lc_value == "enable") ||
33✔
143
        (lc_value == "enabled")) {
13✔
144
      *output = true;
7✔
145
      return true;
7✔
146
    } else if ((lc_value == "off") || (lc_value == "disable") ||
19✔
147
               (lc_value == "disabled")) {
6✔
148
      *output = false;
7✔
149
      return true;
7✔
150
    }
151
  }
14✔
152
  return false;
4✔
153
}
154

155
bool StringToInt(const string &value, uint64_t *output, bool strict) {
369✔
156
  if (value.empty()) {
369✔
157
    return false;
158
  }
159
  char *end_ptr;
363✔
160
  errno = 0;
363✔
161
  unsigned long long l = strtoull(  // NOLINT(runtime/int)
363✔
162
      value.data(), &end_ptr, 10);
163
  if (l == 0 && errno != 0) {
363✔
164
    return false;
165
  }
166
  if (value == end_ptr) {
363✔
167
    return false;
168
  }
169
  if (strict && *end_ptr != 0) {
342✔
170
    return false;
171
  }
172
  if (l > static_cast<unsigned long long>(UINT64_MAX)) {  // NOLINT(runtime/int)
332✔
173
    return false;
174
  }
175
  *output = static_cast<uint64_t>(l);
332✔
176
  return true;
332✔
177
}
178

179
bool StringToInt(const string &value, unsigned int *output, bool strict) {
224✔
180
  uint64_t v;
224✔
181
  if (!StringToInt(value, &v, strict)) {
224✔
182
    return false;
183
  }
184
  if (v > UINT32_MAX) {
202✔
185
    return false;
186
  }
187
  *output = static_cast<unsigned int>(v);
198✔
188
  return true;
198✔
189
}
190

191
bool StringToInt(const string &value, uint16_t *output, bool strict) {
42✔
192
  uint64_t v;
42✔
193
  if (!StringToInt(value, &v, strict)) {
42✔
194
    return false;
195
  }
196
  if (v > UINT16_MAX) {
40✔
197
    return false;
198
  }
199
  *output = static_cast<uint16_t>(v);
36✔
200
  return true;
36✔
201
}
202

203
bool StringToInt(const string &value, uint8_t *output, bool strict) {
98✔
204
  uint64_t v;
98✔
205
  if (!StringToInt(value, &v, strict)) {
98✔
206
    return false;
207
  }
208
  if (v > UINT8_MAX) {
85✔
209
    return false;
210
  }
211
  *output = static_cast<uint8_t>(v);
77✔
212
  return true;
77✔
213
}
214

215
bool StringToInt(const string &value, int64_t *output, bool strict) {
116✔
216
  if (value.empty()) {
116✔
217
    return false;
218
  }
219
  char *end_ptr;
110✔
220
  errno = 0;
110✔
221
  long long l = strtoll(value.data(), &end_ptr, 10);  // NOLINT(runtime/int)
110✔
222
  if (l == 0 && errno != 0) {
110✔
223
    return false;
224
  }
225
  if (value == end_ptr) {
110✔
226
    return false;
227
  }
228
  if (strict && *end_ptr != 0) {
103✔
229
    return false;
230
  }
231
  if (l < INT64_MIN || l > INT64_MAX) {
85✔
232
    return false;
233
  }
234
  *output = static_cast<int64_t>(l);
85✔
235
  return true;
85✔
236
}
237

238
bool StringToInt(const string &value, int *output, bool strict) {
51✔
239
  int64_t v;
51✔
240
  if (!StringToInt(value, &v, strict)) {
51✔
241
    return false;
242
  }
243
  if (v < INT32_MIN || v > INT32_MAX) {
29✔
244
    return false;
245
  }
246
  *output = static_cast<int>(v);
25✔
247
  return true;
25✔
248
}
249

250
bool StringToInt(const string &value, int16_t *output, bool strict) {
30✔
251
  int64_t v;
30✔
252
  if (!StringToInt(value, &v, strict)) {
30✔
253
    return false;
254
  }
255
  if (v < INT16_MIN || v > INT16_MAX) {
26✔
256
    return false;
257
  }
258
  *output = static_cast<int16_t>(v);
22✔
259
  return true;
22✔
260
}
261

262
bool StringToInt(const string &value, int8_t *output, bool strict) {
32✔
263
  int64_t v;
32✔
264
  if (!StringToInt(value, &v, strict)) {
32✔
265
    return false;
266
  }
267
  if (v < INT8_MIN || v > INT8_MAX) {
27✔
268
    return false;
269
  }
270
  *output = static_cast<int8_t>(v);
19✔
271
  return true;
19✔
272
}
273

274
void Escape(string *original) {
739✔
275
  for (string::iterator iter = original->begin(); iter != original->end();
739✔
276
      ++iter) {
6,213✔
277
    switch (*iter) {
5,474✔
278
      case '"':
10✔
279
        iter = original->insert(iter, '\\');
10✔
280
        iter++;
10✔
281
        break;
282
      case '\\':
39✔
283
        iter = original->insert(iter, '\\');
39✔
284
        iter++;
39✔
285
        break;
286
      case '/':
68✔
287
        iter = original->insert(iter, '\\');
68✔
288
        iter++;
68✔
289
        break;
290
      case '\b':
2✔
291
        *iter = 'b';
2✔
292
        iter = original->insert(iter, '\\');
2✔
293
        iter++;
2✔
294
        break;
295
      case '\f':
2✔
296
        *iter = 'f';
2✔
297
        iter = original->insert(iter, '\\');
2✔
298
        iter++;
2✔
299
        break;
300
      case '\n':
3✔
301
        *iter = 'n';
3✔
302
        iter = original->insert(iter, '\\');
3✔
303
        iter++;
3✔
304
        break;
305
      case '\r':
2✔
306
        *iter = 'r';
2✔
307
        iter = original->insert(iter, '\\');
2✔
308
        iter++;
2✔
309
        break;
310
      case '\t':
3✔
311
        *iter = 't';
3✔
312
        iter = original->insert(iter, '\\');
3✔
313
        iter++;
5,474✔
314
        break;
315
      default:
316
        break;
317
    }
318
  }
319
}
739✔
320

321
string EscapeString(const string &original) {
728✔
322
  string result = original;
728✔
323
  Escape(&result);
728✔
324
  return result;
728✔
UNCOV
325
}
×
326

327
string EncodeString(const string &original) {
285✔
328
  ostringstream encoded;
285✔
329
  for (string::const_iterator iter = original.begin();
2,782✔
330
       iter != original.end();
2,782✔
331
       ++iter) {
2,782✔
332
    if (isprint(*iter)) {
2,497✔
333
      encoded << *iter;
2,489✔
334
    } else {
335
      encoded << "\\x"
8✔
336
              << ola::strings::ToHex(static_cast<uint8_t>(*iter), false);
8✔
337
    }
338
  }
339
  return encoded.str();
570✔
340
}
285✔
341

342
void ReplaceAll(string *original, const string &find, const string &replace) {
10✔
343
  if (original->empty() || find.empty()) {
10✔
344
    return;  // No text or nothing to find, so nothing to do
345
  }
346

347
  size_t start = 0;
348
  while ((start = original->find(find, start)) != string::npos) {
19✔
349
    original->replace(start, find.length(), replace);
12✔
350
    // Move to the end of the replaced section
351
    start += ((replace.length() > find.length()) ? replace.length() : 0);
12✔
352
  }
353
}
354

355
bool HexStringToInt(const string &value, uint8_t *output) {
354✔
356
  uint32_t temp;
354✔
357
  if (!HexStringToInt(value, &temp)) {
354✔
358
    return false;
359
  }
360
  if (temp > UINT8_MAX) {
353✔
361
    return false;
362
  }
363
  *output = static_cast<uint8_t>(temp);
353✔
364
  return true;
353✔
365
}
366

367
bool HexStringToInt(const string &value, uint16_t *output) {
24✔
368
  uint32_t temp;
24✔
369
  if (!HexStringToInt(value, &temp)) {
24✔
370
    return false;
371
  }
372
  if (temp > UINT16_MAX) {
19✔
373
    return false;
374
  }
375
  *output = static_cast<uint16_t>(temp);
16✔
376
  return true;
16✔
377
}
378

379
bool HexStringToInt(const string &value, uint32_t *output) {
400✔
380
  if (value.empty()) {
400✔
381
    return false;
382
  }
383

384
  size_t found = value.find_first_not_of("ABCDEFabcdef0123456789");
398✔
385
  if (found != string::npos) {
398✔
386
    return false;
387
  }
388
  *output = strtoul(value.data(), NULL, 16);
389✔
389
  return true;
389✔
390
}
391

392
bool HexStringToInt(const string &value, uint64_t *output) {
1✔
393
  if (value.empty()) {
1✔
394
    return false;
395
  }
396

397
  size_t found = value.find_first_not_of("ABCDEFabcdef0123456789");
1✔
398
  if (found != string::npos) {
1✔
399
    return false;
400
  }
401
  *output = strtoull(value.data(), NULL, 16);
1✔
402
  return true;
1✔
403
}
404

405
bool HexStringToInt(const string &value, int8_t *output) {
18✔
406
  int32_t temp;
18✔
407
  if (!HexStringToInt(value, &temp)) {
18✔
408
    return false;
409
  }
410
  if (temp < 0 || temp > static_cast<int32_t>(UINT8_MAX)) {
13✔
411
    return false;
412
  }
413
  *output = static_cast<int8_t>(temp);
8✔
414
  return true;
8✔
415
}
416

417
bool HexStringToInt(const string &value, int16_t *output) {
18✔
418
  int32_t temp;
18✔
419
  if (!HexStringToInt(value, &temp)) {
18✔
420
    return false;
421
  }
422
  if (temp < 0 || temp > static_cast<int32_t>(UINT16_MAX)) {
13✔
423
    return false;
424
  }
425
  *output = static_cast<int16_t>(temp);
10✔
426
  return true;
10✔
427
}
428

429
bool HexStringToInt(const string &value, int32_t *output) {
57✔
430
  if (value.empty()) {
57✔
431
    return false;
432
  }
433

434
  size_t found = value.find_first_not_of("ABCDEFabcdef0123456789");
53✔
435
  if (found != string::npos) {
53✔
436
    return false;
437
  }
438
  *output = strtoll(value.data(), NULL, 16);
44✔
439
  return true;
44✔
440
}
441

UNCOV
442
bool HexStringToInt(const string &value, int64_t *output) {
×
UNCOV
443
  if (value.empty()) {
×
444
    return false;
445
  }
446

UNCOV
447
  size_t found = value.find_first_not_of("ABCDEFabcdef0123456789");
×
UNCOV
448
  if (found != string::npos) {
×
449
    return false;
450
  }
UNCOV
451
  *output = strtoll(value.data(), NULL, 16);
×
UNCOV
452
  return true;
×
453
}
454

455
void ToLower(string *s) {
192✔
456
  std::transform(s->begin(), s->end(), s->begin(),
192✔
457
                 std::ptr_fun<int, int>(std::tolower));
458
}
192✔
459

460
void ToUpper(string *s) {
5✔
461
  std::transform(s->begin(), s->end(), s->begin(),
5✔
462
                 std::ptr_fun<int, int>(std::toupper));
463
}
5✔
464

465
void CapitalizeLabel(string *s) {
10✔
466
  bool capitalize = true;
10✔
467
  for (string::iterator iter = s->begin(); iter != s->end(); ++iter) {
158✔
468
    switch (*iter) {
148✔
469
      case '-':
21✔
470
        // fall through, also convert to space then capitalize next character
471
        OLA_FALLTHROUGH
21✔
472
      case '_':
21✔
473
        *iter = ' ';
21✔
474
        // fall through, also convert to space then capitalize next character
475
        OLA_FALLTHROUGH
476
      case ' ':
477
        capitalize = true;
478
        break;
479
      default:
127✔
480
        if (capitalize && islower(*iter)) {
127✔
481
          *iter = toupper(*iter);
21✔
482
        }
483
        capitalize = false;
484
    }
485
  }
486
}
10✔
487

488
void CustomCapitalizeLabel(string *s) {
9✔
489
  // Remember to update the Doxygen in include/ola/StringUtils.h too
490
  static const char* const transforms[] = {
9✔
491
    "dhcp",
492
    "dmx",
493
    "dns",
494
    "ip",
495
    "ipv4",  // Should really be IPv4 probably, but better than nothing
496
    "ipv6",  // Should really be IPv6 probably, but better than nothing
497
    "led",
498
    "mdmx",  // City Theatrical, should really be mDMX, but better than nothing
499
    "pdl",
500
    "pid",
501
    "rdm",
502
    "uid",
503
    NULL
504
  };
505
  const size_t size = s->size();
9✔
506
  const char* const *transform = transforms;
9✔
507
  while (*transform) {
117✔
508
    size_t last_match = 0;
108✔
509
    const string ancronym(*transform);
108✔
510
    const size_t ancronym_size = ancronym.size();
108✔
511

512
    while (true) {
121✔
513
      size_t match_position = s->find(ancronym, last_match);
121✔
514
      if (match_position == string::npos) {
121✔
515
        break;
516
      }
517
      last_match = match_position + 1;
13✔
518
      size_t end_position = match_position + ancronym_size;
13✔
519

520
      if ((match_position == 0 || ispunct(s->at(match_position - 1))) &&
26✔
521
          (end_position == size || ispunct(s->at(end_position)))) {
9✔
522
        while (match_position < end_position) {
40✔
523
          s->at(match_position) = toupper(s->at(match_position));
30✔
524
          match_position++;
30✔
525
        }
526
      }
527
    }
528
    transform++;
108✔
529
  }
108✔
530

531
  CapitalizeLabel(s);
9✔
532
}
9✔
533

534
void CapitalizeFirst(string *s) {
2✔
535
  string::iterator iter = s->begin();
2✔
536
  if (islower(*iter)) {
2✔
537
    *iter = toupper(*iter);
1✔
538
  }
539
}
2✔
540
}  // namespace ola
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc