1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/decfmtst.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,249 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* Copyright (C) 2009-2013, International Business Machines Corporation and * 1.7 +* others. All Rights Reserved. * 1.8 +******************************************************************************* 1.9 +* 1.10 +* This file contains the class DecimalFormatStaticSets 1.11 +* 1.12 +* DecimalFormatStaticSets holds the UnicodeSets that are needed for lenient 1.13 +* parsing of decimal and group separators. 1.14 +******************************************************************************** 1.15 +*/ 1.16 + 1.17 +#include "unicode/utypes.h" 1.18 + 1.19 +#if !UCONFIG_NO_FORMATTING 1.20 + 1.21 +#include "unicode/unistr.h" 1.22 +#include "unicode/uniset.h" 1.23 +#include "unicode/uchar.h" 1.24 +#include "cmemory.h" 1.25 +#include "cstring.h" 1.26 +#include "uassert.h" 1.27 +#include "ucln_in.h" 1.28 +#include "umutex.h" 1.29 + 1.30 +#include "decfmtst.h" 1.31 + 1.32 +U_NAMESPACE_BEGIN 1.33 + 1.34 + 1.35 +//------------------------------------------------------------------------------ 1.36 +// 1.37 +// Unicode Set pattern strings for all of the required constant sets. 1.38 +// Initialized with hex values for portability to EBCDIC based machines. 1.39 +// Really ugly, but there's no good way to avoid it. 1.40 +// 1.41 +//------------------------------------------------------------------------------ 1.42 + 1.43 +static const UChar gDotEquivalentsPattern[] = { 1.44 + // [ . \u2024 \u3002 \uFE12 \uFE52 \uFF0E \uFF61 ] 1.45 + 0x005B, 0x002E, 0x2024, 0x3002, 0xFE12, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000}; 1.46 + 1.47 +static const UChar gCommaEquivalentsPattern[] = { 1.48 + // [ , \u060C \u066B \u3001 \uFE10 \uFE11 \uFE50 \uFE51 \uFF0C \uFF64 ] 1.49 + 0x005B, 0x002C, 0x060C, 0x066B, 0x3001, 0xFE10, 0xFE11, 0xFE50, 0xFE51, 0xFF0C, 0xFF64, 0x005D, 0x0000}; 1.50 + 1.51 +static const UChar gOtherGroupingSeparatorsPattern[] = { 1.52 + // [ \ SPACE ' NBSP \u066C \u2000 - \u200A \u2018 \u2019 \u202F \u205F \u3000 \uFF07 ] 1.53 + 0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000}; 1.54 + 1.55 +static const UChar gDashEquivalentsPattern[] = { 1.56 + // [ \ - HYPHEN F_DASH N_DASH MINUS ] 1.57 + 0x005B, 0x005C, 0x002D, 0x2010, 0x2012, 0x2013, 0x2212, 0x005D, 0x0000}; 1.58 + 1.59 +static const UChar gStrictDotEquivalentsPattern[] = { 1.60 + // [ . \u2024 \uFE52 \uFF0E \uFF61 ] 1.61 + 0x005B, 0x002E, 0x2024, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000}; 1.62 + 1.63 +static const UChar gStrictCommaEquivalentsPattern[] = { 1.64 + // [ , \u066B \uFE10 \uFE50 \uFF0C ] 1.65 + 0x005B, 0x002C, 0x066B, 0xFE10, 0xFE50, 0xFF0C, 0x005D, 0x0000}; 1.66 + 1.67 +static const UChar gStrictOtherGroupingSeparatorsPattern[] = { 1.68 + // [ \ SPACE ' NBSP \u066C \u2000 - \u200A \u2018 \u2019 \u202F \u205F \u3000 \uFF07 ] 1.69 + 0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000}; 1.70 + 1.71 +static const UChar gStrictDashEquivalentsPattern[] = { 1.72 + // [ \ - MINUS ] 1.73 + 0x005B, 0x005C, 0x002D, 0x2212, 0x005D, 0x0000}; 1.74 + 1.75 +static UChar32 gMinusSigns[] = { 1.76 + 0x002D, 1.77 + 0x207B, 1.78 + 0x208B, 1.79 + 0x2212, 1.80 + 0x2796, 1.81 + 0xFE63, 1.82 + 0xFF0D}; 1.83 + 1.84 +static UChar32 gPlusSigns[] = { 1.85 + 0x002B, 1.86 + 0x207A, 1.87 + 0x208A, 1.88 + 0x2795, 1.89 + 0xfB29, 1.90 + 0xFE62, 1.91 + 0xFF0B}; 1.92 + 1.93 +static void initUnicodeSet(const UChar32 *raw, int32_t len, UnicodeSet *s) { 1.94 + for (int32_t i = 0; i < len; ++i) { 1.95 + s->add(raw[i]); 1.96 + } 1.97 +} 1.98 + 1.99 +DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode &status) 1.100 +: fDotEquivalents(NULL), 1.101 + fCommaEquivalents(NULL), 1.102 + fOtherGroupingSeparators(NULL), 1.103 + fDashEquivalents(NULL), 1.104 + fStrictDotEquivalents(NULL), 1.105 + fStrictCommaEquivalents(NULL), 1.106 + fStrictOtherGroupingSeparators(NULL), 1.107 + fStrictDashEquivalents(NULL), 1.108 + fDefaultGroupingSeparators(NULL), 1.109 + fStrictDefaultGroupingSeparators(NULL), 1.110 + fMinusSigns(NULL), 1.111 + fPlusSigns(NULL) 1.112 +{ 1.113 + fDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gDotEquivalentsPattern, -1), status); 1.114 + fCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gCommaEquivalentsPattern, -1), status); 1.115 + fOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gOtherGroupingSeparatorsPattern, -1), status); 1.116 + fDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gDashEquivalentsPattern, -1), status); 1.117 + 1.118 + fStrictDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDotEquivalentsPattern, -1), status); 1.119 + fStrictCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictCommaEquivalentsPattern, -1), status); 1.120 + fStrictOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gStrictOtherGroupingSeparatorsPattern, -1), status); 1.121 + fStrictDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDashEquivalentsPattern, -1), status); 1.122 + 1.123 + 1.124 + fDefaultGroupingSeparators = new UnicodeSet(*fDotEquivalents); 1.125 + fDefaultGroupingSeparators->addAll(*fCommaEquivalents); 1.126 + fDefaultGroupingSeparators->addAll(*fOtherGroupingSeparators); 1.127 + 1.128 + fStrictDefaultGroupingSeparators = new UnicodeSet(*fStrictDotEquivalents); 1.129 + fStrictDefaultGroupingSeparators->addAll(*fStrictCommaEquivalents); 1.130 + fStrictDefaultGroupingSeparators->addAll(*fStrictOtherGroupingSeparators); 1.131 + 1.132 + fMinusSigns = new UnicodeSet(); 1.133 + fPlusSigns = new UnicodeSet(); 1.134 + 1.135 + // Check for null pointers 1.136 + if (fDotEquivalents == NULL || fCommaEquivalents == NULL || fOtherGroupingSeparators == NULL || fDashEquivalents == NULL || 1.137 + fStrictDotEquivalents == NULL || fStrictCommaEquivalents == NULL || fStrictOtherGroupingSeparators == NULL || fStrictDashEquivalents == NULL || 1.138 + fDefaultGroupingSeparators == NULL || fStrictOtherGroupingSeparators == NULL || 1.139 + fMinusSigns == NULL || fPlusSigns == NULL) { 1.140 + cleanup(); 1.141 + status = U_MEMORY_ALLOCATION_ERROR; 1.142 + return; 1.143 + } 1.144 + 1.145 + initUnicodeSet( 1.146 + gMinusSigns, 1.147 + sizeof(gMinusSigns) / sizeof(gMinusSigns[0]), 1.148 + fMinusSigns); 1.149 + initUnicodeSet( 1.150 + gPlusSigns, 1.151 + sizeof(gPlusSigns) / sizeof(gPlusSigns[0]), 1.152 + fPlusSigns); 1.153 + 1.154 + // Freeze all the sets 1.155 + fDotEquivalents->freeze(); 1.156 + fCommaEquivalents->freeze(); 1.157 + fOtherGroupingSeparators->freeze(); 1.158 + fDashEquivalents->freeze(); 1.159 + fStrictDotEquivalents->freeze(); 1.160 + fStrictCommaEquivalents->freeze(); 1.161 + fStrictOtherGroupingSeparators->freeze(); 1.162 + fStrictDashEquivalents->freeze(); 1.163 + fDefaultGroupingSeparators->freeze(); 1.164 + fStrictDefaultGroupingSeparators->freeze(); 1.165 + fMinusSigns->freeze(); 1.166 + fPlusSigns->freeze(); 1.167 +} 1.168 + 1.169 +DecimalFormatStaticSets::~DecimalFormatStaticSets() { 1.170 + cleanup(); 1.171 +} 1.172 + 1.173 +void DecimalFormatStaticSets::cleanup() { // Be sure to clean up newly added fields! 1.174 + delete fDotEquivalents; fDotEquivalents = NULL; 1.175 + delete fCommaEquivalents; fCommaEquivalents = NULL; 1.176 + delete fOtherGroupingSeparators; fOtherGroupingSeparators = NULL; 1.177 + delete fDashEquivalents; fDashEquivalents = NULL; 1.178 + delete fStrictDotEquivalents; fStrictDotEquivalents = NULL; 1.179 + delete fStrictCommaEquivalents; fStrictCommaEquivalents = NULL; 1.180 + delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL; 1.181 + delete fStrictDashEquivalents; fStrictDashEquivalents = NULL; 1.182 + delete fDefaultGroupingSeparators; fDefaultGroupingSeparators = NULL; 1.183 + delete fStrictDefaultGroupingSeparators; fStrictDefaultGroupingSeparators = NULL; 1.184 + delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL; 1.185 + delete fMinusSigns; fMinusSigns = NULL; 1.186 + delete fPlusSigns; fPlusSigns = NULL; 1.187 +} 1.188 + 1.189 +static DecimalFormatStaticSets *gStaticSets; 1.190 +static icu::UInitOnce gStaticSetsInitOnce = U_INITONCE_INITIALIZER; 1.191 + 1.192 + 1.193 +//------------------------------------------------------------------------------ 1.194 +// 1.195 +// decfmt_cleanup Memory cleanup function, free/delete all 1.196 +// cached memory. Called by ICU's u_cleanup() function. 1.197 +// 1.198 +//------------------------------------------------------------------------------ 1.199 +U_CDECL_BEGIN 1.200 +static UBool U_CALLCONV 1.201 +decimfmt_cleanup(void) 1.202 +{ 1.203 + delete gStaticSets; 1.204 + gStaticSets = NULL; 1.205 + gStaticSetsInitOnce.reset(); 1.206 + return TRUE; 1.207 +} 1.208 + 1.209 +static void U_CALLCONV initSets(UErrorCode &status) { 1.210 + U_ASSERT(gStaticSets == NULL); 1.211 + ucln_i18n_registerCleanup(UCLN_I18N_DECFMT, decimfmt_cleanup); 1.212 + gStaticSets = new DecimalFormatStaticSets(status); 1.213 + if (U_FAILURE(status)) { 1.214 + delete gStaticSets; 1.215 + gStaticSets = NULL; 1.216 + return; 1.217 + } 1.218 + if (gStaticSets == NULL) { 1.219 + status = U_MEMORY_ALLOCATION_ERROR; 1.220 + } 1.221 +} 1.222 +U_CDECL_END 1.223 + 1.224 +const DecimalFormatStaticSets *DecimalFormatStaticSets::getStaticSets(UErrorCode &status) { 1.225 + umtx_initOnce(gStaticSetsInitOnce, initSets, status); 1.226 + return gStaticSets; 1.227 +} 1.228 + 1.229 + 1.230 +const UnicodeSet *DecimalFormatStaticSets::getSimilarDecimals(UChar32 decimal, UBool strictParse) 1.231 +{ 1.232 + UErrorCode status = U_ZERO_ERROR; 1.233 + umtx_initOnce(gStaticSetsInitOnce, initSets, status); 1.234 + if (U_FAILURE(status)) { 1.235 + return NULL; 1.236 + } 1.237 + 1.238 + if (gStaticSets->fDotEquivalents->contains(decimal)) { 1.239 + return strictParse ? gStaticSets->fStrictDotEquivalents : gStaticSets->fDotEquivalents; 1.240 + } 1.241 + 1.242 + if (gStaticSets->fCommaEquivalents->contains(decimal)) { 1.243 + return strictParse ? gStaticSets->fStrictCommaEquivalents : gStaticSets->fCommaEquivalents; 1.244 + } 1.245 + 1.246 + // if there is no match, return NULL 1.247 + return NULL; 1.248 +} 1.249 + 1.250 + 1.251 +U_NAMESPACE_END 1.252 +#endif // !UCONFIG_NO_FORMATTING