• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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 "base/strings/string_split.h"
6 
7 #include <stddef.h>
8 
9 #include <string_view>
10 
11 #include "base/logging.h"
12 #include "base/strings/string_split_internal.h"
13 #include "base/strings/string_util.h"
14 #include "base/third_party/icu/icu_utf.h"
15 
16 namespace base {
17 
18 namespace {
19 
20 // Helper for the various *SplitStringOnce implementations. When returning a
21 // pair of `std::string_view`, does not include the character at `position`.
22 std::optional<std::pair<std::string_view, std::string_view>>
SplitStringAtExclusive(std::string_view input,size_t position)23 SplitStringAtExclusive(std::string_view input, size_t position) {
24   if (position == std::string_view::npos) {
25     return std::nullopt;
26   }
27 
28   return std::pair(input.substr(0, position), input.substr(position + 1));
29 }
30 
AppendStringKeyValue(std::string_view input,char delimiter,StringPairs * result)31 bool AppendStringKeyValue(std::string_view input,
32                           char delimiter,
33                           StringPairs* result) {
34   // Always append a new item regardless of success (it might be empty). The
35   // below code will copy the strings directly into the result pair.
36   result->resize(result->size() + 1);
37   auto& result_pair = result->back();
38 
39   // Find the delimiter.
40   size_t end_key_pos = input.find_first_of(delimiter);
41   if (end_key_pos == std::string::npos) {
42     DVLOG(1) << "cannot find delimiter in: " << input;
43     return false;    // No delimiter.
44   }
45   result_pair.first = std::string(input.substr(0, end_key_pos));
46 
47   // Find the value string.
48   std::string_view remains =
49       input.substr(end_key_pos, input.size() - end_key_pos);
50   size_t begin_value_pos = remains.find_first_not_of(delimiter);
51   if (begin_value_pos == std::string_view::npos) {
52     DVLOG(1) << "cannot parse value from input: " << input;
53     return false;   // No value.
54   }
55 
56   result_pair.second = std::string(
57       remains.substr(begin_value_pos, remains.size() - begin_value_pos));
58 
59   return true;
60 }
61 
62 }  // namespace
63 
SplitStringOnce(std::string_view input,char separator)64 std::optional<std::pair<std::string_view, std::string_view>> SplitStringOnce(
65     std::string_view input,
66     char separator) {
67   return SplitStringAtExclusive(input, input.find(separator));
68 }
69 
SplitStringOnce(std::string_view input,std::string_view separators)70 std::optional<std::pair<std::string_view, std::string_view>> SplitStringOnce(
71     std::string_view input,
72     std::string_view separators) {
73   return SplitStringAtExclusive(input, input.find_first_of(separators));
74 }
75 
RSplitStringOnce(std::string_view input,char separator)76 std::optional<std::pair<std::string_view, std::string_view>> RSplitStringOnce(
77     std::string_view input,
78     char separator) {
79   return SplitStringAtExclusive(input, input.rfind(separator));
80 }
81 
RSplitStringOnce(std::string_view input,std::string_view separators)82 std::optional<std::pair<std::string_view, std::string_view>> RSplitStringOnce(
83     std::string_view input,
84     std::string_view separators) {
85   return SplitStringAtExclusive(input, input.find_last_of(separators));
86 }
87 
SplitString(std::string_view input,std::string_view separators,WhitespaceHandling whitespace,SplitResult result_type)88 std::vector<std::string> SplitString(std::string_view input,
89                                      std::string_view separators,
90                                      WhitespaceHandling whitespace,
91                                      SplitResult result_type) {
92   return internal::SplitStringT<std::string>(input, separators, whitespace,
93                                              result_type);
94 }
95 
SplitString(std::u16string_view input,std::u16string_view separators,WhitespaceHandling whitespace,SplitResult result_type)96 std::vector<std::u16string> SplitString(std::u16string_view input,
97                                         std::u16string_view separators,
98                                         WhitespaceHandling whitespace,
99                                         SplitResult result_type) {
100   return internal::SplitStringT<std::u16string>(input, separators, whitespace,
101                                                 result_type);
102 }
103 
SplitStringPiece(std::string_view input,std::string_view separators,WhitespaceHandling whitespace,SplitResult result_type)104 std::vector<std::string_view> SplitStringPiece(std::string_view input,
105                                                std::string_view separators,
106                                                WhitespaceHandling whitespace,
107                                                SplitResult result_type) {
108   return internal::SplitStringT<std::string_view>(input, separators, whitespace,
109                                                   result_type);
110 }
111 
SplitStringPiece(std::u16string_view input,std::u16string_view separators,WhitespaceHandling whitespace,SplitResult result_type)112 std::vector<std::u16string_view> SplitStringPiece(
113     std::u16string_view input,
114     std::u16string_view separators,
115     WhitespaceHandling whitespace,
116     SplitResult result_type) {
117   return internal::SplitStringT<std::u16string_view>(input, separators,
118                                                      whitespace, result_type);
119 }
120 
SplitStringIntoKeyValuePairs(std::string_view input,char key_value_delimiter,char key_value_pair_delimiter,StringPairs * key_value_pairs)121 bool SplitStringIntoKeyValuePairs(std::string_view input,
122                                   char key_value_delimiter,
123                                   char key_value_pair_delimiter,
124                                   StringPairs* key_value_pairs) {
125   return SplitStringIntoKeyValuePairsUsingSubstr(
126       input, key_value_delimiter,
127       std::string_view(&key_value_pair_delimiter, 1), key_value_pairs);
128 }
129 
SplitStringIntoKeyValuePairsUsingSubstr(std::string_view input,char key_value_delimiter,std::string_view key_value_pair_delimiter,StringPairs * key_value_pairs)130 bool SplitStringIntoKeyValuePairsUsingSubstr(
131     std::string_view input,
132     char key_value_delimiter,
133     std::string_view key_value_pair_delimiter,
134     StringPairs* key_value_pairs) {
135   key_value_pairs->clear();
136 
137   std::vector<std::string_view> pairs = SplitStringPieceUsingSubstr(
138       input, key_value_pair_delimiter, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
139   key_value_pairs->reserve(pairs.size());
140 
141   bool success = true;
142   for (std::string_view pair : pairs) {
143     if (!AppendStringKeyValue(pair, key_value_delimiter, key_value_pairs)) {
144       // Don't return here, to allow for pairs without associated
145       // value or key; just record that the split failed.
146       success = false;
147     }
148   }
149   return success;
150 }
151 
SplitStringUsingSubstr(std::u16string_view input,std::u16string_view delimiter,WhitespaceHandling whitespace,SplitResult result_type)152 std::vector<std::u16string> SplitStringUsingSubstr(
153     std::u16string_view input,
154     std::u16string_view delimiter,
155     WhitespaceHandling whitespace,
156     SplitResult result_type) {
157   return internal::SplitStringUsingSubstrT<std::u16string>(
158       input, delimiter, whitespace, result_type);
159 }
160 
SplitStringUsingSubstr(std::string_view input,std::string_view delimiter,WhitespaceHandling whitespace,SplitResult result_type)161 std::vector<std::string> SplitStringUsingSubstr(std::string_view input,
162                                                 std::string_view delimiter,
163                                                 WhitespaceHandling whitespace,
164                                                 SplitResult result_type) {
165   return internal::SplitStringUsingSubstrT<std::string>(
166       input, delimiter, whitespace, result_type);
167 }
168 
SplitStringPieceUsingSubstr(std::u16string_view input,std::u16string_view delimiter,WhitespaceHandling whitespace,SplitResult result_type)169 std::vector<std::u16string_view> SplitStringPieceUsingSubstr(
170     std::u16string_view input,
171     std::u16string_view delimiter,
172     WhitespaceHandling whitespace,
173     SplitResult result_type) {
174   std::vector<std::u16string_view> result;
175   return internal::SplitStringUsingSubstrT<std::u16string_view>(
176       input, delimiter, whitespace, result_type);
177 }
178 
SplitStringPieceUsingSubstr(std::string_view input,std::string_view delimiter,WhitespaceHandling whitespace,SplitResult result_type)179 std::vector<std::string_view> SplitStringPieceUsingSubstr(
180     std::string_view input,
181     std::string_view delimiter,
182     WhitespaceHandling whitespace,
183     SplitResult result_type) {
184   return internal::SplitStringUsingSubstrT<std::string_view>(
185       input, delimiter, whitespace, result_type);
186 }
187 
188 }  // namespace base
189