Bug 1833854 - Part 7: Add the FOR_EACH_GC_TUNABLE macro to describe tunable GC parame...
[gecko.git] / dom / encoding / TextDecoder.cpp
blobde49bd0122c351c58deccfe4cc16c309d7d18c18
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 "mozilla/dom/TextDecoder.h"
8 #include "mozilla/dom/UnionTypes.h"
9 #include "mozilla/Encoding.h"
10 #include "mozilla/UniquePtrExtensions.h"
11 #include "nsContentUtils.h"
13 #include <stdint.h>
15 namespace mozilla::dom {
17 void TextDecoder::Init(const nsAString& aLabel,
18 const TextDecoderOptions& aOptions, ErrorResult& aRv) {
19 // Let encoding be the result of getting an encoding from label.
20 // If encoding is failure or replacement, throw a RangeError
21 // (https://encoding.spec.whatwg.org/#dom-textdecoder).
22 const Encoding* encoding = Encoding::ForLabelNoReplacement(aLabel);
23 if (!encoding) {
24 NS_ConvertUTF16toUTF8 label(aLabel);
25 label.Trim(" \t\n\f\r");
26 aRv.ThrowRangeError<MSG_ENCODING_NOT_SUPPORTED>(label);
27 return;
29 InitWithEncoding(WrapNotNull(encoding), aOptions);
32 void TextDecoder::InitWithEncoding(NotNull<const Encoding*> aEncoding,
33 const TextDecoderOptions& aOptions) {
34 aEncoding->Name(mEncoding);
35 // Store the flags passed via our options dictionary.
36 mFatal = aOptions.mFatal;
37 mIgnoreBOM = aOptions.mIgnoreBOM;
39 // Create a decoder object for mEncoding.
40 if (mIgnoreBOM) {
41 mDecoder = aEncoding->NewDecoderWithoutBOMHandling();
42 } else {
43 mDecoder = aEncoding->NewDecoderWithBOMRemoval();
47 void TextDecoderCommon::DecodeNative(Span<const uint8_t> aInput,
48 const bool aStream,
49 nsAString& aOutDecodedString,
50 ErrorResult& aRv) {
51 aOutDecodedString.Truncate();
53 CheckedInt<nsAString::size_type> needed =
54 mDecoder->MaxUTF16BufferLength(aInput.Length());
55 if (!needed.isValid()) {
56 aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
57 return;
60 auto output = aOutDecodedString.GetMutableData(needed.value(), fallible);
61 if (!output) {
62 aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
63 return;
66 uint32_t result;
67 size_t read;
68 size_t written;
69 if (mFatal) {
70 std::tie(result, read, written) =
71 mDecoder->DecodeToUTF16WithoutReplacement(aInput, *output, !aStream);
72 if (result != kInputEmpty) {
73 aRv.ThrowTypeError<MSG_DOM_DECODING_FAILED>();
74 return;
76 } else {
77 std::tie(result, read, written, std::ignore) =
78 mDecoder->DecodeToUTF16(aInput, *output, !aStream);
80 MOZ_ASSERT(result == kInputEmpty);
81 MOZ_ASSERT(read == aInput.Length());
82 MOZ_ASSERT(written <= aOutDecodedString.Length());
84 if (!aOutDecodedString.SetLength(written, fallible)) {
85 aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
86 return;
89 // If the internal streaming flag of the decoder object is not set,
90 // then reset the encoding algorithm state to the default values
91 if (!aStream) {
92 if (mIgnoreBOM) {
93 mDecoder->Encoding()->NewDecoderWithoutBOMHandlingInto(*mDecoder);
94 } else {
95 mDecoder->Encoding()->NewDecoderWithBOMRemovalInto(*mDecoder);
100 void TextDecoder::Decode(const Optional<ArrayBufferViewOrArrayBuffer>& aBuffer,
101 const TextDecodeOptions& aOptions,
102 nsAString& aOutDecodedString, ErrorResult& aRv) {
103 if (!aBuffer.WasPassed()) {
104 DecodeNative(nullptr, aOptions.mStream, aOutDecodedString, aRv);
105 return;
107 const ArrayBufferViewOrArrayBuffer& buf = aBuffer.Value();
108 uint8_t* data;
109 uint32_t length;
110 if (buf.IsArrayBufferView()) {
111 buf.GetAsArrayBufferView().ComputeState();
112 data = buf.GetAsArrayBufferView().Data();
113 length = buf.GetAsArrayBufferView().Length();
114 } else {
115 MOZ_ASSERT(buf.IsArrayBuffer());
116 buf.GetAsArrayBuffer().ComputeState();
117 data = buf.GetAsArrayBuffer().Data();
118 length = buf.GetAsArrayBuffer().Length();
120 DecodeNative(Span(data, length), aOptions.mStream, aOutDecodedString, aRv);
123 void TextDecoderCommon::GetEncoding(nsAString& aEncoding) {
124 CopyASCIItoUTF16(mEncoding, aEncoding);
125 nsContentUtils::ASCIIToLower(aEncoding);
128 } // namespace mozilla::dom