2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is Mozilla Communicator client code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
|
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
#include "pratom.h"
|
|
|
|
#include "nsIComponentManager.h"
|
|
|
|
#include "nsUCSupport.h"
|
|
|
|
#include "nsUnicodeDecodeHelper.h"
|
|
|
|
#include "nsUnicodeEncodeHelper.h"
|
|
|
|
|
|
|
|
#define DEFAULT_BUFFER_CAPACITY 16
|
|
|
|
|
|
|
|
// XXX review the buffer growth limitation code
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Class nsBasicDecoderSupport [implementation]
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
nsBasicDecoderSupport::nsBasicDecoderSupport()
|
2009-02-16 04:22:47 -08:00
|
|
|
: mErrBehavior(kOnError_Recover)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
nsBasicDecoderSupport::~nsBasicDecoderSupport()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Interface nsISupports [implementation]
|
|
|
|
|
|
|
|
#ifdef NS_DEBUG
|
2009-09-25 10:11:02 -07:00
|
|
|
NS_IMPL_THREADSAFE_ISUPPORTS2(nsBasicDecoderSupport,
|
|
|
|
nsIUnicodeDecoder,
|
|
|
|
nsIBasicDecoder)
|
2007-03-22 10:30:00 -07:00
|
|
|
#else
|
2009-09-25 10:11:02 -07:00
|
|
|
NS_IMPL_THREADSAFE_ISUPPORTS1(nsBasicDecoderSupport, nsIUnicodeDecoder)
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Interface nsIUnicodeDecoder [implementation]
|
|
|
|
|
2009-02-16 04:22:47 -08:00
|
|
|
void
|
|
|
|
nsBasicDecoderSupport::SetInputErrorBehavior(PRInt32 aBehavior)
|
|
|
|
{
|
|
|
|
NS_ABORT_IF_FALSE(aBehavior == kOnError_Recover || aBehavior == kOnError_Signal,
|
|
|
|
"Unknown behavior for SetInputErrorBehavior");
|
|
|
|
mErrBehavior = aBehavior;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUnichar
|
|
|
|
nsBasicDecoderSupport::GetCharacterForUnMapped()
|
|
|
|
{
|
|
|
|
return PRUnichar(0xfffd); // Unicode REPLACEMENT CHARACTER
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Class nsBufferDecoderSupport [implementation]
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
nsBufferDecoderSupport::nsBufferDecoderSupport(PRUint32 aMaxLengthFactor)
|
2007-03-22 10:30:00 -07:00
|
|
|
: nsBasicDecoderSupport(),
|
|
|
|
mMaxLengthFactor(aMaxLengthFactor)
|
|
|
|
{
|
|
|
|
mBufferCapacity = DEFAULT_BUFFER_CAPACITY;
|
|
|
|
mBuffer = new char[mBufferCapacity];
|
|
|
|
|
|
|
|
Reset();
|
|
|
|
}
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
nsBufferDecoderSupport::~nsBufferDecoderSupport()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
delete [] mBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsBufferDecoderSupport::FillBuffer(const char ** aSrc, PRInt32 aSrcLength)
|
|
|
|
{
|
|
|
|
PRInt32 bcr = PR_MIN(mBufferCapacity - mBufferLength, aSrcLength);
|
|
|
|
memcpy(mBuffer + mBufferLength, *aSrc, bcr);
|
|
|
|
mBufferLength += bcr;
|
|
|
|
(*aSrc) += bcr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Subclassing of nsBasicDecoderSupport class [implementation]
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
NS_IMETHODIMP nsBufferDecoderSupport::Convert(const char * aSrc,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRInt32 * aSrcLength,
|
2009-11-17 22:08:22 -08:00
|
|
|
PRUnichar * aDest,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRInt32 * aDestLength)
|
|
|
|
{
|
|
|
|
// we do all operations using pointers internally
|
|
|
|
const char * src = aSrc;
|
|
|
|
const char * srcEnd = aSrc + *aSrcLength;
|
|
|
|
PRUnichar * dest = aDest;
|
|
|
|
PRUnichar * destEnd = aDest + *aDestLength;
|
|
|
|
|
|
|
|
PRInt32 bcr, bcw; // byte counts for read & write;
|
|
|
|
nsresult res = NS_OK;
|
|
|
|
|
|
|
|
// do we have some residual data from the last conversion?
|
2009-11-17 22:08:22 -08:00
|
|
|
if (mBufferLength > 0) {
|
|
|
|
if (dest == destEnd) {
|
|
|
|
res = NS_OK_UDEC_MOREOUTPUT;
|
|
|
|
} else {
|
|
|
|
for (;;) {
|
|
|
|
// we need new data to add to the buffer
|
|
|
|
if (src == srcEnd) {
|
|
|
|
res = NS_OK_UDEC_MOREINPUT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// fill that buffer
|
|
|
|
PRInt32 buffLen = mBufferLength; // initial buffer length
|
|
|
|
FillBuffer(&src, srcEnd - src);
|
|
|
|
|
|
|
|
// convert that buffer
|
|
|
|
bcr = mBufferLength;
|
|
|
|
bcw = destEnd - dest;
|
|
|
|
res = ConvertNoBuff(mBuffer, &bcr, dest, &bcw);
|
|
|
|
dest += bcw;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
// Detect invalid input character
|
|
|
|
if (res == NS_ERROR_ILLEGAL_INPUT && mErrBehavior == kOnError_Signal) {
|
|
|
|
break;
|
|
|
|
}
|
2009-02-16 04:22:47 -08:00
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
if ((res == NS_OK_UDEC_MOREINPUT) && (bcw == 0)) {
|
|
|
|
res = NS_ERROR_UNEXPECTED;
|
2007-03-22 10:30:00 -07:00
|
|
|
#if defined(DEBUG_yokoyama) || defined(DEBUG_ftang)
|
2009-11-17 22:08:22 -08:00
|
|
|
NS_ERROR("This should not happen. Internal buffer may be corrupted.");
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
2009-11-17 22:08:22 -08:00
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
if (bcr < buffLen) {
|
|
|
|
// we didn't convert that residual data - unfill the buffer
|
|
|
|
src -= mBufferLength - buffLen;
|
|
|
|
mBufferLength = buffLen;
|
2007-03-22 10:30:00 -07:00
|
|
|
#if defined(DEBUG_yokoyama) || defined(DEBUG_ftang)
|
2009-11-17 22:08:22 -08:00
|
|
|
NS_ERROR("This should not happen. Internal buffer may be corrupted.");
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
2009-11-17 22:08:22 -08:00
|
|
|
} else {
|
|
|
|
// the buffer and some extra data was converted - unget the rest
|
|
|
|
src -= mBufferLength - bcr;
|
|
|
|
mBufferLength = 0;
|
|
|
|
res = NS_OK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res == NS_OK) {
|
|
|
|
bcr = srcEnd - src;
|
|
|
|
bcw = destEnd - dest;
|
|
|
|
res = ConvertNoBuff(src, &bcr, dest, &bcw);
|
|
|
|
src += bcr;
|
|
|
|
dest += bcw;
|
|
|
|
|
|
|
|
// if we have partial input, store it in our internal buffer.
|
|
|
|
if (res == NS_OK_UDEC_MOREINPUT) {
|
|
|
|
bcr = srcEnd - src;
|
|
|
|
// make sure buffer is large enough
|
|
|
|
if (bcr > mBufferCapacity) {
|
2009-11-17 22:08:22 -08:00
|
|
|
// somehow we got into an error state and the buffer is growing out
|
|
|
|
// of control
|
2007-03-22 10:30:00 -07:00
|
|
|
res = NS_ERROR_UNEXPECTED;
|
|
|
|
} else {
|
|
|
|
FillBuffer(&src, bcr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*aSrcLength -= srcEnd - src;
|
|
|
|
*aDestLength -= destEnd - dest;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsBufferDecoderSupport::Reset()
|
|
|
|
{
|
|
|
|
mBufferLength = 0;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsBufferDecoderSupport::GetMaxLength(const char* aSrc,
|
|
|
|
PRInt32 aSrcLength,
|
|
|
|
PRInt32* aDestLength)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(mMaxLengthFactor != 0, "Must override GetMaxLength!");
|
|
|
|
*aDestLength = aSrcLength * mMaxLengthFactor;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Class nsTableDecoderSupport [implementation]
|
|
|
|
|
|
|
|
nsTableDecoderSupport::nsTableDecoderSupport(uScanClassID aScanClass,
|
|
|
|
uShiftInTable * aShiftInTable,
|
|
|
|
uMappingTable * aMappingTable,
|
2009-11-17 22:08:22 -08:00
|
|
|
PRUint32 aMaxLengthFactor)
|
2007-03-22 10:30:00 -07:00
|
|
|
: nsBufferDecoderSupport(aMaxLengthFactor)
|
|
|
|
{
|
|
|
|
mScanClass = aScanClass;
|
|
|
|
mShiftInTable = aShiftInTable;
|
|
|
|
mMappingTable = aMappingTable;
|
|
|
|
}
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
nsTableDecoderSupport::~nsTableDecoderSupport()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Subclassing of nsBufferDecoderSupport class [implementation]
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
NS_IMETHODIMP nsTableDecoderSupport::ConvertNoBuff(const char * aSrc,
|
|
|
|
PRInt32 * aSrcLength,
|
|
|
|
PRUnichar * aDest,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRInt32 * aDestLength)
|
|
|
|
{
|
|
|
|
return nsUnicodeDecodeHelper::ConvertByTable(aSrc, aSrcLength,
|
|
|
|
aDest, aDestLength,
|
2009-11-17 22:08:22 -08:00
|
|
|
mScanClass,
|
2009-02-16 04:22:47 -08:00
|
|
|
mShiftInTable, mMappingTable,
|
|
|
|
mErrBehavior == kOnError_Signal);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Class nsMultiTableDecoderSupport [implementation]
|
|
|
|
|
|
|
|
nsMultiTableDecoderSupport::nsMultiTableDecoderSupport(
|
|
|
|
PRInt32 aTableCount,
|
2009-11-17 22:08:22 -08:00
|
|
|
const uRange * aRangeArray,
|
2007-03-22 10:30:00 -07:00
|
|
|
uScanClassID * aScanClassArray,
|
|
|
|
uMappingTable ** aMappingTable,
|
2009-11-17 22:08:22 -08:00
|
|
|
PRUint32 aMaxLengthFactor)
|
2007-03-22 10:30:00 -07:00
|
|
|
: nsBufferDecoderSupport(aMaxLengthFactor)
|
|
|
|
{
|
|
|
|
mTableCount = aTableCount;
|
|
|
|
mRangeArray = aRangeArray;
|
|
|
|
mScanClassArray = aScanClassArray;
|
|
|
|
mMappingTable = aMappingTable;
|
|
|
|
}
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
nsMultiTableDecoderSupport::~nsMultiTableDecoderSupport()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Subclassing of nsBufferDecoderSupport class [implementation]
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
NS_IMETHODIMP nsMultiTableDecoderSupport::ConvertNoBuff(const char * aSrc,
|
|
|
|
PRInt32 * aSrcLength,
|
|
|
|
PRUnichar * aDest,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRInt32 * aDestLength)
|
|
|
|
{
|
2009-11-17 22:08:22 -08:00
|
|
|
return nsUnicodeDecodeHelper::ConvertByMultiTable(aSrc, aSrcLength,
|
|
|
|
aDest, aDestLength,
|
2007-03-22 10:30:00 -07:00
|
|
|
mTableCount, mRangeArray,
|
|
|
|
mScanClassArray,
|
2009-02-16 04:22:47 -08:00
|
|
|
mMappingTable,
|
|
|
|
mErrBehavior == kOnError_Signal);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Class nsOneByteDecoderSupport [implementation]
|
|
|
|
|
|
|
|
nsOneByteDecoderSupport::nsOneByteDecoderSupport(
|
2009-11-17 22:08:22 -08:00
|
|
|
uMappingTable * aMappingTable)
|
2009-09-25 10:11:02 -07:00
|
|
|
: nsBasicDecoderSupport()
|
|
|
|
, mMappingTable(aMappingTable)
|
|
|
|
, mFastTableCreated(PR_FALSE)
|
|
|
|
, mFastTableMutex("nsOneByteDecoderSupport mFastTableMutex")
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
nsOneByteDecoderSupport::~nsOneByteDecoderSupport()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Subclassing of nsBasicDecoderSupport class [implementation]
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
NS_IMETHODIMP nsOneByteDecoderSupport::Convert(const char * aSrc,
|
|
|
|
PRInt32 * aSrcLength,
|
|
|
|
PRUnichar * aDest,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRInt32 * aDestLength)
|
|
|
|
{
|
|
|
|
if (!mFastTableCreated) {
|
2009-09-25 10:11:02 -07:00
|
|
|
// Probably better to make this non-lazy and get rid of the mutex
|
|
|
|
mozilla::MutexAutoLock autoLock(mFastTableMutex);
|
|
|
|
if (!mFastTableCreated) {
|
|
|
|
nsresult res = nsUnicodeDecodeHelper::CreateFastTable(
|
|
|
|
mMappingTable, mFastTable, ONE_BYTE_TABLE_SIZE);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
mFastTableCreated = PR_TRUE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
return nsUnicodeDecodeHelper::ConvertByFastTable(aSrc, aSrcLength,
|
|
|
|
aDest, aDestLength,
|
2007-03-22 10:30:00 -07:00
|
|
|
mFastTable,
|
2009-02-16 04:22:47 -08:00
|
|
|
ONE_BYTE_TABLE_SIZE,
|
|
|
|
mErrBehavior == kOnError_Signal);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
NS_IMETHODIMP nsOneByteDecoderSupport::GetMaxLength(const char * aSrc,
|
|
|
|
PRInt32 aSrcLength,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRInt32 * aDestLength)
|
|
|
|
{
|
|
|
|
// single byte to Unicode converter
|
|
|
|
*aDestLength = aSrcLength;
|
|
|
|
return NS_OK_UDEC_EXACTLENGTH;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsOneByteDecoderSupport::Reset()
|
|
|
|
{
|
|
|
|
// nothing to reset, no internal state in this case
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Class nsBasicEncoder [implementation]
|
2009-11-17 22:08:22 -08:00
|
|
|
nsBasicEncoder::nsBasicEncoder()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
nsBasicEncoder::~nsBasicEncoder()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Interface nsISupports [implementation]
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF(nsBasicEncoder)
|
|
|
|
NS_IMPL_RELEASE(nsBasicEncoder)
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
NS_IMPL_QUERY_INTERFACE2(nsBasicEncoder,
|
|
|
|
nsIUnicodeEncoder,
|
2010-07-04 05:42:04 -07:00
|
|
|
nsIBasicEncoder)
|
|
|
|
#else
|
|
|
|
NS_IMPL_QUERY_INTERFACE1(nsBasicEncoder,
|
|
|
|
nsIUnicodeEncoder)
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Class nsEncoderSupport [implementation]
|
|
|
|
|
|
|
|
nsEncoderSupport::nsEncoderSupport(PRUint32 aMaxLengthFactor) :
|
|
|
|
mMaxLengthFactor(aMaxLengthFactor)
|
|
|
|
{
|
|
|
|
mBufferCapacity = DEFAULT_BUFFER_CAPACITY;
|
|
|
|
mBuffer = new char[mBufferCapacity];
|
|
|
|
|
|
|
|
mErrBehavior = kOnError_Signal;
|
|
|
|
mErrChar = 0;
|
|
|
|
|
|
|
|
Reset();
|
|
|
|
}
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
nsEncoderSupport::~nsEncoderSupport()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
delete [] mBuffer;
|
|
|
|
}
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
NS_IMETHODIMP nsEncoderSupport::ConvertNoBuff(const PRUnichar * aSrc,
|
|
|
|
PRInt32 * aSrcLength,
|
|
|
|
char * aDest,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRInt32 * aDestLength)
|
|
|
|
{
|
|
|
|
// we do all operations using pointers internally
|
|
|
|
const PRUnichar * src = aSrc;
|
|
|
|
const PRUnichar * srcEnd = aSrc + *aSrcLength;
|
|
|
|
char * dest = aDest;
|
|
|
|
char * destEnd = aDest + *aDestLength;
|
|
|
|
|
|
|
|
PRInt32 bcr, bcw; // byte counts for read & write;
|
|
|
|
nsresult res;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
bcr = srcEnd - src;
|
|
|
|
bcw = destEnd - dest;
|
|
|
|
res = ConvertNoBuffNoErr(src, &bcr, dest, &bcw);
|
|
|
|
src += bcr;
|
|
|
|
dest += bcw;
|
|
|
|
|
|
|
|
if (res == NS_ERROR_UENC_NOMAPPING) {
|
|
|
|
if (mErrBehavior == kOnError_Replace) {
|
|
|
|
const PRUnichar buff[] = {mErrChar};
|
|
|
|
bcr = 1;
|
|
|
|
bcw = destEnd - dest;
|
|
|
|
src--; // back the input: maybe the guy won't consume consume anything.
|
|
|
|
res = ConvertNoBuffNoErr(buff, &bcr, dest, &bcw);
|
|
|
|
src += bcr;
|
|
|
|
dest += bcw;
|
|
|
|
if (res != NS_OK) break;
|
|
|
|
} else if (mErrBehavior == kOnError_CallBack) {
|
|
|
|
bcw = destEnd - dest;
|
|
|
|
src--;
|
|
|
|
res = mErrEncoder->Convert(*src, dest, &bcw);
|
|
|
|
dest += bcw;
|
|
|
|
// if enought output space then the last char was used
|
|
|
|
if (res != NS_OK_UENC_MOREOUTPUT) src++;
|
|
|
|
if (res != NS_OK) break;
|
|
|
|
} else break;
|
|
|
|
}
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
|
|
|
|
*aSrcLength -= srcEnd - src;
|
|
|
|
*aDestLength -= destEnd - dest;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
NS_IMETHODIMP nsEncoderSupport::FinishNoBuff(char * aDest,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRInt32 * aDestLength)
|
|
|
|
{
|
|
|
|
*aDestLength = 0;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsEncoderSupport::FlushBuffer(char ** aDest, const char * aDestEnd)
|
|
|
|
{
|
|
|
|
PRInt32 bcr, bcw; // byte counts for read & write;
|
|
|
|
nsresult res = NS_OK;
|
|
|
|
char * dest = *aDest;
|
|
|
|
|
|
|
|
if (mBufferStart < mBufferEnd) {
|
|
|
|
bcr = mBufferEnd - mBufferStart;
|
|
|
|
bcw = aDestEnd - dest;
|
|
|
|
if (bcw < bcr) bcr = bcw;
|
|
|
|
memcpy(dest, mBufferStart, bcr);
|
|
|
|
dest += bcr;
|
|
|
|
mBufferStart += bcr;
|
|
|
|
|
|
|
|
if (mBufferStart < mBufferEnd) res = NS_OK_UENC_MOREOUTPUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
*aDest = dest;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Interface nsIUnicodeEncoder [implementation]
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
NS_IMETHODIMP nsEncoderSupport::Convert(const PRUnichar * aSrc,
|
|
|
|
PRInt32 * aSrcLength,
|
|
|
|
char * aDest,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRInt32 * aDestLength)
|
|
|
|
{
|
|
|
|
// we do all operations using pointers internally
|
|
|
|
const PRUnichar * src = aSrc;
|
|
|
|
const PRUnichar * srcEnd = aSrc + *aSrcLength;
|
|
|
|
char * dest = aDest;
|
|
|
|
char * destEnd = aDest + *aDestLength;
|
|
|
|
|
|
|
|
PRInt32 bcr, bcw; // byte counts for read & write;
|
|
|
|
nsresult res;
|
|
|
|
|
|
|
|
res = FlushBuffer(&dest, destEnd);
|
|
|
|
if (res == NS_OK_UENC_MOREOUTPUT) goto final;
|
|
|
|
|
|
|
|
bcr = srcEnd - src;
|
|
|
|
bcw = destEnd - dest;
|
|
|
|
res = ConvertNoBuff(src, &bcr, dest, &bcw);
|
|
|
|
src += bcr;
|
|
|
|
dest += bcw;
|
|
|
|
if ((res == NS_OK_UENC_MOREOUTPUT) && (dest < destEnd)) {
|
|
|
|
// convert exactly one character into the internal buffer
|
|
|
|
// at this point, there should be at least a char in the input
|
|
|
|
for (;;) {
|
|
|
|
bcr = 1;
|
|
|
|
bcw = mBufferCapacity;
|
|
|
|
res = ConvertNoBuff(src, &bcr, mBuffer, &bcw);
|
|
|
|
|
|
|
|
if (res == NS_OK_UENC_MOREOUTPUT) {
|
|
|
|
delete [] mBuffer;
|
|
|
|
mBufferCapacity *= 2;
|
|
|
|
mBuffer = new char [mBufferCapacity];
|
|
|
|
} else {
|
|
|
|
src += bcr;
|
|
|
|
mBufferStart = mBufferEnd = mBuffer;
|
|
|
|
mBufferEnd += bcw;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res = FlushBuffer(&dest, destEnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
final:
|
|
|
|
*aSrcLength -= srcEnd - src;
|
|
|
|
*aDestLength -= destEnd - dest;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsEncoderSupport::Finish(char * aDest, PRInt32 * aDestLength)
|
|
|
|
{
|
|
|
|
// we do all operations using pointers internally
|
|
|
|
char * dest = aDest;
|
|
|
|
char * destEnd = aDest + *aDestLength;
|
|
|
|
|
|
|
|
PRInt32 bcw; // byte count for write;
|
|
|
|
nsresult res;
|
|
|
|
|
|
|
|
res = FlushBuffer(&dest, destEnd);
|
|
|
|
if (res == NS_OK_UENC_MOREOUTPUT) goto final;
|
|
|
|
|
|
|
|
// do the finish into the internal buffer.
|
|
|
|
for (;;) {
|
|
|
|
bcw = mBufferCapacity;
|
|
|
|
res = FinishNoBuff(mBuffer, &bcw);
|
|
|
|
|
|
|
|
if (res == NS_OK_UENC_MOREOUTPUT) {
|
|
|
|
delete [] mBuffer;
|
|
|
|
mBufferCapacity *= 2;
|
|
|
|
mBuffer = new char [mBufferCapacity];
|
|
|
|
} else {
|
|
|
|
mBufferStart = mBufferEnd = mBuffer;
|
|
|
|
mBufferEnd += bcw;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res = FlushBuffer(&dest, destEnd);
|
|
|
|
|
|
|
|
final:
|
|
|
|
*aDestLength -= destEnd - dest;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsEncoderSupport::Reset()
|
|
|
|
{
|
|
|
|
mBufferStart = mBufferEnd = mBuffer;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsEncoderSupport::SetOutputErrorBehavior(
|
2009-11-17 22:08:22 -08:00
|
|
|
PRInt32 aBehavior,
|
|
|
|
nsIUnicharEncoder * aEncoder,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRUnichar aChar)
|
|
|
|
{
|
2009-11-17 22:08:22 -08:00
|
|
|
if (aBehavior == kOnError_CallBack && aEncoder == nsnull)
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
mErrEncoder = aEncoder;
|
|
|
|
mErrBehavior = aBehavior;
|
|
|
|
mErrChar = aChar;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2009-11-17 22:08:22 -08:00
|
|
|
nsEncoderSupport::GetMaxLength(const PRUnichar * aSrc,
|
|
|
|
PRInt32 aSrcLength,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRInt32 * aDestLength)
|
|
|
|
{
|
|
|
|
*aDestLength = aSrcLength * mMaxLengthFactor;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Class nsTableEncoderSupport [implementation]
|
|
|
|
|
|
|
|
nsTableEncoderSupport::nsTableEncoderSupport(uScanClassID aScanClass,
|
|
|
|
uShiftOutTable * aShiftOutTable,
|
|
|
|
uMappingTable * aMappingTable,
|
2009-11-17 22:08:22 -08:00
|
|
|
PRUint32 aMaxLengthFactor)
|
2007-03-22 10:30:00 -07:00
|
|
|
: nsEncoderSupport(aMaxLengthFactor)
|
|
|
|
{
|
|
|
|
mScanClass = aScanClass;
|
|
|
|
mShiftOutTable = aShiftOutTable,
|
|
|
|
mMappingTable = aMappingTable;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsTableEncoderSupport::nsTableEncoderSupport(uScanClassID aScanClass,
|
|
|
|
uMappingTable * aMappingTable,
|
2009-11-17 22:08:22 -08:00
|
|
|
PRUint32 aMaxLengthFactor)
|
2007-03-22 10:30:00 -07:00
|
|
|
: nsEncoderSupport(aMaxLengthFactor)
|
|
|
|
{
|
|
|
|
mScanClass = aScanClass;
|
|
|
|
mShiftOutTable = nsnull;
|
|
|
|
mMappingTable = aMappingTable;
|
|
|
|
}
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
nsTableEncoderSupport::~nsTableEncoderSupport()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Subclassing of nsEncoderSupport class [implementation]
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsTableEncoderSupport::ConvertNoBuffNoErr(
|
2009-11-17 22:08:22 -08:00
|
|
|
const PRUnichar * aSrc,
|
|
|
|
PRInt32 * aSrcLength,
|
|
|
|
char * aDest,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRInt32 * aDestLength)
|
|
|
|
{
|
2009-11-17 22:08:22 -08:00
|
|
|
return nsUnicodeEncodeHelper::ConvertByTable(aSrc, aSrcLength,
|
|
|
|
aDest, aDestLength,
|
2007-03-22 10:30:00 -07:00
|
|
|
mScanClass,
|
|
|
|
mShiftOutTable, mMappingTable);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Class nsMultiTableEncoderSupport [implementation]
|
|
|
|
|
|
|
|
nsMultiTableEncoderSupport::nsMultiTableEncoderSupport(
|
|
|
|
PRInt32 aTableCount,
|
|
|
|
uScanClassID * aScanClassArray,
|
2009-11-17 22:08:22 -08:00
|
|
|
uShiftOutTable ** aShiftOutTable,
|
2007-03-22 10:30:00 -07:00
|
|
|
uMappingTable ** aMappingTable,
|
2009-11-17 22:08:22 -08:00
|
|
|
PRUint32 aMaxLengthFactor)
|
2007-03-22 10:30:00 -07:00
|
|
|
: nsEncoderSupport(aMaxLengthFactor)
|
|
|
|
{
|
|
|
|
mTableCount = aTableCount;
|
|
|
|
mScanClassArray = aScanClassArray;
|
|
|
|
mShiftOutTable = aShiftOutTable;
|
|
|
|
mMappingTable = aMappingTable;
|
|
|
|
}
|
|
|
|
|
2009-11-17 22:08:22 -08:00
|
|
|
nsMultiTableEncoderSupport::~nsMultiTableEncoderSupport()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Subclassing of nsEncoderSupport class [implementation]
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsMultiTableEncoderSupport::ConvertNoBuffNoErr(
|
2009-11-17 22:08:22 -08:00
|
|
|
const PRUnichar * aSrc,
|
|
|
|
PRInt32 * aSrcLength,
|
|
|
|
char * aDest,
|
2007-03-22 10:30:00 -07:00
|
|
|
PRInt32 * aDestLength)
|
|
|
|
{
|
|
|
|
return nsUnicodeEncodeHelper::ConvertByMultiTable(aSrc, aSrcLength,
|
2009-11-17 22:08:22 -08:00
|
|
|
aDest, aDestLength,
|
|
|
|
mTableCount,
|
2007-03-22 10:30:00 -07:00
|
|
|
mScanClassArray,
|
2009-11-17 22:08:22 -08:00
|
|
|
mShiftOutTable,
|
2007-03-22 10:30:00 -07:00
|
|
|
mMappingTable);
|
|
|
|
}
|