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

randombit / botan / 26995937053

04 Jun 2026 09:38PM UTC coverage: 89.394% (-2.3%) from 91.672%
26995937053

push

github

web-flow
Merge pull request #5642 from randombit/jack/prefetch-in-ks

Improve prefetching for table based implementations

110588 of 123708 relevant lines covered (89.39%)

11056434.37 hits per line

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

91.95
/src/lib/utils/parsing.cpp
1
/*
2
* Various string utils and parsing functions
3
* (C) 1999-2007,2013,2014,2015,2018 Jack Lloyd
4
* (C) 2015 Simon Warta (Kullo GmbH)
5
* (C) 2017 René Korthaus, Rohde & Schwarz Cybersecurity
6
*
7
* Botan is released under the Simplified BSD License (see license.txt)
8
*/
9

10
#include <botan/internal/parsing.h>
11

12
#include <botan/exceptn.h>
13
#include <botan/internal/fmt.h>
14
#include <botan/internal/loadstor.h>
15
#include <concepts>
16
#include <limits>
17
#include <sstream>
18

19
namespace Botan {
20

21
namespace {
22

23
std::optional<size_t> digit_from_ascii(char c) {
789,325✔
24
   if(c >= '0' && c <= '9') {
789,325✔
25
      return c - '0';
789,226✔
26
   } else {
27
      return {};
28
   }
29
}
30

31
template <std::unsigned_integral T>
32
std::optional<T> parse_decimal_integer(std::string_view input) {
376,373✔
33
   if(input.empty() || input.size() > (std::numeric_limits<T>::digits10 + 1)) {
376,373✔
34
      return {};
5✔
35
   }
36

37
   T accum = 0;
376,368✔
38

39
   for(const char c : input) {
1,165,592✔
40
      if(const auto digit = digit_from_ascii(c)) {
789,325✔
41
         if(accum > (std::numeric_limits<T>::max() - static_cast<T>(*digit)) / 10) {
789,226✔
42
            return {};
2✔
43
         }
44
         accum = accum * 10 + static_cast<T>(*digit);
789,224✔
45
      } else {
46
         return {};
99✔
47
      }
48
   }
49

50
   return accum;
376,267✔
51
}
52

53
}  // namespace
54

55
std::optional<uint16_t> parse_u16(std::string_view input) {
439✔
56
   return parse_decimal_integer<uint16_t>(input);
439✔
57
}
58

59
std::optional<uint32_t> parse_u32(std::string_view input) {
374,796✔
60
   return parse_decimal_integer<uint32_t>(input);
374,796✔
61
}
62

63
std::optional<uint64_t> parse_u64(std::string_view input) {
1,080✔
64
   return parse_decimal_integer<uint64_t>(input);
1,080✔
65
}
66

67
std::optional<size_t> parse_sz(std::string_view input) {
58✔
68
   return parse_decimal_integer<size_t>(input);
58✔
69
}
70

71
uint32_t to_u32bit(std::string_view input) {
373,489✔
72
   if(const auto parsed = parse_u32(input)) {
373,489✔
73
      return *parsed;
373,399✔
74
   } else {
75
      throw Invalid_Argument(fmt("Failed to parse input '{}' as a 32-bit integer", input));
180✔
76
   }
77
}
78

79
/*
80
* Parse a SCAN-style algorithm name
81
*/
82
std::vector<std::string> parse_algorithm_name(std::string_view scan_name) {
19,528✔
83
   if(scan_name.find('(') == std::string::npos && scan_name.find(')') == std::string::npos) {
19,528✔
84
      return {std::string(scan_name)};
36,880✔
85
   }
86

87
   std::string name(scan_name);
1,088✔
88
   std::string substring;
1,088✔
89
   std::vector<std::string> elems;
1,088✔
90
   size_t level = 0;
1,088✔
91

92
   elems.push_back(name.substr(0, name.find('(')));
2,176✔
93
   name = name.substr(name.find('('));
1,088✔
94

95
   for(auto i = name.begin(); i != name.end(); ++i) {
4,433✔
96
      const char c = *i;
4,433✔
97

98
      if(c == '(') {
4,433✔
99
         ++level;
1,088✔
100
      }
101
      if(c == ')') {
4,433✔
102
         if(level == 1 && i == name.end() - 1) {
1,088✔
103
            if(elems.size() == 1) {
1,088✔
104
               elems.push_back(substring.substr(1));
1,756✔
105
            } else {
106
               elems.push_back(substring);
210✔
107
            }
108
            return elems;
1,088✔
109
         }
110

111
         if(level == 0 || (level == 1 && i != name.end() - 1)) {
×
112
            throw Invalid_Algorithm_Name(scan_name);
×
113
         }
114
         --level;
×
115
      }
116

117
      if(c == ',' && level == 1) {
3,345✔
118
         if(elems.size() == 1) {
210✔
119
            elems.push_back(substring.substr(1));
420✔
120
         } else {
121
            elems.push_back(substring);
×
122
         }
123
         substring.clear();
210✔
124
      } else {
125
         substring += c;
6,480✔
126
      }
127
   }
128

129
   if(!substring.empty()) {
×
130
      throw Invalid_Algorithm_Name(scan_name);
×
131
   }
132

133
   return elems;
×
134
}
37,968✔
135

136
std::vector<std::string> split_on(std::string_view str, char delim) {
85,168✔
137
   std::vector<std::string> elems;
85,168✔
138
   if(str.empty()) {
85,168✔
139
      return elems;
140
   }
141

142
   std::string substr;
85,041✔
143
   for(const char c : str) {
1,019,329✔
144
      if(c == delim) {
934,288✔
145
         if(!substr.empty()) {
44,691✔
146
            elems.push_back(substr);
44,652✔
147
         }
148
         substr.clear();
44,691✔
149
      } else {
150
         substr += c;
1,823,885✔
151
      }
152
   }
153

154
   if(substr.empty()) {
85,041✔
155
      throw Invalid_Argument(fmt("Unable to split string '{}", str));
2✔
156
   }
157
   elems.push_back(substr);
85,040✔
158

159
   return elems;
85,040✔
160
}
85,041✔
161

162
/*
163
* Join a string
164
*/
165
std::string string_join(const std::vector<std::string>& strs, char delim) {
19✔
166
   std::ostringstream out;
19✔
167

168
   for(size_t i = 0; i != strs.size(); ++i) {
236✔
169
      if(i != 0) {
217✔
170
         out << delim;
198✔
171
      }
172
      out << strs[i];
217✔
173
   }
174

175
   return out.str();
38✔
176
}
19✔
177

178
std::string tolower_string(std::string_view str) {
7,377✔
179
   // Locale-independent ASCII fold; the only callers (DNS name canonicalization
180
   // for SAN/name-constraints) work on ASCII strings per RFC 1035.
181
   std::string lower(str);
7,377✔
182
   for(char& c : lower) {
41,558✔
183
      if(c >= 'A' && c <= 'Z') {
34,181✔
184
         c = static_cast<char>(c + ('a' - 'A'));
20✔
185
      }
186
   }
187
   return lower;
7,377✔
188
}
189

190
}  // namespace Botan
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

© 2026 Coveralls, Inc