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