1 /* vim:set expandtab ts=4 sw=2 sts=2 cin: */
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/. */
7 #include "nsIOutputStream.h"
9 #include "nsConverterOutputStream.h"
10 #include "mozilla/Encoding.h"
12 using namespace mozilla
;
14 NS_IMPL_ISUPPORTS(nsConverterOutputStream
, nsIUnicharOutputStream
,
15 nsIConverterOutputStream
)
17 nsConverterOutputStream::~nsConverterOutputStream() { Close(); }
20 nsConverterOutputStream::Init(nsIOutputStream
* aOutStream
,
21 const char* aCharset
) {
22 MOZ_ASSERT(aOutStream
, "Null output stream!");
24 const Encoding
* encoding
;
26 encoding
= UTF_8_ENCODING
;
28 encoding
= Encoding::ForLabelNoReplacement(MakeStringSpan(aCharset
));
29 if (!encoding
|| encoding
== UTF_16LE_ENCODING
||
30 encoding
== UTF_16BE_ENCODING
) {
31 return NS_ERROR_UCONV_NOCONV
;
35 mConverter
= encoding
->NewEncoder();
37 mOutStream
= aOutStream
;
43 nsConverterOutputStream::Write(uint32_t aCount
, const char16_t
* aChars
,
46 NS_ASSERTION(!mConverter
, "Closed streams shouldn't have converters");
47 return NS_BASE_STREAM_CLOSED
;
49 MOZ_ASSERT(mConverter
, "Must have a converter when not closed");
51 auto dst
= Span(buffer
);
52 auto src
= Span(aChars
, aCount
);
57 std::tie(result
, read
, written
, std::ignore
) =
58 mConverter
->EncodeFromUTF16(src
, dst
, false);
60 uint32_t streamWritten
;
61 nsresult rv
= mOutStream
->Write(reinterpret_cast<char*>(dst
.Elements()),
62 written
, &streamWritten
);
63 *aSuccess
= NS_SUCCEEDED(rv
) && written
== streamWritten
;
67 if (result
== kInputEmpty
) {
74 nsConverterOutputStream::WriteString(const nsAString
& aString
, bool* aSuccess
) {
75 int32_t inLen
= aString
.Length();
76 nsAString::const_iterator i
;
77 aString
.BeginReading(i
);
78 return Write(inLen
, i
.get(), aSuccess
);
82 nsConverterOutputStream::Flush() {
83 if (!mOutStream
) return NS_OK
; // Already closed.
85 // If we are encoding to ISO-2022-JP, potentially
86 // transition back to the ASCII state. The buffer
87 // needs to be large enough for an additional NCR,
90 auto dst
= Span(buffer
);
91 Span
<char16_t
> src(nullptr);
94 std::tie(result
, std::ignore
, written
, std::ignore
) =
95 mConverter
->EncodeFromUTF16(src
, dst
, true);
96 MOZ_ASSERT(result
== kInputEmpty
);
97 uint32_t streamWritten
;
101 return mOutStream
->Write(reinterpret_cast<char*>(dst
.Elements()), written
,
106 nsConverterOutputStream::Close() {
107 if (!mOutStream
) return NS_OK
; // Already closed.
109 nsresult rv1
= Flush();
111 nsresult rv2
= mOutStream
->Close();
112 mOutStream
= nullptr;
113 mConverter
= nullptr;
114 return NS_FAILED(rv1
) ? rv1
: rv2
;