Merge mozilla-central to autoland. CLOSED TREE
[gecko.git] / xpcom / io / nsUnicharInputStream.cpp
blob1366ab1e34ffc2504f2ddabf230e2bac1b9e99cc
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 "nsUnicharInputStream.h"
8 #include "nsIInputStream.h"
9 #include "nsString.h"
10 #include "nsTArray.h"
11 #include "nsCRT.h"
12 #include "nsStreamUtils.h"
13 #include "nsConverterInputStream.h"
14 #include "mozilla/Attributes.h"
15 #include <fcntl.h>
16 #if defined(XP_WIN)
17 # include <io.h>
18 #else
19 # include <unistd.h>
20 #endif
22 #define STRING_BUFFER_SIZE 8192
24 class StringUnicharInputStream final : public nsIUnicharInputStream {
25 public:
26 explicit StringUnicharInputStream(const nsAString& aString)
27 : mString(aString), mPos(0), mLen(aString.Length()) {}
29 NS_DECL_ISUPPORTS
30 NS_DECL_NSIUNICHARINPUTSTREAM
32 nsString mString;
33 uint32_t mPos;
34 uint32_t mLen;
36 private:
37 ~StringUnicharInputStream() = default;
40 NS_IMETHODIMP
41 StringUnicharInputStream::Read(char16_t* aBuf, uint32_t aCount,
42 uint32_t* aReadCount) {
43 if (mPos >= mLen) {
44 *aReadCount = 0;
45 return NS_OK;
47 nsAString::const_iterator iter;
48 mString.BeginReading(iter);
49 const char16_t* us = iter.get();
50 uint32_t amount = mLen - mPos;
51 if (amount > aCount) {
52 amount = aCount;
54 memcpy(aBuf, us + mPos, sizeof(char16_t) * amount);
55 mPos += amount;
56 *aReadCount = amount;
57 return NS_OK;
60 NS_IMETHODIMP
61 StringUnicharInputStream::ReadSegments(nsWriteUnicharSegmentFun aWriter,
62 void* aClosure, uint32_t aCount,
63 uint32_t* aReadCount) {
64 uint32_t bytesWritten;
65 uint32_t totalBytesWritten = 0;
67 nsresult rv;
68 aCount = XPCOM_MIN<uint32_t>(mString.Length() - mPos, aCount);
70 nsAString::const_iterator iter;
71 mString.BeginReading(iter);
73 while (aCount) {
74 rv = aWriter(this, aClosure, iter.get() + mPos, totalBytesWritten, aCount,
75 &bytesWritten);
77 if (NS_FAILED(rv)) {
78 // don't propagate errors to the caller
79 break;
82 aCount -= bytesWritten;
83 totalBytesWritten += bytesWritten;
84 mPos += bytesWritten;
87 *aReadCount = totalBytesWritten;
89 return NS_OK;
92 NS_IMETHODIMP
93 StringUnicharInputStream::ReadString(uint32_t aCount, nsAString& aString,
94 uint32_t* aReadCount) {
95 if (mPos >= mLen) {
96 *aReadCount = 0;
97 return NS_OK;
99 uint32_t amount = mLen - mPos;
100 if (amount > aCount) {
101 amount = aCount;
103 aString = Substring(mString, mPos, amount);
104 mPos += amount;
105 *aReadCount = amount;
106 return NS_OK;
109 nsresult StringUnicharInputStream::Close() {
110 mPos = mLen;
111 return NS_OK;
114 NS_IMPL_ISUPPORTS(StringUnicharInputStream, nsIUnicharInputStream)
116 //----------------------------------------------------------------------
118 nsresult NS_NewUnicharInputStream(nsIInputStream* aStreamToWrap,
119 nsIUnicharInputStream** aResult) {
120 *aResult = nullptr;
122 // Create converter input stream
123 RefPtr<nsConverterInputStream> it = new nsConverterInputStream();
124 nsresult rv = it->Init(aStreamToWrap, "UTF-8", STRING_BUFFER_SIZE,
125 nsIConverterInputStream::ERRORS_ARE_FATAL);
126 if (NS_FAILED(rv)) {
127 return rv;
130 it.forget(aResult);
131 return NS_OK;