mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
729a46113b
- Bug 1159056. Don't store a value in CSS pixels in a variable with type nscoord in ScrollFrameHelper::SetCoordAttribute. r=dholbert (432f06158) - Bug 1138442 - Disable reftests on Mulet in parity with B2G/B2G Desktop. r=ahal (8b5c55da7) - Don't clip in ComputeFrameMetrics if the scrollframe won't be layerized. (bug 1148582 part 2, r=tn) (088b6ef29) - Bug 1157579 - Make sure the visual scroll port size includes the area of scrollbars when used in TryLayout. r=tn (c35244374) - Bug 1139306: Fix margin sides for right-to-left scrollbars depending on the actual position of the scrollbar as determined by layout.scrollbar.side, r=tn (34328312d) - Fix some full zoom FrameMetrics changes not propagating to APZ. (bug 1147648, r=botond) (91f009ac4) - Bug 1159405 - Fix "Found a non-root APZ with no handoff parent". r=botond (09b0ddf07) - Bug 1161040 - Don't set a scrollparent on the root content document in the child process that points to itself. r=tn (d0dfbffb0) - Bug 1161040 - Add some assertions to guard against infinite loops in the handoff chains. r=botond (e6bae82e8) - Bug 1153539 patch 1 - Improve comments for nsLayoutUtils::ComputeSuitableScaleForAnimation. r=roc (1b2bc00cd) - Bug 1153539 patch 2 - Compute scale for rasterizing off-main-thread transform animations based on ratio to display size in addition to maximum and minimum scale. r=roc (97d632d0f) - Bug 1160250 - Extract a helper method from the triplicated comp-bounds function to determine if we need to deflate the scrollbars. r=botond,tn (8d79c845f) - Bug 1160250 - Extract a helper function from the triplicated composition-bounds-updating code. r=botond,tn (5b3f71329) - Bug 1160250 - Collapse the code from CalculateRootCompositionSize into UpdateCompositionBounds. r=botond,tn (db0f081d6) - Bug 1160250 - Put in a missing transfomToAncestor scaling factor. r=botond,tn (14837aa3a) - Bug 1160250 - Fix up the rect being used for the composition size calculation. r=tn (0ba58021f) - Bug 1139575 - Reset velocity on axes when going from a pan to a pinch. r=botond (2e03d04ab) - Bug 1136971 - Draw layer borders correctly in the presence of multi-FrameMetrics. r=kats (e72f5b171) - Bug 1148871 - Only apply checkerboarding background color to opaque layers. r=botond (20e070b84) - Bug 1157327 - Don't cull out container layers, because their prepared data might be null and cause crashes. r=nical (3d06c925f) - Bug 1157327 follow-up to add a comment. r=me and DONTBUILD (4cd74c0a1) - Bug 1160566 - Make FrameMetrics.mCompositionBounds private and add a getter/setter for it. r=botond (277dd9afd) - Bug 1160566 - Change some return values to be reference-to-const. r=botond (2ce17b63f) - Bug 1158933 - Prevent scrollbars from jumping while zoomed in the B2G browser. r=botond (eca8aae7d) - Bug 1158933 - Replace the compositedHeight/scrollableHeight (and width) term with the adjusted scrollThumbRatio. r=botond (236af4c4a) - Bug 1156401 - Fix painting when building fennec with apzc. r=kats, r=botond (be18764b9) - Bug 1159305 - patch 1 - Provide logical accessors for nsStylePosition and nsStyleSides fields. r=dbaron (7a90c519d) - Bug 1159305 - patch 2 - Clean up layout code by using the new accessors. r=smontagu (926eb7dd5) - Bug 1164406 - Expose scrollbar-area deflation in nsLayoutUtils. r=kats (42e5e8784) - Bug 1139895 - Add fuzz for 1062792-1.html. r=tn (e38d0ac73) - Bug 1139893 - Disable reftest bugs/1062108-1.html on mulet. r=jfkthame (930590d73) - Move the APZ scroll frame clip onto FrameMetrics. (bug 1148582 part 3, r=mstange,tn) (c8e05f8d7) - Fix PostprocessRetainedLayers to not test occlusion with asynchronous clips. (bug 1148582 part 5, r=tn) (cc71cafe2) - Bug 1146626 - Refresh the reftest snapshot after adjusting the async scroll offsets. r=roc (1f041955d) - Bug 1160642. Add reftest-async-zoom to apply an async zoom before taking snapshot. r=dbaron (1e8e54d8d) - Bug 1160285 - Add a staticruntime version of mfbt and link some stuff against it. r=glandium (c733c49c7) - Bug 786520 - Install things to $(DIST)/branding from moz.build instead of manual rules in Makefile.ins. r=mshal (42d38eb26) - Bug 1155776 - move USE_EXTENSION_MANIFEST to moz.build; r=mshal (a87ecc2ca) - Bug 1155816 - part 0 - remove NO_JS_MANIFEST from testing/mochitest/Makefile.in; r=mshal (af90a362c) - Bug 1155816 - part 1 - move NO_JS_MANIFEST to moz.build; r=mshal (3a55e99a0) - Bug 978591 - Remove per-directory uses of MOZ_CHROME_FILE_FORMAT. r=glandium (5084d62b5) - Bug 991983 - Set GARBAGE for GeneratedSources in the recursivemake backend. r=gps (b8ae57c14) - Bug 991983 - Emit absolute paths for UnifiedSources. r=gps (4100640d0) - Bug 991983 - Emit absolute paths for other sources. r=gps (f30ddd773) - Bug 991983 - Remove commented code in gyp_reader.py. r=gps (0685eca6a) - Bug 1167474 - Remove ELFHACK_BUILD hack. r=mshal (b9d56c0b2) - Bug 1097804 - Part 1 - Create a library containing nsISocketTransportService and nsIDNS that can be used to support standalone WebRTC. r=mcmanus (d2f83eb1c) - Bug 1097804 - Part 2 - Added xpcomrt build of library containing unicode util functions. r=gps (fa9306f34) - Bug 1162852 - Remove EXTRA_COMPILE_FLAGS. r=gps (340312bc6) - Bug 1162852 - Remove EXTRA_ASSEMBLER_FLAGS. r=gps (f124c902c) - Bug 1162852 - Remove the VARIABLES method of GypContext now it is doing nothing. r=gps (b6c1c0246) - accidental commit (a1bbb1ada) - Bug 991983 - Define SOURCES as SourcePath. r=gps (678065bce) - Bug 991983 - Use objdir-relative SOURCES instead of GENERATED_SOURCES. r=gps (b54db0304) - Bug 991983 - Make TEST_HARNESS_FILES use the *Path classes instead of a separate set of methods to resolve paths. r=gps (025fe1ca9) - Bug 991983 - Add a deprecation hint for GENERATED_SOURCES. r=gps (67c75f4ab) - Bug 1172800 - Fixup after bug 991983. r=gps (ce6e8c7a3) - Bug 1164218 - Allow running individual mochitests and reftests in chaos mode. r=roc,froydnj (f2ec1d9d8) - Bug 1154231 - Part 1. Use LRU to manage remote layers. r=mattwoodrow (1fe47e64f) - Bug 1128037 - Minimalist support for wildcards in jar manifests. r=gps (1b07a6ffc) - Bug 1162569 - default engine files should be in the omni.ja file, r=markh,glandium. (b07e54881) - Bug 1157279. Escaping CSS identifiers should use lowercase letters for hex digits, not uppercase ones. r=dbaron (6f220936e)
1313 lines
26 KiB
C++
1313 lines
26 KiB
C++
/* -*- 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 <stdio.h>
|
|
|
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
|
#define snprintf _snprintf
|
|
#endif
|
|
|
|
// 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 = snprintf(buf, sizeof(buf), fmt, aInt);
|
|
buf[sizeof(buf) - 1] = '\0';
|
|
|
|
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 = snprintf(buf, sizeof(buf), fmt, aInt);
|
|
buf[sizeof(buf) - 1] = '\0';
|
|
|
|
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;
|
|
}
|
|
|
|
#undef snprintf
|