1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru **********************************************************************
385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Copyright (c) 2003-2008, International Business Machines
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Corporation and others.  All Rights Reserved.
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru **********************************************************************
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Author: Alan Liu
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Created: September 2 2003
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Since: ICU 2.8
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru **********************************************************************
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "gregoimp.h"
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ucal.h"
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uresimp.h"
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cstring.h"
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uassert.h"
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined(U_DEBUG_CALDATA)
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdio.h>
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoint32_t ClockMath::floorDivide(int32_t numerator, int32_t denominator) {
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (numerator >= 0) ?
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        numerator / denominator : ((numerator + 1) / denominator) - 1;
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoint32_t ClockMath::floorDivide(double numerator, int32_t denominator,
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          int32_t& remainder) {
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    double quotient;
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    quotient = uprv_floor(numerator / denominator);
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    remainder = (int32_t) (numerator - (quotient * denominator));
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (int32_t) quotient;
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
4085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hodouble ClockMath::floorDivide(double dividend, double divisor,
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         double& remainder) {
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Only designed to work for positive divisors
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    U_ASSERT(divisor > 0);
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    double quotient = floorDivide(dividend, divisor);
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    remainder = dividend - (quotient * divisor);
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // N.B. For certain large dividends, on certain platforms, there
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // is a bug such that the quotient is off by one.  If you doubt
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // this to be true, set a breakpoint below and run cintltst.
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (remainder < 0 || remainder >= divisor) {
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // E.g. 6.7317038241449352e+022 / 86400000.0 is wrong on my
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // machine (too high by one).  4.1792057231752762e+024 /
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // 86400000.0 is wrong the other way (too low).
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        double q = quotient;
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        quotient += (remainder < 0) ? -1 : +1;
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (q == quotient) {
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // For quotients > ~2^53, we won't be able to add or
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // subtract one, since the LSB of the mantissa will be >
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // 2^0; that is, the exponent (base 2) will be larger than
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the length, in bits, of the mantissa.  In that case, we
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // can't give a correct answer, so we set the remainder to
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // zero.  This has the desired effect of making extreme
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // values give back an approximate answer rather than
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // crashing.  For example, UDate values above a ~10^25
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // might all have a time of midnight.
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            remainder = 0;
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            remainder = dividend - (quotient * divisor);
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    U_ASSERT(0 <= remainder && remainder < divisor);
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return quotient;
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst int32_t JULIAN_1_CE    = 1721426; // January 1, 1 CE Gregorian
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst int32_t JULIAN_1970_CE = 2440588; // January 1, 1970 CE Gregorian
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst int16_t Grego::DAYS_BEFORE[24] =
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {0,31,59,90,120,151,181,212,243,273,304,334,
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     0,31,60,91,121,152,182,213,244,274,305,335};
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst int8_t Grego::MONTH_LENGTH[24] =
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {31,28,31,30,31,30,31,31,30,31,30,31,
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     31,29,31,30,31,30,31,31,30,31,30,31};
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble Grego::fieldsToDay(int32_t year, int32_t month, int32_t dom) {
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t y = year - 1;
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
8985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    double julian = 365 * y + ClockMath::floorDivide(y, 4) + (JULIAN_1_CE - 3) + // Julian cal
9085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ClockMath::floorDivide(y, 400) - ClockMath::floorDivide(y, 100) + 2 + // => Gregorian cal
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DAYS_BEFORE[month + (isLeapYear(year) ? 12 : 0)] + dom; // => month/dom
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return julian - JULIAN_1970_CE; // JD => epoch day
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Grego::dayToFields(double day, int32_t& year, int32_t& month,
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        int32_t& dom, int32_t& dow, int32_t& doy) {
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Convert from 1970 CE epoch to 1 CE epoch (Gregorian calendar)
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    day += JULIAN_1970_CE - JULIAN_1_CE;
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Convert from the day number to the multiple radix
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // representation.  We use 400-year, 100-year, and 4-year cycles.
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // For example, the 4-year cycle has 4 years + 1 leap day; giving
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // 1461 == 365*4 + 1 days.
10685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t n400 = ClockMath::floorDivide(day, 146097, doy); // 400-year cycle length
10785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t n100 = ClockMath::floorDivide(doy, 36524, doy); // 100-year cycle length
10885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t n4   = ClockMath::floorDivide(doy, 1461, doy); // 4-year cycle length
10985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t n1   = ClockMath::floorDivide(doy, 365, doy);
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    year = 400*n400 + 100*n100 + 4*n4 + n1;
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (n100 == 4 || n1 == 4) {
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        doy = 365; // Dec 31 at end of 4- or 400-year cycle
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ++year;
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool isLeap = isLeapYear(year);
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Gregorian day zero is a Monday.
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    dow = (int32_t) uprv_fmod(day + 1, 7);
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    dow += (dow < 0) ? (UCAL_SUNDAY + 7) : UCAL_SUNDAY;
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Common Julian/Gregorian calculation
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t correction = 0;
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t march1 = isLeap ? 60 : 59; // zero-based DOY for March 1
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (doy >= march1) {
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        correction = isLeap ? 1 : 2;
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    month = (12 * (doy + correction) + 6) / 367; // zero-based month
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    dom = doy - DAYS_BEFORE[month + (isLeap ? 12 : 0)] + 1; // one-based DOM
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    doy++; // one-based doy
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Grego::timeToFields(UDate time, int32_t& year, int32_t& month,
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        int32_t& dom, int32_t& dow, int32_t& doy, int32_t& mid) {
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    double millisInDay;
13785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    double day = ClockMath::floorDivide((double)time, (double)U_MILLIS_PER_DAY, millisInDay);
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    mid = (int32_t)millisInDay;
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    dayToFields(day, year, month, dom, dow, doy);
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t Grego::dayOfWeek(double day) {
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t dow;
14485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    ClockMath::floorDivide(day + UCAL_THURSDAY, 7, dow);
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (dow == 0) ? UCAL_SATURDAY : dow;
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t Grego::dayOfWeekInMonth(int32_t year, int32_t month, int32_t dom) {
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t weekInMonth = (dom + 6)/7;
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (weekInMonth == 4) {
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (dom + 7 > monthLength(year, month)) {
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            weekInMonth = -1;
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if (weekInMonth == 5) {
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        weekInMonth = -1;
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return weekInMonth;
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* ---- CalendarData ------ */
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define U_CALENDAR_KEY "calendar"
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define U_GREGORIAN_KEY "gregorian"
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define U_FORMAT_KEY "format"
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define U_DEFAULT_KEY "default"
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define U_CALENDAR_DATA ((char*)0)
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// CalendarData::CalendarData(const Locale& loc, UErrorCode& status)
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//   : fFillin(NULL), fBundle(NULL), fFallback(NULL) {
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//   initData(loc.getBaseName(), (char*) "???", status);
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// }
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarData::CalendarData(const Locale& loc, const char *type, UErrorCode& status)
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : fFillin(NULL), fOtherFillin(NULL), fBundle(NULL), fFallback(NULL) {
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  initData(loc.getBaseName(), type, status);
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid CalendarData::initData(const char *locale, const char *type, UErrorCode& status) {
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  fOtherFillin = ures_open(U_CALENDAR_DATA, locale, &status);
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  fFillin = ures_getByKey(fOtherFillin, U_CALENDAR_KEY, fFillin, &status);
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if((type != NULL) &&
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     (*type != '\0') &&
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     (uprv_strcmp(type, U_GREGORIAN_KEY)))
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  {
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fBundle = ures_getByKeyWithFallback(fFillin, type, NULL, &status);
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fFallback = ures_getByKeyWithFallback(fFillin, U_GREGORIAN_KEY, NULL, &status);
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined (U_DEBUG_CALDATA)
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fprintf(stderr, "%p: CalendarData(%s, %s, %s) -> main(%p, %s)=%s, fallback(%p, %s)=%s\n",
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            this, locale, type, u_errorName(status), fBundle, type, fBundle?ures_getLocale(fBundle, &status):"",
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fFallback, U_GREGORIAN_KEY, fFallback?ures_getLocale(fFallback, &status):"");
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  } else {
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fBundle = ures_getByKeyWithFallback(fFillin, U_GREGORIAN_KEY, NULL, &status);
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined (U_DEBUG_CALDATA)
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fprintf(stderr, "%p: CalendarData(%s, %s, %s) -> main(%p, %s)=%s, fallback = NULL\n",
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            this, locale, type, u_errorName(status), fBundle, U_GREGORIAN_KEY, fBundle?ures_getLocale(fBundle, &status):"" );
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarData::~CalendarData() {
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ures_close(fFillin);
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ures_close(fBundle);
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ures_close(fFallback);
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ures_close(fOtherFillin);
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUResourceBundle*
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarData::getByKey(const char *key, UErrorCode& status) {
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(status)) {
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(fBundle) {
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fFillin = ures_getByKeyWithFallback(fBundle, key, fFillin, &status);
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined (U_DEBUG_CALDATA)
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fprintf(stderr, "%p: get %s -> %s - from MAIN %s\n",this, key, u_errorName(status), ures_getLocale(fFillin, &status));
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(fFallback && (status == U_MISSING_RESOURCE_ERROR)) {
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_ZERO_ERROR; // retry with fallback (gregorian)
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fFillin = ures_getByKeyWithFallback(fFallback, key, fFillin, &status);
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined (U_DEBUG_CALDATA)
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fprintf(stderr, "%p: get %s -> %s - from FALLBACK %s\n",this, key, u_errorName(status), ures_getLocale(fFillin, &status));
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return fFillin;
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUResourceBundle* CalendarData::getByKey2(const char *key, const char *subKey, UErrorCode& status) {
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(status)) {
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(fBundle) {
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined (U_DEBUG_CALDATA)
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fprintf(stderr, "%p: //\n");
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fFillin = ures_getByKeyWithFallback(fBundle, key, fFillin, &status);
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fOtherFillin = ures_getByKeyWithFallback(fFillin, U_FORMAT_KEY, fOtherFillin, &status);
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fFillin = ures_getByKeyWithFallback(fOtherFillin, subKey, fFillin, &status);
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined (U_DEBUG_CALDATA)
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fprintf(stderr, "%p: get %s/format/%s -> %s - from MAIN %s\n", this, key, subKey, u_errorName(status), ures_getLocale(fFillin, &status));
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(fFallback && (status == U_MISSING_RESOURCE_ERROR)) {
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_ZERO_ERROR; // retry with fallback (gregorian)
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fFillin = ures_getByKeyWithFallback(fFallback, key, fFillin, &status);
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fOtherFillin = ures_getByKeyWithFallback(fFillin, U_FORMAT_KEY, fOtherFillin, &status);
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fFillin = ures_getByKeyWithFallback(fOtherFillin, subKey, fFillin, &status);
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined (U_DEBUG_CALDATA)
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fprintf(stderr, "%p: get %s/format/%s -> %s - from FALLBACK %s\n",this, key, subKey, u_errorName(status), ures_getLocale(fFillin,&status));
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//// handling of 'default' keyword on failure: Commented out for 3.0.
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//   if((status == U_MISSING_RESOURCE_ERROR) &&
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//      uprv_strcmp(subKey,U_DEFAULT_KEY)) { // avoid recursion
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// #if defined (U_DEBUG_CALDATA)
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     fprintf(stderr, "%p: - attempting fallback -\n", this);
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     fflush(stderr);
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// #endif
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     UErrorCode subStatus = U_ZERO_ERROR;
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     int32_t len;
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     char kwBuf[128] = "";
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     const UChar *kw;
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     /* fFillin = */ getByKey2(key, U_DEFAULT_KEY, subStatus);
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     kw = ures_getString(fFillin, &len, &subStatus);
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     if(len>126) { // too big
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//       len = 0;
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     }
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     if(U_SUCCESS(subStatus) && (len>0)) {
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//       u_UCharsToChars(kw, kwBuf, len+1);
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//       if(*kwBuf && uprv_strcmp(kwBuf,subKey)) {
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// #if defined (U_DEBUG_CALDATA)
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//         fprintf(stderr, "%p: trying  %s/format/default -> \"%s\"\n",this, key, kwBuf);
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// #endif
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//         // now try again with the default
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//         status = U_ZERO_ERROR;
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//         /* fFillin = */ getByKey2(key, kwBuf, status);
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//       }
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// #if defined (U_DEBUG_CALDATA)
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     } else {
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//       fprintf(stderr, "%p: could not load  %s/format/default  - fail out (%s)\n",this, key, kwBuf, u_errorName(status));
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// #endif
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     }
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//   }
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return fFillin;
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUResourceBundle* CalendarData::getByKey3(const char *key, const char *contextKey, const char *subKey, UErrorCode& status) {
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(status)) {
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(fBundle) {
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined (U_DEBUG_CALDATA)
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fprintf(stderr, "%p: //\n");
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fFillin = ures_getByKeyWithFallback(fBundle, key, fFillin, &status);
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fOtherFillin = ures_getByKeyWithFallback(fFillin, contextKey, fOtherFillin, &status);
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fFillin = ures_getByKeyWithFallback(fOtherFillin, subKey, fFillin, &status);
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined (U_DEBUG_CALDATA)
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fprintf(stderr, "%p: get %s/%s/%s -> %s - from MAIN %s\n", this, key, contextKey, subKey, u_errorName(status), ures_getLocale(fFillin, &status));
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(fFallback && (status == U_MISSING_RESOURCE_ERROR)) {
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_ZERO_ERROR; // retry with fallback (gregorian)
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fFillin = ures_getByKeyWithFallback(fFallback, key, fFillin, &status);
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fOtherFillin = ures_getByKeyWithFallback(fFillin, contextKey, fOtherFillin, &status);
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fFillin = ures_getByKeyWithFallback(fOtherFillin, subKey, fFillin, &status);
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined (U_DEBUG_CALDATA)
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fprintf(stderr, "%p: get %s/%s/%s -> %s - from FALLBACK %s\n",this, key, contextKey, subKey, u_errorName(status), ures_getLocale(fFillin,&status));
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return fFillin;
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//eof
329