|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "mozilla/dom/TextDecoder.h" |
|
6 #include "mozilla/dom/EncodingUtils.h" |
|
7 #include "nsContentUtils.h" |
|
8 |
|
9 namespace mozilla { |
|
10 namespace dom { |
|
11 |
|
12 static const char16_t kReplacementChar = static_cast<char16_t>(0xFFFD); |
|
13 |
|
14 void |
|
15 TextDecoder::Init(const nsAString& aLabel, const bool aFatal, |
|
16 ErrorResult& aRv) |
|
17 { |
|
18 nsAutoString label(aLabel); |
|
19 EncodingUtils::TrimSpaceCharacters(label); |
|
20 |
|
21 nsAutoCString encoding; |
|
22 // Let encoding be the result of getting an encoding from label. |
|
23 // If encoding is failure or replacement, throw a TypeError. |
|
24 if (!EncodingUtils::FindEncodingForLabel(label, encoding) || |
|
25 encoding.EqualsLiteral("replacement")) { |
|
26 aRv.ThrowTypeError(MSG_ENCODING_NOT_SUPPORTED, &label); |
|
27 return; |
|
28 } |
|
29 InitWithEncoding(encoding, aFatal); |
|
30 } |
|
31 |
|
32 void |
|
33 TextDecoder::InitWithEncoding(const nsACString& aEncoding, const bool aFatal) |
|
34 { |
|
35 mEncoding = aEncoding; |
|
36 // If the constructor is called with an options argument, |
|
37 // and the fatal property of the dictionary is set, |
|
38 // set the internal fatal flag of the decoder object. |
|
39 mFatal = aFatal; |
|
40 |
|
41 // Create a decoder object for mEncoding. |
|
42 mDecoder = EncodingUtils::DecoderForEncoding(mEncoding); |
|
43 |
|
44 if (mFatal) { |
|
45 mDecoder->SetInputErrorBehavior(nsIUnicodeDecoder::kOnError_Signal); |
|
46 } |
|
47 } |
|
48 |
|
49 void |
|
50 TextDecoder::Decode(const char* aInput, const int32_t aLength, |
|
51 const bool aStream, nsAString& aOutDecodedString, |
|
52 ErrorResult& aRv) |
|
53 { |
|
54 aOutDecodedString.Truncate(); |
|
55 |
|
56 // Run or resume the decoder algorithm of the decoder object's encoder. |
|
57 int32_t outLen; |
|
58 nsresult rv = mDecoder->GetMaxLength(aInput, aLength, &outLen); |
|
59 if (NS_FAILED(rv)) { |
|
60 aRv.Throw(rv); |
|
61 return; |
|
62 } |
|
63 // Need a fallible allocator because the caller may be a content |
|
64 // and the content can specify the length of the string. |
|
65 static const fallible_t fallible = fallible_t(); |
|
66 nsAutoArrayPtr<char16_t> buf(new (fallible) char16_t[outLen + 1]); |
|
67 if (!buf) { |
|
68 aRv.Throw(NS_ERROR_OUT_OF_MEMORY); |
|
69 return; |
|
70 } |
|
71 |
|
72 int32_t length = aLength; |
|
73 rv = mDecoder->Convert(aInput, &length, buf, &outLen); |
|
74 MOZ_ASSERT(mFatal || rv != NS_ERROR_ILLEGAL_INPUT); |
|
75 buf[outLen] = 0; |
|
76 aOutDecodedString.Append(buf, outLen); |
|
77 |
|
78 // If the internal streaming flag of the decoder object is not set, |
|
79 // then reset the encoding algorithm state to the default values |
|
80 if (!aStream) { |
|
81 mDecoder->Reset(); |
|
82 if (rv == NS_OK_UDEC_MOREINPUT) { |
|
83 if (mFatal) { |
|
84 aRv.Throw(NS_ERROR_DOM_ENCODING_DECODE_ERR); |
|
85 } else { |
|
86 // Need to emit a decode error manually |
|
87 // to simulate the EOF handling of the Encoding spec. |
|
88 aOutDecodedString.Append(kReplacementChar); |
|
89 } |
|
90 } |
|
91 } |
|
92 |
|
93 if (NS_FAILED(rv)) { |
|
94 aRv.Throw(NS_ERROR_DOM_ENCODING_DECODE_ERR); |
|
95 } |
|
96 } |
|
97 |
|
98 void |
|
99 TextDecoder::GetEncoding(nsAString& aEncoding) |
|
100 { |
|
101 CopyASCIItoUTF16(mEncoding, aEncoding); |
|
102 nsContentUtils::ASCIIToLower(aEncoding); |
|
103 } |
|
104 |
|
105 } // dom |
|
106 } // mozilla |