/* -*- 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/. */
// 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;
/** * Compare this string and another ASCII-case-insensitively. * * This method is similar to `LowerCaseEqualsASCII` however both strings are * lowercased, meaning that `aString` need not be all lowercase. * * @param aString is the string to check * @return boolean
*/ bool EqualsIgnoreCase(const std::string_view& aString) const;
// 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));
}
/** * Search for the given substring within this string. * * @param aString is substring to be sought in this * @param aOffset tells us where in this string to start searching * @return offset in string, or kNotFound
*/
int32_t Find(const string_view& aString, index_type aOffset = 0) const;
// 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));
}
/** * Search for the given ASCII substring within this string, ignoring case. * * @param aString is substring to be sought in this * @param aOffset tells us where in this string to start searching * @return offset in string, or kNotFound
*/
int32_t LowerCaseFindASCII(const std::string_view& aString,
index_type aOffset = 0) const;
/** * Scan the string backwards, looking for the given substring. * * @param aString is substring to be sought in this * @return offset in string, or kNotFound
*/
int32_t RFind(const string_view& aString) const;
/** * Search for the first instance of a given char within this string * * @param aChar is the character to search for * @param aOffset tells us where in this string to start searching * @return offset in string, or kNotFound
*/
int32_t FindChar(char_type aChar, index_type aOffset = 0) const;
/** * Search for the last instance of a given char within this string * * @param aChar is the character to search for * @param aOffset tells us where in this string to start searching * @return offset in string, or kNotFound
*/
int32_t RFindChar(char_type aChar, int32_t aOffset = -1) const;
/** * This method searches this string for the first character found in * the given string. * * @param aSet contains set of chars to be found * @param aOffset tells us where in this string to start searching * (counting from left) * @return offset in string, or kNotFound
*/
/** * This method searches this string for the last character found in * the given string. * * @param aSet contains set of chars to be found * @param aOffset tells us where in this string to start searching * (counting from left) * @return offset in string, or kNotFound
*/
/** * Perform locale-independent string to double-precision float conversion. * * Leading spaces in the string will be ignored. The returned value will be * finite unless aErrorCode is set to a failed status. * * @param aErrorCode will contain error if one occurs * @return double-precision float rep of string value
*/ double ToDouble(nsresult* aErrorCode) const;
/** * Perform locale-independent string to single-precision float conversion. * * Leading spaces in the string will be ignored. The returned value will be * finite unless aErrorCode is set to a failed status. * * @param aErrorCode will contain error if one occurs * @return single-precision float rep of string value
*/ float ToFloat(nsresult* aErrorCode) const;
/** * Similar to above ToDouble and ToFloat but allows trailing characters that * are not converted.
*/ double ToDoubleAllowTrailingChars(nsresult* aErrorCode) const; float ToFloatAllowTrailingChars(nsresult* aErrorCode) const;
protected:
nsTStringRepr() = delete; // Never instantiate directly
/** * Checks if the given capacity is valid for this string type.
*/
[[nodiscard]] static constexpr bool CheckCapacity(size_type aCapacity) { return aCapacity <= kMaxCapacity;
}
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 ist noch experimentell.