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 "base/logging.h"
10 #include "base/strings/string_split_internal.h"
11 #include "base/strings/string_util.h"
12 #include "base/third_party/icu/icu_utf.h"
13
14 namespace base {
15
16 namespace {
17
AppendStringKeyValue(StringPiece input,char delimiter,StringPairs * result)18 bool AppendStringKeyValue(StringPiece input,
19 char delimiter,
20 StringPairs* result) {
21 // Always append a new item regardless of success (it might be empty). The
22 // below code will copy the strings directly into the result pair.
23 result->resize(result->size() + 1);
24 auto& result_pair = result->back();
25
26 // Find the delimiter.
27 size_t end_key_pos = input.find_first_of(delimiter);
28 if (end_key_pos == std::string::npos) {
29 DVLOG(1) << "cannot find delimiter in: " << input;
30 return false; // No delimiter.
31 }
32 result_pair.first = std::string(input.substr(0, end_key_pos));
33
34 // Find the value string.
35 StringPiece remains = input.substr(end_key_pos, input.size() - end_key_pos);
36 size_t begin_value_pos = remains.find_first_not_of(delimiter);
37 if (begin_value_pos == StringPiece::npos) {
38 DVLOG(1) << "cannot parse value from input: " << input;
39 return false; // No value.
40 }
41
42 result_pair.second = std::string(
43 remains.substr(begin_value_pos, remains.size() - begin_value_pos));
44
45 return true;
46 }
47
48 } // namespace
49
SplitString(StringPiece input,StringPiece separators,WhitespaceHandling whitespace,SplitResult result_type)50 std::vector<std::string> SplitString(StringPiece input,
51 StringPiece separators,
52 WhitespaceHandling whitespace,
53 SplitResult result_type) {
54 return internal::SplitStringT<std::string>(input, separators, whitespace,
55 result_type);
56 }
57
SplitString(StringPiece16 input,StringPiece16 separators,WhitespaceHandling whitespace,SplitResult result_type)58 std::vector<std::u16string> SplitString(StringPiece16 input,
59 StringPiece16 separators,
60 WhitespaceHandling whitespace,
61 SplitResult result_type) {
62 return internal::SplitStringT<std::u16string>(input, separators, whitespace,
63 result_type);
64 }
65
SplitStringPiece(StringPiece input,StringPiece separators,WhitespaceHandling whitespace,SplitResult result_type)66 std::vector<StringPiece> SplitStringPiece(StringPiece input,
67 StringPiece separators,
68 WhitespaceHandling whitespace,
69 SplitResult result_type) {
70 return internal::SplitStringT<StringPiece>(input, separators, whitespace,
71 result_type);
72 }
73
SplitStringPiece(StringPiece16 input,StringPiece16 separators,WhitespaceHandling whitespace,SplitResult result_type)74 std::vector<StringPiece16> SplitStringPiece(StringPiece16 input,
75 StringPiece16 separators,
76 WhitespaceHandling whitespace,
77 SplitResult result_type) {
78 return internal::SplitStringT<StringPiece16>(input, separators, whitespace,
79 result_type);
80 }
81
SplitStringIntoKeyValuePairs(StringPiece input,char key_value_delimiter,char key_value_pair_delimiter,StringPairs * key_value_pairs)82 bool SplitStringIntoKeyValuePairs(StringPiece input,
83 char key_value_delimiter,
84 char key_value_pair_delimiter,
85 StringPairs* key_value_pairs) {
86 return SplitStringIntoKeyValuePairsUsingSubstr(
87 input, key_value_delimiter, StringPiece(&key_value_pair_delimiter, 1),
88 key_value_pairs);
89 }
90
SplitStringIntoKeyValuePairsUsingSubstr(StringPiece input,char key_value_delimiter,StringPiece key_value_pair_delimiter,StringPairs * key_value_pairs)91 bool SplitStringIntoKeyValuePairsUsingSubstr(
92 StringPiece input,
93 char key_value_delimiter,
94 StringPiece key_value_pair_delimiter,
95 StringPairs* key_value_pairs) {
96 key_value_pairs->clear();
97
98 std::vector<StringPiece> pairs = SplitStringPieceUsingSubstr(
99 input, key_value_pair_delimiter, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
100 key_value_pairs->reserve(pairs.size());
101
102 bool success = true;
103 for (const StringPiece& pair : pairs) {
104 if (!AppendStringKeyValue(pair, key_value_delimiter, key_value_pairs)) {
105 // Don't return here, to allow for pairs without associated
106 // value or key; just record that the split failed.
107 success = false;
108 }
109 }
110 return success;
111 }
112
SplitStringUsingSubstr(StringPiece16 input,StringPiece16 delimiter,WhitespaceHandling whitespace,SplitResult result_type)113 std::vector<std::u16string> SplitStringUsingSubstr(
114 StringPiece16 input,
115 StringPiece16 delimiter,
116 WhitespaceHandling whitespace,
117 SplitResult result_type) {
118 return internal::SplitStringUsingSubstrT<std::u16string>(
119 input, delimiter, whitespace, result_type);
120 }
121
SplitStringUsingSubstr(StringPiece input,StringPiece delimiter,WhitespaceHandling whitespace,SplitResult result_type)122 std::vector<std::string> SplitStringUsingSubstr(StringPiece input,
123 StringPiece delimiter,
124 WhitespaceHandling whitespace,
125 SplitResult result_type) {
126 return internal::SplitStringUsingSubstrT<std::string>(
127 input, delimiter, whitespace, result_type);
128 }
129
SplitStringPieceUsingSubstr(StringPiece16 input,StringPiece16 delimiter,WhitespaceHandling whitespace,SplitResult result_type)130 std::vector<StringPiece16> SplitStringPieceUsingSubstr(
131 StringPiece16 input,
132 StringPiece16 delimiter,
133 WhitespaceHandling whitespace,
134 SplitResult result_type) {
135 std::vector<StringPiece16> result;
136 return internal::SplitStringUsingSubstrT<StringPiece16>(
137 input, delimiter, whitespace, result_type);
138 }
139
SplitStringPieceUsingSubstr(StringPiece input,StringPiece delimiter,WhitespaceHandling whitespace,SplitResult result_type)140 std::vector<StringPiece> SplitStringPieceUsingSubstr(
141 StringPiece input,
142 StringPiece delimiter,
143 WhitespaceHandling whitespace,
144 SplitResult result_type) {
145 return internal::SplitStringUsingSubstrT<StringPiece>(
146 input, delimiter, whitespace, result_type);
147 }
148
149 } // namespace base
150