blob: 364eaa0f0ffc76aef623ac1dc9f214bb4ff0c768 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:261/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Steve Anton10542f22019-01-11 17:11:0011#include "rtc_base/string_encode.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2612
Yves Gerey988cc082018-10-23 10:03:0113#include <cstdio>
14
Jonas Olsson6b1985d2018-07-05 09:59:4815#include "rtc_base/arraysize.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3116#include "rtc_base/checks.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2617
18namespace rtc {
19
20/////////////////////////////////////////////////////////////////////////////
21// String Encoding Utilities
22/////////////////////////////////////////////////////////////////////////////
23
Niels Möllere7e36012019-05-23 10:10:2624namespace {
25const char HEX[] = "0123456789abcdef";
henrike@webrtc.orgf0488722014-05-13 18:00:2626
Niels Möllere7e36012019-05-23 10:10:2627// Convert an unsigned value from 0 to 15 to the hex character equivalent...
henrike@webrtc.orgf0488722014-05-13 18:00:2628char hex_encode(unsigned char val) {
henrikg91d6ede2015-09-17 07:24:3429 RTC_DCHECK_LT(val, 16);
henrike@webrtc.orgf0488722014-05-13 18:00:2630 return (val < 16) ? HEX[val] : '!';
31}
32
Niels Möllere7e36012019-05-23 10:10:2633// ...and vice-versa.
henrike@webrtc.orgf0488722014-05-13 18:00:2634bool hex_decode(char ch, unsigned char* val) {
35 if ((ch >= '0') && (ch <= '9')) {
36 *val = ch - '0';
Niels Möller12048c72018-10-29 11:58:4837 } else if ((ch >= 'A') && (ch <= 'F')) {
henrike@webrtc.orgf0488722014-05-13 18:00:2638 *val = (ch - 'A') + 10;
Niels Möller12048c72018-10-29 11:58:4839 } else if ((ch >= 'a') && (ch <= 'f')) {
henrike@webrtc.orgf0488722014-05-13 18:00:2640 *val = (ch - 'a') + 10;
41 } else {
42 return false;
43 }
44 return true;
45}
46
Niels Möllerf25df352019-05-24 07:14:1347size_t hex_encode_output_length(size_t srclen, char delimiter) {
48 return delimiter && srclen > 0 ? (srclen * 3 - 1) : (srclen * 2);
49}
50
51// hex_encode shows the hex representation of binary data in ascii, with
Artem Titov96e3b992021-07-26 14:03:1452// `delimiter` between bytes, or none if `delimiter` == 0.
Niels Möllerf25df352019-05-24 07:14:1353void hex_encode_with_delimiter(char* buffer,
54 const char* csource,
55 size_t srclen,
56 char delimiter) {
57 RTC_DCHECK(buffer);
henrike@webrtc.orgf0488722014-05-13 18:00:2658
59 // Init and check bounds.
60 const unsigned char* bsource =
61 reinterpret_cast<const unsigned char*>(csource);
62 size_t srcpos = 0, bufpos = 0;
henrike@webrtc.orgf0488722014-05-13 18:00:2663
64 while (srcpos < srclen) {
65 unsigned char ch = bsource[srcpos++];
Yves Gerey665174f2018-06-19 13:03:0566 buffer[bufpos] = hex_encode((ch >> 4) & 0xF);
67 buffer[bufpos + 1] = hex_encode((ch)&0xF);
henrike@webrtc.orgf0488722014-05-13 18:00:2668 bufpos += 2;
69
70 // Don't write a delimiter after the last byte.
71 if (delimiter && (srcpos < srclen)) {
72 buffer[bufpos] = delimiter;
73 ++bufpos;
74 }
75 }
henrike@webrtc.orgf0488722014-05-13 18:00:2676}
77
Niels Möllere7e36012019-05-23 10:10:2678} // namespace
79
Peter Thatcher1cf6f812015-05-15 17:40:4580std::string hex_encode(const std::string& str) {
81 return hex_encode(str.c_str(), str.size());
82}
83
henrike@webrtc.orgf0488722014-05-13 18:00:2684std::string hex_encode(const char* source, size_t srclen) {
85 return hex_encode_with_delimiter(source, srclen, 0);
86}
87
Yves Gerey665174f2018-06-19 13:03:0588std::string hex_encode_with_delimiter(const char* source,
89 size_t srclen,
henrike@webrtc.orgf0488722014-05-13 18:00:2690 char delimiter) {
Niels Möllerf25df352019-05-24 07:14:1391 std::string s(hex_encode_output_length(srclen, delimiter), 0);
Kimmo Kinnunen022a7c82019-08-29 13:22:3992 hex_encode_with_delimiter(&s[0], source, srclen, delimiter);
Niels Möllerf25df352019-05-24 07:14:1393 return s;
henrike@webrtc.orgf0488722014-05-13 18:00:2694}
95
Yves Gerey665174f2018-06-19 13:03:0596size_t hex_decode(char* cbuffer,
97 size_t buflen,
98 const char* source,
99 size_t srclen) {
henrike@webrtc.orgf0488722014-05-13 18:00:26100 return hex_decode_with_delimiter(cbuffer, buflen, source, srclen, 0);
101}
102
Yves Gerey665174f2018-06-19 13:03:05103size_t hex_decode_with_delimiter(char* cbuffer,
104 size_t buflen,
105 const char* source,
106 size_t srclen,
henrike@webrtc.orgf0488722014-05-13 18:00:26107 char delimiter) {
Henrik Grunell84879882018-03-23 14:33:03108 RTC_DCHECK(cbuffer); // TODO(kwiberg): estimate output size
henrike@webrtc.orgf0488722014-05-13 18:00:26109 if (buflen == 0)
110 return 0;
111
112 // Init and bounds check.
113 unsigned char* bbuffer = reinterpret_cast<unsigned char*>(cbuffer);
114 size_t srcpos = 0, bufpos = 0;
115 size_t needed = (delimiter) ? (srclen + 1) / 3 : srclen / 2;
116 if (buflen < needed)
117 return 0;
118
119 while (srcpos < srclen) {
120 if ((srclen - srcpos) < 2) {
121 // This means we have an odd number of bytes.
122 return 0;
123 }
124
125 unsigned char h1, h2;
126 if (!hex_decode(source[srcpos], &h1) ||
127 !hex_decode(source[srcpos + 1], &h2))
128 return 0;
129
130 bbuffer[bufpos++] = (h1 << 4) | h2;
131 srcpos += 2;
132
133 // Remove the delimiter if needed.
134 if (delimiter && (srclen - srcpos) > 1) {
135 if (source[srcpos] != delimiter)
136 return 0;
137 ++srcpos;
138 }
139 }
140
141 return bufpos;
142}
143
144size_t hex_decode(char* buffer, size_t buflen, const std::string& source) {
145 return hex_decode_with_delimiter(buffer, buflen, source, 0);
146}
Yves Gerey665174f2018-06-19 13:03:05147size_t hex_decode_with_delimiter(char* buffer,
148 size_t buflen,
149 const std::string& source,
150 char delimiter) {
151 return hex_decode_with_delimiter(buffer, buflen, source.c_str(),
152 source.length(), delimiter);
henrike@webrtc.orgf0488722014-05-13 18:00:26153}
154
Niels Möller44203802021-09-16 13:39:16155size_t tokenize(absl::string_view source,
Yves Gerey665174f2018-06-19 13:03:05156 char delimiter,
henrike@webrtc.orgf0488722014-05-13 18:00:26157 std::vector<std::string>* fields) {
henrike@webrtc.orgf0488722014-05-13 18:00:26158 fields->clear();
159 size_t last = 0;
160 for (size_t i = 0; i < source.length(); ++i) {
161 if (source[i] == delimiter) {
162 if (i != last) {
Niels Möller44203802021-09-16 13:39:16163 fields->emplace_back(source.substr(last, i - last));
henrike@webrtc.orgf0488722014-05-13 18:00:26164 }
165 last = i + 1;
166 }
167 }
168 if (last != source.length()) {
Niels Möller44203802021-09-16 13:39:16169 fields->emplace_back(source.substr(last, source.length() - last));
henrike@webrtc.orgf0488722014-05-13 18:00:26170 }
171 return fields->size();
172}
173
Niels Möller44203802021-09-16 13:39:16174bool tokenize_first(absl::string_view source,
Donald Curtis144d0182015-05-15 20:14:24175 const char delimiter,
176 std::string* token,
177 std::string* rest) {
Donald Curtis0e07f922015-05-15 16:21:23178 // Find the first delimiter
179 size_t left_pos = source.find(delimiter);
180 if (left_pos == std::string::npos) {
181 return false;
182 }
183
184 // Look for additional occurrances of delimiter.
185 size_t right_pos = left_pos + 1;
Niels Möller44203802021-09-16 13:39:16186 while (right_pos < source.size() && source[right_pos] == delimiter) {
Donald Curtis0e07f922015-05-15 16:21:23187 right_pos++;
188 }
189
Niels Möller44203802021-09-16 13:39:16190 *token = std::string(source.substr(0, left_pos));
191 *rest = std::string(source.substr(right_pos));
Donald Curtis0e07f922015-05-15 16:21:23192 return true;
193}
194
Diogo Real7bd1f1b2017-09-08 19:50:41195std::string join(const std::vector<std::string>& source, char delimiter) {
196 if (source.size() == 0) {
197 return std::string();
198 }
199 // Find length of the string to be returned to pre-allocate memory.
200 size_t source_string_length = 0;
201 for (size_t i = 0; i < source.size(); ++i) {
202 source_string_length += source[i].length();
203 }
204
205 // Build the joined string.
206 std::string joined_string;
207 joined_string.reserve(source_string_length + source.size() - 1);
208 for (size_t i = 0; i < source.size(); ++i) {
209 if (i != 0) {
210 joined_string += delimiter;
211 }
212 joined_string += source[i];
213 }
214 return joined_string;
215}
216
Niels Möller44203802021-09-16 13:39:16217size_t split(absl::string_view source,
Yves Gerey665174f2018-06-19 13:03:05218 char delimiter,
henrike@webrtc.orgf0488722014-05-13 18:00:26219 std::vector<std::string>* fields) {
henrikg91d6ede2015-09-17 07:24:34220 RTC_DCHECK(fields);
henrike@webrtc.orgf0488722014-05-13 18:00:26221 fields->clear();
222 size_t last = 0;
223 for (size_t i = 0; i < source.length(); ++i) {
224 if (source[i] == delimiter) {
Niels Möller44203802021-09-16 13:39:16225 fields->emplace_back(source.substr(last, i - last));
henrike@webrtc.orgf0488722014-05-13 18:00:26226 last = i + 1;
227 }
228 }
Niels Möller44203802021-09-16 13:39:16229 fields->emplace_back(source.substr(last));
henrike@webrtc.orgf0488722014-05-13 18:00:26230 return fields->size();
231}
232
Jonas Olsson6b1985d2018-07-05 09:59:48233std::string ToString(const bool b) {
234 return b ? "true" : "false";
235}
236
237std::string ToString(const char* const s) {
238 return std::string(s);
239}
240std::string ToString(const std::string s) {
241 return s;
242}
243
244std::string ToString(const short s) {
245 char buf[32];
246 const int len = std::snprintf(&buf[0], arraysize(buf), "%hd", s);
247 RTC_DCHECK_LE(len, arraysize(buf));
248 return std::string(&buf[0], len);
249}
250std::string ToString(const unsigned short s) {
251 char buf[32];
252 const int len = std::snprintf(&buf[0], arraysize(buf), "%hu", s);
253 RTC_DCHECK_LE(len, arraysize(buf));
254 return std::string(&buf[0], len);
255}
256std::string ToString(const int s) {
257 char buf[32];
258 const int len = std::snprintf(&buf[0], arraysize(buf), "%d", s);
259 RTC_DCHECK_LE(len, arraysize(buf));
260 return std::string(&buf[0], len);
261}
262std::string ToString(const unsigned int s) {
263 char buf[32];
264 const int len = std::snprintf(&buf[0], arraysize(buf), "%u", s);
265 RTC_DCHECK_LE(len, arraysize(buf));
266 return std::string(&buf[0], len);
267}
268std::string ToString(const long int s) {
269 char buf[32];
270 const int len = std::snprintf(&buf[0], arraysize(buf), "%ld", s);
271 RTC_DCHECK_LE(len, arraysize(buf));
272 return std::string(&buf[0], len);
273}
274std::string ToString(const unsigned long int s) {
275 char buf[32];
276 const int len = std::snprintf(&buf[0], arraysize(buf), "%lu", s);
277 RTC_DCHECK_LE(len, arraysize(buf));
278 return std::string(&buf[0], len);
279}
280std::string ToString(const long long int s) {
281 char buf[32];
282 const int len = std::snprintf(&buf[0], arraysize(buf), "%lld", s);
283 RTC_DCHECK_LE(len, arraysize(buf));
284 return std::string(&buf[0], len);
285}
286std::string ToString(const unsigned long long int s) {
287 char buf[32];
288 const int len = std::snprintf(&buf[0], arraysize(buf), "%llu", s);
289 RTC_DCHECK_LE(len, arraysize(buf));
290 return std::string(&buf[0], len);
291}
292
293std::string ToString(const double d) {
294 char buf[32];
295 const int len = std::snprintf(&buf[0], arraysize(buf), "%g", d);
296 RTC_DCHECK_LE(len, arraysize(buf));
297 return std::string(&buf[0], len);
298}
299
Jonas Olsson88e18482018-09-03 08:15:08300std::string ToString(const long double d) {
301 char buf[32];
302 const int len = std::snprintf(&buf[0], arraysize(buf), "%Lg", d);
303 RTC_DCHECK_LE(len, arraysize(buf));
304 return std::string(&buf[0], len);
305}
306
Jonas Olsson6b1985d2018-07-05 09:59:48307std::string ToString(const void* const p) {
308 char buf[32];
309 const int len = std::snprintf(&buf[0], arraysize(buf), "%p", p);
310 RTC_DCHECK_LE(len, arraysize(buf));
311 return std::string(&buf[0], len);
312}
313
314bool FromString(const std::string& s, bool* b) {
315 if (s == "false") {
316 *b = false;
317 return true;
318 }
319 if (s == "true") {
320 *b = true;
321 return true;
322 }
323 return false;
324}
325
henrike@webrtc.orgf0488722014-05-13 18:00:26326} // namespace rtc