Bug 1874684 - Part 4: Prefer const references instead of copying Instant values....
[gecko.git] / dom / xslt / xslt / txBufferingHandler.cpp
bloba0c7a39f73252d249bd49b3ea7fd08f4c1892539
1 /* -*- Mode: C++; tab-width: 4; 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 #include "txBufferingHandler.h"
8 using mozilla::MakeUnique;
10 class txOutputTransaction {
11 public:
12 enum txTransactionType {
13 eAttributeTransaction,
14 eAttributeAtomTransaction,
15 eCharacterTransaction,
16 eCharacterNoOETransaction,
17 eCommentTransaction,
18 eEndDocumentTransaction,
19 eEndElementTransaction,
20 ePITransaction,
21 eStartDocumentTransaction,
22 eStartElementAtomTransaction,
23 eStartElementTransaction
25 explicit txOutputTransaction(txTransactionType aType) : mType(aType) {
26 MOZ_COUNT_CTOR(txOutputTransaction);
28 MOZ_COUNTED_DTOR_VIRTUAL(txOutputTransaction)
29 txTransactionType mType;
32 class txCharacterTransaction : public txOutputTransaction {
33 public:
34 txCharacterTransaction(txTransactionType aType, uint32_t aLength)
35 : txOutputTransaction(aType), mLength(aLength) {
36 MOZ_COUNT_CTOR_INHERITED(txCharacterTransaction, txOutputTransaction);
38 virtual ~txCharacterTransaction() {
39 MOZ_COUNT_DTOR_INHERITED(txCharacterTransaction, txOutputTransaction);
41 uint32_t mLength;
44 class txCommentTransaction : public txOutputTransaction {
45 public:
46 explicit txCommentTransaction(const nsAString& aValue)
47 : txOutputTransaction(eCommentTransaction), mValue(aValue) {
48 MOZ_COUNT_CTOR_INHERITED(txCommentTransaction, txOutputTransaction);
50 virtual ~txCommentTransaction() {
51 MOZ_COUNT_DTOR_INHERITED(txCommentTransaction, txOutputTransaction);
53 nsString mValue;
56 class txPITransaction : public txOutputTransaction {
57 public:
58 txPITransaction(const nsAString& aTarget, const nsAString& aData)
59 : txOutputTransaction(ePITransaction), mTarget(aTarget), mData(aData) {
60 MOZ_COUNT_CTOR_INHERITED(txPITransaction, txOutputTransaction);
62 virtual ~txPITransaction() {
63 MOZ_COUNT_DTOR_INHERITED(txPITransaction, txOutputTransaction);
65 nsString mTarget;
66 nsString mData;
69 class txStartElementAtomTransaction : public txOutputTransaction {
70 public:
71 txStartElementAtomTransaction(nsAtom* aPrefix, nsAtom* aLocalName,
72 nsAtom* aLowercaseLocalName, int32_t aNsID)
73 : txOutputTransaction(eStartElementAtomTransaction),
74 mPrefix(aPrefix),
75 mLocalName(aLocalName),
76 mLowercaseLocalName(aLowercaseLocalName),
77 mNsID(aNsID) {
78 MOZ_COUNT_CTOR_INHERITED(txStartElementAtomTransaction,
79 txOutputTransaction);
81 virtual ~txStartElementAtomTransaction() {
82 MOZ_COUNT_DTOR_INHERITED(txStartElementAtomTransaction,
83 txOutputTransaction);
85 RefPtr<nsAtom> mPrefix;
86 RefPtr<nsAtom> mLocalName;
87 RefPtr<nsAtom> mLowercaseLocalName;
88 int32_t mNsID;
91 class txStartElementTransaction : public txOutputTransaction {
92 public:
93 txStartElementTransaction(nsAtom* aPrefix, const nsAString& aLocalName,
94 int32_t aNsID)
95 : txOutputTransaction(eStartElementTransaction),
96 mPrefix(aPrefix),
97 mLocalName(aLocalName),
98 mNsID(aNsID) {
99 MOZ_COUNT_CTOR_INHERITED(txStartElementTransaction, txOutputTransaction);
101 virtual ~txStartElementTransaction() {
102 MOZ_COUNT_DTOR_INHERITED(txStartElementTransaction, txOutputTransaction);
104 RefPtr<nsAtom> mPrefix;
105 nsString mLocalName;
106 int32_t mNsID;
109 class txAttributeTransaction : public txOutputTransaction {
110 public:
111 txAttributeTransaction(nsAtom* aPrefix, const nsAString& aLocalName,
112 int32_t aNsID, const nsString& aValue)
113 : txOutputTransaction(eAttributeTransaction),
114 mPrefix(aPrefix),
115 mLocalName(aLocalName),
116 mNsID(aNsID),
117 mValue(aValue) {
118 MOZ_COUNT_CTOR_INHERITED(txAttributeTransaction, txOutputTransaction);
120 virtual ~txAttributeTransaction() {
121 MOZ_COUNT_DTOR_INHERITED(txAttributeTransaction, txOutputTransaction);
123 RefPtr<nsAtom> mPrefix;
124 nsString mLocalName;
125 int32_t mNsID;
126 nsString mValue;
129 class txAttributeAtomTransaction : public txOutputTransaction {
130 public:
131 txAttributeAtomTransaction(nsAtom* aPrefix, nsAtom* aLocalName,
132 nsAtom* aLowercaseLocalName, int32_t aNsID,
133 const nsString& aValue)
134 : txOutputTransaction(eAttributeAtomTransaction),
135 mPrefix(aPrefix),
136 mLocalName(aLocalName),
137 mLowercaseLocalName(aLowercaseLocalName),
138 mNsID(aNsID),
139 mValue(aValue) {
140 MOZ_COUNT_CTOR_INHERITED(txAttributeAtomTransaction, txOutputTransaction);
142 virtual ~txAttributeAtomTransaction() {
143 MOZ_COUNT_DTOR_INHERITED(txAttributeAtomTransaction, txOutputTransaction);
145 RefPtr<nsAtom> mPrefix;
146 RefPtr<nsAtom> mLocalName;
147 RefPtr<nsAtom> mLowercaseLocalName;
148 int32_t mNsID;
149 nsString mValue;
152 txBufferingHandler::txBufferingHandler() : mCanAddAttribute(false) {
153 MOZ_COUNT_CTOR(txBufferingHandler);
154 mBuffer = MakeUnique<txResultBuffer>();
157 txBufferingHandler::~txBufferingHandler() {
158 MOZ_COUNT_DTOR(txBufferingHandler);
161 nsresult txBufferingHandler::attribute(nsAtom* aPrefix, nsAtom* aLocalName,
162 nsAtom* aLowercaseLocalName,
163 int32_t aNsID, const nsString& aValue) {
164 NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
166 if (!mCanAddAttribute) {
167 // XXX ErrorReport: Can't add attributes without element
168 return NS_OK;
171 txOutputTransaction* transaction = new txAttributeAtomTransaction(
172 aPrefix, aLocalName, aLowercaseLocalName, aNsID, aValue);
173 return mBuffer->addTransaction(transaction);
176 nsresult txBufferingHandler::attribute(nsAtom* aPrefix,
177 const nsAString& aLocalName,
178 const int32_t aNsID,
179 const nsString& aValue) {
180 NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
182 if (!mCanAddAttribute) {
183 // XXX ErrorReport: Can't add attributes without element
184 return NS_OK;
187 txOutputTransaction* transaction =
188 new txAttributeTransaction(aPrefix, aLocalName, aNsID, aValue);
189 return mBuffer->addTransaction(transaction);
192 nsresult txBufferingHandler::characters(const nsAString& aData, bool aDOE) {
193 NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
195 mCanAddAttribute = false;
197 txOutputTransaction::txTransactionType type =
198 aDOE ? txOutputTransaction::eCharacterNoOETransaction
199 : txOutputTransaction::eCharacterTransaction;
201 txOutputTransaction* transaction = mBuffer->getLastTransaction();
202 if (transaction && transaction->mType == type) {
203 mBuffer->mStringValue.Append(aData);
204 static_cast<txCharacterTransaction*>(transaction)->mLength +=
205 aData.Length();
206 return NS_OK;
209 transaction = new txCharacterTransaction(type, aData.Length());
210 mBuffer->mStringValue.Append(aData);
211 return mBuffer->addTransaction(transaction);
214 nsresult txBufferingHandler::comment(const nsString& aData) {
215 NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
217 mCanAddAttribute = false;
219 txOutputTransaction* transaction = new txCommentTransaction(aData);
220 return mBuffer->addTransaction(transaction);
223 nsresult txBufferingHandler::endDocument(nsresult aResult) {
224 NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
226 txOutputTransaction* transaction =
227 new txOutputTransaction(txOutputTransaction::eEndDocumentTransaction);
228 return mBuffer->addTransaction(transaction);
231 nsresult txBufferingHandler::endElement() {
232 NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
234 mCanAddAttribute = false;
236 txOutputTransaction* transaction =
237 new txOutputTransaction(txOutputTransaction::eEndElementTransaction);
238 return mBuffer->addTransaction(transaction);
241 nsresult txBufferingHandler::processingInstruction(const nsString& aTarget,
242 const nsString& aData) {
243 NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
245 mCanAddAttribute = false;
247 txOutputTransaction* transaction = new txPITransaction(aTarget, aData);
248 return mBuffer->addTransaction(transaction);
251 nsresult txBufferingHandler::startDocument() {
252 NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
254 txOutputTransaction* transaction =
255 new txOutputTransaction(txOutputTransaction::eStartDocumentTransaction);
256 return mBuffer->addTransaction(transaction);
259 nsresult txBufferingHandler::startElement(nsAtom* aPrefix, nsAtom* aLocalName,
260 nsAtom* aLowercaseLocalName,
261 int32_t aNsID) {
262 NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
264 mCanAddAttribute = true;
266 txOutputTransaction* transaction = new txStartElementAtomTransaction(
267 aPrefix, aLocalName, aLowercaseLocalName, aNsID);
268 return mBuffer->addTransaction(transaction);
271 nsresult txBufferingHandler::startElement(nsAtom* aPrefix,
272 const nsAString& aLocalName,
273 const int32_t aNsID) {
274 NS_ENSURE_TRUE(mBuffer, NS_ERROR_OUT_OF_MEMORY);
276 mCanAddAttribute = true;
278 txOutputTransaction* transaction =
279 new txStartElementTransaction(aPrefix, aLocalName, aNsID);
280 return mBuffer->addTransaction(transaction);
283 txResultBuffer::txResultBuffer() { MOZ_COUNT_CTOR(txResultBuffer); }
285 txResultBuffer::~txResultBuffer() {
286 MOZ_COUNT_DTOR(txResultBuffer);
287 for (uint32_t i = 0, len = mTransactions.Length(); i < len; ++i) {
288 delete mTransactions[i];
292 nsresult txResultBuffer::addTransaction(txOutputTransaction* aTransaction) {
293 // XXX(Bug 1631371) Check if this should use a fallible operation as it
294 // pretended earlier, or change the return type to void.
295 mTransactions.AppendElement(aTransaction);
296 return NS_OK;
299 static nsresult flushTransaction(txOutputTransaction* aTransaction,
300 txAXMLEventHandler* aHandler,
301 nsString::const_char_iterator& aIter) {
302 switch (aTransaction->mType) {
303 case txOutputTransaction::eAttributeAtomTransaction: {
304 txAttributeAtomTransaction* transaction =
305 static_cast<txAttributeAtomTransaction*>(aTransaction);
306 return aHandler->attribute(transaction->mPrefix, transaction->mLocalName,
307 transaction->mLowercaseLocalName,
308 transaction->mNsID, transaction->mValue);
310 case txOutputTransaction::eAttributeTransaction: {
311 txAttributeTransaction* attrTransaction =
312 static_cast<txAttributeTransaction*>(aTransaction);
313 return aHandler->attribute(
314 attrTransaction->mPrefix, attrTransaction->mLocalName,
315 attrTransaction->mNsID, attrTransaction->mValue);
317 case txOutputTransaction::eCharacterTransaction:
318 case txOutputTransaction::eCharacterNoOETransaction: {
319 txCharacterTransaction* charTransaction =
320 static_cast<txCharacterTransaction*>(aTransaction);
321 nsString::const_char_iterator start = aIter;
322 nsString::const_char_iterator end = start + charTransaction->mLength;
323 aIter = end;
324 return aHandler->characters(
325 Substring(start, end),
326 aTransaction->mType ==
327 txOutputTransaction::eCharacterNoOETransaction);
329 case txOutputTransaction::eCommentTransaction: {
330 txCommentTransaction* commentTransaction =
331 static_cast<txCommentTransaction*>(aTransaction);
332 return aHandler->comment(commentTransaction->mValue);
334 case txOutputTransaction::eEndElementTransaction: {
335 return aHandler->endElement();
337 case txOutputTransaction::ePITransaction: {
338 txPITransaction* piTransaction =
339 static_cast<txPITransaction*>(aTransaction);
340 return aHandler->processingInstruction(piTransaction->mTarget,
341 piTransaction->mData);
343 case txOutputTransaction::eStartDocumentTransaction: {
344 return aHandler->startDocument();
346 case txOutputTransaction::eStartElementAtomTransaction: {
347 txStartElementAtomTransaction* transaction =
348 static_cast<txStartElementAtomTransaction*>(aTransaction);
349 return aHandler->startElement(
350 transaction->mPrefix, transaction->mLocalName,
351 transaction->mLowercaseLocalName, transaction->mNsID);
353 case txOutputTransaction::eStartElementTransaction: {
354 txStartElementTransaction* transaction =
355 static_cast<txStartElementTransaction*>(aTransaction);
356 return aHandler->startElement(
357 transaction->mPrefix, transaction->mLocalName, transaction->mNsID);
359 default: {
360 MOZ_ASSERT_UNREACHABLE("Unexpected transaction type");
364 return NS_ERROR_UNEXPECTED;
367 nsresult txResultBuffer::flushToHandler(txAXMLEventHandler* aHandler) {
368 nsString::const_char_iterator iter;
369 mStringValue.BeginReading(iter);
371 for (uint32_t i = 0, len = mTransactions.Length(); i < len; ++i) {
372 nsresult rv = flushTransaction(mTransactions[i], aHandler, iter);
373 NS_ENSURE_SUCCESS(rv, rv);
376 return NS_OK;
379 txOutputTransaction* txResultBuffer::getLastTransaction() {
380 int32_t last = mTransactions.Length() - 1;
381 if (last < 0) {
382 return nullptr;
384 return mTransactions[last];