/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is mainly intended to be used in the context of nsTStrings where // we want to enable a specific function only for a given character class. In // order for this technique to work the member function needs to be templated // on something other than `T`. We keep this in the `mozilla` namespace rather // than `nsTStringRepr` as it's intentionally not dependent on `T`. // // The 'T' at the end of `Char[16]OnlyT` is refering to the `::type` portion // which will only be defined if the character class is correct. This is similar // to `std::enable_if_t` which is available in C++14, but not C++11. // // `CharType` is generally going to be a shadowed type of `T`. // // Example usage of a function that will only be defined if `T` == `char`: // // template <typename T> // class nsTSubstring : public nsTStringRepr<T> { // template <typename Q = T, typename EnableForChar = typename CharOnlyT<Q>> // int Foo() { return 42; } // }; // // Please note that we had to use a separate type `Q` for this to work. You // will get a semi-decent compiler error if you use `T` directly.
template <typename CharType>
using CharOnlyT =
typename std::enable_if<std::is_same<char, CharType>::value>::type;
template <typename CharType>
using Char16OnlyT =
typename std::enable_if<std::is_same<char16_t, CharType>::value>::type;
namespace detail {
// nsTStringLengthStorage is a helper class which holds the string's length and // provides getters and setters for converting to and from `size_t`. This is // done to allow the length to be stored in a `uint32_t` using assertions. template <typename T> class nsTStringLengthStorage {
public: // The maximum byte capacity for a `nsTString` must fit within an `int32_t`, // with enough room for a trailing null, as consumers often cast `Length()` // and `Capacity()` to smaller types like `int32_t`. static constexpr size_t kMax =
size_t{std::numeric_limits<int32_t>::max()} / sizeof(T) - 1;
static_assert(
(kMax + 1) * sizeof(T) <= std::numeric_limits<int32_t>::max(), "nsTString's maximum length, including the trailing null, must fit " "within `int32_t`, as callers will cast to `int32_t` occasionally");
static_assert(((CheckedInt<uint32_t>{kMax} + 1) * sizeof(T) + sizeof(mozilla::StringBuffer))
.isValid(), "Math required to allocate a mozilla::StringBuffer for a " "maximum-capacity string must not overflow uint32_t");
// Implicit conversion and assignment from `size_t` which assert that the // value is in-range.
MOZ_IMPLICIT constexpr nsTStringLengthStorage(size_t aLength)
: mLength(static_cast<uint32_t>(aLength)) {
MOZ_RELEASE_ASSERT(aLength <= kMax, "string is too large");
}
constexpr nsTStringLengthStorage& operator=(size_t aLength) {
MOZ_RELEASE_ASSERT(aLength <= kMax, "string is too large");
mLength = static_cast<uint32_t>(aLength); return *this;
}
MOZ_IMPLICIT constexpr operator size_t() const { return mLength; }
private:
uint32_t mLength = 0;
};
// nsTStringRepr defines a string's memory layout and some accessor methods. // This class exists so that nsTLiteralString can avoid inheriting // nsTSubstring's destructor. All methods on this class must be const because // literal strings are not writable. // // This class is an implementation detail and should not be instantiated // directly, nor used in any way outside of the string code itself. It is // buried in a namespace to discourage its use in function parameters. // If you need to take a parameter, use [const] ns[C]Substring&. // If you need to instantiate a string, use ns[C]String or descendents. // // NAMES: // nsStringRepr for wide characters // nsCStringRepr for narrow characters template <typename T> class nsTStringRepr {
public: typedef mozilla::fallible_t fallible_t;
// These are only for internal use within the string classes: typedef StringDataFlags DataFlags; typedef StringClassFlags ClassFlags; typedef nsTStringLengthStorage<T> LengthStorage;
nsTStringRepr() = delete; // Never instantiate directly
// Reading iterators. // You must not assume the returned value is null-terminated. // If you need a null terminated string, use nsTString::get().
constexpr const_char_iterator BeginReading() const MOZ_LIFETIME_BOUND
MOZ_NON_TERMINATED_STRING { return mData;
}
constexpr const_char_iterator EndReading() const MOZ_LIFETIME_BOUND { return mData + mLength;
}
// Returns a raw pointer to the start of the string's data. // You must not assume the returned value is null-terminated. // If you need a null terminated string, use nsTString::get().
constexpr typename raw_type<T, int>::type Data() const MOZ_LIFETIME_BOUND
MOZ_NON_TERMINATED_STRING { return mData;
}
// An efficient comparison with ASCII that can be used even // for wide strings. Call this version when you know the // length of 'data'. bool NS_FASTCALL EqualsASCII(constchar* aData, size_type aLen) const; // An efficient comparison with ASCII that can be used even // for wide strings. Call this version when 'data' is // null-terminated. bool NS_FASTCALL EqualsASCII(constchar* aData) const;
// An efficient comparison with Latin1 characters that can be used even for // wide strings. bool EqualsLatin1(constchar* aData, size_type aLength) const;
// EqualsLiteral must ONLY be called with an actual literal string, or // a char array *constant* declared without an explicit size and with an // initializer that is a string literal or is otherwise null-terminated. // Use EqualsASCII for other char array variables. // (Although this method may happen to produce expected results for other // char arrays that have bound one greater than the sequence of interest, // such use is discouraged for reasons of readability and maintainability.) // The template trick to acquire the array bound at compile time without // using a macro is due to Corey Kosak, with much thanks. template <int N> inlinebool EqualsLiteral(constchar (&aStr)[N]) const { return EqualsASCII(aStr, N - 1);
}
// EqualsLiteral must ONLY be called with an actual literal string, or // a char array *constant* declared without an explicit size and with an // initializer that is a string literal or is otherwise null-terminated. // Use EqualsASCII for other char array variables. // (Although this method may happen to produce expected results for other // char arrays that have bound one greater than the sequence of interest, // such use is discouraged for reasons of readability and maintainability.) // The template trick to acquire the array bound at compile time without // using a macro is due to Corey Kosak, with much thanks. template <size_t N, typename = std::enable_if_t<!std::is_same_v< constchar (&)[N], const char_type (&)[N]>>> inlinebool EqualsLiteral(const char_type (&aStr)[N]) const { return *this == nsTLiteralString<char_type>(aStr);
}
// The LowerCaseEquals methods compare the ASCII-lowercase version of // this string (lowercasing only ASCII uppercase characters) to some // ASCII/Literal string. The ASCII string is *not* lowercased for // you. If you compare to an ASCII or literal string that contains an // uppercase character, it is guaranteed to return false. We will // throw assertions too. bool NS_FASTCALL LowerCaseEqualsASCII(constchar* aData,
size_type aLen) const; bool NS_FASTCALL LowerCaseEqualsASCII(constchar* aData) const;
// LowerCaseEqualsLiteral must ONLY be called with an actual literal string, // or a char array *constant* declared without an explicit size and with an // initializer that is a string literal or is otherwise null-terminated. // Use LowerCaseEqualsASCII for other char array variables. // (Although this method may happen to produce expected results for other // char arrays that have bound one greater than the sequence of interest, // such use is discouraged for reasons of readability and maintainability.) template <int N> bool LowerCaseEqualsLiteral(constchar (&aStr)[N]) const { 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 (To avoid relying on Undefined Behavior // from comparing pointers from different allocations (which in // principle gives the optimizer the permission to assume elsewhere // that the pointers are from the same allocation), the comparisons // are done on integers, which merely relies on implementation-defined // behavior of converting pointers to integers. std::less and // std::greater implementations don't actually provide the guarantees // that they should.): return (reinterpret_cast<uintptr_t>(aStart) <
reinterpret_cast<uintptr_t>(mData + mLength) &&
reinterpret_cast<uintptr_t>(aEnd) >
reinterpret_cast<uintptr_t>(mData));
}
// Previously there was an overload of `Find()` which took a bool second // argument. Avoid issues by explicitly preventing that overload. // TODO: Remove this at some point. template <typename I,
typename = std::enable_if_t<!std::is_same_v<I, index_type> &&
std::is_convertible_v<I, index_type>>>
int32_t Find(const string_view& aString, I aOffset) const {
static_assert(!std::is_same_v<I, bool>, "offset must not be `bool`"); return Find(aString, static_cast<index_type>(aOffset));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.