1 // © 2017 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *******************************************************************************
5 *
6 * Copyright (C) 2009-2012, International Business Machines
7 * Corporation and others. All Rights Reserved.
8 *
9 *******************************************************************************
10 */
11 #define CAL_FE_DEBUG 1
12
13 #ifndef CAL_FE_DEBUG
14 #define CAL_FE_DEBUG 0
15 #endif
16
17 #if CAL_FE_DEBUG
18 #define debugfprintf(x) fflush(stderr),fflush(stdout),fprintf x,fflush(stderr),fflush(stdout)
19 #else
20 #define debugfprintf(x)
21 #endif
22
23 #include <icuglue/icuglue.h>
24 #include "unicode/ucal.h"
25 //#include <unicode/tblcoll.h>
26 #include "unicode/calendar.h"
27 #include <string.h>
28 #include <stdio.h>
29 #include "unicode/ustring.h"
30 #include "unicode/gregocal.h"
31
32
33
34 /**
35 * Macro to define the Calendar_glue_4_2 class
36 */
37 #ifdef GLUE_VER
38 #error GLUE_VER is defined
39 #endif
40
41 #define GLUE_VER(x) class GLUE_SYM_V( Calendar, x ) : public Calendar { \
42 public: /* static create */ \
43 UCalendar *_this; GLUE_SYM_V( Calendar, x ) ( const Locale&, UErrorCode& ); \
44 private: \
45 virtual ~ GLUE_SYM_V ( Calendar, x) (); \
46 public: \
47 virtual void* getDynamicClassID() const; \
48 static void* getStaticClassID() ; \
49 /* overrides */ \
50 virtual UBool haveDefaultCentury() const; \
51 virtual UDate defaultCenturyStart() const ; \
52 virtual int32_t handleGetExtendedYear() ; \
53 virtual const char * getType() const ; \
54 virtual UBool inDaylightTime(UErrorCode& status) const ; \
55 virtual int32_t defaultCenturyStartYear() const ; \
56 virtual int32_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const ; \
57 virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const ; \
58 virtual Calendar* clone(void) const; \
59 public: static int32_t countAvailable(); \
60 public: static int32_t appendAvailable(UnicodeString* strs, int32_t i, int32_t count); \
61 };
62
63
64 /** ==================================== The following code runs inside the 'target' version (i.e. old ICU) ========== **/
65 #if defined ( ICUGLUE_VER )
66
67 /* code for some version */
68 #include <icuglue/gluren.h>
69 #include "oicu.h"
70
71 #ifdef GLUE_VER
72 GLUE_VER( ICUGLUE_VER )
73 #endif
74
GLUE_SYM(Calendar)75 GLUE_SYM (Calendar ) :: GLUE_SYM(Calendar) ( const Locale& loc, UErrorCode& status ) :
76 Calendar(status), _this(NULL)
77 {
78
79 _this = OICU_ucal_open(NULL, -1, /*locale*/NULL, UCAL_DEFAULT, &status);
80
81 // copy some things over
82 setMinimalDaysInFirstWeek(OICU_ucal_getAttribute(_this, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK));
83 setFirstDayOfWeek((UCalendarDaysOfWeek)OICU_ucal_getAttribute(_this, UCAL_FIRST_DAY_OF_WEEK));
84 }
85
GLUE_SYM(Calendar)86 GLUE_SYM ( Calendar ) :: ~ GLUE_SYM(Calendar) () {
87 #if CAL_FE_DEBUG
88 fprintf(stderr, "VCF " ICUGLUE_VER_STR " ucal_close");
89 #endif
90 OICU_ucal_close(_this);
91 }
92
93
GLUE_SYM(Calendar)94 UBool GLUE_SYM ( Calendar ) :: haveDefaultCentury() const {
95 return false;
96 }
GLUE_SYM(Calendar)97 UDate GLUE_SYM ( Calendar ) :: defaultCenturyStart() const {
98 return 0L;
99 }
GLUE_SYM(Calendar)100 int32_t GLUE_SYM ( Calendar ) :: handleGetExtendedYear() {
101 return 0;
102 }
GLUE_SYM(Calendar)103 const char * GLUE_SYM ( Calendar ) :: getType() const {
104 return "dilbert";
105 }
GLUE_SYM(Calendar)106 UBool GLUE_SYM ( Calendar ) :: inDaylightTime(UErrorCode& status) const {
107 return false;
108 }
GLUE_SYM(Calendar)109 int32_t GLUE_SYM ( Calendar ) :: defaultCenturyStartYear() const {
110 return 2012;
111 }
GLUE_SYM(Calendar)112 int32_t GLUE_SYM ( Calendar ) :: handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const {
113 return 0;
114 }
115
GLUE_SYM(Calendar)116 int32_t GLUE_SYM ( Calendar ) :: handleGetLimit(UCalendarDateFields field, ELimitType limitType) const {
117 return 1;
118 }
GLUE_SYM(Calendar)119 Calendar* GLUE_SYM ( Calendar ) :: clone(void) const {
120 return NULL;
121 }
122
123
124 // DateFormat *
125 // GLUE_SYM ( DateFormat ) :: create(UDateFormatStyle timeStyle,
126 // UDateFormatStyle dateStyle,
127 // const char *locale,
128 // const UChar *tzID,
129 // int32_t tzIDLength,
130 // const UChar *pattern,
131 // int32_t patternLength,
132 // UErrorCode *status,
133 // const Locale &loc, const char */*ver*/) {
134 // // TODO: save version
135 // //char locBuf[200];
136 // //char kwvBuf[200];
137 // UDateFormat * uc = OICU_udat_open( timeStyle, dateStyle, locale,
138 // tzID,
139 // tzIDLength,
140 // pattern,
141 // patternLength,
142 // status);
143 // if(U_FAILURE(*status)) return NULL; // TODO: ERR?
144 // DateFormat *c = new GLUE_SYM( DateFormat ) ( uc );
145 // #if CAL_FE_DEBUG
146 // fprintf(stderr, "VCF " ICUGLUE_VER_STR " udat_open=%s ->> %p\n", loc.getName(), (void*)c);
147 // #endif
148 // return c;
149 // }
150
151
GLUE_SYM(Calendar)152 int32_t GLUE_SYM ( Calendar ) :: countAvailable() {
153 int32_t count = OICU_udat_countAvailable();
154 return count;
155 }
156
157
GLUE_SYM(Calendar)158 int32_t GLUE_SYM ( Calendar ) :: appendAvailable(UnicodeString* strs, int32_t i, int32_t /*count*/) {
159 int avail = OICU_udat_countAvailable();
160 UErrorCode status = U_ZERO_ERROR;
161 OICU_u_init(&status);
162 #if CAL_FE_DEBUG
163 fprintf(stderr, "VCF " ICUGLUE_VER_STR " avail %d - init %s\n", avail, u_errorName(status));
164 #endif
165 for(int j=0;j<avail;j++) {
166 strs[i+j].append(OICU_udat_getAvailable(j));
167 strs[i+j].append("@sp=icu");
168 if(IS_OLD_VERSTR(ICUGLUE_VER_STR)) {
169 strs[i+j].append( ICUGLUE_VER_STR[OLD_VERSTR_MAJ] ); // X_y
170 strs[i+j].append( ICUGLUE_VER_STR[OLD_VERSTR_MIN] ); // x_Y
171 } else {
172 strs[i+j].append( ICUGLUE_VER_STR[NEW_VERSTR_MAJ] ); // Xy_
173 strs[i+j].append( ICUGLUE_VER_STR[NEW_VERSTR_MIN] ); // xY_
174 }
175 #if CAL_FE_DEBUG
176 {
177 char foo[999];
178 const UChar *ss = strs[i+j].getTerminatedBuffer();
179 u_austrcpy(foo, ss);
180 fprintf(stderr, "VCF " ICUGLUE_VER_STR " appending [%d+%d=%d] <<%s>>\n", i, j, i+j, foo);
181 }
182 #endif
183 }
184 return OICU_ucol_countAvailable();
185 }
186
187 UOBJECT_DEFINE_RTTI_IMPLEMENTATION( GLUE_SYM( Calendar ) )
188
189
190
191
192 #else
193 /** ==================================== The following code runs inside the 'provider' version (i.e. current ICU) ========== **/
194
195 // #if (U_ICU_VERSION_MAJOR_NUM < 49)
196 // #define CAL_PROVIDER_UNSUPPORTED
197 // #endif
198
199 #ifndef CAL_PROVIDER_UNSUPPORTED
200 // define Collator_XX
201 #include "icuglue/glver.h"
202
203 #include "servloc.h"
204
205 // generate list of versions
206 static
207 #include <icuglue/fe_verlist.h>
208
209 class VersionCalendarFactory : public LocaleKeyFactory {
210 public:
211 VersionCalendarFactory();
212 virtual UObject* handleCreate(const Locale &loc, int32_t kind, const ICUService* service, UErrorCode& status) const;
213 // virtual Calendar *createFormat(UCalendarStyle timeStyle,
214 // UCalendarStyle dateStyle,
215 // const char *locale,
216 // const UChar *tzID,
217 // int32_t tzIDLength,
218 // const UChar *pattern,
219 // int32_t patternLength,
220 // UErrorCode *status);
221 virtual void* getDynamicClassID() const;
222 static void* getStaticClassID() ;
223 virtual const Hashtable* getSupportedIDs(UErrorCode& status) const;
224 private:
225 const UnicodeString *getSupportedIDs(int32_t &count, UErrorCode &status) const;
226
227 public:
228 virtual UObject*
229 create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const ;
230
231 };
232
233 UOBJECT_DEFINE_RTTI_IMPLEMENTATION( VersionCalendarFactory )
234
235 UObject*
236 VersionCalendarFactory::create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const {
237 // UnicodeString id;
238 // key.currentID(id);
239 // Locale l(id);
240 Locale l;
241 const LocaleKey& lkey = (LocaleKey&)key;
242 lkey.currentLocale(l);
243 debugfprintf((stderr, "VCalF::create() .. %s err=%s\n", (const char*)l.getName(), u_errorName(status)));
244
245 char kw[100];
246 int32_t kwlen = l.getKeywordValue("sp", kw, 100, status);
247
248 UObject *f;
249 if(kwlen>0) {
250 debugfprintf((stderr, "Trying for kw=%s\n", kw));
251 f = handleCreate(l, -1, service, status);
252 } else {
253 f = LocaleKeyFactory::create(key,service,status);
254 }
255
256
257
258 debugfprintf((stderr, "VCalF::create() .. = %p err=%s\n", (void*)f, u_errorName(status)));
259 return f;
260 }
261
262 VersionCalendarFactory::VersionCalendarFactory() :LocaleKeyFactory(LocaleKeyFactory::VISIBLE){
263 #if CAL_FE_DEBUG
264 printf("VCalF: hi! pid=%d, this=%p\n", getpid(), (void*)this);
265 #endif
266 }
267 UObject* VersionCalendarFactory::handleCreate(const Locale &loc, int32_t kind, const ICUService* service, UErrorCode& status) const {
268 //Locale loc(locale);
269 // pull off provider #
270 char provider[200];
271 #if CAL_FE_DEBUG
272 fprintf(stderr, "VCalF:CC %s\n", loc.getName());
273 #endif
274 int32_t len = loc.getKeywordValue("sp", provider, 200, status);
275 if(U_FAILURE(status)||len==0) return NULL;
276 #if CAL_FE_DEBUG
277 fprintf(stderr, "VCalF:KWV> %s/%d\n", u_errorName(status), len);
278 #endif
279 provider[len]=0;
280 #if CAL_FE_DEBUG
281 fprintf(stderr, "VCalF:KWV %s\n", provider);
282 #endif
283 if(strncmp(provider,"icu",3)) return NULL;
284 const char *icuver=provider+3;
285 #if CAL_FE_DEBUG
286 fprintf(stderr, "VCalF:ICUV %s\n", icuver);
287 #endif
288
289 #if defined(GLUE_VER)
290 #undef GLUE_VER
291 #endif
292 #define GLUE_VER(x) debugfprintf((stderr,"%c/%c|%c/%c\n", icuver[0],(#x)[0],icuver[1],(#x)[2])); if(CMP_VERSTR(icuver, (#x))) { Calendar *c = new glue ## Calendar ## x (loc, status); debugfprintf((stderr, "VCalF::CC %s -> %p\n", loc.getName(), c)); return c; }
293 #include "icuglue/glver.h"
294 #if CAL_FE_DEBUG
295 fprintf(stderr, "VCalF:CC %s failed\n", loc.getName());
296 #endif
297
298 return NULL;
299 }
300
301
302 static const UnicodeString *gLocalesDate = NULL;
303 static int32_t gLocCountDate = 0;
304
305 const Hashtable *VersionCalendarFactory::getSupportedIDs (UErrorCode& status) const {
306 // from coll.cpp
307 Hashtable *_ids = NULL;
308 if (U_SUCCESS(status)) {
309 int32_t count = 0;
310 _ids = new Hashtable(status);
311 if (_ids) {
312 const UnicodeString * idlist = /* _delegate -> */ getSupportedIDs(count, status);
313 for (int i = 0; i < count; ++i) {
314 _ids->put(idlist[i], (void*)this, status);
315 if (U_FAILURE(status)) {
316 delete _ids;
317 _ids = NULL;
318 return;
319 }
320 }
321 } else {
322 status = U_MEMORY_ALLOCATION_ERROR;
323 }
324 debugfprintf((stderr,"VCalF: hash=%p, count=%d, err=%s\n", (void*)_ids, count, u_errorName(status)));
325 }
326 return _ids;
327 }
328
329 const UnicodeString
330 *VersionCalendarFactory::getSupportedIDs(int32_t &count, UErrorCode &/*status*/) const {
331 if(gLocalesDate==NULL) {
332 count = 0;
333
334
335 /* gather counts */
336
337 #if defined(GLUE_VER)
338 #undef GLUE_VER
339 #endif
340 #define GLUE_VER(x) count += glue ## Calendar ## x :: countAvailable();
341 #include "icuglue/glver.h"
342
343 #if CAL_FE_DEBUG
344 printf("VCalF: count=%d\n", count);
345 #endif
346 UnicodeString *strs = new UnicodeString[count];
347 int32_t i = 0;
348
349 #if defined(GLUE_VER)
350 #undef GLUE_VER
351 #endif
352 #define GLUE_VER(x) i += glue ## Calendar ## x :: appendAvailable(strs, i, count);
353 #include "icuglue/glver.h"
354
355 #if CAL_FE_DEBUG
356 printf("VCalF: appended count=%d\n", count);
357 #endif
358
359 gLocCountDate = count;
360 gLocalesDate = strs;
361 }
362 count = gLocCountDate;
363 return gLocalesDate;
364 }
365
366
367 /* Plugin Code */
368
369 #include <stdio.h>
370 #include <unicode/uversion.h>
371
372 static URegistryKey rkcal = NULL;
373
374 void cal_provider_register(UErrorCode &status) {
375 debugfprintf((stderr, "about to register VCalF\n"));
376 rkcal = Calendar::registerFactory(new VersionCalendarFactory(), status);
377 debugfprintf((stderr, ".. registered VCalF, key=%p\n", (void*)rkcal));
378 }
379
380 void cal_provider_unregister(UErrorCode &status) {
381 Calendar::unregister(rkcal, status);
382 }
383
384 #else
385
386 /* no op- this ICU doesn't support date providers */
387
388 void cal_provider_register(UErrorCode &) {
389 // not supported
390 }
391
392 void cal_provider_unregister(UErrorCode &) {
393 // not supported
394 }
395
396 #endif
397
398 /* Plugin- only ICU 4.4+ */
399 #if (U_ICU_VERSION_MAJOR_NUM > 4) || ((U_ICU_VERSION_MAJOR_NUM==4)&&(U_ICU_VERSION_MINOR_NUM>3))
400 #include "unicode/icuplug.h"
401
402 U_CAPI UPlugTokenReturn U_EXPORT2 cal_provider_plugin (UPlugData *data, UPlugReason reason, UErrorCode *status);
403
404 U_CAPI UPlugTokenReturn U_EXPORT2 cal_provider_plugin (UPlugData *data, UPlugReason reason, UErrorCode *status)
405 {
406 switch(reason) {
407 case UPLUG_REASON_QUERY:
408 uplug_setPlugName(data, "Calendar Provider Plugin");
409 uplug_setPlugLevel(data, UPLUG_LEVEL_HIGH);
410 break;
411 case UPLUG_REASON_LOAD:
412 cal_provider_register(*status);
413 break;
414 case UPLUG_REASON_UNLOAD:
415 cal_provider_unregister(*status);
416 break;
417 default:
418 break; /* not handled */
419 }
420 return UPLUG_TOKEN;
421 }
422 #else
423
424 /*
425 Note: this ICU version must explicitly call 'cal_provider_plugin'
426 */
427
428 #endif /* plugin */
429
430 #endif /* provider side (vs target) */
431