Bumping manifests a=b2g-bump
[gecko.git] / xpcom / glue / nsStringAPI.cpp
blob185928779957b20751fc3a62a5a7d92cc11aad2b
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nscore.h"
8 #include "nsCRTGlue.h"
9 #include "prprf.h"
10 #include "nsStringAPI.h"
11 #include "nsXPCOMStrings.h"
12 #include "nsDebug.h"
14 #include <stdio.h>
16 #ifdef XP_WIN
17 #define snprintf _snprintf
18 #endif
20 // nsAString
22 uint32_t
23 nsAString::BeginReading(const char_type** aBegin, const char_type** aEnd) const
25 uint32_t len = NS_StringGetData(*this, aBegin);
26 if (aEnd) {
27 *aEnd = *aBegin + len;
30 return len;
33 const nsAString::char_type*
34 nsAString::BeginReading() const
36 const char_type* data;
37 NS_StringGetData(*this, &data);
38 return data;
41 const nsAString::char_type*
42 nsAString::EndReading() const
44 const char_type* data;
45 uint32_t len = NS_StringGetData(*this, &data);
46 return data + len;
49 uint32_t
50 nsAString::BeginWriting(char_type** aBegin, char_type** aEnd, uint32_t aNewSize)
52 uint32_t len = NS_StringGetMutableData(*this, aNewSize, aBegin);
53 if (aEnd) {
54 *aEnd = *aBegin + len;
57 return len;
60 nsAString::char_type*
61 nsAString::BeginWriting(uint32_t aLen)
63 char_type* data;
64 NS_StringGetMutableData(*this, aLen, &data);
65 return data;
68 nsAString::char_type*
69 nsAString::EndWriting()
71 char_type* data;
72 uint32_t len = NS_StringGetMutableData(*this, UINT32_MAX, &data);
73 return data + len;
76 bool
77 nsAString::SetLength(uint32_t aLen)
79 char_type* data;
80 NS_StringGetMutableData(*this, aLen, &data);
81 return data != nullptr;
84 void
85 nsAString::AssignLiteral(const char* aStr)
87 uint32_t len = strlen(aStr);
88 char16_t* buf = BeginWriting(len);
89 if (!buf) {
90 return;
93 for (; *aStr; ++aStr, ++buf) {
94 *buf = *aStr;
98 void
99 nsAString::AppendLiteral(const char* aASCIIStr)
101 uint32_t appendLen = strlen(aASCIIStr);
103 uint32_t thisLen = Length();
104 char16_t* begin;
105 char16_t* end;
106 BeginWriting(&begin, &end, appendLen + thisLen);
107 if (!begin) {
108 return;
111 for (begin += thisLen; begin < end; ++begin, ++aASCIIStr) {
112 *begin = *aASCIIStr;
116 void
117 nsAString::StripChars(const char* aSet)
119 nsString copy(*this);
121 const char_type* source;
122 const char_type* sourceEnd;
123 copy.BeginReading(&source, &sourceEnd);
125 char_type* dest;
126 BeginWriting(&dest);
127 if (!dest) {
128 return;
131 char_type* curDest = dest;
133 for (; source < sourceEnd; ++source) {
134 const char* test;
135 for (test = aSet; *test; ++test) {
136 if (*source == char_type(*test)) {
137 break;
141 if (!*test) {
142 // not stripped, copy this char
143 *curDest = *source;
144 ++curDest;
148 SetLength(curDest - dest);
151 void
152 nsAString::Trim(const char* aSet, bool aLeading, bool aTrailing)
154 NS_ASSERTION(aLeading || aTrailing, "Ineffective Trim");
156 const char16_t* start;
157 const char16_t* end;
158 uint32_t cutLen;
160 if (aLeading) {
161 BeginReading(&start, &end);
162 for (cutLen = 0; start < end; ++start, ++cutLen) {
163 const char* test;
164 for (test = aSet; *test; ++test) {
165 if (*test == *start) {
166 break;
169 if (!*test) {
170 break;
173 if (cutLen) {
174 NS_StringCutData(*this, 0, cutLen);
177 if (aTrailing) {
178 uint32_t len = BeginReading(&start, &end);
179 --end;
180 for (cutLen = 0; end >= start; --end, ++cutLen) {
181 const char* test;
182 for (test = aSet; *test; ++test) {
183 if (*test == *end) {
184 break;
187 if (!*test) {
188 break;
191 if (cutLen) {
192 NS_StringCutData(*this, len - cutLen, cutLen);
197 int32_t
198 nsAString::DefaultComparator(const char_type* aStrA, const char_type* aStrB,
199 uint32_t aLen)
201 for (const char_type* end = aStrA + aLen; aStrA < end; ++aStrA, ++aStrB) {
202 if (*aStrA == *aStrB) {
203 continue;
206 return *aStrA < *aStrB ? -1 : 1;
209 return 0;
212 int32_t
213 nsAString::Compare(const char_type* aOther, ComparatorFunc aComparator) const
215 const char_type* cself;
216 uint32_t selflen = NS_StringGetData(*this, &cself);
217 uint32_t otherlen = NS_strlen(aOther);
218 uint32_t comparelen = selflen <= otherlen ? selflen : otherlen;
220 int32_t result = aComparator(cself, aOther, comparelen);
221 if (result == 0) {
222 if (selflen < otherlen) {
223 return -1;
224 } else if (selflen > otherlen) {
225 return 1;
228 return result;
231 int32_t
232 nsAString::Compare(const self_type& aOther, ComparatorFunc aComparator) const
234 const char_type* cself;
235 const char_type* cother;
236 uint32_t selflen = NS_StringGetData(*this, &cself);
237 uint32_t otherlen = NS_StringGetData(aOther, &cother);
238 uint32_t comparelen = selflen <= otherlen ? selflen : otherlen;
240 int32_t result = aComparator(cself, cother, comparelen);
241 if (result == 0) {
242 if (selflen < otherlen) {
243 return -1;
244 } else if (selflen > otherlen) {
245 return 1;
248 return result;
251 bool
252 nsAString::Equals(const char_type* aOther, ComparatorFunc aComparator) const
254 const char_type* cself;
255 uint32_t selflen = NS_StringGetData(*this, &cself);
256 uint32_t otherlen = NS_strlen(aOther);
258 if (selflen != otherlen) {
259 return false;
262 return aComparator(cself, aOther, selflen) == 0;
265 bool
266 nsAString::Equals(const self_type& aOther, ComparatorFunc aComparator) const
268 const char_type* cself;
269 const char_type* cother;
270 uint32_t selflen = NS_StringGetData(*this, &cself);
271 uint32_t otherlen = NS_StringGetData(aOther, &cother);
273 if (selflen != otherlen) {
274 return false;
277 return aComparator(cself, cother, selflen) == 0;
280 bool
281 nsAString::EqualsLiteral(const char* aASCIIString) const
283 const char16_t* begin;
284 const char16_t* end;
285 BeginReading(&begin, &end);
287 for (; begin < end; ++begin, ++aASCIIString) {
288 if (!*aASCIIString || !NS_IsAscii(*begin) ||
289 (char)*begin != *aASCIIString) {
290 return false;
294 return *aASCIIString == '\0';
297 bool
298 nsAString::LowerCaseEqualsLiteral(const char* aASCIIString) const
300 const char16_t* begin;
301 const char16_t* end;
302 BeginReading(&begin, &end);
304 for (; begin < end; ++begin, ++aASCIIString) {
305 if (!*aASCIIString || !NS_IsAscii(*begin) ||
306 NS_ToLower((char)*begin) != *aASCIIString) {
307 return false;
311 return *aASCIIString == '\0';
314 int32_t
315 nsAString::Find(const self_type& aStr, uint32_t aOffset,
316 ComparatorFunc aComparator) const
318 const char_type* begin;
319 const char_type* end;
320 uint32_t selflen = BeginReading(&begin, &end);
322 if (aOffset > selflen) {
323 return -1;
326 const char_type* other;
327 uint32_t otherlen = aStr.BeginReading(&other);
329 if (otherlen > selflen - aOffset) {
330 return -1;
333 // We want to stop searching otherlen characters before the end of the string
334 end -= otherlen;
336 for (const char_type* cur = begin + aOffset; cur <= end; ++cur) {
337 if (!aComparator(cur, other, otherlen)) {
338 return cur - begin;
341 return -1;
344 static bool
345 ns_strnmatch(const char16_t* aStr, const char* aSubstring, uint32_t aLen)
347 for (; aLen; ++aStr, ++aSubstring, --aLen) {
348 if (!NS_IsAscii(*aStr)) {
349 return false;
352 if ((char)*aStr != *aSubstring) {
353 return false;
357 return true;
360 static bool
361 ns_strnimatch(const char16_t* aStr, const char* aSubstring, uint32_t aLen)
363 for (; aLen; ++aStr, ++aSubstring, --aLen) {
364 if (!NS_IsAscii(*aStr)) {
365 return false;
368 if (NS_ToLower((char)*aStr) != NS_ToLower(*aSubstring)) {
369 return false;
373 return true;
376 int32_t
377 nsAString::Find(const char* aStr, uint32_t aOffset, bool aIgnoreCase) const
379 bool (*match)(const char16_t*, const char*, uint32_t) =
380 aIgnoreCase ? ns_strnimatch : ns_strnmatch;
382 const char_type* begin;
383 const char_type* end;
384 uint32_t selflen = BeginReading(&begin, &end);
386 if (aOffset > selflen) {
387 return -1;
390 uint32_t otherlen = strlen(aStr);
392 if (otherlen > selflen - aOffset) {
393 return -1;
396 // We want to stop searching otherlen characters before the end of the string
397 end -= otherlen;
399 for (const char_type* cur = begin + aOffset; cur <= end; ++cur) {
400 if (match(cur, aStr, otherlen)) {
401 return cur - begin;
404 return -1;
407 int32_t
408 nsAString::RFind(const self_type& aStr, int32_t aOffset,
409 ComparatorFunc aComparator) const
411 const char_type* begin;
412 const char_type* end;
413 uint32_t selflen = BeginReading(&begin, &end);
415 const char_type* other;
416 uint32_t otherlen = aStr.BeginReading(&other);
418 if (selflen < otherlen) {
419 return -1;
422 if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen)) {
423 end -= otherlen;
424 } else {
425 end = begin + aOffset;
428 for (const char_type* cur = end; cur >= begin; --cur) {
429 if (!aComparator(cur, other, otherlen)) {
430 return cur - begin;
433 return -1;
436 int32_t
437 nsAString::RFind(const char* aStr, int32_t aOffset, bool aIgnoreCase) const
439 bool (*match)(const char16_t*, const char*, uint32_t) =
440 aIgnoreCase ? ns_strnimatch : ns_strnmatch;
442 const char_type* begin;
443 const char_type* end;
444 uint32_t selflen = BeginReading(&begin, &end);
445 uint32_t otherlen = strlen(aStr);
447 if (selflen < otherlen) {
448 return -1;
451 if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen)) {
452 end -= otherlen;
453 } else {
454 end = begin + aOffset;
457 for (const char_type* cur = end; cur >= begin; --cur) {
458 if (match(cur, aStr, otherlen)) {
459 return cur - begin;
462 return -1;
465 int32_t
466 nsAString::FindChar(char_type aChar, uint32_t aOffset) const
468 const char_type* start;
469 const char_type* end;
470 uint32_t len = BeginReading(&start, &end);
471 if (aOffset > len) {
472 return -1;
475 const char_type* cur;
477 for (cur = start + aOffset; cur < end; ++cur) {
478 if (*cur == aChar) {
479 return cur - start;
483 return -1;
486 int32_t
487 nsAString::RFindChar(char_type aChar) const
489 const char16_t* start;
490 const char16_t* end;
491 BeginReading(&start, &end);
493 do {
494 --end;
496 if (*end == aChar) {
497 return end - start;
500 } while (end >= start);
502 return -1;
505 void
506 nsAString::AppendInt(int aInt, int32_t aRadix)
508 const char* fmt;
509 switch (aRadix) {
510 case 8:
511 fmt = "%o";
512 break;
514 case 10:
515 fmt = "%d";
516 break;
518 case 16:
519 fmt = "%x";
520 break;
522 default:
523 NS_ERROR("Unrecognized radix");
524 fmt = "";
527 char buf[20];
528 int len = snprintf(buf, sizeof(buf), fmt, aInt);
529 buf[sizeof(buf) - 1] = '\0';
531 Append(NS_ConvertASCIItoUTF16(buf, len));
534 // Strings
536 #ifndef XPCOM_GLUE_AVOID_NSPR
537 int32_t
538 nsAString::ToInteger(nsresult* aErrorCode, uint32_t aRadix) const
540 NS_ConvertUTF16toUTF8 narrow(*this);
542 const char* fmt;
543 switch (aRadix) {
544 case 10:
545 fmt = "%i";
546 break;
548 case 16:
549 fmt = "%x";
550 break;
552 default:
553 NS_ERROR("Unrecognized radix!");
554 *aErrorCode = NS_ERROR_INVALID_ARG;
555 return 0;
558 int32_t result = 0;
559 if (PR_sscanf(narrow.get(), fmt, &result) == 1) {
560 *aErrorCode = NS_OK;
561 } else {
562 *aErrorCode = NS_ERROR_FAILURE;
565 return result;
568 int64_t
569 nsAString::ToInteger64(nsresult* aErrorCode, uint32_t aRadix) const
571 NS_ConvertUTF16toUTF8 narrow(*this);
573 const char* fmt;
574 switch (aRadix) {
575 case 10:
576 fmt = "%lli";
577 break;
579 case 16:
580 fmt = "%llx";
581 break;
583 default:
584 NS_ERROR("Unrecognized radix!");
585 *aErrorCode = NS_ERROR_INVALID_ARG;
586 return 0;
589 int64_t result = 0;
590 if (PR_sscanf(narrow.get(), fmt, &result) == 1) {
591 *aErrorCode = NS_OK;
592 } else {
593 *aErrorCode = NS_ERROR_FAILURE;
596 return result;
598 #endif // XPCOM_GLUE_AVOID_NSPR
600 // nsACString
602 uint32_t
603 nsACString::BeginReading(const char_type** aBegin, const char_type** aEnd) const
605 uint32_t len = NS_CStringGetData(*this, aBegin);
606 if (aEnd) {
607 *aEnd = *aBegin + len;
610 return len;
613 const nsACString::char_type*
614 nsACString::BeginReading() const
616 const char_type* data;
617 NS_CStringGetData(*this, &data);
618 return data;
621 const nsACString::char_type*
622 nsACString::EndReading() const
624 const char_type* data;
625 uint32_t len = NS_CStringGetData(*this, &data);
626 return data + len;
629 uint32_t
630 nsACString::BeginWriting(char_type** aBegin, char_type** aEnd,
631 uint32_t aNewSize)
633 uint32_t len = NS_CStringGetMutableData(*this, aNewSize, aBegin);
634 if (aEnd) {
635 *aEnd = *aBegin + len;
638 return len;
641 nsACString::char_type*
642 nsACString::BeginWriting(uint32_t aLen)
644 char_type* data;
645 NS_CStringGetMutableData(*this, aLen, &data);
646 return data;
649 nsACString::char_type*
650 nsACString::EndWriting()
652 char_type* data;
653 uint32_t len = NS_CStringGetMutableData(*this, UINT32_MAX, &data);
654 return data + len;
657 bool
658 nsACString::SetLength(uint32_t aLen)
660 char_type* data;
661 NS_CStringGetMutableData(*this, aLen, &data);
662 return data != nullptr;
665 void
666 nsACString::StripChars(const char* aSet)
668 nsCString copy(*this);
670 const char_type* source;
671 const char_type* sourceEnd;
672 copy.BeginReading(&source, &sourceEnd);
674 char_type* dest;
675 BeginWriting(&dest);
676 if (!dest) {
677 return;
680 char_type* curDest = dest;
682 for (; source < sourceEnd; ++source) {
683 const char* test;
684 for (test = aSet; *test; ++test) {
685 if (*source == char_type(*test)) {
686 break;
690 if (!*test) {
691 // not stripped, copy this char
692 *curDest = *source;
693 ++curDest;
697 SetLength(curDest - dest);
700 void
701 nsACString::Trim(const char* aSet, bool aLeading, bool aTrailing)
703 NS_ASSERTION(aLeading || aTrailing, "Ineffective Trim");
705 const char* start;
706 const char* end;
707 uint32_t cutLen;
709 if (aLeading) {
710 BeginReading(&start, &end);
711 for (cutLen = 0; start < end; ++start, ++cutLen) {
712 const char* test;
713 for (test = aSet; *test; ++test) {
714 if (*test == *start) {
715 break;
718 if (!*test) {
719 break;
722 if (cutLen) {
723 NS_CStringCutData(*this, 0, cutLen);
726 if (aTrailing) {
727 uint32_t len = BeginReading(&start, &end);
728 --end;
729 for (cutLen = 0; end >= start; --end, ++cutLen) {
730 const char* test;
731 for (test = aSet; *test; ++test) {
732 if (*test == *end) {
733 break;
736 if (!*test) {
737 break;
740 if (cutLen) {
741 NS_CStringCutData(*this, len - cutLen, cutLen);
746 int32_t
747 nsACString::DefaultComparator(const char_type* aStrA, const char_type* aStrB,
748 uint32_t aLen)
750 return memcmp(aStrA, aStrB, aLen);
753 int32_t
754 nsACString::Compare(const char_type* aOther, ComparatorFunc aComparator) const
756 const char_type* cself;
757 uint32_t selflen = NS_CStringGetData(*this, &cself);
758 uint32_t otherlen = strlen(aOther);
759 uint32_t comparelen = selflen <= otherlen ? selflen : otherlen;
761 int32_t result = aComparator(cself, aOther, comparelen);
762 if (result == 0) {
763 if (selflen < otherlen) {
764 return -1;
765 } else if (selflen > otherlen) {
766 return 1;
769 return result;
772 int32_t
773 nsACString::Compare(const self_type& aOther, ComparatorFunc aComparator) const
775 const char_type* cself;
776 const char_type* cother;
777 uint32_t selflen = NS_CStringGetData(*this, &cself);
778 uint32_t otherlen = NS_CStringGetData(aOther, &cother);
779 uint32_t comparelen = selflen <= otherlen ? selflen : otherlen;
781 int32_t result = aComparator(cself, cother, comparelen);
782 if (result == 0) {
783 if (selflen < otherlen) {
784 return -1;
785 } else if (selflen > otherlen) {
786 return 1;
789 return result;
792 bool
793 nsACString::Equals(const char_type* aOther, ComparatorFunc aComparator) const
795 const char_type* cself;
796 uint32_t selflen = NS_CStringGetData(*this, &cself);
797 uint32_t otherlen = strlen(aOther);
799 if (selflen != otherlen) {
800 return false;
803 return aComparator(cself, aOther, selflen) == 0;
806 bool
807 nsACString::Equals(const self_type& aOther, ComparatorFunc aComparator) const
809 const char_type* cself;
810 const char_type* cother;
811 uint32_t selflen = NS_CStringGetData(*this, &cself);
812 uint32_t otherlen = NS_CStringGetData(aOther, &cother);
814 if (selflen != otherlen) {
815 return false;
818 return aComparator(cself, cother, selflen) == 0;
821 int32_t
822 nsACString::Find(const self_type& aStr, uint32_t aOffset,
823 ComparatorFunc aComparator) const
825 const char_type* begin;
826 const char_type* end;
827 uint32_t selflen = BeginReading(&begin, &end);
829 if (aOffset > selflen) {
830 return -1;
833 const char_type* other;
834 uint32_t otherlen = aStr.BeginReading(&other);
836 if (otherlen > selflen - aOffset) {
837 return -1;
840 // We want to stop searching otherlen characters before the end of the string
841 end -= otherlen;
843 for (const char_type* cur = begin + aOffset; cur <= end; ++cur) {
844 if (!aComparator(cur, other, otherlen)) {
845 return cur - begin;
848 return -1;
851 int32_t
852 nsACString::Find(const char_type* aStr, ComparatorFunc aComparator) const
854 return Find(aStr, strlen(aStr), aComparator);
857 int32_t
858 nsACString::Find(const char_type* aStr, uint32_t aLen,
859 ComparatorFunc aComparator) const
861 const char_type* begin;
862 const char_type* end;
863 uint32_t selflen = BeginReading(&begin, &end);
865 if (aLen == 0) {
866 NS_WARNING("Searching for zero-length string.");
867 return -1;
870 if (aLen > selflen) {
871 return -1;
874 // We want to stop searching otherlen characters before the end of the string
875 end -= aLen;
877 for (const char_type* cur = begin; cur <= end; ++cur) {
878 if (!aComparator(cur, aStr, aLen)) {
879 return cur - begin;
882 return -1;
885 int32_t
886 nsACString::RFind(const self_type& aStr, int32_t aOffset,
887 ComparatorFunc aComparator) const
889 const char_type* begin;
890 const char_type* end;
891 uint32_t selflen = BeginReading(&begin, &end);
893 const char_type* other;
894 uint32_t otherlen = aStr.BeginReading(&other);
896 if (selflen < otherlen) {
897 return -1;
900 if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen)) {
901 end -= otherlen;
902 } else {
903 end = begin + aOffset;
906 for (const char_type* cur = end; cur >= begin; --cur) {
907 if (!aComparator(cur, other, otherlen)) {
908 return cur - begin;
911 return -1;
914 int32_t
915 nsACString::RFind(const char_type* aStr, ComparatorFunc aComparator) const
917 return RFind(aStr, strlen(aStr), aComparator);
920 int32_t
921 nsACString::RFind(const char_type* aStr, int32_t aLen,
922 ComparatorFunc aComparator) const
924 const char_type* begin;
925 const char_type* end;
926 uint32_t selflen = BeginReading(&begin, &end);
928 if (aLen <= 0) {
929 NS_WARNING("Searching for zero-length string.");
930 return -1;
933 if (uint32_t(aLen) > selflen) {
934 return -1;
937 // We want to start searching otherlen characters before the end of the string
938 end -= aLen;
940 for (const char_type* cur = end; cur >= begin; --cur) {
941 if (!aComparator(cur, aStr, aLen)) {
942 return cur - begin;
945 return -1;
948 int32_t
949 nsACString::FindChar(char_type aChar, uint32_t aOffset) const
951 const char_type* start;
952 const char_type* end;
953 uint32_t len = BeginReading(&start, &end);
954 if (aOffset > len) {
955 return -1;
958 const char_type* cur;
960 for (cur = start + aOffset; cur < end; ++cur) {
961 if (*cur == aChar) {
962 return cur - start;
966 return -1;
969 int32_t
970 nsACString::RFindChar(char_type aChar) const
972 const char* start;
973 const char* end;
974 BeginReading(&start, &end);
976 for (; end >= start; --end) {
977 if (*end == aChar) {
978 return end - start;
982 return -1;
985 void
986 nsACString::AppendInt(int aInt, int32_t aRadix)
988 const char* fmt;
989 switch (aRadix) {
990 case 8:
991 fmt = "%o";
992 break;
994 case 10:
995 fmt = "%d";
996 break;
998 case 16:
999 fmt = "%x";
1000 break;
1002 default:
1003 NS_ERROR("Unrecognized radix");
1004 fmt = "";
1007 char buf[20];
1008 int len = snprintf(buf, sizeof(buf), fmt, aInt);
1009 buf[sizeof(buf) - 1] = '\0';
1011 Append(buf, len);
1014 #ifndef XPCOM_GLUE_AVOID_NSPR
1015 int32_t
1016 nsACString::ToInteger(nsresult* aErrorCode, uint32_t aRadix) const
1018 const char* fmt;
1019 switch (aRadix) {
1020 case 10:
1021 fmt = "%i";
1022 break;
1024 case 16:
1025 fmt = "%x";
1026 break;
1028 default:
1029 NS_ERROR("Unrecognized radix!");
1030 *aErrorCode = NS_ERROR_INVALID_ARG;
1031 return 0;
1034 int32_t result = 0;
1035 if (PR_sscanf(nsCString(*this).get(), fmt, &result) == 1) {
1036 *aErrorCode = NS_OK;
1037 } else {
1038 *aErrorCode = NS_ERROR_FAILURE;
1041 return result;
1044 int64_t
1045 nsACString::ToInteger64(nsresult* aErrorCode, uint32_t aRadix) const
1047 const char* fmt;
1048 switch (aRadix) {
1049 case 10:
1050 fmt = "%lli";
1051 break;
1053 case 16:
1054 fmt = "%llx";
1055 break;
1057 default:
1058 NS_ERROR("Unrecognized radix!");
1059 *aErrorCode = NS_ERROR_INVALID_ARG;
1060 return 0;
1063 int64_t result = 0;
1064 if (PR_sscanf(nsCString(*this).get(), fmt, &result) == 1) {
1065 *aErrorCode = NS_OK;
1066 } else {
1067 *aErrorCode = NS_ERROR_FAILURE;
1070 return result;
1072 #endif // XPCOM_GLUE_AVOID_NSPR
1074 // Substrings
1076 nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr,
1077 uint32_t aStartPos)
1079 const char16_t* data;
1080 uint32_t len = NS_StringGetData(aStr, &data);
1082 if (aStartPos > len) {
1083 aStartPos = len;
1086 NS_StringContainerInit2(*this, data + aStartPos, len - aStartPos,
1087 NS_STRING_CONTAINER_INIT_DEPEND |
1088 NS_STRING_CONTAINER_INIT_SUBSTRING);
1091 nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr,
1092 uint32_t aStartPos,
1093 uint32_t aLength)
1095 const char16_t* data;
1096 uint32_t len = NS_StringGetData(aStr, &data);
1098 if (aStartPos > len) {
1099 aStartPos = len;
1102 if (aStartPos + aLength > len) {
1103 aLength = len - aStartPos;
1106 NS_StringContainerInit2(*this, data + aStartPos, aLength,
1107 NS_STRING_CONTAINER_INIT_DEPEND |
1108 NS_STRING_CONTAINER_INIT_SUBSTRING);
1111 nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr,
1112 uint32_t aStartPos)
1114 const char* data;
1115 uint32_t len = NS_CStringGetData(aStr, &data);
1117 if (aStartPos > len) {
1118 aStartPos = len;
1121 NS_CStringContainerInit2(*this, data + aStartPos, len - aStartPos,
1122 NS_CSTRING_CONTAINER_INIT_DEPEND |
1123 NS_CSTRING_CONTAINER_INIT_SUBSTRING);
1126 nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr,
1127 uint32_t aStartPos,
1128 uint32_t aLength)
1130 const char* data;
1131 uint32_t len = NS_CStringGetData(aStr, &data);
1133 if (aStartPos > len) {
1134 aStartPos = len;
1137 if (aStartPos + aLength > len) {
1138 aLength = len - aStartPos;
1141 NS_CStringContainerInit2(*this, data + aStartPos, aLength,
1142 NS_CSTRING_CONTAINER_INIT_DEPEND |
1143 NS_CSTRING_CONTAINER_INIT_SUBSTRING);
1146 // Utils
1148 char*
1149 ToNewUTF8String(const nsAString& aSource)
1151 nsCString temp;
1152 CopyUTF16toUTF8(aSource, temp);
1153 return NS_CStringCloneData(temp);
1156 void
1157 CompressWhitespace(nsAString& aString)
1159 char16_t* start;
1160 uint32_t len = NS_StringGetMutableData(aString, UINT32_MAX, &start);
1161 char16_t* end = start + len;
1162 char16_t* from = start;
1163 char16_t* to = start;
1165 // Skip any leading whitespace
1166 while (from < end && NS_IsAsciiWhitespace(*from)) {
1167 from++;
1170 while (from < end) {
1171 char16_t theChar = *from++;
1173 if (NS_IsAsciiWhitespace(theChar)) {
1174 // We found a whitespace char, so skip over any more
1175 while (from < end && NS_IsAsciiWhitespace(*from)) {
1176 from++;
1179 // Turn all whitespace into spaces
1180 theChar = ' ';
1183 *to++ = theChar;
1186 // Drop any trailing space
1187 if (to > start && to[-1] == ' ') {
1188 to--;
1191 // Re-terminate the string
1192 *to = '\0';
1194 // Set the new length
1195 aString.SetLength(to - start);
1198 uint32_t
1199 ToLowerCase(nsACString& aStr)
1201 char* begin;
1202 char* end;
1203 uint32_t len = aStr.BeginWriting(&begin, &end);
1205 for (; begin < end; ++begin) {
1206 *begin = NS_ToLower(*begin);
1209 return len;
1212 uint32_t
1213 ToUpperCase(nsACString& aStr)
1215 char* begin;
1216 char* end;
1217 uint32_t len = aStr.BeginWriting(&begin, &end);
1219 for (; begin < end; ++begin) {
1220 *begin = NS_ToUpper(*begin);
1223 return len;
1226 uint32_t
1227 ToLowerCase(const nsACString& aSrc, nsACString& aDest)
1229 const char* begin;
1230 const char* end;
1231 uint32_t len = aSrc.BeginReading(&begin, &end);
1233 char* dest;
1234 NS_CStringGetMutableData(aDest, len, &dest);
1236 for (; begin < end; ++begin, ++dest) {
1237 *dest = NS_ToLower(*begin);
1240 return len;
1243 uint32_t
1244 ToUpperCase(const nsACString& aSrc, nsACString& aDest)
1246 const char* begin;
1247 const char* end;
1248 uint32_t len = aSrc.BeginReading(&begin, &end);
1250 char* dest;
1251 NS_CStringGetMutableData(aDest, len, &dest);
1253 for (; begin < end; ++begin, ++dest) {
1254 *dest = NS_ToUpper(*begin);
1257 return len;
1260 int32_t
1261 CaseInsensitiveCompare(const char* aStrA, const char* aStrB,
1262 uint32_t aLen)
1264 for (const char* aend = aStrA + aLen; aStrA < aend; ++aStrA, ++aStrB) {
1265 char la = NS_ToLower(*aStrA);
1266 char lb = NS_ToLower(*aStrB);
1268 if (la == lb) {
1269 continue;
1272 return la < lb ? -1 : 1;
1275 return 0;
1278 bool
1279 ParseString(const nsACString& aSource, char aDelimiter,
1280 nsTArray<nsCString>& aArray)
1282 int32_t start = 0;
1283 int32_t end = aSource.Length();
1285 uint32_t oldLength = aArray.Length();
1287 for (;;) {
1288 int32_t delimiter = aSource.FindChar(aDelimiter, start);
1289 if (delimiter < 0) {
1290 delimiter = end;
1293 if (delimiter != start) {
1294 if (!aArray.AppendElement(Substring(aSource, start, delimiter - start))) {
1295 aArray.RemoveElementsAt(oldLength, aArray.Length() - oldLength);
1296 return false;
1300 if (delimiter == end) {
1301 break;
1303 start = ++delimiter;
1304 if (start == end) {
1305 break;
1309 return true;