blob: 495bf2ca838c6858126b994267e5c0f521b96a31 [file] [log] [blame]
/*
*******************************************************************************
*
* Copyright (C) 2009-2011, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
*/
#ifndef DATE_FE_DEBUG
#define DATE_FE_DEBUG 0
#endif
#include <icuglue/icuglue.h>
#include "unicode/udat.h"
//#include <unicode/tblcoll.h>
#include "unicode/datefmt.h"
#include "unicode/smpdtfmt.h"
#include <string.h>
#include <stdio.h>
#include "unicode/ustring.h"
#include "unicode/gregocal.h"
/**
* Macro to define the Collator_glue_4_2 class
*/
#ifdef GLUE_VER
#error GLUE_VER is defined
#endif
#define GLUE_VER(x) class GLUE_SYM_V( DateFormat, x ) : public DateFormat { \
public: static DateFormat *create(const Locale &loc, const char *ver); \
private: UDateFormat *_this; GLUE_SYM_V( DateFormat, x ) ( UDateFormat* tn ); \
virtual ~ GLUE_SYM_V ( DateFormat, x) (); \
public: \
virtual void* getDynamicClassID() const; \
static void* getStaticClassID() ; \
virtual UnicodeString& format( Calendar& cal, UnicodeString& appendTo, FieldPosition& pos) const; \
virtual void parse( const UnicodeString& text, Calendar& cal, ParsePosition& pos) const; \
virtual Format* 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 (DateFormat ) :: GLUE_SYM(DateFormat) ( UDateFormat* tn) :
_this(tn)
{
UErrorCode status = U_ZERO_ERROR;
adoptCalendar(new GregorianCalendar(status));
}
GLUE_SYM ( DateFormat ) :: ~ GLUE_SYM(DateFormat) () {
#if DATE_FE_DEBUG
fprintf(stderr, "VCF " ICUGLUE_VER_STR " udat_close");
#endif
OICU_udat_close(_this);
}
DateFormat *
GLUE_SYM ( DateFormat ) :: create(const Locale &loc, const char */*ver*/) {
// TODO: save 'ver' off.
UErrorCode status = U_ZERO_ERROR;
char locBuf[200];
char kwvBuf[200];
// int32_t len = loc.getKeywordValue("collation", kwvBuf, 200, status);
//strcpy(locBuf,loc.getBaseName());
// if(len>0) {
// strcat(locBuf,"@collator=");
// strcat(locBuf,kwvBuf);
// }
UDateFormat * uc = OICU_udat_open( UDAT_FULL, UDAT_FULL, loc.getName(),
NULL,
-1,
NULL,
-1,
&status);
if(U_FAILURE(status)) return NULL; // TODO: ERR?
DateFormat *c = new GLUE_SYM( DateFormat ) ( uc );
#if DATE_FE_DEBUG
fprintf(stderr, "VCF " ICUGLUE_VER_STR " udat_open=%s ->> %p\n", loc.getName(), (void*)c);
#endif
return c;
}
UnicodeString& GLUE_SYM (DateFormat ) :: format( Calendar& cal, UnicodeString& appendTo, FieldPosition& pos) const
{
#if DATE_FE_DEBUG
fprintf(stderr, "VCF " ICUGLUE_VER_STR " - formatting. \n");
#endif
int32_t len = appendTo.length();
UChar junk[200];
UErrorCode status = U_ZERO_ERROR;
UFieldPosition pos2;
int32_t nlen = OICU_udat_format(_this,
cal.getTime(status),
junk,
200,
&pos2,
&status);
// todo: use pos2
pos.setBeginIndex(len);
pos.setEndIndex(len += nlen);
appendTo.append(junk, nlen);
return appendTo;
}
void GLUE_SYM (DateFormat ) :: parse( const UnicodeString& text, Calendar& cal, ParsePosition& pos) const
{
return;
}
Format* GLUE_SYM (DateFormat ) :: clone(void) const
{
return NULL;
}
int32_t GLUE_SYM ( DateFormat ) :: countAvailable() {
int32_t count = OICU_udat_countAvailable();
return count;
}
int32_t GLUE_SYM ( DateFormat ) :: appendAvailable(UnicodeString* strs, int32_t i, int32_t /*count*/) {
int avail = OICU_udat_countAvailable();
UErrorCode status = U_ZERO_ERROR;
OICU_u_init(&status);
#if DATE_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");
strs[i+j].append( ICUGLUE_VER_STR[0] ); // X_y
strs[i+j].append( ICUGLUE_VER_STR[2] ); // x_Y
#if DATE_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( DateFormat ) )
#else
/** ==================================== The following code runs inside the 'provider' version (i.e. current ICU) ========== **/
// define Collator_XX
#include "icuglue/glver.h"
// generate list of versions
static
#include <icuglue/fe_verlist.h>
class VersionDateFormatFactory : public UObject {
public:
virtual DateFormat *createFormat(const Locale &loc);
virtual const UnicodeString *getSupportedIDs(int32_t &count, UErrorCode &status);
virtual void* getDynamicClassID() const;
static void* getStaticClassID() ;
};
UOBJECT_DEFINE_RTTI_IMPLEMENTATION( VersionDateFormatFactory )
DateFormat *VersionDateFormatFactory::createFormat(const Locale &loc) {
// pull off provider #
char provider[200];
UErrorCode status = U_ZERO_ERROR;
#if DATE_FE_DEBUG
fprintf(stderr, "VCF:CC %s\n", loc.getName());
#endif
int32_t len = loc.getKeywordValue("sp", provider, 200, status);
if(U_FAILURE(status)||len==0) return NULL;
#if DATE_FE_DEBUG
fprintf(stderr, "VCF:KWV> %s/%d\n", u_errorName(status), len);
#endif
provider[len]=0;
#if DATE_FE_DEBUG
fprintf(stderr, "VCF:KWV %s\n", provider);
#endif
if(strncmp(provider,"icu",3)) return NULL;
const char *icuver=provider+3;
#if DATE_FE_DEBUG
fprintf(stderr, "VCF:ICUV %s\n", icuver);
#endif
#if defined(GLUE_VER)
#undef GLUE_VER
#endif
#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(loc, icuver); /*fprintf(stderr, "VCF::CC %s -> %p\n", loc.getName(), c);*/ return c; }
#include "icuglue/glver.h"
#if DATE_FE_DEBUG
fprintf(stderr, "VCF:CC %s failed\n", loc.getName());
#endif
return NULL;
}
static const UnicodeString *gLocalesDate = NULL;
static int32_t gLocCountDate = 0;
const UnicodeString
*VersionDateFormatFactory::getSupportedIDs(int32_t &count, UErrorCode &/*status*/) {
if(gLocalesDate==NULL) {
count = 0;
/* gather counts */
#if defined(GLUE_VER)
#undef GLUE_VER
#endif
#define GLUE_VER(x) count += glue ## DateFormat ## x :: countAvailable();
#include "icuglue/glver.h"
#if DATE_FE_DEBUG
printf("VCF: 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 ## DateFormat ## x :: appendAvailable(strs, i, count);
#include "icuglue/glver.h"
#if DATE_FE_DEBUG
printf("VCF: 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 rkdate = NULL;
VersionDateFormatFactory vdf;
extern "C" UDateFormat *versionDateFormatOpener(UDateFormatStyle timeStyle,
UDateFormatStyle dateStyle,
const char *locale,
const UChar *tzID,
int32_t tzIDLength,
const UChar *pattern,
int32_t patternLength,
UErrorCode *status) {
Locale loc(locale);
DateFormat *df = vdf.createFormat(loc);
// printf("Hey! I got: %s -> %p\n", locale, df);
return (UDateFormat*)df;
}
void date_provider_register(UErrorCode &status) {
udat_registerOpener(versionDateFormatOpener, &status);
// rkdate = DateFormat::registerFactory(new VersionDateFormatFactory(), status);
}
void date_provider_unregister(UErrorCode &status) {
udat_unregisterOpener(versionDateFormatOpener, &status);
}
/* 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 date_provider_plugin (UPlugData *data, UPlugReason reason, UErrorCode *status);
U_CAPI UPlugTokenReturn U_EXPORT2 date_provider_plugin (UPlugData *data, UPlugReason reason, UErrorCode *status)
{
switch(reason) {
case UPLUG_REASON_QUERY:
uplug_setPlugName(data, "Date Provider Plugin");
uplug_setPlugLevel(data, UPLUG_LEVEL_HIGH);
break;
case UPLUG_REASON_LOAD:
date_provider_register(*status);
break;
case UPLUG_REASON_UNLOAD:
date_provider_unregister(*status);
break;
default:
break; /* not handled */
}
return UPLUG_TOKEN;
}
#else
/*
Note: this ICU version must explicitly call 'date_provider_plugin'
*/
#endif /* plugin */
#endif /* provider side (vs target) */