string_split.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 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/string_split.h" 6 7#include "base/logging.h" 8#include "base/string_util.h" 9#include "base/third_party/icu/icu_utf.h" 10#include "base/utf_string_conversions.h" 11 12template<typename STR> 13static void SplitStringT(const STR& str, 14 const typename STR::value_type s, 15 bool trim_whitespace, 16 std::vector<STR>* r) { 17 size_t last = 0; 18 size_t i; 19 size_t c = str.size(); 20 for (i = 0; i <= c; ++i) { 21 if (i == c || str[i] == s) { 22 size_t len = i - last; 23 STR tmp = str.substr(last, len); 24 if (trim_whitespace) { 25 STR t_tmp; 26 TrimWhitespace(tmp, TRIM_ALL, &t_tmp); 27 r->push_back(t_tmp); 28 } else { 29 r->push_back(tmp); 30 } 31 last = i + 1; 32 } 33 } 34} 35 36void SplitString(const std::wstring& str, 37 wchar_t c, 38 std::vector<std::wstring>* r) { 39 SplitStringT(str, c, true, r); 40} 41 42#if !defined(WCHAR_T_IS_UTF16) 43void SplitString(const string16& str, 44 char16 c, 45 std::vector<string16>* r) { 46 DCHECK(CBU16_IS_SINGLE(c)); 47 SplitStringT(str, c, true, r); 48} 49#endif 50 51void SplitString(const std::string& str, 52 char c, 53 std::vector<std::string>* r) { 54 DCHECK(c >= 0 && c < 0x7F); 55 SplitStringT(str, c, true, r); 56} 57 58namespace base { 59 60bool SplitStringIntoKeyValues( 61 const std::string& line, 62 char key_value_delimiter, 63 std::string* key, std::vector<std::string>* values) { 64 key->clear(); 65 values->clear(); 66 67 // Find the key string. 68 size_t end_key_pos = line.find_first_of(key_value_delimiter); 69 if (end_key_pos == std::string::npos) { 70 DLOG(INFO) << "cannot parse key from line: " << line; 71 return false; // no key 72 } 73 key->assign(line, 0, end_key_pos); 74 75 // Find the values string. 76 std::string remains(line, end_key_pos, line.size() - end_key_pos); 77 size_t begin_values_pos = remains.find_first_not_of(key_value_delimiter); 78 if (begin_values_pos == std::string::npos) { 79 DLOG(INFO) << "cannot parse value from line: " << line; 80 return false; // no value 81 } 82 std::string values_string(remains, begin_values_pos, 83 remains.size() - begin_values_pos); 84 85 // Construct the values vector. 86 values->push_back(values_string); 87 return true; 88} 89 90bool SplitStringIntoKeyValuePairs( 91 const std::string& line, 92 char key_value_delimiter, 93 char key_value_pair_delimiter, 94 std::vector<std::pair<std::string, std::string> >* kv_pairs) { 95 kv_pairs->clear(); 96 97 std::vector<std::string> pairs; 98 SplitString(line, key_value_pair_delimiter, &pairs); 99 100 bool success = true; 101 for (size_t i = 0; i < pairs.size(); ++i) { 102 // Empty pair. SplitStringIntoKeyValues is more strict about an empty pair 103 // line, so continue with the next pair. 104 if (pairs[i].empty()) 105 continue; 106 107 std::string key; 108 std::vector<std::string> value; 109 if (!SplitStringIntoKeyValues(pairs[i], 110 key_value_delimiter, 111 &key, &value)) { 112 // Don't return here, to allow for keys without associated 113 // values; just record that our split failed. 114 success = false; 115 } 116 DCHECK_LE(value.size(), 1U); 117 kv_pairs->push_back(make_pair(key, value.empty()? "" : value[0])); 118 } 119 return success; 120} 121 122template <typename STR> 123static void SplitStringUsingSubstrT(const STR& str, 124 const STR& s, 125 std::vector<STR>* r) { 126 typename STR::size_type begin_index = 0; 127 while (true) { 128 const typename STR::size_type end_index = str.find(s, begin_index); 129 if (end_index == STR::npos) { 130 const STR term = str.substr(begin_index); 131 STR tmp; 132 TrimWhitespace(term, TRIM_ALL, &tmp); 133 r->push_back(tmp); 134 return; 135 } 136 const STR term = str.substr(begin_index, end_index - begin_index); 137 STR tmp; 138 TrimWhitespace(term, TRIM_ALL, &tmp); 139 r->push_back(tmp); 140 begin_index = end_index + s.size(); 141 } 142} 143 144void SplitStringUsingSubstr(const string16& str, 145 const string16& s, 146 std::vector<string16>* r) { 147 SplitStringUsingSubstrT(str, s, r); 148} 149 150void SplitStringUsingSubstr(const std::string& str, 151 const std::string& s, 152 std::vector<std::string>* r) { 153 SplitStringUsingSubstrT(str, s, r); 154} 155 156void SplitStringDontTrim(const std::wstring& str, 157 wchar_t c, 158 std::vector<std::wstring>* r) { 159 SplitStringT(str, c, false, r); 160} 161 162#if !defined(WCHAR_T_IS_UTF16) 163void SplitStringDontTrim(const string16& str, 164 char16 c, 165 std::vector<string16>* r) { 166 DCHECK(CBU16_IS_SINGLE(c)); 167 SplitStringT(str, c, false, r); 168} 169#endif 170 171void SplitStringDontTrim(const std::string& str, 172 char c, 173 std::vector<std::string>* r) { 174 DCHECK(IsStringUTF8(str)); 175 DCHECK(c >= 0 && c < 0x7F); 176 SplitStringT(str, c, false, r); 177} 178 179} // namespace base 180