ICU-2438 C++ implementation for getKeywords and getKeywordValue

X-SVN-Rev: 13423
This commit is contained in:
Vladimir Weinstein 2003-10-15 05:30:32 +00:00
parent c93ae8408a
commit f6a15b10ba
3 changed files with 160 additions and 8 deletions

View File

@ -67,6 +67,12 @@ typedef enum ELocalePos {
eMAX_LOCALES
} ELocalePos;
U_CFUNC int32_t locale_getKeywords(const char *localeID,
char prev,
char *keywords, int32_t keywordCapacity,
char *values, int32_t valuesCapacity, int32_t *valLen,
UBool valuesToo,
UErrorCode *status);
static Locale *gLocaleCache = NULL;
static const Locale *gDefaultLocale = NULL;
@ -256,7 +262,8 @@ Locale::Locale(Locale::ELocaleType t)
Locale::Locale( const char * newLanguage,
const char * newCountry,
const char * newVariant)
const char * newVariant,
const char * newKeywords)
: UObject(), fullName(fullNameBuffer)
{
if( (newLanguage==NULL) && (newCountry == NULL) && (newVariant == NULL) )
@ -482,7 +489,11 @@ Locale& Locale::init(const char* localeID)
fieldLen[fieldIdx-1] = separator - field[fieldIdx-1];
fieldIdx++;
}
fieldLen[fieldIdx-1] = length - (int32_t)(field[fieldIdx-1] - fullName);
if(separator = uprv_strchr(field[fieldIdx-1], '@')) {
fieldLen[fieldIdx-1] = separator - field[fieldIdx-1];
} else {
fieldLen[fieldIdx-1] = length - (int32_t)(field[fieldIdx-1] - fullName);
}
if (fieldLen[0] >= (int32_t)(sizeof(language))
|| (fieldLen[1] == 4 && fieldLen[2] >= (int32_t)(sizeof(country)))
@ -1090,5 +1101,109 @@ Locale::getLocaleCache(void)
return gLocaleCache;
}
class KeywordEnumeration : public StringEnumeration {
private:
char *keywords;
char *current;
UChar currUKey[256];
UnicodeString currUSKey;
static const char fgClassID;
public:
static inline UClassID getStaticClassID(void) { return (UClassID)&fgClassID; }
virtual UClassID getDynamicClassID(void) const { return getStaticClassID(); }
public:
KeywordEnumeration(const char *keys, int32_t keywordLen, UErrorCode &status) {
keywords = (char *)uprv_malloc(keywordLen+1);
uprv_memcpy(keywords, keys, keywordLen);
keywords[keywordLen] = 0;
current = keywords;
}
~KeywordEnumeration() {
uprv_free(keywords);
}
int32_t count(UErrorCode &status) const {
char *kw = keywords;
int32_t result = 0;
while(*kw) {
result++;
kw += uprv_strlen(kw)+1;
}
return result;
}
const char* next(int32_t* resultLength, UErrorCode& status) {
const char* result = current;
if(*result) {
*resultLength = uprv_strlen(current);
current += *resultLength+1;
} else {
*resultLength = 0;
result = NULL;
}
return result;
}
const UChar* unext(int32_t* resultLength, UErrorCode& status) {
const char* starter = next(resultLength, status);
if(starter) {
u_charsToUChars(starter, currUKey, *resultLength);
currUKey[*resultLength] = 0;
return currUKey;
} else {
return NULL;
}
}
const UnicodeString* snext(UErrorCode& status) {
int32_t resultLength = 0;
const UChar* starter = unext(&resultLength, status);
if(starter) {
currUSKey.setTo(TRUE, starter, resultLength);
return &currUSKey;
} else {
return NULL;
}
}
void reset(UErrorCode& /*status*/) {
current = keywords;
}
};
const char KeywordEnumeration::fgClassID = '\0';
StringEnumeration *
Locale::getKeywords(UErrorCode &status) const
{
char keywords[256];
int32_t keywordCapacity = 256;
StringEnumeration *result = NULL;
const char* variantStart = uprv_strchr(fullName, '@');
const char* assignment = uprv_strchr(fullName, '=');
if(variantStart) {
if(assignment) {
int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, NULL, 0, NULL, FALSE, &status);
if(keyLen) {
result = new KeywordEnumeration(keywords, keyLen, status);
}
} else {
status = U_INVALID_FORMAT_ERROR;
}
}
return result;
}
int32_t
Locale::getKeywordValue(const char* keywordName, char *buffer, int32_t bufLen, UErrorCode &status) const
{
return uloc_getKeywordValue(fullName, keywordName, buffer, bufLen, &status);
}
//eof
U_NAMESPACE_END

View File

@ -756,10 +756,11 @@ compareKeywordStructs(const void *context, const void *left, const void *right)
return uprv_strcmp(leftString, rightString);
}
static int32_t
_getKeywords(const char *localeID,
U_CFUNC int32_t
locale_getKeywords(const char *localeID,
char prev,
char *keywords, int32_t keywordCapacity,
char *values, int32_t valuesCapacity, int32_t *valLen,
UBool valuesToo,
UErrorCode *status) {
@ -771,6 +772,7 @@ _getKeywords(const char *localeID,
const char* nextSeparator = NULL;
int32_t i = 0;
int32_t keywordsLen = 0;
int32_t valuesLen = 0;
if(prev == '@') { /* start of keyword definition */
/* we will grab pairs, trim spaces, lowercase keywords, sort and return */
@ -856,8 +858,20 @@ _getKeywords(const char *localeID,
keywordsLen++;
}
}
if(values) {
if(valuesLen + keywordList[i].valueLen + 1< valuesCapacity) {
uprv_strcpy(values+valuesLen, keywordList[i].valueStart);
values[valuesLen + keywordList[i].valueLen] = 0;
}
valuesLen += keywordList[i].valueLen + 1;
}
}
if(values) {
values[valuesLen] = 0;
if(valLen) {
*valLen = valuesLen;
}
}
return u_terminateChars(keywords, keywordCapacity, keywordsLen, status);
} else {
return 0;
@ -1004,7 +1018,7 @@ uloc_getKeywords(const char* localeID,
/* keywords are located after '@' */
if((localeID = uprv_strchr(localeID, '@')) != NULL) {
i=_getKeywords(localeID+1, '@', keywords, keywordsCapacity, FALSE, status);
i=locale_getKeywords(localeID+1, '@', keywords, keywordsCapacity, NULL, 0, NULL, FALSE, status);
}
if(i) {
@ -1095,7 +1109,7 @@ uloc_getName(const char* localeID,
}
++i;
++fieldCount;
i += _getKeywords(localeID+1, '@', name+i, nameCapacity-i, TRUE, err);
i += locale_getKeywords(localeID+1, '@', name+i, nameCapacity-i, NULL, 0, NULL, TRUE, err);
} else if(fieldCount < 2) {
do {
if(i<nameCapacity) {

View File

@ -34,6 +34,7 @@
#include "unicode/unistr.h"
#include "unicode/putil.h"
#include "unicode/uloc.h"
#include "unicode/strenum.h"
/**
* \file
@ -250,6 +251,8 @@ public:
* @param country Uppercase two-letter ISO-3166 code. (optional)
* @param variant Uppercase vendor and browser specific code. See class
* description. (optional)
* @param keywordsAndValues A string consisting of keyword/values pairs, such as
* "collation=phonebook;currency=euro"
*
* @see getDefault
* @see uloc_getDefault
@ -257,7 +260,8 @@ public:
*/
Locale( const char * language,
const char * country = 0,
const char * variant = 0);
const char * variant = 0,
const char * keywordsAndValues = 0);
/**
* Initializes a Locale object from another Locale object.
@ -387,6 +391,25 @@ public:
*/
inline const char * getName() const;
/**
* Gets the list of keywords for the specified locale.
*
* @return pointer to StringEnumeration class. Client must dispose of it by calling delete.
* @draft ICU 2.8
*/
StringEnumeration * getKeywords(UErrorCode &status) const;
/**
* Get the value for a keyword.
*
* @param keywordName name of the keyword for which we want the value. Case insensitive.
* @return pointer to the keyword value owned by the Locale object or NULL if there is
* no such a keyword.
*
* @draft ICU 2.8
*/
int32_t getKeywordValue(const char* keywordName, char *buffer, int32_t bufLen, UErrorCode &status) const;
/**
* returns the locale's three-letter language code, as specified
* in ISO draft standard ISO-639-2..