OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/string_util.h" | 5 #include "base/string_util.h" |
6 | 6 |
7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
8 | 8 |
9 #include <ctype.h> | 9 #include <ctype.h> |
10 #include <errno.h> | 10 #include <errno.h> |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 // - a typedef for value_type, the target numeric type. | 82 // - a typedef for value_type, the target numeric type. |
83 // - a static function, convert_func, which dispatches to an appropriate | 83 // - a static function, convert_func, which dispatches to an appropriate |
84 // strtol-like function and returns type value_type. | 84 // strtol-like function and returns type value_type. |
85 // - a static function, valid_func, which validates |input| and returns a bool | 85 // - a static function, valid_func, which validates |input| and returns a bool |
86 // indicating whether it is in proper form. This is used to check for | 86 // indicating whether it is in proper form. This is used to check for |
87 // conditions that convert_func tolerates but should result in | 87 // conditions that convert_func tolerates but should result in |
88 // StringToNumber returning false. For strtol-like funtions, valid_func | 88 // StringToNumber returning false. For strtol-like funtions, valid_func |
89 // should check for leading whitespace. | 89 // should check for leading whitespace. |
90 template<typename StringToNumberTraits> | 90 template<typename StringToNumberTraits> |
91 bool StringToNumber(const typename StringToNumberTraits::string_type& input, | 91 bool StringToNumber(const typename StringToNumberTraits::string_type& input, |
92 typename StringToNumberTraits::value_type* output, | 92 typename StringToNumberTraits::value_type* output) { |
93 base::LocaleDependence locale_dependent) { | |
94 typedef StringToNumberTraits traits; | 93 typedef StringToNumberTraits traits; |
95 | 94 |
96 errno = 0; // Thread-safe? It is on at least Mac, Linux, and Windows. | 95 errno = 0; // Thread-safe? It is on at least Mac, Linux, and Windows. |
97 typename traits::string_type::value_type* endptr = NULL; | 96 typename traits::string_type::value_type* endptr = NULL; |
98 typename traits::value_type value = traits::convert_func(input.c_str(), | 97 typename traits::value_type value = traits::convert_func(input.c_str(), |
99 &endptr, locale_dependent == base::LOCALE_DEPENDENT); | 98 &endptr); |
100 *output = value; | 99 *output = value; |
101 | 100 |
102 // Cases to return false: | 101 // Cases to return false: |
103 // - If errno is ERANGE, there was an overflow or underflow. | 102 // - If errno is ERANGE, there was an overflow or underflow. |
104 // - If the input string is empty, there was nothing to parse. | 103 // - If the input string is empty, there was nothing to parse. |
105 // - If endptr does not point to the end of the string, there are either | 104 // - If endptr does not point to the end of the string, there are either |
106 // characters remaining in the string after a parsed number, or the string | 105 // characters remaining in the string after a parsed number, or the string |
107 // does not begin with a parseable number. endptr is compared to the | 106 // does not begin with a parseable number. endptr is compared to the |
108 // expected end given the string's stated length to correctly catch cases | 107 // expected end given the string's stated length to correctly catch cases |
109 // where the string contains embedded NUL characters. | 108 // where the string contains embedded NUL characters. |
110 // - valid_func determines that the input is not in preferred form. | 109 // - valid_func determines that the input is not in preferred form. |
111 return errno == 0 && | 110 return errno == 0 && |
112 !input.empty() && | 111 !input.empty() && |
113 input.c_str() + input.length() == endptr && | 112 input.c_str() + input.length() == endptr && |
114 traits::valid_func(input); | 113 traits::valid_func(input); |
115 } | 114 } |
116 | 115 |
117 class StringToLongTraits { | 116 class StringToLongTraits { |
118 public: | 117 public: |
119 typedef std::string string_type; | 118 typedef std::string string_type; |
120 typedef long value_type; | 119 typedef long value_type; |
121 static const int kBase = 10; | 120 static const int kBase = 10; |
122 static inline value_type convert_func(const string_type::value_type* str, | 121 static inline value_type convert_func(const string_type::value_type* str, |
123 string_type::value_type** endptr, | 122 string_type::value_type** endptr) { |
124 bool locale_dependent) { | |
125 return strtol(str, endptr, kBase); | 123 return strtol(str, endptr, kBase); |
126 } | 124 } |
127 static inline bool valid_func(const string_type& str) { | 125 static inline bool valid_func(const string_type& str) { |
128 return !str.empty() && !isspace(str[0]); | 126 return !str.empty() && !isspace(str[0]); |
129 } | 127 } |
130 }; | 128 }; |
131 | 129 |
132 class WStringToLongTraits { | 130 class WStringToLongTraits { |
133 public: | 131 public: |
134 typedef std::wstring string_type; | 132 typedef std::wstring string_type; |
135 typedef long value_type; | 133 typedef long value_type; |
136 static const int kBase = 10; | 134 static const int kBase = 10; |
137 static inline value_type convert_func(const string_type::value_type* str, | 135 static inline value_type convert_func(const string_type::value_type* str, |
138 string_type::value_type** endptr, | 136 string_type::value_type** endptr) { |
139 bool locale_dependent) { | |
140 return wcstol(str, endptr, kBase); | 137 return wcstol(str, endptr, kBase); |
141 } | 138 } |
142 static inline bool valid_func(const string_type& str) { | 139 static inline bool valid_func(const string_type& str) { |
143 return !str.empty() && !iswspace(str[0]); | 140 return !str.empty() && !iswspace(str[0]); |
144 } | 141 } |
145 }; | 142 }; |
146 | 143 |
147 class StringToInt64Traits { | 144 class StringToInt64Traits { |
148 public: | 145 public: |
149 typedef std::string string_type; | 146 typedef std::string string_type; |
150 typedef int64 value_type; | 147 typedef int64 value_type; |
151 static const int kBase = 10; | 148 static const int kBase = 10; |
152 static inline value_type convert_func(const string_type::value_type* str, | 149 static inline value_type convert_func(const string_type::value_type* str, |
153 string_type::value_type** endptr, | 150 string_type::value_type** endptr) { |
154 bool locale_dependent) { | |
155 #ifdef OS_WIN | 151 #ifdef OS_WIN |
156 return _strtoi64(str, endptr, kBase); | 152 return _strtoi64(str, endptr, kBase); |
157 #else // assume OS_POSIX | 153 #else // assume OS_POSIX |
158 return strtoll(str, endptr, kBase); | 154 return strtoll(str, endptr, kBase); |
159 #endif | 155 #endif |
160 } | 156 } |
161 static inline bool valid_func(const string_type& str) { | 157 static inline bool valid_func(const string_type& str) { |
162 return !str.empty() && !isspace(str[0]); | 158 return !str.empty() && !isspace(str[0]); |
163 } | 159 } |
164 }; | 160 }; |
165 | 161 |
166 class WStringToInt64Traits { | 162 class WStringToInt64Traits { |
167 public: | 163 public: |
168 typedef std::wstring string_type; | 164 typedef std::wstring string_type; |
169 typedef int64 value_type; | 165 typedef int64 value_type; |
170 static const int kBase = 10; | 166 static const int kBase = 10; |
171 static inline value_type convert_func(const string_type::value_type* str, | 167 static inline value_type convert_func(const string_type::value_type* str, |
172 string_type::value_type** endptr, | 168 string_type::value_type** endptr) { |
173 bool locale_dependent) { | |
174 #ifdef OS_WIN | 169 #ifdef OS_WIN |
175 return _wcstoi64(str, endptr, kBase); | 170 return _wcstoi64(str, endptr, kBase); |
176 #else // assume OS_POSIX | 171 #else // assume OS_POSIX |
177 return wcstoll(str, endptr, kBase); | 172 return wcstoll(str, endptr, kBase); |
178 #endif | 173 #endif |
179 } | 174 } |
180 static inline bool valid_func(const string_type& str) { | 175 static inline bool valid_func(const string_type& str) { |
181 return !str.empty() && !iswspace(str[0]); | 176 return !str.empty() && !iswspace(str[0]); |
182 } | 177 } |
183 }; | 178 }; |
184 | 179 |
185 // For the HexString variants, use the unsigned variants like strtoul for | 180 // For the HexString variants, use the unsigned variants like strtoul for |
186 // convert_func so that input like "0x80000000" doesn't result in an overflow. | 181 // convert_func so that input like "0x80000000" doesn't result in an overflow. |
187 | 182 |
188 class HexStringToLongTraits { | 183 class HexStringToLongTraits { |
189 public: | 184 public: |
190 typedef std::string string_type; | 185 typedef std::string string_type; |
191 typedef long value_type; | 186 typedef long value_type; |
192 static const int kBase = 16; | 187 static const int kBase = 16; |
193 static inline value_type convert_func(const string_type::value_type* str, | 188 static inline value_type convert_func(const string_type::value_type* str, |
194 string_type::value_type** endptr, | 189 string_type::value_type** endptr) { |
195 bool locale_dependent) { | |
196 return strtoul(str, endptr, kBase); | 190 return strtoul(str, endptr, kBase); |
197 } | 191 } |
198 static inline bool valid_func(const string_type& str) { | 192 static inline bool valid_func(const string_type& str) { |
199 return !str.empty() && !isspace(str[0]); | 193 return !str.empty() && !isspace(str[0]); |
200 } | 194 } |
201 }; | 195 }; |
202 | 196 |
203 class HexWStringToLongTraits { | 197 class HexWStringToLongTraits { |
204 public: | 198 public: |
205 typedef std::wstring string_type; | 199 typedef std::wstring string_type; |
206 typedef long value_type; | 200 typedef long value_type; |
207 static const int kBase = 16; | 201 static const int kBase = 16; |
208 static inline value_type convert_func(const string_type::value_type* str, | 202 static inline value_type convert_func(const string_type::value_type* str, |
209 string_type::value_type** endptr, | 203 string_type::value_type** endptr) { |
210 bool locale_dependent) { | |
211 return wcstoul(str, endptr, kBase); | 204 return wcstoul(str, endptr, kBase); |
212 } | 205 } |
213 static inline bool valid_func(const string_type& str) { | 206 static inline bool valid_func(const string_type& str) { |
214 return !str.empty() && !iswspace(str[0]); | 207 return !str.empty() && !iswspace(str[0]); |
215 } | 208 } |
216 }; | 209 }; |
217 | 210 |
218 class StringToDoubleTraits { | 211 class StringToDoubleTraits { |
219 public: | 212 public: |
220 typedef std::string string_type; | 213 typedef std::string string_type; |
221 typedef double value_type; | 214 typedef double value_type; |
222 static inline value_type convert_func(const string_type::value_type* str, | 215 static inline value_type convert_func(const string_type::value_type* str, |
223 string_type::value_type** endptr, | 216 string_type::value_type** endptr) { |
224 bool locale_dependent) { | 217 return dmg_fp::strtod(str, endptr); |
225 if (locale_dependent) { | |
226 return strtod(str, endptr); | |
227 } else { | |
228 return dmg_fp::strtod(str, endptr); | |
229 } | |
230 } | 218 } |
231 static inline bool valid_func(const string_type& str) { | 219 static inline bool valid_func(const string_type& str) { |
232 return !str.empty() && !isspace(str[0]); | 220 return !str.empty() && !isspace(str[0]); |
233 } | 221 } |
234 }; | 222 }; |
235 | 223 |
236 class WStringToDoubleTraits { | 224 class WStringToDoubleTraits { |
237 public: | 225 public: |
238 typedef std::wstring string_type; | 226 typedef std::wstring string_type; |
239 typedef double value_type; | 227 typedef double value_type; |
240 static inline value_type convert_func(const string_type::value_type* str, | 228 static inline value_type convert_func(const string_type::value_type* str, |
241 string_type::value_type** endptr, | 229 string_type::value_type** endptr) { |
242 bool locale_dependent) { | 230 // Because dmg_fp::strtod does not like wchar_t, we convert it to ASCII. |
243 if (locale_dependent) { | 231 // In theory, this should be safe, but it's possible that wide chars |
244 return wcstod(str, endptr); | 232 // might get ignored by accident causing something to be parsed when it |
245 } else { | 233 // shouldn't. |
246 // Because dmg_fp::strtod does not like wchar_t, we convert it to ASCII. | 234 std::string ascii_string = WideToASCII(std::wstring(str)); |
247 // In theory, this should be safe, but it's possible that wide chars | 235 char* ascii_end = NULL; |
248 // might get ignored by accident causing something to be parsed when it | 236 value_type ret = dmg_fp::strtod(ascii_string.c_str(), &ascii_end); |
249 // shouldn't. | 237 if (ascii_string.c_str() + ascii_string.length() == ascii_end) { |
250 std::string ascii_string = WideToASCII(std::wstring(str)); | 238 // Put endptr at end of input string, so it's not recognized as an error. |
251 char* ascii_end = NULL; | 239 *endptr = const_cast<string_type::value_type*>(str) + wcslen(str); |
252 value_type ret = dmg_fp::strtod(ascii_string.c_str(), &ascii_end); | 240 } |
253 if (ascii_string.c_str() + ascii_string.length() == ascii_end) { | |
254 // Put endptr at end of input string, so it's not recognized as an error
. | |
255 *endptr = const_cast<string_type::value_type*>(str) + wcslen(str); | |
256 } | |
257 | 241 |
258 return ret; | 242 return ret; |
259 } | |
260 } | 243 } |
261 static inline bool valid_func(const string_type& str) { | 244 static inline bool valid_func(const string_type& str) { |
262 return !str.empty() && !iswspace(str[0]); | 245 return !str.empty() && !iswspace(str[0]); |
263 } | 246 } |
264 }; | 247 }; |
265 | 248 |
266 } // namespace | 249 } // namespace |
267 | 250 |
268 | 251 |
269 namespace base { | 252 namespace base { |
(...skipping 28 matching lines...) Expand all Loading... |
298 in_specification = false; | 281 in_specification = false; |
299 } | 282 } |
300 } | 283 } |
301 } | 284 } |
302 | 285 |
303 } | 286 } |
304 | 287 |
305 return true; | 288 return true; |
306 } | 289 } |
307 | 290 |
308 std::string DoubleToString(double value, LocaleDependence locale_dependent) { | |
309 if (LOCALE_DEPENDENT == locale_dependent) { | |
310 return StringPrintf("%g", value); | |
311 } else { | |
312 char buffer[32]; | |
313 dmg_fp::g_fmt(buffer, value); | |
314 return std::string(buffer); | |
315 } | |
316 } | |
317 | |
318 std::wstring DoubleToWString(double value, LocaleDependence locale_dependent) { | |
319 return ASCIIToWide(DoubleToString(value, locale_dependent)); | |
320 } | |
321 | |
322 bool StringToDouble(const std::string& input, double* output, | |
323 LocaleDependence locale_dependent) { | |
324 return StringToNumber<StringToDoubleTraits>(input, output, | |
325 locale_dependent); | |
326 } | |
327 | |
328 bool StringToDouble(const std::wstring& input, double* output, | |
329 LocaleDependence locale_dependent) { | |
330 return StringToNumber<WStringToDoubleTraits>(input, output, | |
331 locale_dependent); | |
332 } | |
333 | |
334 double StringToDouble(const std::string& value, | |
335 LocaleDependence locale_dependent) { | |
336 double result; | |
337 StringToDouble(value, &result, locale_dependent); | |
338 return result; | |
339 } | |
340 | |
341 double StringToDouble(const std::wstring& value, | |
342 LocaleDependence locale_dependent) { | |
343 double result; | |
344 StringToDouble(value, &result, locale_dependent); | |
345 return result; | |
346 } | |
347 | 291 |
348 } // namespace base | 292 } // namespace base |
349 | 293 |
350 | 294 |
351 const std::string& EmptyString() { | 295 const std::string& EmptyString() { |
352 return *Singleton<std::string>::get(); | 296 return *Singleton<std::string>::get(); |
353 } | 297 } |
354 | 298 |
355 const std::wstring& EmptyWString() { | 299 const std::wstring& EmptyWString() { |
356 return *Singleton<std::wstring>::get(); | 300 return *Singleton<std::wstring>::get(); |
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1047 } | 991 } |
1048 std::string Uint64ToString(uint64 value) { | 992 std::string Uint64ToString(uint64 value) { |
1049 return IntToStringT<std::string, uint64, uint64, false>:: | 993 return IntToStringT<std::string, uint64, uint64, false>:: |
1050 IntToString(value); | 994 IntToString(value); |
1051 } | 995 } |
1052 std::wstring Uint64ToWString(uint64 value) { | 996 std::wstring Uint64ToWString(uint64 value) { |
1053 return IntToStringT<std::wstring, uint64, uint64, false>:: | 997 return IntToStringT<std::wstring, uint64, uint64, false>:: |
1054 IntToString(value); | 998 IntToString(value); |
1055 } | 999 } |
1056 | 1000 |
| 1001 std::string DoubleToString(double value) { |
| 1002 // According to g_fmt.cc, it is sufficient to declare a buffer of size 32. |
| 1003 char buffer[32]; |
| 1004 dmg_fp::g_fmt(buffer, value); |
| 1005 return std::string(buffer); |
| 1006 } |
| 1007 |
| 1008 std::wstring DoubleToWString(double value) { |
| 1009 return ASCIIToWide(DoubleToString(value)); |
| 1010 } |
| 1011 |
1057 inline void StringAppendV(std::string* dst, const char* format, va_list ap) { | 1012 inline void StringAppendV(std::string* dst, const char* format, va_list ap) { |
1058 StringAppendVT<char>(dst, format, ap); | 1013 StringAppendVT<char>(dst, format, ap); |
1059 } | 1014 } |
1060 | 1015 |
1061 inline void StringAppendV(std::wstring* dst, | 1016 inline void StringAppendV(std::wstring* dst, |
1062 const wchar_t* format, | 1017 const wchar_t* format, |
1063 va_list ap) { | 1018 va_list ap) { |
1064 StringAppendVT<wchar_t>(dst, format, ap); | 1019 StringAppendVT<wchar_t>(dst, format, ap); |
1065 } | 1020 } |
1066 | 1021 |
1067 bool StringToDouble(const std::string& input, double* output) { | |
1068 return StringToDouble(input, output, base::LOCALE_DEPENDENT); | |
1069 } | |
1070 | |
1071 bool StringToDouble(const std::wstring& input, double* output) { | |
1072 return StringToDouble(input, output, base::LOCALE_DEPENDENT); | |
1073 } | |
1074 | |
1075 double StringToDouble(const std::string& value) { | |
1076 return StringToDouble(value, base::LOCALE_DEPENDENT); | |
1077 } | |
1078 | |
1079 double StringToDouble(const std::wstring& value) { | |
1080 return StringToDouble(value, base::LOCALE_DEPENDENT); | |
1081 } | |
1082 | |
1083 std::string StringPrintf(const char* format, ...) { | 1022 std::string StringPrintf(const char* format, ...) { |
1084 va_list ap; | 1023 va_list ap; |
1085 va_start(ap, format); | 1024 va_start(ap, format); |
1086 std::string result; | 1025 std::string result; |
1087 StringAppendV(&result, format, ap); | 1026 StringAppendV(&result, format, ap); |
1088 va_end(ap); | 1027 va_end(ap); |
1089 return result; | 1028 return result; |
1090 } | 1029 } |
1091 | 1030 |
1092 std::wstring StringPrintf(const wchar_t* format, ...) { | 1031 std::wstring StringPrintf(const wchar_t* format, ...) { |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1412 } | 1351 } |
1413 | 1352 |
1414 // For the various *ToInt conversions, there are no *ToIntTraits classes to use | 1353 // For the various *ToInt conversions, there are no *ToIntTraits classes to use |
1415 // because there's no such thing as strtoi. Use *ToLongTraits through a cast | 1354 // because there's no such thing as strtoi. Use *ToLongTraits through a cast |
1416 // instead, requiring that long and int are compatible and equal-width. They | 1355 // instead, requiring that long and int are compatible and equal-width. They |
1417 // are on our target platforms. | 1356 // are on our target platforms. |
1418 | 1357 |
1419 bool StringToInt(const std::string& input, int* output) { | 1358 bool StringToInt(const std::string& input, int* output) { |
1420 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_strtol_to_int); | 1359 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_strtol_to_int); |
1421 return StringToNumber<StringToLongTraits>(input, | 1360 return StringToNumber<StringToLongTraits>(input, |
1422 reinterpret_cast<long*>(output), | 1361 reinterpret_cast<long*>(output)); |
1423 base::LOCALE_DEPENDENT); | |
1424 } | 1362 } |
1425 | 1363 |
1426 bool StringToInt(const std::wstring& input, int* output) { | 1364 bool StringToInt(const std::wstring& input, int* output) { |
1427 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_wcstol_to_int); | 1365 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_wcstol_to_int); |
1428 return StringToNumber<WStringToLongTraits>(input, | 1366 return StringToNumber<WStringToLongTraits>(input, |
1429 reinterpret_cast<long*>(output), | 1367 reinterpret_cast<long*>(output)); |
1430 base::LOCALE_DEPENDENT); | |
1431 } | 1368 } |
1432 | 1369 |
1433 bool StringToInt64(const std::string& input, int64* output) { | 1370 bool StringToInt64(const std::string& input, int64* output) { |
1434 return StringToNumber<StringToInt64Traits>(input, output, base::LOCALE_DEPENDE
NT); | 1371 return StringToNumber<StringToInt64Traits>(input, output); |
1435 } | 1372 } |
1436 | 1373 |
1437 bool StringToInt64(const std::wstring& input, int64* output) { | 1374 bool StringToInt64(const std::wstring& input, int64* output) { |
1438 return StringToNumber<WStringToInt64Traits>(input, output, base::LOCALE_DEPEND
ENT); | 1375 return StringToNumber<WStringToInt64Traits>(input, output); |
1439 } | 1376 } |
1440 | 1377 |
1441 bool HexStringToInt(const std::string& input, int* output) { | 1378 bool HexStringToInt(const std::string& input, int* output) { |
1442 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_strtol_to_int); | 1379 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_strtol_to_int); |
1443 return StringToNumber<HexStringToLongTraits>(input, | 1380 return StringToNumber<HexStringToLongTraits>(input, |
1444 reinterpret_cast<long*>(output), | 1381 reinterpret_cast<long*>(output)); |
1445 base::LOCALE_DEPENDENT); | |
1446 } | 1382 } |
1447 | 1383 |
1448 bool HexStringToInt(const std::wstring& input, int* output) { | 1384 bool HexStringToInt(const std::wstring& input, int* output) { |
1449 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_wcstol_to_int); | 1385 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_wcstol_to_int); |
1450 return StringToNumber<HexWStringToLongTraits>( | 1386 return StringToNumber<HexWStringToLongTraits>( |
1451 input, reinterpret_cast<long*>(output), base::LOCALE_DEPENDENT); | 1387 input, reinterpret_cast<long*>(output)); |
1452 } | 1388 } |
1453 | 1389 |
1454 int StringToInt(const std::string& value) { | 1390 int StringToInt(const std::string& value) { |
1455 int result; | 1391 int result; |
1456 StringToInt(value, &result); | 1392 StringToInt(value, &result); |
1457 return result; | 1393 return result; |
1458 } | 1394 } |
1459 | 1395 |
1460 int StringToInt(const std::wstring& value) { | 1396 int StringToInt(const std::wstring& value) { |
1461 int result; | 1397 int result; |
(...skipping 18 matching lines...) Expand all Loading... |
1480 HexStringToInt(value, &result); | 1416 HexStringToInt(value, &result); |
1481 return result; | 1417 return result; |
1482 } | 1418 } |
1483 | 1419 |
1484 int HexStringToInt(const std::wstring& value) { | 1420 int HexStringToInt(const std::wstring& value) { |
1485 int result; | 1421 int result; |
1486 HexStringToInt(value, &result); | 1422 HexStringToInt(value, &result); |
1487 return result; | 1423 return result; |
1488 } | 1424 } |
1489 | 1425 |
| 1426 bool StringToDouble(const std::string& input, double* output) { |
| 1427 return StringToNumber<StringToDoubleTraits>(input, output); |
| 1428 } |
| 1429 |
| 1430 bool StringToDouble(const std::wstring& input, double* output) { |
| 1431 return StringToNumber<WStringToDoubleTraits>(input, output); |
| 1432 } |
| 1433 |
| 1434 double StringToDouble(const std::string& value) { |
| 1435 double result; |
| 1436 StringToDouble(value, &result); |
| 1437 return result; |
| 1438 } |
| 1439 |
| 1440 double StringToDouble(const std::wstring& value) { |
| 1441 double result; |
| 1442 StringToDouble(value, &result); |
| 1443 return result; |
| 1444 } |
| 1445 |
1490 // The following code is compatible with the OpenBSD lcpy interface. See: | 1446 // The following code is compatible with the OpenBSD lcpy interface. See: |
1491 // http://www.gratisoft.us/todd/papers/strlcpy.html | 1447 // http://www.gratisoft.us/todd/papers/strlcpy.html |
1492 // ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c | 1448 // ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c |
1493 | 1449 |
1494 namespace { | 1450 namespace { |
1495 | 1451 |
1496 template <typename CHAR> | 1452 template <typename CHAR> |
1497 size_t lcpyT(CHAR* dst, const CHAR* src, size_t dst_size) { | 1453 size_t lcpyT(CHAR* dst, const CHAR* src, size_t dst_size) { |
1498 for (size_t i = 0; i < dst_size; ++i) { | 1454 for (size_t i = 0; i < dst_size; ++i) { |
1499 if ((dst[i] = src[i]) == 0) // We hit and copied the terminating NULL. | 1455 if ((dst[i] = src[i]) == 0) // We hit and copied the terminating NULL. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1547 int rstr_len = (max_len - 3) / 2; | 1503 int rstr_len = (max_len - 3) / 2; |
1548 int lstr_len = rstr_len + ((max_len - 3) % 2); | 1504 int lstr_len = rstr_len + ((max_len - 3) % 2); |
1549 output->assign(input.substr(0, lstr_len) + L"..." + | 1505 output->assign(input.substr(0, lstr_len) + L"..." + |
1550 input.substr(input.length() - rstr_len)); | 1506 input.substr(input.length() - rstr_len)); |
1551 break; | 1507 break; |
1552 } | 1508 } |
1553 } | 1509 } |
1554 | 1510 |
1555 return true; | 1511 return true; |
1556 } | 1512 } |
OLD | NEW |