/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #include "nsIUnicharBuffer.h" #include "nsIUnicharInputStream.h" #include "nsCRT.h" #define MIN_BUFFER_SIZE 32 class UnicharBufferImpl : public nsIUnicharBuffer { public: UnicharBufferImpl(PRInt32 aBufferSize); ~UnicharBufferImpl(); NS_DECL_ISUPPORTS virtual PRInt32 GetLength() const; virtual PRInt32 GetBufferSize() const; virtual PRUnichar* GetBuffer() const; virtual PRBool Grow(PRInt32 aNewSize); virtual PRInt32 Fill(nsresult* aErrorCode, nsIUnicharInputStream* aStream, PRInt32 aKeep); PRUnichar* mBuffer; PRInt32 mSpace; PRInt32 mLength; }; UnicharBufferImpl::UnicharBufferImpl(PRInt32 aBufferSize) { if (PRUint32(aBufferSize) < MIN_BUFFER_SIZE) { aBufferSize = MIN_BUFFER_SIZE; } mSpace = aBufferSize; mBuffer = new PRUnichar[aBufferSize]; mLength = 0; NS_INIT_REFCNT(); } NS_DEFINE_IID(kUnicharBufferIID, NS_IUNICHAR_BUFFER_IID); NS_IMPL_ISUPPORTS(UnicharBufferImpl,kUnicharBufferIID) UnicharBufferImpl::~UnicharBufferImpl() { if (nsnull != mBuffer) { delete mBuffer; mBuffer = nsnull; } mLength = 0; } PRInt32 UnicharBufferImpl::GetLength() const { return mLength; } PRInt32 UnicharBufferImpl::GetBufferSize() const { return mSpace; } PRUnichar* UnicharBufferImpl::GetBuffer() const { return mBuffer; } PRBool UnicharBufferImpl::Grow(PRInt32 aNewSize) { if (PRUint32(aNewSize) < MIN_BUFFER_SIZE) { aNewSize = MIN_BUFFER_SIZE; } PRUnichar* newbuf = new PRUnichar[aNewSize]; if (nsnull != newbuf) { if (0 != mLength) { nsCRT::memcpy(newbuf, mBuffer, mLength * sizeof(PRUnichar)); } delete mBuffer; mBuffer = newbuf; return PR_TRUE; } return PR_FALSE; } PRInt32 UnicharBufferImpl::Fill(nsresult* aErrorCode, nsIUnicharInputStream* aStream, PRInt32 aKeep) { NS_PRECONDITION(nsnull != aStream, "null stream"); NS_PRECONDITION(PRUint32(aKeep) < PRUint32(mLength), "illegal keep count"); if ((nsnull == aStream) || (PRUint32(aKeep) >= PRUint32(mLength))) { // whoops *aErrorCode = NS_BASE_STREAM_ILLEGAL_ARGS; return -1; } if (0 != aKeep) { // Slide over kept data nsCRT::memmove(mBuffer, mBuffer + (mLength - aKeep), aKeep * sizeof(PRUnichar)); } // Read in some new data mLength = aKeep; PRInt32 amount = mSpace - aKeep; PRInt32 nb; *aErrorCode = aStream->Read(mBuffer, aKeep, amount, &nb); if (NS_SUCCEEDED(*aErrorCode)) { mLength += nb; } else nb = 0; return nb; } NS_BASE nsresult NS_NewUnicharBuffer(nsIUnicharBuffer** aInstancePtrResult, nsISupports* aOuter, PRInt32 aBufferSize) { if (nsnull != aOuter) { return NS_ERROR_NO_AGGREGATION; } UnicharBufferImpl* it = new UnicharBufferImpl(aBufferSize); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } return it->QueryInterface(kUnicharBufferIID, (void **) aInstancePtrResult); }