dtfmtsym.cpp 106 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556
  1. // © 2016 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. /*
  4. *******************************************************************************
  5. * Copyright (C) 1997-2016, International Business Machines Corporation and *
  6. * others. All Rights Reserved. *
  7. *******************************************************************************
  8. *
  9. * File DTFMTSYM.CPP
  10. *
  11. * Modification History:
  12. *
  13. * Date Name Description
  14. * 02/19/97 aliu Converted from java.
  15. * 07/21/98 stephen Added getZoneIndex
  16. * Changed weekdays/short weekdays to be one-based
  17. * 06/14/99 stephen Removed SimpleDateFormat::fgTimeZoneDataSuffix
  18. * 11/16/99 weiv Added 'Y' and 'e' to fgPatternChars
  19. * 03/27/00 weiv Keeping resource bundle around!
  20. * 06/30/05 emmons Added eraNames, narrow month/day, standalone context
  21. * 10/12/05 emmons Added setters for eraNames, month/day by width/context
  22. *******************************************************************************
  23. */
  24. #include <utility>
  25. #include "unicode/utypes.h"
  26. #if !UCONFIG_NO_FORMATTING
  27. #include "unicode/ustring.h"
  28. #include "unicode/localpointer.h"
  29. #include "unicode/dtfmtsym.h"
  30. #include "unicode/smpdtfmt.h"
  31. #include "unicode/msgfmt.h"
  32. #include "unicode/numsys.h"
  33. #include "unicode/tznames.h"
  34. #include "cpputils.h"
  35. #include "umutex.h"
  36. #include "cmemory.h"
  37. #include "cstring.h"
  38. #include "charstr.h"
  39. #include "dt_impl.h"
  40. #include "locbased.h"
  41. #include "gregoimp.h"
  42. #include "hash.h"
  43. #include "uassert.h"
  44. #include "uresimp.h"
  45. #include "ureslocs.h"
  46. #include "uvector.h"
  47. #include "shareddateformatsymbols.h"
  48. #include "unicode/calendar.h"
  49. #include "unifiedcache.h"
  50. // *****************************************************************************
  51. // class DateFormatSymbols
  52. // *****************************************************************************
  53. /**
  54. * These are static arrays we use only in the case where we have no
  55. * resource data.
  56. */
  57. #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
  58. #define PATTERN_CHARS_LEN 38
  59. #else
  60. #define PATTERN_CHARS_LEN 37
  61. #endif
  62. /**
  63. * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All
  64. * locales use the same these unlocalized pattern characters.
  65. */
  66. static const char16_t gPatternChars[] = {
  67. // if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR:
  68. // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:
  69. // else:
  70. // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB
  71. 0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45,
  72. 0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65,
  73. 0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0x51, 0x71, 0x56,
  74. 0x55, 0x4F, 0x58, 0x78, 0x72, 0x62, 0x42,
  75. #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
  76. 0x3a,
  77. #endif
  78. 0
  79. };
  80. //------------------------------------------------------
  81. // Strings of last resort. These are only used if we have no resource
  82. // files. They aren't designed for actual use, just for backup.
  83. // These are the month names and abbreviations of last resort.
  84. static const char16_t gLastResortMonthNames[13][3] =
  85. {
  86. {0x0030, 0x0031, 0x0000}, /* "01" */
  87. {0x0030, 0x0032, 0x0000}, /* "02" */
  88. {0x0030, 0x0033, 0x0000}, /* "03" */
  89. {0x0030, 0x0034, 0x0000}, /* "04" */
  90. {0x0030, 0x0035, 0x0000}, /* "05" */
  91. {0x0030, 0x0036, 0x0000}, /* "06" */
  92. {0x0030, 0x0037, 0x0000}, /* "07" */
  93. {0x0030, 0x0038, 0x0000}, /* "08" */
  94. {0x0030, 0x0039, 0x0000}, /* "09" */
  95. {0x0031, 0x0030, 0x0000}, /* "10" */
  96. {0x0031, 0x0031, 0x0000}, /* "11" */
  97. {0x0031, 0x0032, 0x0000}, /* "12" */
  98. {0x0031, 0x0033, 0x0000} /* "13" */
  99. };
  100. // These are the weekday names and abbreviations of last resort.
  101. static const char16_t gLastResortDayNames[8][2] =
  102. {
  103. {0x0030, 0x0000}, /* "0" */
  104. {0x0031, 0x0000}, /* "1" */
  105. {0x0032, 0x0000}, /* "2" */
  106. {0x0033, 0x0000}, /* "3" */
  107. {0x0034, 0x0000}, /* "4" */
  108. {0x0035, 0x0000}, /* "5" */
  109. {0x0036, 0x0000}, /* "6" */
  110. {0x0037, 0x0000} /* "7" */
  111. };
  112. // These are the quarter names and abbreviations of last resort.
  113. static const char16_t gLastResortQuarters[4][2] =
  114. {
  115. {0x0031, 0x0000}, /* "1" */
  116. {0x0032, 0x0000}, /* "2" */
  117. {0x0033, 0x0000}, /* "3" */
  118. {0x0034, 0x0000}, /* "4" */
  119. };
  120. // These are the am/pm and BC/AD markers of last resort.
  121. static const char16_t gLastResortAmPmMarkers[2][3] =
  122. {
  123. {0x0041, 0x004D, 0x0000}, /* "AM" */
  124. {0x0050, 0x004D, 0x0000} /* "PM" */
  125. };
  126. static const char16_t gLastResortEras[2][3] =
  127. {
  128. {0x0042, 0x0043, 0x0000}, /* "BC" */
  129. {0x0041, 0x0044, 0x0000} /* "AD" */
  130. };
  131. /* Sizes for the last resort string arrays */
  132. typedef enum LastResortSize {
  133. kMonthNum = 13,
  134. kMonthLen = 3,
  135. kDayNum = 8,
  136. kDayLen = 2,
  137. kAmPmNum = 2,
  138. kAmPmLen = 3,
  139. kQuarterNum = 4,
  140. kQuarterLen = 2,
  141. kEraNum = 2,
  142. kEraLen = 3,
  143. kZoneNum = 5,
  144. kZoneLen = 4,
  145. kGmtHourNum = 4,
  146. kGmtHourLen = 10
  147. } LastResortSize;
  148. U_NAMESPACE_BEGIN
  149. SharedDateFormatSymbols::~SharedDateFormatSymbols() {
  150. }
  151. template<> U_I18N_API
  152. const SharedDateFormatSymbols *
  153. LocaleCacheKey<SharedDateFormatSymbols>::createObject(
  154. const void * /*unusedContext*/, UErrorCode &status) const {
  155. char type[256];
  156. Calendar::getCalendarTypeFromLocale(fLoc, type, UPRV_LENGTHOF(type), status);
  157. if (U_FAILURE(status)) {
  158. return nullptr;
  159. }
  160. SharedDateFormatSymbols *shared
  161. = new SharedDateFormatSymbols(fLoc, type, status);
  162. if (shared == nullptr) {
  163. status = U_MEMORY_ALLOCATION_ERROR;
  164. return nullptr;
  165. }
  166. if (U_FAILURE(status)) {
  167. delete shared;
  168. return nullptr;
  169. }
  170. shared->addRef();
  171. return shared;
  172. }
  173. UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols)
  174. #define kSUPPLEMENTAL "supplementalData"
  175. /**
  176. * These are the tags we expect to see in normal resource bundle files associated
  177. * with a locale and calendar
  178. */
  179. static const char gCalendarTag[]="calendar";
  180. static const char gGregorianTag[]="gregorian";
  181. static const char gErasTag[]="eras";
  182. static const char gCyclicNameSetsTag[]="cyclicNameSets";
  183. static const char gNameSetYearsTag[]="years";
  184. static const char gNameSetZodiacsTag[]="zodiacs";
  185. static const char gMonthNamesTag[]="monthNames";
  186. static const char gMonthPatternsTag[]="monthPatterns";
  187. static const char gDayNamesTag[]="dayNames";
  188. static const char gNamesWideTag[]="wide";
  189. static const char gNamesAbbrTag[]="abbreviated";
  190. static const char gNamesShortTag[]="short";
  191. static const char gNamesNarrowTag[]="narrow";
  192. static const char gNamesAllTag[]="all";
  193. static const char gNamesFormatTag[]="format";
  194. static const char gNamesStandaloneTag[]="stand-alone";
  195. static const char gNamesNumericTag[]="numeric";
  196. static const char gAmPmMarkersTag[]="AmPmMarkers";
  197. static const char gAmPmMarkersAbbrTag[]="AmPmMarkersAbbr";
  198. static const char gAmPmMarkersNarrowTag[]="AmPmMarkersNarrow";
  199. static const char gQuartersTag[]="quarters";
  200. static const char gNumberElementsTag[]="NumberElements";
  201. static const char gSymbolsTag[]="symbols";
  202. static const char gTimeSeparatorTag[]="timeSeparator";
  203. static const char gDayPeriodTag[]="dayPeriod";
  204. // static const char gZoneStringsTag[]="zoneStrings";
  205. // static const char gLocalPatternCharsTag[]="localPatternChars";
  206. static const char gContextTransformsTag[]="contextTransforms";
  207. /**
  208. * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly.
  209. * Work around this.
  210. */
  211. static inline UnicodeString* newUnicodeStringArray(size_t count) {
  212. return new UnicodeString[count ? count : 1];
  213. }
  214. //------------------------------------------------------
  215. DateFormatSymbols * U_EXPORT2
  216. DateFormatSymbols::createForLocale(
  217. const Locale& locale, UErrorCode &status) {
  218. const SharedDateFormatSymbols *shared = nullptr;
  219. UnifiedCache::getByLocale(locale, shared, status);
  220. if (U_FAILURE(status)) {
  221. return nullptr;
  222. }
  223. DateFormatSymbols *result = new DateFormatSymbols(shared->get());
  224. shared->removeRef();
  225. if (result == nullptr) {
  226. status = U_MEMORY_ALLOCATION_ERROR;
  227. return nullptr;
  228. }
  229. return result;
  230. }
  231. DateFormatSymbols::DateFormatSymbols(const Locale& locale,
  232. UErrorCode& status)
  233. : UObject()
  234. {
  235. initializeData(locale, nullptr, status);
  236. }
  237. DateFormatSymbols::DateFormatSymbols(UErrorCode& status)
  238. : UObject()
  239. {
  240. initializeData(Locale::getDefault(), nullptr, status, true);
  241. }
  242. DateFormatSymbols::DateFormatSymbols(const Locale& locale,
  243. const char *type,
  244. UErrorCode& status)
  245. : UObject()
  246. {
  247. initializeData(locale, type, status);
  248. }
  249. DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status)
  250. : UObject()
  251. {
  252. initializeData(Locale::getDefault(), type, status, true);
  253. }
  254. DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other)
  255. : UObject(other)
  256. {
  257. copyData(other);
  258. }
  259. void
  260. DateFormatSymbols::assignArray(UnicodeString*& dstArray,
  261. int32_t& dstCount,
  262. const UnicodeString* srcArray,
  263. int32_t srcCount)
  264. {
  265. // assignArray() is only called by copyData() and initializeData(), which in turn
  266. // implements the copy constructor and the assignment operator.
  267. // All strings in a DateFormatSymbols object are created in one of the following
  268. // three ways that all allow to safely use UnicodeString::fastCopyFrom():
  269. // - readonly-aliases from resource bundles
  270. // - readonly-aliases or allocated strings from constants
  271. // - safely cloned strings (with owned buffers) from setXYZ() functions
  272. //
  273. // Note that this is true for as long as DateFormatSymbols can be constructed
  274. // only from a locale bundle or set via the cloning API,
  275. // *and* for as long as all the strings are in *private* fields, preventing
  276. // a subclass from creating these strings in an "unsafe" way (with respect to fastCopyFrom()).
  277. if(srcArray == nullptr) {
  278. // Do not attempt to copy bogus input (which will crash).
  279. // Note that this assignArray method already had the potential to return a null dstArray;
  280. // see handling below for "if(dstArray != nullptr)".
  281. dstCount = 0;
  282. dstArray = nullptr;
  283. return;
  284. }
  285. dstCount = srcCount;
  286. dstArray = newUnicodeStringArray(srcCount);
  287. if(dstArray != nullptr) {
  288. int32_t i;
  289. for(i=0; i<srcCount; ++i) {
  290. dstArray[i].fastCopyFrom(srcArray[i]);
  291. }
  292. }
  293. }
  294. /**
  295. * Create a copy, in fZoneStrings, of the given zone strings array. The
  296. * member variables fZoneStringsRowCount and fZoneStringsColCount should
  297. * be set already by the caller.
  298. */
  299. void
  300. DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings)
  301. {
  302. int32_t row, col;
  303. UBool failed = false;
  304. fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *));
  305. if (fZoneStrings != nullptr) {
  306. for (row=0; row<fZoneStringsRowCount; ++row)
  307. {
  308. fZoneStrings[row] = newUnicodeStringArray(fZoneStringsColCount);
  309. if (fZoneStrings[row] == nullptr) {
  310. failed = true;
  311. break;
  312. }
  313. for (col=0; col<fZoneStringsColCount; ++col) {
  314. // fastCopyFrom() - see assignArray comments
  315. fZoneStrings[row][col].fastCopyFrom(otherStrings[row][col]);
  316. }
  317. }
  318. }
  319. // If memory allocation failed, roll back and delete fZoneStrings
  320. if (failed) {
  321. for (int i = row; i >= 0; i--) {
  322. delete[] fZoneStrings[i];
  323. }
  324. uprv_free(fZoneStrings);
  325. fZoneStrings = nullptr;
  326. }
  327. }
  328. /**
  329. * Copy all of the other's data to this.
  330. */
  331. void
  332. DateFormatSymbols::copyData(const DateFormatSymbols& other) {
  333. UErrorCode status = U_ZERO_ERROR;
  334. U_LOCALE_BASED(locBased, *this);
  335. locBased.setLocaleIDs(
  336. other.getLocale(ULOC_VALID_LOCALE, status),
  337. other.getLocale(ULOC_ACTUAL_LOCALE, status));
  338. assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
  339. assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
  340. assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount);
  341. assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount);
  342. assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount);
  343. assignArray(fNarrowMonths, fNarrowMonthsCount, other.fNarrowMonths, other.fNarrowMonthsCount);
  344. assignArray(fStandaloneMonths, fStandaloneMonthsCount, other.fStandaloneMonths, other.fStandaloneMonthsCount);
  345. assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, other.fStandaloneShortMonths, other.fStandaloneShortMonthsCount);
  346. assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, other.fStandaloneNarrowMonths, other.fStandaloneNarrowMonthsCount);
  347. assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount);
  348. assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount);
  349. assignArray(fShorterWeekdays, fShorterWeekdaysCount, other.fShorterWeekdays, other.fShorterWeekdaysCount);
  350. assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, other.fNarrowWeekdays, other.fNarrowWeekdaysCount);
  351. assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, other.fStandaloneWeekdays, other.fStandaloneWeekdaysCount);
  352. assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, other.fStandaloneShortWeekdays, other.fStandaloneShortWeekdaysCount);
  353. assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, other.fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdaysCount);
  354. assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount);
  355. assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount);
  356. assignArray(fNarrowAmPms, fNarrowAmPmsCount, other.fNarrowAmPms, other.fNarrowAmPmsCount );
  357. fTimeSeparator.fastCopyFrom(other.fTimeSeparator); // fastCopyFrom() - see assignArray comments
  358. assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount);
  359. assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount);
  360. assignArray(fNarrowQuarters, fNarrowQuartersCount, other.fNarrowQuarters, other.fNarrowQuartersCount);
  361. assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount);
  362. assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount);
  363. assignArray(fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, other.fStandaloneNarrowQuarters, other.fStandaloneNarrowQuartersCount);
  364. assignArray(fWideDayPeriods, fWideDayPeriodsCount,
  365. other.fWideDayPeriods, other.fWideDayPeriodsCount);
  366. assignArray(fNarrowDayPeriods, fNarrowDayPeriodsCount,
  367. other.fNarrowDayPeriods, other.fNarrowDayPeriodsCount);
  368. assignArray(fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount,
  369. other.fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriodsCount);
  370. assignArray(fStandaloneWideDayPeriods, fStandaloneWideDayPeriodsCount,
  371. other.fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriodsCount);
  372. assignArray(fStandaloneNarrowDayPeriods, fStandaloneNarrowDayPeriodsCount,
  373. other.fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriodsCount);
  374. assignArray(fStandaloneAbbreviatedDayPeriods, fStandaloneAbbreviatedDayPeriodsCount,
  375. other.fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriodsCount);
  376. if (other.fLeapMonthPatterns != nullptr) {
  377. assignArray(fLeapMonthPatterns, fLeapMonthPatternsCount, other.fLeapMonthPatterns, other.fLeapMonthPatternsCount);
  378. } else {
  379. fLeapMonthPatterns = nullptr;
  380. fLeapMonthPatternsCount = 0;
  381. }
  382. if (other.fShortYearNames != nullptr) {
  383. assignArray(fShortYearNames, fShortYearNamesCount, other.fShortYearNames, other.fShortYearNamesCount);
  384. } else {
  385. fShortYearNames = nullptr;
  386. fShortYearNamesCount = 0;
  387. }
  388. if (other.fShortZodiacNames != nullptr) {
  389. assignArray(fShortZodiacNames, fShortZodiacNamesCount, other.fShortZodiacNames, other.fShortZodiacNamesCount);
  390. } else {
  391. fShortZodiacNames = nullptr;
  392. fShortZodiacNamesCount = 0;
  393. }
  394. if (other.fZoneStrings != nullptr) {
  395. fZoneStringsColCount = other.fZoneStringsColCount;
  396. fZoneStringsRowCount = other.fZoneStringsRowCount;
  397. createZoneStrings((const UnicodeString**)other.fZoneStrings);
  398. } else {
  399. fZoneStrings = nullptr;
  400. fZoneStringsColCount = 0;
  401. fZoneStringsRowCount = 0;
  402. }
  403. fZSFLocale = other.fZSFLocale;
  404. // Other zone strings data is created on demand
  405. fLocaleZoneStrings = nullptr;
  406. // fastCopyFrom() - see assignArray comments
  407. fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
  408. uprv_memcpy(fCapitalization, other.fCapitalization, sizeof(fCapitalization));
  409. }
  410. /**
  411. * Assignment operator.
  412. */
  413. DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
  414. {
  415. if (this == &other) { return *this; } // self-assignment: no-op
  416. dispose();
  417. copyData(other);
  418. return *this;
  419. }
  420. DateFormatSymbols::~DateFormatSymbols()
  421. {
  422. dispose();
  423. }
  424. void DateFormatSymbols::dispose()
  425. {
  426. delete[] fEras;
  427. delete[] fEraNames;
  428. delete[] fNarrowEras;
  429. delete[] fMonths;
  430. delete[] fShortMonths;
  431. delete[] fNarrowMonths;
  432. delete[] fStandaloneMonths;
  433. delete[] fStandaloneShortMonths;
  434. delete[] fStandaloneNarrowMonths;
  435. delete[] fWeekdays;
  436. delete[] fShortWeekdays;
  437. delete[] fShorterWeekdays;
  438. delete[] fNarrowWeekdays;
  439. delete[] fStandaloneWeekdays;
  440. delete[] fStandaloneShortWeekdays;
  441. delete[] fStandaloneShorterWeekdays;
  442. delete[] fStandaloneNarrowWeekdays;
  443. delete[] fAmPms;
  444. delete[] fNarrowAmPms;
  445. delete[] fQuarters;
  446. delete[] fShortQuarters;
  447. delete[] fNarrowQuarters;
  448. delete[] fStandaloneQuarters;
  449. delete[] fStandaloneShortQuarters;
  450. delete[] fStandaloneNarrowQuarters;
  451. delete[] fLeapMonthPatterns;
  452. delete[] fShortYearNames;
  453. delete[] fShortZodiacNames;
  454. delete[] fAbbreviatedDayPeriods;
  455. delete[] fWideDayPeriods;
  456. delete[] fNarrowDayPeriods;
  457. delete[] fStandaloneAbbreviatedDayPeriods;
  458. delete[] fStandaloneWideDayPeriods;
  459. delete[] fStandaloneNarrowDayPeriods;
  460. disposeZoneStrings();
  461. }
  462. void DateFormatSymbols::disposeZoneStrings()
  463. {
  464. if (fZoneStrings) {
  465. for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
  466. delete[] fZoneStrings[row];
  467. }
  468. uprv_free(fZoneStrings);
  469. }
  470. if (fLocaleZoneStrings) {
  471. for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
  472. delete[] fLocaleZoneStrings[row];
  473. }
  474. uprv_free(fLocaleZoneStrings);
  475. }
  476. fZoneStrings = nullptr;
  477. fLocaleZoneStrings = nullptr;
  478. fZoneStringsRowCount = 0;
  479. fZoneStringsColCount = 0;
  480. }
  481. UBool
  482. DateFormatSymbols::arrayCompare(const UnicodeString* array1,
  483. const UnicodeString* array2,
  484. int32_t count)
  485. {
  486. if (array1 == array2) return true;
  487. while (count>0)
  488. {
  489. --count;
  490. if (array1[count] != array2[count]) return false;
  491. }
  492. return true;
  493. }
  494. bool
  495. DateFormatSymbols::operator==(const DateFormatSymbols& other) const
  496. {
  497. // First do cheap comparisons
  498. if (this == &other) {
  499. return true;
  500. }
  501. if (fErasCount == other.fErasCount &&
  502. fEraNamesCount == other.fEraNamesCount &&
  503. fNarrowErasCount == other.fNarrowErasCount &&
  504. fMonthsCount == other.fMonthsCount &&
  505. fShortMonthsCount == other.fShortMonthsCount &&
  506. fNarrowMonthsCount == other.fNarrowMonthsCount &&
  507. fStandaloneMonthsCount == other.fStandaloneMonthsCount &&
  508. fStandaloneShortMonthsCount == other.fStandaloneShortMonthsCount &&
  509. fStandaloneNarrowMonthsCount == other.fStandaloneNarrowMonthsCount &&
  510. fWeekdaysCount == other.fWeekdaysCount &&
  511. fShortWeekdaysCount == other.fShortWeekdaysCount &&
  512. fShorterWeekdaysCount == other.fShorterWeekdaysCount &&
  513. fNarrowWeekdaysCount == other.fNarrowWeekdaysCount &&
  514. fStandaloneWeekdaysCount == other.fStandaloneWeekdaysCount &&
  515. fStandaloneShortWeekdaysCount == other.fStandaloneShortWeekdaysCount &&
  516. fStandaloneShorterWeekdaysCount == other.fStandaloneShorterWeekdaysCount &&
  517. fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount &&
  518. fAmPmsCount == other.fAmPmsCount &&
  519. fNarrowAmPmsCount == other.fNarrowAmPmsCount &&
  520. fQuartersCount == other.fQuartersCount &&
  521. fShortQuartersCount == other.fShortQuartersCount &&
  522. fNarrowQuartersCount == other.fNarrowQuartersCount &&
  523. fStandaloneQuartersCount == other.fStandaloneQuartersCount &&
  524. fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount &&
  525. fStandaloneNarrowQuartersCount == other.fStandaloneNarrowQuartersCount &&
  526. fLeapMonthPatternsCount == other.fLeapMonthPatternsCount &&
  527. fShortYearNamesCount == other.fShortYearNamesCount &&
  528. fShortZodiacNamesCount == other.fShortZodiacNamesCount &&
  529. fAbbreviatedDayPeriodsCount == other.fAbbreviatedDayPeriodsCount &&
  530. fWideDayPeriodsCount == other.fWideDayPeriodsCount &&
  531. fNarrowDayPeriodsCount == other.fNarrowDayPeriodsCount &&
  532. fStandaloneAbbreviatedDayPeriodsCount == other.fStandaloneAbbreviatedDayPeriodsCount &&
  533. fStandaloneWideDayPeriodsCount == other.fStandaloneWideDayPeriodsCount &&
  534. fStandaloneNarrowDayPeriodsCount == other.fStandaloneNarrowDayPeriodsCount &&
  535. (uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization))==0))
  536. {
  537. // Now compare the arrays themselves
  538. if (arrayCompare(fEras, other.fEras, fErasCount) &&
  539. arrayCompare(fEraNames, other.fEraNames, fEraNamesCount) &&
  540. arrayCompare(fNarrowEras, other.fNarrowEras, fNarrowErasCount) &&
  541. arrayCompare(fMonths, other.fMonths, fMonthsCount) &&
  542. arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) &&
  543. arrayCompare(fNarrowMonths, other.fNarrowMonths, fNarrowMonthsCount) &&
  544. arrayCompare(fStandaloneMonths, other.fStandaloneMonths, fStandaloneMonthsCount) &&
  545. arrayCompare(fStandaloneShortMonths, other.fStandaloneShortMonths, fStandaloneShortMonthsCount) &&
  546. arrayCompare(fStandaloneNarrowMonths, other.fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount) &&
  547. arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) &&
  548. arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) &&
  549. arrayCompare(fShorterWeekdays, other.fShorterWeekdays, fShorterWeekdaysCount) &&
  550. arrayCompare(fNarrowWeekdays, other.fNarrowWeekdays, fNarrowWeekdaysCount) &&
  551. arrayCompare(fStandaloneWeekdays, other.fStandaloneWeekdays, fStandaloneWeekdaysCount) &&
  552. arrayCompare(fStandaloneShortWeekdays, other.fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount) &&
  553. arrayCompare(fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount) &&
  554. arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) &&
  555. arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) &&
  556. arrayCompare(fNarrowAmPms, other.fNarrowAmPms, fNarrowAmPmsCount) &&
  557. fTimeSeparator == other.fTimeSeparator &&
  558. arrayCompare(fQuarters, other.fQuarters, fQuartersCount) &&
  559. arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) &&
  560. arrayCompare(fNarrowQuarters, other.fNarrowQuarters, fNarrowQuartersCount) &&
  561. arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) &&
  562. arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) &&
  563. arrayCompare(fStandaloneNarrowQuarters, other.fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount) &&
  564. arrayCompare(fLeapMonthPatterns, other.fLeapMonthPatterns, fLeapMonthPatternsCount) &&
  565. arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount) &&
  566. arrayCompare(fShortZodiacNames, other.fShortZodiacNames, fShortZodiacNamesCount) &&
  567. arrayCompare(fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount) &&
  568. arrayCompare(fWideDayPeriods, other.fWideDayPeriods, fWideDayPeriodsCount) &&
  569. arrayCompare(fNarrowDayPeriods, other.fNarrowDayPeriods, fNarrowDayPeriodsCount) &&
  570. arrayCompare(fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriods,
  571. fStandaloneAbbreviatedDayPeriodsCount) &&
  572. arrayCompare(fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriods,
  573. fStandaloneWideDayPeriodsCount) &&
  574. arrayCompare(fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriods,
  575. fStandaloneWideDayPeriodsCount))
  576. {
  577. // Compare the contents of fZoneStrings
  578. if (fZoneStrings == nullptr && other.fZoneStrings == nullptr) {
  579. if (fZSFLocale == other.fZSFLocale) {
  580. return true;
  581. }
  582. } else if (fZoneStrings != nullptr && other.fZoneStrings != nullptr) {
  583. if (fZoneStringsRowCount == other.fZoneStringsRowCount
  584. && fZoneStringsColCount == other.fZoneStringsColCount) {
  585. bool cmpres = true;
  586. for (int32_t i = 0; (i < fZoneStringsRowCount) && cmpres; i++) {
  587. cmpres = arrayCompare(fZoneStrings[i], other.fZoneStrings[i], fZoneStringsColCount);
  588. }
  589. return cmpres;
  590. }
  591. }
  592. return false;
  593. }
  594. }
  595. return false;
  596. }
  597. //------------------------------------------------------
  598. const UnicodeString*
  599. DateFormatSymbols::getEras(int32_t &count) const
  600. {
  601. count = fErasCount;
  602. return fEras;
  603. }
  604. const UnicodeString*
  605. DateFormatSymbols::getEraNames(int32_t &count) const
  606. {
  607. count = fEraNamesCount;
  608. return fEraNames;
  609. }
  610. const UnicodeString*
  611. DateFormatSymbols::getNarrowEras(int32_t &count) const
  612. {
  613. count = fNarrowErasCount;
  614. return fNarrowEras;
  615. }
  616. const UnicodeString*
  617. DateFormatSymbols::getMonths(int32_t &count) const
  618. {
  619. count = fMonthsCount;
  620. return fMonths;
  621. }
  622. const UnicodeString*
  623. DateFormatSymbols::getShortMonths(int32_t &count) const
  624. {
  625. count = fShortMonthsCount;
  626. return fShortMonths;
  627. }
  628. const UnicodeString*
  629. DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType width ) const
  630. {
  631. UnicodeString *returnValue = nullptr;
  632. switch (context) {
  633. case FORMAT :
  634. switch(width) {
  635. case WIDE :
  636. count = fMonthsCount;
  637. returnValue = fMonths;
  638. break;
  639. case ABBREVIATED :
  640. case SHORT : // no month data for this, defaults to ABBREVIATED
  641. count = fShortMonthsCount;
  642. returnValue = fShortMonths;
  643. break;
  644. case NARROW :
  645. count = fNarrowMonthsCount;
  646. returnValue = fNarrowMonths;
  647. break;
  648. case DT_WIDTH_COUNT :
  649. break;
  650. }
  651. break;
  652. case STANDALONE :
  653. switch(width) {
  654. case WIDE :
  655. count = fStandaloneMonthsCount;
  656. returnValue = fStandaloneMonths;
  657. break;
  658. case ABBREVIATED :
  659. case SHORT : // no month data for this, defaults to ABBREVIATED
  660. count = fStandaloneShortMonthsCount;
  661. returnValue = fStandaloneShortMonths;
  662. break;
  663. case NARROW :
  664. count = fStandaloneNarrowMonthsCount;
  665. returnValue = fStandaloneNarrowMonths;
  666. break;
  667. case DT_WIDTH_COUNT :
  668. break;
  669. }
  670. break;
  671. case DT_CONTEXT_COUNT :
  672. break;
  673. }
  674. return returnValue;
  675. }
  676. const UnicodeString*
  677. DateFormatSymbols::getWeekdays(int32_t &count) const
  678. {
  679. count = fWeekdaysCount;
  680. return fWeekdays;
  681. }
  682. const UnicodeString*
  683. DateFormatSymbols::getShortWeekdays(int32_t &count) const
  684. {
  685. count = fShortWeekdaysCount;
  686. return fShortWeekdays;
  687. }
  688. const UnicodeString*
  689. DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthType width) const
  690. {
  691. UnicodeString *returnValue = nullptr;
  692. switch (context) {
  693. case FORMAT :
  694. switch(width) {
  695. case WIDE :
  696. count = fWeekdaysCount;
  697. returnValue = fWeekdays;
  698. break;
  699. case ABBREVIATED :
  700. count = fShortWeekdaysCount;
  701. returnValue = fShortWeekdays;
  702. break;
  703. case SHORT :
  704. count = fShorterWeekdaysCount;
  705. returnValue = fShorterWeekdays;
  706. break;
  707. case NARROW :
  708. count = fNarrowWeekdaysCount;
  709. returnValue = fNarrowWeekdays;
  710. break;
  711. case DT_WIDTH_COUNT :
  712. break;
  713. }
  714. break;
  715. case STANDALONE :
  716. switch(width) {
  717. case WIDE :
  718. count = fStandaloneWeekdaysCount;
  719. returnValue = fStandaloneWeekdays;
  720. break;
  721. case ABBREVIATED :
  722. count = fStandaloneShortWeekdaysCount;
  723. returnValue = fStandaloneShortWeekdays;
  724. break;
  725. case SHORT :
  726. count = fStandaloneShorterWeekdaysCount;
  727. returnValue = fStandaloneShorterWeekdays;
  728. break;
  729. case NARROW :
  730. count = fStandaloneNarrowWeekdaysCount;
  731. returnValue = fStandaloneNarrowWeekdays;
  732. break;
  733. case DT_WIDTH_COUNT :
  734. break;
  735. }
  736. break;
  737. case DT_CONTEXT_COUNT :
  738. break;
  739. }
  740. return returnValue;
  741. }
  742. const UnicodeString*
  743. DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const
  744. {
  745. UnicodeString *returnValue = nullptr;
  746. switch (context) {
  747. case FORMAT :
  748. switch(width) {
  749. case WIDE :
  750. count = fQuartersCount;
  751. returnValue = fQuarters;
  752. break;
  753. case ABBREVIATED :
  754. case SHORT : // no quarter data for this, defaults to ABBREVIATED
  755. count = fShortQuartersCount;
  756. returnValue = fShortQuarters;
  757. break;
  758. case NARROW :
  759. count = fNarrowQuartersCount;
  760. returnValue = fNarrowQuarters;
  761. break;
  762. case DT_WIDTH_COUNT :
  763. break;
  764. }
  765. break;
  766. case STANDALONE :
  767. switch(width) {
  768. case WIDE :
  769. count = fStandaloneQuartersCount;
  770. returnValue = fStandaloneQuarters;
  771. break;
  772. case ABBREVIATED :
  773. case SHORT : // no quarter data for this, defaults to ABBREVIATED
  774. count = fStandaloneShortQuartersCount;
  775. returnValue = fStandaloneShortQuarters;
  776. break;
  777. case NARROW :
  778. count = fStandaloneNarrowQuartersCount;
  779. returnValue = fStandaloneNarrowQuarters;
  780. break;
  781. case DT_WIDTH_COUNT :
  782. break;
  783. }
  784. break;
  785. case DT_CONTEXT_COUNT :
  786. break;
  787. }
  788. return returnValue;
  789. }
  790. UnicodeString&
  791. DateFormatSymbols::getTimeSeparatorString(UnicodeString& result) const
  792. {
  793. // fastCopyFrom() - see assignArray comments
  794. return result.fastCopyFrom(fTimeSeparator);
  795. }
  796. const UnicodeString*
  797. DateFormatSymbols::getAmPmStrings(int32_t &count) const
  798. {
  799. count = fAmPmsCount;
  800. return fAmPms;
  801. }
  802. const UnicodeString*
  803. DateFormatSymbols::getLeapMonthPatterns(int32_t &count) const
  804. {
  805. count = fLeapMonthPatternsCount;
  806. return fLeapMonthPatterns;
  807. }
  808. const UnicodeString*
  809. DateFormatSymbols::getYearNames(int32_t& count,
  810. DtContextType /*ignored*/, DtWidthType /*ignored*/) const
  811. {
  812. count = fShortYearNamesCount;
  813. return fShortYearNames;
  814. }
  815. void
  816. DateFormatSymbols::setYearNames(const UnicodeString* yearNames, int32_t count,
  817. DtContextType context, DtWidthType width)
  818. {
  819. if (context == FORMAT && width == ABBREVIATED) {
  820. if (fShortYearNames) {
  821. delete[] fShortYearNames;
  822. }
  823. fShortYearNames = newUnicodeStringArray(count);
  824. uprv_arrayCopy(yearNames, fShortYearNames, count);
  825. fShortYearNamesCount = count;
  826. }
  827. }
  828. const UnicodeString*
  829. DateFormatSymbols::getZodiacNames(int32_t& count,
  830. DtContextType /*ignored*/, DtWidthType /*ignored*/) const
  831. {
  832. count = fShortZodiacNamesCount;
  833. return fShortZodiacNames;
  834. }
  835. void
  836. DateFormatSymbols::setZodiacNames(const UnicodeString* zodiacNames, int32_t count,
  837. DtContextType context, DtWidthType width)
  838. {
  839. if (context == FORMAT && width == ABBREVIATED) {
  840. if (fShortZodiacNames) {
  841. delete[] fShortZodiacNames;
  842. }
  843. fShortZodiacNames = newUnicodeStringArray(count);
  844. uprv_arrayCopy(zodiacNames, fShortZodiacNames, count);
  845. fShortZodiacNamesCount = count;
  846. }
  847. }
  848. //------------------------------------------------------
  849. void
  850. DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count)
  851. {
  852. // delete the old list if we own it
  853. if (fEras)
  854. delete[] fEras;
  855. // we always own the new list, which we create here (we duplicate rather
  856. // than adopting the list passed in)
  857. fEras = newUnicodeStringArray(count);
  858. uprv_arrayCopy(erasArray,fEras, count);
  859. fErasCount = count;
  860. }
  861. void
  862. DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count)
  863. {
  864. // delete the old list if we own it
  865. if (fEraNames)
  866. delete[] fEraNames;
  867. // we always own the new list, which we create here (we duplicate rather
  868. // than adopting the list passed in)
  869. fEraNames = newUnicodeStringArray(count);
  870. uprv_arrayCopy(eraNamesArray,fEraNames, count);
  871. fEraNamesCount = count;
  872. }
  873. void
  874. DateFormatSymbols::setNarrowEras(const UnicodeString* narrowErasArray, int32_t count)
  875. {
  876. // delete the old list if we own it
  877. if (fNarrowEras)
  878. delete[] fNarrowEras;
  879. // we always own the new list, which we create here (we duplicate rather
  880. // than adopting the list passed in)
  881. fNarrowEras = newUnicodeStringArray(count);
  882. uprv_arrayCopy(narrowErasArray,fNarrowEras, count);
  883. fNarrowErasCount = count;
  884. }
  885. void
  886. DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count)
  887. {
  888. // delete the old list if we own it
  889. if (fMonths)
  890. delete[] fMonths;
  891. // we always own the new list, which we create here (we duplicate rather
  892. // than adopting the list passed in)
  893. fMonths = newUnicodeStringArray(count);
  894. uprv_arrayCopy( monthsArray,fMonths,count);
  895. fMonthsCount = count;
  896. }
  897. void
  898. DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count)
  899. {
  900. // delete the old list if we own it
  901. if (fShortMonths)
  902. delete[] fShortMonths;
  903. // we always own the new list, which we create here (we duplicate rather
  904. // than adopting the list passed in)
  905. fShortMonths = newUnicodeStringArray(count);
  906. uprv_arrayCopy(shortMonthsArray,fShortMonths, count);
  907. fShortMonthsCount = count;
  908. }
  909. void
  910. DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, DtContextType context, DtWidthType width)
  911. {
  912. // delete the old list if we own it
  913. // we always own the new list, which we create here (we duplicate rather
  914. // than adopting the list passed in)
  915. switch (context) {
  916. case FORMAT :
  917. switch (width) {
  918. case WIDE :
  919. if (fMonths)
  920. delete[] fMonths;
  921. fMonths = newUnicodeStringArray(count);
  922. uprv_arrayCopy( monthsArray,fMonths,count);
  923. fMonthsCount = count;
  924. break;
  925. case ABBREVIATED :
  926. if (fShortMonths)
  927. delete[] fShortMonths;
  928. fShortMonths = newUnicodeStringArray(count);
  929. uprv_arrayCopy( monthsArray,fShortMonths,count);
  930. fShortMonthsCount = count;
  931. break;
  932. case NARROW :
  933. if (fNarrowMonths)
  934. delete[] fNarrowMonths;
  935. fNarrowMonths = newUnicodeStringArray(count);
  936. uprv_arrayCopy( monthsArray,fNarrowMonths,count);
  937. fNarrowMonthsCount = count;
  938. break;
  939. default :
  940. break;
  941. }
  942. break;
  943. case STANDALONE :
  944. switch (width) {
  945. case WIDE :
  946. if (fStandaloneMonths)
  947. delete[] fStandaloneMonths;
  948. fStandaloneMonths = newUnicodeStringArray(count);
  949. uprv_arrayCopy( monthsArray,fStandaloneMonths,count);
  950. fStandaloneMonthsCount = count;
  951. break;
  952. case ABBREVIATED :
  953. if (fStandaloneShortMonths)
  954. delete[] fStandaloneShortMonths;
  955. fStandaloneShortMonths = newUnicodeStringArray(count);
  956. uprv_arrayCopy( monthsArray,fStandaloneShortMonths,count);
  957. fStandaloneShortMonthsCount = count;
  958. break;
  959. case NARROW :
  960. if (fStandaloneNarrowMonths)
  961. delete[] fStandaloneNarrowMonths;
  962. fStandaloneNarrowMonths = newUnicodeStringArray(count);
  963. uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count);
  964. fStandaloneNarrowMonthsCount = count;
  965. break;
  966. default :
  967. break;
  968. }
  969. break;
  970. case DT_CONTEXT_COUNT :
  971. break;
  972. }
  973. }
  974. void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count)
  975. {
  976. // delete the old list if we own it
  977. if (fWeekdays)
  978. delete[] fWeekdays;
  979. // we always own the new list, which we create here (we duplicate rather
  980. // than adopting the list passed in)
  981. fWeekdays = newUnicodeStringArray(count);
  982. uprv_arrayCopy(weekdaysArray,fWeekdays,count);
  983. fWeekdaysCount = count;
  984. }
  985. void
  986. DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count)
  987. {
  988. // delete the old list if we own it
  989. if (fShortWeekdays)
  990. delete[] fShortWeekdays;
  991. // we always own the new list, which we create here (we duplicate rather
  992. // than adopting the list passed in)
  993. fShortWeekdays = newUnicodeStringArray(count);
  994. uprv_arrayCopy(shortWeekdaysArray, fShortWeekdays, count);
  995. fShortWeekdaysCount = count;
  996. }
  997. void
  998. DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count, DtContextType context, DtWidthType width)
  999. {
  1000. // delete the old list if we own it
  1001. // we always own the new list, which we create here (we duplicate rather
  1002. // than adopting the list passed in)
  1003. switch (context) {
  1004. case FORMAT :
  1005. switch (width) {
  1006. case WIDE :
  1007. if (fWeekdays)
  1008. delete[] fWeekdays;
  1009. fWeekdays = newUnicodeStringArray(count);
  1010. uprv_arrayCopy(weekdaysArray, fWeekdays, count);
  1011. fWeekdaysCount = count;
  1012. break;
  1013. case ABBREVIATED :
  1014. if (fShortWeekdays)
  1015. delete[] fShortWeekdays;
  1016. fShortWeekdays = newUnicodeStringArray(count);
  1017. uprv_arrayCopy(weekdaysArray, fShortWeekdays, count);
  1018. fShortWeekdaysCount = count;
  1019. break;
  1020. case SHORT :
  1021. if (fShorterWeekdays)
  1022. delete[] fShorterWeekdays;
  1023. fShorterWeekdays = newUnicodeStringArray(count);
  1024. uprv_arrayCopy(weekdaysArray, fShorterWeekdays, count);
  1025. fShorterWeekdaysCount = count;
  1026. break;
  1027. case NARROW :
  1028. if (fNarrowWeekdays)
  1029. delete[] fNarrowWeekdays;
  1030. fNarrowWeekdays = newUnicodeStringArray(count);
  1031. uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count);
  1032. fNarrowWeekdaysCount = count;
  1033. break;
  1034. case DT_WIDTH_COUNT :
  1035. break;
  1036. }
  1037. break;
  1038. case STANDALONE :
  1039. switch (width) {
  1040. case WIDE :
  1041. if (fStandaloneWeekdays)
  1042. delete[] fStandaloneWeekdays;
  1043. fStandaloneWeekdays = newUnicodeStringArray(count);
  1044. uprv_arrayCopy(weekdaysArray, fStandaloneWeekdays, count);
  1045. fStandaloneWeekdaysCount = count;
  1046. break;
  1047. case ABBREVIATED :
  1048. if (fStandaloneShortWeekdays)
  1049. delete[] fStandaloneShortWeekdays;
  1050. fStandaloneShortWeekdays = newUnicodeStringArray(count);
  1051. uprv_arrayCopy(weekdaysArray, fStandaloneShortWeekdays, count);
  1052. fStandaloneShortWeekdaysCount = count;
  1053. break;
  1054. case SHORT :
  1055. if (fStandaloneShorterWeekdays)
  1056. delete[] fStandaloneShorterWeekdays;
  1057. fStandaloneShorterWeekdays = newUnicodeStringArray(count);
  1058. uprv_arrayCopy(weekdaysArray, fStandaloneShorterWeekdays, count);
  1059. fStandaloneShorterWeekdaysCount = count;
  1060. break;
  1061. case NARROW :
  1062. if (fStandaloneNarrowWeekdays)
  1063. delete[] fStandaloneNarrowWeekdays;
  1064. fStandaloneNarrowWeekdays = newUnicodeStringArray(count);
  1065. uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count);
  1066. fStandaloneNarrowWeekdaysCount = count;
  1067. break;
  1068. case DT_WIDTH_COUNT :
  1069. break;
  1070. }
  1071. break;
  1072. case DT_CONTEXT_COUNT :
  1073. break;
  1074. }
  1075. }
  1076. void
  1077. DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count, DtContextType context, DtWidthType width)
  1078. {
  1079. // delete the old list if we own it
  1080. // we always own the new list, which we create here (we duplicate rather
  1081. // than adopting the list passed in)
  1082. switch (context) {
  1083. case FORMAT :
  1084. switch (width) {
  1085. case WIDE :
  1086. if (fQuarters)
  1087. delete[] fQuarters;
  1088. fQuarters = newUnicodeStringArray(count);
  1089. uprv_arrayCopy( quartersArray,fQuarters,count);
  1090. fQuartersCount = count;
  1091. break;
  1092. case ABBREVIATED :
  1093. if (fShortQuarters)
  1094. delete[] fShortQuarters;
  1095. fShortQuarters = newUnicodeStringArray(count);
  1096. uprv_arrayCopy( quartersArray,fShortQuarters,count);
  1097. fShortQuartersCount = count;
  1098. break;
  1099. case NARROW :
  1100. if (fNarrowQuarters)
  1101. delete[] fNarrowQuarters;
  1102. fNarrowQuarters = newUnicodeStringArray(count);
  1103. uprv_arrayCopy( quartersArray,fNarrowQuarters,count);
  1104. fNarrowQuartersCount = count;
  1105. break;
  1106. default :
  1107. break;
  1108. }
  1109. break;
  1110. case STANDALONE :
  1111. switch (width) {
  1112. case WIDE :
  1113. if (fStandaloneQuarters)
  1114. delete[] fStandaloneQuarters;
  1115. fStandaloneQuarters = newUnicodeStringArray(count);
  1116. uprv_arrayCopy( quartersArray,fStandaloneQuarters,count);
  1117. fStandaloneQuartersCount = count;
  1118. break;
  1119. case ABBREVIATED :
  1120. if (fStandaloneShortQuarters)
  1121. delete[] fStandaloneShortQuarters;
  1122. fStandaloneShortQuarters = newUnicodeStringArray(count);
  1123. uprv_arrayCopy( quartersArray,fStandaloneShortQuarters,count);
  1124. fStandaloneShortQuartersCount = count;
  1125. break;
  1126. case NARROW :
  1127. if (fStandaloneNarrowQuarters)
  1128. delete[] fStandaloneNarrowQuarters;
  1129. fStandaloneNarrowQuarters = newUnicodeStringArray(count);
  1130. uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count);
  1131. fStandaloneNarrowQuartersCount = count;
  1132. break;
  1133. default :
  1134. break;
  1135. }
  1136. break;
  1137. case DT_CONTEXT_COUNT :
  1138. break;
  1139. }
  1140. }
  1141. void
  1142. DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count)
  1143. {
  1144. // delete the old list if we own it
  1145. if (fAmPms) delete[] fAmPms;
  1146. // we always own the new list, which we create here (we duplicate rather
  1147. // than adopting the list passed in)
  1148. fAmPms = newUnicodeStringArray(count);
  1149. uprv_arrayCopy(amPmsArray,fAmPms,count);
  1150. fAmPmsCount = count;
  1151. }
  1152. void
  1153. DateFormatSymbols::setTimeSeparatorString(const UnicodeString& newTimeSeparator)
  1154. {
  1155. fTimeSeparator = newTimeSeparator;
  1156. }
  1157. const UnicodeString**
  1158. DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
  1159. {
  1160. const UnicodeString **result = nullptr;
  1161. static UMutex LOCK;
  1162. umtx_lock(&LOCK);
  1163. if (fZoneStrings == nullptr) {
  1164. if (fLocaleZoneStrings == nullptr) {
  1165. ((DateFormatSymbols*)this)->initZoneStringsArray();
  1166. }
  1167. result = (const UnicodeString**)fLocaleZoneStrings;
  1168. } else {
  1169. result = (const UnicodeString**)fZoneStrings;
  1170. }
  1171. rowCount = fZoneStringsRowCount;
  1172. columnCount = fZoneStringsColCount;
  1173. umtx_unlock(&LOCK);
  1174. return result;
  1175. }
  1176. // For now, we include all zones
  1177. #define ZONE_SET UCAL_ZONE_TYPE_ANY
  1178. // This code must be called within a synchronized block
  1179. void
  1180. DateFormatSymbols::initZoneStringsArray() {
  1181. if (fZoneStrings != nullptr || fLocaleZoneStrings != nullptr) {
  1182. return;
  1183. }
  1184. UErrorCode status = U_ZERO_ERROR;
  1185. StringEnumeration *tzids = nullptr;
  1186. UnicodeString ** zarray = nullptr;
  1187. TimeZoneNames *tzNames = nullptr;
  1188. int32_t rows = 0;
  1189. static const UTimeZoneNameType TYPES[] = {
  1190. UTZNM_LONG_STANDARD, UTZNM_SHORT_STANDARD,
  1191. UTZNM_LONG_DAYLIGHT, UTZNM_SHORT_DAYLIGHT
  1192. };
  1193. static const int32_t NUM_TYPES = 4;
  1194. do { // dummy do-while
  1195. tzids = TimeZone::createTimeZoneIDEnumeration(ZONE_SET, nullptr, nullptr, status);
  1196. rows = tzids->count(status);
  1197. if (U_FAILURE(status)) {
  1198. break;
  1199. }
  1200. // Allocate array
  1201. int32_t size = rows * sizeof(UnicodeString*);
  1202. zarray = (UnicodeString**)uprv_malloc(size);
  1203. if (zarray == nullptr) {
  1204. status = U_MEMORY_ALLOCATION_ERROR;
  1205. break;
  1206. }
  1207. uprv_memset(zarray, 0, size);
  1208. tzNames = TimeZoneNames::createInstance(fZSFLocale, status);
  1209. tzNames->loadAllDisplayNames(status);
  1210. if (U_FAILURE(status)) { break; }
  1211. const UnicodeString *tzid;
  1212. int32_t i = 0;
  1213. UDate now = Calendar::getNow();
  1214. UnicodeString tzDispName;
  1215. while ((tzid = tzids->snext(status)) != 0) {
  1216. if (U_FAILURE(status)) {
  1217. break;
  1218. }
  1219. zarray[i] = new UnicodeString[5];
  1220. if (zarray[i] == nullptr) {
  1221. status = U_MEMORY_ALLOCATION_ERROR;
  1222. break;
  1223. }
  1224. zarray[i][0].setTo(*tzid);
  1225. tzNames->getDisplayNames(*tzid, TYPES, NUM_TYPES, now, zarray[i]+1, status);
  1226. i++;
  1227. }
  1228. } while (false);
  1229. if (U_FAILURE(status)) {
  1230. if (zarray) {
  1231. for (int32_t i = 0; i < rows; i++) {
  1232. if (zarray[i]) {
  1233. delete[] zarray[i];
  1234. }
  1235. }
  1236. uprv_free(zarray);
  1237. zarray = nullptr;
  1238. }
  1239. }
  1240. if (tzNames) {
  1241. delete tzNames;
  1242. }
  1243. if (tzids) {
  1244. delete tzids;
  1245. }
  1246. fLocaleZoneStrings = zarray;
  1247. fZoneStringsRowCount = rows;
  1248. fZoneStringsColCount = 1 + NUM_TYPES;
  1249. }
  1250. void
  1251. DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t rowCount, int32_t columnCount)
  1252. {
  1253. // since deleting a 2-d array is a pain in the butt, we offload that task to
  1254. // a separate function
  1255. disposeZoneStrings();
  1256. // we always own the new list, which we create here (we duplicate rather
  1257. // than adopting the list passed in)
  1258. fZoneStringsRowCount = rowCount;
  1259. fZoneStringsColCount = columnCount;
  1260. createZoneStrings((const UnicodeString**)strings);
  1261. }
  1262. //------------------------------------------------------
  1263. const char16_t * U_EXPORT2
  1264. DateFormatSymbols::getPatternUChars()
  1265. {
  1266. return gPatternChars;
  1267. }
  1268. UDateFormatField U_EXPORT2
  1269. DateFormatSymbols::getPatternCharIndex(char16_t c) {
  1270. const char16_t *p = u_strchr(gPatternChars, c);
  1271. if (p == nullptr) {
  1272. return UDAT_FIELD_COUNT;
  1273. } else {
  1274. return static_cast<UDateFormatField>(p - gPatternChars);
  1275. }
  1276. }
  1277. static const uint64_t kNumericFieldsAlways =
  1278. ((uint64_t)1 << UDAT_YEAR_FIELD) | // y
  1279. ((uint64_t)1 << UDAT_DATE_FIELD) | // d
  1280. ((uint64_t)1 << UDAT_HOUR_OF_DAY1_FIELD) | // k
  1281. ((uint64_t)1 << UDAT_HOUR_OF_DAY0_FIELD) | // H
  1282. ((uint64_t)1 << UDAT_MINUTE_FIELD) | // m
  1283. ((uint64_t)1 << UDAT_SECOND_FIELD) | // s
  1284. ((uint64_t)1 << UDAT_FRACTIONAL_SECOND_FIELD) | // S
  1285. ((uint64_t)1 << UDAT_DAY_OF_YEAR_FIELD) | // D
  1286. ((uint64_t)1 << UDAT_DAY_OF_WEEK_IN_MONTH_FIELD) | // F
  1287. ((uint64_t)1 << UDAT_WEEK_OF_YEAR_FIELD) | // w
  1288. ((uint64_t)1 << UDAT_WEEK_OF_MONTH_FIELD) | // W
  1289. ((uint64_t)1 << UDAT_HOUR1_FIELD) | // h
  1290. ((uint64_t)1 << UDAT_HOUR0_FIELD) | // K
  1291. ((uint64_t)1 << UDAT_YEAR_WOY_FIELD) | // Y
  1292. ((uint64_t)1 << UDAT_EXTENDED_YEAR_FIELD) | // u
  1293. ((uint64_t)1 << UDAT_JULIAN_DAY_FIELD) | // g
  1294. ((uint64_t)1 << UDAT_MILLISECONDS_IN_DAY_FIELD) | // A
  1295. ((uint64_t)1 << UDAT_RELATED_YEAR_FIELD); // r
  1296. static const uint64_t kNumericFieldsForCount12 =
  1297. ((uint64_t)1 << UDAT_MONTH_FIELD) | // M or MM
  1298. ((uint64_t)1 << UDAT_DOW_LOCAL_FIELD) | // e or ee
  1299. ((uint64_t)1 << UDAT_STANDALONE_DAY_FIELD) | // c or cc
  1300. ((uint64_t)1 << UDAT_STANDALONE_MONTH_FIELD) | // L or LL
  1301. ((uint64_t)1 << UDAT_QUARTER_FIELD) | // Q or QQ
  1302. ((uint64_t)1 << UDAT_STANDALONE_QUARTER_FIELD); // q or qq
  1303. UBool U_EXPORT2
  1304. DateFormatSymbols::isNumericField(UDateFormatField f, int32_t count) {
  1305. if (f == UDAT_FIELD_COUNT) {
  1306. return false;
  1307. }
  1308. uint64_t flag = ((uint64_t)1 << f);
  1309. return ((kNumericFieldsAlways & flag) != 0 || ((kNumericFieldsForCount12 & flag) != 0 && count < 3));
  1310. }
  1311. UBool U_EXPORT2
  1312. DateFormatSymbols::isNumericPatternChar(char16_t c, int32_t count) {
  1313. return isNumericField(getPatternCharIndex(c), count);
  1314. }
  1315. //------------------------------------------------------
  1316. UnicodeString&
  1317. DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
  1318. {
  1319. // fastCopyFrom() - see assignArray comments
  1320. return result.fastCopyFrom(fLocalPatternChars);
  1321. }
  1322. //------------------------------------------------------
  1323. void
  1324. DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
  1325. {
  1326. fLocalPatternChars = newLocalPatternChars;
  1327. }
  1328. //------------------------------------------------------
  1329. namespace {
  1330. // Constants declarations
  1331. static const char16_t kCalendarAliasPrefixUChar[] = {
  1332. SOLIDUS, CAP_L, CAP_O, CAP_C, CAP_A, CAP_L, CAP_E, SOLIDUS,
  1333. LOW_C, LOW_A, LOW_L, LOW_E, LOW_N, LOW_D, LOW_A, LOW_R, SOLIDUS
  1334. };
  1335. static const char16_t kGregorianTagUChar[] = {
  1336. LOW_G, LOW_R, LOW_E, LOW_G, LOW_O, LOW_R, LOW_I, LOW_A, LOW_N
  1337. };
  1338. static const char16_t kVariantTagUChar[] = {
  1339. PERCENT, LOW_V, LOW_A, LOW_R, LOW_I, LOW_A, LOW_N, LOW_T
  1340. };
  1341. static const char16_t kLeapTagUChar[] = {
  1342. LOW_L, LOW_E, LOW_A, LOW_P
  1343. };
  1344. static const char16_t kCyclicNameSetsTagUChar[] = {
  1345. LOW_C, LOW_Y, LOW_C, LOW_L, LOW_I, LOW_C, CAP_N, LOW_A, LOW_M, LOW_E, CAP_S, LOW_E, LOW_T, LOW_S
  1346. };
  1347. static const char16_t kYearsTagUChar[] = {
  1348. SOLIDUS, LOW_Y, LOW_E, LOW_A, LOW_R, LOW_S
  1349. };
  1350. static const char16_t kZodiacsUChar[] = {
  1351. SOLIDUS, LOW_Z, LOW_O, LOW_D, LOW_I, LOW_A, LOW_C, LOW_S
  1352. };
  1353. static const char16_t kDayPartsTagUChar[] = {
  1354. SOLIDUS, LOW_D, LOW_A, LOW_Y, CAP_P, LOW_A, LOW_R, LOW_T, LOW_S
  1355. };
  1356. static const char16_t kFormatTagUChar[] = {
  1357. SOLIDUS, LOW_F, LOW_O, LOW_R, LOW_M, LOW_A, LOW_T
  1358. };
  1359. static const char16_t kAbbrTagUChar[] = {
  1360. SOLIDUS, LOW_A, LOW_B, LOW_B, LOW_R, LOW_E, LOW_V, LOW_I, LOW_A, LOW_T, LOW_E, LOW_D
  1361. };
  1362. // ResourceSink to enumerate all calendar resources
  1363. struct CalendarDataSink : public ResourceSink {
  1364. // Enum which specifies the type of alias received, or no alias
  1365. enum AliasType {
  1366. SAME_CALENDAR,
  1367. DIFFERENT_CALENDAR,
  1368. GREGORIAN,
  1369. NONE
  1370. };
  1371. // Data structures to store resources from the current resource bundle
  1372. Hashtable arrays;
  1373. Hashtable arraySizes;
  1374. Hashtable maps;
  1375. /**
  1376. * Whenever there are aliases, the same object will be added twice to 'map'.
  1377. * To avoid double deletion, 'maps' won't take ownership of the objects. Instead,
  1378. * 'mapRefs' will own them and will delete them when CalendarDataSink is deleted.
  1379. */
  1380. MemoryPool<Hashtable> mapRefs;
  1381. // Paths and the aliases they point to
  1382. UVector aliasPathPairs;
  1383. // Current and next calendar resource table which should be loaded
  1384. UnicodeString currentCalendarType;
  1385. UnicodeString nextCalendarType;
  1386. // Resources to visit when enumerating fallback calendars
  1387. LocalPointer<UVector> resourcesToVisit;
  1388. // Alias' relative path populated whenever an alias is read
  1389. UnicodeString aliasRelativePath;
  1390. // Initializes CalendarDataSink with default values
  1391. CalendarDataSink(UErrorCode& status)
  1392. : arrays(false, status), arraySizes(false, status), maps(false, status),
  1393. mapRefs(),
  1394. aliasPathPairs(uprv_deleteUObject, uhash_compareUnicodeString, status),
  1395. currentCalendarType(), nextCalendarType(),
  1396. resourcesToVisit(nullptr), aliasRelativePath() {
  1397. if (U_FAILURE(status)) { return; }
  1398. }
  1399. virtual ~CalendarDataSink();
  1400. // Configure the CalendarSink to visit all the resources
  1401. void visitAllResources() {
  1402. resourcesToVisit.adoptInstead(nullptr);
  1403. }
  1404. // Actions to be done before enumerating
  1405. void preEnumerate(const UnicodeString &calendarType) {
  1406. currentCalendarType = calendarType;
  1407. nextCalendarType.setToBogus();
  1408. aliasPathPairs.removeAllElements();
  1409. }
  1410. virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) override {
  1411. if (U_FAILURE(errorCode)) { return; }
  1412. U_ASSERT(!currentCalendarType.isEmpty());
  1413. // Stores the resources to visit on the next calendar.
  1414. LocalPointer<UVector> resourcesToVisitNext(nullptr);
  1415. ResourceTable calendarData = value.getTable(errorCode);
  1416. if (U_FAILURE(errorCode)) { return; }
  1417. // Enumerate all resources for this calendar
  1418. for (int i = 0; calendarData.getKeyAndValue(i, key, value); i++) {
  1419. UnicodeString keyUString(key, -1, US_INV);
  1420. // == Handle aliases ==
  1421. AliasType aliasType = processAliasFromValue(keyUString, value, errorCode);
  1422. if (U_FAILURE(errorCode)) { return; }
  1423. if (aliasType == GREGORIAN) {
  1424. // Ignore aliases to the gregorian calendar, all of its resources will be loaded anyway.
  1425. continue;
  1426. } else if (aliasType == DIFFERENT_CALENDAR) {
  1427. // Whenever an alias to the next calendar (except gregorian) is encountered, register the
  1428. // calendar type it's pointing to
  1429. if (resourcesToVisitNext.isNull()) {
  1430. resourcesToVisitNext
  1431. .adoptInsteadAndCheckErrorCode(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, errorCode),
  1432. errorCode);
  1433. if (U_FAILURE(errorCode)) { return; }
  1434. }
  1435. LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode);
  1436. resourcesToVisitNext->adoptElement(aliasRelativePathCopy.orphan(), errorCode);
  1437. if (U_FAILURE(errorCode)) { return; }
  1438. continue;
  1439. } else if (aliasType == SAME_CALENDAR) {
  1440. // Register same-calendar alias
  1441. if (arrays.get(aliasRelativePath) == nullptr && maps.get(aliasRelativePath) == nullptr) {
  1442. LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode);
  1443. aliasPathPairs.adoptElement(aliasRelativePathCopy.orphan(), errorCode);
  1444. if (U_FAILURE(errorCode)) { return; }
  1445. LocalPointer<UnicodeString> keyUStringCopy(keyUString.clone(), errorCode);
  1446. aliasPathPairs.adoptElement(keyUStringCopy.orphan(), errorCode);
  1447. if (U_FAILURE(errorCode)) { return; }
  1448. }
  1449. continue;
  1450. }
  1451. // Only visit the resources that were referenced by an alias on the previous calendar
  1452. // (AmPmMarkersAbbr is an exception).
  1453. if (!resourcesToVisit.isNull() && !resourcesToVisit->isEmpty() && !resourcesToVisit->contains(&keyUString)
  1454. && uprv_strcmp(key, gAmPmMarkersAbbrTag) != 0) { continue; }
  1455. // == Handle data ==
  1456. if (uprv_strcmp(key, gAmPmMarkersTag) == 0
  1457. || uprv_strcmp(key, gAmPmMarkersAbbrTag) == 0
  1458. || uprv_strcmp(key, gAmPmMarkersNarrowTag) == 0) {
  1459. if (arrays.get(keyUString) == nullptr) {
  1460. ResourceArray resourceArray = value.getArray(errorCode);
  1461. int32_t arraySize = resourceArray.getSize();
  1462. LocalArray<UnicodeString> stringArray(new UnicodeString[arraySize], errorCode);
  1463. value.getStringArray(stringArray.getAlias(), arraySize, errorCode);
  1464. arrays.put(keyUString, stringArray.orphan(), errorCode);
  1465. arraySizes.puti(keyUString, arraySize, errorCode);
  1466. if (U_FAILURE(errorCode)) { return; }
  1467. }
  1468. } else if (uprv_strcmp(key, gErasTag) == 0
  1469. || uprv_strcmp(key, gDayNamesTag) == 0
  1470. || uprv_strcmp(key, gMonthNamesTag) == 0
  1471. || uprv_strcmp(key, gQuartersTag) == 0
  1472. || uprv_strcmp(key, gDayPeriodTag) == 0
  1473. || uprv_strcmp(key, gMonthPatternsTag) == 0
  1474. || uprv_strcmp(key, gCyclicNameSetsTag) == 0) {
  1475. processResource(keyUString, key, value, errorCode);
  1476. }
  1477. }
  1478. // Apply same-calendar aliases
  1479. UBool modified;
  1480. do {
  1481. modified = false;
  1482. for (int32_t i = 0; i < aliasPathPairs.size();) {
  1483. UBool mod = false;
  1484. UnicodeString *alias = (UnicodeString*)aliasPathPairs[i];
  1485. UnicodeString *aliasArray;
  1486. Hashtable *aliasMap;
  1487. if ((aliasArray = (UnicodeString*)arrays.get(*alias)) != nullptr) {
  1488. UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
  1489. if (arrays.get(*path) == nullptr) {
  1490. // Clone the array
  1491. int32_t aliasArraySize = arraySizes.geti(*alias);
  1492. LocalArray<UnicodeString> aliasArrayCopy(new UnicodeString[aliasArraySize], errorCode);
  1493. if (U_FAILURE(errorCode)) { return; }
  1494. uprv_arrayCopy(aliasArray, aliasArrayCopy.getAlias(), aliasArraySize);
  1495. // Put the array on the 'arrays' map
  1496. arrays.put(*path, aliasArrayCopy.orphan(), errorCode);
  1497. arraySizes.puti(*path, aliasArraySize, errorCode);
  1498. }
  1499. if (U_FAILURE(errorCode)) { return; }
  1500. mod = true;
  1501. } else if ((aliasMap = (Hashtable*)maps.get(*alias)) != nullptr) {
  1502. UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
  1503. if (maps.get(*path) == nullptr) {
  1504. maps.put(*path, aliasMap, errorCode);
  1505. }
  1506. if (U_FAILURE(errorCode)) { return; }
  1507. mod = true;
  1508. }
  1509. if (mod) {
  1510. aliasPathPairs.removeElementAt(i + 1);
  1511. aliasPathPairs.removeElementAt(i);
  1512. modified = true;
  1513. } else {
  1514. i += 2;
  1515. }
  1516. }
  1517. } while (modified && !aliasPathPairs.isEmpty());
  1518. // Set the resources to visit on the next calendar
  1519. if (!resourcesToVisitNext.isNull()) {
  1520. resourcesToVisit = std::move(resourcesToVisitNext);
  1521. }
  1522. }
  1523. // Process the nested resource bundle tables
  1524. void processResource(UnicodeString &path, const char *key, ResourceValue &value, UErrorCode &errorCode) {
  1525. if (U_FAILURE(errorCode)) return;
  1526. ResourceTable table = value.getTable(errorCode);
  1527. if (U_FAILURE(errorCode)) return;
  1528. Hashtable* stringMap = nullptr;
  1529. // Iterate over all the elements of the table and add them to the map
  1530. for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
  1531. UnicodeString keyUString(key, -1, US_INV);
  1532. // Ignore '%variant' keys
  1533. if (keyUString.endsWith(kVariantTagUChar, UPRV_LENGTHOF(kVariantTagUChar))) {
  1534. continue;
  1535. }
  1536. // == Handle String elements ==
  1537. if (value.getType() == URES_STRING) {
  1538. // We are on a leaf, store the map elements into the stringMap
  1539. if (i == 0) {
  1540. // mapRefs will keep ownership of 'stringMap':
  1541. stringMap = mapRefs.create(false, errorCode);
  1542. if (stringMap == nullptr) {
  1543. errorCode = U_MEMORY_ALLOCATION_ERROR;
  1544. return;
  1545. }
  1546. maps.put(path, stringMap, errorCode);
  1547. if (U_FAILURE(errorCode)) { return; }
  1548. stringMap->setValueDeleter(uprv_deleteUObject);
  1549. }
  1550. U_ASSERT(stringMap != nullptr);
  1551. int32_t valueStringSize;
  1552. const char16_t *valueString = value.getString(valueStringSize, errorCode);
  1553. if (U_FAILURE(errorCode)) { return; }
  1554. LocalPointer<UnicodeString> valueUString(new UnicodeString(true, valueString, valueStringSize), errorCode);
  1555. stringMap->put(keyUString, valueUString.orphan(), errorCode);
  1556. if (U_FAILURE(errorCode)) { return; }
  1557. continue;
  1558. }
  1559. U_ASSERT(stringMap == nullptr);
  1560. // Store the current path's length and append the current key to the path.
  1561. int32_t pathLength = path.length();
  1562. path.append(SOLIDUS).append(keyUString);
  1563. // In cyclicNameSets ignore everything but years/format/abbreviated
  1564. // and zodiacs/format/abbreviated
  1565. if (path.startsWith(kCyclicNameSetsTagUChar, UPRV_LENGTHOF(kCyclicNameSetsTagUChar))) {
  1566. UBool skip = true;
  1567. int32_t startIndex = UPRV_LENGTHOF(kCyclicNameSetsTagUChar);
  1568. int32_t length = 0;
  1569. if (startIndex == path.length()
  1570. || path.compare(startIndex, (length = UPRV_LENGTHOF(kZodiacsUChar)), kZodiacsUChar, 0, UPRV_LENGTHOF(kZodiacsUChar)) == 0
  1571. || path.compare(startIndex, (length = UPRV_LENGTHOF(kYearsTagUChar)), kYearsTagUChar, 0, UPRV_LENGTHOF(kYearsTagUChar)) == 0
  1572. || path.compare(startIndex, (length = UPRV_LENGTHOF(kDayPartsTagUChar)), kDayPartsTagUChar, 0, UPRV_LENGTHOF(kDayPartsTagUChar)) == 0) {
  1573. startIndex += length;
  1574. length = 0;
  1575. if (startIndex == path.length()
  1576. || path.compare(startIndex, (length = UPRV_LENGTHOF(kFormatTagUChar)), kFormatTagUChar, 0, UPRV_LENGTHOF(kFormatTagUChar)) == 0) {
  1577. startIndex += length;
  1578. length = 0;
  1579. if (startIndex == path.length()
  1580. || path.compare(startIndex, (length = UPRV_LENGTHOF(kAbbrTagUChar)), kAbbrTagUChar, 0, UPRV_LENGTHOF(kAbbrTagUChar)) == 0) {
  1581. skip = false;
  1582. }
  1583. }
  1584. }
  1585. if (skip) {
  1586. // Drop the latest key on the path and continue
  1587. path.retainBetween(0, pathLength);
  1588. continue;
  1589. }
  1590. }
  1591. // == Handle aliases ==
  1592. if (arrays.get(path) != nullptr || maps.get(path) != nullptr) {
  1593. // Drop the latest key on the path and continue
  1594. path.retainBetween(0, pathLength);
  1595. continue;
  1596. }
  1597. AliasType aliasType = processAliasFromValue(path, value, errorCode);
  1598. if (U_FAILURE(errorCode)) { return; }
  1599. if (aliasType == SAME_CALENDAR) {
  1600. // Store the alias path and the current path on aliasPathPairs
  1601. LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode);
  1602. aliasPathPairs.adoptElement(aliasRelativePathCopy.orphan(), errorCode);
  1603. if (U_FAILURE(errorCode)) { return; }
  1604. LocalPointer<UnicodeString> pathCopy(path.clone(), errorCode);
  1605. aliasPathPairs.adoptElement(pathCopy.orphan(), errorCode);
  1606. if (U_FAILURE(errorCode)) { return; }
  1607. // Drop the latest key on the path and continue
  1608. path.retainBetween(0, pathLength);
  1609. continue;
  1610. }
  1611. U_ASSERT(aliasType == NONE);
  1612. // == Handle data ==
  1613. if (value.getType() == URES_ARRAY) {
  1614. // We are on a leaf, store the array
  1615. ResourceArray rDataArray = value.getArray(errorCode);
  1616. int32_t dataArraySize = rDataArray.getSize();
  1617. LocalArray<UnicodeString> dataArray(new UnicodeString[dataArraySize], errorCode);
  1618. value.getStringArray(dataArray.getAlias(), dataArraySize, errorCode);
  1619. arrays.put(path, dataArray.orphan(), errorCode);
  1620. arraySizes.puti(path, dataArraySize, errorCode);
  1621. if (U_FAILURE(errorCode)) { return; }
  1622. } else if (value.getType() == URES_TABLE) {
  1623. // We are not on a leaf, recursively process the subtable.
  1624. processResource(path, key, value, errorCode);
  1625. if (U_FAILURE(errorCode)) { return; }
  1626. }
  1627. // Drop the latest key on the path
  1628. path.retainBetween(0, pathLength);
  1629. }
  1630. }
  1631. // Populates an AliasIdentifier with the alias information contained on the UResource.Value.
  1632. AliasType processAliasFromValue(UnicodeString &currentRelativePath, ResourceValue &value,
  1633. UErrorCode &errorCode) {
  1634. if (U_FAILURE(errorCode)) { return NONE; }
  1635. if (value.getType() == URES_ALIAS) {
  1636. int32_t aliasPathSize;
  1637. const char16_t* aliasPathUChar = value.getAliasString(aliasPathSize, errorCode);
  1638. if (U_FAILURE(errorCode)) { return NONE; }
  1639. UnicodeString aliasPath(aliasPathUChar, aliasPathSize);
  1640. const int32_t aliasPrefixLength = UPRV_LENGTHOF(kCalendarAliasPrefixUChar);
  1641. if (aliasPath.startsWith(kCalendarAliasPrefixUChar, aliasPrefixLength)
  1642. && aliasPath.length() > aliasPrefixLength) {
  1643. int32_t typeLimit = aliasPath.indexOf(SOLIDUS, aliasPrefixLength);
  1644. if (typeLimit > aliasPrefixLength) {
  1645. const UnicodeString aliasCalendarType =
  1646. aliasPath.tempSubStringBetween(aliasPrefixLength, typeLimit);
  1647. aliasRelativePath.setTo(aliasPath, typeLimit + 1, aliasPath.length());
  1648. if (currentCalendarType == aliasCalendarType
  1649. && currentRelativePath != aliasRelativePath) {
  1650. // If we have an alias to the same calendar, the path to the resource must be different
  1651. return SAME_CALENDAR;
  1652. } else if (currentCalendarType != aliasCalendarType
  1653. && currentRelativePath == aliasRelativePath) {
  1654. // If we have an alias to a different calendar, the path to the resource must be the same
  1655. if (aliasCalendarType.compare(kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar)) == 0) {
  1656. return GREGORIAN;
  1657. } else if (nextCalendarType.isBogus()) {
  1658. nextCalendarType = aliasCalendarType;
  1659. return DIFFERENT_CALENDAR;
  1660. } else if (nextCalendarType == aliasCalendarType) {
  1661. return DIFFERENT_CALENDAR;
  1662. }
  1663. }
  1664. }
  1665. }
  1666. errorCode = U_INTERNAL_PROGRAM_ERROR;
  1667. return NONE;
  1668. }
  1669. return NONE;
  1670. }
  1671. // Deleter function to be used by 'arrays'
  1672. static void U_CALLCONV deleteUnicodeStringArray(void *uArray) {
  1673. delete[] static_cast<UnicodeString *>(uArray);
  1674. }
  1675. };
  1676. // Virtual destructors have to be defined out of line
  1677. CalendarDataSink::~CalendarDataSink() {
  1678. arrays.setValueDeleter(deleteUnicodeStringArray);
  1679. }
  1680. }
  1681. //------------------------------------------------------
  1682. static void
  1683. initField(UnicodeString **field, int32_t& length, const char16_t *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
  1684. if (U_SUCCESS(status)) {
  1685. length = numStr;
  1686. *field = newUnicodeStringArray((size_t)numStr);
  1687. if (*field) {
  1688. for(int32_t i = 0; i<length; i++) {
  1689. // readonly aliases - all "data" strings are constant
  1690. // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
  1691. (*(field)+i)->setTo(true, data+(i*((int32_t)strLen)), -1);
  1692. }
  1693. }
  1694. else {
  1695. length = 0;
  1696. status = U_MEMORY_ALLOCATION_ERROR;
  1697. }
  1698. }
  1699. }
  1700. static void
  1701. initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, UErrorCode &status) {
  1702. if (U_SUCCESS(status)) {
  1703. UnicodeString keyUString(key.data(), -1, US_INV);
  1704. UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
  1705. if (array != nullptr) {
  1706. length = sink.arraySizes.geti(keyUString);
  1707. *field = array;
  1708. // DateFormatSymbols takes ownership of the array:
  1709. sink.arrays.remove(keyUString);
  1710. } else {
  1711. length = 0;
  1712. status = U_MISSING_RESOURCE_ERROR;
  1713. }
  1714. }
  1715. }
  1716. static void
  1717. initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, int32_t arrayOffset, UErrorCode &status) {
  1718. if (U_SUCCESS(status)) {
  1719. UnicodeString keyUString(key.data(), -1, US_INV);
  1720. UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
  1721. if (array != nullptr) {
  1722. int32_t arrayLength = sink.arraySizes.geti(keyUString);
  1723. length = arrayLength + arrayOffset;
  1724. *field = new UnicodeString[length];
  1725. if (*field == nullptr) {
  1726. status = U_MEMORY_ALLOCATION_ERROR;
  1727. return;
  1728. }
  1729. uprv_arrayCopy(array, 0, *field, arrayOffset, arrayLength);
  1730. } else {
  1731. length = 0;
  1732. status = U_MISSING_RESOURCE_ERROR;
  1733. }
  1734. }
  1735. }
  1736. static void
  1737. initLeapMonthPattern(UnicodeString *field, int32_t index, CalendarDataSink &sink, CharString &path, UErrorCode &status) {
  1738. field[index].remove();
  1739. if (U_SUCCESS(status)) {
  1740. UnicodeString pathUString(path.data(), -1, US_INV);
  1741. Hashtable *leapMonthTable = static_cast<Hashtable*>(sink.maps.get(pathUString));
  1742. if (leapMonthTable != nullptr) {
  1743. UnicodeString leapLabel(false, kLeapTagUChar, UPRV_LENGTHOF(kLeapTagUChar));
  1744. UnicodeString *leapMonthPattern = static_cast<UnicodeString*>(leapMonthTable->get(leapLabel));
  1745. if (leapMonthPattern != nullptr) {
  1746. field[index].fastCopyFrom(*leapMonthPattern);
  1747. } else {
  1748. field[index].setToBogus();
  1749. }
  1750. return;
  1751. }
  1752. status = U_MISSING_RESOURCE_ERROR;
  1753. }
  1754. }
  1755. static CharString
  1756. &buildResourcePath(CharString &path, const char* segment1, UErrorCode &errorCode) {
  1757. return path.clear().append(segment1, -1, errorCode);
  1758. }
  1759. static CharString
  1760. &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
  1761. UErrorCode &errorCode) {
  1762. return buildResourcePath(path, segment1, errorCode).append('/', errorCode)
  1763. .append(segment2, -1, errorCode);
  1764. }
  1765. static CharString
  1766. &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
  1767. const char* segment3, UErrorCode &errorCode) {
  1768. return buildResourcePath(path, segment1, segment2, errorCode).append('/', errorCode)
  1769. .append(segment3, -1, errorCode);
  1770. }
  1771. static CharString
  1772. &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
  1773. const char* segment3, const char* segment4, UErrorCode &errorCode) {
  1774. return buildResourcePath(path, segment1, segment2, segment3, errorCode).append('/', errorCode)
  1775. .append(segment4, -1, errorCode);
  1776. }
  1777. typedef struct {
  1778. const char * usageTypeName;
  1779. DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
  1780. } ContextUsageTypeNameToEnumValue;
  1781. static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
  1782. // Entries must be sorted by usageTypeName; entry with nullptr name terminates list.
  1783. { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
  1784. { "day-narrow", DateFormatSymbols::kCapContextUsageDayNarrow },
  1785. { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
  1786. { "era-abbr", DateFormatSymbols::kCapContextUsageEraAbbrev },
  1787. { "era-name", DateFormatSymbols::kCapContextUsageEraWide },
  1788. { "era-narrow", DateFormatSymbols::kCapContextUsageEraNarrow },
  1789. { "metazone-long", DateFormatSymbols::kCapContextUsageMetazoneLong },
  1790. { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
  1791. { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
  1792. { "month-narrow", DateFormatSymbols::kCapContextUsageMonthNarrow },
  1793. { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
  1794. { "zone-long", DateFormatSymbols::kCapContextUsageZoneLong },
  1795. { "zone-short", DateFormatSymbols::kCapContextUsageZoneShort },
  1796. { nullptr, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
  1797. };
  1798. // Resource keys to look up localized strings for day periods.
  1799. // The first one must be midnight and the second must be noon, so that their indices coincide
  1800. // with the am/pm field. Formatting and parsing code for day periods relies on this coincidence.
  1801. static const char *dayPeriodKeys[] = {"midnight", "noon",
  1802. "morning1", "afternoon1", "evening1", "night1",
  1803. "morning2", "afternoon2", "evening2", "night2"};
  1804. UnicodeString* loadDayPeriodStrings(CalendarDataSink &sink, CharString &path,
  1805. int32_t &stringCount, UErrorCode &status) {
  1806. if (U_FAILURE(status)) { return nullptr; }
  1807. UnicodeString pathUString(path.data(), -1, US_INV);
  1808. Hashtable* map = static_cast<Hashtable*>(sink.maps.get(pathUString));
  1809. stringCount = UPRV_LENGTHOF(dayPeriodKeys);
  1810. UnicodeString *strings = new UnicodeString[stringCount];
  1811. if (strings == nullptr) {
  1812. status = U_MEMORY_ALLOCATION_ERROR;
  1813. return nullptr;
  1814. }
  1815. if (map != nullptr) {
  1816. for (int32_t i = 0; i < stringCount; ++i) {
  1817. UnicodeString dayPeriodKey(dayPeriodKeys[i], -1, US_INV);
  1818. UnicodeString *dayPeriod = static_cast<UnicodeString*>(map->get(dayPeriodKey));
  1819. if (dayPeriod != nullptr) {
  1820. strings[i].fastCopyFrom(*dayPeriod);
  1821. } else {
  1822. strings[i].setToBogus();
  1823. }
  1824. }
  1825. } else {
  1826. for (int32_t i = 0; i < stringCount; i++) {
  1827. strings[i].setToBogus();
  1828. }
  1829. }
  1830. return strings;
  1831. }
  1832. void
  1833. DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
  1834. {
  1835. int32_t len = 0;
  1836. /* In case something goes wrong, initialize all of the data to nullptr. */
  1837. fEras = nullptr;
  1838. fErasCount = 0;
  1839. fEraNames = nullptr;
  1840. fEraNamesCount = 0;
  1841. fNarrowEras = nullptr;
  1842. fNarrowErasCount = 0;
  1843. fMonths = nullptr;
  1844. fMonthsCount=0;
  1845. fShortMonths = nullptr;
  1846. fShortMonthsCount=0;
  1847. fNarrowMonths = nullptr;
  1848. fNarrowMonthsCount=0;
  1849. fStandaloneMonths = nullptr;
  1850. fStandaloneMonthsCount=0;
  1851. fStandaloneShortMonths = nullptr;
  1852. fStandaloneShortMonthsCount=0;
  1853. fStandaloneNarrowMonths = nullptr;
  1854. fStandaloneNarrowMonthsCount=0;
  1855. fWeekdays = nullptr;
  1856. fWeekdaysCount=0;
  1857. fShortWeekdays = nullptr;
  1858. fShortWeekdaysCount=0;
  1859. fShorterWeekdays = nullptr;
  1860. fShorterWeekdaysCount=0;
  1861. fNarrowWeekdays = nullptr;
  1862. fNarrowWeekdaysCount=0;
  1863. fStandaloneWeekdays = nullptr;
  1864. fStandaloneWeekdaysCount=0;
  1865. fStandaloneShortWeekdays = nullptr;
  1866. fStandaloneShortWeekdaysCount=0;
  1867. fStandaloneShorterWeekdays = nullptr;
  1868. fStandaloneShorterWeekdaysCount=0;
  1869. fStandaloneNarrowWeekdays = nullptr;
  1870. fStandaloneNarrowWeekdaysCount=0;
  1871. fAmPms = nullptr;
  1872. fAmPmsCount=0;
  1873. fNarrowAmPms = nullptr;
  1874. fNarrowAmPmsCount=0;
  1875. fTimeSeparator.setToBogus();
  1876. fQuarters = nullptr;
  1877. fQuartersCount = 0;
  1878. fShortQuarters = nullptr;
  1879. fShortQuartersCount = 0;
  1880. fNarrowQuarters = nullptr;
  1881. fNarrowQuartersCount = 0;
  1882. fStandaloneQuarters = nullptr;
  1883. fStandaloneQuartersCount = 0;
  1884. fStandaloneShortQuarters = nullptr;
  1885. fStandaloneShortQuartersCount = 0;
  1886. fStandaloneNarrowQuarters = nullptr;
  1887. fStandaloneNarrowQuartersCount = 0;
  1888. fLeapMonthPatterns = nullptr;
  1889. fLeapMonthPatternsCount = 0;
  1890. fShortYearNames = nullptr;
  1891. fShortYearNamesCount = 0;
  1892. fShortZodiacNames = nullptr;
  1893. fShortZodiacNamesCount = 0;
  1894. fZoneStringsRowCount = 0;
  1895. fZoneStringsColCount = 0;
  1896. fZoneStrings = nullptr;
  1897. fLocaleZoneStrings = nullptr;
  1898. fAbbreviatedDayPeriods = nullptr;
  1899. fAbbreviatedDayPeriodsCount = 0;
  1900. fWideDayPeriods = nullptr;
  1901. fWideDayPeriodsCount = 0;
  1902. fNarrowDayPeriods = nullptr;
  1903. fNarrowDayPeriodsCount = 0;
  1904. fStandaloneAbbreviatedDayPeriods = nullptr;
  1905. fStandaloneAbbreviatedDayPeriodsCount = 0;
  1906. fStandaloneWideDayPeriods = nullptr;
  1907. fStandaloneWideDayPeriodsCount = 0;
  1908. fStandaloneNarrowDayPeriods = nullptr;
  1909. fStandaloneNarrowDayPeriodsCount = 0;
  1910. uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
  1911. // We need to preserve the requested locale for
  1912. // lazy ZoneStringFormat instantiation. ZoneStringFormat
  1913. // is region sensitive, thus, bundle locale bundle's locale
  1914. // is not sufficient.
  1915. fZSFLocale = locale;
  1916. if (U_FAILURE(status)) return;
  1917. // Create a CalendarDataSink to process this data and the resource bundles
  1918. CalendarDataSink calendarSink(status);
  1919. UResourceBundle *rb = ures_open(nullptr, locale.getBaseName(), &status);
  1920. UResourceBundle *cb = ures_getByKey(rb, gCalendarTag, nullptr, &status);
  1921. if (U_FAILURE(status)) return;
  1922. // Iterate over the resource bundle data following the fallbacks through different calendar types
  1923. UnicodeString calendarType((type != nullptr && *type != '\0')? type : gGregorianTag, -1, US_INV);
  1924. while (!calendarType.isBogus()) {
  1925. CharString calendarTypeBuffer;
  1926. calendarTypeBuffer.appendInvariantChars(calendarType, status);
  1927. if (U_FAILURE(status)) { return; }
  1928. const char *calendarTypeCArray = calendarTypeBuffer.data();
  1929. // Enumerate this calendar type. If the calendar is not found fallback to gregorian
  1930. UErrorCode oldStatus = status;
  1931. UResourceBundle *ctb = ures_getByKeyWithFallback(cb, calendarTypeCArray, nullptr, &status);
  1932. if (status == U_MISSING_RESOURCE_ERROR) {
  1933. ures_close(ctb);
  1934. if (uprv_strcmp(calendarTypeCArray, gGregorianTag) != 0) {
  1935. calendarType.setTo(false, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
  1936. calendarSink.visitAllResources();
  1937. status = oldStatus;
  1938. continue;
  1939. }
  1940. return;
  1941. }
  1942. calendarSink.preEnumerate(calendarType);
  1943. ures_getAllItemsWithFallback(ctb, "", calendarSink, status);
  1944. ures_close(ctb);
  1945. if (U_FAILURE(status)) break;
  1946. // Stop loading when gregorian was loaded
  1947. if (uprv_strcmp(calendarTypeCArray, gGregorianTag) == 0) {
  1948. break;
  1949. }
  1950. // Get the next calendar type to process from the sink
  1951. calendarType = calendarSink.nextCalendarType;
  1952. // Gregorian is always the last fallback
  1953. if (calendarType.isBogus()) {
  1954. calendarType.setTo(false, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
  1955. calendarSink.visitAllResources();
  1956. }
  1957. }
  1958. // CharString object to build paths
  1959. CharString path;
  1960. // Load Leap Month Patterns
  1961. UErrorCode tempStatus = status;
  1962. fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
  1963. if (fLeapMonthPatterns) {
  1964. initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calendarSink,
  1965. buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesWideTag, tempStatus), tempStatus);
  1966. initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calendarSink,
  1967. buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
  1968. initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calendarSink,
  1969. buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesNarrowTag, tempStatus), tempStatus);
  1970. initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calendarSink,
  1971. buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
  1972. initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calendarSink,
  1973. buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
  1974. initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calendarSink,
  1975. buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
  1976. initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calendarSink,
  1977. buildResourcePath(path, gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
  1978. if (U_SUCCESS(tempStatus)) {
  1979. // Hack to fix bad C inheritance for dangi monthPatterns (OK in J); this should be handled by aliases in root, but isn't.
  1980. // The ordering of the following statements is important.
  1981. if (fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].isEmpty()) {
  1982. fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
  1983. }
  1984. if (fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].isEmpty()) {
  1985. fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].setTo(fLeapMonthPatterns[kLeapMonthPatternStandaloneNarrow]);
  1986. }
  1987. if (fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].isEmpty()) {
  1988. fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
  1989. }
  1990. if (fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].isEmpty()) {
  1991. fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev]);
  1992. }
  1993. // end of hack
  1994. fLeapMonthPatternsCount = kMonthPatternsCount;
  1995. } else {
  1996. delete[] fLeapMonthPatterns;
  1997. fLeapMonthPatterns = nullptr;
  1998. }
  1999. }
  2000. // Load cyclic names sets
  2001. tempStatus = status;
  2002. initField(&fShortYearNames, fShortYearNamesCount, calendarSink,
  2003. buildResourcePath(path, gCyclicNameSetsTag, gNameSetYearsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
  2004. initField(&fShortZodiacNames, fShortZodiacNamesCount, calendarSink,
  2005. buildResourcePath(path, gCyclicNameSetsTag, gNameSetZodiacsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
  2006. // Load context transforms and capitalization
  2007. tempStatus = U_ZERO_ERROR;
  2008. UResourceBundle *localeBundle = ures_open(nullptr, locale.getName(), &tempStatus);
  2009. if (U_SUCCESS(tempStatus)) {
  2010. UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, gContextTransformsTag, nullptr, &tempStatus);
  2011. if (U_SUCCESS(tempStatus)) {
  2012. UResourceBundle *contextTransformUsage;
  2013. while ( (contextTransformUsage = ures_getNextResource(contextTransforms, nullptr, &tempStatus)) != nullptr ) {
  2014. const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
  2015. if (U_SUCCESS(tempStatus) && intVector != nullptr && len >= 2) {
  2016. const char* usageType = ures_getKey(contextTransformUsage);
  2017. if (usageType != nullptr) {
  2018. const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
  2019. int32_t compResult = 0;
  2020. // linear search; list is short and we cannot be sure that bsearch is available
  2021. while ( typeMapPtr->usageTypeName != nullptr && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
  2022. ++typeMapPtr;
  2023. }
  2024. if (typeMapPtr->usageTypeName != nullptr && compResult == 0) {
  2025. fCapitalization[typeMapPtr->usageTypeEnumValue][0] = static_cast<UBool>(intVector[0]);
  2026. fCapitalization[typeMapPtr->usageTypeEnumValue][1] = static_cast<UBool>(intVector[1]);
  2027. }
  2028. }
  2029. }
  2030. tempStatus = U_ZERO_ERROR;
  2031. ures_close(contextTransformUsage);
  2032. }
  2033. ures_close(contextTransforms);
  2034. }
  2035. tempStatus = U_ZERO_ERROR;
  2036. const LocalPointer<NumberingSystem> numberingSystem(
  2037. NumberingSystem::createInstance(locale, tempStatus), tempStatus);
  2038. if (U_SUCCESS(tempStatus)) {
  2039. // These functions all fail gracefully if passed nullptr pointers and
  2040. // do nothing unless U_SUCCESS(tempStatus), so it's only necessary
  2041. // to check for errors once after all calls are made.
  2042. const LocalUResourceBundlePointer numberElementsData(ures_getByKeyWithFallback(
  2043. localeBundle, gNumberElementsTag, nullptr, &tempStatus));
  2044. const LocalUResourceBundlePointer nsNameData(ures_getByKeyWithFallback(
  2045. numberElementsData.getAlias(), numberingSystem->getName(), nullptr, &tempStatus));
  2046. const LocalUResourceBundlePointer symbolsData(ures_getByKeyWithFallback(
  2047. nsNameData.getAlias(), gSymbolsTag, nullptr, &tempStatus));
  2048. fTimeSeparator = ures_getUnicodeStringByKey(
  2049. symbolsData.getAlias(), gTimeSeparatorTag, &tempStatus);
  2050. if (U_FAILURE(tempStatus)) {
  2051. fTimeSeparator.setToBogus();
  2052. }
  2053. }
  2054. ures_close(localeBundle);
  2055. }
  2056. if (fTimeSeparator.isBogus()) {
  2057. fTimeSeparator.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR);
  2058. }
  2059. // Load day periods
  2060. fAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
  2061. buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesAbbrTag, status),
  2062. fAbbreviatedDayPeriodsCount, status);
  2063. fWideDayPeriods = loadDayPeriodStrings(calendarSink,
  2064. buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesWideTag, status),
  2065. fWideDayPeriodsCount, status);
  2066. fNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
  2067. buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesNarrowTag, status),
  2068. fNarrowDayPeriodsCount, status);
  2069. fStandaloneAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
  2070. buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesAbbrTag, status),
  2071. fStandaloneAbbreviatedDayPeriodsCount, status);
  2072. fStandaloneWideDayPeriods = loadDayPeriodStrings(calendarSink,
  2073. buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesWideTag, status),
  2074. fStandaloneWideDayPeriodsCount, status);
  2075. fStandaloneNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
  2076. buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesNarrowTag, status),
  2077. fStandaloneNarrowDayPeriodsCount, status);
  2078. // Fill in for missing/bogus items (dayPeriods are a map so single items might be missing)
  2079. if (U_SUCCESS(status)) {
  2080. for (int32_t dpidx = 0; dpidx < fAbbreviatedDayPeriodsCount; ++dpidx) {
  2081. if (dpidx < fWideDayPeriodsCount && fWideDayPeriods != nullptr && fWideDayPeriods[dpidx].isBogus()) {
  2082. fWideDayPeriods[dpidx].fastCopyFrom(fAbbreviatedDayPeriods[dpidx]);
  2083. }
  2084. if (dpidx < fNarrowDayPeriodsCount && fNarrowDayPeriods != nullptr && fNarrowDayPeriods[dpidx].isBogus()) {
  2085. fNarrowDayPeriods[dpidx].fastCopyFrom(fAbbreviatedDayPeriods[dpidx]);
  2086. }
  2087. if (dpidx < fStandaloneAbbreviatedDayPeriodsCount && fStandaloneAbbreviatedDayPeriods != nullptr && fStandaloneAbbreviatedDayPeriods[dpidx].isBogus()) {
  2088. fStandaloneAbbreviatedDayPeriods[dpidx].fastCopyFrom(fAbbreviatedDayPeriods[dpidx]);
  2089. }
  2090. if (dpidx < fStandaloneWideDayPeriodsCount && fStandaloneWideDayPeriods != nullptr && fStandaloneWideDayPeriods[dpidx].isBogus()) {
  2091. fStandaloneWideDayPeriods[dpidx].fastCopyFrom(fStandaloneAbbreviatedDayPeriods[dpidx]);
  2092. }
  2093. if (dpidx < fStandaloneNarrowDayPeriodsCount && fStandaloneNarrowDayPeriods != nullptr && fStandaloneNarrowDayPeriods[dpidx].isBogus()) {
  2094. fStandaloneNarrowDayPeriods[dpidx].fastCopyFrom(fStandaloneAbbreviatedDayPeriods[dpidx]);
  2095. }
  2096. }
  2097. }
  2098. U_LOCALE_BASED(locBased, *this);
  2099. // if we make it to here, the resource data is cool, and we can get everything out
  2100. // of it that we need except for the time-zone and localized-pattern data, which
  2101. // are stored in a separate file
  2102. locBased.setLocaleIDs(ures_getLocaleByType(cb, ULOC_VALID_LOCALE, &status),
  2103. ures_getLocaleByType(cb, ULOC_ACTUAL_LOCALE, &status));
  2104. // Load eras
  2105. initField(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status), status);
  2106. UErrorCode oldStatus = status;
  2107. initField(&fEraNames, fEraNamesCount, calendarSink, buildResourcePath(path, gErasTag, gNamesWideTag, status), status);
  2108. if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
  2109. status = oldStatus;
  2110. assignArray(fEraNames, fEraNamesCount, fEras, fErasCount);
  2111. }
  2112. // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
  2113. oldStatus = status;
  2114. initField(&fNarrowEras, fNarrowErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesNarrowTag, status), status);
  2115. if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
  2116. status = oldStatus;
  2117. assignArray(fNarrowEras, fNarrowErasCount, fEras, fErasCount);
  2118. }
  2119. // Load month names
  2120. initField(&fMonths, fMonthsCount, calendarSink,
  2121. buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesWideTag, status), status);
  2122. initField(&fShortMonths, fShortMonthsCount, calendarSink,
  2123. buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesAbbrTag, status), status);
  2124. initField(&fStandaloneMonths, fStandaloneMonthsCount, calendarSink,
  2125. buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
  2126. if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide not available, use format/wide */
  2127. status = U_ZERO_ERROR;
  2128. assignArray(fStandaloneMonths, fStandaloneMonthsCount, fMonths, fMonthsCount);
  2129. }
  2130. initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calendarSink,
  2131. buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
  2132. if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated not available, use format/abbreviated */
  2133. status = U_ZERO_ERROR;
  2134. assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, fShortMonths, fShortMonthsCount);
  2135. }
  2136. UErrorCode narrowMonthsEC = status;
  2137. UErrorCode standaloneNarrowMonthsEC = status;
  2138. initField(&fNarrowMonths, fNarrowMonthsCount, calendarSink,
  2139. buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesNarrowTag, narrowMonthsEC), narrowMonthsEC);
  2140. initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calendarSink,
  2141. buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, narrowMonthsEC), standaloneNarrowMonthsEC);
  2142. if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC != U_MISSING_RESOURCE_ERROR) {
  2143. // If format/narrow not available, use standalone/narrow
  2144. assignArray(fNarrowMonths, fNarrowMonthsCount, fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount);
  2145. } else if (narrowMonthsEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
  2146. // If standalone/narrow not available, use format/narrow
  2147. assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fNarrowMonths, fNarrowMonthsCount);
  2148. } else if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
  2149. // If neither is available, use format/abbreviated
  2150. assignArray(fNarrowMonths, fNarrowMonthsCount, fShortMonths, fShortMonthsCount);
  2151. assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fShortMonths, fShortMonthsCount);
  2152. }
  2153. // Load AM/PM markers; if wide or narrow not available, use short
  2154. UErrorCode ampmStatus = U_ZERO_ERROR;
  2155. initField(&fAmPms, fAmPmsCount, calendarSink,
  2156. buildResourcePath(path, gAmPmMarkersTag, ampmStatus), ampmStatus);
  2157. if (U_FAILURE(ampmStatus)) {
  2158. initField(&fAmPms, fAmPmsCount, calendarSink,
  2159. buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
  2160. }
  2161. ampmStatus = U_ZERO_ERROR;
  2162. initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
  2163. buildResourcePath(path, gAmPmMarkersNarrowTag, ampmStatus), ampmStatus);
  2164. if (U_FAILURE(ampmStatus)) {
  2165. initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
  2166. buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
  2167. }
  2168. if(status == U_MISSING_RESOURCE_ERROR) {
  2169. status = U_ZERO_ERROR;
  2170. assignArray(fNarrowAmPms, fNarrowAmPmsCount, fAmPms, fAmPmsCount);
  2171. }
  2172. // Load quarters
  2173. initField(&fQuarters, fQuartersCount, calendarSink,
  2174. buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesWideTag, status), status);
  2175. initField(&fShortQuarters, fShortQuartersCount, calendarSink,
  2176. buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesAbbrTag, status), status);
  2177. if(status == U_MISSING_RESOURCE_ERROR) {
  2178. status = U_ZERO_ERROR;
  2179. assignArray(fShortQuarters, fShortQuartersCount, fQuarters, fQuartersCount);
  2180. }
  2181. initField(&fStandaloneQuarters, fStandaloneQuartersCount, calendarSink,
  2182. buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
  2183. if(status == U_MISSING_RESOURCE_ERROR) {
  2184. status = U_ZERO_ERROR;
  2185. assignArray(fStandaloneQuarters, fStandaloneQuartersCount, fQuarters, fQuartersCount);
  2186. }
  2187. initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calendarSink,
  2188. buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
  2189. if(status == U_MISSING_RESOURCE_ERROR) {
  2190. status = U_ZERO_ERROR;
  2191. assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, fShortQuarters, fShortQuartersCount);
  2192. }
  2193. // unlike the fields above, narrow format quarters fall back on narrow standalone quarters
  2194. initField(&fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, calendarSink,
  2195. buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
  2196. initField(&fNarrowQuarters, fNarrowQuartersCount, calendarSink,
  2197. buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesNarrowTag, status), status);
  2198. if(status == U_MISSING_RESOURCE_ERROR) {
  2199. status = U_ZERO_ERROR;
  2200. assignArray(fNarrowQuarters, fNarrowQuartersCount, fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount);
  2201. }
  2202. // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
  2203. /*
  2204. // fastCopyFrom()/setTo() - see assignArray comments
  2205. resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
  2206. fLocalPatternChars.setTo(true, resStr, len);
  2207. // If the locale data does not include new pattern chars, use the defaults
  2208. // TODO: Consider making this an error, since this may add conflicting characters.
  2209. if (len < PATTERN_CHARS_LEN) {
  2210. fLocalPatternChars.append(UnicodeString(true, &gPatternChars[len], PATTERN_CHARS_LEN-len));
  2211. }
  2212. */
  2213. fLocalPatternChars.setTo(true, gPatternChars, PATTERN_CHARS_LEN);
  2214. // Format wide weekdays -> fWeekdays
  2215. // {sfb} fixed to handle 1-based weekdays
  2216. initField(&fWeekdays, fWeekdaysCount, calendarSink,
  2217. buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesWideTag, status), 1, status);
  2218. // Format abbreviated weekdays -> fShortWeekdays
  2219. initField(&fShortWeekdays, fShortWeekdaysCount, calendarSink,
  2220. buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesAbbrTag, status), 1, status);
  2221. // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
  2222. initField(&fShorterWeekdays, fShorterWeekdaysCount, calendarSink,
  2223. buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesShortTag, status), 1, status);
  2224. if (status == U_MISSING_RESOURCE_ERROR) {
  2225. status = U_ZERO_ERROR;
  2226. assignArray(fShorterWeekdays, fShorterWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
  2227. }
  2228. // Stand-alone wide weekdays -> fStandaloneWeekdays
  2229. initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, calendarSink,
  2230. buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status), 1, status);
  2231. if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide is not available, use format/wide */
  2232. status = U_ZERO_ERROR;
  2233. assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, fWeekdays, fWeekdaysCount);
  2234. }
  2235. // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
  2236. initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, calendarSink,
  2237. buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), 1, status);
  2238. if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated is not available, use format/abbreviated */
  2239. status = U_ZERO_ERROR;
  2240. assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
  2241. }
  2242. // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
  2243. initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, calendarSink,
  2244. buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status), 1, status);
  2245. if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/short is not available, use format/short */
  2246. status = U_ZERO_ERROR;
  2247. assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, fShorterWeekdays, fShorterWeekdaysCount);
  2248. }
  2249. // Format narrow weekdays -> fNarrowWeekdays
  2250. UErrorCode narrowWeeksEC = status;
  2251. initField(&fNarrowWeekdays, fNarrowWeekdaysCount, calendarSink,
  2252. buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesNarrowTag, status), 1, narrowWeeksEC);
  2253. // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
  2254. UErrorCode standaloneNarrowWeeksEC = status;
  2255. initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, calendarSink,
  2256. buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), 1, standaloneNarrowWeeksEC);
  2257. if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC != U_MISSING_RESOURCE_ERROR) {
  2258. // If format/narrow not available, use standalone/narrow
  2259. assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount);
  2260. } else if (narrowWeeksEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR) {
  2261. // If standalone/narrow not available, use format/narrow
  2262. assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fNarrowWeekdays, fNarrowWeekdaysCount);
  2263. } else if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR ) {
  2264. // If neither is available, use format/abbreviated
  2265. assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
  2266. assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
  2267. }
  2268. // Last resort fallback in case previous data wasn't loaded
  2269. if (U_FAILURE(status))
  2270. {
  2271. if (useLastResortData)
  2272. {
  2273. // Handle the case in which there is no resource data present.
  2274. // We don't have to generate usable patterns in this situation;
  2275. // we just need to produce something that will be semi-intelligible
  2276. // in most locales.
  2277. status = U_USING_FALLBACK_WARNING;
  2278. //TODO(fabalbon): make sure we are storing las resort data for all fields in here.
  2279. initField(&fEras, fErasCount, (const char16_t *)gLastResortEras, kEraNum, kEraLen, status);
  2280. initField(&fEraNames, fEraNamesCount, (const char16_t *)gLastResortEras, kEraNum, kEraLen, status);
  2281. initField(&fNarrowEras, fNarrowErasCount, (const char16_t *)gLastResortEras, kEraNum, kEraLen, status);
  2282. initField(&fMonths, fMonthsCount, (const char16_t *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
  2283. initField(&fShortMonths, fShortMonthsCount, (const char16_t *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
  2284. initField(&fNarrowMonths, fNarrowMonthsCount, (const char16_t *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
  2285. initField(&fStandaloneMonths, fStandaloneMonthsCount, (const char16_t *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
  2286. initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const char16_t *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
  2287. initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const char16_t *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
  2288. initField(&fWeekdays, fWeekdaysCount, (const char16_t *)gLastResortDayNames, kDayNum, kDayLen, status);
  2289. initField(&fShortWeekdays, fShortWeekdaysCount, (const char16_t *)gLastResortDayNames, kDayNum, kDayLen, status);
  2290. initField(&fShorterWeekdays, fShorterWeekdaysCount, (const char16_t *)gLastResortDayNames, kDayNum, kDayLen, status);
  2291. initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const char16_t *)gLastResortDayNames, kDayNum, kDayLen, status);
  2292. initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const char16_t *)gLastResortDayNames, kDayNum, kDayLen, status);
  2293. initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const char16_t *)gLastResortDayNames, kDayNum, kDayLen, status);
  2294. initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, (const char16_t *)gLastResortDayNames, kDayNum, kDayLen, status);
  2295. initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const char16_t *)gLastResortDayNames, kDayNum, kDayLen, status);
  2296. initField(&fAmPms, fAmPmsCount, (const char16_t *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
  2297. initField(&fNarrowAmPms, fNarrowAmPmsCount, (const char16_t *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
  2298. initField(&fQuarters, fQuartersCount, (const char16_t *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
  2299. initField(&fShortQuarters, fShortQuartersCount, (const char16_t *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
  2300. initField(&fNarrowQuarters, fNarrowQuartersCount, (const char16_t *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
  2301. initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const char16_t *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
  2302. initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const char16_t *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
  2303. initField(&fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, (const char16_t *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
  2304. fLocalPatternChars.setTo(true, gPatternChars, PATTERN_CHARS_LEN);
  2305. }
  2306. }
  2307. // Close resources
  2308. ures_close(cb);
  2309. ures_close(rb);
  2310. }
  2311. Locale
  2312. DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
  2313. U_LOCALE_BASED(locBased, *this);
  2314. return locBased.getLocale(type, status);
  2315. }
  2316. U_NAMESPACE_END
  2317. #endif /* #if !UCONFIG_NO_FORMATTING */
  2318. //eof