Bug 1344629 - Part 3: Move const accessors from nsTSubstring to nsTStringRepr. r=dbaron

All nsTStringRepr methods must be const, so the mutators remain on nsTSubstring.

I left a small number of const methods on nsTSubstring, e.g. Capacity(), the rationale being that you would only be interested in this method if you intend to mutate the string.

I considered splitting up the typedefs block and leaving behind the ones related to mutation (e.g. nsWritingIterator) but I think it makes for clearer documentation to have them all in one place.

MozReview-Commit-ID: 7dEaRgc8NLK

--HG--
extra : rebase_source : 01b387b7e5bf2f21d6af1afcccf6ec0d7e8a2ac7
This commit is contained in:
David Major 2017-03-14 10:02:50 +13:00
parent fc4fab5ae2
commit b7e6bde277
4 changed files with 239 additions and 226 deletions

View File

@ -15,6 +15,15 @@
#error Internal string headers are not available from external-linkage code.
#endif
namespace mozilla {
namespace detail {
class nsStringRepr;
class nsCStringRepr;
} // namespace detail
} // namespace mozilla
/**
* double-byte (char16_t) string types
*/

View File

@ -27,8 +27,8 @@ public:
typedef const CharT& reference;
private:
friend class nsAString;
friend class nsACString;
friend class mozilla::detail::nsStringRepr;
friend class mozilla::detail::nsCStringRepr;
// unfortunately, the API for nsReadingIterator requires that the
// iterator know its start and end positions. this was needed when

View File

@ -32,21 +32,6 @@ AsFixedString(const nsTSubstring_CharT* aStr)
return static_cast<const nsTFixedString_CharT*>(aStr);
}
nsTSubstring_CharT::char_type
nsTSubstring_CharT::First() const
{
MOZ_RELEASE_ASSERT(mLength > 0, "|First()| called on an empty string");
return mData[0];
}
nsTSubstring_CharT::char_type
nsTSubstring_CharT::Last() const
{
MOZ_RELEASE_ASSERT(mLength > 0, "|Last()| called on an empty string");
return mData[mLength - 1];
}
/**
* this function is called to prepare mData for writing. the given capacity
* indicates the required minimum storage size for mData, in sizeof(char_type)
@ -762,23 +747,40 @@ nsTSubstring_CharT::SetIsVoid(bool aVal)
}
}
namespace mozilla {
namespace detail {
nsTStringRepr_CharT::char_type
nsTStringRepr_CharT::First() const
{
MOZ_RELEASE_ASSERT(mLength > 0, "|First()| called on an empty string");
return mData[0];
}
nsTStringRepr_CharT::char_type
nsTStringRepr_CharT::Last() const
{
MOZ_RELEASE_ASSERT(mLength > 0, "|Last()| called on an empty string");
return mData[mLength - 1];
}
bool
nsTSubstring_CharT::Equals(const self_type& aStr) const
nsTStringRepr_CharT::Equals(const self_type& aStr) const
{
return mLength == aStr.mLength &&
char_traits::compare(mData, aStr.mData, mLength) == 0;
}
bool
nsTSubstring_CharT::Equals(const self_type& aStr,
const comparator_type& aComp) const
nsTStringRepr_CharT::Equals(const self_type& aStr,
const comparator_type& aComp) const
{
return mLength == aStr.mLength &&
aComp(mData, aStr.mData, mLength, aStr.mLength) == 0;
}
bool
nsTSubstring_CharT::Equals(const char_type* aData) const
nsTStringRepr_CharT::Equals(const char_type* aData) const
{
// unfortunately, some callers pass null :-(
if (!aData) {
@ -793,8 +795,8 @@ nsTSubstring_CharT::Equals(const char_type* aData) const
}
bool
nsTSubstring_CharT::Equals(const char_type* aData,
const comparator_type& aComp) const
nsTStringRepr_CharT::Equals(const char_type* aData,
const comparator_type& aComp) const
{
// unfortunately, some callers pass null :-(
if (!aData) {
@ -808,36 +810,36 @@ nsTSubstring_CharT::Equals(const char_type* aData,
}
bool
nsTSubstring_CharT::EqualsASCII(const char* aData, size_type aLen) const
nsTStringRepr_CharT::EqualsASCII(const char* aData, size_type aLen) const
{
return mLength == aLen &&
char_traits::compareASCII(mData, aData, aLen) == 0;
}
bool
nsTSubstring_CharT::EqualsASCII(const char* aData) const
nsTStringRepr_CharT::EqualsASCII(const char* aData) const
{
return char_traits::compareASCIINullTerminated(mData, mLength, aData) == 0;
}
bool
nsTSubstring_CharT::LowerCaseEqualsASCII(const char* aData,
size_type aLen) const
nsTStringRepr_CharT::LowerCaseEqualsASCII(const char* aData,
size_type aLen) const
{
return mLength == aLen &&
char_traits::compareLowerCaseToASCII(mData, aData, aLen) == 0;
}
bool
nsTSubstring_CharT::LowerCaseEqualsASCII(const char* aData) const
nsTStringRepr_CharT::LowerCaseEqualsASCII(const char* aData) const
{
return char_traits::compareLowerCaseToASCIINullTerminated(mData,
mLength,
aData) == 0;
}
nsTSubstring_CharT::size_type
nsTSubstring_CharT::CountChar(char_type aChar) const
nsTStringRepr_CharT::size_type
nsTStringRepr_CharT::CountChar(char_type aChar) const
{
const char_type* start = mData;
const char_type* end = mData + mLength;
@ -846,7 +848,7 @@ nsTSubstring_CharT::CountChar(char_type aChar) const
}
int32_t
nsTSubstring_CharT::FindChar(char_type aChar, index_type aOffset) const
nsTStringRepr_CharT::FindChar(char_type aChar, index_type aOffset) const
{
if (aOffset < mLength) {
const char_type* result = char_traits::find(mData + aOffset,
@ -858,6 +860,9 @@ nsTSubstring_CharT::FindChar(char_type aChar, index_type aOffset) const
return -1;
}
} // namespace detail
} // namespace mozilla
void
nsTSubstring_CharT::StripChar(char_type aChar, int32_t aOffset)
{

View File

@ -72,54 +72,18 @@ namespace detail {
*/
class nsTStringRepr_CharT
{
public:
typedef CharT char_type;
typedef uint32_t size_type;
protected:
nsTStringRepr_CharT() = delete; // Never instantiate directly
constexpr
nsTStringRepr_CharT(char_type* aData, size_type aLength, uint32_t aFlags)
: mData(aData)
, mLength(aLength)
, mFlags(aFlags)
{
}
char_type* mData;
size_type mLength;
uint32_t mFlags;
};
} // namespace detail
} // namespace mozilla
/**
* nsTSubstring is an abstract string class. From an API perspective, this
* class is the root of the string class hierarchy. It represents a single
* contiguous array of characters, which may or may not be null-terminated.
* This type is not instantiated directly. A sub-class is instantiated
* instead. For example, see nsTString.
*
* NAMES:
* nsAString for wide characters
* nsACString for narrow characters
*
*/
class nsTSubstring_CharT : public mozilla::detail::nsTStringRepr_CharT
{
public:
typedef mozilla::fallible_t fallible_t;
typedef CharT char_type;
typedef nsCharTraits<char_type> char_traits;
typedef char_traits::incompatible_char_type incompatible_char_type;
typedef nsTSubstring_CharT self_type;
typedef nsTStringRepr_CharT self_type;
typedef self_type base_string_type;
typedef self_type substring_type;
typedef nsTSubstring_CharT substring_type;
typedef nsTSubstringTuple_CharT substring_tuple_type;
typedef nsTString_CharT string_type;
@ -132,14 +96,7 @@ public:
typedef const char_type* const_char_iterator;
typedef uint32_t index_type;
public:
// this acts like a virtual destructor
~nsTSubstring_CharT()
{
Finalize();
}
typedef uint32_t size_type;
/**
* reading iterators
@ -184,81 +141,6 @@ public:
return aIter = mData + mLength;
}
/**
* writing iterators
*/
char_iterator BeginWriting()
{
if (!EnsureMutable()) {
AllocFailed(mLength);
}
return mData;
}
char_iterator BeginWriting(const fallible_t&)
{
return EnsureMutable() ? mData : char_iterator(0);
}
char_iterator EndWriting()
{
if (!EnsureMutable()) {
AllocFailed(mLength);
}
return mData + mLength;
}
char_iterator EndWriting(const fallible_t&)
{
return EnsureMutable() ? (mData + mLength) : char_iterator(0);
}
char_iterator& BeginWriting(char_iterator& aIter)
{
return aIter = BeginWriting();
}
char_iterator& BeginWriting(char_iterator& aIter, const fallible_t& aFallible)
{
return aIter = BeginWriting(aFallible);
}
char_iterator& EndWriting(char_iterator& aIter)
{
return aIter = EndWriting();
}
char_iterator& EndWriting(char_iterator& aIter, const fallible_t& aFallible)
{
return aIter = EndWriting(aFallible);
}
/**
* deprecated writing iterators
*/
iterator& BeginWriting(iterator& aIter)
{
char_type* data = BeginWriting();
aIter.mStart = data;
aIter.mEnd = data + mLength;
aIter.mPosition = aIter.mStart;
return aIter;
}
iterator& EndWriting(iterator& aIter)
{
char_type* data = BeginWriting();
aIter.mStart = data;
aIter.mEnd = data + mLength;
aIter.mPosition = aIter.mEnd;
return aIter;
}
/**
* accessors
*/
@ -394,6 +276,195 @@ public:
return LowerCaseEqualsASCII(aStr, N - 1);
}
/**
* returns true if this string overlaps with the given string fragment.
*/
bool IsDependentOn(const char_type* aStart, const char_type* aEnd) const
{
/**
* if it _isn't_ the case that one fragment starts after the other ends,
* or ends before the other starts, then, they conflict:
*
* !(f2.begin >= f1.aEnd || f2.aEnd <= f1.begin)
*
* Simplified, that gives us:
*/
return (aStart < (mData + mLength) && aEnd > mData);
}
protected:
nsTStringRepr_CharT() = delete; // Never instantiate directly
constexpr
nsTStringRepr_CharT(char_type* aData, size_type aLength, uint32_t aFlags)
: mData(aData)
, mLength(aLength)
, mFlags(aFlags)
{
}
char_type* mData;
size_type mLength;
uint32_t mFlags;
public:
// mFlags is a bitwise combination of the following flags. the meaning
// and interpretation of these flags is an implementation detail.
//
// NOTE: these flags are declared public _only_ for convenience inside
// the string implementation.
enum
{
F_NONE = 0, // no flags
// data flags are in the lower 16-bits
F_TERMINATED = 1 << 0, // IsTerminated returns true
F_VOIDED = 1 << 1, // IsVoid returns true
F_SHARED = 1 << 2, // mData points to a heap-allocated, shared buffer
F_OWNED = 1 << 3, // mData points to a heap-allocated, raw buffer
F_FIXED = 1 << 4, // mData points to a fixed-size writable, dependent buffer
F_LITERAL = 1 << 5, // mData points to a string literal; F_TERMINATED will also be set
// class flags are in the upper 16-bits
F_CLASS_FIXED = 1 << 16 // indicates that |this| is of type nsTFixedString
};
//
// Some terminology:
//
// "dependent buffer" A dependent buffer is one that the string class
// does not own. The string class relies on some
// external code to ensure the lifetime of the
// dependent buffer.
//
// "shared buffer" A shared buffer is one that the string class
// allocates. When it allocates a shared string
// buffer, it allocates some additional space at
// the beginning of the buffer for additional
// fields, including a reference count and a
// buffer length. See nsStringHeader.
//
// "adopted buffer" An adopted buffer is a raw string buffer
// allocated on the heap (using moz_xmalloc)
// of which the string class subsumes ownership.
//
// Some comments about the string flags:
//
// F_SHARED, F_OWNED, and F_FIXED are all mutually exlusive. They
// indicate the allocation type of mData. If none of these flags
// are set, then the string buffer is dependent.
//
// F_SHARED, F_OWNED, or F_FIXED imply F_TERMINATED. This is because
// the string classes always allocate null-terminated buffers, and
// non-terminated substrings are always dependent.
//
// F_VOIDED implies F_TERMINATED, and moreover it implies that mData
// points to char_traits::sEmptyBuffer. Therefore, F_VOIDED is
// mutually exclusive with F_SHARED, F_OWNED, and F_FIXED.
//
};
} // namespace detail
} // namespace mozilla
/**
* nsTSubstring is an abstract string class. From an API perspective, this
* class is the root of the string class hierarchy. It represents a single
* contiguous array of characters, which may or may not be null-terminated.
* This type is not instantiated directly. A sub-class is instantiated
* instead. For example, see nsTString.
*
* NAMES:
* nsAString for wide characters
* nsACString for narrow characters
*
*/
class nsTSubstring_CharT : public mozilla::detail::nsTStringRepr_CharT
{
public:
typedef nsTSubstring_CharT self_type;
// this acts like a virtual destructor
~nsTSubstring_CharT()
{
Finalize();
}
/**
* writing iterators
*/
char_iterator BeginWriting()
{
if (!EnsureMutable()) {
AllocFailed(mLength);
}
return mData;
}
char_iterator BeginWriting(const fallible_t&)
{
return EnsureMutable() ? mData : char_iterator(0);
}
char_iterator EndWriting()
{
if (!EnsureMutable()) {
AllocFailed(mLength);
}
return mData + mLength;
}
char_iterator EndWriting(const fallible_t&)
{
return EnsureMutable() ? (mData + mLength) : char_iterator(0);
}
char_iterator& BeginWriting(char_iterator& aIter)
{
return aIter = BeginWriting();
}
char_iterator& BeginWriting(char_iterator& aIter, const fallible_t& aFallible)
{
return aIter = BeginWriting(aFallible);
}
char_iterator& EndWriting(char_iterator& aIter)
{
return aIter = EndWriting();
}
char_iterator& EndWriting(char_iterator& aIter, const fallible_t& aFallible)
{
return aIter = EndWriting(aFallible);
}
/**
* deprecated writing iterators
*/
iterator& BeginWriting(iterator& aIter)
{
char_type* data = BeginWriting();
aIter.mStart = data;
aIter.mEnd = data + mLength;
aIter.mPosition = aIter.mStart;
return aIter;
}
iterator& EndWriting(iterator& aIter)
{
char_type* data = BeginWriting();
aIter.mStart = data;
aIter.mEnd = data + mLength;
aIter.mPosition = aIter.mEnd;
return aIter;
}
/**
* assignment
*/
@ -1035,22 +1106,6 @@ protected:
MOZ_MUST_USE bool NS_FASTCALL EnsureMutable(
size_type aNewLen = size_type(-1));
/**
* returns true if this string overlaps with the given string fragment.
*/
bool IsDependentOn(const char_type* aStart, const char_type* aEnd) const
{
/**
* if it _isn't_ the case that one fragment starts after the other ends,
* or ends before the other starts, then, they conflict:
*
* !(f2.begin >= f1.aEnd || f2.aEnd <= f1.begin)
*
* Simplified, that gives us:
*/
return (aStart < (mData + mLength) && aEnd > mData);
}
/**
* this helper function stores the specified dataFlags in mFlags
*/
@ -1068,62 +1123,6 @@ public:
// NOTE: this method is declared public _only_ for convenience for
// callers who don't have access to the original nsLiteralString_CharT.
void NS_FASTCALL AssignLiteral(const char_type* aData, size_type aLength);
// mFlags is a bitwise combination of the following flags. the meaning
// and interpretation of these flags is an implementation detail.
//
// NOTE: these flags are declared public _only_ for convenience inside
// the string implementation.
enum
{
F_NONE = 0, // no flags
// data flags are in the lower 16-bits
F_TERMINATED = 1 << 0, // IsTerminated returns true
F_VOIDED = 1 << 1, // IsVoid returns true
F_SHARED = 1 << 2, // mData points to a heap-allocated, shared buffer
F_OWNED = 1 << 3, // mData points to a heap-allocated, raw buffer
F_FIXED = 1 << 4, // mData points to a fixed-size writable, dependent buffer
F_LITERAL = 1 << 5, // mData points to a string literal; F_TERMINATED will also be set
// class flags are in the upper 16-bits
F_CLASS_FIXED = 1 << 16 // indicates that |this| is of type nsTFixedString
};
//
// Some terminology:
//
// "dependent buffer" A dependent buffer is one that the string class
// does not own. The string class relies on some
// external code to ensure the lifetime of the
// dependent buffer.
//
// "shared buffer" A shared buffer is one that the string class
// allocates. When it allocates a shared string
// buffer, it allocates some additional space at
// the beginning of the buffer for additional
// fields, including a reference count and a
// buffer length. See nsStringHeader.
//
// "adopted buffer" An adopted buffer is a raw string buffer
// allocated on the heap (using moz_xmalloc)
// of which the string class subsumes ownership.
//
// Some comments about the string flags:
//
// F_SHARED, F_OWNED, and F_FIXED are all mutually exlusive. They
// indicate the allocation type of mData. If none of these flags
// are set, then the string buffer is dependent.
//
// F_SHARED, F_OWNED, or F_FIXED imply F_TERMINATED. This is because
// the string classes always allocate null-terminated buffers, and
// non-terminated substrings are always dependent.
//
// F_VOIDED implies F_TERMINATED, and moreover it implies that mData
// points to char_traits::sEmptyBuffer. Therefore, F_VOIDED is
// mutually exclusive with F_SHARED, F_OWNED, and F_FIXED.
//
};
static_assert(sizeof(nsTSubstring_CharT) ==