1/*
2*******************************************************************************
3*
4*   Copyright (C) 1998-2012, International Business Machines
5*   Corporation and others.  All Rights Reserved.
6*
7*******************************************************************************
8*
9* File locbund.cpp
10*
11* Modification History:
12*
13*   Date        Name        Description
14*   11/18/98    stephen        Creation.
15*   12/10/1999  bobbyr(at)optiosoftware.com       Fix for memory leak + string allocation bugs
16*******************************************************************************
17*/
18
19#include "unicode/utypes.h"
20
21#if !UCONFIG_NO_FORMATTING
22
23#include "locbund.h"
24
25#include "cmemory.h"
26#include "cstring.h"
27#include "ucln_io.h"
28#include "umutex.h"
29#include "unicode/ustring.h"
30#include "unicode/uloc.h"
31
32static UNumberFormat *gPosixNumberFormat[ULOCALEBUNDLE_NUMBERFORMAT_COUNT];
33
34U_CDECL_BEGIN
35static UBool U_CALLCONV locbund_cleanup(void) {
36    int32_t style;
37    for (style = 0; style < ULOCALEBUNDLE_NUMBERFORMAT_COUNT; style++) {
38        unum_close(gPosixNumberFormat[style]);
39        gPosixNumberFormat[style] = NULL;
40    }
41    return TRUE;
42}
43U_CDECL_END
44
45
46static inline UNumberFormat * copyInvariantFormatter(ULocaleBundle *result, UNumberFormatStyle style) {
47    if (result->fNumberFormat[style-1] == NULL) {
48        UErrorCode status = U_ZERO_ERROR;
49        UBool needsInit;
50
51        UMTX_CHECK(NULL, gPosixNumberFormat[style-1] == NULL, needsInit);
52        if (needsInit) {
53            UNumberFormat *formatAlias = unum_open(style, NULL, 0, "en_US_POSIX", NULL, &status);
54
55            /* Cache upon first request. */
56            if (U_SUCCESS(status)) {
57                umtx_lock(NULL);
58                gPosixNumberFormat[style-1] = formatAlias;
59                ucln_io_registerCleanup(UCLN_IO_LOCBUND, locbund_cleanup);
60                umtx_unlock(NULL);
61            }
62        }
63
64        /* Copy the needed formatter. */
65        result->fNumberFormat[style-1] = unum_clone(gPosixNumberFormat[style-1], &status);
66    }
67    return result->fNumberFormat[style-1];
68}
69
70U_CAPI ULocaleBundle *
71u_locbund_init(ULocaleBundle *result, const char *loc)
72{
73    int32_t len;
74
75    if(result == 0)
76        return 0;
77
78    if (loc == NULL) {
79        loc = uloc_getDefault();
80    }
81
82    uprv_memset(result, 0, sizeof(ULocaleBundle));
83
84    len = (int32_t)strlen(loc);
85    result->fLocale = (char*) uprv_malloc(len + 1);
86    if(result->fLocale == 0) {
87        return 0;
88    }
89
90    uprv_strcpy(result->fLocale, loc);
91
92    result->isInvariantLocale = uprv_strcmp(result->fLocale, "en_US_POSIX") == 0;
93
94    return result;
95}
96
97/*U_CAPI ULocaleBundle *
98u_locbund_new(const char *loc)
99{
100    ULocaleBundle *result = (ULocaleBundle*) uprv_malloc(sizeof(ULocaleBundle));
101    return u_locbund_init(result, loc);
102}
103
104U_CAPI ULocaleBundle *
105u_locbund_clone(const ULocaleBundle *bundle)
106{
107    ULocaleBundle *result = (ULocaleBundle*)uprv_malloc(sizeof(ULocaleBundle));
108    UErrorCode status = U_ZERO_ERROR;
109    int32_t styleIdx;
110
111    if(result == 0)
112        return 0;
113
114    result->fLocale = (char*) uprv_malloc(strlen(bundle->fLocale) + 1);
115    if(result->fLocale == 0) {
116        uprv_free(result);
117        return 0;
118    }
119
120    strcpy(result->fLocale, bundle->fLocale );
121
122    for (styleIdx = 0; styleIdx < ULOCALEBUNDLE_NUMBERFORMAT_COUNT; styleIdx++) {
123        status = U_ZERO_ERROR;
124        if (result->fNumberFormat[styleIdx]) {
125            result->fNumberFormat[styleIdx] = unum_clone(bundle->fNumberFormat[styleIdx], &status);
126            if (U_FAILURE(status)) {
127                result->fNumberFormat[styleIdx] = NULL;
128            }
129        }
130        else {
131            result->fNumberFormat[styleIdx] = NULL;
132        }
133    }
134    result->fDateFormat         = (bundle->fDateFormat == 0 ? 0 :
135        udat_clone(bundle->fDateFormat, &status));
136    result->fTimeFormat         = (bundle->fTimeFormat == 0 ? 0 :
137        udat_clone(bundle->fTimeFormat, &status));
138
139    return result;
140}*/
141
142U_CAPI void
143u_locbund_close(ULocaleBundle *bundle)
144{
145    int32_t styleIdx;
146
147    uprv_free(bundle->fLocale);
148
149    for (styleIdx = 0; styleIdx < ULOCALEBUNDLE_NUMBERFORMAT_COUNT; styleIdx++) {
150        if (bundle->fNumberFormat[styleIdx]) {
151            unum_close(bundle->fNumberFormat[styleIdx]);
152        }
153    }
154
155    uprv_memset(bundle, 0, sizeof(ULocaleBundle));
156/*    uprv_free(bundle);*/
157}
158
159U_CAPI UNumberFormat *
160u_locbund_getNumberFormat(ULocaleBundle *bundle, UNumberFormatStyle style)
161{
162    UNumberFormat *formatAlias = NULL;
163    if (style > UNUM_IGNORE) {
164        formatAlias = bundle->fNumberFormat[style-1];
165        if (formatAlias == NULL) {
166            if (bundle->isInvariantLocale) {
167                formatAlias = copyInvariantFormatter(bundle, style);
168            }
169            else {
170                UErrorCode status = U_ZERO_ERROR;
171                formatAlias = unum_open(style, NULL, 0, bundle->fLocale, NULL, &status);
172                if (U_FAILURE(status)) {
173                    unum_close(formatAlias);
174                    formatAlias = NULL;
175                }
176                else {
177                    bundle->fNumberFormat[style-1] = formatAlias;
178                }
179            }
180        }
181    }
182    return formatAlias;
183}
184
185#endif /* #if !UCONFIG_NO_FORMATTING */
186