gecko-dev/intl/uconv/util/nsUnicodeDecodeHelper.cpp

295 строки
8.8 KiB
C++
Исходник Обычный вид История

1999-03-23 23:47:35 +03:00
/* -*- 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.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/NPL/
1999-03-23 23:47:35 +03:00
*
* 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.
1999-03-23 23:47:35 +03:00
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
1999-03-23 23:47:35 +03:00
*/
#include "pratom.h"
#include "unicpriv.h"
1999-05-11 03:19:21 +04:00
#include "nsUConvDll.h"
#include "nsIMappingCache.h"
#include "nsMappingCache.h"
1999-03-23 23:47:35 +03:00
#include "nsIUnicodeDecodeHelper.h"
1999-05-11 03:19:21 +04:00
#include "nsIUnicodeDecoder.h"
1999-03-23 23:47:35 +03:00
//----------------------------------------------------------------------
// Class nsUnicodeDecodeHelper [declaration]
/**
* The actual implementation of the nsIUnicodeDecodeHelper interface.
*
* @created 18/Mar/1998
* @author Catalin Rotaru [CATA]
*/
class nsUnicodeDecodeHelper : public nsIUnicodeDecodeHelper
{
NS_DECL_ISUPPORTS
public:
/**
* Class constructor.
*/
nsUnicodeDecodeHelper();
/**
* Class destructor.
*/
virtual ~nsUnicodeDecodeHelper();
//--------------------------------------------------------------------
// Interface nsIUnicodeDecodeHelper [declaration]
NS_IMETHOD ConvertByTable(const char * aSrc, PRInt32 * aSrcLength,
PRUnichar * aDest, PRInt32 * aDestLength, uShiftTable * aShiftTable,
uMappingTable * aMappingTable);
1999-04-20 00:26:26 +04:00
NS_IMETHOD ConvertByMultiTable(const char * aSrc, PRInt32 * aSrcLength,
PRUnichar * aDest, PRInt32 * aDestLength, PRInt32 aTableCount,
uRange * aRangeArray, uShiftTable ** aShiftTable,
uMappingTable ** aMappingTable);
NS_IMETHOD ConvertByFastTable(const char * aSrc, PRInt32 * aSrcLength,
PRUnichar * aDest, PRInt32 * aDestLength, PRUnichar * aFastTable,
PRInt32 aTableSize);
NS_IMETHOD CreateFastTable( uShiftTable * aShiftTable,
uMappingTable * aMappingTable, PRUnichar * aFastTable,
PRInt32 aTableSize);
1999-05-11 03:19:21 +04:00
NS_IMETHOD CreateCache(nsMappingCacheType aType, nsIMappingCache* aResult);
NS_IMETHOD DestroyCache(nsIMappingCache aResult);
1999-03-23 23:47:35 +03:00
};
//----------------------------------------------------------------------
// Class nsUnicodeDecodeHelper [implementation]
NS_IMPL_ISUPPORTS1(nsUnicodeDecodeHelper, nsIUnicodeDecodeHelper)
1999-03-23 23:47:35 +03:00
nsUnicodeDecodeHelper::nsUnicodeDecodeHelper()
{
NS_INIT_REFCNT();
}
nsUnicodeDecodeHelper::~nsUnicodeDecodeHelper()
{
}
//----------------------------------------------------------------------
// Interface nsIUnicodeDecodeHelper [implementation]
1999-04-20 00:26:26 +04:00
NS_IMETHODIMP nsUnicodeDecodeHelper::ConvertByTable(
const char * aSrc,
PRInt32 * aSrcLength,
PRUnichar * aDest,
PRInt32 * aDestLength,
uShiftTable * aShiftTable,
uMappingTable * aMappingTable)
1999-03-23 23:47:35 +03:00
{
const char * src = aSrc;
PRInt32 srcLen = *aSrcLength;
PRUnichar * dest = aDest;
PRUnichar * destEnd = aDest + *aDestLength;
PRUnichar med;
PRInt32 bcr; // byte count for read
nsresult res = NS_OK;
while ((srcLen > 0) && (dest < destEnd)) {
if (!uScan(aShiftTable, NULL, (PRUint8 *)src, NS_REINTERPRET_CAST(PRUint16*, &med), srcLen,
1999-03-23 23:47:35 +03:00
(PRUint32 *)&bcr)) {
res = NS_OK_UDEC_MOREINPUT;
break;
}
if (!uMapCode((uTable*) aMappingTable, NS_STATIC_CAST(PRUint16, med), NS_REINTERPRET_CAST(PRUint16*, dest))) {
1999-03-23 23:47:35 +03:00
if (med < 0x20) {
// somehow some table miss the 0x00 - 0x20 part
*dest = med;
} else {
// Unicode replacement value for unmappable chars
*dest = 0xfffd;
}
}
src += bcr;
srcLen -= bcr;
dest++;
}
1999-03-30 03:48:55 +04:00
if ((srcLen > 0) && (res == NS_OK)) res = NS_OK_UDEC_MOREOUTPUT;
1999-03-23 23:47:35 +03:00
*aSrcLength = src - aSrc;
*aDestLength = dest - aDest;
return res;
}
1999-04-20 00:26:26 +04:00
NS_IMETHODIMP nsUnicodeDecodeHelper::ConvertByMultiTable(
const char * aSrc,
PRInt32 * aSrcLength,
PRUnichar * aDest,
PRInt32 * aDestLength,
PRInt32 aTableCount,
uRange * aRangeArray,
uShiftTable ** aShiftTable,
uMappingTable ** aMappingTable)
1999-03-23 23:47:35 +03:00
{
1999-04-01 06:22:17 +04:00
PRUint8 * src = (PRUint8 *)aSrc;
1999-03-25 20:33:39 +03:00
PRInt32 srcLen = *aSrcLength;
PRUnichar * dest = aDest;
PRUnichar * destEnd = aDest + *aDestLength;
PRUnichar med;
PRInt32 bcr; // byte count for read
nsresult res = NS_OK;
PRInt32 i;
while ((srcLen > 0) && (dest < destEnd)) {
for (i=0; i<aTableCount; i++)
if ((aRangeArray[i].min <= *src) && (*src <= aRangeArray[i].max)) break;
if (i == aTableCount) {
if (*src == (PRUint8)0xa0)
*dest = 0x00a0;
else
*dest = 0xfffd;
bcr = 1;
1999-03-25 20:33:39 +03:00
}
else
{
if (!uScan(aShiftTable[i], NULL, src, NS_REINTERPRET_CAST(PRUint16*, &med), srcLen,
(PRUint32 *)&bcr)) {
res = NS_OK_UDEC_MOREINPUT;
break;
}
if (!uMapCode((uTable*) aMappingTable[i], NS_STATIC_CAST(PRUint16, med), NS_REINTERPRET_CAST(PRUint16*, dest))) {
if (med < 0x20) {
// somehow some table miss the 0x00 - 0x20 part
*dest = med;
} else {
// 2 for EUC-KR code set 1 and EUC-JP codeset 1 and 2
// 3 for EUC-JP codeset 3, 4 for EUC-TW code set 3(CNS 11643 Plane 2 - 7)
if (bcr >= 2 && !(*(src+1) & 0x80) ) {
bcr-= (bcr-1);
}
// If stand-alone 0xa0 gets this far (BIG5), leave it alone.
// Otherwise, use Unicode replacement value for unmappable chars
*dest = (*src == (PRUint8)0xa0 ) ? 0x00a0 : 0xfffd;
}
}
1999-03-25 20:33:39 +03:00
}
src += bcr;
srcLen -= bcr;
dest++;
}
1999-03-30 03:48:55 +04:00
if ((srcLen > 0) && (res == NS_OK)) res = NS_OK_UDEC_MOREOUTPUT;
1999-03-25 20:33:39 +03:00
1999-04-01 06:22:17 +04:00
*aSrcLength = src - (PRUint8 *)aSrc;
1999-03-25 20:33:39 +03:00
*aDestLength = dest - aDest;
return res;
1999-03-23 23:47:35 +03:00
}
1999-05-11 03:19:21 +04:00
NS_IMETHODIMP nsUnicodeDecodeHelper::CreateCache(nsMappingCacheType aType, nsIMappingCache* aResult)
{
return nsMappingCache::CreateCache(aType, aResult);
}
NS_IMETHODIMP nsUnicodeDecodeHelper::DestroyCache(nsIMappingCache aCache)
{
return nsMappingCache::DestroyCache(aCache);
}
1999-04-20 00:26:26 +04:00
NS_IMETHODIMP nsUnicodeDecodeHelper::ConvertByFastTable(
const char * aSrc,
PRInt32 * aSrcLength,
PRUnichar * aDest,
PRInt32 * aDestLength,
PRUnichar * aFastTable,
PRInt32 aTableSize)
{
PRUint8 * src = (PRUint8 *)aSrc;
PRUint8 * srcEnd = src;
PRUnichar * dest = aDest;
nsresult res;
if (*aSrcLength > *aDestLength) {
srcEnd += (*aDestLength);
res = NS_PARTIAL_MORE_OUTPUT;
} else {
srcEnd += (*aSrcLength);
res = NS_OK;
}
for (; src<srcEnd;) *dest++ = aFastTable[*src++];
*aSrcLength = src - (PRUint8 *)aSrc;
*aDestLength = dest - aDest;
return res;
}
NS_IMETHODIMP nsUnicodeDecodeHelper::CreateFastTable(
uShiftTable * aShiftTable,
uMappingTable * aMappingTable,
PRUnichar * aFastTable,
PRInt32 aTableSize)
{
PRInt32 tableSize = aTableSize;
PRInt32 buffSize = aTableSize;
char * buff = new char [buffSize];
if (buff == NULL) return NS_ERROR_OUT_OF_MEMORY;
char * p = buff;
for (PRInt32 i=0; i<aTableSize; i++) *(p++) = i;
nsresult res = ConvertByTable(buff, &buffSize, aFastTable, &tableSize,
aShiftTable, aMappingTable);
delete [] buff;
return res;
}
1999-03-23 23:47:35 +03:00
//----------------------------------------------------------------------
1999-10-01 01:11:05 +04:00
NS_IMETHODIMP
NS_NewUnicodeDecodeHelper(nsISupports* aOuter,
const nsIID &aIID,
void **aResult)
1999-03-23 23:47:35 +03:00
{
1999-10-01 01:11:05 +04:00
if (!aResult) {
return NS_ERROR_NULL_POINTER;
}
if (aOuter) {
*aResult = nsnull;
return NS_ERROR_NO_AGGREGATION;
}
nsUnicodeDecodeHelper* inst = new nsUnicodeDecodeHelper();
if (!inst) {
*aResult = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult res = inst->QueryInterface(aIID, aResult);
if (NS_FAILED(res)) {
*aResult = nsnull;
delete inst;
}
1999-03-23 23:47:35 +03:00
return res;
}