blob: 86ad8173ba3d483a6f6003b3096d648189a855f9 [file] [log] [blame]
/*
*******************************************************************************
*
* 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) */