Bumping manifests a=b2g-bump
[gecko.git] / dom / bindings / DOMString.h
blobfff5da925779458395ab309c2fcbd4be877e8147
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef mozilla_dom_DOMString_h
7 #define mozilla_dom_DOMString_h
9 #include "nsStringGlue.h"
10 #include "nsStringBuffer.h"
11 #include "mozilla/Assertions.h"
12 #include "mozilla/Attributes.h"
13 #include "mozilla/Maybe.h"
14 #include "nsDOMString.h"
15 #include "nsIAtom.h"
17 namespace mozilla {
18 namespace dom {
20 /**
21 * A class for representing string return values. This can be either passed to
22 * callees that have an nsString or nsAString out param or passed to a callee
23 * that actually knows about this class and can work with it. Such a callee may
24 * call SetStringBuffer or SetOwnedString or SetOwnedAtom on this object, but
25 * only if it plans to keep holding a strong ref to the internal stringbuffer!
27 * The proper way to store a value in this class is to either to do nothing
28 * (which leaves this as an empty string), to call SetStringBuffer with a
29 * non-null stringbuffer, to call SetOwnedString, to call SetOwnedAtom, to call
30 * SetNull(), or to call AsAString() and set the value in the resulting
31 * nsString. These options are mutually exclusive! Don't do more than one of
32 * them.
34 * The proper way to extract a value is to check IsNull(). If not null, then
35 * check HasStringBuffer(). If that's true, check for a zero length, and if the
36 * length is nonzero call StringBuffer(). If the length is zero this is the
37 * empty string. If HasStringBuffer() returns false, call AsAString() and get
38 * the value from that.
40 class MOZ_STACK_CLASS DOMString {
41 public:
42 DOMString()
43 : mStringBuffer(nullptr)
44 , mLength(0)
45 , mIsNull(false)
47 ~DOMString()
49 MOZ_ASSERT(!mString || !mStringBuffer,
50 "Shouldn't have both present!");
53 operator nsString&()
55 return AsAString();
58 nsString& AsAString()
60 MOZ_ASSERT(!mStringBuffer, "We already have a stringbuffer?");
61 MOZ_ASSERT(!mIsNull, "We're already set as null");
62 if (!mString) {
63 mString.emplace();
65 return *mString;
68 bool HasStringBuffer() const
70 MOZ_ASSERT(!mString || !mStringBuffer,
71 "Shouldn't have both present!");
72 MOZ_ASSERT(!mIsNull, "Caller should have checked IsNull() first");
73 return !mString;
76 // Get the stringbuffer. This can only be called if HasStringBuffer()
77 // returned true and StringBufferLength() is nonzero. If that's true, it will
78 // never return null.
79 nsStringBuffer* StringBuffer() const
81 MOZ_ASSERT(!mIsNull, "Caller should have checked IsNull() first");
82 MOZ_ASSERT(HasStringBuffer(),
83 "Don't ask for the stringbuffer if we don't have it");
84 MOZ_ASSERT(StringBufferLength() != 0, "Why are you asking for this?");
85 MOZ_ASSERT(mStringBuffer,
86 "If our length is nonzero, we better have a stringbuffer.");
87 return mStringBuffer;
90 // Get the length of the stringbuffer. Can only be called if
91 // HasStringBuffer().
92 uint32_t StringBufferLength() const
94 MOZ_ASSERT(HasStringBuffer(), "Don't call this if there is no stringbuffer");
95 return mLength;
98 void SetStringBuffer(nsStringBuffer* aStringBuffer, uint32_t aLength)
100 MOZ_ASSERT(mString.isNothing(), "We already have a string?");
101 MOZ_ASSERT(!mIsNull, "We're already set as null");
102 MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
103 MOZ_ASSERT(aStringBuffer, "Why are we getting null?");
104 mStringBuffer = aStringBuffer;
105 mLength = aLength;
108 void SetOwnedString(const nsAString& aString)
110 MOZ_ASSERT(mString.isNothing(), "We already have a string?");
111 MOZ_ASSERT(!mIsNull, "We're already set as null");
112 MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
113 nsStringBuffer* buf = nsStringBuffer::FromString(aString);
114 if (buf) {
115 SetStringBuffer(buf, aString.Length());
116 } else if (aString.IsVoid()) {
117 SetNull();
118 } else if (!aString.IsEmpty()) {
119 AsAString() = aString;
123 enum NullHandling
125 eTreatNullAsNull,
126 eTreatNullAsEmpty,
127 eNullNotExpected
130 void SetOwnedAtom(nsIAtom* aAtom, NullHandling aNullHandling)
132 MOZ_ASSERT(mString.isNothing(), "We already have a string?");
133 MOZ_ASSERT(!mIsNull, "We're already set as null");
134 MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
135 MOZ_ASSERT(aAtom || aNullHandling != eNullNotExpected);
136 if (aNullHandling == eNullNotExpected || aAtom) {
137 SetStringBuffer(aAtom->GetStringBuffer(), aAtom->GetLength());
138 } else if (aNullHandling == eTreatNullAsNull) {
139 SetNull();
143 void SetNull()
145 MOZ_ASSERT(!mStringBuffer, "Should have no stringbuffer if null");
146 MOZ_ASSERT(mString.isNothing(), "Should have no string if null");
147 mIsNull = true;
150 bool IsNull() const
152 MOZ_ASSERT(!mStringBuffer || mString.isNothing(),
153 "How could we have a stringbuffer and a nonempty string?");
154 return mIsNull || (mString && mString->IsVoid());
157 void ToString(nsAString& aString)
159 if (IsNull()) {
160 SetDOMStringToNull(aString);
161 } else if (HasStringBuffer()) {
162 if (StringBufferLength() == 0) {
163 aString.Truncate();
164 } else {
165 StringBuffer()->ToString(StringBufferLength(), aString);
167 } else {
168 aString = AsAString();
172 private:
173 // We need to be able to act like a string as needed
174 Maybe<nsAutoString> mString;
176 // For callees that know we exist, we can be a stringbuffer/length/null-flag
177 // triple.
178 nsStringBuffer* mStringBuffer;
179 uint32_t mLength;
180 bool mIsNull;
183 } // namespace dom
184 } // namespace mozilla
186 #endif // mozilla_dom_DOMString_h