1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/glue/nsStringAPI.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1203 @@ 1.4 +/* vim:set ts=2 sw=2 et cindent: */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nscore.h" 1.10 +#include "nsCRTGlue.h" 1.11 +#include "prprf.h" 1.12 +#include "nsStringAPI.h" 1.13 +#include "nsXPCOMStrings.h" 1.14 +#include "nsDebug.h" 1.15 + 1.16 +#include <stdio.h> 1.17 + 1.18 +#ifdef XP_WIN 1.19 +#define snprintf _snprintf 1.20 +#endif 1.21 + 1.22 +// nsAString 1.23 + 1.24 +uint32_t 1.25 +nsAString::BeginReading(const char_type **begin, const char_type **end) const 1.26 +{ 1.27 + uint32_t len = NS_StringGetData(*this, begin); 1.28 + if (end) 1.29 + *end = *begin + len; 1.30 + 1.31 + return len; 1.32 +} 1.33 + 1.34 +const nsAString::char_type* 1.35 +nsAString::BeginReading() const 1.36 +{ 1.37 + const char_type *data; 1.38 + NS_StringGetData(*this, &data); 1.39 + return data; 1.40 +} 1.41 + 1.42 +const nsAString::char_type* 1.43 +nsAString::EndReading() const 1.44 +{ 1.45 + const char_type *data; 1.46 + uint32_t len = NS_StringGetData(*this, &data); 1.47 + return data + len; 1.48 +} 1.49 + 1.50 +uint32_t 1.51 +nsAString::BeginWriting(char_type **begin, char_type **end, uint32_t newSize) 1.52 +{ 1.53 + uint32_t len = NS_StringGetMutableData(*this, newSize, begin); 1.54 + if (end) 1.55 + *end = *begin + len; 1.56 + 1.57 + return len; 1.58 +} 1.59 + 1.60 +nsAString::char_type* 1.61 +nsAString::BeginWriting(uint32_t aLen) 1.62 +{ 1.63 + char_type *data; 1.64 + NS_StringGetMutableData(*this, aLen, &data); 1.65 + return data; 1.66 +} 1.67 + 1.68 +nsAString::char_type* 1.69 +nsAString::EndWriting() 1.70 +{ 1.71 + char_type *data; 1.72 + uint32_t len = NS_StringGetMutableData(*this, UINT32_MAX, &data); 1.73 + return data + len; 1.74 +} 1.75 + 1.76 +bool 1.77 +nsAString::SetLength(uint32_t aLen) 1.78 +{ 1.79 + char_type *data; 1.80 + NS_StringGetMutableData(*this, aLen, &data); 1.81 + return data != nullptr; 1.82 +} 1.83 + 1.84 +void 1.85 +nsAString::AssignLiteral(const char *aStr) 1.86 +{ 1.87 + uint32_t len = strlen(aStr); 1.88 + char16_t *buf = BeginWriting(len); 1.89 + if (!buf) 1.90 + return; 1.91 + 1.92 + for (; *aStr; ++aStr, ++buf) 1.93 + *buf = *aStr; 1.94 +} 1.95 + 1.96 +void 1.97 +nsAString::AppendLiteral(const char *aASCIIStr) 1.98 +{ 1.99 + uint32_t appendLen = strlen(aASCIIStr); 1.100 + 1.101 + uint32_t thisLen = Length(); 1.102 + char16_t *begin, *end; 1.103 + BeginWriting(&begin, &end, appendLen + thisLen); 1.104 + if (!begin) 1.105 + return; 1.106 + 1.107 + for (begin += thisLen; begin < end; ++begin, ++aASCIIStr) 1.108 + *begin = *aASCIIStr; 1.109 +} 1.110 + 1.111 +void 1.112 +nsAString::StripChars(const char *aSet) 1.113 +{ 1.114 + nsString copy(*this); 1.115 + 1.116 + const char_type *source, *sourceEnd; 1.117 + copy.BeginReading(&source, &sourceEnd); 1.118 + 1.119 + char_type *dest; 1.120 + BeginWriting(&dest); 1.121 + if (!dest) 1.122 + return; 1.123 + 1.124 + char_type *curDest = dest; 1.125 + 1.126 + for (; source < sourceEnd; ++source) { 1.127 + const char *test; 1.128 + for (test = aSet; *test; ++test) { 1.129 + if (*source == char_type(*test)) 1.130 + break; 1.131 + } 1.132 + 1.133 + if (!*test) { 1.134 + // not stripped, copy this char 1.135 + *curDest = *source; 1.136 + ++curDest; 1.137 + } 1.138 + } 1.139 + 1.140 + SetLength(curDest - dest); 1.141 +} 1.142 + 1.143 +void 1.144 +nsAString::Trim(const char *aSet, bool aLeading, bool aTrailing) 1.145 +{ 1.146 + NS_ASSERTION(aLeading || aTrailing, "Ineffective Trim"); 1.147 + 1.148 + const char16_t *start, *end; 1.149 + uint32_t cutLen; 1.150 + 1.151 + if (aLeading) { 1.152 + BeginReading(&start, &end); 1.153 + for (cutLen = 0; start < end; ++start, ++cutLen) { 1.154 + const char *test; 1.155 + for (test = aSet; *test; ++test) { 1.156 + if (*test == *start) 1.157 + break; 1.158 + } 1.159 + if (!*test) 1.160 + break; 1.161 + } 1.162 + if (cutLen) { 1.163 + NS_StringCutData(*this, 0, cutLen); 1.164 + } 1.165 + } 1.166 + if (aTrailing) { 1.167 + uint32_t len = BeginReading(&start, &end); 1.168 + --end; 1.169 + for (cutLen = 0; end >= start; --end, ++cutLen) { 1.170 + const char *test; 1.171 + for (test = aSet; *test; ++test) { 1.172 + if (*test == *end) 1.173 + break; 1.174 + } 1.175 + if (!*test) 1.176 + break; 1.177 + } 1.178 + if (cutLen) { 1.179 + NS_StringCutData(*this, len - cutLen, cutLen); 1.180 + } 1.181 + } 1.182 +} 1.183 + 1.184 +int32_t 1.185 +nsAString::DefaultComparator(const char_type *a, const char_type *b, 1.186 + uint32_t len) 1.187 +{ 1.188 + for (const char_type *end = a + len; a < end; ++a, ++b) { 1.189 + if (*a == *b) 1.190 + continue; 1.191 + 1.192 + return *a < *b ? -1 : 1; 1.193 + } 1.194 + 1.195 + return 0; 1.196 +} 1.197 + 1.198 +int32_t 1.199 +nsAString::Compare(const char_type *other, ComparatorFunc c) const 1.200 +{ 1.201 + const char_type *cself; 1.202 + uint32_t selflen = NS_StringGetData(*this, &cself); 1.203 + uint32_t otherlen = NS_strlen(other); 1.204 + uint32_t comparelen = selflen <= otherlen ? selflen : otherlen; 1.205 + 1.206 + int32_t result = c(cself, other, comparelen); 1.207 + if (result == 0) { 1.208 + if (selflen < otherlen) 1.209 + return -1; 1.210 + else if (selflen > otherlen) 1.211 + return 1; 1.212 + } 1.213 + return result; 1.214 +} 1.215 + 1.216 +int32_t 1.217 +nsAString::Compare(const self_type &other, ComparatorFunc c) const 1.218 +{ 1.219 + const char_type *cself, *cother; 1.220 + uint32_t selflen = NS_StringGetData(*this, &cself); 1.221 + uint32_t otherlen = NS_StringGetData(other, &cother); 1.222 + uint32_t comparelen = selflen <= otherlen ? selflen : otherlen; 1.223 + 1.224 + int32_t result = c(cself, cother, comparelen); 1.225 + if (result == 0) { 1.226 + if (selflen < otherlen) 1.227 + return -1; 1.228 + else if (selflen > otherlen) 1.229 + return 1; 1.230 + } 1.231 + return result; 1.232 +} 1.233 + 1.234 +bool 1.235 +nsAString::Equals(const char_type *other, ComparatorFunc c) const 1.236 +{ 1.237 + const char_type *cself; 1.238 + uint32_t selflen = NS_StringGetData(*this, &cself); 1.239 + uint32_t otherlen = NS_strlen(other); 1.240 + 1.241 + if (selflen != otherlen) 1.242 + return false; 1.243 + 1.244 + return c(cself, other, selflen) == 0; 1.245 +} 1.246 + 1.247 +bool 1.248 +nsAString::Equals(const self_type &other, ComparatorFunc c) const 1.249 +{ 1.250 + const char_type *cself; 1.251 + const char_type *cother; 1.252 + uint32_t selflen = NS_StringGetData(*this, &cself); 1.253 + uint32_t otherlen = NS_StringGetData(other, &cother); 1.254 + 1.255 + if (selflen != otherlen) 1.256 + return false; 1.257 + 1.258 + return c(cself, cother, selflen) == 0; 1.259 +} 1.260 + 1.261 +bool 1.262 +nsAString::EqualsLiteral(const char *aASCIIString) const 1.263 +{ 1.264 + const char16_t *begin, *end; 1.265 + BeginReading(&begin, &end); 1.266 + 1.267 + for (; begin < end; ++begin, ++aASCIIString) { 1.268 + if (!*aASCIIString || !NS_IsAscii(*begin) || 1.269 + (char) *begin != *aASCIIString) { 1.270 + return false; 1.271 + } 1.272 + } 1.273 + 1.274 + return *aASCIIString == '\0'; 1.275 +} 1.276 + 1.277 +bool 1.278 +nsAString::LowerCaseEqualsLiteral(const char *aASCIIString) const 1.279 +{ 1.280 + const char16_t *begin, *end; 1.281 + BeginReading(&begin, &end); 1.282 + 1.283 + for (; begin < end; ++begin, ++aASCIIString) { 1.284 + if (!*aASCIIString || !NS_IsAscii(*begin) || 1.285 + NS_ToLower((char) *begin) != *aASCIIString) { 1.286 + return false; 1.287 + } 1.288 + } 1.289 + 1.290 + return *aASCIIString == '\0'; 1.291 +} 1.292 + 1.293 +int32_t 1.294 +nsAString::Find(const self_type& aStr, uint32_t aOffset, 1.295 + ComparatorFunc c) const 1.296 +{ 1.297 + const char_type *begin, *end; 1.298 + uint32_t selflen = BeginReading(&begin, &end); 1.299 + 1.300 + if (aOffset > selflen) 1.301 + return -1; 1.302 + 1.303 + const char_type *other; 1.304 + uint32_t otherlen = aStr.BeginReading(&other); 1.305 + 1.306 + if (otherlen > selflen - aOffset) 1.307 + return -1; 1.308 + 1.309 + // We want to stop searching otherlen characters before the end of the string 1.310 + end -= otherlen; 1.311 + 1.312 + for (const char_type *cur = begin + aOffset; cur <= end; ++cur) { 1.313 + if (!c(cur, other, otherlen)) 1.314 + return cur - begin; 1.315 + } 1.316 + return -1; 1.317 +} 1.318 + 1.319 +static bool ns_strnmatch(const char16_t *aStr, const char* aSubstring, 1.320 + uint32_t aLen) 1.321 +{ 1.322 + for (; aLen; ++aStr, ++aSubstring, --aLen) { 1.323 + if (!NS_IsAscii(*aStr)) 1.324 + return false; 1.325 + 1.326 + if ((char) *aStr != *aSubstring) 1.327 + return false; 1.328 + } 1.329 + 1.330 + return true; 1.331 +} 1.332 + 1.333 +static bool ns_strnimatch(const char16_t *aStr, const char* aSubstring, 1.334 + uint32_t aLen) 1.335 +{ 1.336 + for (; aLen; ++aStr, ++aSubstring, --aLen) { 1.337 + if (!NS_IsAscii(*aStr)) 1.338 + return false; 1.339 + 1.340 + if (NS_ToLower((char) *aStr) != NS_ToLower(*aSubstring)) 1.341 + return false; 1.342 + } 1.343 + 1.344 + return true; 1.345 +} 1.346 + 1.347 +int32_t 1.348 +nsAString::Find(const char *aStr, uint32_t aOffset, bool aIgnoreCase) const 1.349 +{ 1.350 + bool (*match)(const char16_t*, const char*, uint32_t) = 1.351 + aIgnoreCase ? ns_strnimatch : ns_strnmatch; 1.352 + 1.353 + const char_type *begin, *end; 1.354 + uint32_t selflen = BeginReading(&begin, &end); 1.355 + 1.356 + if (aOffset > selflen) 1.357 + return -1; 1.358 + 1.359 + uint32_t otherlen = strlen(aStr); 1.360 + 1.361 + if (otherlen > selflen - aOffset) 1.362 + return -1; 1.363 + 1.364 + // We want to stop searching otherlen characters before the end of the string 1.365 + end -= otherlen; 1.366 + 1.367 + for (const char_type *cur = begin + aOffset; cur <= end; ++cur) { 1.368 + if (match(cur, aStr, otherlen)) { 1.369 + return cur - begin; 1.370 + } 1.371 + } 1.372 + return -1; 1.373 +} 1.374 + 1.375 +int32_t 1.376 +nsAString::RFind(const self_type& aStr, int32_t aOffset, ComparatorFunc c) const 1.377 +{ 1.378 + const char_type *begin, *end; 1.379 + uint32_t selflen = BeginReading(&begin, &end); 1.380 + 1.381 + const char_type *other; 1.382 + uint32_t otherlen = aStr.BeginReading(&other); 1.383 + 1.384 + if (selflen < otherlen) 1.385 + return -1; 1.386 + 1.387 + if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen)) 1.388 + end -= otherlen; 1.389 + else 1.390 + end = begin + aOffset; 1.391 + 1.392 + for (const char_type *cur = end; cur >= begin; --cur) { 1.393 + if (!c(cur, other, otherlen)) 1.394 + return cur - begin; 1.395 + } 1.396 + return -1; 1.397 +} 1.398 + 1.399 +int32_t 1.400 +nsAString::RFind(const char *aStr, int32_t aOffset, bool aIgnoreCase) const 1.401 +{ 1.402 + bool (*match)(const char16_t*, const char*, uint32_t) = 1.403 + aIgnoreCase ? ns_strnimatch : ns_strnmatch; 1.404 + 1.405 + const char_type *begin, *end; 1.406 + uint32_t selflen = BeginReading(&begin, &end); 1.407 + uint32_t otherlen = strlen(aStr); 1.408 + 1.409 + if (selflen < otherlen) 1.410 + return -1; 1.411 + 1.412 + if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen)) 1.413 + end -= otherlen; 1.414 + else 1.415 + end = begin + aOffset; 1.416 + 1.417 + for (const char_type *cur = end; cur >= begin; --cur) { 1.418 + if (match(cur, aStr, otherlen)) { 1.419 + return cur - begin; 1.420 + } 1.421 + } 1.422 + return -1; 1.423 +} 1.424 + 1.425 +int32_t 1.426 +nsAString::FindChar(char_type aChar, uint32_t aOffset) const 1.427 +{ 1.428 + const char_type *start, *end; 1.429 + uint32_t len = BeginReading(&start, &end); 1.430 + if (aOffset > len) 1.431 + return -1; 1.432 + 1.433 + const char_type *cur; 1.434 + 1.435 + for (cur = start + aOffset; cur < end; ++cur) { 1.436 + if (*cur == aChar) 1.437 + return cur - start; 1.438 + } 1.439 + 1.440 + return -1; 1.441 +} 1.442 + 1.443 +int32_t 1.444 +nsAString::RFindChar(char_type aChar) const 1.445 +{ 1.446 + const char16_t *start, *end; 1.447 + BeginReading(&start, &end); 1.448 + 1.449 + do { 1.450 + --end; 1.451 + 1.452 + if (*end == aChar) 1.453 + return end - start; 1.454 + 1.455 + } while (end >= start); 1.456 + 1.457 + return -1; 1.458 +} 1.459 + 1.460 +void 1.461 +nsAString::AppendInt(int aInt, int32_t aRadix) 1.462 +{ 1.463 + const char *fmt; 1.464 + switch (aRadix) { 1.465 + case 8: 1.466 + fmt = "%o"; 1.467 + break; 1.468 + 1.469 + case 10: 1.470 + fmt = "%d"; 1.471 + break; 1.472 + 1.473 + case 16: 1.474 + fmt = "%x"; 1.475 + break; 1.476 + 1.477 + default: 1.478 + NS_ERROR("Unrecognized radix"); 1.479 + fmt = ""; 1.480 + }; 1.481 + 1.482 + char buf[20]; 1.483 + int len = snprintf(buf, sizeof(buf), fmt, aInt); 1.484 + buf[sizeof(buf) - 1] = '\0'; 1.485 + 1.486 + Append(NS_ConvertASCIItoUTF16(buf, len)); 1.487 +} 1.488 + 1.489 +// Strings 1.490 + 1.491 +#ifndef XPCOM_GLUE_AVOID_NSPR 1.492 +int32_t 1.493 +nsAString::ToInteger(nsresult *aErrorCode, uint32_t aRadix) const 1.494 +{ 1.495 + NS_ConvertUTF16toUTF8 narrow(*this); 1.496 + 1.497 + const char *fmt; 1.498 + switch (aRadix) { 1.499 + case 10: 1.500 + fmt = "%i"; 1.501 + break; 1.502 + 1.503 + case 16: 1.504 + fmt = "%x"; 1.505 + break; 1.506 + 1.507 + default: 1.508 + NS_ERROR("Unrecognized radix!"); 1.509 + *aErrorCode = NS_ERROR_INVALID_ARG; 1.510 + return 0; 1.511 + } 1.512 + 1.513 + int32_t result = 0; 1.514 + if (PR_sscanf(narrow.get(), fmt, &result) == 1) 1.515 + *aErrorCode = NS_OK; 1.516 + else 1.517 + *aErrorCode = NS_ERROR_FAILURE; 1.518 + 1.519 + return result; 1.520 +} 1.521 + 1.522 +int64_t 1.523 +nsAString::ToInteger64(nsresult *aErrorCode, uint32_t aRadix) const 1.524 +{ 1.525 + NS_ConvertUTF16toUTF8 narrow(*this); 1.526 + 1.527 + const char *fmt; 1.528 + switch (aRadix) { 1.529 + case 10: 1.530 + fmt = "%lli"; 1.531 + break; 1.532 + 1.533 + case 16: 1.534 + fmt = "%llx"; 1.535 + break; 1.536 + 1.537 + default: 1.538 + NS_ERROR("Unrecognized radix!"); 1.539 + *aErrorCode = NS_ERROR_INVALID_ARG; 1.540 + return 0; 1.541 + } 1.542 + 1.543 + int64_t result = 0; 1.544 + if (PR_sscanf(narrow.get(), fmt, &result) == 1) 1.545 + *aErrorCode = NS_OK; 1.546 + else 1.547 + *aErrorCode = NS_ERROR_FAILURE; 1.548 + 1.549 + return result; 1.550 +} 1.551 +#endif // XPCOM_GLUE_AVOID_NSPR 1.552 + 1.553 +// nsACString 1.554 + 1.555 +uint32_t 1.556 +nsACString::BeginReading(const char_type **begin, const char_type **end) const 1.557 +{ 1.558 + uint32_t len = NS_CStringGetData(*this, begin); 1.559 + if (end) 1.560 + *end = *begin + len; 1.561 + 1.562 + return len; 1.563 +} 1.564 + 1.565 +const nsACString::char_type* 1.566 +nsACString::BeginReading() const 1.567 +{ 1.568 + const char_type *data; 1.569 + NS_CStringGetData(*this, &data); 1.570 + return data; 1.571 +} 1.572 + 1.573 +const nsACString::char_type* 1.574 +nsACString::EndReading() const 1.575 +{ 1.576 + const char_type *data; 1.577 + uint32_t len = NS_CStringGetData(*this, &data); 1.578 + return data + len; 1.579 +} 1.580 + 1.581 +uint32_t 1.582 +nsACString::BeginWriting(char_type **begin, char_type **end, uint32_t newSize) 1.583 +{ 1.584 + uint32_t len = NS_CStringGetMutableData(*this, newSize, begin); 1.585 + if (end) 1.586 + *end = *begin + len; 1.587 + 1.588 + return len; 1.589 +} 1.590 + 1.591 +nsACString::char_type* 1.592 +nsACString::BeginWriting(uint32_t aLen) 1.593 +{ 1.594 + char_type *data; 1.595 + NS_CStringGetMutableData(*this, aLen, &data); 1.596 + return data; 1.597 +} 1.598 + 1.599 +nsACString::char_type* 1.600 +nsACString::EndWriting() 1.601 +{ 1.602 + char_type *data; 1.603 + uint32_t len = NS_CStringGetMutableData(*this, UINT32_MAX, &data); 1.604 + return data + len; 1.605 +} 1.606 + 1.607 +bool 1.608 +nsACString::SetLength(uint32_t aLen) 1.609 +{ 1.610 + char_type *data; 1.611 + NS_CStringGetMutableData(*this, aLen, &data); 1.612 + return data != nullptr; 1.613 +} 1.614 + 1.615 +void 1.616 +nsACString::StripChars(const char *aSet) 1.617 +{ 1.618 + nsCString copy(*this); 1.619 + 1.620 + const char_type *source, *sourceEnd; 1.621 + copy.BeginReading(&source, &sourceEnd); 1.622 + 1.623 + char_type *dest; 1.624 + BeginWriting(&dest); 1.625 + if (!dest) 1.626 + return; 1.627 + 1.628 + char_type *curDest = dest; 1.629 + 1.630 + for (; source < sourceEnd; ++source) { 1.631 + const char *test; 1.632 + for (test = aSet; *test; ++test) { 1.633 + if (*source == char_type(*test)) 1.634 + break; 1.635 + } 1.636 + 1.637 + if (!*test) { 1.638 + // not stripped, copy this char 1.639 + *curDest = *source; 1.640 + ++curDest; 1.641 + } 1.642 + } 1.643 + 1.644 + SetLength(curDest - dest); 1.645 +} 1.646 + 1.647 +void 1.648 +nsACString::Trim(const char *aSet, bool aLeading, bool aTrailing) 1.649 +{ 1.650 + NS_ASSERTION(aLeading || aTrailing, "Ineffective Trim"); 1.651 + 1.652 + const char *start, *end; 1.653 + uint32_t cutLen; 1.654 + 1.655 + if (aLeading) { 1.656 + BeginReading(&start, &end); 1.657 + for (cutLen = 0; start < end; ++start, ++cutLen) { 1.658 + const char *test; 1.659 + for (test = aSet; *test; ++test) { 1.660 + if (*test == *start) 1.661 + break; 1.662 + } 1.663 + if (!*test) 1.664 + break; 1.665 + } 1.666 + if (cutLen) { 1.667 + NS_CStringCutData(*this, 0, cutLen); 1.668 + } 1.669 + } 1.670 + if (aTrailing) { 1.671 + uint32_t len = BeginReading(&start, &end); 1.672 + --end; 1.673 + for (cutLen = 0; end >= start; --end, ++cutLen) { 1.674 + const char *test; 1.675 + for (test = aSet; *test; ++test) { 1.676 + if (*test == *end) 1.677 + break; 1.678 + } 1.679 + if (!*test) 1.680 + break; 1.681 + } 1.682 + if (cutLen) { 1.683 + NS_CStringCutData(*this, len - cutLen, cutLen); 1.684 + } 1.685 + } 1.686 +} 1.687 + 1.688 +int32_t 1.689 +nsACString::DefaultComparator(const char_type *a, const char_type *b, 1.690 + uint32_t len) 1.691 +{ 1.692 + return memcmp(a, b, len); 1.693 +} 1.694 + 1.695 +int32_t 1.696 +nsACString::Compare(const char_type *other, ComparatorFunc c) const 1.697 +{ 1.698 + const char_type *cself; 1.699 + uint32_t selflen = NS_CStringGetData(*this, &cself); 1.700 + uint32_t otherlen = strlen(other); 1.701 + uint32_t comparelen = selflen <= otherlen ? selflen : otherlen; 1.702 + 1.703 + int32_t result = c(cself, other, comparelen); 1.704 + if (result == 0) { 1.705 + if (selflen < otherlen) 1.706 + return -1; 1.707 + else if (selflen > otherlen) 1.708 + return 1; 1.709 + } 1.710 + return result; 1.711 +} 1.712 + 1.713 +int32_t 1.714 +nsACString::Compare(const self_type &other, ComparatorFunc c) const 1.715 +{ 1.716 + const char_type *cself, *cother; 1.717 + uint32_t selflen = NS_CStringGetData(*this, &cself); 1.718 + uint32_t otherlen = NS_CStringGetData(other, &cother); 1.719 + uint32_t comparelen = selflen <= otherlen ? selflen : otherlen; 1.720 + 1.721 + int32_t result = c(cself, cother, comparelen); 1.722 + if (result == 0) { 1.723 + if (selflen < otherlen) 1.724 + return -1; 1.725 + else if (selflen > otherlen) 1.726 + return 1; 1.727 + } 1.728 + return result; 1.729 +} 1.730 + 1.731 +bool 1.732 +nsACString::Equals(const char_type *other, ComparatorFunc c) const 1.733 +{ 1.734 + const char_type *cself; 1.735 + uint32_t selflen = NS_CStringGetData(*this, &cself); 1.736 + uint32_t otherlen = strlen(other); 1.737 + 1.738 + if (selflen != otherlen) 1.739 + return false; 1.740 + 1.741 + return c(cself, other, selflen) == 0; 1.742 +} 1.743 + 1.744 +bool 1.745 +nsACString::Equals(const self_type &other, ComparatorFunc c) const 1.746 +{ 1.747 + const char_type *cself; 1.748 + const char_type *cother; 1.749 + uint32_t selflen = NS_CStringGetData(*this, &cself); 1.750 + uint32_t otherlen = NS_CStringGetData(other, &cother); 1.751 + 1.752 + if (selflen != otherlen) 1.753 + return false; 1.754 + 1.755 + return c(cself, cother, selflen) == 0; 1.756 +} 1.757 + 1.758 +int32_t 1.759 +nsACString::Find(const self_type& aStr, uint32_t aOffset, 1.760 + ComparatorFunc c) const 1.761 +{ 1.762 + const char_type *begin, *end; 1.763 + uint32_t selflen = BeginReading(&begin, &end); 1.764 + 1.765 + if (aOffset > selflen) 1.766 + return -1; 1.767 + 1.768 + const char_type *other; 1.769 + uint32_t otherlen = aStr.BeginReading(&other); 1.770 + 1.771 + if (otherlen > selflen - aOffset) 1.772 + return -1; 1.773 + 1.774 + // We want to stop searching otherlen characters before the end of the string 1.775 + end -= otherlen; 1.776 + 1.777 + for (const char_type *cur = begin + aOffset; cur <= end; ++cur) { 1.778 + if (!c(cur, other, otherlen)) 1.779 + return cur - begin; 1.780 + } 1.781 + return -1; 1.782 +} 1.783 + 1.784 +int32_t 1.785 +nsACString::Find(const char_type *aStr, ComparatorFunc c) const 1.786 +{ 1.787 + return Find(aStr, strlen(aStr), c); 1.788 +} 1.789 + 1.790 +int32_t 1.791 +nsACString::Find(const char_type *aStr, uint32_t aLen, ComparatorFunc c) const 1.792 +{ 1.793 + const char_type *begin, *end; 1.794 + uint32_t selflen = BeginReading(&begin, &end); 1.795 + 1.796 + if (aLen == 0) { 1.797 + NS_WARNING("Searching for zero-length string."); 1.798 + return -1; 1.799 + } 1.800 + 1.801 + if (aLen > selflen) 1.802 + return -1; 1.803 + 1.804 + // We want to stop searching otherlen characters before the end of the string 1.805 + end -= aLen; 1.806 + 1.807 + for (const char_type *cur = begin; cur <= end; ++cur) { 1.808 + if (!c(cur, aStr, aLen)) 1.809 + return cur - begin; 1.810 + } 1.811 + return -1; 1.812 +} 1.813 + 1.814 +int32_t 1.815 +nsACString::RFind(const self_type& aStr, int32_t aOffset, ComparatorFunc c) const 1.816 +{ 1.817 + const char_type *begin, *end; 1.818 + uint32_t selflen = BeginReading(&begin, &end); 1.819 + 1.820 + const char_type *other; 1.821 + uint32_t otherlen = aStr.BeginReading(&other); 1.822 + 1.823 + if (selflen < otherlen) 1.824 + return -1; 1.825 + 1.826 + if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen)) 1.827 + end -= otherlen; 1.828 + else 1.829 + end = begin + aOffset; 1.830 + 1.831 + for (const char_type *cur = end; cur >= begin; --cur) { 1.832 + if (!c(cur, other, otherlen)) 1.833 + return cur - begin; 1.834 + } 1.835 + return -1; 1.836 +} 1.837 + 1.838 +int32_t 1.839 +nsACString::RFind(const char_type *aStr, ComparatorFunc c) const 1.840 +{ 1.841 + return RFind(aStr, strlen(aStr), c); 1.842 +} 1.843 + 1.844 +int32_t 1.845 +nsACString::RFind(const char_type *aStr, int32_t aLen, ComparatorFunc c) const 1.846 +{ 1.847 + const char_type *begin, *end; 1.848 + uint32_t selflen = BeginReading(&begin, &end); 1.849 + 1.850 + if (aLen <= 0) { 1.851 + NS_WARNING("Searching for zero-length string."); 1.852 + return -1; 1.853 + } 1.854 + 1.855 + if (uint32_t(aLen) > selflen) 1.856 + return -1; 1.857 + 1.858 + // We want to start searching otherlen characters before the end of the string 1.859 + end -= aLen; 1.860 + 1.861 + for (const char_type *cur = end; cur >= begin; --cur) { 1.862 + if (!c(cur, aStr, aLen)) 1.863 + return cur - begin; 1.864 + } 1.865 + return -1; 1.866 +} 1.867 + 1.868 +int32_t 1.869 +nsACString::FindChar(char_type aChar, uint32_t aOffset) const 1.870 +{ 1.871 + const char_type *start, *end; 1.872 + uint32_t len = BeginReading(&start, &end); 1.873 + if (aOffset > len) 1.874 + return -1; 1.875 + 1.876 + const char_type *cur; 1.877 + 1.878 + for (cur = start + aOffset; cur < end; ++cur) { 1.879 + if (*cur == aChar) 1.880 + return cur - start; 1.881 + } 1.882 + 1.883 + return -1; 1.884 +} 1.885 + 1.886 +int32_t 1.887 +nsACString::RFindChar(char_type aChar) const 1.888 +{ 1.889 + const char *start, *end; 1.890 + BeginReading(&start, &end); 1.891 + 1.892 + for (; end >= start; --end) { 1.893 + if (*end == aChar) 1.894 + return end - start; 1.895 + } 1.896 + 1.897 + return -1; 1.898 +} 1.899 + 1.900 +void 1.901 +nsACString::AppendInt(int aInt, int32_t aRadix) 1.902 +{ 1.903 + const char *fmt; 1.904 + switch (aRadix) { 1.905 + case 8: 1.906 + fmt = "%o"; 1.907 + break; 1.908 + 1.909 + case 10: 1.910 + fmt = "%d"; 1.911 + break; 1.912 + 1.913 + case 16: 1.914 + fmt = "%x"; 1.915 + break; 1.916 + 1.917 + default: 1.918 + NS_ERROR("Unrecognized radix"); 1.919 + fmt = ""; 1.920 + }; 1.921 + 1.922 + char buf[20]; 1.923 + int len = snprintf(buf, sizeof(buf), fmt, aInt); 1.924 + buf[sizeof(buf) - 1] = '\0'; 1.925 + 1.926 + Append(buf, len); 1.927 +} 1.928 + 1.929 +#ifndef XPCOM_GLUE_AVOID_NSPR 1.930 +int32_t 1.931 +nsACString::ToInteger(nsresult *aErrorCode, uint32_t aRadix) const 1.932 +{ 1.933 + const char *fmt; 1.934 + switch (aRadix) { 1.935 + case 10: 1.936 + fmt = "%i"; 1.937 + break; 1.938 + 1.939 + case 16: 1.940 + fmt = "%x"; 1.941 + break; 1.942 + 1.943 + default: 1.944 + NS_ERROR("Unrecognized radix!"); 1.945 + *aErrorCode = NS_ERROR_INVALID_ARG; 1.946 + return 0; 1.947 + } 1.948 + 1.949 + int32_t result = 0; 1.950 + if (PR_sscanf(nsCString(*this).get(), fmt, &result) == 1) 1.951 + *aErrorCode = NS_OK; 1.952 + else 1.953 + *aErrorCode = NS_ERROR_FAILURE; 1.954 + 1.955 + return result; 1.956 +} 1.957 + 1.958 +int64_t 1.959 +nsACString::ToInteger64(nsresult *aErrorCode, uint32_t aRadix) const 1.960 +{ 1.961 + const char *fmt; 1.962 + switch (aRadix) { 1.963 + case 10: 1.964 + fmt = "%lli"; 1.965 + break; 1.966 + 1.967 + case 16: 1.968 + fmt = "%llx"; 1.969 + break; 1.970 + 1.971 + default: 1.972 + NS_ERROR("Unrecognized radix!"); 1.973 + *aErrorCode = NS_ERROR_INVALID_ARG; 1.974 + return 0; 1.975 + } 1.976 + 1.977 + int64_t result = 0; 1.978 + if (PR_sscanf(nsCString(*this).get(), fmt, &result) == 1) 1.979 + *aErrorCode = NS_OK; 1.980 + else 1.981 + *aErrorCode = NS_ERROR_FAILURE; 1.982 + 1.983 + return result; 1.984 +} 1.985 +#endif // XPCOM_GLUE_AVOID_NSPR 1.986 + 1.987 +// Substrings 1.988 + 1.989 +nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr, 1.990 + uint32_t aStartPos) 1.991 +{ 1.992 + const char16_t* data; 1.993 + uint32_t len = NS_StringGetData(aStr, &data); 1.994 + 1.995 + if (aStartPos > len) 1.996 + aStartPos = len; 1.997 + 1.998 + NS_StringContainerInit2(*this, data + aStartPos, len - aStartPos, 1.999 + NS_STRING_CONTAINER_INIT_DEPEND | 1.1000 + NS_STRING_CONTAINER_INIT_SUBSTRING); 1.1001 +} 1.1002 + 1.1003 +nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr, 1.1004 + uint32_t aStartPos, 1.1005 + uint32_t aLength) 1.1006 +{ 1.1007 + const char16_t* data; 1.1008 + uint32_t len = NS_StringGetData(aStr, &data); 1.1009 + 1.1010 + if (aStartPos > len) 1.1011 + aStartPos = len; 1.1012 + 1.1013 + if (aStartPos + aLength > len) 1.1014 + aLength = len - aStartPos; 1.1015 + 1.1016 + NS_StringContainerInit2(*this, data + aStartPos, aLength, 1.1017 + NS_STRING_CONTAINER_INIT_DEPEND | 1.1018 + NS_STRING_CONTAINER_INIT_SUBSTRING); 1.1019 +} 1.1020 + 1.1021 +nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr, 1.1022 + uint32_t aStartPos) 1.1023 +{ 1.1024 + const char* data; 1.1025 + uint32_t len = NS_CStringGetData(aStr, &data); 1.1026 + 1.1027 + if (aStartPos > len) 1.1028 + aStartPos = len; 1.1029 + 1.1030 + NS_CStringContainerInit2(*this, data + aStartPos, len - aStartPos, 1.1031 + NS_CSTRING_CONTAINER_INIT_DEPEND | 1.1032 + NS_CSTRING_CONTAINER_INIT_SUBSTRING); 1.1033 +} 1.1034 + 1.1035 +nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr, 1.1036 + uint32_t aStartPos, 1.1037 + uint32_t aLength) 1.1038 +{ 1.1039 + const char* data; 1.1040 + uint32_t len = NS_CStringGetData(aStr, &data); 1.1041 + 1.1042 + if (aStartPos > len) 1.1043 + aStartPos = len; 1.1044 + 1.1045 + if (aStartPos + aLength > len) 1.1046 + aLength = len - aStartPos; 1.1047 + 1.1048 + NS_CStringContainerInit2(*this, data + aStartPos, aLength, 1.1049 + NS_CSTRING_CONTAINER_INIT_DEPEND | 1.1050 + NS_CSTRING_CONTAINER_INIT_SUBSTRING); 1.1051 +} 1.1052 + 1.1053 +// Utils 1.1054 + 1.1055 +char* 1.1056 +ToNewUTF8String(const nsAString& aSource) 1.1057 +{ 1.1058 + nsCString temp; 1.1059 + CopyUTF16toUTF8(aSource, temp); 1.1060 + return NS_CStringCloneData(temp); 1.1061 +} 1.1062 + 1.1063 +void 1.1064 +CompressWhitespace(nsAString& aString) 1.1065 +{ 1.1066 + char16_t *start; 1.1067 + uint32_t len = NS_StringGetMutableData(aString, UINT32_MAX, &start); 1.1068 + char16_t *end = start + len; 1.1069 + char16_t *from = start, *to = start; 1.1070 + 1.1071 + // Skip any leading whitespace 1.1072 + while (from < end && NS_IsAsciiWhitespace(*from)) 1.1073 + from++; 1.1074 + 1.1075 + while (from < end) { 1.1076 + char16_t theChar = *from++; 1.1077 + 1.1078 + if (NS_IsAsciiWhitespace(theChar)) { 1.1079 + // We found a whitespace char, so skip over any more 1.1080 + while (from < end && NS_IsAsciiWhitespace(*from)) 1.1081 + from++; 1.1082 + 1.1083 + // Turn all whitespace into spaces 1.1084 + theChar = ' '; 1.1085 + } 1.1086 + 1.1087 + *to++ = theChar; 1.1088 + } 1.1089 + 1.1090 + // Drop any trailing space 1.1091 + if (to > start && to[-1] == ' ') 1.1092 + to--; 1.1093 + 1.1094 + // Re-terminate the string 1.1095 + *to = '\0'; 1.1096 + 1.1097 + // Set the new length 1.1098 + aString.SetLength(to - start); 1.1099 +} 1.1100 + 1.1101 +uint32_t 1.1102 +ToLowerCase(nsACString& aStr) 1.1103 +{ 1.1104 + char *begin, *end; 1.1105 + uint32_t len = aStr.BeginWriting(&begin, &end); 1.1106 + 1.1107 + for (; begin < end; ++begin) { 1.1108 + *begin = NS_ToLower(*begin); 1.1109 + } 1.1110 + 1.1111 + return len; 1.1112 +} 1.1113 + 1.1114 +uint32_t 1.1115 +ToUpperCase(nsACString& aStr) 1.1116 +{ 1.1117 + char *begin, *end; 1.1118 + uint32_t len = aStr.BeginWriting(&begin, &end); 1.1119 + 1.1120 + for (; begin < end; ++begin) { 1.1121 + *begin = NS_ToUpper(*begin); 1.1122 + } 1.1123 + 1.1124 + return len; 1.1125 +} 1.1126 + 1.1127 +uint32_t 1.1128 +ToLowerCase(const nsACString& aSrc, nsACString& aDest) 1.1129 +{ 1.1130 + const char *begin, *end; 1.1131 + uint32_t len = aSrc.BeginReading(&begin, &end); 1.1132 + 1.1133 + char *dest; 1.1134 + NS_CStringGetMutableData(aDest, len, &dest); 1.1135 + 1.1136 + for (; begin < end; ++begin, ++dest) { 1.1137 + *dest = NS_ToLower(*begin); 1.1138 + } 1.1139 + 1.1140 + return len; 1.1141 +} 1.1142 + 1.1143 +uint32_t 1.1144 +ToUpperCase(const nsACString& aSrc, nsACString& aDest) 1.1145 +{ 1.1146 + const char *begin, *end; 1.1147 + uint32_t len = aSrc.BeginReading(&begin, &end); 1.1148 + 1.1149 + char *dest; 1.1150 + NS_CStringGetMutableData(aDest, len, &dest); 1.1151 + 1.1152 + for (; begin < end; ++begin, ++dest) { 1.1153 + *dest = NS_ToUpper(*begin); 1.1154 + } 1.1155 + 1.1156 + return len; 1.1157 +} 1.1158 + 1.1159 +int32_t 1.1160 +CaseInsensitiveCompare(const char *a, const char *b, 1.1161 + uint32_t len) 1.1162 +{ 1.1163 + for (const char *aend = a + len; a < aend; ++a, ++b) { 1.1164 + char la = NS_ToLower(*a); 1.1165 + char lb = NS_ToLower(*b); 1.1166 + 1.1167 + if (la == lb) 1.1168 + continue; 1.1169 + 1.1170 + return la < lb ? -1 : 1; 1.1171 + } 1.1172 + 1.1173 + return 0; 1.1174 +} 1.1175 + 1.1176 +bool 1.1177 +ParseString(const nsACString& aSource, char aDelimiter, 1.1178 + nsTArray<nsCString>& aArray) 1.1179 +{ 1.1180 + int32_t start = 0; 1.1181 + int32_t end = aSource.Length(); 1.1182 + 1.1183 + uint32_t oldLength = aArray.Length(); 1.1184 + 1.1185 + for (;;) { 1.1186 + int32_t delimiter = aSource.FindChar(aDelimiter, start); 1.1187 + if (delimiter < 0) { 1.1188 + delimiter = end; 1.1189 + } 1.1190 + 1.1191 + if (delimiter != start) { 1.1192 + if (!aArray.AppendElement(Substring(aSource, start, delimiter - start))) { 1.1193 + aArray.RemoveElementsAt(oldLength, aArray.Length() - oldLength); 1.1194 + return false; 1.1195 + } 1.1196 + } 1.1197 + 1.1198 + if (delimiter == end) 1.1199 + break; 1.1200 + start = ++delimiter; 1.1201 + if (start == end) 1.1202 + break; 1.1203 + } 1.1204 + 1.1205 + return true; 1.1206 +}