1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_encode.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <cstdio>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
16*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
17*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/arraysize.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
19*d9f75844SAndroid Build Coastguard Worker
20*d9f75844SAndroid Build Coastguard Worker namespace rtc {
21*d9f75844SAndroid Build Coastguard Worker
22*d9f75844SAndroid Build Coastguard Worker /////////////////////////////////////////////////////////////////////////////
23*d9f75844SAndroid Build Coastguard Worker // String Encoding Utilities
24*d9f75844SAndroid Build Coastguard Worker /////////////////////////////////////////////////////////////////////////////
25*d9f75844SAndroid Build Coastguard Worker
26*d9f75844SAndroid Build Coastguard Worker namespace {
27*d9f75844SAndroid Build Coastguard Worker const char HEX[] = "0123456789abcdef";
28*d9f75844SAndroid Build Coastguard Worker
29*d9f75844SAndroid Build Coastguard Worker // Convert an unsigned value from 0 to 15 to the hex character equivalent...
hex_encode(unsigned char val)30*d9f75844SAndroid Build Coastguard Worker char hex_encode(unsigned char val) {
31*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LT(val, 16);
32*d9f75844SAndroid Build Coastguard Worker return (val < 16) ? HEX[val] : '!';
33*d9f75844SAndroid Build Coastguard Worker }
34*d9f75844SAndroid Build Coastguard Worker
35*d9f75844SAndroid Build Coastguard Worker // ...and vice-versa.
hex_decode(char ch,unsigned char * val)36*d9f75844SAndroid Build Coastguard Worker bool hex_decode(char ch, unsigned char* val) {
37*d9f75844SAndroid Build Coastguard Worker if ((ch >= '0') && (ch <= '9')) {
38*d9f75844SAndroid Build Coastguard Worker *val = ch - '0';
39*d9f75844SAndroid Build Coastguard Worker } else if ((ch >= 'A') && (ch <= 'F')) {
40*d9f75844SAndroid Build Coastguard Worker *val = (ch - 'A') + 10;
41*d9f75844SAndroid Build Coastguard Worker } else if ((ch >= 'a') && (ch <= 'f')) {
42*d9f75844SAndroid Build Coastguard Worker *val = (ch - 'a') + 10;
43*d9f75844SAndroid Build Coastguard Worker } else {
44*d9f75844SAndroid Build Coastguard Worker return false;
45*d9f75844SAndroid Build Coastguard Worker }
46*d9f75844SAndroid Build Coastguard Worker return true;
47*d9f75844SAndroid Build Coastguard Worker }
48*d9f75844SAndroid Build Coastguard Worker
hex_encode_output_length(size_t srclen,char delimiter)49*d9f75844SAndroid Build Coastguard Worker size_t hex_encode_output_length(size_t srclen, char delimiter) {
50*d9f75844SAndroid Build Coastguard Worker return delimiter && srclen > 0 ? (srclen * 3 - 1) : (srclen * 2);
51*d9f75844SAndroid Build Coastguard Worker }
52*d9f75844SAndroid Build Coastguard Worker
53*d9f75844SAndroid Build Coastguard Worker // hex_encode shows the hex representation of binary data in ascii, with
54*d9f75844SAndroid Build Coastguard Worker // `delimiter` between bytes, or none if `delimiter` == 0.
hex_encode_with_delimiter(char * buffer,absl::string_view source,char delimiter)55*d9f75844SAndroid Build Coastguard Worker void hex_encode_with_delimiter(char* buffer,
56*d9f75844SAndroid Build Coastguard Worker absl::string_view source,
57*d9f75844SAndroid Build Coastguard Worker char delimiter) {
58*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(buffer);
59*d9f75844SAndroid Build Coastguard Worker
60*d9f75844SAndroid Build Coastguard Worker // Init and check bounds.
61*d9f75844SAndroid Build Coastguard Worker const unsigned char* bsource =
62*d9f75844SAndroid Build Coastguard Worker reinterpret_cast<const unsigned char*>(source.data());
63*d9f75844SAndroid Build Coastguard Worker size_t srcpos = 0, bufpos = 0;
64*d9f75844SAndroid Build Coastguard Worker
65*d9f75844SAndroid Build Coastguard Worker size_t srclen = source.length();
66*d9f75844SAndroid Build Coastguard Worker while (srcpos < srclen) {
67*d9f75844SAndroid Build Coastguard Worker unsigned char ch = bsource[srcpos++];
68*d9f75844SAndroid Build Coastguard Worker buffer[bufpos] = hex_encode((ch >> 4) & 0xF);
69*d9f75844SAndroid Build Coastguard Worker buffer[bufpos + 1] = hex_encode((ch)&0xF);
70*d9f75844SAndroid Build Coastguard Worker bufpos += 2;
71*d9f75844SAndroid Build Coastguard Worker
72*d9f75844SAndroid Build Coastguard Worker // Don't write a delimiter after the last byte.
73*d9f75844SAndroid Build Coastguard Worker if (delimiter && (srcpos < srclen)) {
74*d9f75844SAndroid Build Coastguard Worker buffer[bufpos] = delimiter;
75*d9f75844SAndroid Build Coastguard Worker ++bufpos;
76*d9f75844SAndroid Build Coastguard Worker }
77*d9f75844SAndroid Build Coastguard Worker }
78*d9f75844SAndroid Build Coastguard Worker }
79*d9f75844SAndroid Build Coastguard Worker
80*d9f75844SAndroid Build Coastguard Worker } // namespace
81*d9f75844SAndroid Build Coastguard Worker
hex_encode(absl::string_view str)82*d9f75844SAndroid Build Coastguard Worker std::string hex_encode(absl::string_view str) {
83*d9f75844SAndroid Build Coastguard Worker return hex_encode_with_delimiter(str, 0);
84*d9f75844SAndroid Build Coastguard Worker }
85*d9f75844SAndroid Build Coastguard Worker
hex_encode_with_delimiter(absl::string_view source,char delimiter)86*d9f75844SAndroid Build Coastguard Worker std::string hex_encode_with_delimiter(absl::string_view source,
87*d9f75844SAndroid Build Coastguard Worker char delimiter) {
88*d9f75844SAndroid Build Coastguard Worker std::string s(hex_encode_output_length(source.length(), delimiter), 0);
89*d9f75844SAndroid Build Coastguard Worker hex_encode_with_delimiter(&s[0], source, delimiter);
90*d9f75844SAndroid Build Coastguard Worker return s;
91*d9f75844SAndroid Build Coastguard Worker }
92*d9f75844SAndroid Build Coastguard Worker
hex_decode_with_delimiter(ArrayView<char> cbuffer,absl::string_view source,char delimiter)93*d9f75844SAndroid Build Coastguard Worker size_t hex_decode_with_delimiter(ArrayView<char> cbuffer,
94*d9f75844SAndroid Build Coastguard Worker absl::string_view source,
95*d9f75844SAndroid Build Coastguard Worker char delimiter) {
96*d9f75844SAndroid Build Coastguard Worker if (cbuffer.empty())
97*d9f75844SAndroid Build Coastguard Worker return 0;
98*d9f75844SAndroid Build Coastguard Worker
99*d9f75844SAndroid Build Coastguard Worker // Init and bounds check.
100*d9f75844SAndroid Build Coastguard Worker unsigned char* bbuffer = reinterpret_cast<unsigned char*>(cbuffer.data());
101*d9f75844SAndroid Build Coastguard Worker size_t srcpos = 0, bufpos = 0;
102*d9f75844SAndroid Build Coastguard Worker size_t srclen = source.length();
103*d9f75844SAndroid Build Coastguard Worker
104*d9f75844SAndroid Build Coastguard Worker size_t needed = (delimiter) ? (srclen + 1) / 3 : srclen / 2;
105*d9f75844SAndroid Build Coastguard Worker if (cbuffer.size() < needed)
106*d9f75844SAndroid Build Coastguard Worker return 0;
107*d9f75844SAndroid Build Coastguard Worker
108*d9f75844SAndroid Build Coastguard Worker while (srcpos < srclen) {
109*d9f75844SAndroid Build Coastguard Worker if ((srclen - srcpos) < 2) {
110*d9f75844SAndroid Build Coastguard Worker // This means we have an odd number of bytes.
111*d9f75844SAndroid Build Coastguard Worker return 0;
112*d9f75844SAndroid Build Coastguard Worker }
113*d9f75844SAndroid Build Coastguard Worker
114*d9f75844SAndroid Build Coastguard Worker unsigned char h1, h2;
115*d9f75844SAndroid Build Coastguard Worker if (!hex_decode(source[srcpos], &h1) ||
116*d9f75844SAndroid Build Coastguard Worker !hex_decode(source[srcpos + 1], &h2))
117*d9f75844SAndroid Build Coastguard Worker return 0;
118*d9f75844SAndroid Build Coastguard Worker
119*d9f75844SAndroid Build Coastguard Worker bbuffer[bufpos++] = (h1 << 4) | h2;
120*d9f75844SAndroid Build Coastguard Worker srcpos += 2;
121*d9f75844SAndroid Build Coastguard Worker
122*d9f75844SAndroid Build Coastguard Worker // Remove the delimiter if needed.
123*d9f75844SAndroid Build Coastguard Worker if (delimiter && (srclen - srcpos) > 1) {
124*d9f75844SAndroid Build Coastguard Worker if (source[srcpos] != delimiter)
125*d9f75844SAndroid Build Coastguard Worker return 0;
126*d9f75844SAndroid Build Coastguard Worker ++srcpos;
127*d9f75844SAndroid Build Coastguard Worker }
128*d9f75844SAndroid Build Coastguard Worker }
129*d9f75844SAndroid Build Coastguard Worker
130*d9f75844SAndroid Build Coastguard Worker return bufpos;
131*d9f75844SAndroid Build Coastguard Worker }
132*d9f75844SAndroid Build Coastguard Worker
hex_decode(ArrayView<char> buffer,absl::string_view source)133*d9f75844SAndroid Build Coastguard Worker size_t hex_decode(ArrayView<char> buffer, absl::string_view source) {
134*d9f75844SAndroid Build Coastguard Worker return hex_decode_with_delimiter(buffer, source, 0);
135*d9f75844SAndroid Build Coastguard Worker }
136*d9f75844SAndroid Build Coastguard Worker
tokenize(absl::string_view source,char delimiter,std::vector<std::string> * fields)137*d9f75844SAndroid Build Coastguard Worker size_t tokenize(absl::string_view source,
138*d9f75844SAndroid Build Coastguard Worker char delimiter,
139*d9f75844SAndroid Build Coastguard Worker std::vector<std::string>* fields) {
140*d9f75844SAndroid Build Coastguard Worker fields->clear();
141*d9f75844SAndroid Build Coastguard Worker size_t last = 0;
142*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < source.length(); ++i) {
143*d9f75844SAndroid Build Coastguard Worker if (source[i] == delimiter) {
144*d9f75844SAndroid Build Coastguard Worker if (i != last) {
145*d9f75844SAndroid Build Coastguard Worker fields->emplace_back(source.substr(last, i - last));
146*d9f75844SAndroid Build Coastguard Worker }
147*d9f75844SAndroid Build Coastguard Worker last = i + 1;
148*d9f75844SAndroid Build Coastguard Worker }
149*d9f75844SAndroid Build Coastguard Worker }
150*d9f75844SAndroid Build Coastguard Worker if (last != source.length()) {
151*d9f75844SAndroid Build Coastguard Worker fields->emplace_back(source.substr(last, source.length() - last));
152*d9f75844SAndroid Build Coastguard Worker }
153*d9f75844SAndroid Build Coastguard Worker return fields->size();
154*d9f75844SAndroid Build Coastguard Worker }
155*d9f75844SAndroid Build Coastguard Worker
tokenize_first(absl::string_view source,const char delimiter,std::string * token,std::string * rest)156*d9f75844SAndroid Build Coastguard Worker bool tokenize_first(absl::string_view source,
157*d9f75844SAndroid Build Coastguard Worker const char delimiter,
158*d9f75844SAndroid Build Coastguard Worker std::string* token,
159*d9f75844SAndroid Build Coastguard Worker std::string* rest) {
160*d9f75844SAndroid Build Coastguard Worker // Find the first delimiter
161*d9f75844SAndroid Build Coastguard Worker size_t left_pos = source.find(delimiter);
162*d9f75844SAndroid Build Coastguard Worker if (left_pos == absl::string_view::npos) {
163*d9f75844SAndroid Build Coastguard Worker return false;
164*d9f75844SAndroid Build Coastguard Worker }
165*d9f75844SAndroid Build Coastguard Worker
166*d9f75844SAndroid Build Coastguard Worker // Look for additional occurrances of delimiter.
167*d9f75844SAndroid Build Coastguard Worker size_t right_pos = left_pos + 1;
168*d9f75844SAndroid Build Coastguard Worker while (right_pos < source.size() && source[right_pos] == delimiter) {
169*d9f75844SAndroid Build Coastguard Worker right_pos++;
170*d9f75844SAndroid Build Coastguard Worker }
171*d9f75844SAndroid Build Coastguard Worker
172*d9f75844SAndroid Build Coastguard Worker *token = std::string(source.substr(0, left_pos));
173*d9f75844SAndroid Build Coastguard Worker *rest = std::string(source.substr(right_pos));
174*d9f75844SAndroid Build Coastguard Worker return true;
175*d9f75844SAndroid Build Coastguard Worker }
176*d9f75844SAndroid Build Coastguard Worker
split(absl::string_view source,char delimiter)177*d9f75844SAndroid Build Coastguard Worker std::vector<absl::string_view> split(absl::string_view source, char delimiter) {
178*d9f75844SAndroid Build Coastguard Worker std::vector<absl::string_view> fields;
179*d9f75844SAndroid Build Coastguard Worker size_t last = 0;
180*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < source.length(); ++i) {
181*d9f75844SAndroid Build Coastguard Worker if (source[i] == delimiter) {
182*d9f75844SAndroid Build Coastguard Worker fields.push_back(source.substr(last, i - last));
183*d9f75844SAndroid Build Coastguard Worker last = i + 1;
184*d9f75844SAndroid Build Coastguard Worker }
185*d9f75844SAndroid Build Coastguard Worker }
186*d9f75844SAndroid Build Coastguard Worker fields.push_back(source.substr(last));
187*d9f75844SAndroid Build Coastguard Worker return fields;
188*d9f75844SAndroid Build Coastguard Worker }
189*d9f75844SAndroid Build Coastguard Worker
ToString(const bool b)190*d9f75844SAndroid Build Coastguard Worker std::string ToString(const bool b) {
191*d9f75844SAndroid Build Coastguard Worker return b ? "true" : "false";
192*d9f75844SAndroid Build Coastguard Worker }
193*d9f75844SAndroid Build Coastguard Worker
ToString(absl::string_view s)194*d9f75844SAndroid Build Coastguard Worker std::string ToString(absl::string_view s) {
195*d9f75844SAndroid Build Coastguard Worker return std::string(s);
196*d9f75844SAndroid Build Coastguard Worker }
197*d9f75844SAndroid Build Coastguard Worker
ToString(const char * s)198*d9f75844SAndroid Build Coastguard Worker std::string ToString(const char* s) {
199*d9f75844SAndroid Build Coastguard Worker return std::string(s);
200*d9f75844SAndroid Build Coastguard Worker }
201*d9f75844SAndroid Build Coastguard Worker
ToString(const short s)202*d9f75844SAndroid Build Coastguard Worker std::string ToString(const short s) {
203*d9f75844SAndroid Build Coastguard Worker char buf[32];
204*d9f75844SAndroid Build Coastguard Worker const int len = std::snprintf(&buf[0], arraysize(buf), "%hd", s);
205*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(len, arraysize(buf));
206*d9f75844SAndroid Build Coastguard Worker return std::string(&buf[0], len);
207*d9f75844SAndroid Build Coastguard Worker }
ToString(const unsigned short s)208*d9f75844SAndroid Build Coastguard Worker std::string ToString(const unsigned short s) {
209*d9f75844SAndroid Build Coastguard Worker char buf[32];
210*d9f75844SAndroid Build Coastguard Worker const int len = std::snprintf(&buf[0], arraysize(buf), "%hu", s);
211*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(len, arraysize(buf));
212*d9f75844SAndroid Build Coastguard Worker return std::string(&buf[0], len);
213*d9f75844SAndroid Build Coastguard Worker }
ToString(const int s)214*d9f75844SAndroid Build Coastguard Worker std::string ToString(const int s) {
215*d9f75844SAndroid Build Coastguard Worker char buf[32];
216*d9f75844SAndroid Build Coastguard Worker const int len = std::snprintf(&buf[0], arraysize(buf), "%d", s);
217*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(len, arraysize(buf));
218*d9f75844SAndroid Build Coastguard Worker return std::string(&buf[0], len);
219*d9f75844SAndroid Build Coastguard Worker }
ToString(const unsigned int s)220*d9f75844SAndroid Build Coastguard Worker std::string ToString(const unsigned int s) {
221*d9f75844SAndroid Build Coastguard Worker char buf[32];
222*d9f75844SAndroid Build Coastguard Worker const int len = std::snprintf(&buf[0], arraysize(buf), "%u", s);
223*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(len, arraysize(buf));
224*d9f75844SAndroid Build Coastguard Worker return std::string(&buf[0], len);
225*d9f75844SAndroid Build Coastguard Worker }
ToString(const long int s)226*d9f75844SAndroid Build Coastguard Worker std::string ToString(const long int s) {
227*d9f75844SAndroid Build Coastguard Worker char buf[32];
228*d9f75844SAndroid Build Coastguard Worker const int len = std::snprintf(&buf[0], arraysize(buf), "%ld", s);
229*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(len, arraysize(buf));
230*d9f75844SAndroid Build Coastguard Worker return std::string(&buf[0], len);
231*d9f75844SAndroid Build Coastguard Worker }
ToString(const unsigned long int s)232*d9f75844SAndroid Build Coastguard Worker std::string ToString(const unsigned long int s) {
233*d9f75844SAndroid Build Coastguard Worker char buf[32];
234*d9f75844SAndroid Build Coastguard Worker const int len = std::snprintf(&buf[0], arraysize(buf), "%lu", s);
235*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(len, arraysize(buf));
236*d9f75844SAndroid Build Coastguard Worker return std::string(&buf[0], len);
237*d9f75844SAndroid Build Coastguard Worker }
ToString(const long long int s)238*d9f75844SAndroid Build Coastguard Worker std::string ToString(const long long int s) {
239*d9f75844SAndroid Build Coastguard Worker char buf[32];
240*d9f75844SAndroid Build Coastguard Worker const int len = std::snprintf(&buf[0], arraysize(buf), "%lld", s);
241*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(len, arraysize(buf));
242*d9f75844SAndroid Build Coastguard Worker return std::string(&buf[0], len);
243*d9f75844SAndroid Build Coastguard Worker }
ToString(const unsigned long long int s)244*d9f75844SAndroid Build Coastguard Worker std::string ToString(const unsigned long long int s) {
245*d9f75844SAndroid Build Coastguard Worker char buf[32];
246*d9f75844SAndroid Build Coastguard Worker const int len = std::snprintf(&buf[0], arraysize(buf), "%llu", s);
247*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(len, arraysize(buf));
248*d9f75844SAndroid Build Coastguard Worker return std::string(&buf[0], len);
249*d9f75844SAndroid Build Coastguard Worker }
250*d9f75844SAndroid Build Coastguard Worker
ToString(const double d)251*d9f75844SAndroid Build Coastguard Worker std::string ToString(const double d) {
252*d9f75844SAndroid Build Coastguard Worker char buf[32];
253*d9f75844SAndroid Build Coastguard Worker const int len = std::snprintf(&buf[0], arraysize(buf), "%g", d);
254*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(len, arraysize(buf));
255*d9f75844SAndroid Build Coastguard Worker return std::string(&buf[0], len);
256*d9f75844SAndroid Build Coastguard Worker }
257*d9f75844SAndroid Build Coastguard Worker
ToString(const long double d)258*d9f75844SAndroid Build Coastguard Worker std::string ToString(const long double d) {
259*d9f75844SAndroid Build Coastguard Worker char buf[32];
260*d9f75844SAndroid Build Coastguard Worker const int len = std::snprintf(&buf[0], arraysize(buf), "%Lg", d);
261*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(len, arraysize(buf));
262*d9f75844SAndroid Build Coastguard Worker return std::string(&buf[0], len);
263*d9f75844SAndroid Build Coastguard Worker }
264*d9f75844SAndroid Build Coastguard Worker
ToString(const void * const p)265*d9f75844SAndroid Build Coastguard Worker std::string ToString(const void* const p) {
266*d9f75844SAndroid Build Coastguard Worker char buf[32];
267*d9f75844SAndroid Build Coastguard Worker const int len = std::snprintf(&buf[0], arraysize(buf), "%p", p);
268*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(len, arraysize(buf));
269*d9f75844SAndroid Build Coastguard Worker return std::string(&buf[0], len);
270*d9f75844SAndroid Build Coastguard Worker }
271*d9f75844SAndroid Build Coastguard Worker
FromString(absl::string_view s,bool * b)272*d9f75844SAndroid Build Coastguard Worker bool FromString(absl::string_view s, bool* b) {
273*d9f75844SAndroid Build Coastguard Worker if (s == "false") {
274*d9f75844SAndroid Build Coastguard Worker *b = false;
275*d9f75844SAndroid Build Coastguard Worker return true;
276*d9f75844SAndroid Build Coastguard Worker }
277*d9f75844SAndroid Build Coastguard Worker if (s == "true") {
278*d9f75844SAndroid Build Coastguard Worker *b = true;
279*d9f75844SAndroid Build Coastguard Worker return true;
280*d9f75844SAndroid Build Coastguard Worker }
281*d9f75844SAndroid Build Coastguard Worker return false;
282*d9f75844SAndroid Build Coastguard Worker }
283*d9f75844SAndroid Build Coastguard Worker
284*d9f75844SAndroid Build Coastguard Worker } // namespace rtc
285