mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 07:39:16 +00:00
ICU-4092 Increase code coverage.
Fix broken RTTI on Windows by splitting service registration into separate files, and rename files for consistency at the request from Doug. X-SVN-Rev: 16979
This commit is contained in:
parent
5a592ce19e
commit
fef1b77683
21 changed files with 1182 additions and 992 deletions
|
@ -74,8 +74,8 @@ uscript.o usc_impl.o uvector.o ustack.o uvectr32.o ucmp8.o \
|
|||
uarrsort.o utrie.o uset.o uset_props.o uniset.o uniset_props.o ruleiter.o caniter.o unifilt.o unifunct.o usetiter.o \
|
||||
brkiter.o brkdict.o ubrk.o dbbi.o dbbi_tbl.o \
|
||||
rbbi.o rbbidata.o rbbinode.o rbbirb.o rbbiscan.o rbbisetb.o rbbistbl.o rbbitblb.o \
|
||||
icuserv.o iculserv.o icunotif.o uenum.o ustrenum.o \
|
||||
uidna.o usprep.o punycode.o \
|
||||
serv.o servnotf.o servls.o servlu.o servlk.o servlkf.o servrbf.o servslkf.o \
|
||||
uenum.o ustrenum.o uidna.o usprep.o punycode.o \
|
||||
cwchar.o filestrm.o util.o parsepos.o utrace.o locbased.o
|
||||
|
||||
STATIC_OBJECTS = $(OBJECTS:.o=.$(STATIC_O))
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include "ucln_cmn.h"
|
||||
#include "cstring.h"
|
||||
#include "mutex.h"
|
||||
#include "iculserv.h"
|
||||
#include "servloc.h"
|
||||
#include "locbased.h"
|
||||
#include "uresimp.h"
|
||||
|
||||
|
|
|
@ -2986,35 +2986,47 @@ InputPath=.\unicode\usetiter.h
|
|||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\iculdata.h
|
||||
SOURCE=.\serv.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\iculserv.cpp
|
||||
SOURCE=.\serv.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\iculserv.h
|
||||
SOURCE=.\servlk.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\icunotif.cpp
|
||||
SOURCE=.\servlkf.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\icunotif.h
|
||||
SOURCE=.\servloc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\icurwlck.h
|
||||
SOURCE=.\servls.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\icuserv.cpp
|
||||
SOURCE=.\servlu.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\icuserv.h
|
||||
SOURCE=.\servnotf.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\servnotf.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\servrbf.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\servslkf.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "sprep"
|
||||
|
|
|
@ -1582,22 +1582,37 @@
|
|||
Name="registration"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\iculserv.cpp">
|
||||
RelativePath=".\serv.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\iculserv.h">
|
||||
RelativePath=".\serv.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\icunotif.cpp">
|
||||
RelativePath=".\servlk.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\icunotif.h">
|
||||
RelativePath=".\servlkf.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\icuserv.cpp">
|
||||
RelativePath=".\servloc.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\icuserv.h">
|
||||
RelativePath=".\servls.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\servlu.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\servnotf.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\servnotf.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\servrbf.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\servslkf.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
|
|
@ -1,960 +0,0 @@
|
|||
/**
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2001-2004, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
|
||||
#include "unicode/resbund.h"
|
||||
#include "uresimp.h"
|
||||
#include "cmemory.h"
|
||||
#include "iculserv.h"
|
||||
#include "ustrfmt.h"
|
||||
#include "uhash.h"
|
||||
#include "charstr.h"
|
||||
#include "ucln_cmn.h"
|
||||
#include "uassert.h"
|
||||
|
||||
// see LocaleUtility::getAvailableLocaleNames
|
||||
static Hashtable * LocaleUtility_cache = NULL;
|
||||
|
||||
#define UNDERSCORE_CHAR ((UChar)0x005f)
|
||||
#define AT_SIGN_CHAR ((UChar)64)
|
||||
#define PERIOD_CHAR ((UChar)46)
|
||||
|
||||
/*
|
||||
******************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Release all static memory held by Locale Utility.
|
||||
*/
|
||||
U_CDECL_BEGIN
|
||||
static UBool U_CALLCONV service_cleanup(void) {
|
||||
if (LocaleUtility_cache) {
|
||||
delete LocaleUtility_cache;
|
||||
LocaleUtility_cache = NULL;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
U_CDECL_END
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
UnicodeString&
|
||||
LocaleUtility::canonicalLocaleString(const UnicodeString* id, UnicodeString& result)
|
||||
{
|
||||
if (id == NULL) {
|
||||
result.setToBogus();
|
||||
} else {
|
||||
// Fix case only (no other changes) up to the first '@' or '.' or
|
||||
// end of string, whichever comes first. In 3.0 I changed this to
|
||||
// stop at first '@' or '.'. It used to run out to the end of
|
||||
// string. My fix makes the tests pass but is probably
|
||||
// structurally incorrect. See below. [alan 3.0]
|
||||
|
||||
// TODO: Doug, you might want to revise this...
|
||||
result = *id;
|
||||
int32_t i = 0;
|
||||
int32_t end = result.indexOf(AT_SIGN_CHAR);
|
||||
int32_t n = result.indexOf(PERIOD_CHAR);
|
||||
if (n >= 0 && n < end) {
|
||||
end = n;
|
||||
}
|
||||
if (end < 0) {
|
||||
end = result.length();
|
||||
}
|
||||
n = result.indexOf(UNDERSCORE_CHAR);
|
||||
if (n < 0) {
|
||||
n = end;
|
||||
}
|
||||
for (; i < n; ++i) {
|
||||
UChar c = result.charAt(i);
|
||||
if (c >= 0x0041 && c <= 0x005a) {
|
||||
c += 0x20;
|
||||
result.setCharAt(i, c);
|
||||
}
|
||||
}
|
||||
for (n = end; i < n; ++i) {
|
||||
UChar c = result.charAt(i);
|
||||
if (c >= 0x0061 && c <= 0x007a) {
|
||||
c -= 0x20;
|
||||
result.setCharAt(i, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
#if 0
|
||||
// This code does a proper full level 2 canonicalization of id.
|
||||
// It's nasty to go from UChar to char to char to UChar -- but
|
||||
// that's what you have to do to use the uloc_canonicalize
|
||||
// function on UnicodeStrings.
|
||||
|
||||
// I ended up doing the alternate fix (see above) not for
|
||||
// performance reasons, although performance will certainly be
|
||||
// better, but because doing a full level 2 canonicalization
|
||||
// causes some tests to fail. [alan 3.0]
|
||||
|
||||
// TODO: Doug, you might want to revisit this...
|
||||
result.setToBogus();
|
||||
if (id != 0) {
|
||||
int32_t buflen = id->length() + 8; // space for NUL
|
||||
char* buf = (char*) uprv_malloc(buflen);
|
||||
char* canon = (buf == 0) ? 0 : (char*) uprv_malloc(buflen);
|
||||
if (buf != 0 && canon != 0) {
|
||||
U_ASSERT(id->extract(0, INT32_MAX, buf, buflen) < buflen);
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
uloc_canonicalize(buf, canon, buflen, &ec);
|
||||
if (U_SUCCESS(ec)) {
|
||||
result = UnicodeString(canon);
|
||||
}
|
||||
}
|
||||
uprv_free(buf);
|
||||
uprv_free(canon);
|
||||
}
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
Locale&
|
||||
LocaleUtility::initLocaleFromName(const UnicodeString& id, Locale& result)
|
||||
{
|
||||
enum { BUFLEN = 128 }; // larger than ever needed
|
||||
|
||||
if (id.isBogus() || id.length() >= BUFLEN) {
|
||||
result.setToBogus();
|
||||
} else {
|
||||
/*
|
||||
* We need to convert from a UnicodeString to char * in order to
|
||||
* create a Locale.
|
||||
*
|
||||
* Problem: Locale ID strings may contain '@' which is a variant
|
||||
* character and cannot be handled by invariant-character conversion.
|
||||
*
|
||||
* Hack: Since ICU code can handle locale IDs with multiple encodings
|
||||
* of '@' (at least for EBCDIC; it's not known to be a problem for
|
||||
* ASCII-based systems),
|
||||
* we use regular invariant-character conversion for everything else
|
||||
* and manually convert U+0040 into a compiler-char-constant '@'.
|
||||
* While this compilation-time constant may not match the runtime
|
||||
* encoding of '@', it should be one of the encodings which ICU
|
||||
* recognizes.
|
||||
*
|
||||
* There should be only at most one '@' in a locale ID.
|
||||
*/
|
||||
char buffer[BUFLEN];
|
||||
int32_t prev, i;
|
||||
prev = 0;
|
||||
for(;;) {
|
||||
i = id.indexOf((UChar)0x40, prev);
|
||||
if(i < 0) {
|
||||
// no @ between prev and the rest of the string
|
||||
id.extract(prev, INT32_MAX, buffer + prev, BUFLEN - prev, US_INV);
|
||||
break; // done
|
||||
} else {
|
||||
// normal invariant-character conversion for text between @s
|
||||
id.extract(prev, i - prev, buffer + prev, BUFLEN - prev, US_INV);
|
||||
// manually "convert" U+0040 at id[i] into '@' at buffer[i]
|
||||
buffer[i] = '@';
|
||||
prev = i + 1;
|
||||
}
|
||||
}
|
||||
result = Locale::createFromName(buffer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleUtility::initNameFromLocale(const Locale& locale, UnicodeString& result)
|
||||
{
|
||||
if (locale.isBogus()) {
|
||||
result.setToBogus();
|
||||
} else {
|
||||
result.append(UnicodeString(locale.getName(), -1, US_INV));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const Hashtable*
|
||||
LocaleUtility::getAvailableLocaleNames(const UnicodeString& bundleID)
|
||||
{
|
||||
// LocaleUtility_cache is a hash-of-hashes. The top-level keys
|
||||
// are path strings ('bundleID') passed to
|
||||
// ures_openAvailableLocales. The top-level values are
|
||||
// second-level hashes. The second-level keys are result strings
|
||||
// from ures_openAvailableLocales. The second-level values are
|
||||
// garbage ((void*)1 or other random pointer).
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
Hashtable* cache;
|
||||
umtx_lock(NULL);
|
||||
cache = LocaleUtility_cache;
|
||||
umtx_unlock(NULL);
|
||||
|
||||
if (cache == NULL) {
|
||||
cache = new Hashtable(status);
|
||||
if (cache == NULL || U_FAILURE(status)) {
|
||||
return NULL; // catastrophic failure; e.g. out of memory
|
||||
}
|
||||
cache->setValueDeleter(uhash_deleteHashtable);
|
||||
Hashtable* h; // set this to final LocaleUtility_cache value
|
||||
umtx_lock(NULL);
|
||||
h = LocaleUtility_cache;
|
||||
if (h == NULL) {
|
||||
LocaleUtility_cache = h = cache;
|
||||
cache = NULL;
|
||||
ucln_common_registerCleanup(UCLN_COMMON_SERVICE, service_cleanup);
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
delete cache;
|
||||
cache = h;
|
||||
}
|
||||
|
||||
U_ASSERT(cache != NULL);
|
||||
|
||||
Hashtable* htp;
|
||||
umtx_lock(NULL);
|
||||
htp = (Hashtable*) cache->get(bundleID);
|
||||
umtx_unlock(NULL);
|
||||
|
||||
if (htp == NULL) {
|
||||
htp = new Hashtable(status);
|
||||
if (htp && U_SUCCESS(status)) {
|
||||
CharString cbundleID(bundleID);
|
||||
const char* path = (const char*) cbundleID;
|
||||
if (*path == 0) path = NULL; // empty string => NULL
|
||||
UEnumeration *uenum = ures_openAvailableLocales(path, &status);
|
||||
for (;;) {
|
||||
const UChar* id = uenum_unext(uenum, NULL, &status);
|
||||
if (id == NULL) {
|
||||
break;
|
||||
}
|
||||
htp->put(UnicodeString(id), (void*)htp, status);
|
||||
}
|
||||
uenum_close(uenum);
|
||||
if (U_FAILURE(status)) {
|
||||
delete htp;
|
||||
return NULL;
|
||||
}
|
||||
umtx_lock(NULL);
|
||||
cache->put(bundleID, (void*)htp, status);
|
||||
umtx_unlock(NULL);
|
||||
}
|
||||
}
|
||||
return htp;
|
||||
}
|
||||
|
||||
UBool
|
||||
LocaleUtility::isFallbackOf(const UnicodeString& root, const UnicodeString& child)
|
||||
{
|
||||
return child.indexOf(root) == 0 &&
|
||||
(child.length() == root.length() ||
|
||||
child.charAt(root.length()) == UNDERSCORE_CHAR);
|
||||
}
|
||||
|
||||
/*
|
||||
******************************************************************
|
||||
*/
|
||||
|
||||
LocaleKey*
|
||||
LocaleKey::createWithCanonicalFallback(const UnicodeString* primaryID,
|
||||
const UnicodeString* canonicalFallbackID,
|
||||
UErrorCode& status)
|
||||
{
|
||||
return LocaleKey::createWithCanonicalFallback(primaryID, canonicalFallbackID, KIND_ANY, status);
|
||||
}
|
||||
|
||||
LocaleKey*
|
||||
LocaleKey::createWithCanonicalFallback(const UnicodeString* primaryID,
|
||||
const UnicodeString* canonicalFallbackID,
|
||||
int32_t kind,
|
||||
UErrorCode& status)
|
||||
{
|
||||
if (primaryID == NULL || U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
UnicodeString canonicalPrimaryID;
|
||||
LocaleUtility::canonicalLocaleString(primaryID, canonicalPrimaryID);
|
||||
return new LocaleKey(*primaryID, canonicalPrimaryID, canonicalFallbackID, kind);
|
||||
}
|
||||
|
||||
LocaleKey::LocaleKey(const UnicodeString& primaryID,
|
||||
const UnicodeString& canonicalPrimaryID,
|
||||
const UnicodeString* canonicalFallbackID,
|
||||
int32_t kind)
|
||||
: ICUServiceKey(primaryID)
|
||||
, _kind(kind)
|
||||
, _primaryID(canonicalPrimaryID)
|
||||
, _fallbackID()
|
||||
, _currentID()
|
||||
{
|
||||
_fallbackID.setToBogus();
|
||||
if (_primaryID.length() != 0) {
|
||||
if (canonicalFallbackID != NULL && _primaryID != *canonicalFallbackID) {
|
||||
_fallbackID = *canonicalFallbackID;
|
||||
}
|
||||
}
|
||||
|
||||
_currentID = _primaryID;
|
||||
}
|
||||
|
||||
LocaleKey::~LocaleKey() {}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKey::prefix(UnicodeString& result) const {
|
||||
if (_kind != KIND_ANY) {
|
||||
UChar buffer[64];
|
||||
uprv_itou(buffer, 64, _kind, 10, 0);
|
||||
UnicodeString temp(buffer);
|
||||
result.append(temp);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t
|
||||
LocaleKey::kind() const {
|
||||
return _kind;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKey::canonicalID(UnicodeString& result) const {
|
||||
return result.append(_primaryID);
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKey::currentID(UnicodeString& result) const {
|
||||
if (!_currentID.isBogus()) {
|
||||
result.append(_currentID);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKey::currentDescriptor(UnicodeString& result) const {
|
||||
if (!_currentID.isBogus()) {
|
||||
prefix(result).append(PREFIX_DELIMITER).append(_currentID);
|
||||
} else {
|
||||
result.setToBogus();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Locale&
|
||||
LocaleKey::canonicalLocale(Locale& result) const {
|
||||
return LocaleUtility::initLocaleFromName(_primaryID, result);
|
||||
}
|
||||
|
||||
Locale&
|
||||
LocaleKey::currentLocale(Locale& result) const {
|
||||
return LocaleUtility::initLocaleFromName(_currentID, result);
|
||||
}
|
||||
|
||||
UBool
|
||||
LocaleKey::fallback() {
|
||||
if (!_currentID.isBogus()) {
|
||||
int x = _currentID.lastIndexOf(UNDERSCORE_CHAR);
|
||||
if (x != -1) {
|
||||
_currentID.remove(x); // truncate current or fallback, whichever we're pointing to
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!_fallbackID.isBogus()) {
|
||||
_currentID = _fallbackID;
|
||||
_fallbackID.setToBogus();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (_currentID.length() > 0) {
|
||||
_currentID.remove(0); // completely truncate
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_currentID.setToBogus();
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
UBool
|
||||
LocaleKey::isFallbackOf(const UnicodeString& id) const {
|
||||
UnicodeString temp(id);
|
||||
parseSuffix(temp);
|
||||
return temp.indexOf(_primaryID) == 0 &&
|
||||
(temp.length() == _primaryID.length() ||
|
||||
temp.charAt(_primaryID.length()) == UNDERSCORE_CHAR);
|
||||
}
|
||||
|
||||
#ifdef SERVICE_DEBUG
|
||||
UnicodeString&
|
||||
LocaleKey::debug(UnicodeString& result) const
|
||||
{
|
||||
ICUServiceKey::debug(result);
|
||||
result.append(" kind: ");
|
||||
result.append(_kind);
|
||||
result.append(" primaryID: ");
|
||||
result.append(_primaryID);
|
||||
result.append(" fallbackID: ");
|
||||
result.append(_fallbackID);
|
||||
result.append(" currentID: ");
|
||||
result.append(_currentID);
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKey::debugClass(UnicodeString& result) const
|
||||
{
|
||||
return result.append("LocaleKey ");
|
||||
}
|
||||
#endif
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LocaleKey)
|
||||
|
||||
/*
|
||||
******************************************************************
|
||||
*/
|
||||
|
||||
LocaleKeyFactory::LocaleKeyFactory(int32_t coverage)
|
||||
: _name()
|
||||
, _coverage(coverage)
|
||||
{
|
||||
}
|
||||
|
||||
LocaleKeyFactory::LocaleKeyFactory(int32_t coverage, const UnicodeString& name)
|
||||
: _name(name)
|
||||
, _coverage(coverage)
|
||||
{
|
||||
}
|
||||
|
||||
LocaleKeyFactory::~LocaleKeyFactory() {
|
||||
}
|
||||
|
||||
UObject*
|
||||
LocaleKeyFactory::create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const {
|
||||
if (handlesKey(key, status)) {
|
||||
const LocaleKey& lkey = (const LocaleKey&)key;
|
||||
int32_t kind = lkey.kind();
|
||||
Locale loc;
|
||||
lkey.currentLocale(loc);
|
||||
|
||||
return handleCreate(loc, kind, service, status);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UBool
|
||||
LocaleKeyFactory::handlesKey(const ICUServiceKey& key, UErrorCode& status) const {
|
||||
const Hashtable* supported = getSupportedIDs(status);
|
||||
if (supported) {
|
||||
UnicodeString id;
|
||||
key.currentID(id);
|
||||
return supported->get(id) != NULL;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
LocaleKeyFactory::updateVisibleIDs(Hashtable& result, UErrorCode& status) const {
|
||||
const Hashtable* supported = getSupportedIDs(status);
|
||||
if (supported) {
|
||||
UBool visible = (_coverage & 0x1) == 0;
|
||||
|
||||
const UHashElement* elem = NULL;
|
||||
int32_t pos = 0;
|
||||
while ((elem = supported->nextElement(pos)) != NULL) {
|
||||
const UnicodeString& id = *((const UnicodeString*)elem->key.pointer);
|
||||
if (!visible) {
|
||||
result.remove(id);
|
||||
} else {
|
||||
result.put(id, (void*)this, status); // this is dummy non-void marker used for set semantics
|
||||
if (U_FAILURE(status)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKeyFactory::getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const {
|
||||
if ((_coverage & 0x1) == 0) {
|
||||
//UErrorCode status = U_ZERO_ERROR;
|
||||
// assume if this is called on us, we support some fallback of this id
|
||||
// if (isSupportedID(id, status)) {
|
||||
Locale loc;
|
||||
LocaleUtility::initLocaleFromName(id, loc);
|
||||
return loc.getDisplayName(locale, result);
|
||||
// }
|
||||
}
|
||||
result.setToBogus();
|
||||
return result;
|
||||
}
|
||||
|
||||
UObject*
|
||||
LocaleKeyFactory::handleCreate(const Locale& /* loc */,
|
||||
int32_t /* kind */,
|
||||
const ICUService* /* service */,
|
||||
UErrorCode& /* status */) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UBool
|
||||
LocaleKeyFactory::isSupportedID(const UnicodeString& id, UErrorCode& status) const {
|
||||
const Hashtable* ids = getSupportedIDs(status);
|
||||
return ids && ids->get(id);
|
||||
}
|
||||
|
||||
const Hashtable*
|
||||
LocaleKeyFactory::getSupportedIDs(UErrorCode& /* status */) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef SERVICE_DEBUG
|
||||
UnicodeString&
|
||||
LocaleKeyFactory::debug(UnicodeString& result) const
|
||||
{
|
||||
debugClass(result);
|
||||
result.append(", name: ");
|
||||
result.append(_name);
|
||||
result.append(", coverage: ");
|
||||
result.append(_coverage);
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKeyFactory::debugClass(UnicodeString& result) const
|
||||
{
|
||||
return result.append("LocaleKeyFactory");
|
||||
}
|
||||
#endif
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LocaleKeyFactory)
|
||||
|
||||
/*
|
||||
******************************************************************
|
||||
*/
|
||||
|
||||
SimpleLocaleKeyFactory::SimpleLocaleKeyFactory(UObject* objToAdopt,
|
||||
const UnicodeString& locale,
|
||||
int32_t kind,
|
||||
int32_t coverage)
|
||||
: LocaleKeyFactory(coverage)
|
||||
, _obj(objToAdopt)
|
||||
, _id(locale)
|
||||
, _kind(kind)
|
||||
{
|
||||
}
|
||||
|
||||
SimpleLocaleKeyFactory::SimpleLocaleKeyFactory(UObject* objToAdopt,
|
||||
const Locale& locale,
|
||||
int32_t kind,
|
||||
int32_t coverage)
|
||||
: LocaleKeyFactory(coverage)
|
||||
, _obj(objToAdopt)
|
||||
, _id()
|
||||
, _kind(kind)
|
||||
{
|
||||
LocaleUtility::initNameFromLocale(locale, _id);
|
||||
}
|
||||
|
||||
SimpleLocaleKeyFactory::~SimpleLocaleKeyFactory()
|
||||
{
|
||||
delete _obj;
|
||||
_obj = NULL;
|
||||
}
|
||||
|
||||
UObject*
|
||||
SimpleLocaleKeyFactory::create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
const LocaleKey& lkey = (const LocaleKey&)key;
|
||||
if (_kind == LocaleKey::KIND_ANY || _kind == lkey.kind()) {
|
||||
UnicodeString keyID;
|
||||
lkey.currentID(keyID);
|
||||
if (_id == keyID) {
|
||||
return service->cloneInstance(_obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UBool
|
||||
SimpleLocaleKeyFactory::isSupportedID(const UnicodeString& id, UErrorCode& /* status */) const
|
||||
{
|
||||
return id == _id;
|
||||
}
|
||||
|
||||
void
|
||||
SimpleLocaleKeyFactory::updateVisibleIDs(Hashtable& result, UErrorCode& status) const
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
if (_coverage & 0x1) {
|
||||
result.remove(_id);
|
||||
} else {
|
||||
result.put(_id, (void*)this, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SERVICE_DEBUG
|
||||
UnicodeString&
|
||||
SimpleLocaleKeyFactory::debug(UnicodeString& result) const
|
||||
{
|
||||
LocaleKeyFactory::debug(result);
|
||||
result.append(", id: ");
|
||||
result.append(_id);
|
||||
result.append(", kind: ");
|
||||
result.append(_kind);
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
SimpleLocaleKeyFactory::debugClass(UnicodeString& result) const
|
||||
{
|
||||
return result.append("SimpleLocaleKeyFactory");
|
||||
}
|
||||
#endif
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleLocaleKeyFactory)
|
||||
|
||||
/*
|
||||
******************************************************************
|
||||
*/
|
||||
|
||||
ICUResourceBundleFactory::ICUResourceBundleFactory()
|
||||
: LocaleKeyFactory(VISIBLE)
|
||||
, _bundleName()
|
||||
{
|
||||
}
|
||||
|
||||
ICUResourceBundleFactory::ICUResourceBundleFactory(const UnicodeString& bundleName)
|
||||
: LocaleKeyFactory(VISIBLE)
|
||||
, _bundleName(bundleName)
|
||||
{
|
||||
}
|
||||
|
||||
ICUResourceBundleFactory::~ICUResourceBundleFactory() {}
|
||||
|
||||
const Hashtable*
|
||||
ICUResourceBundleFactory::getSupportedIDs(UErrorCode& status) const
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
return LocaleUtility::getAvailableLocaleNames(_bundleName);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UObject*
|
||||
ICUResourceBundleFactory::handleCreate(const Locale& loc, int32_t /* kind */, const ICUService* /* service */, UErrorCode& status) const
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
// _bundleName is a package name
|
||||
// and should only contain invariant characters
|
||||
char pkg[20];
|
||||
int32_t length;
|
||||
length=_bundleName.extract(0, INT32_MAX, pkg, (int32_t)sizeof(pkg), US_INV);
|
||||
if(length>=(int32_t)sizeof(pkg)) {
|
||||
return NULL;
|
||||
}
|
||||
return new ResourceBundle(pkg, loc, status);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef SERVICE_DEBUG
|
||||
UnicodeString&
|
||||
ICUResourceBundleFactory::debug(UnicodeString& result) const
|
||||
{
|
||||
LocaleKeyFactory::debug(result);
|
||||
result.append(", bundle: ");
|
||||
return result.append(_bundleName);
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
ICUResourceBundleFactory::debugClass(UnicodeString& result) const
|
||||
{
|
||||
return result.append("ICUResourceBundleFactory");
|
||||
}
|
||||
#endif
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ICUResourceBundleFactory)
|
||||
|
||||
/*
|
||||
******************************************************************
|
||||
*/
|
||||
|
||||
ICULocaleService::ICULocaleService()
|
||||
: fallbackLocale(Locale::getDefault())
|
||||
, llock(0)
|
||||
{
|
||||
umtx_init(&llock);
|
||||
}
|
||||
|
||||
ICULocaleService::ICULocaleService(const UnicodeString& dname)
|
||||
: ICUService(dname)
|
||||
, fallbackLocale(Locale::getDefault())
|
||||
, llock(0)
|
||||
{
|
||||
umtx_init(&llock);
|
||||
}
|
||||
|
||||
ICULocaleService::~ICULocaleService()
|
||||
{
|
||||
umtx_destroy(&llock);
|
||||
}
|
||||
|
||||
UObject*
|
||||
ICULocaleService::get(const Locale& locale, UErrorCode& status) const
|
||||
{
|
||||
return get(locale, LocaleKey::KIND_ANY, NULL, status);
|
||||
}
|
||||
|
||||
UObject*
|
||||
ICULocaleService::get(const Locale& locale, int32_t kind, UErrorCode& status) const
|
||||
{
|
||||
return get(locale, kind, NULL, status);
|
||||
}
|
||||
|
||||
UObject*
|
||||
ICULocaleService::get(const Locale& locale, Locale* actualReturn, UErrorCode& status) const
|
||||
{
|
||||
return get(locale, LocaleKey::KIND_ANY, actualReturn, status);
|
||||
}
|
||||
|
||||
UObject*
|
||||
ICULocaleService::get(const Locale& locale, int32_t kind, Locale* actualReturn, UErrorCode& status) const
|
||||
{
|
||||
UObject* result = NULL;
|
||||
if (U_FAILURE(status)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString locName(locale.getName(), -1, US_INV);
|
||||
if (locName.isBogus()) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
ICUServiceKey* key = createKey(&locName, kind, status);
|
||||
if (key) {
|
||||
if (actualReturn == NULL) {
|
||||
result = getKey(*key, status);
|
||||
} else {
|
||||
UnicodeString temp;
|
||||
result = getKey(*key, &temp, status);
|
||||
|
||||
if (result != NULL) {
|
||||
key->parseSuffix(temp);
|
||||
LocaleUtility::initLocaleFromName(temp, *actualReturn);
|
||||
}
|
||||
}
|
||||
delete key;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale,
|
||||
UBool visible, UErrorCode& status)
|
||||
{
|
||||
Locale loc;
|
||||
LocaleUtility::initLocaleFromName(locale, loc);
|
||||
return registerInstance(objToAdopt, loc, LocaleKey::KIND_ANY,
|
||||
visible ? LocaleKeyFactory::VISIBLE : LocaleKeyFactory::INVISIBLE, status);
|
||||
}
|
||||
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, UErrorCode& status)
|
||||
{
|
||||
return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status);
|
||||
}
|
||||
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, UErrorCode& status)
|
||||
{
|
||||
return registerInstance(objToAdopt, locale, kind, LocaleKeyFactory::VISIBLE, status);
|
||||
}
|
||||
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, int32_t coverage, UErrorCode& status)
|
||||
{
|
||||
ICUServiceFactory * factory = new SimpleLocaleKeyFactory(objToAdopt, locale, kind, coverage);
|
||||
if (factory != NULL) {
|
||||
return registerFactory(factory, status);
|
||||
}
|
||||
delete objToAdopt;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, UErrorCode& status)
|
||||
{
|
||||
return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status);
|
||||
}
|
||||
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, UBool visible, UErrorCode& status)
|
||||
{
|
||||
return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY,
|
||||
visible ? LocaleKeyFactory::VISIBLE : LocaleKeyFactory::INVISIBLE,
|
||||
status);
|
||||
}
|
||||
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, int32_t kind, int32_t coverage, UErrorCode& status)
|
||||
{
|
||||
ICUServiceFactory * factory = new SimpleLocaleKeyFactory(objToAdopt, locale, kind, coverage);
|
||||
if (factory != NULL) {
|
||||
return registerFactory(factory, status);
|
||||
}
|
||||
delete objToAdopt;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
class ServiceEnumeration : public StringEnumeration {
|
||||
private:
|
||||
const ICULocaleService* _service;
|
||||
int32_t _timestamp;
|
||||
UVector _ids;
|
||||
int32_t _pos;
|
||||
|
||||
private:
|
||||
ServiceEnumeration(const ICULocaleService* service, UErrorCode &status)
|
||||
: _service(service)
|
||||
, _timestamp(service->getTimestamp())
|
||||
, _ids(uhash_deleteUnicodeString, NULL, status)
|
||||
, _pos(0)
|
||||
{
|
||||
_service->getVisibleIDs(_ids, status);
|
||||
}
|
||||
|
||||
ServiceEnumeration(const ServiceEnumeration &other, UErrorCode &status)
|
||||
: _service(other._service)
|
||||
, _timestamp(other._timestamp)
|
||||
, _ids(uhash_deleteUnicodeString, NULL, status)
|
||||
, _pos(0)
|
||||
{
|
||||
if(U_SUCCESS(status)) {
|
||||
int32_t i, length;
|
||||
|
||||
length = other._ids.size();
|
||||
for(i = 0; i < length; ++i) {
|
||||
_ids.addElement(((UnicodeString *)other._ids.elementAt(i))->clone(), status);
|
||||
}
|
||||
|
||||
if(U_SUCCESS(status)) {
|
||||
_pos = other._pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static ServiceEnumeration* create(const ICULocaleService* service) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
ServiceEnumeration* result = new ServiceEnumeration(service, status);
|
||||
if (U_SUCCESS(status)) {
|
||||
return result;
|
||||
}
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual ~ServiceEnumeration() {}
|
||||
|
||||
virtual StringEnumeration *clone() const {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
ServiceEnumeration *cl = new ServiceEnumeration(*this, status);
|
||||
if(U_FAILURE(status)) {
|
||||
delete cl;
|
||||
cl = NULL;
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
|
||||
UBool upToDate(UErrorCode& status) const {
|
||||
if (U_SUCCESS(status)) {
|
||||
if (_timestamp == _service->getTimestamp()) {
|
||||
return TRUE;
|
||||
}
|
||||
status = U_ENUM_OUT_OF_SYNC_ERROR;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
virtual int32_t count(UErrorCode& status) const {
|
||||
return upToDate(status) ? _ids.size() : 0;
|
||||
}
|
||||
|
||||
virtual const UnicodeString* snext(UErrorCode& status) {
|
||||
if (upToDate(status) && (_pos < _ids.size())) {
|
||||
return (const UnicodeString*)_ids[_pos++];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual void reset(UErrorCode& status) {
|
||||
if (status == U_ENUM_OUT_OF_SYNC_ERROR) {
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
if (U_SUCCESS(status)) {
|
||||
_timestamp = _service->getTimestamp();
|
||||
_pos = 0;
|
||||
_service->getVisibleIDs(_ids, status);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static UClassID U_EXPORT2 getStaticClassID(void);
|
||||
virtual UClassID getDynamicClassID(void) const;
|
||||
};
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration)
|
||||
|
||||
StringEnumeration*
|
||||
ICULocaleService::getAvailableLocales(void) const
|
||||
{
|
||||
return ServiceEnumeration::create(this);
|
||||
}
|
||||
|
||||
const UnicodeString&
|
||||
ICULocaleService::validateFallbackLocale() const
|
||||
{
|
||||
const Locale& loc = Locale::getDefault();
|
||||
ICULocaleService* ncThis = (ICULocaleService*)this;
|
||||
{
|
||||
Mutex mutex(&ncThis->llock);
|
||||
if (loc != fallbackLocale) {
|
||||
ncThis->fallbackLocale = loc;
|
||||
LocaleUtility::initNameFromLocale(loc, ncThis->fallbackLocaleName);
|
||||
ncThis->clearServiceCache();
|
||||
}
|
||||
}
|
||||
return fallbackLocaleName;
|
||||
}
|
||||
|
||||
ICUServiceKey*
|
||||
ICULocaleService::createKey(const UnicodeString* id, UErrorCode& status) const
|
||||
{
|
||||
return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), status);
|
||||
}
|
||||
|
||||
ICUServiceKey*
|
||||
ICULocaleService::createKey(const UnicodeString* id, int32_t kind, UErrorCode& status) const
|
||||
{
|
||||
return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), kind, status);
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/* !UCONFIG_NO_SERVICE */
|
||||
#endif
|
||||
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
|
||||
#include "icuserv.h"
|
||||
#include "serv.h"
|
||||
#include "umutex.h"
|
||||
|
||||
#undef SERVICE_REFCOUNT
|
|
@ -29,7 +29,7 @@ U_NAMESPACE_END
|
|||
|
||||
#include "hash.h"
|
||||
#include "uvector.h"
|
||||
#include "icunotif.h"
|
||||
#include "servnotf.h"
|
||||
|
||||
class ICUServiceTest;
|
||||
|
187
icu4c/source/common/servlk.cpp
Normal file
187
icu4c/source/common/servlk.cpp
Normal file
|
@ -0,0 +1,187 @@
|
|||
/**
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2001-2004, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
|
||||
#include "unicode/resbund.h"
|
||||
#include "uresimp.h"
|
||||
#include "cmemory.h"
|
||||
#include "servloc.h"
|
||||
#include "ustrfmt.h"
|
||||
#include "uhash.h"
|
||||
#include "charstr.h"
|
||||
#include "ucln_cmn.h"
|
||||
#include "uassert.h"
|
||||
|
||||
#define UNDERSCORE_CHAR ((UChar)0x005f)
|
||||
#define AT_SIGN_CHAR ((UChar)64)
|
||||
#define PERIOD_CHAR ((UChar)46)
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
LocaleKey*
|
||||
LocaleKey::createWithCanonicalFallback(const UnicodeString* primaryID,
|
||||
const UnicodeString* canonicalFallbackID,
|
||||
UErrorCode& status)
|
||||
{
|
||||
return LocaleKey::createWithCanonicalFallback(primaryID, canonicalFallbackID, KIND_ANY, status);
|
||||
}
|
||||
|
||||
LocaleKey*
|
||||
LocaleKey::createWithCanonicalFallback(const UnicodeString* primaryID,
|
||||
const UnicodeString* canonicalFallbackID,
|
||||
int32_t kind,
|
||||
UErrorCode& status)
|
||||
{
|
||||
if (primaryID == NULL || U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
UnicodeString canonicalPrimaryID;
|
||||
LocaleUtility::canonicalLocaleString(primaryID, canonicalPrimaryID);
|
||||
return new LocaleKey(*primaryID, canonicalPrimaryID, canonicalFallbackID, kind);
|
||||
}
|
||||
|
||||
LocaleKey::LocaleKey(const UnicodeString& primaryID,
|
||||
const UnicodeString& canonicalPrimaryID,
|
||||
const UnicodeString* canonicalFallbackID,
|
||||
int32_t kind)
|
||||
: ICUServiceKey(primaryID)
|
||||
, _kind(kind)
|
||||
, _primaryID(canonicalPrimaryID)
|
||||
, _fallbackID()
|
||||
, _currentID()
|
||||
{
|
||||
_fallbackID.setToBogus();
|
||||
if (_primaryID.length() != 0) {
|
||||
if (canonicalFallbackID != NULL && _primaryID != *canonicalFallbackID) {
|
||||
_fallbackID = *canonicalFallbackID;
|
||||
}
|
||||
}
|
||||
|
||||
_currentID = _primaryID;
|
||||
}
|
||||
|
||||
LocaleKey::~LocaleKey() {}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKey::prefix(UnicodeString& result) const {
|
||||
if (_kind != KIND_ANY) {
|
||||
UChar buffer[64];
|
||||
uprv_itou(buffer, 64, _kind, 10, 0);
|
||||
UnicodeString temp(buffer);
|
||||
result.append(temp);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t
|
||||
LocaleKey::kind() const {
|
||||
return _kind;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKey::canonicalID(UnicodeString& result) const {
|
||||
return result.append(_primaryID);
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKey::currentID(UnicodeString& result) const {
|
||||
if (!_currentID.isBogus()) {
|
||||
result.append(_currentID);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKey::currentDescriptor(UnicodeString& result) const {
|
||||
if (!_currentID.isBogus()) {
|
||||
prefix(result).append(PREFIX_DELIMITER).append(_currentID);
|
||||
} else {
|
||||
result.setToBogus();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Locale&
|
||||
LocaleKey::canonicalLocale(Locale& result) const {
|
||||
return LocaleUtility::initLocaleFromName(_primaryID, result);
|
||||
}
|
||||
|
||||
Locale&
|
||||
LocaleKey::currentLocale(Locale& result) const {
|
||||
return LocaleUtility::initLocaleFromName(_currentID, result);
|
||||
}
|
||||
|
||||
UBool
|
||||
LocaleKey::fallback() {
|
||||
if (!_currentID.isBogus()) {
|
||||
int x = _currentID.lastIndexOf(UNDERSCORE_CHAR);
|
||||
if (x != -1) {
|
||||
_currentID.remove(x); // truncate current or fallback, whichever we're pointing to
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!_fallbackID.isBogus()) {
|
||||
_currentID = _fallbackID;
|
||||
_fallbackID.setToBogus();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (_currentID.length() > 0) {
|
||||
_currentID.remove(0); // completely truncate
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_currentID.setToBogus();
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
UBool
|
||||
LocaleKey::isFallbackOf(const UnicodeString& id) const {
|
||||
UnicodeString temp(id);
|
||||
parseSuffix(temp);
|
||||
return temp.indexOf(_primaryID) == 0 &&
|
||||
(temp.length() == _primaryID.length() ||
|
||||
temp.charAt(_primaryID.length()) == UNDERSCORE_CHAR);
|
||||
}
|
||||
|
||||
#ifdef SERVICE_DEBUG
|
||||
UnicodeString&
|
||||
LocaleKey::debug(UnicodeString& result) const
|
||||
{
|
||||
ICUServiceKey::debug(result);
|
||||
result.append(" kind: ");
|
||||
result.append(_kind);
|
||||
result.append(" primaryID: ");
|
||||
result.append(_primaryID);
|
||||
result.append(" fallbackID: ");
|
||||
result.append(_fallbackID);
|
||||
result.append(" currentID: ");
|
||||
result.append(_currentID);
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKey::debugClass(UnicodeString& result) const
|
||||
{
|
||||
return result.append("LocaleKey ");
|
||||
}
|
||||
#endif
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LocaleKey)
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/* !UCONFIG_NO_SERVICE */
|
||||
#endif
|
||||
|
||||
|
151
icu4c/source/common/servlkf.cpp
Normal file
151
icu4c/source/common/servlkf.cpp
Normal file
|
@ -0,0 +1,151 @@
|
|||
/**
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2001-2004, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
|
||||
#include "unicode/resbund.h"
|
||||
#include "uresimp.h"
|
||||
#include "cmemory.h"
|
||||
#include "servloc.h"
|
||||
#include "ustrfmt.h"
|
||||
#include "uhash.h"
|
||||
#include "charstr.h"
|
||||
#include "ucln_cmn.h"
|
||||
#include "uassert.h"
|
||||
|
||||
#define UNDERSCORE_CHAR ((UChar)0x005f)
|
||||
#define AT_SIGN_CHAR ((UChar)64)
|
||||
#define PERIOD_CHAR ((UChar)46)
|
||||
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
LocaleKeyFactory::LocaleKeyFactory(int32_t coverage)
|
||||
: _name()
|
||||
, _coverage(coverage)
|
||||
{
|
||||
}
|
||||
|
||||
LocaleKeyFactory::LocaleKeyFactory(int32_t coverage, const UnicodeString& name)
|
||||
: _name(name)
|
||||
, _coverage(coverage)
|
||||
{
|
||||
}
|
||||
|
||||
LocaleKeyFactory::~LocaleKeyFactory() {
|
||||
}
|
||||
|
||||
UObject*
|
||||
LocaleKeyFactory::create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const {
|
||||
if (handlesKey(key, status)) {
|
||||
const LocaleKey& lkey = (const LocaleKey&)key;
|
||||
int32_t kind = lkey.kind();
|
||||
Locale loc;
|
||||
lkey.currentLocale(loc);
|
||||
|
||||
return handleCreate(loc, kind, service, status);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UBool
|
||||
LocaleKeyFactory::handlesKey(const ICUServiceKey& key, UErrorCode& status) const {
|
||||
const Hashtable* supported = getSupportedIDs(status);
|
||||
if (supported) {
|
||||
UnicodeString id;
|
||||
key.currentID(id);
|
||||
return supported->get(id) != NULL;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
LocaleKeyFactory::updateVisibleIDs(Hashtable& result, UErrorCode& status) const {
|
||||
const Hashtable* supported = getSupportedIDs(status);
|
||||
if (supported) {
|
||||
UBool visible = (_coverage & 0x1) == 0;
|
||||
|
||||
const UHashElement* elem = NULL;
|
||||
int32_t pos = 0;
|
||||
while ((elem = supported->nextElement(pos)) != NULL) {
|
||||
const UnicodeString& id = *((const UnicodeString*)elem->key.pointer);
|
||||
if (!visible) {
|
||||
result.remove(id);
|
||||
} else {
|
||||
result.put(id, (void*)this, status); // this is dummy non-void marker used for set semantics
|
||||
if (U_FAILURE(status)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKeyFactory::getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const {
|
||||
if ((_coverage & 0x1) == 0) {
|
||||
//UErrorCode status = U_ZERO_ERROR;
|
||||
// assume if this is called on us, we support some fallback of this id
|
||||
// if (isSupportedID(id, status)) {
|
||||
Locale loc;
|
||||
LocaleUtility::initLocaleFromName(id, loc);
|
||||
return loc.getDisplayName(locale, result);
|
||||
// }
|
||||
}
|
||||
result.setToBogus();
|
||||
return result;
|
||||
}
|
||||
|
||||
UObject*
|
||||
LocaleKeyFactory::handleCreate(const Locale& /* loc */,
|
||||
int32_t /* kind */,
|
||||
const ICUService* /* service */,
|
||||
UErrorCode& /* status */) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UBool
|
||||
LocaleKeyFactory::isSupportedID(const UnicodeString& id, UErrorCode& status) const {
|
||||
const Hashtable* ids = getSupportedIDs(status);
|
||||
return ids && ids->get(id);
|
||||
}
|
||||
|
||||
const Hashtable*
|
||||
LocaleKeyFactory::getSupportedIDs(UErrorCode& /* status */) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef SERVICE_DEBUG
|
||||
UnicodeString&
|
||||
LocaleKeyFactory::debug(UnicodeString& result) const
|
||||
{
|
||||
debugClass(result);
|
||||
result.append(", name: ");
|
||||
result.append(_name);
|
||||
result.append(", coverage: ");
|
||||
result.append(_coverage);
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleKeyFactory::debugClass(UnicodeString& result) const
|
||||
{
|
||||
return result.append("LocaleKeyFactory");
|
||||
}
|
||||
#endif
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LocaleKeyFactory)
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/* !UCONFIG_NO_SERVICE */
|
||||
#endif
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ U_NAMESPACE_END
|
|||
#include "hash.h"
|
||||
#include "uvector.h"
|
||||
|
||||
#include "icuserv.h"
|
||||
#include "serv.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
297
icu4c/source/common/servls.cpp
Normal file
297
icu4c/source/common/servls.cpp
Normal file
|
@ -0,0 +1,297 @@
|
|||
/**
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2001-2004, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
|
||||
#include "unicode/resbund.h"
|
||||
#include "uresimp.h"
|
||||
#include "cmemory.h"
|
||||
#include "servloc.h"
|
||||
#include "ustrfmt.h"
|
||||
#include "uhash.h"
|
||||
#include "charstr.h"
|
||||
#include "ucln_cmn.h"
|
||||
#include "uassert.h"
|
||||
|
||||
#define UNDERSCORE_CHAR ((UChar)0x005f)
|
||||
#define AT_SIGN_CHAR ((UChar)64)
|
||||
#define PERIOD_CHAR ((UChar)46)
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
ICULocaleService::ICULocaleService()
|
||||
: fallbackLocale(Locale::getDefault())
|
||||
, llock(0)
|
||||
{
|
||||
umtx_init(&llock);
|
||||
}
|
||||
|
||||
ICULocaleService::ICULocaleService(const UnicodeString& dname)
|
||||
: ICUService(dname)
|
||||
, fallbackLocale(Locale::getDefault())
|
||||
, llock(0)
|
||||
{
|
||||
umtx_init(&llock);
|
||||
}
|
||||
|
||||
ICULocaleService::~ICULocaleService()
|
||||
{
|
||||
umtx_destroy(&llock);
|
||||
}
|
||||
|
||||
UObject*
|
||||
ICULocaleService::get(const Locale& locale, UErrorCode& status) const
|
||||
{
|
||||
return get(locale, LocaleKey::KIND_ANY, NULL, status);
|
||||
}
|
||||
|
||||
UObject*
|
||||
ICULocaleService::get(const Locale& locale, int32_t kind, UErrorCode& status) const
|
||||
{
|
||||
return get(locale, kind, NULL, status);
|
||||
}
|
||||
|
||||
UObject*
|
||||
ICULocaleService::get(const Locale& locale, Locale* actualReturn, UErrorCode& status) const
|
||||
{
|
||||
return get(locale, LocaleKey::KIND_ANY, actualReturn, status);
|
||||
}
|
||||
|
||||
UObject*
|
||||
ICULocaleService::get(const Locale& locale, int32_t kind, Locale* actualReturn, UErrorCode& status) const
|
||||
{
|
||||
UObject* result = NULL;
|
||||
if (U_FAILURE(status)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString locName(locale.getName(), -1, US_INV);
|
||||
if (locName.isBogus()) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
ICUServiceKey* key = createKey(&locName, kind, status);
|
||||
if (key) {
|
||||
if (actualReturn == NULL) {
|
||||
result = getKey(*key, status);
|
||||
} else {
|
||||
UnicodeString temp;
|
||||
result = getKey(*key, &temp, status);
|
||||
|
||||
if (result != NULL) {
|
||||
key->parseSuffix(temp);
|
||||
LocaleUtility::initLocaleFromName(temp, *actualReturn);
|
||||
}
|
||||
}
|
||||
delete key;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale,
|
||||
UBool visible, UErrorCode& status)
|
||||
{
|
||||
Locale loc;
|
||||
LocaleUtility::initLocaleFromName(locale, loc);
|
||||
return registerInstance(objToAdopt, loc, LocaleKey::KIND_ANY,
|
||||
visible ? LocaleKeyFactory::VISIBLE : LocaleKeyFactory::INVISIBLE, status);
|
||||
}
|
||||
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, UErrorCode& status)
|
||||
{
|
||||
return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status);
|
||||
}
|
||||
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, UErrorCode& status)
|
||||
{
|
||||
return registerInstance(objToAdopt, locale, kind, LocaleKeyFactory::VISIBLE, status);
|
||||
}
|
||||
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, int32_t coverage, UErrorCode& status)
|
||||
{
|
||||
ICUServiceFactory * factory = new SimpleLocaleKeyFactory(objToAdopt, locale, kind, coverage);
|
||||
if (factory != NULL) {
|
||||
return registerFactory(factory, status);
|
||||
}
|
||||
delete objToAdopt;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, UErrorCode& status)
|
||||
{
|
||||
return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status);
|
||||
}
|
||||
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, UBool visible, UErrorCode& status)
|
||||
{
|
||||
return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY,
|
||||
visible ? LocaleKeyFactory::VISIBLE : LocaleKeyFactory::INVISIBLE,
|
||||
status);
|
||||
}
|
||||
|
||||
URegistryKey
|
||||
ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, int32_t kind, int32_t coverage, UErrorCode& status)
|
||||
{
|
||||
ICUServiceFactory * factory = new SimpleLocaleKeyFactory(objToAdopt, locale, kind, coverage);
|
||||
if (factory != NULL) {
|
||||
return registerFactory(factory, status);
|
||||
}
|
||||
delete objToAdopt;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
class ServiceEnumeration : public StringEnumeration {
|
||||
private:
|
||||
const ICULocaleService* _service;
|
||||
int32_t _timestamp;
|
||||
UVector _ids;
|
||||
int32_t _pos;
|
||||
|
||||
private:
|
||||
ServiceEnumeration(const ICULocaleService* service, UErrorCode &status)
|
||||
: _service(service)
|
||||
, _timestamp(service->getTimestamp())
|
||||
, _ids(uhash_deleteUnicodeString, NULL, status)
|
||||
, _pos(0)
|
||||
{
|
||||
_service->getVisibleIDs(_ids, status);
|
||||
}
|
||||
|
||||
ServiceEnumeration(const ServiceEnumeration &other, UErrorCode &status)
|
||||
: _service(other._service)
|
||||
, _timestamp(other._timestamp)
|
||||
, _ids(uhash_deleteUnicodeString, NULL, status)
|
||||
, _pos(0)
|
||||
{
|
||||
if(U_SUCCESS(status)) {
|
||||
int32_t i, length;
|
||||
|
||||
length = other._ids.size();
|
||||
for(i = 0; i < length; ++i) {
|
||||
_ids.addElement(((UnicodeString *)other._ids.elementAt(i))->clone(), status);
|
||||
}
|
||||
|
||||
if(U_SUCCESS(status)) {
|
||||
_pos = other._pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static ServiceEnumeration* create(const ICULocaleService* service) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
ServiceEnumeration* result = new ServiceEnumeration(service, status);
|
||||
if (U_SUCCESS(status)) {
|
||||
return result;
|
||||
}
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual ~ServiceEnumeration() {}
|
||||
|
||||
virtual StringEnumeration *clone() const {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
ServiceEnumeration *cl = new ServiceEnumeration(*this, status);
|
||||
if(U_FAILURE(status)) {
|
||||
delete cl;
|
||||
cl = NULL;
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
|
||||
UBool upToDate(UErrorCode& status) const {
|
||||
if (U_SUCCESS(status)) {
|
||||
if (_timestamp == _service->getTimestamp()) {
|
||||
return TRUE;
|
||||
}
|
||||
status = U_ENUM_OUT_OF_SYNC_ERROR;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
virtual int32_t count(UErrorCode& status) const {
|
||||
return upToDate(status) ? _ids.size() : 0;
|
||||
}
|
||||
|
||||
virtual const UnicodeString* snext(UErrorCode& status) {
|
||||
if (upToDate(status) && (_pos < _ids.size())) {
|
||||
return (const UnicodeString*)_ids[_pos++];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual void reset(UErrorCode& status) {
|
||||
if (status == U_ENUM_OUT_OF_SYNC_ERROR) {
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
if (U_SUCCESS(status)) {
|
||||
_timestamp = _service->getTimestamp();
|
||||
_pos = 0;
|
||||
_service->getVisibleIDs(_ids, status);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static UClassID U_EXPORT2 getStaticClassID(void);
|
||||
virtual UClassID getDynamicClassID(void) const;
|
||||
};
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration)
|
||||
|
||||
StringEnumeration*
|
||||
ICULocaleService::getAvailableLocales(void) const
|
||||
{
|
||||
return ServiceEnumeration::create(this);
|
||||
}
|
||||
|
||||
const UnicodeString&
|
||||
ICULocaleService::validateFallbackLocale() const
|
||||
{
|
||||
const Locale& loc = Locale::getDefault();
|
||||
ICULocaleService* ncThis = (ICULocaleService*)this;
|
||||
{
|
||||
Mutex mutex(&ncThis->llock);
|
||||
if (loc != fallbackLocale) {
|
||||
ncThis->fallbackLocale = loc;
|
||||
LocaleUtility::initNameFromLocale(loc, ncThis->fallbackLocaleName);
|
||||
ncThis->clearServiceCache();
|
||||
}
|
||||
}
|
||||
return fallbackLocaleName;
|
||||
}
|
||||
|
||||
ICUServiceKey*
|
||||
ICULocaleService::createKey(const UnicodeString* id, UErrorCode& status) const
|
||||
{
|
||||
return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), status);
|
||||
}
|
||||
|
||||
ICUServiceKey*
|
||||
ICULocaleService::createKey(const UnicodeString* id, int32_t kind, UErrorCode& status) const
|
||||
{
|
||||
return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), kind, status);
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/* !UCONFIG_NO_SERVICE */
|
||||
#endif
|
||||
|
||||
|
266
icu4c/source/common/servlu.cpp
Normal file
266
icu4c/source/common/servlu.cpp
Normal file
|
@ -0,0 +1,266 @@
|
|||
/**
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2001-2004, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
|
||||
#include "unicode/resbund.h"
|
||||
#include "uresimp.h"
|
||||
#include "cmemory.h"
|
||||
#include "servloc.h"
|
||||
#include "ustrfmt.h"
|
||||
#include "uhash.h"
|
||||
#include "charstr.h"
|
||||
#include "ucln_cmn.h"
|
||||
#include "uassert.h"
|
||||
|
||||
// see LocaleUtility::getAvailableLocaleNames
|
||||
static Hashtable * LocaleUtility_cache = NULL;
|
||||
|
||||
#define UNDERSCORE_CHAR ((UChar)0x005f)
|
||||
#define AT_SIGN_CHAR ((UChar)64)
|
||||
#define PERIOD_CHAR ((UChar)46)
|
||||
|
||||
/*
|
||||
******************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Release all static memory held by Locale Utility.
|
||||
*/
|
||||
U_CDECL_BEGIN
|
||||
static UBool U_CALLCONV service_cleanup(void) {
|
||||
if (LocaleUtility_cache) {
|
||||
delete LocaleUtility_cache;
|
||||
LocaleUtility_cache = NULL;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
U_CDECL_END
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
UnicodeString&
|
||||
LocaleUtility::canonicalLocaleString(const UnicodeString* id, UnicodeString& result)
|
||||
{
|
||||
if (id == NULL) {
|
||||
result.setToBogus();
|
||||
} else {
|
||||
// Fix case only (no other changes) up to the first '@' or '.' or
|
||||
// end of string, whichever comes first. In 3.0 I changed this to
|
||||
// stop at first '@' or '.'. It used to run out to the end of
|
||||
// string. My fix makes the tests pass but is probably
|
||||
// structurally incorrect. See below. [alan 3.0]
|
||||
|
||||
// TODO: Doug, you might want to revise this...
|
||||
result = *id;
|
||||
int32_t i = 0;
|
||||
int32_t end = result.indexOf(AT_SIGN_CHAR);
|
||||
int32_t n = result.indexOf(PERIOD_CHAR);
|
||||
if (n >= 0 && n < end) {
|
||||
end = n;
|
||||
}
|
||||
if (end < 0) {
|
||||
end = result.length();
|
||||
}
|
||||
n = result.indexOf(UNDERSCORE_CHAR);
|
||||
if (n < 0) {
|
||||
n = end;
|
||||
}
|
||||
for (; i < n; ++i) {
|
||||
UChar c = result.charAt(i);
|
||||
if (c >= 0x0041 && c <= 0x005a) {
|
||||
c += 0x20;
|
||||
result.setCharAt(i, c);
|
||||
}
|
||||
}
|
||||
for (n = end; i < n; ++i) {
|
||||
UChar c = result.charAt(i);
|
||||
if (c >= 0x0061 && c <= 0x007a) {
|
||||
c -= 0x20;
|
||||
result.setCharAt(i, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
#if 0
|
||||
// This code does a proper full level 2 canonicalization of id.
|
||||
// It's nasty to go from UChar to char to char to UChar -- but
|
||||
// that's what you have to do to use the uloc_canonicalize
|
||||
// function on UnicodeStrings.
|
||||
|
||||
// I ended up doing the alternate fix (see above) not for
|
||||
// performance reasons, although performance will certainly be
|
||||
// better, but because doing a full level 2 canonicalization
|
||||
// causes some tests to fail. [alan 3.0]
|
||||
|
||||
// TODO: Doug, you might want to revisit this...
|
||||
result.setToBogus();
|
||||
if (id != 0) {
|
||||
int32_t buflen = id->length() + 8; // space for NUL
|
||||
char* buf = (char*) uprv_malloc(buflen);
|
||||
char* canon = (buf == 0) ? 0 : (char*) uprv_malloc(buflen);
|
||||
if (buf != 0 && canon != 0) {
|
||||
U_ASSERT(id->extract(0, INT32_MAX, buf, buflen) < buflen);
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
uloc_canonicalize(buf, canon, buflen, &ec);
|
||||
if (U_SUCCESS(ec)) {
|
||||
result = UnicodeString(canon);
|
||||
}
|
||||
}
|
||||
uprv_free(buf);
|
||||
uprv_free(canon);
|
||||
}
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
Locale&
|
||||
LocaleUtility::initLocaleFromName(const UnicodeString& id, Locale& result)
|
||||
{
|
||||
enum { BUFLEN = 128 }; // larger than ever needed
|
||||
|
||||
if (id.isBogus() || id.length() >= BUFLEN) {
|
||||
result.setToBogus();
|
||||
} else {
|
||||
/*
|
||||
* We need to convert from a UnicodeString to char * in order to
|
||||
* create a Locale.
|
||||
*
|
||||
* Problem: Locale ID strings may contain '@' which is a variant
|
||||
* character and cannot be handled by invariant-character conversion.
|
||||
*
|
||||
* Hack: Since ICU code can handle locale IDs with multiple encodings
|
||||
* of '@' (at least for EBCDIC; it's not known to be a problem for
|
||||
* ASCII-based systems),
|
||||
* we use regular invariant-character conversion for everything else
|
||||
* and manually convert U+0040 into a compiler-char-constant '@'.
|
||||
* While this compilation-time constant may not match the runtime
|
||||
* encoding of '@', it should be one of the encodings which ICU
|
||||
* recognizes.
|
||||
*
|
||||
* There should be only at most one '@' in a locale ID.
|
||||
*/
|
||||
char buffer[BUFLEN];
|
||||
int32_t prev, i;
|
||||
prev = 0;
|
||||
for(;;) {
|
||||
i = id.indexOf((UChar)0x40, prev);
|
||||
if(i < 0) {
|
||||
// no @ between prev and the rest of the string
|
||||
id.extract(prev, INT32_MAX, buffer + prev, BUFLEN - prev, US_INV);
|
||||
break; // done
|
||||
} else {
|
||||
// normal invariant-character conversion for text between @s
|
||||
id.extract(prev, i - prev, buffer + prev, BUFLEN - prev, US_INV);
|
||||
// manually "convert" U+0040 at id[i] into '@' at buffer[i]
|
||||
buffer[i] = '@';
|
||||
prev = i + 1;
|
||||
}
|
||||
}
|
||||
result = Locale::createFromName(buffer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
LocaleUtility::initNameFromLocale(const Locale& locale, UnicodeString& result)
|
||||
{
|
||||
if (locale.isBogus()) {
|
||||
result.setToBogus();
|
||||
} else {
|
||||
result.append(UnicodeString(locale.getName(), -1, US_INV));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const Hashtable*
|
||||
LocaleUtility::getAvailableLocaleNames(const UnicodeString& bundleID)
|
||||
{
|
||||
// LocaleUtility_cache is a hash-of-hashes. The top-level keys
|
||||
// are path strings ('bundleID') passed to
|
||||
// ures_openAvailableLocales. The top-level values are
|
||||
// second-level hashes. The second-level keys are result strings
|
||||
// from ures_openAvailableLocales. The second-level values are
|
||||
// garbage ((void*)1 or other random pointer).
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
Hashtable* cache;
|
||||
umtx_lock(NULL);
|
||||
cache = LocaleUtility_cache;
|
||||
umtx_unlock(NULL);
|
||||
|
||||
if (cache == NULL) {
|
||||
cache = new Hashtable(status);
|
||||
if (cache == NULL || U_FAILURE(status)) {
|
||||
return NULL; // catastrophic failure; e.g. out of memory
|
||||
}
|
||||
cache->setValueDeleter(uhash_deleteHashtable);
|
||||
Hashtable* h; // set this to final LocaleUtility_cache value
|
||||
umtx_lock(NULL);
|
||||
h = LocaleUtility_cache;
|
||||
if (h == NULL) {
|
||||
LocaleUtility_cache = h = cache;
|
||||
cache = NULL;
|
||||
ucln_common_registerCleanup(UCLN_COMMON_SERVICE, service_cleanup);
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
delete cache;
|
||||
cache = h;
|
||||
}
|
||||
|
||||
U_ASSERT(cache != NULL);
|
||||
|
||||
Hashtable* htp;
|
||||
umtx_lock(NULL);
|
||||
htp = (Hashtable*) cache->get(bundleID);
|
||||
umtx_unlock(NULL);
|
||||
|
||||
if (htp == NULL) {
|
||||
htp = new Hashtable(status);
|
||||
if (htp && U_SUCCESS(status)) {
|
||||
CharString cbundleID(bundleID);
|
||||
const char* path = (const char*) cbundleID;
|
||||
if (*path == 0) path = NULL; // empty string => NULL
|
||||
UEnumeration *uenum = ures_openAvailableLocales(path, &status);
|
||||
for (;;) {
|
||||
const UChar* id = uenum_unext(uenum, NULL, &status);
|
||||
if (id == NULL) {
|
||||
break;
|
||||
}
|
||||
htp->put(UnicodeString(id), (void*)htp, status);
|
||||
}
|
||||
uenum_close(uenum);
|
||||
if (U_FAILURE(status)) {
|
||||
delete htp;
|
||||
return NULL;
|
||||
}
|
||||
umtx_lock(NULL);
|
||||
cache->put(bundleID, (void*)htp, status);
|
||||
umtx_unlock(NULL);
|
||||
}
|
||||
}
|
||||
return htp;
|
||||
}
|
||||
|
||||
UBool
|
||||
LocaleUtility::isFallbackOf(const UnicodeString& root, const UnicodeString& child)
|
||||
{
|
||||
return child.indexOf(root) == 0 &&
|
||||
(child.length() == root.length() ||
|
||||
child.charAt(root.length()) == UNDERSCORE_CHAR);
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/* !UCONFIG_NO_SERVICE */
|
||||
#endif
|
||||
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
|
||||
#include "icunotif.h"
|
||||
#include "servnotf.h"
|
||||
#ifdef NOTIFIER_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
92
icu4c/source/common/servrbf.cpp
Normal file
92
icu4c/source/common/servrbf.cpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2001-2004, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
|
||||
#include "unicode/resbund.h"
|
||||
#include "uresimp.h"
|
||||
#include "cmemory.h"
|
||||
#include "servloc.h"
|
||||
#include "ustrfmt.h"
|
||||
#include "uhash.h"
|
||||
#include "charstr.h"
|
||||
#include "ucln_cmn.h"
|
||||
#include "uassert.h"
|
||||
|
||||
#define UNDERSCORE_CHAR ((UChar)0x005f)
|
||||
#define AT_SIGN_CHAR ((UChar)64)
|
||||
#define PERIOD_CHAR ((UChar)46)
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
ICUResourceBundleFactory::ICUResourceBundleFactory()
|
||||
: LocaleKeyFactory(VISIBLE)
|
||||
, _bundleName()
|
||||
{
|
||||
}
|
||||
|
||||
ICUResourceBundleFactory::ICUResourceBundleFactory(const UnicodeString& bundleName)
|
||||
: LocaleKeyFactory(VISIBLE)
|
||||
, _bundleName(bundleName)
|
||||
{
|
||||
}
|
||||
|
||||
ICUResourceBundleFactory::~ICUResourceBundleFactory() {}
|
||||
|
||||
const Hashtable*
|
||||
ICUResourceBundleFactory::getSupportedIDs(UErrorCode& status) const
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
return LocaleUtility::getAvailableLocaleNames(_bundleName);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UObject*
|
||||
ICUResourceBundleFactory::handleCreate(const Locale& loc, int32_t /* kind */, const ICUService* /* service */, UErrorCode& status) const
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
// _bundleName is a package name
|
||||
// and should only contain invariant characters
|
||||
char pkg[20];
|
||||
int32_t length;
|
||||
length=_bundleName.extract(0, INT32_MAX, pkg, (int32_t)sizeof(pkg), US_INV);
|
||||
if(length>=(int32_t)sizeof(pkg)) {
|
||||
return NULL;
|
||||
}
|
||||
return new ResourceBundle(pkg, loc, status);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef SERVICE_DEBUG
|
||||
UnicodeString&
|
||||
ICUResourceBundleFactory::debug(UnicodeString& result) const
|
||||
{
|
||||
LocaleKeyFactory::debug(result);
|
||||
result.append(", bundle: ");
|
||||
return result.append(_bundleName);
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
ICUResourceBundleFactory::debugClass(UnicodeString& result) const
|
||||
{
|
||||
return result.append("ICUResourceBundleFactory");
|
||||
}
|
||||
#endif
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ICUResourceBundleFactory)
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/* !UCONFIG_NO_SERVICE */
|
||||
#endif
|
||||
|
||||
|
122
icu4c/source/common/servslkf.cpp
Normal file
122
icu4c/source/common/servslkf.cpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
/**
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2001-2004, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
|
||||
#include "unicode/resbund.h"
|
||||
#include "uresimp.h"
|
||||
#include "cmemory.h"
|
||||
#include "servloc.h"
|
||||
#include "ustrfmt.h"
|
||||
#include "uhash.h"
|
||||
#include "charstr.h"
|
||||
#include "ucln_cmn.h"
|
||||
#include "uassert.h"
|
||||
|
||||
#define UNDERSCORE_CHAR ((UChar)0x005f)
|
||||
#define AT_SIGN_CHAR ((UChar)64)
|
||||
#define PERIOD_CHAR ((UChar)46)
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
/*
|
||||
******************************************************************
|
||||
*/
|
||||
|
||||
SimpleLocaleKeyFactory::SimpleLocaleKeyFactory(UObject* objToAdopt,
|
||||
const UnicodeString& locale,
|
||||
int32_t kind,
|
||||
int32_t coverage)
|
||||
: LocaleKeyFactory(coverage)
|
||||
, _obj(objToAdopt)
|
||||
, _id(locale)
|
||||
, _kind(kind)
|
||||
{
|
||||
}
|
||||
|
||||
SimpleLocaleKeyFactory::SimpleLocaleKeyFactory(UObject* objToAdopt,
|
||||
const Locale& locale,
|
||||
int32_t kind,
|
||||
int32_t coverage)
|
||||
: LocaleKeyFactory(coverage)
|
||||
, _obj(objToAdopt)
|
||||
, _id()
|
||||
, _kind(kind)
|
||||
{
|
||||
LocaleUtility::initNameFromLocale(locale, _id);
|
||||
}
|
||||
|
||||
SimpleLocaleKeyFactory::~SimpleLocaleKeyFactory()
|
||||
{
|
||||
delete _obj;
|
||||
_obj = NULL;
|
||||
}
|
||||
|
||||
UObject*
|
||||
SimpleLocaleKeyFactory::create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
const LocaleKey& lkey = (const LocaleKey&)key;
|
||||
if (_kind == LocaleKey::KIND_ANY || _kind == lkey.kind()) {
|
||||
UnicodeString keyID;
|
||||
lkey.currentID(keyID);
|
||||
if (_id == keyID) {
|
||||
return service->cloneInstance(_obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UBool
|
||||
SimpleLocaleKeyFactory::isSupportedID(const UnicodeString& id, UErrorCode& /* status */) const
|
||||
{
|
||||
return id == _id;
|
||||
}
|
||||
|
||||
void
|
||||
SimpleLocaleKeyFactory::updateVisibleIDs(Hashtable& result, UErrorCode& status) const
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
if (_coverage & 0x1) {
|
||||
result.remove(_id);
|
||||
} else {
|
||||
result.put(_id, (void*)this, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SERVICE_DEBUG
|
||||
UnicodeString&
|
||||
SimpleLocaleKeyFactory::debug(UnicodeString& result) const
|
||||
{
|
||||
LocaleKeyFactory::debug(result);
|
||||
result.append(", id: ");
|
||||
result.append(_id);
|
||||
result.append(", kind: ");
|
||||
result.append(_kind);
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
SimpleLocaleKeyFactory::debugClass(UnicodeString& result) const
|
||||
{
|
||||
return result.append("SimpleLocaleKeyFactory");
|
||||
}
|
||||
#endif
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleLocaleKeyFactory)
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/* !UCONFIG_NO_SERVICE */
|
||||
#endif
|
||||
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
#include "chnsecal.h"
|
||||
#include "unicode/calendar.h"
|
||||
#include "cpputils.h"
|
||||
#include "iculserv.h"
|
||||
#include "servloc.h"
|
||||
#include "ucln_in.h"
|
||||
#include "cstring.h"
|
||||
#include "locbased.h"
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#include "ucol_imp.h"
|
||||
#include "cmemory.h"
|
||||
#include "mutex.h"
|
||||
#include "iculserv.h"
|
||||
#include "servloc.h"
|
||||
#include "ustrenum.h"
|
||||
#include "ucln_in.h"
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include "unicode/curramt.h"
|
||||
#include "uhash.h"
|
||||
#include "cmemory.h"
|
||||
#include "iculserv.h"
|
||||
#include "servloc.h"
|
||||
#include "ucln_in.h"
|
||||
#include "cstring.h"
|
||||
#include "putilimp.h"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#if !UCONFIG_NO_SERVICE
|
||||
|
||||
#include "icusvtst.h"
|
||||
#include "iculserv.h"
|
||||
#include "servloc.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
|
|
@ -122,9 +122,13 @@ UObject *UObjectTest::testClass(UObject *obj,
|
|||
#include "unicode/utypes.h"
|
||||
|
||||
// Things we Patch
|
||||
#if UOBJTEST_TEST_INTERNALS
|
||||
#define protected public /* to access private factory function */
|
||||
#include "iculserv.h"
|
||||
#endif
|
||||
#include "servloc.h"
|
||||
#if UOBJTEST_TEST_INTERNALS
|
||||
#undef protected
|
||||
#endif
|
||||
|
||||
// Internal Things (woo)
|
||||
#include "cpdtrans.h"
|
||||
|
@ -135,8 +139,8 @@ UObject *UObjectTest::testClass(UObject *obj,
|
|||
#include "digitlst.h"
|
||||
#include "esctrn.h"
|
||||
#include "funcrepl.h"
|
||||
#include "icunotif.h"
|
||||
#include "icuserv.h"
|
||||
#include "servnotf.h"
|
||||
#include "serv.h"
|
||||
#include "name2uni.h"
|
||||
#include "nfsubs.h"
|
||||
#include "nortrans.h"
|
||||
|
@ -156,6 +160,7 @@ UObject *UObjectTest::testClass(UObject *obj,
|
|||
#include "islamcal.h"
|
||||
#include "japancal.h"
|
||||
#include "hebrwcal.h"
|
||||
#include "ustrenum.h"
|
||||
|
||||
// External Things
|
||||
#include "unicode/brkiter.h"
|
||||
|
@ -228,6 +233,7 @@ void UObjectTest::testIDs()
|
|||
//TESTCLASSID_DEFAULT(CollationElementIterator);
|
||||
#if !UCONFIG_NO_COLLATION
|
||||
TESTCLASSID_DEFAULT(CollationKey);
|
||||
TESTCLASSID_FACTORY(UStringEnumeration, Collator::getKeywords(status));
|
||||
#endif
|
||||
//TESTCLASSID_FACTORY(CompoundTransliterator, Transliterator::createInstance(UnicodeString("Any-Jex;Hangul-Jamo"), UTRANS_FORWARD, parseError, status));
|
||||
|
||||
|
@ -335,12 +341,14 @@ void UObjectTest::testIDs()
|
|||
#if !UCONFIG_NO_SERVICE
|
||||
TESTCLASSID_CTOR(SimpleFactory, (NULL, UnicodeString("foo")));
|
||||
TESTCLASSID_DEFAULT(EventListener);
|
||||
#if UOBJTEST_TEST_INTERNALS
|
||||
TESTCLASSID_DEFAULT(ICUResourceBundleFactory);
|
||||
//TESTCLASSID_DEFAULT(Key); // does ont exist?
|
||||
TESTCLASSID_CTOR(LocaleKey, (UnicodeString("baz"), UnicodeString("bat"), NULL, 92));
|
||||
TESTCLASSID_CTOR(LocaleKeyFactory, (42));
|
||||
//TESTCLASSID_DEFAULT(Key); // does not exist?
|
||||
UnicodeString baz("baz");
|
||||
UnicodeString bat("bat");
|
||||
TESTCLASSID_FACTORY(LocaleKey, LocaleKey::createWithCanonicalFallback(&baz, &bat, LocaleKey::KIND_ANY, status));
|
||||
TESTCLASSID_CTOR(SimpleLocaleKeyFactory, (NULL, UnicodeString("bar"), 8, 12) );
|
||||
#if UOBJTEST_TEST_INTERNALS
|
||||
TESTCLASSID_CTOR(LocaleKeyFactory, (42));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue