16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Copyright (C) 1998-2013, International Business Machines
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Corporation and others.  All Rights Reserved.
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* File locbund.cpp
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Modification History:
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Date        Name        Description
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   11/18/98    stephen        Creation.
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   12/10/1999  bobbyr(at)optiosoftware.com       Fix for memory leak + string allocation bugs
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h"
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_FORMATTING
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "locbund.h"
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h"
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cstring.h"
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ucln_io.h"
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "mutex.h"
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "umutex.h"
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ustring.h"
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/uloc.h"
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UNumberFormat *gPosixNumberFormat[ULOCALEBUNDLE_NUMBERFORMAT_COUNT];
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CDECL_BEGIN
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool U_CALLCONV locbund_cleanup(void) {
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t style;
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (style = 0; style < ULOCALEBUNDLE_NUMBERFORMAT_COUNT; style++) {
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        unum_close(gPosixNumberFormat[style]);
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        gPosixNumberFormat[style] = NULL;
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CDECL_END
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UMutex gLock = U_MUTEX_INITIALIZER;
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic inline UNumberFormat * copyInvariantFormatter(ULocaleBundle *result, UNumberFormatStyle style) {
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    U_NAMESPACE_USE
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    Mutex lock(&gLock);
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (result->fNumberFormat[style-1] == NULL) {
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (gPosixNumberFormat[style-1] == NULL) {
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UErrorCode status = U_ZERO_ERROR;
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UNumberFormat *formatAlias = unum_open(style, NULL, 0, "en_US_POSIX", NULL, &status);
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (U_SUCCESS(status)) {
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                gPosixNumberFormat[style-1] = formatAlias;
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ucln_io_registerCleanup(UCLN_IO_LOCBUND, locbund_cleanup);
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* Copy the needed formatter. */
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (gPosixNumberFormat[style-1] != NULL) {
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UErrorCode status = U_ZERO_ERROR;
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result->fNumberFormat[style-1] = unum_clone(gPosixNumberFormat[style-1], &status);
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return result->fNumberFormat[style-1];
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI ULocaleBundle *
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_locbund_init(ULocaleBundle *result, const char *loc)
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t len;
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(result == 0)
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (loc == NULL) {
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        loc = uloc_getDefault();
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_memset(result, 0, sizeof(ULocaleBundle));
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    len = (int32_t)strlen(loc);
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    result->fLocale = (char*) uprv_malloc(len + 1);
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(result->fLocale == 0) {
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_strcpy(result->fLocale, loc);
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    result->isInvariantLocale = uprv_strcmp(result->fLocale, "en_US_POSIX") == 0;
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return result;
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*U_CAPI ULocaleBundle *
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_locbund_new(const char *loc)
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ULocaleBundle *result = (ULocaleBundle*) uprv_malloc(sizeof(ULocaleBundle));
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return u_locbund_init(result, loc);
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI ULocaleBundle *
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_locbund_clone(const ULocaleBundle *bundle)
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ULocaleBundle *result = (ULocaleBundle*)uprv_malloc(sizeof(ULocaleBundle));
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode status = U_ZERO_ERROR;
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t styleIdx;
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(result == 0)
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    result->fLocale = (char*) uprv_malloc(strlen(bundle->fLocale) + 1);
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(result->fLocale == 0) {
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(result);
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    strcpy(result->fLocale, bundle->fLocale );
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (styleIdx = 0; styleIdx < ULOCALEBUNDLE_NUMBERFORMAT_COUNT; styleIdx++) {
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        status = U_ZERO_ERROR;
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (result->fNumberFormat[styleIdx]) {
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result->fNumberFormat[styleIdx] = unum_clone(bundle->fNumberFormat[styleIdx], &status);
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (U_FAILURE(status)) {
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                result->fNumberFormat[styleIdx] = NULL;
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        else {
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result->fNumberFormat[styleIdx] = NULL;
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    result->fDateFormat         = (bundle->fDateFormat == 0 ? 0 :
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        udat_clone(bundle->fDateFormat, &status));
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    result->fTimeFormat         = (bundle->fTimeFormat == 0 ? 0 :
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        udat_clone(bundle->fTimeFormat, &status));
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return result;
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}*/
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_locbund_close(ULocaleBundle *bundle)
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t styleIdx;
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_free(bundle->fLocale);
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (styleIdx = 0; styleIdx < ULOCALEBUNDLE_NUMBERFORMAT_COUNT; styleIdx++) {
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (bundle->fNumberFormat[styleIdx]) {
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            unum_close(bundle->fNumberFormat[styleIdx]);
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_memset(bundle, 0, sizeof(ULocaleBundle));
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*    uprv_free(bundle);*/
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI UNumberFormat *
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_locbund_getNumberFormat(ULocaleBundle *bundle, UNumberFormatStyle style)
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UNumberFormat *formatAlias = NULL;
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (style > UNUM_IGNORE) {
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        formatAlias = bundle->fNumberFormat[style-1];
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (formatAlias == NULL) {
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (bundle->isInvariantLocale) {
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                formatAlias = copyInvariantFormatter(bundle, style);
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            else {
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UErrorCode status = U_ZERO_ERROR;
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                formatAlias = unum_open(style, NULL, 0, bundle->fLocale, NULL, &status);
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (U_FAILURE(status)) {
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    unum_close(formatAlias);
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    formatAlias = NULL;
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                else {
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    bundle->fNumberFormat[style-1] = formatAlias;
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return formatAlias;
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif /* #if !UCONFIG_NO_FORMATTING */
184