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
12 #ifndef DATE_FE_DEBUG
13 #define DATE_FE_DEBUG 0
14 #endif
15
16 #include <icuglue/icuglue.h>
17 #include "unicode/udat.h"
18 //#include <unicode/tblcoll.h>
19 #include "unicode/datefmt.h"
20 #include "unicode/smpdtfmt.h"
21 #include <string.h>
22 #include <stdio.h>
23 #include "unicode/ustring.h"
24 #include "unicode/gregocal.h"
25
26
27
28 /**
29 * Macro to define the Collator_glue_4_2 class
30 */
31 #ifdef GLUE_VER
32 #error GLUE_VER is defined
33 #endif
34
35 #define GLUE_VER(x) class GLUE_SYM_V( DateFormat, x ) : public DateFormat { \
36 public: static DateFormat *create(UDateFormatStyle timeStyle, \
37 UDateFormatStyle dateStyle, \
38 const char *locale, \
39 const UChar *tzID, \
40 int32_t tzIDLength, \
41 const UChar *pattern, \
42 int32_t patternLength, \
43 UErrorCode *status, const Locale &loc, const char *ver); \
44 private: UDateFormat *_this; GLUE_SYM_V( DateFormat, x ) ( UDateFormat* tn ); \
45 virtual ~ GLUE_SYM_V ( DateFormat, x) (); \
46 public: \
47 virtual void* getDynamicClassID() const; \
48 static void* getStaticClassID() ; \
49 virtual UnicodeString& format( Calendar& cal, UnicodeString& appendTo, FieldPosition& pos) const; \
50 virtual void parse( const UnicodeString& text, Calendar& cal, ParsePosition& pos) const; \
51 virtual Format* clone(void) const; \
52 public: static int32_t countAvailable(); \
53 public: static int32_t appendAvailable(UnicodeString* strs, int32_t i, int32_t count); \
54 }; \
55
56
57
58 /** ==================================== The following code runs inside the 'target' version (i.e. old ICU) ========== **/
59 #if defined ( ICUGLUE_VER )
60
61
62
63 /* code for some version */
64 #include <icuglue/gluren.h>
65 #include "oicu.h"
66
67 #ifdef GLUE_VER
68 GLUE_VER( ICUGLUE_VER )
69 #endif
70
GLUE_SYM(DateFormat)71 GLUE_SYM (DateFormat ) :: GLUE_SYM(DateFormat) ( UDateFormat* tn) :
72 _this(tn)
73 {
74
75 UErrorCode status = U_ZERO_ERROR;
76 adoptCalendar(new GregorianCalendar(status));
77 }
78
GLUE_SYM(DateFormat)79 GLUE_SYM ( DateFormat ) :: ~ GLUE_SYM(DateFormat) () {
80 #if DATE_FE_DEBUG
81 fprintf(stderr, "VCF " ICUGLUE_VER_STR " udat_close");
82 #endif
83 OICU_udat_close(_this);
84 }
85
86 DateFormat *
GLUE_SYM(DateFormat)87 GLUE_SYM ( DateFormat ) :: create(UDateFormatStyle timeStyle,
88 UDateFormatStyle dateStyle,
89 const char *locale,
90 const UChar *tzID,
91 int32_t tzIDLength,
92 const UChar *pattern,
93 int32_t patternLength,
94 UErrorCode *status,
95 const Locale &loc, const char */*ver*/) {
96 // TODO: save version
97 //char locBuf[200];
98 //char kwvBuf[200];
99 UDateFormat * uc = OICU_udat_open( timeStyle, dateStyle, locale,
100 tzID,
101 tzIDLength,
102 pattern,
103 patternLength,
104 status);
105 if(U_FAILURE(*status)) return NULL; // TODO: ERR?
106 DateFormat *c = new GLUE_SYM( DateFormat ) ( uc );
107 #if DATE_FE_DEBUG
108 fprintf(stderr, "VCF " ICUGLUE_VER_STR " udat_open=%s ->> %p\n", loc.getName(), (void*)c);
109 #endif
110 return c;
111 }
112
GLUE_SYM(DateFormat)113 UnicodeString& GLUE_SYM (DateFormat ) :: format( Calendar& cal, UnicodeString& appendTo, FieldPosition& pos) const
114 {
115 #if DATE_FE_DEBUG
116 fprintf(stderr, "VCF " ICUGLUE_VER_STR " - formatting. \n");
117 #endif
118 int32_t len = appendTo.length();
119
120 UChar junk[200];
121 UErrorCode status = U_ZERO_ERROR;
122
123 UFieldPosition pos2;
124
125 int32_t nlen = OICU_udat_format(_this,
126 cal.getTime(status),
127 junk,
128 200,
129 &pos2,
130 &status);
131
132 // todo: use pos2
133 pos.setBeginIndex(len);
134 pos.setEndIndex(len += nlen);
135 appendTo.append(junk, nlen);
136
137 return appendTo;
138 }
139
GLUE_SYM(DateFormat)140 void GLUE_SYM (DateFormat ) :: parse( const UnicodeString& text, Calendar& cal, ParsePosition& pos) const
141 {
142 return;
143 }
144
GLUE_SYM(DateFormat)145 Format* GLUE_SYM (DateFormat ) :: clone(void) const
146 {
147 return NULL;
148 }
149
150
151
GLUE_SYM(DateFormat)152 int32_t GLUE_SYM ( DateFormat ) :: countAvailable() {
153 int32_t count = OICU_udat_countAvailable();
154 return count;
155 }
156
157
GLUE_SYM(DateFormat)158 int32_t GLUE_SYM ( DateFormat ) :: 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 DATE_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 strs[i+j].append( ICUGLUE_VER_STR[0] ); // X_y
169 strs[i+j].append( ICUGLUE_VER_STR[2] ); // x_Y
170 #if DATE_FE_DEBUG
171 {
172 char foo[999];
173 const UChar *ss = strs[i+j].getTerminatedBuffer();
174 u_austrcpy(foo, ss);
175 // fprintf(stderr, "VCF " ICUGLUE_VER_STR " appending [%d+%d=%d] <<%s>>\n", i, j, i+j, foo);
176 }
177 #endif
178 }
179 return OICU_ucol_countAvailable();
180 }
181
182 UOBJECT_DEFINE_RTTI_IMPLEMENTATION( GLUE_SYM( DateFormat ) )
183
184
185
186
187 #else
188 /** ==================================== The following code runs inside the 'provider' version (i.e. current ICU) ========== **/
189
190 #if (U_ICU_VERSION_MAJOR_NUM < 49)
191 #define DATE_PROVIDER_UNSUPPORTED
192 #endif
193
194 #ifndef DATE_PROVIDER_UNSUPPORTED
195 // define Collator_XX
196 #include "icuglue/glver.h"
197
198 // generate list of versions
199 static
200 #include <icuglue/fe_verlist.h>
201
202 class VersionDateFormatFactory : public UObject {
203 public:
204 virtual DateFormat *createFormat(UDateFormatStyle timeStyle,
205 UDateFormatStyle dateStyle,
206 const char *locale,
207 const UChar *tzID,
208 int32_t tzIDLength,
209 const UChar *pattern,
210 int32_t patternLength,
211 UErrorCode *status);
212 virtual const UnicodeString *getSupportedIDs(int32_t &count, UErrorCode &status);
213 virtual void* getDynamicClassID() const;
214 static void* getStaticClassID() ;
215 };
216
217 UOBJECT_DEFINE_RTTI_IMPLEMENTATION( VersionDateFormatFactory )
218
219 DateFormat *VersionDateFormatFactory::createFormat(UDateFormatStyle timeStyle,
220 UDateFormatStyle dateStyle,
221 const char *locale,
222 const UChar *tzID,
223 int32_t tzIDLength,
224 const UChar *pattern,
225 int32_t patternLength,
226 UErrorCode *status) {
227 Locale loc(locale);
228 // pull off provider #
229 char provider[200];
230 #if DATE_FE_DEBUG
231 fprintf(stderr, "VCF:CC %s\n", loc.getName());
232 #endif
233 int32_t len = loc.getKeywordValue("sp", provider, 200, *status);
234 if(U_FAILURE(*status)||len==0) return NULL;
235 #if DATE_FE_DEBUG
236 fprintf(stderr, "VCF:KWV> %s/%d\n", u_errorName(*status), len);
237 #endif
238 provider[len]=0;
239 #if DATE_FE_DEBUG
240 fprintf(stderr, "VCF:KWV %s\n", provider);
241 #endif
242 if(strncmp(provider,"icu",3)) return NULL;
243 const char *icuver=provider+3;
244 #if DATE_FE_DEBUG
245 fprintf(stderr, "VCF:ICUV %s\n", icuver);
246 #endif
247
248 #if defined(GLUE_VER)
249 #undef GLUE_VER
250 #endif
251 #define GLUE_VER(x) /*printf("%c/%c|%c/%c\n", icuver[0],(#x)[0],icuver[1],(#x)[2]);*/ if(icuver[0]== (#x)[0] && icuver[1]==(#x)[2]) { DateFormat *c = glue ## DateFormat ## x :: create(timeStyle,dateStyle,locale,tzID,tzIDLength,pattern,patternLength,status,loc,icuver); /*fprintf(stderr, "VCF::CC %s -> %p\n", loc.getName(), c);*/ return c; }
252 #include "icuglue/glver.h"
253 #if DATE_FE_DEBUG
254 fprintf(stderr, "VCF:CC %s failed\n", loc.getName());
255 #endif
256
257 return NULL;
258 }
259
260
261 static const UnicodeString *gLocalesDate = NULL;
262 static int32_t gLocCountDate = 0;
263
264
265 const UnicodeString
266 *VersionDateFormatFactory::getSupportedIDs(int32_t &count, UErrorCode &/*status*/) {
267 if(gLocalesDate==NULL) {
268 count = 0;
269
270
271 /* gather counts */
272
273 #if defined(GLUE_VER)
274 #undef GLUE_VER
275 #endif
276 #define GLUE_VER(x) count += glue ## DateFormat ## x :: countAvailable();
277 #include "icuglue/glver.h"
278
279 #if DATE_FE_DEBUG
280 printf("VCF: count=%d\n", count);
281 #endif
282 UnicodeString *strs = new UnicodeString[count];
283 int32_t i = 0;
284
285 #if defined(GLUE_VER)
286 #undef GLUE_VER
287 #endif
288 #define GLUE_VER(x) i += glue ## DateFormat ## x :: appendAvailable(strs, i, count);
289 #include "icuglue/glver.h"
290
291 #if DATE_FE_DEBUG
292 printf("VCF: appended count=%d\n", count);
293 #endif
294
295 gLocCountDate = count;
296 gLocalesDate = strs;
297 }
298 count = gLocCountDate;
299 return gLocalesDate;
300 }
301
302
303 /* Plugin Code */
304
305 #include <stdio.h>
306 #include <unicode/uversion.h>
307
308 //static URegistryKey rkdate = NULL;
309
310 static VersionDateFormatFactory vdf;
311
312 extern "C" UDateFormat *versionDateFormatOpener(UDateFormatStyle timeStyle,
313 UDateFormatStyle dateStyle,
314 const char *locale,
315 const UChar *tzID,
316 int32_t tzIDLength,
317 const UChar *pattern,
318 int32_t patternLength,
319 UErrorCode *status) {
320 DateFormat *df = vdf.createFormat(timeStyle,dateStyle,locale,tzID,tzIDLength,pattern,patternLength,status);
321 // printf("Hey! I got: %s -> %p\n", locale, df);
322 return (UDateFormat*)df;
323 }
324
325 void date_provider_register(UErrorCode &status) {
326 udat_registerOpener(versionDateFormatOpener, &status);
327 // rkdate = DateFormat::registerFactory(new VersionDateFormatFactory(), status);
328 }
329
330 void date_provider_unregister(UErrorCode &status) {
331 udat_unregisterOpener(versionDateFormatOpener, &status);
332 }
333
334 #else
335
336 /* no op- this ICU doesn't support date providers */
337
338 void date_provider_register(UErrorCode &) {
339 // not supported
340 }
341
342 void date_provider_unregister(UErrorCode &) {
343 // not supported
344 }
345
346 #endif
347
348 /* Plugin- only ICU 4.4+ */
349 #if (U_ICU_VERSION_MAJOR_NUM > 4) || ((U_ICU_VERSION_MAJOR_NUM==4)&&(U_ICU_VERSION_MINOR_NUM>3))
350 #include "unicode/icuplug.h"
351
352 U_CAPI UPlugTokenReturn U_EXPORT2 date_provider_plugin (UPlugData *data, UPlugReason reason, UErrorCode *status);
353
354 U_CAPI UPlugTokenReturn U_EXPORT2 date_provider_plugin (UPlugData *data, UPlugReason reason, UErrorCode *status)
355 {
356 switch(reason) {
357 case UPLUG_REASON_QUERY:
358 uplug_setPlugName(data, "Date Provider Plugin");
359 uplug_setPlugLevel(data, UPLUG_LEVEL_HIGH);
360 break;
361 case UPLUG_REASON_LOAD:
362 date_provider_register(*status);
363 break;
364 case UPLUG_REASON_UNLOAD:
365 date_provider_unregister(*status);
366 break;
367 default:
368 break; /* not handled */
369 }
370 return UPLUG_TOKEN;
371 }
372 #else
373
374 /*
375 Note: this ICU version must explicitly call 'date_provider_plugin'
376 */
377
378 #endif /* plugin */
379
380 #endif /* provider side (vs target) */
381