Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "XMLHttpRequestString.h"
8 : #include "nsISupportsImpl.h"
9 : #include "mozilla/dom/DOMString.h"
10 :
11 : namespace mozilla {
12 : namespace dom {
13 :
14 : class XMLHttpRequestStringBuffer final
15 : {
16 : friend class XMLHttpRequestStringWriterHelper;
17 : friend class XMLHttpRequestStringSnapshotReaderHelper;
18 :
19 : public:
20 88 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(XMLHttpRequestStringBuffer)
21 : NS_DECL_OWNINGTHREAD
22 :
23 10 : XMLHttpRequestStringBuffer()
24 10 : : mMutex("XMLHttpRequestStringBuffer::mMutex")
25 : {
26 10 : }
27 :
28 : uint32_t
29 3 : Length()
30 : {
31 6 : MutexAutoLock lock(mMutex);
32 6 : return mData.Length();
33 : }
34 :
35 : uint32_t
36 19 : UnsafeLength() const
37 : {
38 19 : return mData.Length();
39 : }
40 :
41 : void
42 0 : Append(const nsAString& aString)
43 : {
44 0 : NS_ASSERT_OWNINGTHREAD(XMLHttpRequestStringBuffer);
45 :
46 0 : MutexAutoLock lock(mMutex);
47 0 : mData.Append(aString);
48 0 : }
49 :
50 : MOZ_MUST_USE bool
51 0 : GetAsString(nsAString& aString)
52 : {
53 0 : MutexAutoLock lock(mMutex);
54 0 : return aString.Assign(mData, mozilla::fallible);
55 : }
56 :
57 : size_t
58 0 : SizeOfThis(MallocSizeOf aMallocSizeOf) const
59 : {
60 0 : return mData.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
61 : }
62 :
63 : MOZ_MUST_USE bool
64 2 : GetAsString(DOMString& aString, uint32_t aLength)
65 : {
66 4 : MutexAutoLock lock(mMutex);
67 2 : MOZ_ASSERT(aLength <= mData.Length());
68 2 : nsStringBuffer* buf = nsStringBuffer::FromString(mData);
69 2 : if (buf) {
70 : // We have to use SetEphemeralStringBuffer, because once we release our
71 : // mutex mData can get mutated from some other thread while the DOMString
72 : // is still alive.
73 2 : aString.SetEphemeralStringBuffer(buf, aLength);
74 2 : return true;
75 : }
76 :
77 : // We can get here if mData is empty. In that case it won't have an
78 : // nsStringBuffer....
79 0 : MOZ_ASSERT(mData.IsEmpty());
80 0 : return aString.AsAString().Assign(mData.BeginReading(), aLength,
81 0 : mozilla::fallible);
82 : }
83 :
84 : void
85 10 : CreateSnapshot(XMLHttpRequestStringSnapshot& aSnapshot)
86 : {
87 20 : MutexAutoLock lock(mMutex);
88 10 : aSnapshot.Set(this, mData.Length());
89 10 : }
90 :
91 : private:
92 7 : ~XMLHttpRequestStringBuffer()
93 7 : {}
94 :
95 9 : nsString& UnsafeData()
96 : {
97 9 : return mData;
98 : }
99 :
100 : Mutex mMutex;
101 :
102 : // The following member variable is protected by mutex.
103 : nsString mData;
104 : };
105 :
106 : // ---------------------------------------------------------------------------
107 : // XMLHttpRequestString
108 :
109 3 : XMLHttpRequestString::XMLHttpRequestString()
110 3 : : mBuffer(new XMLHttpRequestStringBuffer())
111 : {
112 3 : }
113 :
114 0 : XMLHttpRequestString::~XMLHttpRequestString()
115 : {
116 0 : }
117 :
118 : void
119 7 : XMLHttpRequestString::Truncate()
120 : {
121 7 : mBuffer = new XMLHttpRequestStringBuffer();
122 7 : }
123 :
124 : uint32_t
125 3 : XMLHttpRequestString::Length() const
126 : {
127 3 : return mBuffer->Length();
128 : }
129 :
130 : void
131 0 : XMLHttpRequestString::Append(const nsAString& aString)
132 : {
133 0 : mBuffer->Append(aString);
134 0 : }
135 :
136 : bool
137 0 : XMLHttpRequestString::GetAsString(nsAString& aString) const
138 : {
139 0 : return mBuffer->GetAsString(aString);
140 : }
141 :
142 : size_t
143 0 : XMLHttpRequestString::SizeOfThis(MallocSizeOf aMallocSizeOf) const
144 : {
145 0 : return mBuffer->SizeOfThis(aMallocSizeOf);
146 : }
147 :
148 : bool
149 0 : XMLHttpRequestString::IsEmpty() const
150 : {
151 0 : return !mBuffer->Length();
152 : }
153 :
154 : void
155 10 : XMLHttpRequestString::CreateSnapshot(XMLHttpRequestStringSnapshot& aSnapshot)
156 : {
157 10 : mBuffer->CreateSnapshot(aSnapshot);
158 10 : }
159 :
160 : // ---------------------------------------------------------------------------
161 : // XMLHttpRequestStringSnapshot
162 :
163 37 : XMLHttpRequestStringSnapshot::XMLHttpRequestStringSnapshot()
164 : : mLength(0)
165 37 : , mVoid(false)
166 : {
167 37 : }
168 :
169 34 : XMLHttpRequestStringSnapshot::~XMLHttpRequestStringSnapshot()
170 : {
171 34 : }
172 :
173 : XMLHttpRequestStringSnapshot&
174 34 : XMLHttpRequestStringSnapshot::operator=(const XMLHttpRequestStringSnapshot& aOther)
175 : {
176 34 : mBuffer = aOther.mBuffer;
177 34 : mLength = aOther.mLength;
178 34 : mVoid = aOther.mVoid;
179 34 : return *this;
180 : }
181 :
182 : void
183 17 : XMLHttpRequestStringSnapshot::ResetInternal(bool aIsVoid)
184 : {
185 17 : mBuffer = nullptr;
186 17 : mLength = 0;
187 17 : mVoid = aIsVoid;
188 17 : }
189 :
190 : void
191 10 : XMLHttpRequestStringSnapshot::Set(XMLHttpRequestStringBuffer* aBuffer,
192 : uint32_t aLength)
193 : {
194 10 : MOZ_ASSERT(aBuffer);
195 10 : MOZ_ASSERT(aLength <= aBuffer->UnsafeLength());
196 :
197 10 : mBuffer = aBuffer;
198 10 : mLength = aLength;
199 10 : mVoid = false;
200 10 : }
201 :
202 : bool
203 2 : XMLHttpRequestStringSnapshot::GetAsString(DOMString& aString) const
204 : {
205 2 : if (mBuffer) {
206 2 : MOZ_ASSERT(!mVoid);
207 2 : return mBuffer->GetAsString(aString, mLength);
208 : }
209 :
210 0 : if (mVoid) {
211 0 : aString.SetNull();
212 : }
213 :
214 0 : return true;
215 : }
216 :
217 : // ---------------------------------------------------------------------------
218 : // XMLHttpRequestStringWriterHelper
219 :
220 3 : XMLHttpRequestStringWriterHelper::XMLHttpRequestStringWriterHelper(XMLHttpRequestString& aString)
221 : : mBuffer(aString.mBuffer)
222 3 : , mLock(aString.mBuffer->mMutex)
223 : {
224 3 : }
225 :
226 : bool
227 3 : XMLHttpRequestStringWriterHelper::AddCapacity(int32_t aCapacity)
228 : {
229 3 : return mBuffer->UnsafeData().SetCapacity(mBuffer->UnsafeLength() + aCapacity, fallible);
230 : }
231 :
232 : char16_t*
233 3 : XMLHttpRequestStringWriterHelper::EndOfExistingData()
234 : {
235 3 : return mBuffer->UnsafeData().BeginWriting() + mBuffer->UnsafeLength();
236 : }
237 :
238 : void
239 3 : XMLHttpRequestStringWriterHelper::AddLength(int32_t aLength)
240 : {
241 3 : mBuffer->UnsafeData().SetLength(mBuffer->UnsafeLength() + aLength);
242 3 : }
243 :
244 : // ---------------------------------------------------------------------------
245 : // XMLHttpRequestStringReaderHelper
246 :
247 0 : XMLHttpRequestStringSnapshotReaderHelper::XMLHttpRequestStringSnapshotReaderHelper(XMLHttpRequestStringSnapshot& aSnapshot)
248 : : mBuffer(aSnapshot.mBuffer)
249 0 : , mLock(aSnapshot.mBuffer->mMutex)
250 : {
251 0 : }
252 :
253 : const char16_t*
254 0 : XMLHttpRequestStringSnapshotReaderHelper::Buffer() const
255 : {
256 0 : return mBuffer->UnsafeData().BeginReading();
257 : }
258 :
259 : uint32_t
260 0 : XMLHttpRequestStringSnapshotReaderHelper::Length() const
261 : {
262 0 : return mBuffer->UnsafeLength();
263 : }
264 :
265 : } // dom namespace
266 : } // mozilla namespace
|