1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "string_util.h"
6
7 #include <algorithm>
8 #include <iomanip>
9 #include <sstream>
10 #include <string>
11
12 #include <openssl/mem.h>
13
14 namespace bssl::string_util {
15
IsAscii(std::string_view str)16 bool IsAscii(std::string_view str) {
17 for (unsigned char c : str) {
18 if (c > 127) {
19 return false;
20 }
21 }
22 return true;
23 }
24
IsEqualNoCase(std::string_view str1,std::string_view str2)25 bool IsEqualNoCase(std::string_view str1, std::string_view str2) {
26 return std::equal(str1.begin(), str1.end(), str2.begin(), str2.end(),
27 [](const unsigned char a, const unsigned char b) {
28 return OPENSSL_tolower(a) == OPENSSL_tolower(b);
29 });
30 }
31
EndsWithNoCase(std::string_view str,std::string_view suffix)32 bool EndsWithNoCase(std::string_view str, std::string_view suffix) {
33 return suffix.size() <= str.size() &&
34 IsEqualNoCase(suffix, str.substr(str.size() - suffix.size()));
35 }
36
StartsWithNoCase(std::string_view str,std::string_view prefix)37 bool StartsWithNoCase(std::string_view str, std::string_view prefix) {
38 return prefix.size() <= str.size() &&
39 IsEqualNoCase(prefix, str.substr(0, prefix.size()));
40 }
41
FindAndReplace(std::string_view str,std::string_view find,std::string_view replace)42 std::string FindAndReplace(std::string_view str,
43 std::string_view find,
44 std::string_view replace) {
45 std::string ret;
46
47 if (find.empty()) {
48 return std::string(str);
49 }
50 while (!str.empty()) {
51 size_t index = str.find(find);
52 if (index == std::string_view::npos) {
53 ret.append(str);
54 break;
55 }
56 ret.append(str.substr(0, index));
57 ret.append(replace);
58 str = str.substr(index + find.size());
59 }
60 return ret;
61 }
62
63 // TODO(bbe) get rid of this once we can c++20.
EndsWith(std::string_view str,std::string_view suffix)64 bool EndsWith(std::string_view str, std::string_view suffix) {
65 return suffix.size() <= str.size() &&
66 suffix == str.substr(str.size() - suffix.size());
67 }
68
69 // TODO(bbe) get rid of this once we can c++20.
StartsWith(std::string_view str,std::string_view prefix)70 bool StartsWith(std::string_view str, std::string_view prefix) {
71 return prefix.size() <= str.size() && prefix == str.substr(0, prefix.size());
72 }
73
HexEncode(const uint8_t * data,size_t length)74 std::string HexEncode(const uint8_t* data, size_t length) {
75 std::ostringstream out;
76 for (size_t i = 0; i < length; i++) {
77 out << std::hex << std::setfill('0') << std::setw(2) << std::uppercase
78 << int{data[i]};
79 }
80 return out.str();
81 }
82
83 // TODO(bbe) get rid of this once extracted to boringssl. Everything else
84 // in third_party uses std::to_string
NumberToDecimalString(int i)85 std::string NumberToDecimalString(int i) {
86 std::ostringstream out;
87 out << std::dec << i;
88 return out.str();
89 }
90
SplitString(std::string_view str,char split_char)91 std::vector<std::string_view> SplitString(std::string_view str,
92 char split_char) {
93 std::vector<std::string_view> out;
94
95 if (str.empty()) {
96 return out;
97 }
98
99 while (true) {
100 // Find end of current token
101 size_t i = str.find(split_char);
102
103 // Add current token
104 out.push_back(str.substr(0, i));
105
106 if (i == str.npos) {
107 // That was the last token
108 break;
109 }
110 // Continue to next
111 str = str.substr(i + 1);
112 }
113
114 return out;
115 }
116
117 } // namespace bssl::string_util
118