• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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