annotate modules/javafx.web/src/main/native/Source/ThirdParty/icu/source/common/resbund.cpp @ 11348:6744f504e684

8231310: Add .jcheck/conf to jfx git repo Reviewed-by: prr, jvos
author kcr
date Tue, 01 Oct 2019 05:28:24 -0700
parents fee4ef5c87df
children
rev   line source
arajkumar@11038 1 // © 2016 and later: Unicode, Inc. and others.
arajkumar@11038 2 // License & terms of use: http://www.unicode.org/copyright.html
ghb@10550 3 /*
ghb@10550 4 **********************************************************************
arajkumar@11038 5 * Copyright (C) 1997-2013, International Business Machines
ghb@10550 6 * Corporation and others. All Rights Reserved.
ghb@10550 7 **********************************************************************
ghb@10550 8 *
ghb@10550 9 * File resbund.cpp
ghb@10550 10 *
ghb@10550 11 * Modification History:
ghb@10550 12 *
ghb@10550 13 * Date Name Description
ghb@10550 14 * 02/05/97 aliu Fixed bug in chopLocale. Added scanForLocaleInFile
ghb@10550 15 * based on code taken from scanForLocale. Added
ghb@10550 16 * constructor which attempts to read resource bundle
ghb@10550 17 * from a specific file, without searching other files.
ghb@10550 18 * 02/11/97 aliu Added UErrorCode return values to constructors. Fixed
ghb@10550 19 * infinite loops in scanForFile and scanForLocale.
ghb@10550 20 * Modified getRawResourceData to not delete storage in
ghb@10550 21 * localeData and resourceData which it doesn't own.
ghb@10550 22 * Added Mac compatibility #ifdefs for tellp() and
ghb@10550 23 * ios::nocreate.
ghb@10550 24 * 03/04/97 aliu Modified to use ExpandingDataSink objects instead of
ghb@10550 25 * the highly inefficient ostrstream objects.
ghb@10550 26 * 03/13/97 aliu Rewrote to load in entire resource bundle and store
ghb@10550 27 * it as a Hashtable of ResourceBundleData objects.
ghb@10550 28 * Added state table to govern parsing of files.
ghb@10550 29 * Modified to load locale index out of new file distinct
ghb@10550 30 * from default.txt.
ghb@10550 31 * 03/25/97 aliu Modified to support 2-d arrays, needed for timezone data.
ghb@10550 32 * Added support for custom file suffixes. Again, needed
ghb@10550 33 * to support timezone data. Improved error handling to
ghb@10550 34 * detect duplicate tags and subtags.
ghb@10550 35 * 04/07/97 aliu Fixed bug in getHashtableForLocale(). Fixed handling
ghb@10550 36 * of failing UErrorCode values on entry to API methods.
ghb@10550 37 * Fixed bugs in getArrayItem() for negative indices.
ghb@10550 38 * 04/29/97 aliu Update to use new Hashtable deletion protocol.
ghb@10550 39 * 05/06/97 aliu Flattened kTransitionTable for HP compiler.
ghb@10550 40 * Fixed usage of CharString.
ghb@10550 41 * 06/11/99 stephen Removed parsing of .txt files.
ghb@10550 42 * Reworked to use new binary format.
ghb@10550 43 * Cleaned up.
ghb@10550 44 * 06/14/99 stephen Removed methods taking a filename suffix.
ghb@10550 45 * 06/22/99 stephen Added missing T_FileStream_close in parse()
ghb@10550 46 * 11/09/99 weiv Added getLocale(), rewritten constructForLocale()
ghb@10550 47 * March 2000 weiv complete overhaul.
ghb@10550 48 ******************************************************************************
ghb@10550 49 */
ghb@10550 50
ghb@10550 51 #include "unicode/utypes.h"
ghb@10550 52 #include "unicode/resbund.h"
arajkumar@11038 53
arajkumar@11038 54 #include "mutex.h"
arajkumar@11038 55 #include "uassert.h"
ghb@10550 56 #include "umutex.h"
ghb@10550 57
ghb@10550 58 #include "uresimp.h"
ghb@10550 59
ghb@10550 60 U_NAMESPACE_BEGIN
ghb@10550 61
ghb@10550 62 /*-----------------------------------------------------------------------------
ghb@10550 63 * Implementation Notes
ghb@10550 64 *
ghb@10550 65 * Resource bundles are read in once, and thereafter cached.
ghb@10550 66 * ResourceBundle statically keeps track of which files have been
ghb@10550 67 * read, so we are guaranteed that each file is read at most once.
ghb@10550 68 * Resource bundles can be loaded from different data directories and
ghb@10550 69 * will be treated as distinct, even if they are for the same locale.
ghb@10550 70 *
ghb@10550 71 * Resource bundles are lightweight objects, which have pointers to
ghb@10550 72 * one or more shared Hashtable objects containing all the data.
ghb@10550 73 * Copying would be cheap, but there is no copy constructor, since
ghb@10550 74 * there wasn't one in the original API.
ghb@10550 75 *
ghb@10550 76 * The ResourceBundle parsing mechanism is implemented as a transition
ghb@10550 77 * network, for easy maintenance and modification. The network is
ghb@10550 78 * implemented as a matrix (instead of in code) to make this even
ghb@10550 79 * easier. The matrix contains Transition objects. Each Transition
ghb@10550 80 * object describes a destination node and an action to take before
ghb@10550 81 * moving to the destination node. The source node is encoded by the
ghb@10550 82 * index of the object in the array that contains it. The pieces
ghb@10550 83 * needed to understand the transition network are the enums for node
ghb@10550 84 * IDs and actions, the parse() method, which walks through the
ghb@10550 85 * network and implements the actions, and the network itself. The
ghb@10550 86 * network guarantees certain conditions, for example, that a new
ghb@10550 87 * resource will not be closed until one has been opened first; or
ghb@10550 88 * that data will not be stored into a TaggedList until a TaggedList
ghb@10550 89 * has been created. Nonetheless, the code in parse() does some
ghb@10550 90 * consistency checks as it runs the network, and fails with an
ghb@10550 91 * U_INTERNAL_PROGRAM_ERROR if one of these checks fails. If the input
ghb@10550 92 * data has a bad format, an U_INVALID_FORMAT_ERROR is returned. If you
ghb@10550 93 * see an U_INTERNAL_PROGRAM_ERROR the transition matrix has a bug in
ghb@10550 94 * it.
ghb@10550 95 *
ghb@10550 96 * Old functionality of multiple locales in a single file is still
ghb@10550 97 * supported. For this reason, LOCALE names override FILE names. If
ghb@10550 98 * data for en_US is located in the en.txt file, once it is loaded,
ghb@10550 99 * the code will not care where it came from (other than remembering
ghb@10550 100 * which directory it came from). However, if there is an en_US
ghb@10550 101 * resource in en_US.txt, that will take precedence. There is no
ghb@10550 102 * limit to the number or type of resources that can be stored in a
ghb@10550 103 * file, however, files are only searched in a specific way. If
ghb@10550 104 * en_US_CA is requested, then first en_US_CA.txt is searched, then
ghb@10550 105 * en_US.txt, then en.txt, then default.txt. So it only makes sense
ghb@10550 106 * to put certain locales in certain files. In this example, it would
ghb@10550 107 * be logical to put en_US_CA, en_US, and en into the en.txt file,
ghb@10550 108 * since they would be found there if asked for. The extreme example
ghb@10550 109 * is to place all locale resources into default.txt, which should
ghb@10550 110 * also work.
ghb@10550 111 *
ghb@10550 112 * Inheritance is implemented. For example, xx_YY_zz inherits as
ghb@10550 113 * follows: xx_YY_zz, xx_YY, xx, default. Inheritance is implemented
ghb@10550 114 * as an array of hashtables. There will be from 1 to 4 hashtables in
ghb@10550 115 * the array.
ghb@10550 116 *
ghb@10550 117 * Fallback files are implemented. The fallback pattern is Language
ghb@10550 118 * Country Variant (LCV) -> LC -> L. Fallback is first done for the
ghb@10550 119 * requested locale. Then it is done for the default locale, as
ghb@10550 120 * returned by Locale::getDefault(). Then the special file
ghb@10550 121 * default.txt is searched for the default locale. The overall FILE
ghb@10550 122 * fallback path is LCV -> LC -> L -> dLCV -> dLC -> dL -> default.
ghb@10550 123 *
ghb@10550 124 * Note that although file name searching includes the default locale,
ghb@10550 125 * once a ResourceBundle object is constructed, the inheritance path
ghb@10550 126 * no longer includes the default locale. The path is LCV -> LC -> L
ghb@10550 127 * -> default.
ghb@10550 128 *
ghb@10550 129 * File parsing is lazy. Nothing is parsed unless it is called for by
ghb@10550 130 * someone. So when a ResourceBundle for xx_YY_zz is constructed,
ghb@10550 131 * only that locale is parsed (along with anything else in the same
ghb@10550 132 * file). Later, if the FooBar tag is asked for, and if it isn't
ghb@10550 133 * found in xx_YY_zz, then xx_YY.txt will be parsed and checked, and
ghb@10550 134 * so forth, until the chain is exhausted or the tag is found.
ghb@10550 135 *
ghb@10550 136 * Thread-safety is implemented around caches, both the cache that
ghb@10550 137 * stores all the resouce data, and the cache that stores flags
ghb@10550 138 * indicating whether or not a file has been visited. These caches
ghb@10550 139 * delete their storage at static cleanup time, when the process
ghb@10550 140 * quits.
ghb@10550 141 *
ghb@10550 142 * ResourceBundle supports TableCollation as a special case. This
ghb@10550 143 * involves having special ResourceBundle objects which DO own their
ghb@10550 144 * data, since we don't want large collation rule strings in the
ghb@10550 145 * ResourceBundle cache (these are already cached in the
ghb@10550 146 * TableCollation cache). TableCollation files (.ctx files) have the
ghb@10550 147 * same format as normal resource data files, with a different
ghb@10550 148 * interpretation, from the standpoint of ResourceBundle. .ctx files
ghb@10550 149 * are loaded into otherwise ordinary ResourceBundle objects. They
ghb@10550 150 * don't inherit (that's implemented by TableCollation) and they own
ghb@10550 151 * their data (as mentioned above). However, they still support
ghb@10550 152 * possible multiple locales in a single .ctx file. (This is in
ghb@10550 153 * practice a bad idea, since you only want the one locale you're
ghb@10550 154 * looking for, and only one tag will be present
ghb@10550 155 * ("CollationElements"), so you don't need an inheritance chain of
ghb@10550 156 * multiple locales.) Up to 4 locale resources will be loaded from a
ghb@10550 157 * .ctx file; everything after the first 4 is ignored (parsed and
ghb@10550 158 * deleted). (Normal .txt files have no limit.) Instead of being
ghb@10550 159 * loaded into the cache, and then looked up as needed, the locale
ghb@10550 160 * resources are read straight into the ResourceBundle object.
ghb@10550 161 *
ghb@10550 162 * The Index, which used to reside in default.txt, has been moved to a
ghb@10550 163 * new file, index.txt. This file contains a slightly modified format
ghb@10550 164 * with the addition of the "InstalledLocales" tag; it looks like:
ghb@10550 165 *
ghb@10550 166 * Index {
ghb@10550 167 * InstalledLocales {
ghb@10550 168 * ar
ghb@10550 169 * ..
ghb@10550 170 * zh_TW
ghb@10550 171 * }
ghb@10550 172 * }
ghb@10550 173 */
ghb@10550 174 //-----------------------------------------------------------------------------
ghb@10550 175
ghb@10550 176 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ResourceBundle)
ghb@10550 177
ghb@10550 178 ResourceBundle::ResourceBundle(UErrorCode &err)
ghb@10550 179 :UObject(), fLocale(NULL)
ghb@10550 180 {
ghb@10550 181 fResource = ures_open(0, Locale::getDefault().getName(), &err);
ghb@10550 182 }
ghb@10550 183
ghb@10550 184 ResourceBundle::ResourceBundle(const ResourceBundle &other)
ghb@10550 185 :UObject(other), fLocale(NULL)
ghb@10550 186 {
ghb@10550 187 UErrorCode status = U_ZERO_ERROR;
ghb@10550 188
ghb@10550 189 if (other.fResource) {
ghb@10550 190 fResource = ures_copyResb(0, other.fResource, &status);
ghb@10550 191 } else {
ghb@10550 192 /* Copying a bad resource bundle */
ghb@10550 193 fResource = NULL;
ghb@10550 194 }
ghb@10550 195 }
ghb@10550 196
ghb@10550 197 ResourceBundle::ResourceBundle(UResourceBundle *res, UErrorCode& err)
ghb@10550 198 :UObject(), fLocale(NULL)
ghb@10550 199 {
ghb@10550 200 if (res) {
ghb@10550 201 fResource = ures_copyResb(0, res, &err);
ghb@10550 202 } else {
ghb@10550 203 /* Copying a bad resource bundle */
ghb@10550 204 fResource = NULL;
ghb@10550 205 }
ghb@10550 206 }
ghb@10550 207
ghb@10550 208 ResourceBundle::ResourceBundle(const char* path, const Locale& locale, UErrorCode& err)
ghb@10550 209 :UObject(), fLocale(NULL)
ghb@10550 210 {
ghb@10550 211 fResource = ures_open(path, locale.getName(), &err);
ghb@10550 212 }
ghb@10550 213
ghb@10550 214
ghb@10550 215 ResourceBundle& ResourceBundle::operator=(const ResourceBundle& other)
ghb@10550 216 {
ghb@10550 217 if(this == &other) {
ghb@10550 218 return *this;
ghb@10550 219 }
ghb@10550 220 if(fResource != 0) {
ghb@10550 221 ures_close(fResource);
ghb@10550 222 fResource = NULL;
ghb@10550 223 }
arajkumar@11038 224 if (fLocale != NULL) {
arajkumar@11038 225 delete fLocale;
arajkumar@11038 226 fLocale = NULL;
arajkumar@11038 227 }
ghb@10550 228 UErrorCode status = U_ZERO_ERROR;
ghb@10550 229 if (other.fResource) {
ghb@10550 230 fResource = ures_copyResb(0, other.fResource, &status);
ghb@10550 231 } else {
ghb@10550 232 /* Copying a bad resource bundle */
ghb@10550 233 fResource = NULL;
ghb@10550 234 }
ghb@10550 235 return *this;
ghb@10550 236 }
ghb@10550 237
ghb@10550 238 ResourceBundle::~ResourceBundle()
ghb@10550 239 {
ghb@10550 240 if(fResource != 0) {
ghb@10550 241 ures_close(fResource);
ghb@10550 242 }
ghb@10550 243 if(fLocale != NULL) {
ghb@10550 244 delete(fLocale);
ghb@10550 245 }
ghb@10550 246 }
ghb@10550 247
ghb@10550 248 ResourceBundle *
ghb@10550 249 ResourceBundle::clone() const {
ghb@10550 250 return new ResourceBundle(*this);
ghb@10550 251 }
ghb@10550 252
ghb@10550 253 UnicodeString ResourceBundle::getString(UErrorCode& status) const {
ghb@10550 254 int32_t len = 0;
ghb@10550 255 const UChar *r = ures_getString(fResource, &len, &status);
ghb@10550 256 return UnicodeString(TRUE, r, len);
ghb@10550 257 }
ghb@10550 258
ghb@10550 259 const uint8_t *ResourceBundle::getBinary(int32_t& len, UErrorCode& status) const {
ghb@10550 260 return ures_getBinary(fResource, &len, &status);
ghb@10550 261 }
ghb@10550 262
ghb@10550 263 const int32_t *ResourceBundle::getIntVector(int32_t& len, UErrorCode& status) const {
ghb@10550 264 return ures_getIntVector(fResource, &len, &status);
ghb@10550 265 }
ghb@10550 266
ghb@10550 267 uint32_t ResourceBundle::getUInt(UErrorCode& status) const {
ghb@10550 268 return ures_getUInt(fResource, &status);
ghb@10550 269 }
ghb@10550 270
ghb@10550 271 int32_t ResourceBundle::getInt(UErrorCode& status) const {
ghb@10550 272 return ures_getInt(fResource, &status);
ghb@10550 273 }
ghb@10550 274
ghb@10550 275 const char *ResourceBundle::getName(void) const {
ghb@10550 276 return ures_getName(fResource);
ghb@10550 277 }
ghb@10550 278
ghb@10550 279 const char *ResourceBundle::getKey(void) const {
ghb@10550 280 return ures_getKey(fResource);
ghb@10550 281 }
ghb@10550 282
ghb@10550 283 UResType ResourceBundle::getType(void) const {
ghb@10550 284 return ures_getType(fResource);
ghb@10550 285 }
ghb@10550 286
ghb@10550 287 int32_t ResourceBundle::getSize(void) const {
ghb@10550 288 return ures_getSize(fResource);
ghb@10550 289 }
ghb@10550 290
ghb@10550 291 UBool ResourceBundle::hasNext(void) const {
ghb@10550 292 return ures_hasNext(fResource);
ghb@10550 293 }
ghb@10550 294
ghb@10550 295 void ResourceBundle::resetIterator(void) {
ghb@10550 296 ures_resetIterator(fResource);
ghb@10550 297 }
ghb@10550 298
ghb@10550 299 ResourceBundle ResourceBundle::getNext(UErrorCode& status) {
ghb@10550 300 UResourceBundle r;
ghb@10550 301
ghb@10550 302 ures_initStackObject(&r);
ghb@10550 303 ures_getNextResource(fResource, &r, &status);
ghb@10550 304 ResourceBundle res(&r, status);
ghb@10550 305 if (U_SUCCESS(status)) {
ghb@10550 306 ures_close(&r);
ghb@10550 307 }
ghb@10550 308 return res;
ghb@10550 309 }
ghb@10550 310
ghb@10550 311 UnicodeString ResourceBundle::getNextString(UErrorCode& status) {
ghb@10550 312 int32_t len = 0;
ghb@10550 313 const UChar* r = ures_getNextString(fResource, &len, 0, &status);
ghb@10550 314 return UnicodeString(TRUE, r, len);
ghb@10550 315 }
ghb@10550 316
ghb@10550 317 UnicodeString ResourceBundle::getNextString(const char ** key, UErrorCode& status) {
ghb@10550 318 int32_t len = 0;
ghb@10550 319 const UChar* r = ures_getNextString(fResource, &len, key, &status);
ghb@10550 320 return UnicodeString(TRUE, r, len);
ghb@10550 321 }
ghb@10550 322
ghb@10550 323 ResourceBundle ResourceBundle::get(int32_t indexR, UErrorCode& status) const {
ghb@10550 324 UResourceBundle r;
ghb@10550 325
ghb@10550 326 ures_initStackObject(&r);
ghb@10550 327 ures_getByIndex(fResource, indexR, &r, &status);
ghb@10550 328 ResourceBundle res(&r, status);
ghb@10550 329 if (U_SUCCESS(status)) {
ghb@10550 330 ures_close(&r);
ghb@10550 331 }
ghb@10550 332 return res;
ghb@10550 333 }
ghb@10550 334
ghb@10550 335 UnicodeString ResourceBundle::getStringEx(int32_t indexS, UErrorCode& status) const {
ghb@10550 336 int32_t len = 0;
ghb@10550 337 const UChar* r = ures_getStringByIndex(fResource, indexS, &len, &status);
ghb@10550 338 return UnicodeString(TRUE, r, len);
ghb@10550 339 }
ghb@10550 340
ghb@10550 341 ResourceBundle ResourceBundle::get(const char* key, UErrorCode& status) const {
ghb@10550 342 UResourceBundle r;
ghb@10550 343
ghb@10550 344 ures_initStackObject(&r);
ghb@10550 345 ures_getByKey(fResource, key, &r, &status);
ghb@10550 346 ResourceBundle res(&r, status);
ghb@10550 347 if (U_SUCCESS(status)) {
ghb@10550 348 ures_close(&r);
ghb@10550 349 }
ghb@10550 350 return res;
ghb@10550 351 }
ghb@10550 352
ghb@10550 353 ResourceBundle ResourceBundle::getWithFallback(const char* key, UErrorCode& status){
ghb@10550 354 UResourceBundle r;
ghb@10550 355 ures_initStackObject(&r);
ghb@10550 356 ures_getByKeyWithFallback(fResource, key, &r, &status);
ghb@10550 357 ResourceBundle res(&r, status);
ghb@10550 358 if(U_SUCCESS(status)){
ghb@10550 359 ures_close(&r);
ghb@10550 360 }
ghb@10550 361 return res;
ghb@10550 362 }
ghb@10550 363 UnicodeString ResourceBundle::getStringEx(const char* key, UErrorCode& status) const {
ghb@10550 364 int32_t len = 0;
ghb@10550 365 const UChar* r = ures_getStringByKey(fResource, key, &len, &status);
ghb@10550 366 return UnicodeString(TRUE, r, len);
ghb@10550 367 }
ghb@10550 368
ghb@10550 369 const char*
ghb@10550 370 ResourceBundle::getVersionNumber() const
ghb@10550 371 {
ghb@10550 372 return ures_getVersionNumberInternal(fResource);
ghb@10550 373 }
ghb@10550 374
ghb@10550 375 void ResourceBundle::getVersion(UVersionInfo versionInfo) const {
ghb@10550 376 ures_getVersion(fResource, versionInfo);
ghb@10550 377 }
ghb@10550 378
arajkumar@11038 379 static UMutex gLocaleLock = U_MUTEX_INITIALIZER;
arajkumar@11038 380 const Locale &ResourceBundle::getLocale(void) const {
arajkumar@11038 381 Mutex lock(&gLocaleLock);
arajkumar@11038 382 if (fLocale != NULL) {
arajkumar@11038 383 return *fLocale;
ghb@10550 384 }
arajkumar@11038 385 UErrorCode status = U_ZERO_ERROR;
arajkumar@11038 386 const char *localeName = ures_getLocaleInternal(fResource, &status);
arajkumar@11038 387 ResourceBundle *ncThis = const_cast<ResourceBundle *>(this);
arajkumar@11038 388 ncThis->fLocale = new Locale(localeName);
arajkumar@11038 389 return ncThis->fLocale != NULL ? *ncThis->fLocale : Locale::getDefault();
ghb@10550 390 }
ghb@10550 391
ghb@10550 392 const Locale ResourceBundle::getLocale(ULocDataLocaleType type, UErrorCode &status) const
ghb@10550 393 {
ghb@10550 394 return ures_getLocaleByType(fResource, type, &status);
ghb@10550 395 }
ghb@10550 396
arajkumar@11038 397 U_NAMESPACE_END
ghb@10550 398 //eof