Fix typo in 9b54bd30006c008b4a951331b273613d5bac3abf
[pm.git] / intl / uconv / nsConverterOutputStream.cpp
blobdae3624a960f07e65311a9cf86f289bc0e2f331b
1 /* vim:set expandtab ts=4 sw=4 sts=4 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/. */
6 #include "nsCOMPtr.h"
8 #include "nsIOutputStream.h"
9 #include "nsString.h"
11 #include "nsConverterOutputStream.h"
12 #include "nsIUnicodeEncoder.h"
13 #include "mozilla/dom/EncodingUtils.h"
15 using mozilla::dom::EncodingUtils;
17 NS_IMPL_ISUPPORTS(nsConverterOutputStream,
18 nsIUnicharOutputStream,
19 nsIConverterOutputStream)
21 nsConverterOutputStream::~nsConverterOutputStream()
23 Close();
26 NS_IMETHODIMP
27 nsConverterOutputStream::Init(nsIOutputStream* aOutStream,
28 const char* aCharset,
29 uint32_t aBufferSize /* ignored */,
30 char16_t aReplacementChar)
32 NS_PRECONDITION(aOutStream, "Null output stream!");
34 nsAutoCString label;
35 if (!aCharset) {
36 label.AssignLiteral("UTF-8");
37 } else {
38 label = aCharset;
41 nsAutoCString encoding;
42 if (label.EqualsLiteral("UTF-16")) {
43 // Make sure to output a BOM when UTF-16 requested
44 encoding.Assign(label);
45 } else if (!EncodingUtils::FindEncodingForLabelNoReplacement(label,
46 encoding)) {
47 return NS_ERROR_UCONV_NOCONV;
49 mConverter = EncodingUtils::EncoderForEncoding(encoding);
51 mOutStream = aOutStream;
53 int32_t behaviour = aReplacementChar ? nsIUnicodeEncoder::kOnError_Replace
54 : nsIUnicodeEncoder::kOnError_Signal;
55 return mConverter->
56 SetOutputErrorBehavior(behaviour,
57 nullptr,
58 aReplacementChar);
61 NS_IMETHODIMP
62 nsConverterOutputStream::Write(uint32_t aCount, const char16_t* aChars,
63 bool* aSuccess)
65 if (!mOutStream) {
66 NS_ASSERTION(!mConverter, "Closed streams shouldn't have converters");
67 return NS_BASE_STREAM_CLOSED;
69 NS_ASSERTION(mConverter, "Must have a converter when not closed");
71 int32_t inLen = aCount;
73 int32_t maxLen;
74 nsresult rv = mConverter->GetMaxLength(aChars, inLen, &maxLen);
75 NS_ENSURE_SUCCESS(rv, rv);
77 nsAutoCString buf;
78 buf.SetLength(maxLen);
79 if (buf.Length() != (uint32_t) maxLen)
80 return NS_ERROR_OUT_OF_MEMORY;
82 int32_t outLen = maxLen;
83 rv = mConverter->Convert(aChars, &inLen, buf.BeginWriting(), &outLen);
84 if (NS_FAILED(rv))
85 return rv;
86 if (rv == NS_ERROR_UENC_NOMAPPING) {
87 // Yes, NS_ERROR_UENC_NOMAPPING is a success code
88 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
90 NS_ASSERTION((uint32_t) inLen == aCount,
91 "Converter didn't consume all the data!");
93 uint32_t written;
94 rv = mOutStream->Write(buf.get(), outLen, &written);
95 *aSuccess = NS_SUCCEEDED(rv) && written == uint32_t(outLen);
96 return rv;
100 NS_IMETHODIMP
101 nsConverterOutputStream::WriteString(const nsAString& aString, bool* aSuccess)
103 int32_t inLen = aString.Length();
104 nsAString::const_iterator i;
105 aString.BeginReading(i);
106 return Write(inLen, i.get(), aSuccess);
109 NS_IMETHODIMP
110 nsConverterOutputStream::Flush()
112 if (!mOutStream)
113 return NS_OK; // Already closed.
115 char buf[1024];
116 int32_t size = sizeof(buf);
117 nsresult rv = mConverter->Finish(buf, &size);
118 NS_ASSERTION(rv != NS_OK_UENC_MOREOUTPUT,
119 "1024 bytes ought to be enough for everyone");
120 if (NS_FAILED(rv))
121 return rv;
122 if (size == 0)
123 return NS_OK;
125 uint32_t written;
126 rv = mOutStream->Write(buf, size, &written);
127 if (NS_FAILED(rv)) {
128 NS_WARNING("Flush() lost data!");
129 return rv;
131 if (written != uint32_t(size)) {
132 NS_WARNING("Flush() lost data!");
133 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
135 return rv;
138 NS_IMETHODIMP
139 nsConverterOutputStream::Close()
141 if (!mOutStream)
142 return NS_OK; // Already closed.
144 nsresult rv1 = Flush();
146 nsresult rv2 = mOutStream->Close();
147 mOutStream = nullptr;
148 mConverter = nullptr;
149 return NS_FAILED(rv1) ? rv1 : rv2;