/* 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/. */ #ifndef mozilla_dom_DOMString_h #define mozilla_dom_DOMString_h #include "nsAtom.h" #include "nsDOMString.h" #include "nsString.h" namespace mozilla::dom { // DOMString is an AutoTString with a few extra dangerous methods needed for // performance in some cases, where we want to propagate a "weak" reference to a // string up. See bug 2023628 for some context. // // Some of these methods could actually live in nsTSubString, perhaps, but // they're hard to get right, and make assumptions about what kind of strings // they are called with in order to save cycles. class DOMString final : public nsAutoString { public: enum NullHandling { eTreatNullAsNull, eTreatNullAsEmpty, eNullNotExpected }; void SetKnownLiveAtom(nsAtom* aAtom, NullHandling aNullHandling) { AssertSetKnownLivePrecondition(); MOZ_ASSERT(aAtom || aNullHandling != eNullNotExpected); if (aNullHandling == eNullNotExpected || aAtom) { // Static atoms are backed by literals, and dynamic ones by StringBuffer. DataFlags flags = DataFlags::TERMINATED; const char_type* data; if (aAtom->IsStatic()) { data = aAtom->AsStatic()->String(); flags |= DataFlags::LITERAL; } else { MOZ_ASSERT(aAtom->AsDynamic()->StringBuffer()); data = aAtom->AsDynamic()->String(); flags |= DataFlags::STRINGBUFFER; } SetData(const_cast(data), aAtom->GetLength(), flags); AssertValid(); } else if (aNullHandling == eTreatNullAsNull) { SetNull(); } } void SetKnownLiveString(const nsAString& aString) { AssertSetKnownLivePrecondition(); MOZ_ASSERT(aString.IsTerminated(), "If we are not terminated, then we need copying or so"); // NOTE: This is a bit subtle, but the data flags we copy are basically "all // except OWNED | INLINE", which cause us to copy null-ness, // refcounted-ness, etc. const char_type* data = aString.Data(); SetData( const_cast(data), aString.Length(), aString.GetDataFlags() & (DataFlags::TERMINATED | DataFlags::LITERAL | DataFlags::STRINGBUFFER | DataFlags::VOIDED)); AssertValid(); } void SetKnownLiveStringBuffer(StringBuffer* aBuffer, LengthStorage aLen) { AssertSetKnownLivePrecondition(); MOZ_ASSERT(aBuffer); // NOTE: No DataFlags::OWNED. SetData(static_cast(aBuffer->Data()), aLen, DataFlags::STRINGBUFFER | DataFlags::TERMINATED); AssertValid(); } void SetNull() { SetIsVoid(true); } bool IsNull() const { return IsVoid(); } private: void AssertSetKnownLivePrecondition() { MOZ_ASSERT(IsEmpty(), "We rely on this being called only on empty strings"); MOZ_ASSERT(!(mDataFlags & DataFlags::OWNED), "Would leak"); } }; } // namespace mozilla::dom #endif // mozilla_dom_DOMString_h