|
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/TextEncoder.h" |
|
6 #include "mozilla/dom/EncodingUtils.h" |
|
7 #include "nsContentUtils.h" |
|
8 |
|
9 namespace mozilla { |
|
10 namespace dom { |
|
11 |
|
12 void |
|
13 TextEncoder::Init(const nsAString& aEncoding, ErrorResult& aRv) |
|
14 { |
|
15 nsAutoString label(aEncoding); |
|
16 EncodingUtils::TrimSpaceCharacters(label); |
|
17 |
|
18 // Let encoding be the result of getting an encoding from label. |
|
19 // If encoding is failure, or is none of utf-8, utf-16, and utf-16be, |
|
20 // throw a TypeError. |
|
21 if (!EncodingUtils::FindEncodingForLabel(label, mEncoding)) { |
|
22 aRv.ThrowTypeError(MSG_ENCODING_NOT_SUPPORTED, &label); |
|
23 return; |
|
24 } |
|
25 |
|
26 if (!mEncoding.EqualsLiteral("UTF-8") && |
|
27 !mEncoding.EqualsLiteral("UTF-16LE") && |
|
28 !mEncoding.EqualsLiteral("UTF-16BE")) { |
|
29 aRv.ThrowTypeError(MSG_DOM_ENCODING_NOT_UTF); |
|
30 return; |
|
31 } |
|
32 |
|
33 // Create an encoder object for mEncoding. |
|
34 mEncoder = EncodingUtils::EncoderForEncoding(mEncoding); |
|
35 } |
|
36 |
|
37 void |
|
38 TextEncoder::Encode(JSContext* aCx, |
|
39 JS::Handle<JSObject*> aObj, |
|
40 const nsAString& aString, |
|
41 const bool aStream, |
|
42 JS::MutableHandle<JSObject*> aRetval, |
|
43 ErrorResult& aRv) |
|
44 { |
|
45 // Run the steps of the encoding algorithm. |
|
46 int32_t srcLen = aString.Length(); |
|
47 int32_t maxLen; |
|
48 const char16_t* data = PromiseFlatString(aString).get(); |
|
49 nsresult rv = mEncoder->GetMaxLength(data, srcLen, &maxLen); |
|
50 if (NS_FAILED(rv)) { |
|
51 aRv.Throw(rv); |
|
52 return; |
|
53 } |
|
54 // Need a fallible allocator because the caller may be a content |
|
55 // and the content can specify the length of the string. |
|
56 static const fallible_t fallible = fallible_t(); |
|
57 nsAutoArrayPtr<char> buf(new (fallible) char[maxLen + 1]); |
|
58 if (!buf) { |
|
59 aRv.Throw(NS_ERROR_OUT_OF_MEMORY); |
|
60 return; |
|
61 } |
|
62 |
|
63 int32_t dstLen = maxLen; |
|
64 rv = mEncoder->Convert(data, &srcLen, buf, &dstLen); |
|
65 |
|
66 // If the internal streaming flag is not set, then reset |
|
67 // the encoding algorithm state to the default values for encoding. |
|
68 if (!aStream) { |
|
69 int32_t finishLen = maxLen - dstLen; |
|
70 rv = mEncoder->Finish(buf + dstLen, &finishLen); |
|
71 if (NS_SUCCEEDED(rv)) { |
|
72 dstLen += finishLen; |
|
73 } |
|
74 } |
|
75 |
|
76 JSObject* outView = nullptr; |
|
77 if (NS_SUCCEEDED(rv)) { |
|
78 buf[dstLen] = '\0'; |
|
79 JSAutoCompartment ac(aCx, aObj); |
|
80 outView = Uint8Array::Create(aCx, dstLen, |
|
81 reinterpret_cast<uint8_t*>(buf.get())); |
|
82 if (!outView) { |
|
83 aRv.Throw(NS_ERROR_OUT_OF_MEMORY); |
|
84 return; |
|
85 } |
|
86 } |
|
87 |
|
88 if (NS_FAILED(rv)) { |
|
89 aRv.Throw(rv); |
|
90 } |
|
91 aRetval.set(outView); |
|
92 } |
|
93 |
|
94 void |
|
95 TextEncoder::GetEncoding(nsAString& aEncoding) |
|
96 { |
|
97 CopyASCIItoUTF16(mEncoding, aEncoding); |
|
98 nsContentUtils::ASCIIToLower(aEncoding); |
|
99 } |
|
100 |
|
101 } // dom |
|
102 } // mozilla |