Bug 486080 - Remove nsIByteBuffer and nsIUnicharBuffer. r=bsmedberg

This commit is contained in:
Michael Harrison 2013-08-20 11:03:50 +00:00
parent 48f3ff5a82
commit 50b6d60cb1
14 changed files with 96 additions and 483 deletions

View File

@ -8,6 +8,7 @@
#include "nsICharsetConverterManager.h"
#include "nsIServiceManager.h"
#include "nsReadLine.h"
#include "nsStreamUtils.h"
#include <algorithm>
#define CONVERTER_BUFFER_SIZE 8192
@ -39,11 +40,10 @@ nsConverterInputStream::Init(nsIInputStream* aStream,
if (NS_FAILED(rv)) return rv;
// set up our buffers
rv = NS_NewByteBuffer(getter_AddRefs(mByteData), nullptr, aBufferSize);
if (NS_FAILED(rv)) return rv;
rv = NS_NewUnicharBuffer(getter_AddRefs(mUnicharData), nullptr, aBufferSize);
if (NS_FAILED(rv)) return rv;
if (!mByteData.SetCapacity(aBufferSize) ||
!mUnicharData.SetCapacity(aBufferSize)) {
return NS_ERROR_OUT_OF_MEMORY;
}
mInput = aStream;
mReplacementChar = aReplacementChar;
@ -62,8 +62,8 @@ nsConverterInputStream::Close()
mLineBuffer = nullptr;
mInput = nullptr;
mConverter = nullptr;
mByteData = nullptr;
mUnicharData = nullptr;
mByteData.Clear();
mUnicharData.Clear();
return rv;
}
@ -85,7 +85,7 @@ nsConverterInputStream::Read(PRUnichar* aBuf,
if (readCount > aCount) {
readCount = aCount;
}
memcpy(aBuf, mUnicharData->GetBuffer() + mUnicharDataOffset,
memcpy(aBuf, mUnicharData.Elements() + mUnicharDataOffset,
readCount * sizeof(PRUnichar));
mUnicharDataOffset += readCount;
*aReadCount = readCount;
@ -117,7 +117,7 @@ nsConverterInputStream::ReadSegments(nsWriteUnicharSegmentFun aWriter,
while (bytesToWrite) {
rv = aWriter(this, aClosure,
mUnicharData->GetBuffer() + mUnicharDataOffset,
mUnicharData.Elements() + mUnicharDataOffset,
totalBytesWritten, bytesToWrite, &bytesWritten);
if (NS_FAILED(rv)) {
// don't propagate errors to the caller
@ -152,8 +152,7 @@ nsConverterInputStream::ReadString(uint32_t aCount, nsAString& aString,
if (readCount > aCount) {
readCount = aCount;
}
const PRUnichar* buf = reinterpret_cast<const PRUnichar*>(mUnicharData->GetBuffer() +
mUnicharDataOffset);
const PRUnichar* buf = mUnicharData.Elements() + mUnicharDataOffset;
aString.Assign(buf, readCount);
mUnicharDataOffset += readCount;
*aReadCount = readCount;
@ -182,32 +181,27 @@ nsConverterInputStream::Fill(nsresult * aErrorCode)
// to n+1 unicode chars. Thus we need to keep track of the leftover
// bytes as we convert.
int32_t nb = mByteData->Fill(aErrorCode, mInput, mLeftOverBytes);
#if defined(DEBUG_bzbarsky) && 0
for (unsigned int foo = 0; foo < mByteData->GetLength(); ++foo) {
fprintf(stderr, "%c", mByteData->GetBuffer()[foo]);
}
fprintf(stderr, "\n");
#endif
if (nb <= 0 && mLeftOverBytes == 0) {
uint32_t nb;
*aErrorCode = NS_FillArray(mByteData, mInput, mLeftOverBytes, &nb);
if (nb == 0 && mLeftOverBytes == 0) {
// No more data
*aErrorCode = NS_OK;
return 0;
}
NS_ASSERTION(uint32_t(nb) + mLeftOverBytes == mByteData->GetLength(),
NS_ASSERTION(uint32_t(nb) + mLeftOverBytes == mByteData.Length(),
"mByteData is lying to us somewhere");
// Now convert as much of the byte buffer to unicode as possible
mUnicharDataOffset = 0;
mUnicharDataLength = 0;
uint32_t srcConsumed = 0;
do {
int32_t srcLen = mByteData->GetLength() - srcConsumed;
int32_t dstLen = mUnicharData->GetBufferSize() - mUnicharDataLength;
*aErrorCode = mConverter->Convert(mByteData->GetBuffer()+srcConsumed,
int32_t srcLen = mByteData.Length() - srcConsumed;
int32_t dstLen = mUnicharData.Capacity() - mUnicharDataLength;
*aErrorCode = mConverter->Convert(mByteData.Elements()+srcConsumed,
&srcLen,
mUnicharData->GetBuffer()+mUnicharDataLength,
mUnicharData.Elements()+mUnicharDataLength,
&dstLen);
mUnicharDataLength += dstLen;
// XXX if srcLen is negative, we want to drop the _first_ byte in
@ -215,23 +209,23 @@ nsConverterInputStream::Fill(nsresult * aErrorCode)
// possible right now -- see bug 160784
srcConsumed += srcLen;
if (NS_FAILED(*aErrorCode) && mReplacementChar) {
NS_ASSERTION(0 < mUnicharData->GetBufferSize() - mUnicharDataLength,
NS_ASSERTION(0 < mUnicharData.Capacity() - mUnicharDataLength,
"Decoder returned an error but filled the output buffer! "
"Should not happen.");
mUnicharData->GetBuffer()[mUnicharDataLength++] = mReplacementChar;
mUnicharData.Elements()[mUnicharDataLength++] = mReplacementChar;
++srcConsumed;
// XXX this is needed to make sure we don't underrun our buffer;
// bug 160784 again
srcConsumed = std::max<uint32_t>(srcConsumed, 0);
mConverter->Reset();
}
NS_ASSERTION(srcConsumed <= mByteData->GetLength(),
NS_ASSERTION(srcConsumed <= mByteData.Length(),
"Whoa. The converter should have returned NS_OK_UDEC_MOREINPUT before this point!");
} while (mReplacementChar &&
NS_FAILED(*aErrorCode) &&
uint32_t(mUnicharData->GetBufferSize()) > mUnicharDataLength);
mUnicharData.Capacity() > mUnicharDataLength);
mLeftOverBytes = mByteData->GetLength() - srcConsumed;
mLeftOverBytes = mByteData.Length() - srcConsumed;
return mUnicharDataLength;
}

View File

@ -7,12 +7,10 @@
#include "nsIConverterInputStream.h"
#include "nsIUnicharLineInputStream.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsIUnicodeDecoder.h"
#include "nsIByteBuffer.h"
#include "nsIUnicharBuffer.h"
#include "nsReadLine.h"
#define NS_CONVERTERINPUTSTREAM_CONTRACTID "@mozilla.org/intl/converter-input-stream;1"
@ -49,8 +47,8 @@ class nsConverterInputStream : public nsIConverterInputStream,
uint32_t Fill(nsresult *aErrorCode);
nsCOMPtr<nsIUnicodeDecoder> mConverter;
nsCOMPtr<nsIByteBuffer> mByteData;
nsCOMPtr<nsIUnicharBuffer> mUnicharData;
FallibleTArray<char> mByteData;
FallibleTArray<PRUnichar> mUnicharData;
nsCOMPtr<nsIInputStream> mInput;
nsresult mLastErrorCode;

View File

@ -4,7 +4,6 @@
COMPONENT(CATEGORYMANAGER, nsCategoryManager::Create)
COMPONENT(BYTEBUFFER, ByteBufferImpl::Create)
COMPONENT(SCRIPTABLEINPUTSTREAM, nsScriptableInputStream::Create)
COMPONENT(BINARYINPUTSTREAM, nsBinaryInputStreamConstructor)
COMPONENT(BINARYOUTPUTSTREAM, nsBinaryOutputStreamConstructor)

View File

@ -31,7 +31,6 @@
#include "nsDebugImpl.h"
#include "nsTraceRefcntImpl.h"
#include "nsErrorService.h"
#include "nsByteBuffer.h"
#include "nsSupportsArray.h"
#include "nsArray.h"

View File

@ -55,8 +55,6 @@ EXPORTS += [
'nsExpirationTracker.h',
'nsHashPropertyBag.h',
'nsHashtable.h',
'nsIByteBuffer.h',
'nsIUnicharBuffer.h',
'nsMathUtils.h',
'nsObserverList.h',
'nsObserverService.h',
@ -79,7 +77,6 @@ CPP_SOURCES += [
'nsArray.cpp',
'nsAtomService.cpp',
'nsAtomTable.cpp',
'nsByteBuffer.cpp',
'nsCRT.cpp',
'nsHashPropertyBag.cpp',
'nsHashtable.cpp',
@ -93,7 +90,6 @@ CPP_SOURCES += [
'nsSupportsArray.cpp',
'nsSupportsArrayEnumerator.cpp',
'nsSupportsPrimitives.cpp',
'nsUnicharBuffer.cpp',
'nsVariant.cpp',
'TimeStamp.cpp',
]

View File

@ -1,130 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsByteBuffer.h"
#include "nsIInputStream.h"
#include "nsCRT.h"
#include "nsAutoPtr.h"
#define MIN_BUFFER_SIZE 32
ByteBufferImpl::ByteBufferImpl(void)
: mBuffer(NULL), mSpace(0), mLength(0)
{
}
NS_IMETHODIMP
ByteBufferImpl::Init(uint32_t aBufferSize)
{
if (aBufferSize < MIN_BUFFER_SIZE) {
aBufferSize = MIN_BUFFER_SIZE;
}
mSpace = aBufferSize;
mLength = 0;
mBuffer = new char[aBufferSize];
return NS_OK;
}
NS_IMPL_ISUPPORTS1(ByteBufferImpl,nsIByteBuffer)
ByteBufferImpl::~ByteBufferImpl()
{
if (nullptr != mBuffer) {
delete[] mBuffer;
mBuffer = nullptr;
}
mLength = 0;
}
nsresult
ByteBufferImpl::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
if (aOuter)
return NS_ERROR_NO_AGGREGATION;
nsRefPtr<ByteBufferImpl> it = new ByteBufferImpl();
return it->QueryInterface(aIID, (void**)aResult);
}
NS_IMETHODIMP_(uint32_t)
ByteBufferImpl::GetLength(void) const
{
return mLength;
}
NS_IMETHODIMP_(uint32_t)
ByteBufferImpl::GetBufferSize(void) const
{
return mSpace;
}
NS_IMETHODIMP_(char*)
ByteBufferImpl::GetBuffer(void) const
{
return mBuffer;
}
NS_IMETHODIMP_(bool)
ByteBufferImpl::Grow(uint32_t aNewSize)
{
if (aNewSize < MIN_BUFFER_SIZE) {
aNewSize = MIN_BUFFER_SIZE;
}
char* newbuf = new char[aNewSize];
if (0 != mLength) {
memcpy(newbuf, mBuffer, mLength);
}
delete[] mBuffer;
mBuffer = newbuf;
return true;
}
NS_IMETHODIMP_(int32_t)
ByteBufferImpl::Fill(nsresult* aErrorCode, nsIInputStream* aStream,
uint32_t aKeep)
{
NS_PRECONDITION(nullptr != aStream, "null stream");
NS_PRECONDITION(aKeep <= mLength, "illegal keep count");
if ((nullptr == aStream) || (uint32_t(aKeep) > uint32_t(mLength))) {
// whoops
*aErrorCode = NS_BASE_STREAM_ILLEGAL_ARGS;
return -1;
}
if (0 != aKeep) {
// Slide over kept data
memmove(mBuffer, mBuffer + (mLength - aKeep), aKeep);
}
// Read in some new data
mLength = aKeep;
uint32_t nb;
*aErrorCode = aStream->Read(mBuffer + aKeep, mSpace - aKeep, &nb);
if (NS_SUCCEEDED(*aErrorCode)) {
mLength += nb;
}
else
nb = 0;
return nb;
}
nsresult NS_NewByteBuffer(nsIByteBuffer** aInstancePtrResult,
nsISupports* aOuter,
uint32_t aBufferSize)
{
nsresult rv;
nsIByteBuffer* buf;
rv = ByteBufferImpl::Create(aOuter, NS_GET_IID(nsIByteBuffer), (void**)&buf);
if (NS_FAILED(rv)) return rv;
rv = buf->Init(aBufferSize);
if (NS_FAILED(rv)) {
NS_RELEASE(buf);
return rv;
}
*aInstancePtrResult = buf;
return rv;
}

View File

@ -1,37 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsByteBuffer_h__
#define nsByteBuffer_h__
#include "mozilla/Attributes.h"
#include "nsIByteBuffer.h"
class ByteBufferImpl MOZ_FINAL : public nsIByteBuffer {
public:
ByteBufferImpl(void);
NS_DECL_ISUPPORTS
static nsresult
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
NS_IMETHOD Init(uint32_t aBufferSize);
NS_IMETHOD_(uint32_t) GetLength(void) const;
NS_IMETHOD_(uint32_t) GetBufferSize(void) const;
NS_IMETHOD_(char*) GetBuffer() const;
NS_IMETHOD_(bool) Grow(uint32_t aNewSize);
NS_IMETHOD_(int32_t) Fill(nsresult* aErrorCode, nsIInputStream* aStream,
uint32_t aKeep);
char* mBuffer;
uint32_t mSpace;
uint32_t mLength;
private:
~ByteBufferImpl();
};
#endif // nsByteBuffer_h__

View File

@ -1,64 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsIByteBuffer_h___
#define nsIByteBuffer_h___
#include "nscore.h"
#include "nsISupports.h"
class nsIInputStream;
#define NS_IBYTE_BUFFER_IID \
{ 0xe4a6e4b0, 0x93b4, 0x11d1, \
{0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} }
#define NS_IBYTEBUFFER_IID \
{ 0xe4a6e4b0, 0x93b4, 0x11d1, \
{0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} }
#define NS_BYTEBUFFER_CONTRACTID "@mozilla.org/byte-buffer;1"
/** Interface to a buffer that holds bytes */
class nsIByteBuffer : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IBYTEBUFFER_IID)
NS_IMETHOD Init(uint32_t aBufferSize) = 0;
/** @return length of buffer, i.e. how many bytes are currently in it. */
NS_IMETHOD_(uint32_t) GetLength(void) const = 0;
/** @return number of bytes allocated in the buffer */
NS_IMETHOD_(uint32_t) GetBufferSize(void) const = 0;
/** @return the buffer */
NS_IMETHOD_(char*) GetBuffer(void) const = 0;
/** Grow buffer to aNewSize bytes. */
NS_IMETHOD_(bool) Grow(uint32_t aNewSize) = 0;
/** Fill the buffer with data from aStream. Don't grow the buffer, only
* read until length of buffer equals buffer size. */
NS_IMETHOD_(int32_t) Fill(nsresult* aErrorCode, nsIInputStream* aStream,
uint32_t aKeep) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIByteBuffer, NS_IBYTEBUFFER_IID)
#define NS_BYTEBUFFER_CID \
{ /* a49d5280-0d6b-11d3-9331-00104ba0fd40 */ \
0xa49d5280, \
0x0d6b, \
0x11d3, \
{0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
}
/** Create a new byte buffer using the given buffer size. */
extern nsresult
NS_NewByteBuffer(nsIByteBuffer** aInstancePtrResult,
nsISupports* aOuter,
uint32_t aBufferSize = 0);
#endif /* nsIByteBuffer_h___ */

View File

@ -1,43 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsIUnicharBuffer_h___
#define nsIUnicharBuffer_h___
#include "nscore.h"
#include "nsISupports.h"
#define NS_IUNICHARBUFFER_IID \
{ 0x14cf6970, 0x93b5, 0x11d1, \
{0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} }
/// Interface to a buffer that holds unicode characters
class nsIUnicharBuffer : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IUNICHARBUFFER_IID)
NS_IMETHOD Init(uint32_t aBufferSize) = 0;
NS_IMETHOD_(int32_t) GetLength() const = 0;
NS_IMETHOD_(int32_t) GetBufferSize() const = 0;
NS_IMETHOD_(PRUnichar*) GetBuffer() const = 0;
NS_IMETHOD_(bool) Grow(int32_t aNewSize) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIUnicharBuffer, NS_IUNICHARBUFFER_IID)
/// Factory method for nsIUnicharBuffer.
extern nsresult
NS_NewUnicharBuffer(nsIUnicharBuffer** aInstancePtrResult,
nsISupports* aOuter,
uint32_t aBufferSize = 0);
#define NS_UNICHARBUFFER_CID \
{ /* c81fd8f0-0d6b-11d3-9331-00104ba0fd40 */ \
0xc81fd8f0, \
0x0d6b, \
0x11d3, \
{0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
}
#endif /* nsIUnicharBuffer_h___ */

View File

@ -1,104 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsUnicharBuffer.h"
#include "nsCRT.h"
#include "nsAutoPtr.h"
#define MIN_BUFFER_SIZE 32
UnicharBufferImpl::UnicharBufferImpl()
: mBuffer(NULL), mSpace(0), mLength(0)
{
}
NS_METHOD
UnicharBufferImpl::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
if (aOuter)
return NS_ERROR_NO_AGGREGATION;
nsRefPtr<UnicharBufferImpl> it = new UnicharBufferImpl();
return it->QueryInterface(aIID, aResult);
}
NS_IMETHODIMP
UnicharBufferImpl::Init(uint32_t aBufferSize)
{
if (aBufferSize < MIN_BUFFER_SIZE) {
aBufferSize = MIN_BUFFER_SIZE;
}
mSpace = aBufferSize;
mLength = 0;
mBuffer = new PRUnichar[aBufferSize];
return NS_OK;
}
NS_IMPL_ISUPPORTS1(UnicharBufferImpl, nsIUnicharBuffer)
UnicharBufferImpl::~UnicharBufferImpl()
{
if (nullptr != mBuffer) {
delete[] mBuffer;
mBuffer = nullptr;
}
mLength = 0;
}
NS_IMETHODIMP_(int32_t)
UnicharBufferImpl::GetLength() const
{
return mLength;
}
NS_IMETHODIMP_(int32_t)
UnicharBufferImpl::GetBufferSize() const
{
return mSpace;
}
NS_IMETHODIMP_(PRUnichar*)
UnicharBufferImpl::GetBuffer() const
{
return mBuffer;
}
NS_IMETHODIMP_(bool)
UnicharBufferImpl::Grow(int32_t aNewSize)
{
if (uint32_t(aNewSize) < MIN_BUFFER_SIZE) {
aNewSize = MIN_BUFFER_SIZE;
}
PRUnichar* newbuf = new PRUnichar[aNewSize];
if (nullptr != newbuf) {
if (0 != mLength) {
memcpy(newbuf, mBuffer, mLength * sizeof(PRUnichar));
}
delete[] mBuffer;
mBuffer = newbuf;
return true;
}
return false;
}
nsresult
NS_NewUnicharBuffer(nsIUnicharBuffer** aInstancePtrResult,
nsISupports* aOuter,
uint32_t aBufferSize)
{
nsresult rv;
nsIUnicharBuffer* buf;
rv = UnicharBufferImpl::Create(aOuter, NS_GET_IID(nsIUnicharBuffer),
(void**)&buf);
if (NS_FAILED(rv)) return rv;
rv = buf->Init(aBufferSize);
if (NS_FAILED(rv)) {
NS_RELEASE(buf);
return rv;
}
*aInstancePtrResult = buf;
return rv;
}

View File

@ -1,34 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsUnicharBuffer_h__
#define nsUnicharBuffer_h__
#include "nsIUnicharBuffer.h"
#include "mozilla/Attributes.h"
class UnicharBufferImpl MOZ_FINAL : public nsIUnicharBuffer {
public:
UnicharBufferImpl();
static NS_METHOD
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
NS_DECL_ISUPPORTS
NS_IMETHOD Init(uint32_t aBufferSize);
NS_IMETHOD_(int32_t) GetLength() const;
NS_IMETHOD_(int32_t) GetBufferSize() const;
NS_IMETHOD_(PRUnichar*) GetBuffer() const;
NS_IMETHOD_(bool) Grow(int32_t aNewSize);
PRUnichar* mBuffer;
uint32_t mSpace;
uint32_t mLength;
private:
~UnicharBufferImpl();
};
#endif // nsUnicharBuffer_h__

View File

@ -773,3 +773,29 @@ NS_WriteSegmentThunk(nsIInputStream *inStr,
return thunk->mFun(thunk->mStream, thunk->mClosure, buffer, offset, count,
countWritten);
}
NS_METHOD
NS_FillArray(FallibleTArray<char>& aDest, nsIInputStream *aInput,
uint32_t aKeep, uint32_t *aNewBytes)
{
MOZ_ASSERT(aInput, "null stream");
MOZ_ASSERT(aKeep <= aDest.Length(), "illegal keep count");
char* aBuffer = aDest.Elements();
int64_t keepOffset = int64_t(aDest.Length()) - aKeep;
if (0 != aKeep && keepOffset > 0) {
memmove(aBuffer, aBuffer + keepOffset, aKeep);
}
nsresult rv =
aInput->Read(aBuffer + aKeep, aDest.Capacity() - aKeep, aNewBytes);
if (NS_FAILED(rv)) {
*aNewBytes = 0;
}
// NOTE: we rely on the fact that the new slots are NOT initialized by
// SetLength here, see nsTArrayElementTraits::Construct() in nsTArray.h:
aDest.SetLength(aKeep + *aNewBytes);
MOZ_ASSERT(aDest.Length() <= aDest.Capacity(), "buffer overflow");
return rv;
}

View File

@ -8,6 +8,7 @@
#include "nsCOMPtr.h"
#include "nsStringFwd.h"
#include "nsIInputStream.h"
#include "nsTArray.h"
class nsIOutputStream;
class nsIInputStreamCallback;
@ -232,4 +233,21 @@ struct nsWriteSegmentThunk {
void *mClosure;
};
/**
* Read data from aInput and store in aDest. A non-zero aKeep will keep that
* many bytes from aDest (from the end). New data is appended after the kept
* bytes (if any). aDest's new length on returning from this function is
* aKeep + aNewBytes and is guaranteed to be less than or equal to aDest's
* current capacity.
* @param aDest the array to fill
* @param aInput the stream to read from
* @param aKeep number of bytes to keep (0 <= aKeep <= aDest.Length())
* @param aNewBytes (out) number of bytes read from aInput or zero if Read()
* failed
* @return the result from aInput->Read(...)
*/
extern NS_METHOD
NS_FillArray(FallibleTArray<char> &aDest, nsIInputStream *aInput,
uint32_t aKeep, uint32_t *aNewBytes);
#endif // !nsStreamUtils_h__

View File

@ -5,12 +5,12 @@
#include "nsUnicharInputStream.h"
#include "nsIInputStream.h"
#include "nsIByteBuffer.h"
#include "nsIUnicharBuffer.h"
#include "nsIServiceManager.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsAutoPtr.h"
#include "nsCRT.h"
#include "nsStreamUtils.h"
#include "nsUTF8Utils.h"
#include "mozilla/Attributes.h"
#include <fcntl.h>
@ -138,8 +138,8 @@ protected:
static void CountValidUTF8Bytes(const char *aBuf, uint32_t aMaxBytes, uint32_t& aValidUTF8bytes, uint32_t& aValidUTF16CodeUnits);
nsCOMPtr<nsIInputStream> mInput;
nsCOMPtr<nsIByteBuffer> mByteData;
nsCOMPtr<nsIUnicharBuffer> mUnicharData;
FallibleTArray<char> mByteData;
FallibleTArray<PRUnichar> mUnicharData;
uint32_t mByteDataOffset;
uint32_t mUnicharDataOffset;
@ -156,13 +156,10 @@ UTF8InputStream::UTF8InputStream() :
nsresult
UTF8InputStream::Init(nsIInputStream* aStream)
{
nsresult rv = NS_NewByteBuffer(getter_AddRefs(mByteData), nullptr,
STRING_BUFFER_SIZE);
if (NS_FAILED(rv)) return rv;
rv = NS_NewUnicharBuffer(getter_AddRefs(mUnicharData), nullptr,
STRING_BUFFER_SIZE);
if (NS_FAILED(rv)) return rv;
if (!mByteData.SetCapacity(STRING_BUFFER_SIZE) ||
!mUnicharData.SetCapacity(STRING_BUFFER_SIZE)) {
return NS_ERROR_OUT_OF_MEMORY;
}
mInput = aStream;
return NS_OK;
@ -178,9 +175,8 @@ UTF8InputStream::~UTF8InputStream()
nsresult UTF8InputStream::Close()
{
mInput = nullptr;
mByteData = nullptr;
mUnicharData = nullptr;
mByteData.Clear();
mUnicharData.Clear();
return NS_OK;
}
@ -203,7 +199,7 @@ nsresult UTF8InputStream::Read(PRUnichar* aBuf,
if (readCount > aCount) {
readCount = aCount;
}
memcpy(aBuf, mUnicharData->GetBuffer() + mUnicharDataOffset,
memcpy(aBuf, mUnicharData.Elements() + mUnicharDataOffset,
readCount * sizeof(PRUnichar));
mUnicharDataOffset += readCount;
*aReadCount = readCount;
@ -236,7 +232,7 @@ UTF8InputStream::ReadSegments(nsWriteUnicharSegmentFun aWriter,
while (bytesToWrite) {
rv = aWriter(this, aClosure,
mUnicharData->GetBuffer() + mUnicharDataOffset,
mUnicharData.Elements() + mUnicharDataOffset,
totalBytesWritten, bytesToWrite, &bytesWritten);
if (NS_FAILED(rv)) {
@ -273,8 +269,7 @@ UTF8InputStream::ReadString(uint32_t aCount, nsAString& aString,
if (readCount > aCount) {
readCount = aCount;
}
const PRUnichar* buf = reinterpret_cast<const PRUnichar*>(mUnicharData->GetBuffer() +
mUnicharDataOffset);
const PRUnichar* buf = mUnicharData.Elements() + mUnicharDataOffset;
aString.Assign(buf, readCount);
mUnicharDataOffset += readCount;
@ -282,7 +277,6 @@ UTF8InputStream::ReadString(uint32_t aCount, nsAString& aString,
return NS_OK;
}
int32_t UTF8InputStream::Fill(nsresult * aErrorCode)
{
if (nullptr == mInput) {
@ -291,11 +285,12 @@ int32_t UTF8InputStream::Fill(nsresult * aErrorCode)
return -1;
}
NS_ASSERTION(mByteData->GetLength() >= mByteDataOffset, "unsigned madness");
uint32_t remainder = mByteData->GetLength() - mByteDataOffset;
NS_ASSERTION(mByteData.Length() >= mByteDataOffset, "unsigned madness");
uint32_t remainder = mByteData.Length() - mByteDataOffset;
mByteDataOffset = remainder;
int32_t nb = mByteData->Fill(aErrorCode, mInput, remainder);
if (nb <= 0) {
uint32_t nb;
*aErrorCode = NS_FillArray(mByteData, mInput, remainder, &nb);
if (nb == 0) {
// Because we assume a many to one conversion, the lingering data
// in the byte buffer must be a partial conversion
// fragment. Because we know that we have received no more new
@ -303,23 +298,23 @@ int32_t UTF8InputStream::Fill(nsresult * aErrorCode)
// it.
return nb;
}
NS_ASSERTION(remainder + nb == mByteData->GetLength(), "bad nb");
NS_ASSERTION(remainder + nb == mByteData.Length(), "bad nb");
// Now convert as much of the byte buffer to unicode as possible
uint32_t srcLen, dstLen;
CountValidUTF8Bytes(mByteData->GetBuffer(),remainder + nb, srcLen, dstLen);
CountValidUTF8Bytes(mByteData.Elements(),remainder + nb, srcLen, dstLen);
// the number of UCS2 characters should always be <= the number of
// UTF8 chars
NS_ASSERTION( (remainder+nb >= srcLen), "cannot be longer than out buffer");
NS_ASSERTION(int32_t(dstLen) <= mUnicharData->GetBufferSize(),
NS_ASSERTION(dstLen <= mUnicharData.Capacity(),
"Ouch. I would overflow my buffer if I wasn't so careful.");
if (int32_t(dstLen) > mUnicharData->GetBufferSize()) return 0;
if (dstLen > mUnicharData.Capacity()) return 0;
ConvertUTF8toUTF16 converter(mUnicharData->GetBuffer());
ConvertUTF8toUTF16 converter(mUnicharData.Elements());
nsASingleFragmentCString::const_char_iterator start = mByteData->GetBuffer();
nsASingleFragmentCString::const_char_iterator end = mByteData->GetBuffer() + srcLen;
nsASingleFragmentCString::const_char_iterator start = mByteData.Elements();
nsASingleFragmentCString::const_char_iterator end = mByteData.Elements() + srcLen;
copy_string(start, end, converter);
if (converter.Length() != dstLen) {