Add our implementation for wcscoll() and wcsxfrm().

* add Wcscoll() and Wcsxfrm() ICU locale backend
* provide implementations of wcscoll() and wcsxfrm() that are using
  the respective methods of the locale backend
This commit is contained in:
Oliver Tappe 2012-01-07 21:47:31 +01:00
parent 1b93a2e630
commit bd55dcbefb
8 changed files with 165 additions and 6 deletions

View File

@ -29,6 +29,10 @@ public:
status_t Strcoll(const char* a, const char* b, int& out);
status_t Strxfrm(char* out, const char* in, size_t size,
size_t& outSize);
status_t Wcscoll(const wchar_t* a, const wchar_t* b,
int& out);
status_t Wcsxfrm(wchar_t* out, const wchar_t* in,
size_t size, size_t& outSize);
private:
status_t _ToUnicodeString(const char* in,

View File

@ -61,6 +61,10 @@ public:
virtual status_t Strcoll(const char* a, const char* b, int& out);
virtual status_t Strxfrm(char* out, const char* in, size_t size,
size_t& outSize);
virtual status_t Wcscoll(const wchar_t* a, const wchar_t* b,
int& out);
virtual status_t Wcsxfrm(wchar_t* out, const wchar_t* in,
size_t size, size_t& outSize);
virtual status_t TZSet(const char* timeZoneID, const char* tz);
virtual status_t Localtime(const time_t* inTime,

View File

@ -144,6 +144,10 @@ public:
int& out) = 0;
virtual status_t Strxfrm(char* out, const char* in, size_t size,
size_t& outSize) = 0;
virtual status_t Wcscoll(const wchar_t* a, const wchar_t* b,
int& out) = 0;
virtual status_t Wcsxfrm(wchar_t* out, const wchar_t* in,
size_t size, size_t& outSize) = 0;
virtual status_t TZSet(const char* timeZoneID,
const char* tz) = 0;

View File

@ -7,9 +7,12 @@
#include "ICUCollateData.h"
#include <string.h>
#include <wchar.h>
#include <unicode/unistr.h>
#include <AutoDeleter.h>
namespace BPrivate {
namespace Libroot {
@ -63,7 +66,7 @@ ICUCollateData::SetToPosix()
status_t
ICUCollateData::Strcoll(const char* a, const char* b, int& result)
{
if (strcmp(fPosixLocaleName, "POSIX") == 0) {
if (fCollator == NULL || strcmp(fPosixLocaleName, "POSIX") == 0) {
// handle POSIX here as the collator ICU uses for that (english) is
// incompatible in too many ways
result = strcmp(a, b);
@ -109,7 +112,7 @@ ICUCollateData::Strcoll(const char* a, const char* b, int& result)
status_t
ICUCollateData::Strxfrm(char* out, const char* in, size_t size, size_t& outSize)
{
if (strcmp(fPosixLocaleName, "POSIX") == 0) {
if (fCollator == NULL || strcmp(fPosixLocaleName, "POSIX") == 0) {
// handle POSIX here as the collator ICU uses for that (english) is
// incompatible in too many ways
outSize = strlcpy(out, in, size);
@ -125,13 +128,40 @@ ICUCollateData::Strxfrm(char* out, const char* in, size_t size, size_t& outSize)
return B_OK;
}
UErrorCode icuStatus = U_ZERO_ERROR;
UnicodeString unicodeIn;
if (_ToUnicodeString(in, unicodeIn) != B_OK)
return B_BAD_VALUE;
outSize = fCollator->getSortKey(unicodeIn, (uint8_t*)out, size);
return B_OK;
}
status_t
ICUCollateData::Wcscoll(const wchar_t* a, const wchar_t* b, int& result)
{
if (fCollator == NULL || strcmp(fPosixLocaleName, "POSIX") == 0) {
// handle POSIX here as the collator ICU uses for that (english) is
// incompatible in too many ways
result = wcscmp(a, b);
for (const wchar_t* aIter = a; *aIter != 0; ++aIter) {
if (*aIter > 127)
return B_BAD_VALUE;
}
for (const wchar_t* bIter = b; *bIter != 0; ++bIter) {
if (*bIter > 127)
return B_BAD_VALUE;
}
return B_OK;
}
UnicodeString unicodeA = UnicodeString::fromUTF32((UChar32*)a, -1);
UnicodeString unicodeB = UnicodeString::fromUTF32((UChar32*)b, -1);
UErrorCode icuStatus = U_ZERO_ERROR;
result = fCollator->compare(unicodeA, unicodeB, icuStatus);
if (!U_SUCCESS(icuStatus))
return B_BAD_VALUE;
@ -139,6 +169,40 @@ ICUCollateData::Strxfrm(char* out, const char* in, size_t size, size_t& outSize)
}
status_t
ICUCollateData::Wcsxfrm(wchar_t* out, const wchar_t* in, size_t size,
size_t& outSize)
{
if (in == NULL) {
outSize = 0;
return B_OK;
}
if (fCollator == NULL || strcmp(fPosixLocaleName, "POSIX") == 0) {
// handle POSIX here as the collator ICU uses for that (english) is
// incompatible in too many ways
outSize = wcslcpy(out, in, size);
for (const wchar_t* inIter = in; *inIter != 0; ++inIter) {
if (*inIter > 127)
return B_BAD_VALUE;
}
return B_OK;
}
UnicodeString unicodeIn = UnicodeString::fromUTF32((UChar32*)in, -1);
size_t requiredSize = fCollator->getSortKey(unicodeIn, NULL, 0);
uint8_t* buffer = (uint8_t*)out;
outSize = fCollator->getSortKey(unicodeIn, buffer, requiredSize);
// convert 1-byte characters to 4-byte wide characters:
for (size_t i = 0; i < outSize; ++i)
out[outSize - 1 - i] = buffer[outSize - 1 - i];
return B_OK;
}
status_t
ICUCollateData::_ToUnicodeString(const char* in, UnicodeString& out)
{

View File

@ -294,6 +294,25 @@ ICULocaleBackend::Strxfrm(char* out, const char* in, size_t size,
}
status_t
ICULocaleBackend::Wcscoll(const wchar_t* a, const wchar_t* b, int& result)
{
ErrnoMaintainer errnoMaintainer;
return fCollateData.Wcscoll(a, b, result);
}
status_t
ICULocaleBackend::Wcsxfrm(wchar_t* out, const wchar_t* in, size_t size,
size_t& outSize)
{
ErrnoMaintainer errnoMaintainer;
return fCollateData.Wcsxfrm(out, in, size, outSize);
}
status_t
ICULocaleBackend::TZSet(const char* timeZoneID, const char* tz)
{

View File

@ -11,8 +11,6 @@
#include <unicode/gregocal.h>
#include <AutoDeleter.h>
namespace BPrivate {
namespace Libroot {

View File

@ -0,0 +1,32 @@
/*
** Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved.
** Distributed under the terms of the Haiku License.
*/
#include <errno_private.h>
#include <LocaleBackend.h>
#include <wchar_private.h>
using BPrivate::Libroot::gLocaleBackend;
extern "C" int
__wcscoll(const wchar_t* wcs1, const wchar_t* wcs2)
{
if (gLocaleBackend != NULL) {
int result = 0;
status_t status = gLocaleBackend->Wcscoll(wcs1, wcs2, result);
if (status != B_OK)
__set_errno(EINVAL);
return result;
}
return wcscmp(wcs1, wcs2);
}
extern "C"
B_DEFINE_WEAK_ALIAS(__wcscoll, wcscoll);

View File

@ -0,0 +1,34 @@
/*
* Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de.
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include <errno.h>
#include <errno_private.h>
#include <LocaleBackend.h>
#include <wchar_private.h>
using BPrivate::Libroot::gLocaleBackend;
extern "C" size_t
__wcsxfrm(wchar_t* dest, const wchar_t* src, size_t destSize)
{
if (gLocaleBackend != NULL) {
size_t outSize = 0;
status_t status = gLocaleBackend->Wcsxfrm(dest, src, destSize, outSize);
if (status != B_OK)
__set_errno(EINVAL);
return outSize;
}
return wcslcpy(dest, src, destSize);
}
extern "C"
B_DEFINE_WEAK_ALIAS(__wcsxfrm, wcsxfrm);