760d3f2d73
X-SVN-Rev: 10521
836 lines
22 KiB
C++
836 lines
22 KiB
C++
/**
|
|
*******************************************************************************
|
|
* Copyright (C) 2001-2002, International Business Machines Corporation and *
|
|
* others. All Rights Reserved. *
|
|
*******************************************************************************
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
#include "unicode/utypes.h"
|
|
|
|
#if !UCONFIG_NO_SERVICE
|
|
|
|
#include "unicode/resbund.h"
|
|
#include "cmemory.h"
|
|
#include "iculserv.h"
|
|
#include "ustrfmt.h"
|
|
|
|
U_NAMESPACE_BEGIN
|
|
|
|
/*
|
|
******************************************************************
|
|
*/
|
|
|
|
UnicodeString&
|
|
LocaleUtility::canonicalLocaleString(const UnicodeString* id, UnicodeString& result)
|
|
{
|
|
if (id == NULL) {
|
|
result.setToBogus();
|
|
} else {
|
|
result = *id;
|
|
int32_t i = 0;
|
|
int32_t n = result.indexOf(UNDERSCORE_CHAR);
|
|
if (n < 0) {
|
|
n = result.length();
|
|
}
|
|
for (; i < n; ++i) {
|
|
UChar c = result.charAt(i);
|
|
if (c >= 0x0041 && c <= 0x005a) {
|
|
c += 0x20;
|
|
result.setCharAt(i, c);
|
|
}
|
|
}
|
|
for (n = result.length(); i < n; ++i) {
|
|
UChar c = result.charAt(i);
|
|
if (c >= 0x0061 && c <= 0x007a) {
|
|
c -= 0x20;
|
|
result.setCharAt(i, c);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Locale&
|
|
LocaleUtility::initLocaleFromName(const UnicodeString& id, Locale& result)
|
|
{
|
|
if (id.isBogus()) {
|
|
result.setToBogus();
|
|
} else {
|
|
const int32_t BUFLEN = 128; // larger than ever needed
|
|
char buffer[BUFLEN];
|
|
int len = id.extract(0, BUFLEN, buffer);
|
|
if (len >= BUFLEN) {
|
|
result.setToBogus();
|
|
} else {
|
|
buffer[len] = '\0';
|
|
result = Locale::createFromName(buffer);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
UnicodeString&
|
|
LocaleUtility::initNameFromLocale(const Locale& locale, UnicodeString& result)
|
|
{
|
|
if (locale.isBogus()) {
|
|
result.setToBogus();
|
|
} else {
|
|
result.append(locale.getName());
|
|
}
|
|
return result;
|
|
}
|
|
|
|
const Hashtable*
|
|
LocaleUtility::getAvailableLocaleNames(const UnicodeString& bundleID)
|
|
{
|
|
// have to ignore bundleID for the moment, since we don't have easy C++ api.
|
|
// assume it's the default bundle
|
|
|
|
if (cache == NULL) {
|
|
Hashtable* result = new Hashtable();
|
|
if (result) {
|
|
UErrorCode status = U_ZERO_ERROR;
|
|
int32_t count = uloc_countAvailable();
|
|
for (int32_t i = 0; i < count; ++i) {
|
|
UnicodeString temp(uloc_getAvailable(i));
|
|
result->put(temp, (void*)result, status);
|
|
if (U_FAILURE(status)) {
|
|
delete result;
|
|
return NULL;
|
|
}
|
|
}
|
|
{
|
|
Mutex mutex(&lock);
|
|
if (cache == NULL) {
|
|
cache = result;
|
|
return cache;
|
|
}
|
|
}
|
|
delete result;
|
|
}
|
|
}
|
|
return cache;
|
|
}
|
|
|
|
UBool
|
|
LocaleUtility::isFallbackOf(const UnicodeString& root, const UnicodeString& child)
|
|
{
|
|
return child.indexOf(root) == 0 &&
|
|
(child.length() == root.length() ||
|
|
child.charAt(root.length()) == UNDERSCORE_CHAR);
|
|
}
|
|
|
|
UBool
|
|
LocaleUtility::cleanup(void) {
|
|
if (cache) {
|
|
Mutex mutex(&lock);
|
|
delete cache;
|
|
cache = NULL;
|
|
}
|
|
umtx_destroy(&lock);
|
|
return TRUE;
|
|
}
|
|
|
|
Hashtable * LocaleUtility::cache = NULL;
|
|
|
|
const UChar LocaleUtility::UNDERSCORE_CHAR = 0x005f;
|
|
|
|
UMTX LocaleUtility::lock = 0;
|
|
|
|
/*
|
|
******************************************************************
|
|
*/
|
|
|
|
const UChar LocaleKey::UNDERSCORE_CHAR = 0x005f;
|
|
|
|
const int32_t LocaleKey::KIND_ANY = -1;
|
|
|
|
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;
|
|
}
|
|
|
|
UnicodeString&
|
|
LocaleKey::prefix(UnicodeString& result) const {
|
|
if (_kind != KIND_ANY) {
|
|
UChar buffer[64];
|
|
uprv_itou(buffer, _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
|
|
|
|
const char LocaleKey::fgClassID = 0;
|
|
|
|
/*
|
|
******************************************************************
|
|
*/
|
|
|
|
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.canonicalLocale(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)) {
|
|
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;
|
|
const Hashtable* ids = getSupportedIDs(status);
|
|
if (ids && (ids->get(id) != NULL)) {
|
|
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;
|
|
}
|
|
|
|
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
|
|
|
|
const char LocaleKeyFactory::fgClassID = 0;
|
|
|
|
/*
|
|
******************************************************************
|
|
*/
|
|
|
|
SimpleLocaleKeyFactory::SimpleLocaleKeyFactory(UObject* objToAdopt,
|
|
const UnicodeString& locale,
|
|
int32_t kind,
|
|
int32_t coverage)
|
|
: LocaleKeyFactory(coverage)
|
|
, _obj(objToAdopt)
|
|
, _id(locale)
|
|
, _kind(kind)
|
|
{
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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
|
|
|
|
const char SimpleLocaleKeyFactory::fgClassID = 0;
|
|
|
|
/*
|
|
******************************************************************
|
|
*/
|
|
|
|
ICUResourceBundleFactory::ICUResourceBundleFactory()
|
|
: LocaleKeyFactory(VISIBLE)
|
|
, _bundleName()
|
|
{
|
|
}
|
|
|
|
ICUResourceBundleFactory::ICUResourceBundleFactory(const UnicodeString& bundleName)
|
|
: LocaleKeyFactory(VISIBLE)
|
|
, _bundleName(bundleName)
|
|
{
|
|
}
|
|
|
|
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)) {
|
|
return new ResourceBundle(_bundleName, 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
|
|
|
|
const char ICUResourceBundleFactory::fgClassID = '\0';
|
|
|
|
/*
|
|
******************************************************************
|
|
*/
|
|
|
|
ICULocaleService::ICULocaleService()
|
|
: fallbackLocale(Locale::getDefault())
|
|
, llock(0)
|
|
{
|
|
}
|
|
|
|
ICULocaleService::ICULocaleService(const UnicodeString& dname)
|
|
: ICUService(dname)
|
|
, fallbackLocale(Locale::getDefault())
|
|
, llock(0)
|
|
{
|
|
}
|
|
|
|
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());
|
|
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)
|
|
{
|
|
return ICUService::registerInstance(objToAdopt, locale, visible, 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.getName(), 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;
|
|
void* _bufp;
|
|
int32_t _buflen;
|
|
|
|
private:
|
|
ServiceEnumeration(const ICULocaleService* service, UErrorCode status)
|
|
: _service(service)
|
|
, _timestamp(service->getTimestamp())
|
|
, _ids(uhash_deleteUnicodeString, NULL, status)
|
|
, _pos(0)
|
|
, _bufp(NULL)
|
|
, _buflen(0)
|
|
{
|
|
_service->getVisibleIDs(_ids, status);
|
|
}
|
|
|
|
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() {
|
|
uprv_free(_bufp);
|
|
}
|
|
|
|
virtual int32_t count(UErrorCode& status) const {
|
|
return upToDate(status) ? _ids.size() : 0;
|
|
}
|
|
|
|
const char* next(int32_t* resultLength, UErrorCode& status) {
|
|
const UnicodeString* us = snext(status);
|
|
if (us) {
|
|
while (TRUE) {
|
|
int32_t newlen = us->extract((char*)_bufp, _buflen / sizeof(char), NULL, status);
|
|
if (status == U_STRING_NOT_TERMINATED_WARNING || status == U_BUFFER_OVERFLOW_ERROR) {
|
|
resizeBuffer((newlen + 1) * sizeof(char));
|
|
status = U_ZERO_ERROR;
|
|
} else if (U_SUCCESS(status)) {
|
|
((char*)_bufp)[newlen] = 0;
|
|
if (resultLength) {
|
|
resultLength[0] = newlen;
|
|
}
|
|
return (const char*)_bufp;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
const UChar* unext(int32_t* resultLength, UErrorCode& status) {
|
|
const UnicodeString* us = snext(status);
|
|
if (us) {
|
|
while (TRUE) {
|
|
int32_t newlen = us->extract((UChar*)_bufp, _buflen / sizeof(UChar), status);
|
|
if (status == U_STRING_NOT_TERMINATED_WARNING || status == U_BUFFER_OVERFLOW_ERROR) {
|
|
resizeBuffer((newlen + 1) * sizeof(UChar));
|
|
} else if (U_SUCCESS(status)) {
|
|
((UChar*)_bufp)[newlen] = 0;
|
|
if (resultLength) {
|
|
resultLength[0] = newlen;
|
|
}
|
|
return (const UChar*)_bufp;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
const UnicodeString* snext(UErrorCode& status) {
|
|
if (upToDate(status) && (_pos < _ids.size())) {
|
|
return (const UnicodeString*)_ids[_pos++];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void resizeBuffer(int32_t newlen) {
|
|
if (_bufp) {
|
|
_bufp = uprv_realloc(_bufp, newlen);
|
|
} else {
|
|
_bufp = uprv_malloc(newlen);
|
|
}
|
|
_buflen = newlen;
|
|
}
|
|
|
|
UBool upToDate(UErrorCode& status) const {
|
|
if (U_SUCCESS(status)) {
|
|
if (_timestamp == _service->getTimestamp()) {
|
|
return TRUE;
|
|
}
|
|
status = U_ENUM_OUT_OF_SYNC_ERROR;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void reset(UErrorCode& status) {
|
|
if (U_SUCCESS(status)) {
|
|
_timestamp = _service->getTimestamp();
|
|
_pos = 0;
|
|
_service->getVisibleIDs(_ids, status);
|
|
}
|
|
}
|
|
|
|
public:
|
|
virtual UClassID getDynamicClassID(void) const { return getStaticClassID(); }
|
|
static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; }
|
|
private:
|
|
static const char fgClassID;
|
|
};
|
|
|
|
const char ServiceEnumeration::fgClassID = '\0';
|
|
|
|
StringEnumeration*
|
|
ICULocaleService::getAvailableLocales(void) const
|
|
{
|
|
return ServiceEnumeration::create(this);
|
|
}
|
|
|
|
const UnicodeString&
|
|
ICULocaleService::validateFallbackLocale() const
|
|
{
|
|
const Locale& loc = Locale::getDefault();
|
|
if (loc != fallbackLocale) {
|
|
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
|
|
|
|
// defined in ucln_cmn.h
|
|
|
|
/**
|
|
* Release all static memory held by breakiterator.
|
|
*/
|
|
U_CFUNC UBool service_cleanup(void) {
|
|
return LocaleUtility::cleanup();
|
|
}
|
|
|
|
/* !UCONFIG_NO_SERVICE */
|
|
#endif
|
|
|
|
|