summaryrefslogtreecommitdiffstats
path: root/xpcom/string/nsTString.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--xpcom/string/nsTString.h447
1 files changed, 447 insertions, 0 deletions
diff --git a/xpcom/string/nsTString.h b/xpcom/string/nsTString.h
new file mode 100644
index 0000000000..9793f70e3b
--- /dev/null
+++ b/xpcom/string/nsTString.h
@@ -0,0 +1,447 @@
+/* -*- 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/. */
+// IWYU pragma: private, include "nsString.h"
+
+#ifndef nsTString_h
+#define nsTString_h
+
+#include "nsTSubstring.h"
+
+/**
+ * This is the canonical null-terminated string class. All subclasses
+ * promise null-terminated storage. Instances of this class allocate
+ * strings on the heap.
+ *
+ * NAMES:
+ * nsString for wide characters
+ * nsCString for narrow characters
+ *
+ * This class is also known as nsAFlat[C]String, where "flat" is used
+ * to denote a null-terminated string.
+ */
+template <typename T>
+class nsTString : public nsTSubstring<T> {
+ public:
+ typedef nsTString<T> self_type;
+
+ using repr_type = mozilla::detail::nsTStringRepr<T>;
+
+#ifdef __clang__
+ // bindgen w/ clang 3.9 at least chokes on a typedef, but using is okay.
+ using typename nsTSubstring<T>::substring_type;
+#else
+ // On the other hand msvc chokes on the using statement. It seems others
+ // don't care either way so we lump them in here.
+ typedef typename nsTSubstring<T>::substring_type substring_type;
+#endif
+
+ typedef typename substring_type::fallible_t fallible_t;
+
+ typedef typename substring_type::char_type char_type;
+ typedef typename substring_type::char_traits char_traits;
+ typedef
+ typename substring_type::incompatible_char_type incompatible_char_type;
+
+ typedef typename substring_type::substring_tuple_type substring_tuple_type;
+
+ typedef typename substring_type::const_iterator const_iterator;
+ typedef typename substring_type::iterator iterator;
+
+ typedef typename substring_type::comparator_type comparator_type;
+
+ typedef typename substring_type::const_char_iterator const_char_iterator;
+
+ typedef typename substring_type::string_view string_view;
+
+ typedef typename substring_type::index_type index_type;
+ typedef typename substring_type::size_type size_type;
+
+ // These are only for internal use within the string classes:
+ typedef typename substring_type::DataFlags DataFlags;
+ typedef typename substring_type::ClassFlags ClassFlags;
+
+ public:
+ /**
+ * constructors
+ */
+
+ nsTString() : substring_type(ClassFlags::NULL_TERMINATED) {}
+
+ explicit nsTString(const char_type* aData, size_type aLength = size_type(-1))
+ : substring_type(ClassFlags::NULL_TERMINATED) {
+ this->Assign(aData, aLength);
+ }
+
+ explicit nsTString(mozilla::Span<const char_type> aData)
+ : nsTString(aData.Elements(), aData.Length()) {}
+
+#if defined(MOZ_USE_CHAR16_WRAPPER)
+ template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
+ explicit nsTString(char16ptr_t aStr, size_type aLength = size_type(-1))
+ : substring_type(ClassFlags::NULL_TERMINATED) {
+ this->Assign(static_cast<const char16_t*>(aStr), aLength);
+ }
+#endif
+
+ nsTString(const self_type& aStr)
+ : substring_type(ClassFlags::NULL_TERMINATED) {
+ this->Assign(aStr);
+ }
+
+ nsTString(self_type&& aStr) : substring_type(ClassFlags::NULL_TERMINATED) {
+ this->Assign(std::move(aStr));
+ }
+
+ MOZ_IMPLICIT nsTString(const substring_tuple_type& aTuple)
+ : substring_type(ClassFlags::NULL_TERMINATED) {
+ this->Assign(aTuple);
+ }
+
+ explicit nsTString(const substring_type& aReadable)
+ : substring_type(ClassFlags::NULL_TERMINATED) {
+ this->Assign(aReadable);
+ }
+
+ explicit nsTString(substring_type&& aReadable)
+ : substring_type(ClassFlags::NULL_TERMINATED) {
+ this->Assign(std::move(aReadable));
+ }
+
+ // |operator=| does not inherit, so we must define our own
+ self_type& operator=(char_type aChar) {
+ this->Assign(aChar);
+ return *this;
+ }
+ self_type& operator=(const char_type* aData) {
+ this->Assign(aData);
+ return *this;
+ }
+ self_type& operator=(const self_type& aStr) {
+ this->Assign(aStr);
+ return *this;
+ }
+ self_type& operator=(self_type&& aStr) {
+ this->Assign(std::move(aStr));
+ return *this;
+ }
+#if defined(MOZ_USE_CHAR16_WRAPPER)
+ template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
+ self_type& operator=(const char16ptr_t aStr) {
+ this->Assign(static_cast<const char16_t*>(aStr));
+ return *this;
+ }
+#endif
+ self_type& operator=(const substring_type& aStr) {
+ this->Assign(aStr);
+ return *this;
+ }
+ self_type& operator=(substring_type&& aStr) {
+ this->Assign(std::move(aStr));
+ return *this;
+ }
+ self_type& operator=(const substring_tuple_type& aTuple) {
+ this->Assign(aTuple);
+ return *this;
+ }
+
+ /**
+ * returns the null-terminated string
+ */
+
+ template <typename U, typename Dummy>
+ struct raw_type {
+ typedef const U* type;
+ };
+#if defined(MOZ_USE_CHAR16_WRAPPER)
+ template <typename Dummy>
+ struct raw_type<char16_t, Dummy> {
+ typedef char16ptr_t type;
+ };
+#endif
+
+ MOZ_NO_DANGLING_ON_TEMPORARIES typename raw_type<T, int>::type get() const {
+ return this->mData;
+ }
+
+ /**
+ * returns character at specified index.
+ *
+ * NOTE: unlike nsTSubstring::CharAt, this function allows you to index
+ * the null terminator character.
+ */
+
+ char_type CharAt(index_type aIndex) const {
+ MOZ_ASSERT(aIndex <= this->Length(), "index exceeds allowable range");
+ return this->mData[aIndex];
+ }
+
+ char_type operator[](index_type aIndex) const { return CharAt(aIndex); }
+
+ /**
+ * Set a char inside this string at given index
+ *
+ * @param aChar is the char you want to write into this string
+ * @param anIndex is the ofs where you want to write the given char
+ * @return TRUE if successful
+ */
+ bool SetCharAt(char16_t aChar, index_type aIndex);
+
+ /**
+ * Allow this string to be bound to a character buffer
+ * until the string is rebound or mutated; the caller
+ * must ensure that the buffer outlives the string.
+ */
+ void Rebind(const char_type* aData, size_type aLength);
+
+ /**
+ * verify restrictions for dependent strings
+ */
+ void AssertValidDependentString() {
+ MOZ_ASSERT(this->mData, "nsTDependentString must wrap a non-NULL buffer");
+ MOZ_ASSERT(this->mData[substring_type::mLength] == 0,
+ "nsTDependentString must wrap only null-terminated strings. "
+ "You are probably looking for nsTDependentSubstring.");
+ }
+
+ protected:
+ // allow subclasses to initialize fields directly
+ nsTString(char_type* aData, size_type aLength, DataFlags aDataFlags,
+ ClassFlags aClassFlags)
+ : substring_type(aData, aLength, aDataFlags,
+ aClassFlags | ClassFlags::NULL_TERMINATED) {}
+
+ friend const nsTString<char>& VoidCString();
+ friend const nsTString<char16_t>& VoidString();
+
+ // Used by Null[C]String.
+ explicit nsTString(DataFlags aDataFlags)
+ : substring_type(char_traits::sEmptyBuffer, 0,
+ aDataFlags | DataFlags::TERMINATED,
+ ClassFlags::NULL_TERMINATED) {}
+};
+
+extern template class nsTString<char>;
+extern template class nsTString<char16_t>;
+
+/**
+ * nsTAutoStringN
+ *
+ * Subclass of nsTString that adds support for stack-based string
+ * allocation. It is normally not a good idea to use this class on the
+ * heap, because it will allocate space which may be wasted if the string
+ * it contains is significantly smaller or any larger than 64 characters.
+ *
+ * NAMES:
+ * nsAutoStringN / nsTAutoString for wide characters
+ * nsAutoCStringN / nsTAutoCString for narrow characters
+ */
+template <typename T, size_t N>
+class MOZ_NON_MEMMOVABLE nsTAutoStringN : public nsTString<T> {
+ public:
+ typedef nsTAutoStringN<T, N> self_type;
+
+ typedef nsTString<T> base_string_type;
+ typedef typename base_string_type::string_type string_type;
+ typedef typename base_string_type::char_type char_type;
+ typedef typename base_string_type::char_traits char_traits;
+ typedef typename base_string_type::substring_type substring_type;
+ typedef typename base_string_type::size_type size_type;
+ typedef typename base_string_type::substring_tuple_type substring_tuple_type;
+
+ // These are only for internal use within the string classes:
+ typedef typename base_string_type::DataFlags DataFlags;
+ typedef typename base_string_type::ClassFlags ClassFlags;
+ typedef typename base_string_type::LengthStorage LengthStorage;
+
+ public:
+ /**
+ * constructors
+ */
+
+ nsTAutoStringN()
+ : string_type(mStorage, 0, DataFlags::TERMINATED | DataFlags::INLINE,
+ ClassFlags::INLINE),
+ mInlineCapacity(N - 1) {
+ // null-terminate
+ mStorage[0] = char_type(0);
+ }
+
+ explicit nsTAutoStringN(char_type aChar) : self_type() {
+ this->Assign(aChar);
+ }
+
+ explicit nsTAutoStringN(const char_type* aData,
+ size_type aLength = size_type(-1))
+ : self_type() {
+ this->Assign(aData, aLength);
+ }
+
+#if defined(MOZ_USE_CHAR16_WRAPPER)
+ template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
+ explicit nsTAutoStringN(char16ptr_t aData, size_type aLength = size_type(-1))
+ : self_type(static_cast<const char16_t*>(aData), aLength) {}
+#endif
+
+ nsTAutoStringN(const self_type& aStr) : self_type() { this->Assign(aStr); }
+
+ nsTAutoStringN(self_type&& aStr) : self_type() {
+ this->Assign(std::move(aStr));
+ }
+
+ explicit nsTAutoStringN(const substring_type& aStr) : self_type() {
+ this->Assign(aStr);
+ }
+
+ explicit nsTAutoStringN(substring_type&& aStr) : self_type() {
+ this->Assign(std::move(aStr));
+ }
+
+ MOZ_IMPLICIT nsTAutoStringN(const substring_tuple_type& aTuple)
+ : self_type() {
+ this->Assign(aTuple);
+ }
+
+ // |operator=| does not inherit, so we must define our own
+ self_type& operator=(char_type aChar) {
+ this->Assign(aChar);
+ return *this;
+ }
+ self_type& operator=(const char_type* aData) {
+ this->Assign(aData);
+ return *this;
+ }
+#if defined(MOZ_USE_CHAR16_WRAPPER)
+ template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
+ self_type& operator=(char16ptr_t aStr) {
+ this->Assign(aStr);
+ return *this;
+ }
+#endif
+ self_type& operator=(const self_type& aStr) {
+ this->Assign(aStr);
+ return *this;
+ }
+ self_type& operator=(self_type&& aStr) {
+ this->Assign(std::move(aStr));
+ return *this;
+ }
+ self_type& operator=(const substring_type& aStr) {
+ this->Assign(aStr);
+ return *this;
+ }
+ self_type& operator=(substring_type&& aStr) {
+ this->Assign(std::move(aStr));
+ return *this;
+ }
+ self_type& operator=(const substring_tuple_type& aTuple) {
+ this->Assign(aTuple);
+ return *this;
+ }
+
+ static const size_t kStorageSize = N;
+
+ protected:
+ friend class nsTSubstring<T>;
+
+ const LengthStorage mInlineCapacity;
+
+ private:
+ char_type mStorage[N];
+};
+
+// Externs for the most common nsTAutoStringN variations.
+extern template class nsTAutoStringN<char, 64>;
+extern template class nsTAutoStringN<char16_t, 64>;
+
+//
+// nsAutoString stores pointers into itself which are invalidated when an
+// nsTArray is resized, so nsTArray must not be instantiated with nsAutoString
+// elements!
+//
+template <class E>
+class nsTArrayElementTraits;
+template <typename T>
+class nsTArrayElementTraits<nsTAutoString<T>> {
+ public:
+ template <class A>
+ struct Dont_Instantiate_nsTArray_of;
+ template <class A>
+ struct Instead_Use_nsTArray_of;
+
+ static Dont_Instantiate_nsTArray_of<nsTAutoString<T>>* Construct(
+ Instead_Use_nsTArray_of<nsTString<T>>* aE) {
+ return 0;
+ }
+ template <class A>
+ static Dont_Instantiate_nsTArray_of<nsTAutoString<T>>* Construct(
+ Instead_Use_nsTArray_of<nsTString<T>>* aE, const A& aArg) {
+ return 0;
+ }
+ template <class... Args>
+ static Dont_Instantiate_nsTArray_of<nsTAutoString<T>>* Construct(
+ Instead_Use_nsTArray_of<nsTString<T>>* aE, Args&&... aArgs) {
+ return 0;
+ }
+ static Dont_Instantiate_nsTArray_of<nsTAutoString<T>>* Destruct(
+ Instead_Use_nsTArray_of<nsTString<T>>* aE) {
+ return 0;
+ }
+};
+
+/**
+ * getter_Copies support for adopting raw string out params that are
+ * heap-allocated, e.g.:
+ *
+ * char* gStr;
+ * void GetBlah(char** aStr)
+ * {
+ * *aStr = strdup(gStr);
+ * }
+ *
+ * // This works, but is clumsy.
+ * void Inelegant()
+ * {
+ * char* buf;
+ * GetBlah(&buf);
+ * nsCString str;
+ * str.Adopt(buf);
+ * // ...
+ * }
+ *
+ * // This is nicer.
+ * void Elegant()
+ * {
+ * nsCString str;
+ * GetBlah(getter_Copies(str));
+ * // ...
+ * }
+ */
+template <typename T>
+class MOZ_STACK_CLASS nsTGetterCopies {
+ public:
+ typedef T char_type;
+
+ explicit nsTGetterCopies(nsTSubstring<T>& aStr)
+ : mString(aStr), mData(nullptr) {}
+
+ ~nsTGetterCopies() {
+ mString.Adopt(mData); // OK if mData is null
+ }
+
+ operator char_type**() { return &mData; }
+
+ private:
+ nsTSubstring<T>& mString;
+ char_type* mData;
+};
+
+// See the comment above nsTGetterCopies_CharT for how to use this.
+template <typename T>
+inline nsTGetterCopies<T> getter_Copies(nsTSubstring<T>& aString) {
+ return nsTGetterCopies<T>(aString);
+}
+
+#endif