diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /xpcom/glue/nsStringAPI.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'xpcom/glue/nsStringAPI.cpp')
-rw-r--r-- | xpcom/glue/nsStringAPI.cpp | 1304 |
1 files changed, 1304 insertions, 0 deletions
diff --git a/xpcom/glue/nsStringAPI.cpp b/xpcom/glue/nsStringAPI.cpp new file mode 100644 index 000000000..e5114a149 --- /dev/null +++ b/xpcom/glue/nsStringAPI.cpp @@ -0,0 +1,1304 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nscore.h" +#include "nsCRTGlue.h" +#include "prprf.h" +#include "nsStringAPI.h" +#include "nsXPCOMStrings.h" +#include "nsDebug.h" + +#include "mozilla/Sprintf.h" + +#include <stdio.h> + +// nsAString + +uint32_t +nsAString::BeginReading(const char_type** aBegin, const char_type** aEnd) const +{ + uint32_t len = NS_StringGetData(*this, aBegin); + if (aEnd) { + *aEnd = *aBegin + len; + } + + return len; +} + +const nsAString::char_type* +nsAString::BeginReading() const +{ + const char_type* data; + NS_StringGetData(*this, &data); + return data; +} + +const nsAString::char_type* +nsAString::EndReading() const +{ + const char_type* data; + uint32_t len = NS_StringGetData(*this, &data); + return data + len; +} + +uint32_t +nsAString::BeginWriting(char_type** aBegin, char_type** aEnd, uint32_t aNewSize) +{ + uint32_t len = NS_StringGetMutableData(*this, aNewSize, aBegin); + if (aEnd) { + *aEnd = *aBegin + len; + } + + return len; +} + +nsAString::char_type* +nsAString::BeginWriting(uint32_t aLen) +{ + char_type* data; + NS_StringGetMutableData(*this, aLen, &data); + return data; +} + +nsAString::char_type* +nsAString::EndWriting() +{ + char_type* data; + uint32_t len = NS_StringGetMutableData(*this, UINT32_MAX, &data); + return data + len; +} + +bool +nsAString::SetLength(uint32_t aLen) +{ + char_type* data; + NS_StringGetMutableData(*this, aLen, &data); + return data != nullptr; +} + +void +nsAString::AssignLiteral(const char* aStr) +{ + uint32_t len = strlen(aStr); + char16_t* buf = BeginWriting(len); + if (!buf) { + return; + } + + for (; *aStr; ++aStr, ++buf) { + *buf = *aStr; + } +} + +void +nsAString::AppendLiteral(const char* aASCIIStr) +{ + uint32_t appendLen = strlen(aASCIIStr); + + uint32_t thisLen = Length(); + char16_t* begin; + char16_t* end; + BeginWriting(&begin, &end, appendLen + thisLen); + if (!begin) { + return; + } + + for (begin += thisLen; begin < end; ++begin, ++aASCIIStr) { + *begin = *aASCIIStr; + } +} + +void +nsAString::StripChars(const char* aSet) +{ + nsString copy(*this); + + const char_type* source; + const char_type* sourceEnd; + copy.BeginReading(&source, &sourceEnd); + + char_type* dest; + BeginWriting(&dest); + if (!dest) { + return; + } + + char_type* curDest = dest; + + for (; source < sourceEnd; ++source) { + const char* test; + for (test = aSet; *test; ++test) { + if (*source == char_type(*test)) { + break; + } + } + + if (!*test) { + // not stripped, copy this char + *curDest = *source; + ++curDest; + } + } + + SetLength(curDest - dest); +} + +void +nsAString::Trim(const char* aSet, bool aLeading, bool aTrailing) +{ + NS_ASSERTION(aLeading || aTrailing, "Ineffective Trim"); + + const char16_t* start; + const char16_t* end; + uint32_t cutLen; + + if (aLeading) { + BeginReading(&start, &end); + for (cutLen = 0; start < end; ++start, ++cutLen) { + const char* test; + for (test = aSet; *test; ++test) { + if (*test == *start) { + break; + } + } + if (!*test) { + break; + } + } + if (cutLen) { + NS_StringCutData(*this, 0, cutLen); + } + } + if (aTrailing) { + uint32_t len = BeginReading(&start, &end); + --end; + for (cutLen = 0; end >= start; --end, ++cutLen) { + const char* test; + for (test = aSet; *test; ++test) { + if (*test == *end) { + break; + } + } + if (!*test) { + break; + } + } + if (cutLen) { + NS_StringCutData(*this, len - cutLen, cutLen); + } + } +} + +int32_t +nsAString::DefaultComparator(const char_type* aStrA, const char_type* aStrB, + uint32_t aLen) +{ + for (const char_type* end = aStrA + aLen; aStrA < end; ++aStrA, ++aStrB) { + if (*aStrA == *aStrB) { + continue; + } + + return *aStrA < *aStrB ? -1 : 1; + } + + return 0; +} + +int32_t +nsAString::Compare(const char_type* aOther, ComparatorFunc aComparator) const +{ + const char_type* cself; + uint32_t selflen = NS_StringGetData(*this, &cself); + uint32_t otherlen = NS_strlen(aOther); + uint32_t comparelen = selflen <= otherlen ? selflen : otherlen; + + int32_t result = aComparator(cself, aOther, comparelen); + if (result == 0) { + if (selflen < otherlen) { + return -1; + } else if (selflen > otherlen) { + return 1; + } + } + return result; +} + +int32_t +nsAString::Compare(const self_type& aOther, ComparatorFunc aComparator) const +{ + const char_type* cself; + const char_type* cother; + uint32_t selflen = NS_StringGetData(*this, &cself); + uint32_t otherlen = NS_StringGetData(aOther, &cother); + uint32_t comparelen = selflen <= otherlen ? selflen : otherlen; + + int32_t result = aComparator(cself, cother, comparelen); + if (result == 0) { + if (selflen < otherlen) { + return -1; + } else if (selflen > otherlen) { + return 1; + } + } + return result; +} + +bool +nsAString::Equals(const char_type* aOther, ComparatorFunc aComparator) const +{ + const char_type* cself; + uint32_t selflen = NS_StringGetData(*this, &cself); + uint32_t otherlen = NS_strlen(aOther); + + if (selflen != otherlen) { + return false; + } + + return aComparator(cself, aOther, selflen) == 0; +} + +bool +nsAString::Equals(const self_type& aOther, ComparatorFunc aComparator) const +{ + const char_type* cself; + const char_type* cother; + uint32_t selflen = NS_StringGetData(*this, &cself); + uint32_t otherlen = NS_StringGetData(aOther, &cother); + + if (selflen != otherlen) { + return false; + } + + return aComparator(cself, cother, selflen) == 0; +} + +bool +nsAString::EqualsLiteral(const char* aASCIIString) const +{ + const char16_t* begin; + const char16_t* end; + BeginReading(&begin, &end); + + for (; begin < end; ++begin, ++aASCIIString) { + if (!*aASCIIString || !NS_IsAscii(*begin) || + (char)*begin != *aASCIIString) { + return false; + } + } + + return *aASCIIString == '\0'; +} + +bool +nsAString::LowerCaseEqualsLiteral(const char* aASCIIString) const +{ + const char16_t* begin; + const char16_t* end; + BeginReading(&begin, &end); + + for (; begin < end; ++begin, ++aASCIIString) { + if (!*aASCIIString || !NS_IsAscii(*begin) || + NS_ToLower((char)*begin) != *aASCIIString) { + return false; + } + } + + return *aASCIIString == '\0'; +} + +int32_t +nsAString::Find(const self_type& aStr, uint32_t aOffset, + ComparatorFunc aComparator) const +{ + const char_type* begin; + const char_type* end; + uint32_t selflen = BeginReading(&begin, &end); + + if (aOffset > selflen) { + return -1; + } + + const char_type* other; + uint32_t otherlen = aStr.BeginReading(&other); + + if (otherlen > selflen - aOffset) { + return -1; + } + + // We want to stop searching otherlen characters before the end of the string + end -= otherlen; + + for (const char_type* cur = begin + aOffset; cur <= end; ++cur) { + if (!aComparator(cur, other, otherlen)) { + return cur - begin; + } + } + return -1; +} + +static bool +ns_strnmatch(const char16_t* aStr, const char* aSubstring, uint32_t aLen) +{ + for (; aLen; ++aStr, ++aSubstring, --aLen) { + if (!NS_IsAscii(*aStr)) { + return false; + } + + if ((char)*aStr != *aSubstring) { + return false; + } + } + + return true; +} + +static bool +ns_strnimatch(const char16_t* aStr, const char* aSubstring, uint32_t aLen) +{ + for (; aLen; ++aStr, ++aSubstring, --aLen) { + if (!NS_IsAscii(*aStr)) { + return false; + } + + if (NS_ToLower((char)*aStr) != NS_ToLower(*aSubstring)) { + return false; + } + } + + return true; +} + +int32_t +nsAString::Find(const char* aStr, uint32_t aOffset, bool aIgnoreCase) const +{ + bool (*match)(const char16_t*, const char*, uint32_t) = + aIgnoreCase ? ns_strnimatch : ns_strnmatch; + + const char_type* begin; + const char_type* end; + uint32_t selflen = BeginReading(&begin, &end); + + if (aOffset > selflen) { + return -1; + } + + uint32_t otherlen = strlen(aStr); + + if (otherlen > selflen - aOffset) { + return -1; + } + + // We want to stop searching otherlen characters before the end of the string + end -= otherlen; + + for (const char_type* cur = begin + aOffset; cur <= end; ++cur) { + if (match(cur, aStr, otherlen)) { + return cur - begin; + } + } + return -1; +} + +int32_t +nsAString::RFind(const self_type& aStr, int32_t aOffset, + ComparatorFunc aComparator) const +{ + const char_type* begin; + const char_type* end; + uint32_t selflen = BeginReading(&begin, &end); + + const char_type* other; + uint32_t otherlen = aStr.BeginReading(&other); + + if (selflen < otherlen) { + return -1; + } + + if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen)) { + end -= otherlen; + } else { + end = begin + aOffset; + } + + for (const char_type* cur = end; cur >= begin; --cur) { + if (!aComparator(cur, other, otherlen)) { + return cur - begin; + } + } + return -1; +} + +int32_t +nsAString::RFind(const char* aStr, int32_t aOffset, bool aIgnoreCase) const +{ + bool (*match)(const char16_t*, const char*, uint32_t) = + aIgnoreCase ? ns_strnimatch : ns_strnmatch; + + const char_type* begin; + const char_type* end; + uint32_t selflen = BeginReading(&begin, &end); + uint32_t otherlen = strlen(aStr); + + if (selflen < otherlen) { + return -1; + } + + if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen)) { + end -= otherlen; + } else { + end = begin + aOffset; + } + + for (const char_type* cur = end; cur >= begin; --cur) { + if (match(cur, aStr, otherlen)) { + return cur - begin; + } + } + return -1; +} + +int32_t +nsAString::FindChar(char_type aChar, uint32_t aOffset) const +{ + const char_type* start; + const char_type* end; + uint32_t len = BeginReading(&start, &end); + if (aOffset > len) { + return -1; + } + + const char_type* cur; + + for (cur = start + aOffset; cur < end; ++cur) { + if (*cur == aChar) { + return cur - start; + } + } + + return -1; +} + +int32_t +nsAString::RFindChar(char_type aChar) const +{ + const char16_t* start; + const char16_t* end; + BeginReading(&start, &end); + + do { + --end; + + if (*end == aChar) { + return end - start; + } + + } while (end >= start); + + return -1; +} + +void +nsAString::AppendInt(int aInt, int32_t aRadix) +{ + const char* fmt; + switch (aRadix) { + case 8: + fmt = "%o"; + break; + + case 10: + fmt = "%d"; + break; + + case 16: + fmt = "%x"; + break; + + default: + NS_ERROR("Unrecognized radix"); + fmt = ""; + } + + char buf[20]; + int len = SprintfLiteral(buf, fmt, aInt); + Append(NS_ConvertASCIItoUTF16(buf, len)); +} + +// Strings + +#ifndef XPCOM_GLUE_AVOID_NSPR +int32_t +nsAString::ToInteger(nsresult* aErrorCode, uint32_t aRadix) const +{ + NS_ConvertUTF16toUTF8 narrow(*this); + + const char* fmt; + switch (aRadix) { + case 10: + fmt = "%i"; + break; + + case 16: + fmt = "%x"; + break; + + default: + NS_ERROR("Unrecognized radix!"); + *aErrorCode = NS_ERROR_INVALID_ARG; + return 0; + } + + int32_t result = 0; + if (PR_sscanf(narrow.get(), fmt, &result) == 1) { + *aErrorCode = NS_OK; + } else { + *aErrorCode = NS_ERROR_FAILURE; + } + + return result; +} + +int64_t +nsAString::ToInteger64(nsresult* aErrorCode, uint32_t aRadix) const +{ + NS_ConvertUTF16toUTF8 narrow(*this); + + const char* fmt; + switch (aRadix) { + case 10: + fmt = "%lli"; + break; + + case 16: + fmt = "%llx"; + break; + + default: + NS_ERROR("Unrecognized radix!"); + *aErrorCode = NS_ERROR_INVALID_ARG; + return 0; + } + + int64_t result = 0; + if (PR_sscanf(narrow.get(), fmt, &result) == 1) { + *aErrorCode = NS_OK; + } else { + *aErrorCode = NS_ERROR_FAILURE; + } + + return result; +} +#endif // XPCOM_GLUE_AVOID_NSPR + +// nsACString + +uint32_t +nsACString::BeginReading(const char_type** aBegin, const char_type** aEnd) const +{ + uint32_t len = NS_CStringGetData(*this, aBegin); + if (aEnd) { + *aEnd = *aBegin + len; + } + + return len; +} + +const nsACString::char_type* +nsACString::BeginReading() const +{ + const char_type* data; + NS_CStringGetData(*this, &data); + return data; +} + +const nsACString::char_type* +nsACString::EndReading() const +{ + const char_type* data; + uint32_t len = NS_CStringGetData(*this, &data); + return data + len; +} + +uint32_t +nsACString::BeginWriting(char_type** aBegin, char_type** aEnd, + uint32_t aNewSize) +{ + uint32_t len = NS_CStringGetMutableData(*this, aNewSize, aBegin); + if (aEnd) { + *aEnd = *aBegin + len; + } + + return len; +} + +nsACString::char_type* +nsACString::BeginWriting(uint32_t aLen) +{ + char_type* data; + NS_CStringGetMutableData(*this, aLen, &data); + return data; +} + +nsACString::char_type* +nsACString::EndWriting() +{ + char_type* data; + uint32_t len = NS_CStringGetMutableData(*this, UINT32_MAX, &data); + return data + len; +} + +bool +nsACString::SetLength(uint32_t aLen) +{ + char_type* data; + NS_CStringGetMutableData(*this, aLen, &data); + return data != nullptr; +} + +void +nsACString::StripChars(const char* aSet) +{ + nsCString copy(*this); + + const char_type* source; + const char_type* sourceEnd; + copy.BeginReading(&source, &sourceEnd); + + char_type* dest; + BeginWriting(&dest); + if (!dest) { + return; + } + + char_type* curDest = dest; + + for (; source < sourceEnd; ++source) { + const char* test; + for (test = aSet; *test; ++test) { + if (*source == char_type(*test)) { + break; + } + } + + if (!*test) { + // not stripped, copy this char + *curDest = *source; + ++curDest; + } + } + + SetLength(curDest - dest); +} + +void +nsACString::Trim(const char* aSet, bool aLeading, bool aTrailing) +{ + NS_ASSERTION(aLeading || aTrailing, "Ineffective Trim"); + + const char* start; + const char* end; + uint32_t cutLen; + + if (aLeading) { + BeginReading(&start, &end); + for (cutLen = 0; start < end; ++start, ++cutLen) { + const char* test; + for (test = aSet; *test; ++test) { + if (*test == *start) { + break; + } + } + if (!*test) { + break; + } + } + if (cutLen) { + NS_CStringCutData(*this, 0, cutLen); + } + } + if (aTrailing) { + uint32_t len = BeginReading(&start, &end); + --end; + for (cutLen = 0; end >= start; --end, ++cutLen) { + const char* test; + for (test = aSet; *test; ++test) { + if (*test == *end) { + break; + } + } + if (!*test) { + break; + } + } + if (cutLen) { + NS_CStringCutData(*this, len - cutLen, cutLen); + } + } +} + +int32_t +nsACString::DefaultComparator(const char_type* aStrA, const char_type* aStrB, + uint32_t aLen) +{ + return memcmp(aStrA, aStrB, aLen); +} + +int32_t +nsACString::Compare(const char_type* aOther, ComparatorFunc aComparator) const +{ + const char_type* cself; + uint32_t selflen = NS_CStringGetData(*this, &cself); + uint32_t otherlen = strlen(aOther); + uint32_t comparelen = selflen <= otherlen ? selflen : otherlen; + + int32_t result = aComparator(cself, aOther, comparelen); + if (result == 0) { + if (selflen < otherlen) { + return -1; + } else if (selflen > otherlen) { + return 1; + } + } + return result; +} + +int32_t +nsACString::Compare(const self_type& aOther, ComparatorFunc aComparator) const +{ + const char_type* cself; + const char_type* cother; + uint32_t selflen = NS_CStringGetData(*this, &cself); + uint32_t otherlen = NS_CStringGetData(aOther, &cother); + uint32_t comparelen = selflen <= otherlen ? selflen : otherlen; + + int32_t result = aComparator(cself, cother, comparelen); + if (result == 0) { + if (selflen < otherlen) { + return -1; + } else if (selflen > otherlen) { + return 1; + } + } + return result; +} + +bool +nsACString::Equals(const char_type* aOther, ComparatorFunc aComparator) const +{ + const char_type* cself; + uint32_t selflen = NS_CStringGetData(*this, &cself); + uint32_t otherlen = strlen(aOther); + + if (selflen != otherlen) { + return false; + } + + return aComparator(cself, aOther, selflen) == 0; +} + +bool +nsACString::Equals(const self_type& aOther, ComparatorFunc aComparator) const +{ + const char_type* cself; + const char_type* cother; + uint32_t selflen = NS_CStringGetData(*this, &cself); + uint32_t otherlen = NS_CStringGetData(aOther, &cother); + + if (selflen != otherlen) { + return false; + } + + return aComparator(cself, cother, selflen) == 0; +} + +int32_t +nsACString::Find(const self_type& aStr, uint32_t aOffset, + ComparatorFunc aComparator) const +{ + const char_type* begin; + const char_type* end; + uint32_t selflen = BeginReading(&begin, &end); + + if (aOffset > selflen) { + return -1; + } + + const char_type* other; + uint32_t otherlen = aStr.BeginReading(&other); + + if (otherlen > selflen - aOffset) { + return -1; + } + + // We want to stop searching otherlen characters before the end of the string + end -= otherlen; + + for (const char_type* cur = begin + aOffset; cur <= end; ++cur) { + if (!aComparator(cur, other, otherlen)) { + return cur - begin; + } + } + return -1; +} + +int32_t +nsACString::Find(const char_type* aStr, ComparatorFunc aComparator) const +{ + return Find(aStr, strlen(aStr), aComparator); +} + +int32_t +nsACString::Find(const char_type* aStr, uint32_t aLen, + ComparatorFunc aComparator) const +{ + const char_type* begin; + const char_type* end; + uint32_t selflen = BeginReading(&begin, &end); + + if (aLen == 0) { + NS_WARNING("Searching for zero-length string."); + return -1; + } + + if (aLen > selflen) { + return -1; + } + + // We want to stop searching otherlen characters before the end of the string + end -= aLen; + + for (const char_type* cur = begin; cur <= end; ++cur) { + if (!aComparator(cur, aStr, aLen)) { + return cur - begin; + } + } + return -1; +} + +int32_t +nsACString::RFind(const self_type& aStr, int32_t aOffset, + ComparatorFunc aComparator) const +{ + const char_type* begin; + const char_type* end; + uint32_t selflen = BeginReading(&begin, &end); + + const char_type* other; + uint32_t otherlen = aStr.BeginReading(&other); + + if (selflen < otherlen) { + return -1; + } + + if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen)) { + end -= otherlen; + } else { + end = begin + aOffset; + } + + for (const char_type* cur = end; cur >= begin; --cur) { + if (!aComparator(cur, other, otherlen)) { + return cur - begin; + } + } + return -1; +} + +int32_t +nsACString::RFind(const char_type* aStr, ComparatorFunc aComparator) const +{ + return RFind(aStr, strlen(aStr), aComparator); +} + +int32_t +nsACString::RFind(const char_type* aStr, int32_t aLen, + ComparatorFunc aComparator) const +{ + const char_type* begin; + const char_type* end; + uint32_t selflen = BeginReading(&begin, &end); + + if (aLen <= 0) { + NS_WARNING("Searching for zero-length string."); + return -1; + } + + if (uint32_t(aLen) > selflen) { + return -1; + } + + // We want to start searching otherlen characters before the end of the string + end -= aLen; + + for (const char_type* cur = end; cur >= begin; --cur) { + if (!aComparator(cur, aStr, aLen)) { + return cur - begin; + } + } + return -1; +} + +int32_t +nsACString::FindChar(char_type aChar, uint32_t aOffset) const +{ + const char_type* start; + const char_type* end; + uint32_t len = BeginReading(&start, &end); + if (aOffset > len) { + return -1; + } + + const char_type* cur; + + for (cur = start + aOffset; cur < end; ++cur) { + if (*cur == aChar) { + return cur - start; + } + } + + return -1; +} + +int32_t +nsACString::RFindChar(char_type aChar) const +{ + const char* start; + const char* end; + BeginReading(&start, &end); + + for (; end >= start; --end) { + if (*end == aChar) { + return end - start; + } + } + + return -1; +} + +void +nsACString::AppendInt(int aInt, int32_t aRadix) +{ + const char* fmt; + switch (aRadix) { + case 8: + fmt = "%o"; + break; + + case 10: + fmt = "%d"; + break; + + case 16: + fmt = "%x"; + break; + + default: + NS_ERROR("Unrecognized radix"); + fmt = ""; + } + + char buf[20]; + int len = SprintfLiteral(buf, fmt, aInt); + Append(buf, len); +} + +#ifndef XPCOM_GLUE_AVOID_NSPR +int32_t +nsACString::ToInteger(nsresult* aErrorCode, uint32_t aRadix) const +{ + const char* fmt; + switch (aRadix) { + case 10: + fmt = "%i"; + break; + + case 16: + fmt = "%x"; + break; + + default: + NS_ERROR("Unrecognized radix!"); + *aErrorCode = NS_ERROR_INVALID_ARG; + return 0; + } + + int32_t result = 0; + if (PR_sscanf(nsCString(*this).get(), fmt, &result) == 1) { + *aErrorCode = NS_OK; + } else { + *aErrorCode = NS_ERROR_FAILURE; + } + + return result; +} + +int64_t +nsACString::ToInteger64(nsresult* aErrorCode, uint32_t aRadix) const +{ + const char* fmt; + switch (aRadix) { + case 10: + fmt = "%lli"; + break; + + case 16: + fmt = "%llx"; + break; + + default: + NS_ERROR("Unrecognized radix!"); + *aErrorCode = NS_ERROR_INVALID_ARG; + return 0; + } + + int64_t result = 0; + if (PR_sscanf(nsCString(*this).get(), fmt, &result) == 1) { + *aErrorCode = NS_OK; + } else { + *aErrorCode = NS_ERROR_FAILURE; + } + + return result; +} +#endif // XPCOM_GLUE_AVOID_NSPR + +// Substrings + +nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr, + uint32_t aStartPos) +{ + const char16_t* data; + uint32_t len = NS_StringGetData(aStr, &data); + + if (aStartPos > len) { + aStartPos = len; + } + + NS_StringContainerInit2(*this, data + aStartPos, len - aStartPos, + NS_STRING_CONTAINER_INIT_DEPEND | + NS_STRING_CONTAINER_INIT_SUBSTRING); +} + +nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr, + uint32_t aStartPos, + uint32_t aLength) +{ + const char16_t* data; + uint32_t len = NS_StringGetData(aStr, &data); + + if (aStartPos > len) { + aStartPos = len; + } + + if (aStartPos + aLength > len) { + aLength = len - aStartPos; + } + + NS_StringContainerInit2(*this, data + aStartPos, aLength, + NS_STRING_CONTAINER_INIT_DEPEND | + NS_STRING_CONTAINER_INIT_SUBSTRING); +} + +nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr, + uint32_t aStartPos) +{ + const char* data; + uint32_t len = NS_CStringGetData(aStr, &data); + + if (aStartPos > len) { + aStartPos = len; + } + + NS_CStringContainerInit2(*this, data + aStartPos, len - aStartPos, + NS_CSTRING_CONTAINER_INIT_DEPEND | + NS_CSTRING_CONTAINER_INIT_SUBSTRING); +} + +nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr, + uint32_t aStartPos, + uint32_t aLength) +{ + const char* data; + uint32_t len = NS_CStringGetData(aStr, &data); + + if (aStartPos > len) { + aStartPos = len; + } + + if (aStartPos + aLength > len) { + aLength = len - aStartPos; + } + + NS_CStringContainerInit2(*this, data + aStartPos, aLength, + NS_CSTRING_CONTAINER_INIT_DEPEND | + NS_CSTRING_CONTAINER_INIT_SUBSTRING); +} + +// Utils + +char* +ToNewUTF8String(const nsAString& aSource) +{ + nsCString temp; + CopyUTF16toUTF8(aSource, temp); + return NS_CStringCloneData(temp); +} + +void +CompressWhitespace(nsAString& aString) +{ + char16_t* start; + uint32_t len = NS_StringGetMutableData(aString, UINT32_MAX, &start); + char16_t* end = start + len; + char16_t* from = start; + char16_t* to = start; + + // Skip any leading whitespace + while (from < end && NS_IsAsciiWhitespace(*from)) { + from++; + } + + while (from < end) { + char16_t theChar = *from++; + + if (NS_IsAsciiWhitespace(theChar)) { + // We found a whitespace char, so skip over any more + while (from < end && NS_IsAsciiWhitespace(*from)) { + from++; + } + + // Turn all whitespace into spaces + theChar = ' '; + } + + *to++ = theChar; + } + + // Drop any trailing space + if (to > start && to[-1] == ' ') { + to--; + } + + // Re-terminate the string + *to = '\0'; + + // Set the new length + aString.SetLength(to - start); +} + +uint32_t +ToLowerCase(nsACString& aStr) +{ + char* begin; + char* end; + uint32_t len = aStr.BeginWriting(&begin, &end); + + for (; begin < end; ++begin) { + *begin = NS_ToLower(*begin); + } + + return len; +} + +uint32_t +ToUpperCase(nsACString& aStr) +{ + char* begin; + char* end; + uint32_t len = aStr.BeginWriting(&begin, &end); + + for (; begin < end; ++begin) { + *begin = NS_ToUpper(*begin); + } + + return len; +} + +uint32_t +ToLowerCase(const nsACString& aSrc, nsACString& aDest) +{ + const char* begin; + const char* end; + uint32_t len = aSrc.BeginReading(&begin, &end); + + char* dest; + NS_CStringGetMutableData(aDest, len, &dest); + + for (; begin < end; ++begin, ++dest) { + *dest = NS_ToLower(*begin); + } + + return len; +} + +uint32_t +ToUpperCase(const nsACString& aSrc, nsACString& aDest) +{ + const char* begin; + const char* end; + uint32_t len = aSrc.BeginReading(&begin, &end); + + char* dest; + NS_CStringGetMutableData(aDest, len, &dest); + + for (; begin < end; ++begin, ++dest) { + *dest = NS_ToUpper(*begin); + } + + return len; +} + +int32_t +CaseInsensitiveCompare(const char* aStrA, const char* aStrB, + uint32_t aLen) +{ + for (const char* aend = aStrA + aLen; aStrA < aend; ++aStrA, ++aStrB) { + char la = NS_ToLower(*aStrA); + char lb = NS_ToLower(*aStrB); + + if (la == lb) { + continue; + } + + return la < lb ? -1 : 1; + } + + return 0; +} + +bool +ParseString(const nsACString& aSource, char aDelimiter, + nsTArray<nsCString>& aArray) +{ + int32_t start = 0; + int32_t end = aSource.Length(); + + uint32_t oldLength = aArray.Length(); + + for (;;) { + int32_t delimiter = aSource.FindChar(aDelimiter, start); + if (delimiter < 0) { + delimiter = end; + } + + if (delimiter != start) { + if (!aArray.AppendElement(Substring(aSource, start, delimiter - start))) { + aArray.RemoveElementsAt(oldLength, aArray.Length() - oldLength); + return false; + } + } + + if (delimiter == end) { + break; + } + start = ++delimiter; + if (start == end) { + break; + } + } + + return true; +} |