#189480 r=mkaply, sr=blizzard (platform specific), a=mkaply OS/2 only - switch to using Mozilla Unicode encoders/decoders instead of platform decoders

This commit is contained in:
mkaply@us.ibm.com 2007-09-06 11:41:01 -07:00
Родитель 6cfe8d5a6d
Коммит dc245972f8
2 изменённых файлов: 153 добавлений и 84 удалений

Просмотреть файл

@ -35,98 +35,150 @@
* ***** END LICENSE BLOCK ***** */
#include "nsOS2Uni.h"
#include "nsIServiceManager.h"
#include "nsIPlatformCharset.h"
#include <stdlib.h>
int WideCharToMultiByte( int CodePage, const PRUnichar *pText, ULONG ulLength, char* szBuffer, ULONG ulSize )
/**********************************************************
OS2Uni
**********************************************************/
nsICharsetConverterManager* OS2Uni::gCharsetManager = nsnull;
struct ConverterInfo
{
UconvObject Converter = OS2Uni::GetUconvObject(CodePage);
PRUint16 mCodePage;
char* mConvName;
nsIUnicodeEncoder* mEncoder;
nsIUnicodeDecoder* mDecoder;
};
UniChar *ucsString = (UniChar*) pText;
size_t ucsLen = ulLength;
size_t cplen = ulSize;
size_t cSubs = 0;
#define eCONVERTER_COUNT 17
ConverterInfo gConverterInfo[eCONVERTER_COUNT] =
{
{ 0, "", nsnull, nsnull },
{ 1252, "windows-1252", nsnull, nsnull },
{ 1208, "UTF-8", nsnull, nsnull },
{ 1250, "windows-1250", nsnull, nsnull },
{ 1251, "windows-1251", nsnull, nsnull },
{ 813, "ISO-8859-7", nsnull, nsnull },
{ 1254, "windows-1254", nsnull, nsnull },
{ 864, "IBM864", nsnull, nsnull },
{ 1257, "windows-1257", nsnull, nsnull },
{ 874, "windows-874", nsnull, nsnull },
{ 932, "Shift_JIS", nsnull, nsnull },
{ 943, "Shift_JIS", nsnull, nsnull },
{ 1381, "GB2312", nsnull, nsnull },
{ 1386, "GB2312", nsnull, nsnull },
{ 949, "x-windows-949", nsnull, nsnull },
{ 950, "Big5", nsnull, nsnull },
{ 1361, "x-johab", nsnull, nsnull }
};
char *tmp = szBuffer; // function alters the out pointer
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
int unirc = ::UniUconvFromUcs( Converter, &ucsString, &ucsLen,
(void**) &tmp, &cplen, &cSubs);
if( unirc != ULS_SUCCESS )
return 0;
if( unirc == UCONV_E2BIG)
{
// terminate output string (truncating)
*(szBuffer + ulSize - 1) = '\0';
nsISupports*
OS2Uni::GetUconvObject(int aCodePage, ConverterRequest aReq)
{
if (gCharsetManager == nsnull) {
nsServiceManager::GetService(kCharsetConverterManagerCID,
NS_GET_IID(nsICharsetConverterManager), (nsISupports**) &gCharsetManager);
}
return ulSize - cplen;
}
int MultiByteToWideChar( int CodePage, const char*pText, ULONG ulLength, PRUnichar *szBuffer, ULONG ulSize )
{
UconvObject Converter = OS2Uni::GetUconvObject(CodePage);
char *ucsString = (char*) pText;
size_t ucsLen = ulLength;
size_t cplen = ulSize;
size_t cSubs = 0;
PRUnichar *tmp = szBuffer; // function alters the out pointer
int unirc = ::UniUconvToUcs( Converter, (void**)&ucsString, &ucsLen,
NS_REINTERPRET_CAST(UniChar**, &tmp),
&cplen, &cSubs);
if( unirc != ULS_SUCCESS )
return 0;
if( unirc == UCONV_E2BIG)
{
// terminate output string (truncating)
*(szBuffer + ulSize - 1) = '\0';
}
return ulSize - cplen;
}
nsHashtable OS2Uni::gUconvObjects;
UconvObject
OS2Uni::GetUconvObject(int CodePage)
{
nsPRUint32Key key(CodePage);
UconvObject uco = OS2Uni::gUconvObjects.Get(&key);
if (!uco) {
UniChar codepage[20];
int unirc = ::UniMapCpToUcsCp(CodePage, codepage, 20);
if (unirc == ULS_SUCCESS) {
unirc = ::UniCreateUconvObject(codepage, &uco);
if (unirc == ULS_SUCCESS) {
uconv_attribute_t attr;
::UniQueryUconvObject(uco, &attr, sizeof(uconv_attribute_t),
NULL, NULL, NULL);
attr.options = UCONV_OPTION_SUBSTITUTE_BOTH;
attr.subchar_len=1;
attr.subchar[0]='?';
::UniSetUconvObject(uco, &attr);
OS2Uni::gUconvObjects.Put(&key, uco);
}
nsresult rv;
nsISupports* uco = nsnull;
for (int i = 0; i < eCONVERTER_COUNT; i++) {
if (aCodePage == gConverterInfo[i].mCodePage) {
if (gConverterInfo[i].mEncoder == nsnull) {
const char* convname;
nsCAutoString charset;
if (aCodePage == 0) {
nsCOMPtr<nsIPlatformCharset>
plat(do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv));
if (NS_SUCCEEDED(rv)) {
plat->GetCharset(kPlatformCharsetSel_FileName, charset);
} else {
// default to IBM850 if this should fail
charset = "IBM850";
}
convname = charset.get();
} else {
convname = gConverterInfo[i].mConvName;
}
rv = gCharsetManager->GetUnicodeEncoderRaw(convname,
&gConverterInfo[i].mEncoder);
gConverterInfo[i].mEncoder->
SetOutputErrorBehavior(nsIUnicodeEncoder::kOnError_Replace,
nsnull, '?');
gCharsetManager->GetUnicodeDecoderRaw(convname,
&gConverterInfo[i].mDecoder);
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get converter");
}
if (aReq == eConv_Encoder) {
uco = gConverterInfo[i].mEncoder;
} else {
uco = gConverterInfo[i].mDecoder;
}
break;
}
}
return uco;
}
PR_STATIC_CALLBACK(PRIntn)
UconvObjectEnum(nsHashKey* hashKey, void *aData, void* closure)
{
UniFreeUconvObject((UconvObject)aData);
return kHashEnumerateRemove;
return uco;
}
void OS2Uni::FreeUconvObjects()
{
if (gUconvObjects.Count()) {
gUconvObjects.Enumerate(UconvObjectEnum, nsnull);
for (int i = 0; i < eCONVERTER_COUNT; i++) {
NS_IF_RELEASE(gConverterInfo[i].mEncoder);
NS_IF_RELEASE(gConverterInfo[i].mDecoder);
}
NS_IF_RELEASE(gCharsetManager);
}
/**********************************************************
WideCharToMultiByte
**********************************************************/
nsresult
WideCharToMultiByte(int aCodePage, const PRUnichar* aSrc,
PRInt32 aSrcLength, nsAutoCharBuffer& aResult,
PRInt32& aResultLength)
{
nsresult rv;
nsISupports* sup = OS2Uni::GetUconvObject(aCodePage, eConv_Encoder);
nsCOMPtr<nsIUnicodeEncoder> uco = do_QueryInterface(sup);
if (NS_FAILED(uco->GetMaxLength(aSrc, aSrcLength, &aResultLength))) {
return NS_ERROR_UNEXPECTED;
}
if (!aResult.EnsureElemCapacity(aResultLength + 1))
return NS_ERROR_OUT_OF_MEMORY;
char* str = aResult.get();
rv = uco->Convert(aSrc, &aSrcLength, str, &aResultLength);
aResult.get()[aResultLength] = '\0';
return rv;
}
/**********************************************************
MultiByteToWideChar
**********************************************************/
nsresult
MultiByteToWideChar(int aCodePage, const char* aSrc,
PRInt32 aSrcLength, nsAutoChar16Buffer& aResult,
PRInt32& aResultLength)
{
nsresult rv;
nsISupports* sup = OS2Uni::GetUconvObject(aCodePage, eConv_Decoder);
nsCOMPtr<nsIUnicodeDecoder> uco = do_QueryInterface(sup);
if (NS_FAILED(uco->GetMaxLength(aSrc, aSrcLength, &aResultLength))) {
return NS_ERROR_UNEXPECTED;
}
if (!aResult.EnsureElemCapacity(aResultLength + 1))
return NS_ERROR_OUT_OF_MEMORY;
PRUnichar* str = aResult.get();
rv = uco->Convert(aSrc, &aSrcLength, str, &aResultLength);
aResult.get()[aResultLength] = '\0';
return rv;
}

Просмотреть файл

@ -37,19 +37,36 @@
#ifndef _nsos2uni_h
#define _nsos2uni_h
#define INCL_WIN
#include <os2.h>
#include <uconv.h>
#include "nsHashTable.h"
#include "nsAutoBuffer.h"
#include "nsICharsetConverterManager.h"
enum ConverterRequest {
eConv_Encoder,
eConv_Decoder
};
class OS2Uni {
public:
static UconvObject GetUconvObject(int CodePage);
static nsISupports* GetUconvObject(int CodePage, ConverterRequest aReq);
static void FreeUconvObjects();
private:
static nsHashtable gUconvObjects;
static nsICharsetConverterManager* gCharsetManager;
};
int WideCharToMultiByte( int CodePage, const PRUnichar *pText, ULONG ulLength, char* szBuffer, ULONG ulSize );
int MultiByteToWideChar( int CodePage, const char*pText, ULONG ulLength, PRUnichar *szBuffer, ULONG ulSize );
#define CHAR_BUFFER_SIZE 1024
typedef nsAutoBuffer<char, CHAR_BUFFER_SIZE> nsAutoCharBuffer;
typedef nsAutoBuffer<PRUnichar, CHAR_BUFFER_SIZE> nsAutoChar16Buffer;
nsresult WideCharToMultiByte(int aCodePage, const PRUnichar* aSrc,
PRInt32 aSrcLength, nsAutoCharBuffer& aResult,
PRInt32& aResultLength);
nsresult MultiByteToWideChar(int aCodePage, const char* aSrc,
PRInt32 aSrcLength, nsAutoChar16Buffer& aResult,
PRInt32& aResultLength);
#endif