| Index: icu51/source/common/listformatter.cpp
|
| ===================================================================
|
| --- icu51/source/common/listformatter.cpp (revision 0)
|
| +++ icu51/source/common/listformatter.cpp (revision 0)
|
| @@ -0,0 +1,238 @@
|
| +/*
|
| +*******************************************************************************
|
| +*
|
| +* Copyright (C) 2012, International Business Machines
|
| +* Corporation and others. All Rights Reserved.
|
| +*
|
| +*******************************************************************************
|
| +* file name: listformatter.cpp
|
| +* encoding: US-ASCII
|
| +* tab size: 8 (not used)
|
| +* indentation:4
|
| +*
|
| +* created on: 2012aug27
|
| +* created by: Umesh P. Nair
|
| +*/
|
| +
|
| +#include "unicode/listformatter.h"
|
| +#include "mutex.h"
|
| +#include "hash.h"
|
| +#include "cstring.h"
|
| +#include "ulocimp.h"
|
| +#include "charstr.h"
|
| +#include "ucln_cmn.h"
|
| +#include "uresimp.h"
|
| +
|
| +U_NAMESPACE_BEGIN
|
| +
|
| +static Hashtable* listPatternHash = NULL;
|
| +static UMutex listFormatterMutex = U_MUTEX_INITIALIZER;
|
| +static UChar FIRST_PARAMETER[] = { 0x7b, 0x30, 0x7d }; // "{0}"
|
| +static UChar SECOND_PARAMETER[] = { 0x7b, 0x31, 0x7d }; // "{0}"
|
| +
|
| +U_CDECL_BEGIN
|
| +static UBool U_CALLCONV uprv_listformatter_cleanup() {
|
| + delete listPatternHash;
|
| + listPatternHash = NULL;
|
| + return TRUE;
|
| +}
|
| +
|
| +static void U_CALLCONV
|
| +uprv_deleteListFormatData(void *obj) {
|
| + delete static_cast<ListFormatData *>(obj);
|
| +}
|
| +
|
| +U_CDECL_END
|
| +
|
| +static ListFormatData* loadListFormatData(const Locale& locale, UErrorCode& errorCode);
|
| +static void getStringByKey(const UResourceBundle* rb, const char* key, UnicodeString& result, UErrorCode& errorCode);
|
| +
|
| +void ListFormatter::initializeHash(UErrorCode& errorCode) {
|
| + if (U_FAILURE(errorCode)) {
|
| + return;
|
| + }
|
| +
|
| + listPatternHash = new Hashtable();
|
| + if (listPatternHash == NULL) {
|
| + errorCode = U_MEMORY_ALLOCATION_ERROR;
|
| + return;
|
| + }
|
| +
|
| + listPatternHash->setValueDeleter(uprv_deleteListFormatData);
|
| + ucln_common_registerCleanup(UCLN_COMMON_LIST_FORMATTER, uprv_listformatter_cleanup);
|
| +
|
| +}
|
| +
|
| +const ListFormatData* ListFormatter::getListFormatData(
|
| + const Locale& locale, UErrorCode& errorCode) {
|
| + if (U_FAILURE(errorCode)) {
|
| + return NULL;
|
| + }
|
| + UnicodeString key(locale.getName(), -1, US_INV);
|
| + ListFormatData* result = NULL;
|
| + {
|
| + Mutex m(&listFormatterMutex);
|
| + if (listPatternHash == NULL) {
|
| + initializeHash(errorCode);
|
| + if (U_FAILURE(errorCode)) {
|
| + return NULL;
|
| + }
|
| + }
|
| + result = static_cast<ListFormatData*>(listPatternHash->get(key));
|
| + }
|
| + if (result != NULL) {
|
| + return result;
|
| + }
|
| + result = loadListFormatData(locale, errorCode);
|
| + if (U_FAILURE(errorCode)) {
|
| + return NULL;
|
| + }
|
| +
|
| + {
|
| + Mutex m(&listFormatterMutex);
|
| + ListFormatData* temp = static_cast<ListFormatData*>(listPatternHash->get(key));
|
| + if (temp != NULL) {
|
| + delete result;
|
| + result = temp;
|
| + } else {
|
| + listPatternHash->put(key, result, errorCode);
|
| + if (U_FAILURE(errorCode)) {
|
| + return NULL;
|
| + }
|
| + }
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +static ListFormatData* loadListFormatData(const Locale& locale, UErrorCode& errorCode) {
|
| + UResourceBundle* rb = ures_open(NULL, locale.getName(), &errorCode);
|
| + if (U_FAILURE(errorCode)) {
|
| + ures_close(rb);
|
| + return NULL;
|
| + }
|
| + rb = ures_getByKeyWithFallback(rb, "listPattern", rb, &errorCode);
|
| + rb = ures_getByKeyWithFallback(rb, "standard", rb, &errorCode);
|
| + if (U_FAILURE(errorCode)) {
|
| + ures_close(rb);
|
| + return NULL;
|
| + }
|
| + UnicodeString two, start, middle, end;
|
| + getStringByKey(rb, "2", two, errorCode);
|
| + getStringByKey(rb, "start", start, errorCode);
|
| + getStringByKey(rb, "middle", middle, errorCode);
|
| + getStringByKey(rb, "end", end, errorCode);
|
| + ures_close(rb);
|
| + if (U_FAILURE(errorCode)) {
|
| + return NULL;
|
| + }
|
| + ListFormatData* result = new ListFormatData(two, start, middle, end);
|
| + if (result == NULL) {
|
| + errorCode = U_MEMORY_ALLOCATION_ERROR;
|
| + return NULL;
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +static void getStringByKey(const UResourceBundle* rb, const char* key, UnicodeString& result, UErrorCode& errorCode) {
|
| + int32_t len;
|
| + const UChar* ustr = ures_getStringByKeyWithFallback(rb, key, &len, &errorCode);
|
| + if (U_FAILURE(errorCode)) {
|
| + return;
|
| + }
|
| + result.setTo(ustr, len);
|
| +}
|
| +
|
| +ListFormatter* ListFormatter::createInstance(UErrorCode& errorCode) {
|
| + Locale locale; // The default locale.
|
| + return createInstance(locale, errorCode);
|
| +}
|
| +
|
| +ListFormatter* ListFormatter::createInstance(const Locale& locale, UErrorCode& errorCode) {
|
| + Locale tempLocale = locale;
|
| + const ListFormatData* listFormatData = getListFormatData(tempLocale, errorCode);
|
| + if (U_FAILURE(errorCode)) {
|
| + return NULL;
|
| + }
|
| + ListFormatter* p = new ListFormatter(*listFormatData);
|
| + if (p == NULL) {
|
| + errorCode = U_MEMORY_ALLOCATION_ERROR;
|
| + return NULL;
|
| + }
|
| + return p;
|
| +}
|
| +
|
| +ListFormatter::ListFormatter(const ListFormatData& listFormatterData) : data(listFormatterData) {
|
| +}
|
| +
|
| +ListFormatter::~ListFormatter() {}
|
| +
|
| +UnicodeString& ListFormatter::format(const UnicodeString items[], int32_t nItems,
|
| + UnicodeString& appendTo, UErrorCode& errorCode) const {
|
| + if (U_FAILURE(errorCode)) {
|
| + return appendTo;
|
| + }
|
| +
|
| + if (nItems > 0) {
|
| + UnicodeString newString = items[0];
|
| + if (nItems == 2) {
|
| + addNewString(data.twoPattern, newString, items[1], errorCode);
|
| + } else if (nItems > 2) {
|
| + addNewString(data.startPattern, newString, items[1], errorCode);
|
| + int32_t i;
|
| + for (i = 2; i < nItems - 1; ++i) {
|
| + addNewString(data.middlePattern, newString, items[i], errorCode);
|
| + }
|
| + addNewString(data.endPattern, newString, items[nItems - 1], errorCode);
|
| + }
|
| + if (U_SUCCESS(errorCode)) {
|
| + appendTo += newString;
|
| + }
|
| + }
|
| + return appendTo;
|
| +}
|
| +
|
| +/**
|
| + * Joins originalString and nextString using the pattern pat and puts the result in
|
| + * originalString.
|
| + */
|
| +void ListFormatter::addNewString(const UnicodeString& pat, UnicodeString& originalString,
|
| + const UnicodeString& nextString, UErrorCode& errorCode) const {
|
| + if (U_FAILURE(errorCode)) {
|
| + return;
|
| + }
|
| +
|
| + int32_t p0Offset = pat.indexOf(FIRST_PARAMETER, 3, 0);
|
| + if (p0Offset < 0) {
|
| + errorCode = U_ILLEGAL_ARGUMENT_ERROR;
|
| + return;
|
| + }
|
| + int32_t p1Offset = pat.indexOf(SECOND_PARAMETER, 3, 0);
|
| + if (p1Offset < 0) {
|
| + errorCode = U_ILLEGAL_ARGUMENT_ERROR;
|
| + return;
|
| + }
|
| +
|
| + int32_t i, j;
|
| +
|
| + const UnicodeString* firstString;
|
| + const UnicodeString* secondString;
|
| + if (p0Offset < p1Offset) {
|
| + i = p0Offset;
|
| + j = p1Offset;
|
| + firstString = &originalString;
|
| + secondString = &nextString;
|
| + } else {
|
| + i = p1Offset;
|
| + j = p0Offset;
|
| + firstString = &nextString;
|
| + secondString = &originalString;
|
| + }
|
| +
|
| + UnicodeString result = UnicodeString(pat, 0, i) + *firstString;
|
| + result += UnicodeString(pat, i+3, j-i-3);
|
| + result += *secondString;
|
| + result += UnicodeString(pat, j+3);
|
| + originalString = result;
|
| +}
|
| +
|
| +U_NAMESPACE_END
|
|
|
| Property changes on: icu51/source/common/listformatter.cpp
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|