• 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 
12 #ifndef COLL_FE_DEBUG
13 #define COLL_FE_DEBUG 0
14 #endif
15 
16 #include <icuglue/icuglue.h>
17 #include <unicode/coll.h>
18 //#include <unicode/tblcoll.h>
19 #include <unicode/ucol.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include "unicode/ustring.h"
23 
24 #if COLL_FE_DEBUG
25 #define debugfprintf(x) fprintf x
26 #else
27 #define debugfprintf(x)
28 #endif
29 
30 /*
31  * Before ICU 50.0.2 (50m2) - there was a different collator signature.
32  * see: ticket:9460 ticket:9346
33  */
34 #if (U_ICU_VERSION_MAJOR_NUM < 50) || ((U_ICU_VERSION_MAJOR_NUM==50)&&(U_ICU_VERSION_MINOR_NUM==0)&&(U_ICU_VERSION_PATCHLEVEL_NUM<2))
35 #define PRE_50_0_2_COLLATOR
36 #define CONST_BEFORE_50_0_2 const
37 #define CONST_AFTER_50_0_2
38 #define REF_AFTER_50_0_2
39 #else
40 /* "current" API */
41 #define CONST_BEFORE_50_0_2
42 #define CONST_AFTER_50_0_2 const
43 #define REF_AFTER_50_0_2 &
44 #endif
45 
46 /**
47  * Macro to define the Collator_glue_4_2 class
48  */
49 #define GLUE_VER(x) class GLUE_SYM_V( Collator, x ) : public Collator {  \
50     \
51   public:  static Collator *create(const Locale &loc, const char *ver); \
52   private: UCollator *_this; GLUE_SYM_V( Collator, x ) ( UCollator* tn ) : _this(tn){} \
53     virtual ~ GLUE_SYM_V ( Collator, x) ();                             \
54   public:                                                               \
55     virtual void* getDynamicClassID() const;                            \
56     static void* getStaticClassID() ;                                   \
57     virtual Collator* clone() const;                                    \
58     virtual UCollationResult compare(const UnicodeString&, const UnicodeString&, UErrorCode&) const; \
59     virtual UCollationResult compare(const UnicodeString&, const UnicodeString&, int32_t, UErrorCode&) const; \
60     virtual UCollationResult compare(const UChar*, int32_t, const UChar*, int32_t, UErrorCode&) const; \
61     virtual CollationKey& getCollationKey(const UnicodeString&, CollationKey&, UErrorCode&) const; \
62     virtual CollationKey& getCollationKey(const UChar*, int32_t, CollationKey&, UErrorCode&) const; \
63     virtual int32_t hashCode() const;                                   \
64     virtual CONST_BEFORE_50_0_2 Locale getLocale(ULocDataLocaleType, UErrorCode&) const; \
65     virtual ECollationStrength getStrength() const;                     \
66     virtual void setStrength(ECollationStrength);                       \
67     virtual void getVersion(uint8_t*) const;                            \
68     virtual void setAttribute(UColAttribute, UColAttributeValue, UErrorCode&) ; \
69     virtual UColAttributeValue getAttribute(UColAttribute, UErrorCode&) CONST_AFTER_50_0_2; \
70     virtual uint32_t setVariableTop(const UChar*, int32_t, UErrorCode&); \
71     virtual uint32_t setVariableTop(const UnicodeString REF_AFTER_50_0_2, UErrorCode&);        \
72     virtual void setVariableTop(uint32_t, UErrorCode&);                 \
73     virtual uint32_t getVariableTop(UErrorCode&) const;                 \
74     virtual Collator* safeClone() CONST_AFTER_50_0_2 ;                                      \
75     virtual int32_t getSortKey(const UnicodeString&, uint8_t*, int32_t) const; \
76     virtual int32_t getSortKey(const UChar*, int32_t, uint8_t*, int32_t) const; \
77   public: static int32_t countAvailable();                              \
78   public: static int32_t appendAvailable(UnicodeString* strs, int32_t i, int32_t count); \
79   public: virtual int32_t internalGetShortDefinitionString(const char *locale, char *buffer, int32_t capacity, UErrorCode &status) const; \
80   };
81 
82 /** ==================================== The following code runs inside the 'target' version (i.e. old ICU) ========== **/
83 #if defined ( ICUGLUE_VER )
84 
85 
86 // these from tblcoll.h
_getECollationStrength(const UCollationStrength & strength)87 static Collator::ECollationStrength _getECollationStrength(
88                                        const UCollationStrength &strength)
89 {
90     switch (strength)
91     {
92     case UCOL_PRIMARY :
93         return Collator::PRIMARY;
94     case UCOL_SECONDARY :
95         return Collator::SECONDARY;
96     case UCOL_TERTIARY :
97         return Collator::TERTIARY;
98     case UCOL_QUATERNARY :
99         return Collator::QUATERNARY;
100     default :
101         return Collator::IDENTICAL;
102     }
103 }
104 
_getUCollationStrength(const Collator::ECollationStrength & strength)105 static UCollationStrength _getUCollationStrength(
106                              const Collator::ECollationStrength &strength)
107 {
108     switch (strength)
109     {
110     case Collator::PRIMARY :
111         return UCOL_PRIMARY;
112     case Collator::SECONDARY :
113         return UCOL_SECONDARY;
114     case Collator::TERTIARY :
115         return UCOL_TERTIARY;
116     case Collator::QUATERNARY :
117         return UCOL_QUATERNARY;
118     default :
119         return UCOL_IDENTICAL;
120     }
121 }
122 
123 
124 
125 /* code for some version */
126 #include <icuglue/gluren.h>
127 
128 #include "oicu.h"
129 
130 /* Expand GLUE_VER to define the class */
131 #ifdef GLUE_VER
132 GLUE_VER( ICUGLUE_VER )
133 #endif
134 
GLUE_SYM(Collator)135 GLUE_SYM ( Collator ) :: ~ GLUE_SYM(Collator) () {
136 #if COLL_FE_DEBUG
137     fprintf(stderr, "VCF " ICUGLUE_VER_STR " ucol_close");
138 #endif
139     OICU_ucol_close(_this);
140 }
141 
142 #if 0
143 U_CFUNC int32_t U_CALLCONV
144 GLUE_SYM ( glue_calcSortKey) (const    UCollator    *coll,
145         const    UChar        *source,
146         int32_t        sourceLength,
147         uint8_t        **result,
148         uint32_t        resultLength,
149         UBool allocateSKBuffer,
150         UErrorCode *status);
151 
152 #endif
153 
154 Collator *
GLUE_SYM(Collator)155 GLUE_SYM ( Collator ) :: create (const Locale &loc, const char */*ver*/) {
156   // TODO: save 'ver' off.
157     UErrorCode status = U_ZERO_ERROR;
158     char locBuf[200];
159     char kwvBuf[200];
160     int32_t len = loc.getKeywordValue("collation", kwvBuf, 200, status);
161     strcpy(locBuf,loc.getBaseName());
162     if(len>0) {
163         strcat(locBuf,"@collator=");
164         strcat(locBuf,kwvBuf);
165     }
166     UCollator * uc =  OICU_ucol_open( locBuf, status);
167     if(U_FAILURE(status)) return NULL; // TODO: ERR?
168     Collator *c =  new GLUE_SYM( Collator ) ( uc );
169 #if COLL_FE_DEBUG
170     fprintf(stderr, "VCF " ICUGLUE_VER_STR " ucol_open=%s ->> %p\n", locBuf, c);
171 #endif
172     return c;
173 }
174 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(GLUE_SYM (Collator))175 UOBJECT_DEFINE_RTTI_IMPLEMENTATION( GLUE_SYM( Collator ) )
176 
177 Collator* GLUE_SYM ( Collator ) :: clone() const  {
178     UErrorCode status = U_ZERO_ERROR;
179 #if COLL_FE_DEBUG
180     fprintf(stderr, "VCF " ICUGLUE_VER_STR " clone %p -> " , this);
181 #endif
182     UCollator *clc = OICU_ucol_safeClone( _this, NULL, 0, &status);
183 #if COLL_FE_DEBUG
184     fprintf(stderr, "VCF " ICUGLUE_VER_STR " .. safeclone %s _this %p-> %p " , u_errorName(status), _this, clc);
185 #endif
186     if(U_FAILURE(status)||clc==NULL) return NULL;
187     Collator *c = new GLUE_SYM( Collator ) ( clc );
188 #if COLL_FE_DEBUG
189     fprintf(stderr, "VCF " ICUGLUE_VER_STR " .. wrap(%p) -> %p\n", clc, c);
190 #endif
191 
192     return c;
193 }
194 
195 
GLUE_SYM(Collator)196 UCollationResult GLUE_SYM ( Collator ) :: compare(const UnicodeString&, const UnicodeString&, UErrorCode&) const  {
197     return (UCollationResult)0;
198 }
199 
200 
GLUE_SYM(Collator)201 UCollationResult GLUE_SYM ( Collator ) :: compare(const UnicodeString&, const UnicodeString&, int32_t, UErrorCode&) const  {
202     return (UCollationResult)0;
203 }
204 
205 
GLUE_SYM(Collator)206 UCollationResult GLUE_SYM ( Collator ) :: compare(const UChar* s, int32_t sl, const UChar* d , int32_t dl, UErrorCode&/*e*/ ) const  {
207     return OICU_ucol_strcoll(_this, s, sl, d, dl);
208 }
209 
210 #include "unicode/sortkey.h"
211 
212 static CollationKey kk;
213 
GLUE_SYM(Collator)214 CollationKey& GLUE_SYM ( Collator ) :: getCollationKey(const UnicodeString&, CollationKey&, UErrorCode&) const  {
215   //#if COLL_FE_DEBUG
216     fprintf(stderr,  "VCF " ICUGLUE_VER_STR " GCK - notimp");
217     //#endif
218 return kk;
219 }
220 
221 
GLUE_SYM(Collator)222 CollationKey& GLUE_SYM ( Collator ) :: getCollationKey(const UChar*, int32_t, CollationKey&, UErrorCode&) const  {
223     fprintf(stderr,  "VCF " ICUGLUE_VER_STR " GKK2 - notimp");
224 return kk;
225 }
226 
227 
GLUE_SYM(Collator)228 int32_t GLUE_SYM ( Collator ) :: hashCode() const  {
229     return 0;
230 }
231 
232 
GLUE_SYM(Collator)233 CONST_BEFORE_50_0_2 Locale GLUE_SYM ( Collator ) :: getLocale(ULocDataLocaleType, UErrorCode&) const  {
234     return Locale();
235 }
236 
237 
238 Collator::ECollationStrength
GLUE_SYM(Collator)239  GLUE_SYM ( Collator ) :: getStrength() const  {
240     return _getECollationStrength(OICU_ucol_getStrength(_this));
241 }
242 
243 
GLUE_SYM(Collator)244 void GLUE_SYM ( Collator ) :: setStrength(ECollationStrength s)  {
245     OICU_ucol_setStrength(_this, _getUCollationStrength(s));
246 }
247 
248 
GLUE_SYM(Collator)249 void GLUE_SYM ( Collator ) :: getVersion(uint8_t*) const  {
250 }
251 
252 
GLUE_SYM(Collator)253 void GLUE_SYM ( Collator ) :: setAttribute(UColAttribute, UColAttributeValue, UErrorCode&) {
254 }
255 
256 
GLUE_SYM(Collator)257 UColAttributeValue GLUE_SYM ( Collator ) :: getAttribute(UColAttribute, UErrorCode&) CONST_AFTER_50_0_2 {
258 return (UColAttributeValue)0;
259 }
260 
261 
GLUE_SYM(Collator)262 uint32_t GLUE_SYM ( Collator ) :: setVariableTop(const UChar*, int32_t, UErrorCode&)  {
263 return 0;
264 }
265 
266 
GLUE_SYM(Collator)267 uint32_t GLUE_SYM ( Collator ) :: setVariableTop(const UnicodeString REF_AFTER_50_0_2, UErrorCode&)  {
268 return 0;
269 }
270 
271 
GLUE_SYM(Collator)272 void GLUE_SYM ( Collator ) :: setVariableTop(uint32_t, UErrorCode&)  {
273 }
274 
275 
GLUE_SYM(Collator)276 uint32_t GLUE_SYM ( Collator ) :: getVariableTop(UErrorCode&) const  {
277 return 0;
278 }
279 
280 
GLUE_SYM(Collator)281 Collator* GLUE_SYM ( Collator ) :: safeClone() CONST_AFTER_50_0_2 {
282     return clone();
283 }
284 
285 
GLUE_SYM(Collator)286 int32_t GLUE_SYM ( Collator ) :: getSortKey(const UnicodeString& s, uint8_t*buf, int32_t len) const  {
287 #if COLL_FE_DEBUG
288   fprintf(stderr,  "VCF " ICUGLUE_VER_STR " GSK");
289 #endif
290     return getSortKey(s.getBuffer(),s.length(), buf, len);
291 }
292 
293 
294 
295 
GLUE_SYM(Collator)296 int32_t GLUE_SYM ( Collator ) :: getSortKey(const UChar*s, int32_t l, uint8_t*d, int32_t b) const  {
297 #if COLL_FE_DEBUG
298     fprintf(stderr,  "VCF " ICUGLUE_VER_STR " GKS");
299 #endif
300     return OICU_ucol_getSortKey(_this, s,l,d,b);
301 }
302 
GLUE_SYM(Collator)303 int32_t GLUE_SYM (Collator ) ::  internalGetShortDefinitionString(const char *locale, char *buffer, int32_t capacity, UErrorCode &status) const {
304   if(U_FAILURE(status)) return 0;
305   int32_t intRes = OICU_ucol_getShortDefinitionString(_this, locale, buffer, capacity, &status);
306   int32_t newRes = (intRes += 7); /* _PICU38 */
307   int32_t remainCap = capacity - newRes;
308 
309   if(remainCap < 0 && U_SUCCESS(status)) {
310     status = U_BUFFER_OVERFLOW_ERROR; /* ran out of space on our watch */
311   }
312   if(U_SUCCESS(status)) {
313     char *p = buffer+strlen(buffer);
314     strncat(p,"_PICU",5);
315     p +=5 ;
316     CPY_VERSTR(p, ICUGLUE_VER_STR);
317     p +=2;
318     if(remainCap>0) {
319       *(p++)=0;
320     }
321   }
322   return newRes;
323 }
324 
325 
326 
GLUE_SYM(Collator)327  int32_t GLUE_SYM ( Collator ) :: countAvailable() {
328     int32_t count =  OICU_ucol_countAvailable();
329     return count;
330  }
331 
332 
GLUE_SYM(Collator)333 int32_t GLUE_SYM ( Collator ) :: appendAvailable(UnicodeString* strs, int32_t i, int32_t /*count*/) {
334    int avail = OICU_ucol_countAvailable();
335    UErrorCode status = U_ZERO_ERROR;
336    OICU_u_init(&status);
337 #if COLL_FE_DEBUG
338    fprintf(stderr,  "VCF " ICUGLUE_VER_STR " avail %d - init %s\n", avail, u_errorName(status));
339 #endif
340     for(int j=0;j<avail;j++) {
341          strs[i+j].append(OICU_ucol_getAvailable(j));
342          strs[i+j].append("@sp=icu");
343 
344          if(IS_OLD_VERSTR(ICUGLUE_VER_STR)) {
345            strs[i+j].append( ICUGLUE_VER_STR[OLD_VERSTR_MAJ] );  // X_y
346            strs[i+j].append( ICUGLUE_VER_STR[OLD_VERSTR_MIN] );  // x_Y
347          } else {
348            strs[i+j].append( ICUGLUE_VER_STR[NEW_VERSTR_MAJ] );  // Xy_
349            strs[i+j].append( ICUGLUE_VER_STR[NEW_VERSTR_MIN] );  // xY_
350          }
351 
352 #if COLL_FE_DEBUG
353          {
354             char foo[999];
355             const UChar *ss = strs[i+j].getTerminatedBuffer();
356             u_austrcpy(foo, ss);
357             debugfprintf((stderr,  "VCF " ICUGLUE_VER_STR " appending [%d+%d=%d] <<%s>>\n", i, j, i+j, foo));
358         }
359 #endif
360     }
361     return OICU_ucol_countAvailable();
362  }
363 
364 
365 
366 #else
367 /** ==================================== The following code runs inside the 'provider' version (i.e. current ICU) ========== **/
368 
369 // define Collator_XX
370 #include "icuglue/glver.h"
371 
372 // generate list of versions
373 static
374 #include <icuglue/fe_verlist.h>
375 
376 class VersionCollatorFactory : public CollatorFactory {
377 public:
378   virtual Collator *createCollator(const Locale &loc);
379   virtual const UnicodeString *getSupportedIDs(int32_t &count, UErrorCode &status);
380   virtual void* getDynamicClassID() const;
381   static void* getStaticClassID() ;
382 };
383 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(VersionCollatorFactory)384 UOBJECT_DEFINE_RTTI_IMPLEMENTATION( VersionCollatorFactory )
385 
386 Collator *VersionCollatorFactory::createCollator(const Locale &loc) {
387     // pull off provider #
388     char provider[200];
389     UErrorCode status = U_ZERO_ERROR;
390 #if COLL_FE_DEBUG
391     fprintf(stderr,  "VCF:CC %s\n", loc.getName());
392 #endif
393     int32_t len = loc.getKeywordValue("sp", provider, 200, status);
394     if(U_FAILURE(status)||len==0) return NULL;
395 #if COLL_FE_DEBUG
396     fprintf(stderr,  "VCF:KWV> %s/%d\n", u_errorName(status), len);
397 #endif
398     provider[len]=0;
399 #if COLL_FE_DEBUG
400     fprintf(stderr,  "VCF:KWV %s\n", provider);
401 #endif
402     if(strncmp(provider,"icu",3)) return NULL;
403     const char *icuver=provider+3;
404 #if COLL_FE_DEBUG
405     fprintf(stderr,  "VCF:ICUV %s\n", icuver);
406 #endif
407 
408 #if defined(GLUE_VER)
409 #undef GLUE_VER
410 #endif
411 
412 #define GLUE_VER(x) \
413     debugfprintf((stderr,"%c/%c|%c/%c\n", icuver[0],(#x)[0],icuver[1],(#x)[2]));  \
414     if(CMP_VERSTR(icuver, (#x))) {                                      \
415       Collator *c = glue ## Collator ## x :: create(loc, icuver); \
416       debugfprintf((stderr, "VCF::CC %s -> %p\n", loc.getName(), c)); \
417       return c; \
418     }
419 
420 #include "icuglue/glver.h"
421 #if COLL_FE_DEBUG
422     fprintf(stderr,  "VCF:CC %s failed\n", loc.getName());
423 #endif
424 
425     return NULL;
426 }
427 
428 
429 static const UnicodeString *gLocales = NULL;
430 static  int32_t gLocCount = 0;
431 
432 const UnicodeString
getSupportedIDs(int32_t & count,UErrorCode &)433 *VersionCollatorFactory::getSupportedIDs(int32_t &count, UErrorCode &/*status*/) {
434   if(gLocales==NULL) {
435     count = 0;
436 
437 
438     /* gather counts */
439 #if defined(GLUE_VER)
440 #undef GLUE_VER
441 #endif
442 #define GLUE_VER(x) count += glue ## Collator ## x :: countAvailable();
443 #include "icuglue/glver.h"
444 
445 #if COLL_FE_DEBUG
446     printf("VCF: count=%d\n", count);
447 #endif
448     UnicodeString *strs = new  UnicodeString[count];
449     int32_t i = 0;
450 
451 #if defined(GLUE_VER)
452 #undef GLUE_VER
453 #endif
454 #define GLUE_VER(x) i += glue ## Collator ## x :: appendAvailable(strs, i, count);
455 #include "icuglue/glver.h"
456 
457 #if COLL_FE_DEBUG
458     printf("VCF: appended count=%d\n", count);
459 #endif
460 
461     gLocCount = count;
462     gLocales = strs;
463   }
464   count = gLocCount;
465   return gLocales;
466 }
467 
468 
469 /* Plugin Code */
470 
471 #include <stdio.h>
472 #include <unicode/uversion.h>
473 
474 static URegistryKey rk = NULL;
475 
coll_provider_register(UErrorCode & status)476 void coll_provider_register(UErrorCode &status) {
477   rk = Collator::registerFactory(new VersionCollatorFactory(), status);
478 }
479 
coll_provider_unregister(UErrorCode & status)480 void coll_provider_unregister(UErrorCode &status) {
481   Collator::unregister(rk, status);
482 }
483 
484 /* Plugin- only ICU 4.4+ */
485 #if (U_ICU_VERSION_MAJOR_NUM > 4) || ((U_ICU_VERSION_MAJOR_NUM==4)&&(U_ICU_VERSION_MINOR_NUM>3))
486 #include "unicode/icuplug.h"
487 
488 U_CAPI UPlugTokenReturn U_EXPORT2 coll_provider_plugin (UPlugData *data, UPlugReason reason, UErrorCode *status);
489 
coll_provider_plugin(UPlugData * data,UPlugReason reason,UErrorCode * status)490 U_CAPI UPlugTokenReturn U_EXPORT2 coll_provider_plugin (UPlugData *data, UPlugReason reason, UErrorCode *status)
491 {
492   switch(reason) {
493   case UPLUG_REASON_QUERY:
494     uplug_setPlugName(data, "Collation Provider Plugin");
495     uplug_setPlugLevel(data, UPLUG_LEVEL_HIGH);
496     break;
497   case UPLUG_REASON_LOAD:
498     coll_provider_register(*status);
499     break;
500   case UPLUG_REASON_UNLOAD:
501     coll_provider_unregister(*status);
502     break;
503   default:
504     break; /* not handled */
505   }
506   return UPLUG_TOKEN;
507 }
508 #else
509 
510 /*
511    Note: this ICU version must explicitly call 'coll_provider_plugin'
512 */
513 
514 #endif /* plugin */
515 
516 #endif /* provider side (vs target) */
517