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/. */
7 #include "XMLHttpRequestString.h"
8 #include "nsISupportsImpl.h"
9 #include "mozilla/dom/DOMString.h"
11 namespace mozilla::dom
{
13 class XMLHttpRequestStringBuffer final
{
14 friend class XMLHttpRequestStringWriterHelper
;
15 friend class XMLHttpRequestStringSnapshotReaderHelper
;
18 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(XMLHttpRequestStringBuffer
)
21 XMLHttpRequestStringBuffer() : mMutex("XMLHttpRequestStringBuffer::mMutex") {}
24 MutexAutoLock
lock(mMutex
);
25 return mData
.Length();
28 uint32_t UnsafeLength() const MOZ_NO_THREAD_SAFETY_ANALYSIS
{
29 return mData
.Length();
32 mozilla::Result
<mozilla::BulkWriteHandle
<char16_t
>, nsresult
> UnsafeBulkWrite(
33 uint32_t aCapacity
) MOZ_NO_THREAD_SAFETY_ANALYSIS
{
34 return mData
.BulkWrite(aCapacity
, UnsafeLength(), false);
37 void Append(const nsAString
& aString
) {
38 NS_ASSERT_OWNINGTHREAD(XMLHttpRequestStringBuffer
);
40 MutexAutoLock
lock(mMutex
);
41 mData
.Append(aString
);
44 [[nodiscard
]] bool GetAsString(nsAString
& aString
) {
45 MutexAutoLock
lock(mMutex
);
46 return aString
.Assign(mData
, mozilla::fallible
);
49 size_t SizeOfThis(MallocSizeOf aMallocSizeOf
) {
50 MutexAutoLock
lock(mMutex
);
51 return mData
.SizeOfExcludingThisIfUnshared(aMallocSizeOf
);
54 [[nodiscard
]] bool GetAsString(DOMString
& aString
, uint32_t aLength
) {
55 MutexAutoLock
lock(mMutex
);
56 MOZ_ASSERT(aLength
<= mData
.Length());
58 // XXX: Bug 1408793 suggests encapsulating the following sequence within
60 nsStringBuffer
* buf
= nsStringBuffer::FromString(mData
);
62 // We have to use SetStringBuffer, because once we release our mutex mData
63 // can get mutated from some other thread while the DOMString is still
65 aString
.SetStringBuffer(buf
, aLength
);
69 // We can get here if mData is empty. In that case it won't have an
71 MOZ_ASSERT(mData
.IsEmpty());
72 return aString
.AsAString().Assign(mData
.BeginReading(), aLength
,
76 void CreateSnapshot(XMLHttpRequestStringSnapshot
& aSnapshot
) {
77 MutexAutoLock
lock(mMutex
);
78 aSnapshot
.Set(this, mData
.Length());
82 ~XMLHttpRequestStringBuffer() = default;
84 nsString
& UnsafeData() MOZ_NO_THREAD_SAFETY_ANALYSIS
{ return mData
; }
88 // The following member variable is protected by mutex.
89 nsString mData
MOZ_GUARDED_BY(mMutex
);
92 // ---------------------------------------------------------------------------
93 // XMLHttpRequestString
95 XMLHttpRequestString::XMLHttpRequestString()
96 : mBuffer(new XMLHttpRequestStringBuffer()) {}
98 XMLHttpRequestString::~XMLHttpRequestString() = default;
100 void XMLHttpRequestString::Truncate() {
101 mBuffer
= new XMLHttpRequestStringBuffer();
104 uint32_t XMLHttpRequestString::Length() const { return mBuffer
->Length(); }
106 void XMLHttpRequestString::Append(const nsAString
& aString
) {
107 mBuffer
->Append(aString
);
110 bool XMLHttpRequestString::GetAsString(nsAString
& aString
) const {
111 return mBuffer
->GetAsString(aString
);
114 size_t XMLHttpRequestString::SizeOfThis(MallocSizeOf aMallocSizeOf
) const {
115 return mBuffer
->SizeOfThis(aMallocSizeOf
);
118 bool XMLHttpRequestString::IsEmpty() const { return !mBuffer
->Length(); }
120 void XMLHttpRequestString::CreateSnapshot(
121 XMLHttpRequestStringSnapshot
& aSnapshot
) {
122 mBuffer
->CreateSnapshot(aSnapshot
);
125 // ---------------------------------------------------------------------------
126 // XMLHttpRequestStringSnapshot
128 XMLHttpRequestStringSnapshot::XMLHttpRequestStringSnapshot()
129 : mLength(0), mVoid(false) {}
131 XMLHttpRequestStringSnapshot::~XMLHttpRequestStringSnapshot() = default;
133 void XMLHttpRequestStringSnapshot::ResetInternal(bool aIsVoid
) {
139 void XMLHttpRequestStringSnapshot::Set(XMLHttpRequestStringBuffer
* aBuffer
,
142 MOZ_ASSERT(aLength
<= aBuffer
->UnsafeLength());
149 bool XMLHttpRequestStringSnapshot::GetAsString(DOMString
& aString
) const {
152 return mBuffer
->GetAsString(aString
, mLength
);
162 // ---------------------------------------------------------------------------
163 // XMLHttpRequestStringWriterHelper
165 XMLHttpRequestStringWriterHelper::XMLHttpRequestStringWriterHelper(
166 XMLHttpRequestString
& aString
)
167 : mBuffer(aString
.mBuffer
), mLock(aString
.mBuffer
->mMutex
) {}
169 XMLHttpRequestStringWriterHelper::~XMLHttpRequestStringWriterHelper() = default;
171 uint32_t XMLHttpRequestStringWriterHelper::Length() const {
172 return mBuffer
->UnsafeLength();
175 mozilla::Result
<mozilla::BulkWriteHandle
<char16_t
>, nsresult
>
176 XMLHttpRequestStringWriterHelper::BulkWrite(uint32_t aCapacity
) {
177 return mBuffer
->UnsafeBulkWrite(aCapacity
);
180 // ---------------------------------------------------------------------------
181 // XMLHttpRequestStringReaderHelper
183 XMLHttpRequestStringSnapshotReaderHelper::
184 XMLHttpRequestStringSnapshotReaderHelper(
185 XMLHttpRequestStringSnapshot
& aSnapshot
)
186 : mBuffer(aSnapshot
.mBuffer
), mLock(aSnapshot
.mBuffer
->mMutex
) {}
188 XMLHttpRequestStringSnapshotReaderHelper::
189 ~XMLHttpRequestStringSnapshotReaderHelper() = default;
191 const char16_t
* XMLHttpRequestStringSnapshotReaderHelper::Buffer() const {
192 return mBuffer
->UnsafeData().BeginReading();
195 uint32_t XMLHttpRequestStringSnapshotReaderHelper::Length() const {
196 return mBuffer
->UnsafeLength();
199 } // namespace mozilla::dom