| /* |
| ******************************************************************************* |
| * |
| * Copyright (C) 2009-2012, International Business Machines |
| * Corporation and others. All Rights Reserved. |
| * |
| ******************************************************************************* |
| */ |
| #define CAL_FE_DEBUG 1 |
| |
| #ifndef CAL_FE_DEBUG |
| #define CAL_FE_DEBUG 0 |
| #endif |
| |
| #if CAL_FE_DEBUG |
| #define debugfprintf(x) fflush(stderr),fflush(stdout),fprintf x,fflush(stderr),fflush(stdout) |
| #else |
| #define debugfprintf(x) |
| #endif |
| |
| #include <icuglue/icuglue.h> |
| #include "unicode/ucal.h" |
| //#include <unicode/tblcoll.h> |
| #include "unicode/calendar.h" |
| #include <string.h> |
| #include <stdio.h> |
| #include "unicode/ustring.h" |
| #include "unicode/gregocal.h" |
| |
| |
| |
| /** |
| * Macro to define the Calendar_glue_4_2 class |
| */ |
| #ifdef GLUE_VER |
| #error GLUE_VER is defined |
| #endif |
| |
| #define GLUE_VER(x) class GLUE_SYM_V( Calendar, x ) : public Calendar { \ |
| public: /* static create */ \ |
| UCalendar *_this; GLUE_SYM_V( Calendar, x ) ( const Locale&, UErrorCode& ); \ |
| private: \ |
| virtual ~ GLUE_SYM_V ( Calendar, x) (); \ |
| public: \ |
| virtual void* getDynamicClassID() const; \ |
| static void* getStaticClassID() ; \ |
| /* overrides */ \ |
| virtual UBool haveDefaultCentury() const; \ |
| virtual UDate defaultCenturyStart() const ; \ |
| virtual int32_t handleGetExtendedYear() ; \ |
| virtual const char * getType() const ; \ |
| virtual UBool inDaylightTime(UErrorCode& status) const ; \ |
| virtual int32_t defaultCenturyStartYear() const ; \ |
| virtual int32_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const ; \ |
| virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const ; \ |
| virtual Calendar* clone(void) const; \ |
| public: static int32_t countAvailable(); \ |
| public: static int32_t appendAvailable(UnicodeString* strs, int32_t i, int32_t count); \ |
| }; |
| |
| |
| /** ==================================== The following code runs inside the 'target' version (i.e. old ICU) ========== **/ |
| #if defined ( ICUGLUE_VER ) |
| |
| /* code for some version */ |
| #include <icuglue/gluren.h> |
| #include "oicu.h" |
| |
| #ifdef GLUE_VER |
| GLUE_VER( ICUGLUE_VER ) |
| #endif |
| |
| GLUE_SYM (Calendar ) :: GLUE_SYM(Calendar) ( const Locale& loc, UErrorCode& status ) : |
| Calendar(status), _this(NULL) |
| { |
| |
| _this = OICU_ucal_open(NULL, -1, /*locale*/NULL, UCAL_DEFAULT, &status); |
| |
| // copy some things over |
| setMinimalDaysInFirstWeek(OICU_ucal_getAttribute(_this, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK)); |
| setFirstDayOfWeek((UCalendarDaysOfWeek)OICU_ucal_getAttribute(_this, UCAL_FIRST_DAY_OF_WEEK)); |
| } |
| |
| GLUE_SYM ( Calendar ) :: ~ GLUE_SYM(Calendar) () { |
| #if CAL_FE_DEBUG |
| fprintf(stderr, "VCF " ICUGLUE_VER_STR " ucal_close"); |
| #endif |
| OICU_ucal_close(_this); |
| } |
| |
| |
| UBool GLUE_SYM ( Calendar ) :: haveDefaultCentury() const { |
| return FALSE; |
| } |
| UDate GLUE_SYM ( Calendar ) :: defaultCenturyStart() const { |
| return 0L; |
| } |
| int32_t GLUE_SYM ( Calendar ) :: handleGetExtendedYear() { |
| return 0; |
| } |
| const char * GLUE_SYM ( Calendar ) :: getType() const { |
| return "dilbert"; |
| } |
| UBool GLUE_SYM ( Calendar ) :: inDaylightTime(UErrorCode& status) const { |
| return FALSE; |
| } |
| int32_t GLUE_SYM ( Calendar ) :: defaultCenturyStartYear() const { |
| return 2012; |
| } |
| int32_t GLUE_SYM ( Calendar ) :: handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const { |
| return 0; |
| } |
| |
| int32_t GLUE_SYM ( Calendar ) :: handleGetLimit(UCalendarDateFields field, ELimitType limitType) const { |
| return 1; |
| } |
| Calendar* GLUE_SYM ( Calendar ) :: clone(void) const { |
| return NULL; |
| } |
| |
| |
| // DateFormat * |
| // GLUE_SYM ( DateFormat ) :: create(UDateFormatStyle timeStyle, |
| // UDateFormatStyle dateStyle, |
| // const char *locale, |
| // const UChar *tzID, |
| // int32_t tzIDLength, |
| // const UChar *pattern, |
| // int32_t patternLength, |
| // UErrorCode *status, |
| // const Locale &loc, const char */*ver*/) { |
| // // TODO: save version |
| // //char locBuf[200]; |
| // //char kwvBuf[200]; |
| // UDateFormat * uc = OICU_udat_open( timeStyle, dateStyle, locale, |
| // tzID, |
| // tzIDLength, |
| // pattern, |
| // patternLength, |
| // status); |
| // if(U_FAILURE(*status)) return NULL; // TODO: ERR? |
| // DateFormat *c = new GLUE_SYM( DateFormat ) ( uc ); |
| // #if CAL_FE_DEBUG |
| // fprintf(stderr, "VCF " ICUGLUE_VER_STR " udat_open=%s ->> %p\n", loc.getName(), (void*)c); |
| // #endif |
| // return c; |
| // } |
| |
| |
| int32_t GLUE_SYM ( Calendar ) :: countAvailable() { |
| int32_t count = OICU_udat_countAvailable(); |
| return count; |
| } |
| |
| |
| int32_t GLUE_SYM ( Calendar ) :: appendAvailable(UnicodeString* strs, int32_t i, int32_t /*count*/) { |
| int avail = OICU_udat_countAvailable(); |
| UErrorCode status = U_ZERO_ERROR; |
| OICU_u_init(&status); |
| #if CAL_FE_DEBUG |
| fprintf(stderr, "VCF " ICUGLUE_VER_STR " avail %d - init %s\n", avail, u_errorName(status)); |
| #endif |
| for(int j=0;j<avail;j++) { |
| strs[i+j].append(OICU_udat_getAvailable(j)); |
| strs[i+j].append("@sp=icu"); |
| if(IS_OLD_VERSTR(ICUGLUE_VER_STR)) { |
| strs[i+j].append( ICUGLUE_VER_STR[OLD_VERSTR_MAJ] ); // X_y |
| strs[i+j].append( ICUGLUE_VER_STR[OLD_VERSTR_MIN] ); // x_Y |
| } else { |
| strs[i+j].append( ICUGLUE_VER_STR[NEW_VERSTR_MAJ] ); // Xy_ |
| strs[i+j].append( ICUGLUE_VER_STR[NEW_VERSTR_MIN] ); // xY_ |
| } |
| #if CAL_FE_DEBUG |
| { |
| char foo[999]; |
| const UChar *ss = strs[i+j].getTerminatedBuffer(); |
| u_austrcpy(foo, ss); |
| fprintf(stderr, "VCF " ICUGLUE_VER_STR " appending [%d+%d=%d] <<%s>>\n", i, j, i+j, foo); |
| } |
| #endif |
| } |
| return OICU_ucol_countAvailable(); |
| } |
| |
| UOBJECT_DEFINE_RTTI_IMPLEMENTATION( GLUE_SYM( Calendar ) ) |
| |
| |
| |
| |
| #else |
| /** ==================================== The following code runs inside the 'provider' version (i.e. current ICU) ========== **/ |
| |
| // #if (U_ICU_VERSION_MAJOR_NUM < 49) |
| // #define CAL_PROVIDER_UNSUPPORTED |
| // #endif |
| |
| #ifndef CAL_PROVIDER_UNSUPPORTED |
| // define Collator_XX |
| #include "icuglue/glver.h" |
| |
| #include "servloc.h" |
| |
| // generate list of versions |
| static |
| #include <icuglue/fe_verlist.h> |
| |
| class VersionCalendarFactory : public LocaleKeyFactory { |
| public: |
| VersionCalendarFactory(); |
| virtual UObject* handleCreate(const Locale &loc, int32_t kind, const ICUService* service, UErrorCode& status) const; |
| // virtual Calendar *createFormat(UCalendarStyle timeStyle, |
| // UCalendarStyle dateStyle, |
| // const char *locale, |
| // const UChar *tzID, |
| // int32_t tzIDLength, |
| // const UChar *pattern, |
| // int32_t patternLength, |
| // UErrorCode *status); |
| virtual void* getDynamicClassID() const; |
| static void* getStaticClassID() ; |
| virtual const Hashtable* getSupportedIDs(UErrorCode& status) const; |
| private: |
| const UnicodeString *getSupportedIDs(int32_t &count, UErrorCode &status) const; |
| |
| public: |
| virtual UObject* |
| create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const ; |
| |
| }; |
| |
| UOBJECT_DEFINE_RTTI_IMPLEMENTATION( VersionCalendarFactory ) |
| |
| UObject* |
| VersionCalendarFactory::create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const { |
| // UnicodeString id; |
| // key.currentID(id); |
| // Locale l(id); |
| Locale l; |
| const LocaleKey& lkey = (LocaleKey&)key; |
| lkey.currentLocale(l); |
| debugfprintf((stderr, "VCalF::create() .. %s err=%s\n", (const char*)l.getName(), u_errorName(status))); |
| |
| char kw[100]; |
| int32_t kwlen = l.getKeywordValue("sp", kw, 100, status); |
| |
| UObject *f; |
| if(kwlen>0) { |
| debugfprintf((stderr, "Trying for kw=%s\n", kw)); |
| f = handleCreate(l, -1, service, status); |
| } else { |
| f = LocaleKeyFactory::create(key,service,status); |
| } |
| |
| |
| |
| debugfprintf((stderr, "VCalF::create() .. = %p err=%s\n", (void*)f, u_errorName(status))); |
| return f; |
| } |
| |
| VersionCalendarFactory::VersionCalendarFactory() :LocaleKeyFactory(LocaleKeyFactory::VISIBLE){ |
| #if CAL_FE_DEBUG |
| printf("VCalF: hi! pid=%d, this=%p\n", getpid(), (void*)this); |
| #endif |
| } |
| UObject* VersionCalendarFactory::handleCreate(const Locale &loc, int32_t kind, const ICUService* service, UErrorCode& status) const { |
| //Locale loc(locale); |
| // pull off provider # |
| char provider[200]; |
| #if CAL_FE_DEBUG |
| fprintf(stderr, "VCalF:CC %s\n", loc.getName()); |
| #endif |
| int32_t len = loc.getKeywordValue("sp", provider, 200, status); |
| if(U_FAILURE(status)||len==0) return NULL; |
| #if CAL_FE_DEBUG |
| fprintf(stderr, "VCalF:KWV> %s/%d\n", u_errorName(status), len); |
| #endif |
| provider[len]=0; |
| #if CAL_FE_DEBUG |
| fprintf(stderr, "VCalF:KWV %s\n", provider); |
| #endif |
| if(strncmp(provider,"icu",3)) return NULL; |
| const char *icuver=provider+3; |
| #if CAL_FE_DEBUG |
| fprintf(stderr, "VCalF:ICUV %s\n", icuver); |
| #endif |
| |
| #if defined(GLUE_VER) |
| #undef GLUE_VER |
| #endif |
| #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; } |
| #include "icuglue/glver.h" |
| #if CAL_FE_DEBUG |
| fprintf(stderr, "VCalF:CC %s failed\n", loc.getName()); |
| #endif |
| |
| return NULL; |
| } |
| |
| |
| static const UnicodeString *gLocalesDate = NULL; |
| static int32_t gLocCountDate = 0; |
| |
| const Hashtable *VersionCalendarFactory::getSupportedIDs (UErrorCode& status) const { |
| // from coll.cpp |
| Hashtable *_ids = NULL; |
| if (U_SUCCESS(status)) { |
| int32_t count = 0; |
| _ids = new Hashtable(status); |
| if (_ids) { |
| const UnicodeString * idlist = /* _delegate -> */ getSupportedIDs(count, status); |
| for (int i = 0; i < count; ++i) { |
| _ids->put(idlist[i], (void*)this, status); |
| if (U_FAILURE(status)) { |
| delete _ids; |
| _ids = NULL; |
| return; |
| } |
| } |
| } else { |
| status = U_MEMORY_ALLOCATION_ERROR; |
| } |
| debugfprintf((stderr,"VCalF: hash=%p, count=%d, err=%s\n", (void*)_ids, count, u_errorName(status))); |
| } |
| return _ids; |
| } |
| |
| const UnicodeString |
| *VersionCalendarFactory::getSupportedIDs(int32_t &count, UErrorCode &/*status*/) const { |
| if(gLocalesDate==NULL) { |
| count = 0; |
| |
| |
| /* gather counts */ |
| |
| #if defined(GLUE_VER) |
| #undef GLUE_VER |
| #endif |
| #define GLUE_VER(x) count += glue ## Calendar ## x :: countAvailable(); |
| #include "icuglue/glver.h" |
| |
| #if CAL_FE_DEBUG |
| printf("VCalF: count=%d\n", count); |
| #endif |
| UnicodeString *strs = new UnicodeString[count]; |
| int32_t i = 0; |
| |
| #if defined(GLUE_VER) |
| #undef GLUE_VER |
| #endif |
| #define GLUE_VER(x) i += glue ## Calendar ## x :: appendAvailable(strs, i, count); |
| #include "icuglue/glver.h" |
| |
| #if CAL_FE_DEBUG |
| printf("VCalF: appended count=%d\n", count); |
| #endif |
| |
| gLocCountDate = count; |
| gLocalesDate = strs; |
| } |
| count = gLocCountDate; |
| return gLocalesDate; |
| } |
| |
| |
| /* Plugin Code */ |
| |
| #include <stdio.h> |
| #include <unicode/uversion.h> |
| |
| static URegistryKey rkcal = NULL; |
| |
| void cal_provider_register(UErrorCode &status) { |
| debugfprintf((stderr, "about to register VCalF\n")); |
| rkcal = Calendar::registerFactory(new VersionCalendarFactory(), status); |
| debugfprintf((stderr, ".. registered VCalF, key=%p\n", (void*)rkcal)); |
| } |
| |
| void cal_provider_unregister(UErrorCode &status) { |
| Calendar::unregister(rkcal, status); |
| } |
| |
| #else |
| |
| /* no op- this ICU doesn't support date providers */ |
| |
| void cal_provider_register(UErrorCode &) { |
| // not supported |
| } |
| |
| void cal_provider_unregister(UErrorCode &) { |
| // not supported |
| } |
| |
| #endif |
| |
| /* Plugin- only ICU 4.4+ */ |
| #if (U_ICU_VERSION_MAJOR_NUM > 4) || ((U_ICU_VERSION_MAJOR_NUM==4)&&(U_ICU_VERSION_MINOR_NUM>3)) |
| #include "unicode/icuplug.h" |
| |
| U_CAPI UPlugTokenReturn U_EXPORT2 cal_provider_plugin (UPlugData *data, UPlugReason reason, UErrorCode *status); |
| |
| U_CAPI UPlugTokenReturn U_EXPORT2 cal_provider_plugin (UPlugData *data, UPlugReason reason, UErrorCode *status) |
| { |
| switch(reason) { |
| case UPLUG_REASON_QUERY: |
| uplug_setPlugName(data, "Calendar Provider Plugin"); |
| uplug_setPlugLevel(data, UPLUG_LEVEL_HIGH); |
| break; |
| case UPLUG_REASON_LOAD: |
| cal_provider_register(*status); |
| break; |
| case UPLUG_REASON_UNLOAD: |
| cal_provider_unregister(*status); |
| break; |
| default: |
| break; /* not handled */ |
| } |
| return UPLUG_TOKEN; |
| } |
| #else |
| |
| /* |
| Note: this ICU version must explicitly call 'cal_provider_plugin' |
| */ |
| |
| #endif /* plugin */ |
| |
| #endif /* provider side (vs target) */ |