xpcom/glue/nsStringAPI.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* vim:set ts=2 sw=2 et cindent: */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nscore.h"
michael@0 7 #include "nsCRTGlue.h"
michael@0 8 #include "prprf.h"
michael@0 9 #include "nsStringAPI.h"
michael@0 10 #include "nsXPCOMStrings.h"
michael@0 11 #include "nsDebug.h"
michael@0 12
michael@0 13 #include <stdio.h>
michael@0 14
michael@0 15 #ifdef XP_WIN
michael@0 16 #define snprintf _snprintf
michael@0 17 #endif
michael@0 18
michael@0 19 // nsAString
michael@0 20
michael@0 21 uint32_t
michael@0 22 nsAString::BeginReading(const char_type **begin, const char_type **end) const
michael@0 23 {
michael@0 24 uint32_t len = NS_StringGetData(*this, begin);
michael@0 25 if (end)
michael@0 26 *end = *begin + len;
michael@0 27
michael@0 28 return len;
michael@0 29 }
michael@0 30
michael@0 31 const nsAString::char_type*
michael@0 32 nsAString::BeginReading() const
michael@0 33 {
michael@0 34 const char_type *data;
michael@0 35 NS_StringGetData(*this, &data);
michael@0 36 return data;
michael@0 37 }
michael@0 38
michael@0 39 const nsAString::char_type*
michael@0 40 nsAString::EndReading() const
michael@0 41 {
michael@0 42 const char_type *data;
michael@0 43 uint32_t len = NS_StringGetData(*this, &data);
michael@0 44 return data + len;
michael@0 45 }
michael@0 46
michael@0 47 uint32_t
michael@0 48 nsAString::BeginWriting(char_type **begin, char_type **end, uint32_t newSize)
michael@0 49 {
michael@0 50 uint32_t len = NS_StringGetMutableData(*this, newSize, begin);
michael@0 51 if (end)
michael@0 52 *end = *begin + len;
michael@0 53
michael@0 54 return len;
michael@0 55 }
michael@0 56
michael@0 57 nsAString::char_type*
michael@0 58 nsAString::BeginWriting(uint32_t aLen)
michael@0 59 {
michael@0 60 char_type *data;
michael@0 61 NS_StringGetMutableData(*this, aLen, &data);
michael@0 62 return data;
michael@0 63 }
michael@0 64
michael@0 65 nsAString::char_type*
michael@0 66 nsAString::EndWriting()
michael@0 67 {
michael@0 68 char_type *data;
michael@0 69 uint32_t len = NS_StringGetMutableData(*this, UINT32_MAX, &data);
michael@0 70 return data + len;
michael@0 71 }
michael@0 72
michael@0 73 bool
michael@0 74 nsAString::SetLength(uint32_t aLen)
michael@0 75 {
michael@0 76 char_type *data;
michael@0 77 NS_StringGetMutableData(*this, aLen, &data);
michael@0 78 return data != nullptr;
michael@0 79 }
michael@0 80
michael@0 81 void
michael@0 82 nsAString::AssignLiteral(const char *aStr)
michael@0 83 {
michael@0 84 uint32_t len = strlen(aStr);
michael@0 85 char16_t *buf = BeginWriting(len);
michael@0 86 if (!buf)
michael@0 87 return;
michael@0 88
michael@0 89 for (; *aStr; ++aStr, ++buf)
michael@0 90 *buf = *aStr;
michael@0 91 }
michael@0 92
michael@0 93 void
michael@0 94 nsAString::AppendLiteral(const char *aASCIIStr)
michael@0 95 {
michael@0 96 uint32_t appendLen = strlen(aASCIIStr);
michael@0 97
michael@0 98 uint32_t thisLen = Length();
michael@0 99 char16_t *begin, *end;
michael@0 100 BeginWriting(&begin, &end, appendLen + thisLen);
michael@0 101 if (!begin)
michael@0 102 return;
michael@0 103
michael@0 104 for (begin += thisLen; begin < end; ++begin, ++aASCIIStr)
michael@0 105 *begin = *aASCIIStr;
michael@0 106 }
michael@0 107
michael@0 108 void
michael@0 109 nsAString::StripChars(const char *aSet)
michael@0 110 {
michael@0 111 nsString copy(*this);
michael@0 112
michael@0 113 const char_type *source, *sourceEnd;
michael@0 114 copy.BeginReading(&source, &sourceEnd);
michael@0 115
michael@0 116 char_type *dest;
michael@0 117 BeginWriting(&dest);
michael@0 118 if (!dest)
michael@0 119 return;
michael@0 120
michael@0 121 char_type *curDest = dest;
michael@0 122
michael@0 123 for (; source < sourceEnd; ++source) {
michael@0 124 const char *test;
michael@0 125 for (test = aSet; *test; ++test) {
michael@0 126 if (*source == char_type(*test))
michael@0 127 break;
michael@0 128 }
michael@0 129
michael@0 130 if (!*test) {
michael@0 131 // not stripped, copy this char
michael@0 132 *curDest = *source;
michael@0 133 ++curDest;
michael@0 134 }
michael@0 135 }
michael@0 136
michael@0 137 SetLength(curDest - dest);
michael@0 138 }
michael@0 139
michael@0 140 void
michael@0 141 nsAString::Trim(const char *aSet, bool aLeading, bool aTrailing)
michael@0 142 {
michael@0 143 NS_ASSERTION(aLeading || aTrailing, "Ineffective Trim");
michael@0 144
michael@0 145 const char16_t *start, *end;
michael@0 146 uint32_t cutLen;
michael@0 147
michael@0 148 if (aLeading) {
michael@0 149 BeginReading(&start, &end);
michael@0 150 for (cutLen = 0; start < end; ++start, ++cutLen) {
michael@0 151 const char *test;
michael@0 152 for (test = aSet; *test; ++test) {
michael@0 153 if (*test == *start)
michael@0 154 break;
michael@0 155 }
michael@0 156 if (!*test)
michael@0 157 break;
michael@0 158 }
michael@0 159 if (cutLen) {
michael@0 160 NS_StringCutData(*this, 0, cutLen);
michael@0 161 }
michael@0 162 }
michael@0 163 if (aTrailing) {
michael@0 164 uint32_t len = BeginReading(&start, &end);
michael@0 165 --end;
michael@0 166 for (cutLen = 0; end >= start; --end, ++cutLen) {
michael@0 167 const char *test;
michael@0 168 for (test = aSet; *test; ++test) {
michael@0 169 if (*test == *end)
michael@0 170 break;
michael@0 171 }
michael@0 172 if (!*test)
michael@0 173 break;
michael@0 174 }
michael@0 175 if (cutLen) {
michael@0 176 NS_StringCutData(*this, len - cutLen, cutLen);
michael@0 177 }
michael@0 178 }
michael@0 179 }
michael@0 180
michael@0 181 int32_t
michael@0 182 nsAString::DefaultComparator(const char_type *a, const char_type *b,
michael@0 183 uint32_t len)
michael@0 184 {
michael@0 185 for (const char_type *end = a + len; a < end; ++a, ++b) {
michael@0 186 if (*a == *b)
michael@0 187 continue;
michael@0 188
michael@0 189 return *a < *b ? -1 : 1;
michael@0 190 }
michael@0 191
michael@0 192 return 0;
michael@0 193 }
michael@0 194
michael@0 195 int32_t
michael@0 196 nsAString::Compare(const char_type *other, ComparatorFunc c) const
michael@0 197 {
michael@0 198 const char_type *cself;
michael@0 199 uint32_t selflen = NS_StringGetData(*this, &cself);
michael@0 200 uint32_t otherlen = NS_strlen(other);
michael@0 201 uint32_t comparelen = selflen <= otherlen ? selflen : otherlen;
michael@0 202
michael@0 203 int32_t result = c(cself, other, comparelen);
michael@0 204 if (result == 0) {
michael@0 205 if (selflen < otherlen)
michael@0 206 return -1;
michael@0 207 else if (selflen > otherlen)
michael@0 208 return 1;
michael@0 209 }
michael@0 210 return result;
michael@0 211 }
michael@0 212
michael@0 213 int32_t
michael@0 214 nsAString::Compare(const self_type &other, ComparatorFunc c) const
michael@0 215 {
michael@0 216 const char_type *cself, *cother;
michael@0 217 uint32_t selflen = NS_StringGetData(*this, &cself);
michael@0 218 uint32_t otherlen = NS_StringGetData(other, &cother);
michael@0 219 uint32_t comparelen = selflen <= otherlen ? selflen : otherlen;
michael@0 220
michael@0 221 int32_t result = c(cself, cother, comparelen);
michael@0 222 if (result == 0) {
michael@0 223 if (selflen < otherlen)
michael@0 224 return -1;
michael@0 225 else if (selflen > otherlen)
michael@0 226 return 1;
michael@0 227 }
michael@0 228 return result;
michael@0 229 }
michael@0 230
michael@0 231 bool
michael@0 232 nsAString::Equals(const char_type *other, ComparatorFunc c) const
michael@0 233 {
michael@0 234 const char_type *cself;
michael@0 235 uint32_t selflen = NS_StringGetData(*this, &cself);
michael@0 236 uint32_t otherlen = NS_strlen(other);
michael@0 237
michael@0 238 if (selflen != otherlen)
michael@0 239 return false;
michael@0 240
michael@0 241 return c(cself, other, selflen) == 0;
michael@0 242 }
michael@0 243
michael@0 244 bool
michael@0 245 nsAString::Equals(const self_type &other, ComparatorFunc c) const
michael@0 246 {
michael@0 247 const char_type *cself;
michael@0 248 const char_type *cother;
michael@0 249 uint32_t selflen = NS_StringGetData(*this, &cself);
michael@0 250 uint32_t otherlen = NS_StringGetData(other, &cother);
michael@0 251
michael@0 252 if (selflen != otherlen)
michael@0 253 return false;
michael@0 254
michael@0 255 return c(cself, cother, selflen) == 0;
michael@0 256 }
michael@0 257
michael@0 258 bool
michael@0 259 nsAString::EqualsLiteral(const char *aASCIIString) const
michael@0 260 {
michael@0 261 const char16_t *begin, *end;
michael@0 262 BeginReading(&begin, &end);
michael@0 263
michael@0 264 for (; begin < end; ++begin, ++aASCIIString) {
michael@0 265 if (!*aASCIIString || !NS_IsAscii(*begin) ||
michael@0 266 (char) *begin != *aASCIIString) {
michael@0 267 return false;
michael@0 268 }
michael@0 269 }
michael@0 270
michael@0 271 return *aASCIIString == '\0';
michael@0 272 }
michael@0 273
michael@0 274 bool
michael@0 275 nsAString::LowerCaseEqualsLiteral(const char *aASCIIString) const
michael@0 276 {
michael@0 277 const char16_t *begin, *end;
michael@0 278 BeginReading(&begin, &end);
michael@0 279
michael@0 280 for (; begin < end; ++begin, ++aASCIIString) {
michael@0 281 if (!*aASCIIString || !NS_IsAscii(*begin) ||
michael@0 282 NS_ToLower((char) *begin) != *aASCIIString) {
michael@0 283 return false;
michael@0 284 }
michael@0 285 }
michael@0 286
michael@0 287 return *aASCIIString == '\0';
michael@0 288 }
michael@0 289
michael@0 290 int32_t
michael@0 291 nsAString::Find(const self_type& aStr, uint32_t aOffset,
michael@0 292 ComparatorFunc c) const
michael@0 293 {
michael@0 294 const char_type *begin, *end;
michael@0 295 uint32_t selflen = BeginReading(&begin, &end);
michael@0 296
michael@0 297 if (aOffset > selflen)
michael@0 298 return -1;
michael@0 299
michael@0 300 const char_type *other;
michael@0 301 uint32_t otherlen = aStr.BeginReading(&other);
michael@0 302
michael@0 303 if (otherlen > selflen - aOffset)
michael@0 304 return -1;
michael@0 305
michael@0 306 // We want to stop searching otherlen characters before the end of the string
michael@0 307 end -= otherlen;
michael@0 308
michael@0 309 for (const char_type *cur = begin + aOffset; cur <= end; ++cur) {
michael@0 310 if (!c(cur, other, otherlen))
michael@0 311 return cur - begin;
michael@0 312 }
michael@0 313 return -1;
michael@0 314 }
michael@0 315
michael@0 316 static bool ns_strnmatch(const char16_t *aStr, const char* aSubstring,
michael@0 317 uint32_t aLen)
michael@0 318 {
michael@0 319 for (; aLen; ++aStr, ++aSubstring, --aLen) {
michael@0 320 if (!NS_IsAscii(*aStr))
michael@0 321 return false;
michael@0 322
michael@0 323 if ((char) *aStr != *aSubstring)
michael@0 324 return false;
michael@0 325 }
michael@0 326
michael@0 327 return true;
michael@0 328 }
michael@0 329
michael@0 330 static bool ns_strnimatch(const char16_t *aStr, const char* aSubstring,
michael@0 331 uint32_t aLen)
michael@0 332 {
michael@0 333 for (; aLen; ++aStr, ++aSubstring, --aLen) {
michael@0 334 if (!NS_IsAscii(*aStr))
michael@0 335 return false;
michael@0 336
michael@0 337 if (NS_ToLower((char) *aStr) != NS_ToLower(*aSubstring))
michael@0 338 return false;
michael@0 339 }
michael@0 340
michael@0 341 return true;
michael@0 342 }
michael@0 343
michael@0 344 int32_t
michael@0 345 nsAString::Find(const char *aStr, uint32_t aOffset, bool aIgnoreCase) const
michael@0 346 {
michael@0 347 bool (*match)(const char16_t*, const char*, uint32_t) =
michael@0 348 aIgnoreCase ? ns_strnimatch : ns_strnmatch;
michael@0 349
michael@0 350 const char_type *begin, *end;
michael@0 351 uint32_t selflen = BeginReading(&begin, &end);
michael@0 352
michael@0 353 if (aOffset > selflen)
michael@0 354 return -1;
michael@0 355
michael@0 356 uint32_t otherlen = strlen(aStr);
michael@0 357
michael@0 358 if (otherlen > selflen - aOffset)
michael@0 359 return -1;
michael@0 360
michael@0 361 // We want to stop searching otherlen characters before the end of the string
michael@0 362 end -= otherlen;
michael@0 363
michael@0 364 for (const char_type *cur = begin + aOffset; cur <= end; ++cur) {
michael@0 365 if (match(cur, aStr, otherlen)) {
michael@0 366 return cur - begin;
michael@0 367 }
michael@0 368 }
michael@0 369 return -1;
michael@0 370 }
michael@0 371
michael@0 372 int32_t
michael@0 373 nsAString::RFind(const self_type& aStr, int32_t aOffset, ComparatorFunc c) const
michael@0 374 {
michael@0 375 const char_type *begin, *end;
michael@0 376 uint32_t selflen = BeginReading(&begin, &end);
michael@0 377
michael@0 378 const char_type *other;
michael@0 379 uint32_t otherlen = aStr.BeginReading(&other);
michael@0 380
michael@0 381 if (selflen < otherlen)
michael@0 382 return -1;
michael@0 383
michael@0 384 if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen))
michael@0 385 end -= otherlen;
michael@0 386 else
michael@0 387 end = begin + aOffset;
michael@0 388
michael@0 389 for (const char_type *cur = end; cur >= begin; --cur) {
michael@0 390 if (!c(cur, other, otherlen))
michael@0 391 return cur - begin;
michael@0 392 }
michael@0 393 return -1;
michael@0 394 }
michael@0 395
michael@0 396 int32_t
michael@0 397 nsAString::RFind(const char *aStr, int32_t aOffset, bool aIgnoreCase) const
michael@0 398 {
michael@0 399 bool (*match)(const char16_t*, const char*, uint32_t) =
michael@0 400 aIgnoreCase ? ns_strnimatch : ns_strnmatch;
michael@0 401
michael@0 402 const char_type *begin, *end;
michael@0 403 uint32_t selflen = BeginReading(&begin, &end);
michael@0 404 uint32_t otherlen = strlen(aStr);
michael@0 405
michael@0 406 if (selflen < otherlen)
michael@0 407 return -1;
michael@0 408
michael@0 409 if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen))
michael@0 410 end -= otherlen;
michael@0 411 else
michael@0 412 end = begin + aOffset;
michael@0 413
michael@0 414 for (const char_type *cur = end; cur >= begin; --cur) {
michael@0 415 if (match(cur, aStr, otherlen)) {
michael@0 416 return cur - begin;
michael@0 417 }
michael@0 418 }
michael@0 419 return -1;
michael@0 420 }
michael@0 421
michael@0 422 int32_t
michael@0 423 nsAString::FindChar(char_type aChar, uint32_t aOffset) const
michael@0 424 {
michael@0 425 const char_type *start, *end;
michael@0 426 uint32_t len = BeginReading(&start, &end);
michael@0 427 if (aOffset > len)
michael@0 428 return -1;
michael@0 429
michael@0 430 const char_type *cur;
michael@0 431
michael@0 432 for (cur = start + aOffset; cur < end; ++cur) {
michael@0 433 if (*cur == aChar)
michael@0 434 return cur - start;
michael@0 435 }
michael@0 436
michael@0 437 return -1;
michael@0 438 }
michael@0 439
michael@0 440 int32_t
michael@0 441 nsAString::RFindChar(char_type aChar) const
michael@0 442 {
michael@0 443 const char16_t *start, *end;
michael@0 444 BeginReading(&start, &end);
michael@0 445
michael@0 446 do {
michael@0 447 --end;
michael@0 448
michael@0 449 if (*end == aChar)
michael@0 450 return end - start;
michael@0 451
michael@0 452 } while (end >= start);
michael@0 453
michael@0 454 return -1;
michael@0 455 }
michael@0 456
michael@0 457 void
michael@0 458 nsAString::AppendInt(int aInt, int32_t aRadix)
michael@0 459 {
michael@0 460 const char *fmt;
michael@0 461 switch (aRadix) {
michael@0 462 case 8:
michael@0 463 fmt = "%o";
michael@0 464 break;
michael@0 465
michael@0 466 case 10:
michael@0 467 fmt = "%d";
michael@0 468 break;
michael@0 469
michael@0 470 case 16:
michael@0 471 fmt = "%x";
michael@0 472 break;
michael@0 473
michael@0 474 default:
michael@0 475 NS_ERROR("Unrecognized radix");
michael@0 476 fmt = "";
michael@0 477 };
michael@0 478
michael@0 479 char buf[20];
michael@0 480 int len = snprintf(buf, sizeof(buf), fmt, aInt);
michael@0 481 buf[sizeof(buf) - 1] = '\0';
michael@0 482
michael@0 483 Append(NS_ConvertASCIItoUTF16(buf, len));
michael@0 484 }
michael@0 485
michael@0 486 // Strings
michael@0 487
michael@0 488 #ifndef XPCOM_GLUE_AVOID_NSPR
michael@0 489 int32_t
michael@0 490 nsAString::ToInteger(nsresult *aErrorCode, uint32_t aRadix) const
michael@0 491 {
michael@0 492 NS_ConvertUTF16toUTF8 narrow(*this);
michael@0 493
michael@0 494 const char *fmt;
michael@0 495 switch (aRadix) {
michael@0 496 case 10:
michael@0 497 fmt = "%i";
michael@0 498 break;
michael@0 499
michael@0 500 case 16:
michael@0 501 fmt = "%x";
michael@0 502 break;
michael@0 503
michael@0 504 default:
michael@0 505 NS_ERROR("Unrecognized radix!");
michael@0 506 *aErrorCode = NS_ERROR_INVALID_ARG;
michael@0 507 return 0;
michael@0 508 }
michael@0 509
michael@0 510 int32_t result = 0;
michael@0 511 if (PR_sscanf(narrow.get(), fmt, &result) == 1)
michael@0 512 *aErrorCode = NS_OK;
michael@0 513 else
michael@0 514 *aErrorCode = NS_ERROR_FAILURE;
michael@0 515
michael@0 516 return result;
michael@0 517 }
michael@0 518
michael@0 519 int64_t
michael@0 520 nsAString::ToInteger64(nsresult *aErrorCode, uint32_t aRadix) const
michael@0 521 {
michael@0 522 NS_ConvertUTF16toUTF8 narrow(*this);
michael@0 523
michael@0 524 const char *fmt;
michael@0 525 switch (aRadix) {
michael@0 526 case 10:
michael@0 527 fmt = "%lli";
michael@0 528 break;
michael@0 529
michael@0 530 case 16:
michael@0 531 fmt = "%llx";
michael@0 532 break;
michael@0 533
michael@0 534 default:
michael@0 535 NS_ERROR("Unrecognized radix!");
michael@0 536 *aErrorCode = NS_ERROR_INVALID_ARG;
michael@0 537 return 0;
michael@0 538 }
michael@0 539
michael@0 540 int64_t result = 0;
michael@0 541 if (PR_sscanf(narrow.get(), fmt, &result) == 1)
michael@0 542 *aErrorCode = NS_OK;
michael@0 543 else
michael@0 544 *aErrorCode = NS_ERROR_FAILURE;
michael@0 545
michael@0 546 return result;
michael@0 547 }
michael@0 548 #endif // XPCOM_GLUE_AVOID_NSPR
michael@0 549
michael@0 550 // nsACString
michael@0 551
michael@0 552 uint32_t
michael@0 553 nsACString::BeginReading(const char_type **begin, const char_type **end) const
michael@0 554 {
michael@0 555 uint32_t len = NS_CStringGetData(*this, begin);
michael@0 556 if (end)
michael@0 557 *end = *begin + len;
michael@0 558
michael@0 559 return len;
michael@0 560 }
michael@0 561
michael@0 562 const nsACString::char_type*
michael@0 563 nsACString::BeginReading() const
michael@0 564 {
michael@0 565 const char_type *data;
michael@0 566 NS_CStringGetData(*this, &data);
michael@0 567 return data;
michael@0 568 }
michael@0 569
michael@0 570 const nsACString::char_type*
michael@0 571 nsACString::EndReading() const
michael@0 572 {
michael@0 573 const char_type *data;
michael@0 574 uint32_t len = NS_CStringGetData(*this, &data);
michael@0 575 return data + len;
michael@0 576 }
michael@0 577
michael@0 578 uint32_t
michael@0 579 nsACString::BeginWriting(char_type **begin, char_type **end, uint32_t newSize)
michael@0 580 {
michael@0 581 uint32_t len = NS_CStringGetMutableData(*this, newSize, begin);
michael@0 582 if (end)
michael@0 583 *end = *begin + len;
michael@0 584
michael@0 585 return len;
michael@0 586 }
michael@0 587
michael@0 588 nsACString::char_type*
michael@0 589 nsACString::BeginWriting(uint32_t aLen)
michael@0 590 {
michael@0 591 char_type *data;
michael@0 592 NS_CStringGetMutableData(*this, aLen, &data);
michael@0 593 return data;
michael@0 594 }
michael@0 595
michael@0 596 nsACString::char_type*
michael@0 597 nsACString::EndWriting()
michael@0 598 {
michael@0 599 char_type *data;
michael@0 600 uint32_t len = NS_CStringGetMutableData(*this, UINT32_MAX, &data);
michael@0 601 return data + len;
michael@0 602 }
michael@0 603
michael@0 604 bool
michael@0 605 nsACString::SetLength(uint32_t aLen)
michael@0 606 {
michael@0 607 char_type *data;
michael@0 608 NS_CStringGetMutableData(*this, aLen, &data);
michael@0 609 return data != nullptr;
michael@0 610 }
michael@0 611
michael@0 612 void
michael@0 613 nsACString::StripChars(const char *aSet)
michael@0 614 {
michael@0 615 nsCString copy(*this);
michael@0 616
michael@0 617 const char_type *source, *sourceEnd;
michael@0 618 copy.BeginReading(&source, &sourceEnd);
michael@0 619
michael@0 620 char_type *dest;
michael@0 621 BeginWriting(&dest);
michael@0 622 if (!dest)
michael@0 623 return;
michael@0 624
michael@0 625 char_type *curDest = dest;
michael@0 626
michael@0 627 for (; source < sourceEnd; ++source) {
michael@0 628 const char *test;
michael@0 629 for (test = aSet; *test; ++test) {
michael@0 630 if (*source == char_type(*test))
michael@0 631 break;
michael@0 632 }
michael@0 633
michael@0 634 if (!*test) {
michael@0 635 // not stripped, copy this char
michael@0 636 *curDest = *source;
michael@0 637 ++curDest;
michael@0 638 }
michael@0 639 }
michael@0 640
michael@0 641 SetLength(curDest - dest);
michael@0 642 }
michael@0 643
michael@0 644 void
michael@0 645 nsACString::Trim(const char *aSet, bool aLeading, bool aTrailing)
michael@0 646 {
michael@0 647 NS_ASSERTION(aLeading || aTrailing, "Ineffective Trim");
michael@0 648
michael@0 649 const char *start, *end;
michael@0 650 uint32_t cutLen;
michael@0 651
michael@0 652 if (aLeading) {
michael@0 653 BeginReading(&start, &end);
michael@0 654 for (cutLen = 0; start < end; ++start, ++cutLen) {
michael@0 655 const char *test;
michael@0 656 for (test = aSet; *test; ++test) {
michael@0 657 if (*test == *start)
michael@0 658 break;
michael@0 659 }
michael@0 660 if (!*test)
michael@0 661 break;
michael@0 662 }
michael@0 663 if (cutLen) {
michael@0 664 NS_CStringCutData(*this, 0, cutLen);
michael@0 665 }
michael@0 666 }
michael@0 667 if (aTrailing) {
michael@0 668 uint32_t len = BeginReading(&start, &end);
michael@0 669 --end;
michael@0 670 for (cutLen = 0; end >= start; --end, ++cutLen) {
michael@0 671 const char *test;
michael@0 672 for (test = aSet; *test; ++test) {
michael@0 673 if (*test == *end)
michael@0 674 break;
michael@0 675 }
michael@0 676 if (!*test)
michael@0 677 break;
michael@0 678 }
michael@0 679 if (cutLen) {
michael@0 680 NS_CStringCutData(*this, len - cutLen, cutLen);
michael@0 681 }
michael@0 682 }
michael@0 683 }
michael@0 684
michael@0 685 int32_t
michael@0 686 nsACString::DefaultComparator(const char_type *a, const char_type *b,
michael@0 687 uint32_t len)
michael@0 688 {
michael@0 689 return memcmp(a, b, len);
michael@0 690 }
michael@0 691
michael@0 692 int32_t
michael@0 693 nsACString::Compare(const char_type *other, ComparatorFunc c) const
michael@0 694 {
michael@0 695 const char_type *cself;
michael@0 696 uint32_t selflen = NS_CStringGetData(*this, &cself);
michael@0 697 uint32_t otherlen = strlen(other);
michael@0 698 uint32_t comparelen = selflen <= otherlen ? selflen : otherlen;
michael@0 699
michael@0 700 int32_t result = c(cself, other, comparelen);
michael@0 701 if (result == 0) {
michael@0 702 if (selflen < otherlen)
michael@0 703 return -1;
michael@0 704 else if (selflen > otherlen)
michael@0 705 return 1;
michael@0 706 }
michael@0 707 return result;
michael@0 708 }
michael@0 709
michael@0 710 int32_t
michael@0 711 nsACString::Compare(const self_type &other, ComparatorFunc c) const
michael@0 712 {
michael@0 713 const char_type *cself, *cother;
michael@0 714 uint32_t selflen = NS_CStringGetData(*this, &cself);
michael@0 715 uint32_t otherlen = NS_CStringGetData(other, &cother);
michael@0 716 uint32_t comparelen = selflen <= otherlen ? selflen : otherlen;
michael@0 717
michael@0 718 int32_t result = c(cself, cother, comparelen);
michael@0 719 if (result == 0) {
michael@0 720 if (selflen < otherlen)
michael@0 721 return -1;
michael@0 722 else if (selflen > otherlen)
michael@0 723 return 1;
michael@0 724 }
michael@0 725 return result;
michael@0 726 }
michael@0 727
michael@0 728 bool
michael@0 729 nsACString::Equals(const char_type *other, ComparatorFunc c) const
michael@0 730 {
michael@0 731 const char_type *cself;
michael@0 732 uint32_t selflen = NS_CStringGetData(*this, &cself);
michael@0 733 uint32_t otherlen = strlen(other);
michael@0 734
michael@0 735 if (selflen != otherlen)
michael@0 736 return false;
michael@0 737
michael@0 738 return c(cself, other, selflen) == 0;
michael@0 739 }
michael@0 740
michael@0 741 bool
michael@0 742 nsACString::Equals(const self_type &other, ComparatorFunc c) const
michael@0 743 {
michael@0 744 const char_type *cself;
michael@0 745 const char_type *cother;
michael@0 746 uint32_t selflen = NS_CStringGetData(*this, &cself);
michael@0 747 uint32_t otherlen = NS_CStringGetData(other, &cother);
michael@0 748
michael@0 749 if (selflen != otherlen)
michael@0 750 return false;
michael@0 751
michael@0 752 return c(cself, cother, selflen) == 0;
michael@0 753 }
michael@0 754
michael@0 755 int32_t
michael@0 756 nsACString::Find(const self_type& aStr, uint32_t aOffset,
michael@0 757 ComparatorFunc c) const
michael@0 758 {
michael@0 759 const char_type *begin, *end;
michael@0 760 uint32_t selflen = BeginReading(&begin, &end);
michael@0 761
michael@0 762 if (aOffset > selflen)
michael@0 763 return -1;
michael@0 764
michael@0 765 const char_type *other;
michael@0 766 uint32_t otherlen = aStr.BeginReading(&other);
michael@0 767
michael@0 768 if (otherlen > selflen - aOffset)
michael@0 769 return -1;
michael@0 770
michael@0 771 // We want to stop searching otherlen characters before the end of the string
michael@0 772 end -= otherlen;
michael@0 773
michael@0 774 for (const char_type *cur = begin + aOffset; cur <= end; ++cur) {
michael@0 775 if (!c(cur, other, otherlen))
michael@0 776 return cur - begin;
michael@0 777 }
michael@0 778 return -1;
michael@0 779 }
michael@0 780
michael@0 781 int32_t
michael@0 782 nsACString::Find(const char_type *aStr, ComparatorFunc c) const
michael@0 783 {
michael@0 784 return Find(aStr, strlen(aStr), c);
michael@0 785 }
michael@0 786
michael@0 787 int32_t
michael@0 788 nsACString::Find(const char_type *aStr, uint32_t aLen, ComparatorFunc c) const
michael@0 789 {
michael@0 790 const char_type *begin, *end;
michael@0 791 uint32_t selflen = BeginReading(&begin, &end);
michael@0 792
michael@0 793 if (aLen == 0) {
michael@0 794 NS_WARNING("Searching for zero-length string.");
michael@0 795 return -1;
michael@0 796 }
michael@0 797
michael@0 798 if (aLen > selflen)
michael@0 799 return -1;
michael@0 800
michael@0 801 // We want to stop searching otherlen characters before the end of the string
michael@0 802 end -= aLen;
michael@0 803
michael@0 804 for (const char_type *cur = begin; cur <= end; ++cur) {
michael@0 805 if (!c(cur, aStr, aLen))
michael@0 806 return cur - begin;
michael@0 807 }
michael@0 808 return -1;
michael@0 809 }
michael@0 810
michael@0 811 int32_t
michael@0 812 nsACString::RFind(const self_type& aStr, int32_t aOffset, ComparatorFunc c) const
michael@0 813 {
michael@0 814 const char_type *begin, *end;
michael@0 815 uint32_t selflen = BeginReading(&begin, &end);
michael@0 816
michael@0 817 const char_type *other;
michael@0 818 uint32_t otherlen = aStr.BeginReading(&other);
michael@0 819
michael@0 820 if (selflen < otherlen)
michael@0 821 return -1;
michael@0 822
michael@0 823 if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen))
michael@0 824 end -= otherlen;
michael@0 825 else
michael@0 826 end = begin + aOffset;
michael@0 827
michael@0 828 for (const char_type *cur = end; cur >= begin; --cur) {
michael@0 829 if (!c(cur, other, otherlen))
michael@0 830 return cur - begin;
michael@0 831 }
michael@0 832 return -1;
michael@0 833 }
michael@0 834
michael@0 835 int32_t
michael@0 836 nsACString::RFind(const char_type *aStr, ComparatorFunc c) const
michael@0 837 {
michael@0 838 return RFind(aStr, strlen(aStr), c);
michael@0 839 }
michael@0 840
michael@0 841 int32_t
michael@0 842 nsACString::RFind(const char_type *aStr, int32_t aLen, ComparatorFunc c) const
michael@0 843 {
michael@0 844 const char_type *begin, *end;
michael@0 845 uint32_t selflen = BeginReading(&begin, &end);
michael@0 846
michael@0 847 if (aLen <= 0) {
michael@0 848 NS_WARNING("Searching for zero-length string.");
michael@0 849 return -1;
michael@0 850 }
michael@0 851
michael@0 852 if (uint32_t(aLen) > selflen)
michael@0 853 return -1;
michael@0 854
michael@0 855 // We want to start searching otherlen characters before the end of the string
michael@0 856 end -= aLen;
michael@0 857
michael@0 858 for (const char_type *cur = end; cur >= begin; --cur) {
michael@0 859 if (!c(cur, aStr, aLen))
michael@0 860 return cur - begin;
michael@0 861 }
michael@0 862 return -1;
michael@0 863 }
michael@0 864
michael@0 865 int32_t
michael@0 866 nsACString::FindChar(char_type aChar, uint32_t aOffset) const
michael@0 867 {
michael@0 868 const char_type *start, *end;
michael@0 869 uint32_t len = BeginReading(&start, &end);
michael@0 870 if (aOffset > len)
michael@0 871 return -1;
michael@0 872
michael@0 873 const char_type *cur;
michael@0 874
michael@0 875 for (cur = start + aOffset; cur < end; ++cur) {
michael@0 876 if (*cur == aChar)
michael@0 877 return cur - start;
michael@0 878 }
michael@0 879
michael@0 880 return -1;
michael@0 881 }
michael@0 882
michael@0 883 int32_t
michael@0 884 nsACString::RFindChar(char_type aChar) const
michael@0 885 {
michael@0 886 const char *start, *end;
michael@0 887 BeginReading(&start, &end);
michael@0 888
michael@0 889 for (; end >= start; --end) {
michael@0 890 if (*end == aChar)
michael@0 891 return end - start;
michael@0 892 }
michael@0 893
michael@0 894 return -1;
michael@0 895 }
michael@0 896
michael@0 897 void
michael@0 898 nsACString::AppendInt(int aInt, int32_t aRadix)
michael@0 899 {
michael@0 900 const char *fmt;
michael@0 901 switch (aRadix) {
michael@0 902 case 8:
michael@0 903 fmt = "%o";
michael@0 904 break;
michael@0 905
michael@0 906 case 10:
michael@0 907 fmt = "%d";
michael@0 908 break;
michael@0 909
michael@0 910 case 16:
michael@0 911 fmt = "%x";
michael@0 912 break;
michael@0 913
michael@0 914 default:
michael@0 915 NS_ERROR("Unrecognized radix");
michael@0 916 fmt = "";
michael@0 917 };
michael@0 918
michael@0 919 char buf[20];
michael@0 920 int len = snprintf(buf, sizeof(buf), fmt, aInt);
michael@0 921 buf[sizeof(buf) - 1] = '\0';
michael@0 922
michael@0 923 Append(buf, len);
michael@0 924 }
michael@0 925
michael@0 926 #ifndef XPCOM_GLUE_AVOID_NSPR
michael@0 927 int32_t
michael@0 928 nsACString::ToInteger(nsresult *aErrorCode, uint32_t aRadix) const
michael@0 929 {
michael@0 930 const char *fmt;
michael@0 931 switch (aRadix) {
michael@0 932 case 10:
michael@0 933 fmt = "%i";
michael@0 934 break;
michael@0 935
michael@0 936 case 16:
michael@0 937 fmt = "%x";
michael@0 938 break;
michael@0 939
michael@0 940 default:
michael@0 941 NS_ERROR("Unrecognized radix!");
michael@0 942 *aErrorCode = NS_ERROR_INVALID_ARG;
michael@0 943 return 0;
michael@0 944 }
michael@0 945
michael@0 946 int32_t result = 0;
michael@0 947 if (PR_sscanf(nsCString(*this).get(), fmt, &result) == 1)
michael@0 948 *aErrorCode = NS_OK;
michael@0 949 else
michael@0 950 *aErrorCode = NS_ERROR_FAILURE;
michael@0 951
michael@0 952 return result;
michael@0 953 }
michael@0 954
michael@0 955 int64_t
michael@0 956 nsACString::ToInteger64(nsresult *aErrorCode, uint32_t aRadix) const
michael@0 957 {
michael@0 958 const char *fmt;
michael@0 959 switch (aRadix) {
michael@0 960 case 10:
michael@0 961 fmt = "%lli";
michael@0 962 break;
michael@0 963
michael@0 964 case 16:
michael@0 965 fmt = "%llx";
michael@0 966 break;
michael@0 967
michael@0 968 default:
michael@0 969 NS_ERROR("Unrecognized radix!");
michael@0 970 *aErrorCode = NS_ERROR_INVALID_ARG;
michael@0 971 return 0;
michael@0 972 }
michael@0 973
michael@0 974 int64_t result = 0;
michael@0 975 if (PR_sscanf(nsCString(*this).get(), fmt, &result) == 1)
michael@0 976 *aErrorCode = NS_OK;
michael@0 977 else
michael@0 978 *aErrorCode = NS_ERROR_FAILURE;
michael@0 979
michael@0 980 return result;
michael@0 981 }
michael@0 982 #endif // XPCOM_GLUE_AVOID_NSPR
michael@0 983
michael@0 984 // Substrings
michael@0 985
michael@0 986 nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr,
michael@0 987 uint32_t aStartPos)
michael@0 988 {
michael@0 989 const char16_t* data;
michael@0 990 uint32_t len = NS_StringGetData(aStr, &data);
michael@0 991
michael@0 992 if (aStartPos > len)
michael@0 993 aStartPos = len;
michael@0 994
michael@0 995 NS_StringContainerInit2(*this, data + aStartPos, len - aStartPos,
michael@0 996 NS_STRING_CONTAINER_INIT_DEPEND |
michael@0 997 NS_STRING_CONTAINER_INIT_SUBSTRING);
michael@0 998 }
michael@0 999
michael@0 1000 nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr,
michael@0 1001 uint32_t aStartPos,
michael@0 1002 uint32_t aLength)
michael@0 1003 {
michael@0 1004 const char16_t* data;
michael@0 1005 uint32_t len = NS_StringGetData(aStr, &data);
michael@0 1006
michael@0 1007 if (aStartPos > len)
michael@0 1008 aStartPos = len;
michael@0 1009
michael@0 1010 if (aStartPos + aLength > len)
michael@0 1011 aLength = len - aStartPos;
michael@0 1012
michael@0 1013 NS_StringContainerInit2(*this, data + aStartPos, aLength,
michael@0 1014 NS_STRING_CONTAINER_INIT_DEPEND |
michael@0 1015 NS_STRING_CONTAINER_INIT_SUBSTRING);
michael@0 1016 }
michael@0 1017
michael@0 1018 nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr,
michael@0 1019 uint32_t aStartPos)
michael@0 1020 {
michael@0 1021 const char* data;
michael@0 1022 uint32_t len = NS_CStringGetData(aStr, &data);
michael@0 1023
michael@0 1024 if (aStartPos > len)
michael@0 1025 aStartPos = len;
michael@0 1026
michael@0 1027 NS_CStringContainerInit2(*this, data + aStartPos, len - aStartPos,
michael@0 1028 NS_CSTRING_CONTAINER_INIT_DEPEND |
michael@0 1029 NS_CSTRING_CONTAINER_INIT_SUBSTRING);
michael@0 1030 }
michael@0 1031
michael@0 1032 nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr,
michael@0 1033 uint32_t aStartPos,
michael@0 1034 uint32_t aLength)
michael@0 1035 {
michael@0 1036 const char* data;
michael@0 1037 uint32_t len = NS_CStringGetData(aStr, &data);
michael@0 1038
michael@0 1039 if (aStartPos > len)
michael@0 1040 aStartPos = len;
michael@0 1041
michael@0 1042 if (aStartPos + aLength > len)
michael@0 1043 aLength = len - aStartPos;
michael@0 1044
michael@0 1045 NS_CStringContainerInit2(*this, data + aStartPos, aLength,
michael@0 1046 NS_CSTRING_CONTAINER_INIT_DEPEND |
michael@0 1047 NS_CSTRING_CONTAINER_INIT_SUBSTRING);
michael@0 1048 }
michael@0 1049
michael@0 1050 // Utils
michael@0 1051
michael@0 1052 char*
michael@0 1053 ToNewUTF8String(const nsAString& aSource)
michael@0 1054 {
michael@0 1055 nsCString temp;
michael@0 1056 CopyUTF16toUTF8(aSource, temp);
michael@0 1057 return NS_CStringCloneData(temp);
michael@0 1058 }
michael@0 1059
michael@0 1060 void
michael@0 1061 CompressWhitespace(nsAString& aString)
michael@0 1062 {
michael@0 1063 char16_t *start;
michael@0 1064 uint32_t len = NS_StringGetMutableData(aString, UINT32_MAX, &start);
michael@0 1065 char16_t *end = start + len;
michael@0 1066 char16_t *from = start, *to = start;
michael@0 1067
michael@0 1068 // Skip any leading whitespace
michael@0 1069 while (from < end && NS_IsAsciiWhitespace(*from))
michael@0 1070 from++;
michael@0 1071
michael@0 1072 while (from < end) {
michael@0 1073 char16_t theChar = *from++;
michael@0 1074
michael@0 1075 if (NS_IsAsciiWhitespace(theChar)) {
michael@0 1076 // We found a whitespace char, so skip over any more
michael@0 1077 while (from < end && NS_IsAsciiWhitespace(*from))
michael@0 1078 from++;
michael@0 1079
michael@0 1080 // Turn all whitespace into spaces
michael@0 1081 theChar = ' ';
michael@0 1082 }
michael@0 1083
michael@0 1084 *to++ = theChar;
michael@0 1085 }
michael@0 1086
michael@0 1087 // Drop any trailing space
michael@0 1088 if (to > start && to[-1] == ' ')
michael@0 1089 to--;
michael@0 1090
michael@0 1091 // Re-terminate the string
michael@0 1092 *to = '\0';
michael@0 1093
michael@0 1094 // Set the new length
michael@0 1095 aString.SetLength(to - start);
michael@0 1096 }
michael@0 1097
michael@0 1098 uint32_t
michael@0 1099 ToLowerCase(nsACString& aStr)
michael@0 1100 {
michael@0 1101 char *begin, *end;
michael@0 1102 uint32_t len = aStr.BeginWriting(&begin, &end);
michael@0 1103
michael@0 1104 for (; begin < end; ++begin) {
michael@0 1105 *begin = NS_ToLower(*begin);
michael@0 1106 }
michael@0 1107
michael@0 1108 return len;
michael@0 1109 }
michael@0 1110
michael@0 1111 uint32_t
michael@0 1112 ToUpperCase(nsACString& aStr)
michael@0 1113 {
michael@0 1114 char *begin, *end;
michael@0 1115 uint32_t len = aStr.BeginWriting(&begin, &end);
michael@0 1116
michael@0 1117 for (; begin < end; ++begin) {
michael@0 1118 *begin = NS_ToUpper(*begin);
michael@0 1119 }
michael@0 1120
michael@0 1121 return len;
michael@0 1122 }
michael@0 1123
michael@0 1124 uint32_t
michael@0 1125 ToLowerCase(const nsACString& aSrc, nsACString& aDest)
michael@0 1126 {
michael@0 1127 const char *begin, *end;
michael@0 1128 uint32_t len = aSrc.BeginReading(&begin, &end);
michael@0 1129
michael@0 1130 char *dest;
michael@0 1131 NS_CStringGetMutableData(aDest, len, &dest);
michael@0 1132
michael@0 1133 for (; begin < end; ++begin, ++dest) {
michael@0 1134 *dest = NS_ToLower(*begin);
michael@0 1135 }
michael@0 1136
michael@0 1137 return len;
michael@0 1138 }
michael@0 1139
michael@0 1140 uint32_t
michael@0 1141 ToUpperCase(const nsACString& aSrc, nsACString& aDest)
michael@0 1142 {
michael@0 1143 const char *begin, *end;
michael@0 1144 uint32_t len = aSrc.BeginReading(&begin, &end);
michael@0 1145
michael@0 1146 char *dest;
michael@0 1147 NS_CStringGetMutableData(aDest, len, &dest);
michael@0 1148
michael@0 1149 for (; begin < end; ++begin, ++dest) {
michael@0 1150 *dest = NS_ToUpper(*begin);
michael@0 1151 }
michael@0 1152
michael@0 1153 return len;
michael@0 1154 }
michael@0 1155
michael@0 1156 int32_t
michael@0 1157 CaseInsensitiveCompare(const char *a, const char *b,
michael@0 1158 uint32_t len)
michael@0 1159 {
michael@0 1160 for (const char *aend = a + len; a < aend; ++a, ++b) {
michael@0 1161 char la = NS_ToLower(*a);
michael@0 1162 char lb = NS_ToLower(*b);
michael@0 1163
michael@0 1164 if (la == lb)
michael@0 1165 continue;
michael@0 1166
michael@0 1167 return la < lb ? -1 : 1;
michael@0 1168 }
michael@0 1169
michael@0 1170 return 0;
michael@0 1171 }
michael@0 1172
michael@0 1173 bool
michael@0 1174 ParseString(const nsACString& aSource, char aDelimiter,
michael@0 1175 nsTArray<nsCString>& aArray)
michael@0 1176 {
michael@0 1177 int32_t start = 0;
michael@0 1178 int32_t end = aSource.Length();
michael@0 1179
michael@0 1180 uint32_t oldLength = aArray.Length();
michael@0 1181
michael@0 1182 for (;;) {
michael@0 1183 int32_t delimiter = aSource.FindChar(aDelimiter, start);
michael@0 1184 if (delimiter < 0) {
michael@0 1185 delimiter = end;
michael@0 1186 }
michael@0 1187
michael@0 1188 if (delimiter != start) {
michael@0 1189 if (!aArray.AppendElement(Substring(aSource, start, delimiter - start))) {
michael@0 1190 aArray.RemoveElementsAt(oldLength, aArray.Length() - oldLength);
michael@0 1191 return false;
michael@0 1192 }
michael@0 1193 }
michael@0 1194
michael@0 1195 if (delimiter == end)
michael@0 1196 break;
michael@0 1197 start = ++delimiter;
michael@0 1198 if (start == end)
michael@0 1199 break;
michael@0 1200 }
michael@0 1201
michael@0 1202 return true;
michael@0 1203 }

mercurial