From 4e6377cb52ec43a6bcee613b15f2943129845d06 Mon Sep 17 00:00:00 2001 From: "cata%netscape.com" Date: Tue, 23 Mar 1999 22:05:39 +0000 Subject: [PATCH] Improved support classes. git-svn-id: svn://10.0.0.236/trunk@24894 18797224-902f-48f8-a5cc-f745e15eee43 --- .../intl/uconv/ucvlatin/nsLatin1ToUnicode.cpp | 72 ++--- .../intl/uconv/ucvlatin/nsLatin1ToUnicode.h | 35 +-- mozilla/intl/uconv/ucvlatin/nsUCvLatinDll.cpp | 1 + .../intl/uconv/ucvlatin/nsUCvLatinSupport.cpp | 259 +++++++++++++++++- .../intl/uconv/ucvlatin/nsUCvLatinSupport.h | 138 +++++++++- 5 files changed, 415 insertions(+), 90 deletions(-) diff --git a/mozilla/intl/uconv/ucvlatin/nsLatin1ToUnicode.cpp b/mozilla/intl/uconv/ucvlatin/nsLatin1ToUnicode.cpp index 44608cbfd2e..55165802afe 100644 --- a/mozilla/intl/uconv/ucvlatin/nsLatin1ToUnicode.cpp +++ b/mozilla/intl/uconv/ucvlatin/nsLatin1ToUnicode.cpp @@ -17,25 +17,27 @@ * Netscape Communications Corporation. All Rights Reserved. */ -#include "pratom.h" #include "nsLatin1ToUnicode.h" -#include "nsUCvLatinCID.h" -#include "nsUCvLatinDll.h" + +//---------------------------------------------------------------------- +// Global functions and data [declaration] + +static PRUint16 g_Latin1MappingTable[] = { +#include "8859-1.ut" +}; + +static PRInt16 g_Latin1ShiftTable[] = { + 1, u1ByteCharset , + ShiftCell(0,0,0,0,0,0,0,0) +}; //---------------------------------------------------------------------- // Class nsLatin1ToUnicode [implementation] -NS_IMPL_ISUPPORTS(nsLatin1ToUnicode, kIUnicodeDecoderIID); - nsLatin1ToUnicode::nsLatin1ToUnicode() +: nsTableDecoderSupport((uShiftTable*) &g_Latin1ShiftTable, + (uMappingTable*) &g_Latin1MappingTable) { - NS_INIT_REFCNT(); - PR_AtomicIncrement(&g_InstanceCount); -} - -nsLatin1ToUnicode::~nsLatin1ToUnicode() -{ - PR_AtomicDecrement(&g_InstanceCount); } nsresult nsLatin1ToUnicode::CreateInstance(nsISupports ** aResult) @@ -45,38 +47,7 @@ nsresult nsLatin1ToUnicode::CreateInstance(nsISupports ** aResult) } //---------------------------------------------------------------------- -// Interface nsICharsetConverter [implementation] - -NS_IMETHODIMP nsLatin1ToUnicode::Convert(PRUnichar * aDest, - PRInt32 aDestOffset, - PRInt32 * aDestLength, - const char * aSrc, - PRInt32 aSrcOffset, - PRInt32 * aSrcLength) -{ - // XXX hello, this isn't ASCII! So do a table-driven mapping for Latin1 - - aSrc += aSrcOffset; - aDest += aDestOffset; - PRInt32 len = PR_MIN(*aSrcLength, *aDestLength); - const char * srcEnd = aSrc+len; - - for (;aSrc len)? NS_PARTIAL_MORE_OUTPUT : NS_OK; - *aSrcLength = *aDestLength = len; - - return res; -} - -NS_IMETHODIMP nsLatin1ToUnicode::Finish(PRUnichar * aDest, - PRInt32 aDestOffset, - PRInt32 * aDestLength) -{ - // it is really only a stateless converter... - *aDestLength = 0; - return NS_OK; -} +// Subclassing of nsTableDecoderSupport class [implementation] NS_IMETHODIMP nsLatin1ToUnicode::Length(const char * aSrc, PRInt32 aSrcOffset, @@ -85,16 +56,5 @@ NS_IMETHODIMP nsLatin1ToUnicode::Length(const char * aSrc, { // we are a single byte to Unicode converter, so... *aDestLength = aSrcLength; - return NS_EXACT_LENGTH; -} - -NS_IMETHODIMP nsLatin1ToUnicode::Reset() -{ - return NS_OK; -} - -NS_IMETHODIMP nsLatin1ToUnicode::SetInputErrorBehavior(PRInt32 aBehavior) -{ - // no input error possible, this encoding is too simple - return NS_OK; + return NS_OK_UDEC_EXACTLENGTH; } diff --git a/mozilla/intl/uconv/ucvlatin/nsLatin1ToUnicode.h b/mozilla/intl/uconv/ucvlatin/nsLatin1ToUnicode.h index 383bff5637a..96516fdd12e 100644 --- a/mozilla/intl/uconv/ucvlatin/nsLatin1ToUnicode.h +++ b/mozilla/intl/uconv/ucvlatin/nsLatin1ToUnicode.h @@ -20,10 +20,7 @@ #ifndef nsLatin1ToUnicode_h___ #define nsLatin1ToUnicode_h___ -#include "nsIUnicodeDecoder.h" - -//---------------------------------------------------------------------- -// Class nsLatin1ToUnicodeFactory [declaration] +#include "nsUCvLatinSupport.h" //---------------------------------------------------------------------- // Class nsLatin1ToUnicode [declaration] @@ -31,20 +28,11 @@ /** * A character set converter from Latin1 to Unicode. * - * This particular converter does not use the general single-byte converter - * helper object. That is because someone may want to optimise this converter - * to the fullest, as it is one of the most heavily used. - * - * Multithreading: not an issue, the object has one instance per user thread. - * As a plus, it is also stateless! - * * @created 23/Nov/1998 * @author Catalin Rotaru [CATA] */ -class nsLatin1ToUnicode : public nsIUnicodeDecoder +class nsLatin1ToUnicode : public nsTableDecoderSupport { - NS_DECL_ISUPPORTS - public: /** @@ -52,28 +40,19 @@ public: */ nsLatin1ToUnicode(); - /** - * Class destructor. - */ - virtual ~nsLatin1ToUnicode(); - /** * Static class constructor. */ static nsresult CreateInstance(nsISupports **aResult); - //-------------------------------------------------------------------- - // Interface nsIUnicodeDecoder [declaration] +protected: + + //-------------------------------------------------------------------- + // Subclassing of nsDecoderSupport class [declaration] - NS_IMETHOD Convert(PRUnichar * aDest, PRInt32 aDestOffset, - PRInt32 * aDestLength,const char * aSrc, PRInt32 aSrcOffset, - PRInt32 * aSrcLength); - NS_IMETHOD Finish(PRUnichar * aDest, PRInt32 aDestOffset, - PRInt32 * aDestLength); NS_IMETHOD Length(const char * aSrc, PRInt32 aSrcOffset, PRInt32 aSrcLength, PRInt32 * aDestLength); - NS_IMETHOD Reset(); - NS_IMETHOD SetInputErrorBehavior(PRInt32 aBehavior); + }; #endif /* nsLatin1ToUnicode_h___ */ diff --git a/mozilla/intl/uconv/ucvlatin/nsUCvLatinDll.cpp b/mozilla/intl/uconv/ucvlatin/nsUCvLatinDll.cpp index 7ff937a8dfa..8479d85691f 100644 --- a/mozilla/intl/uconv/ucvlatin/nsUCvLatinDll.cpp +++ b/mozilla/intl/uconv/ucvlatin/nsUCvLatinDll.cpp @@ -36,6 +36,7 @@ // just for NS_IMPL_IDS; this is a good, central place to implement GUIDs #include "nsIUnicodeDecoder.h" #include "nsIUnicodeDecodeUtil.h" +#include "nsIUnicodeDecodeHelper.h" #include "nsIUnicodeEncoder.h" #include "nsIUnicodeEncodeHelper.h" #include "nsICharsetConverterManager.h" diff --git a/mozilla/intl/uconv/ucvlatin/nsUCvLatinSupport.cpp b/mozilla/intl/uconv/ucvlatin/nsUCvLatinSupport.cpp index 8f927f0c8d6..4ef06653296 100644 --- a/mozilla/intl/uconv/ucvlatin/nsUCvLatinSupport.cpp +++ b/mozilla/intl/uconv/ucvlatin/nsUCvLatinSupport.cpp @@ -22,12 +22,14 @@ #include "nsUCvLatinSupport.h" #include "nsUCvLatinDll.h" +#define DEFAULT_BUFFER_CAPACITY 16 + //---------------------------------------------------------------------- // Class nsEncoderSupport [implementation] nsEncoderSupport::nsEncoderSupport() { - mBufferCapacity = 16; + mBufferCapacity = DEFAULT_BUFFER_CAPACITY; mBuffer = new char[mBufferCapacity]; mErrBehavior = kOnError_Signal; @@ -102,8 +104,7 @@ NS_IMETHODIMP nsEncoderSupport::FinishNoBuff(char * aDest, return NS_OK; } -NS_IMETHODIMP nsEncoderSupport::FlushBuffer(char ** aDest, - const char * aDestEnd) +nsresult nsEncoderSupport::FlushBuffer(char ** aDest, const char * aDestEnd) { PRInt32 bcr, bcw; // byte counts for read & write; nsresult res = NS_OK; @@ -131,7 +132,7 @@ NS_IMPL_ADDREF(nsEncoderSupport); NS_IMPL_RELEASE(nsEncoderSupport); nsresult nsEncoderSupport::QueryInterface(REFNSIID aIID, - void** aInstancePtr) + void** aInstancePtr) { if (NULL == aInstancePtr) { return NS_ERROR_NULL_POINTER; @@ -246,7 +247,7 @@ final: NS_IMETHODIMP nsEncoderSupport::Reset() { - mBufferStart = mBufferEnd; + mBufferStart = mBufferEnd = mBuffer; return NS_OK; } @@ -306,3 +307,251 @@ NS_IMETHODIMP nsTableEncoderSupport::ConvertNoBuffNoErr( mShiftTable, mMappingTable); return res; } + +//---------------------------------------------------------------------- +// Class nsTablesEncoderSupport [implementation] + +nsTablesEncoderSupport::nsTablesEncoderSupport(PRInt32 aTableCount, + uShiftTable ** aShiftTable, + uMappingTable ** aMappingTable) +: nsEncoderSupport() +{ + mHelper = NULL; + mTableCount = aTableCount; + mShiftTable = aShiftTable; + mMappingTable = aMappingTable; +} + +nsTablesEncoderSupport::~nsTablesEncoderSupport() +{ + NS_IF_RELEASE(mHelper); +} + +//---------------------------------------------------------------------- +// Subclassing of nsEncoderSupport class [implementation] + +NS_IMETHODIMP nsTablesEncoderSupport::ConvertNoBuffNoErr( + const PRUnichar * aSrc, + PRInt32 * aSrcLength, + char * aDest, + PRInt32 * aDestLength) +{ + nsresult res; + + if (mHelper == nsnull) { + res = nsComponentManager::CreateInstance(kUnicodeEncodeHelperCID, NULL, + kIUnicodeEncodeHelperIID, (void**) & mHelper); + + if (NS_FAILED(res)) return NS_ERROR_UENC_NOHELPER; + } + + res = mHelper->ConvertByTables(aSrc, aSrcLength, aDest, aDestLength, + mTableCount, mShiftTable, mMappingTable); + return res; +} + +//---------------------------------------------------------------------- +// Class nsDecoderSupport [implementation] + +nsDecoderSupport::nsDecoderSupport() +{ + mBufferCapacity = DEFAULT_BUFFER_CAPACITY; + mBuffer = new char[mBufferCapacity]; + + Reset(); + NS_INIT_REFCNT(); + PR_AtomicIncrement(&g_InstanceCount); +} + +nsDecoderSupport::~nsDecoderSupport() +{ + delete [] mBuffer; + PR_AtomicDecrement(&g_InstanceCount); +} + +void nsDecoderSupport::FillBuffer(const char ** aSrc, PRInt32 aSrcLength) +{ + PRInt32 bcr = PR_MIN(mBufferCapacity - mBufferLength, aSrcLength); + memcpy(mBuffer + mBufferLength, *aSrc, bcr); + mBufferLength += bcr; + (*aSrc) += bcr; +} + +void nsDecoderSupport::DoubleBuffer() +{ + mBufferCapacity *= 2; + char * newBuffer = new char [mBufferCapacity]; + if (mBufferLength > 0) memcpy(newBuffer, mBuffer, mBufferLength); + delete [] mBuffer; + mBuffer = newBuffer; +} + +//---------------------------------------------------------------------- +// Interface nsISupports [implementation] + +NS_IMPL_ADDREF(nsDecoderSupport); +NS_IMPL_RELEASE(nsDecoderSupport); + +nsresult nsDecoderSupport::QueryInterface(REFNSIID aIID, + void** aInstancePtr) +{ + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + + *aInstancePtr = NULL; + + static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + + if (aIID.Equals(kIUnicodeDecoderIID)) { + *aInstancePtr = (void*) ((nsIUnicodeDecoder*)this); + NS_ADDREF_THIS(); + return NS_OK; + } + if (aIID.Equals(kISupportsIID)) { + *aInstancePtr = (void*) ((nsISupports*)this); + NS_ADDREF_THIS(); + return NS_OK; + } + + return NS_NOINTERFACE; +} + +//---------------------------------------------------------------------- +// Interface nsIUnicodeDecoder [implementation] + +NS_IMETHODIMP nsDecoderSupport::Convert(PRUnichar * aDest, + PRInt32 aDestOffset, + PRInt32 * aDestLength, + const char * aSrc, + PRInt32 aSrcOffset, + PRInt32 * aSrcLength) +{ + // XXX this will go away when interface is cleaned + aSrc += aSrcOffset; + aDest += aDestOffset; + + // 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? + 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; + + if ((res == NS_OK_UDEC_MOREINPUT) && (bcw == 0)) { + // not enough input to convert even a single char: repeat! + DoubleBuffer(); + } else { + if (bcr < buffLen) { + // we didn't convert that residual data - unfill the buffer + src -= mBufferLength - buffLen; + mBufferLength = buffLen; + } else { + // the buffer and some extra data was converted - unget the rest + src -= mBufferLength - bcr; + mBufferLength = 0; + } + break; + } + } + + 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 + while (bcr > mBufferCapacity) DoubleBuffer(); + FillBuffer(&src, bcr); + } + } + + *aSrcLength -= srcEnd - src; + *aDestLength -= destEnd - dest; + return res; +} + +NS_IMETHODIMP nsDecoderSupport::Finish(PRUnichar * aDest, PRInt32 aDestOffset, + PRInt32 * aDestLength) +{ + // XXX deprecated + return NS_OK; +} + +NS_IMETHODIMP nsDecoderSupport::Reset() +{ + mBufferLength = 0; + return NS_OK; +} + +NS_IMETHODIMP nsDecoderSupport::SetInputErrorBehavior(PRInt32 aBehavior) +{ + // XXX deprecated + return NS_OK; +} + +//---------------------------------------------------------------------- +// Class nsTableDecoderSupport [implementation] + +nsTableDecoderSupport::nsTableDecoderSupport(uShiftTable * aShiftTable, + uMappingTable * aMappingTable) +: nsDecoderSupport() +{ + mHelper = NULL; + mShiftTable = aShiftTable; + mMappingTable = aMappingTable; +} + +nsTableDecoderSupport::~nsTableDecoderSupport() +{ + NS_IF_RELEASE(mHelper); +} + +//---------------------------------------------------------------------- +// Subclassing of nsDecoderSupport class [implementation] + +NS_IMETHODIMP nsTableDecoderSupport::ConvertNoBuff(const char * aSrc, + PRInt32 * aSrcLength, + PRUnichar * aDest, + PRInt32 * aDestLength) +{ + nsresult res; + + if (mHelper == nsnull) { + res = nsComponentManager::CreateInstance(kUnicodeDecodeHelperCID, NULL, + kIUnicodeDecodeHelperIID, (void**) & mHelper); + + if (NS_FAILED(res)) return NS_ERROR_UDEC_NOHELPER; + } + + res = mHelper->ConvertByTable(aSrc, aSrcLength, aDest, aDestLength, + mShiftTable, mMappingTable); + return res; +} diff --git a/mozilla/intl/uconv/ucvlatin/nsUCvLatinSupport.h b/mozilla/intl/uconv/ucvlatin/nsUCvLatinSupport.h index 8b645f1914b..170ce5c287f 100644 --- a/mozilla/intl/uconv/ucvlatin/nsUCvLatinSupport.h +++ b/mozilla/intl/uconv/ucvlatin/nsUCvLatinSupport.h @@ -21,7 +21,9 @@ #define nsUCvLatinSupport_h___ #include "nsIUnicodeEncoder.h" +#include "nsIUnicodeDecoder.h" #include "nsIUnicodeEncodeHelper.h" +#include "nsIUnicodeDecodeHelper.h" //---------------------------------------------------------------------- // Class nsEncoderSupport [declaration] @@ -85,7 +87,7 @@ protected: /** * Copy as much as possible from the internal buffer to the destination. */ - NS_IMETHOD FlushBuffer(char ** aDest, const char * aDestEnd); + nsresult FlushBuffer(char ** aDest, const char * aDestEnd); public: @@ -147,4 +149,138 @@ protected: char * aDest, PRInt32 * aDestLength); }; +//---------------------------------------------------------------------- +// Class nsTablesEncoderSupport [declaration] + +/** + * Support class for a multi-table-driven Unicode encoder. + * + * @created 11/Mar/1999 + * @author Catalin Rotaru [CATA] + */ +class nsTablesEncoderSupport : public nsEncoderSupport +{ +public: + + /** + * Class constructor. + */ + nsTablesEncoderSupport(PRInt32 aTableCount, uShiftTable ** aShiftTable, + uMappingTable ** aMappingTable); + + /** + * Class destructor. + */ + virtual ~nsTablesEncoderSupport(); + +protected: + + nsIUnicodeEncodeHelper * mHelper; // encoder helper object + PRInt32 mTableCount; + uShiftTable ** mShiftTable; + uMappingTable ** mMappingTable; + + //-------------------------------------------------------------------- + // Subclassing of nsEncoderSupport class [declaration] + + NS_IMETHOD ConvertNoBuffNoErr(const PRUnichar * aSrc, PRInt32 * aSrcLength, + char * aDest, PRInt32 * aDestLength); +}; + +//---------------------------------------------------------------------- +// Class nsDecoderSupport [declaration] + +/** + * Support class for the Unicode decoders. + * + * This class implements: + * - nsISupports + * - the buffer management + * + * @created 15/Mar/1999 + * @author Catalin Rotaru [CATA] + */ +class nsDecoderSupport : public nsIUnicodeDecoder +{ + NS_DECL_ISUPPORTS + +protected: + + /** + * Internal buffer for partial conversions. + */ + char * mBuffer; + PRInt32 mBufferCapacity; + PRInt32 mBufferLength; + + /** + * Convert method but *without* the buffer management stuff. + */ + NS_IMETHOD ConvertNoBuff(const char * aSrc, PRInt32 * aSrcLength, + PRUnichar * aDest, PRInt32 * aDestLength) = 0; + + void FillBuffer(const char ** aSrc, PRInt32 aSrcLength); + void DoubleBuffer(); + +public: + + /** + * Class constructor. + */ + nsDecoderSupport(); + + /** + * Class destructor. + */ + virtual ~nsDecoderSupport(); + + //-------------------------------------------------------------------- + // Interface nsIUnicodeDecoder [declaration] + + NS_IMETHOD Convert(PRUnichar * aDest, PRInt32 aDestOffset, + PRInt32 * aDestLength, const char * aSrc, PRInt32 aSrcOffset, + PRInt32 * aSrcLength); + NS_IMETHOD Finish(PRUnichar * aDest, PRInt32 aDestOffset, + PRInt32 * aDestLength); + NS_IMETHOD Reset(); + NS_IMETHOD SetInputErrorBehavior(PRInt32 aBehavior); +}; + +//---------------------------------------------------------------------- +// Class nsTableDecoderSupport [declaration] + +/** + * Support class for a single-table-driven Unicode decoder. + * + * @created 15/Mar/1999 + * @author Catalin Rotaru [CATA] + */ +class nsTableDecoderSupport : public nsDecoderSupport +{ +public: + + /** + * Class constructor. + */ + nsTableDecoderSupport(uShiftTable * aShiftTable, + uMappingTable * aMappingTable); + + /** + * Class destructor. + */ + virtual ~nsTableDecoderSupport(); + +protected: + + nsIUnicodeDecodeHelper * mHelper; // decoder helper object + uShiftTable * mShiftTable; + uMappingTable * mMappingTable; + + //-------------------------------------------------------------------- + // Subclassing of nsDecoderSupport class [declaration] + + NS_IMETHOD ConvertNoBuff(const char * aSrc, PRInt32 * aSrcLength, + PRUnichar * aDest, PRInt32 * aDestLength); +}; + #endif /* nsUCvLatinSupport_h___ */