Home | History | Annotate | Download | only in genrb
      1 /*
      2 *******************************************************************************
      3 *
      4 *   Copyright (C) 2000-2012, International Business Machines
      5 *   Corporation and others.  All Rights Reserved.
      6 *
      7 *******************************************************************************
      8 *
      9 * File wrtjava.c
     10 *
     11 * Modification History:
     12 *
     13 *   Date        Name        Description
     14 *   01/11/02    Ram         Creation.
     15 *   02/12/08    Spieth      Fix errant 'new Object[][]{' insertion
     16 *   02/19/08    Spieth      Removed ICUListResourceBundle dependancy
     17 *******************************************************************************
     18 */
     19 
     20 #include <assert.h>
     21 #include "reslist.h"
     22 #include "unewdata.h"
     23 #include "unicode/ures.h"
     24 #include "errmsg.h"
     25 #include "filestrm.h"
     26 #include "cstring.h"
     27 #include "unicode/ucnv.h"
     28 #include "genrb.h"
     29 #include "rle.h"
     30 #include "uhash.h"
     31 #include "uresimp.h"
     32 #include "unicode/ustring.h"
     33 
     34 void res_write_java(struct SResource *res,UErrorCode *status);
     35 
     36 
     37 static const char copyRight[] =
     38     "/* \n"
     39     " *******************************************************************************\n"
     40     " *\n"
     41     " *   Copyright (C) International Business Machines\n"
     42     " *   Corporation and others.  All Rights Reserved.\n"
     43     " *\n"
     44     " *******************************************************************************\n"
     45     " * $" "Source:  $ \n"
     46     " * $" "Date:  $ \n"
     47     " * $" "Revision:  $ \n"
     48     " *******************************************************************************\n"
     49     " */\n\n";
     50 static const char warningMsg[] =
     51     "/*********************************************************************\n"
     52     "######################################################################\n"
     53     "\n"
     54     "   WARNING: This file is generated by genrb Version " GENRB_VERSION ".\n"
     55     "            If you edit this file, please make sure that, the source\n"
     56     "            of this file (XXXX.txt in LocaleElements_XXXX.java)\n"
     57     "            is also edited.\n"
     58     "######################################################################\n"
     59     " *********************************************************************\n"
     60     " */\n\n";
     61 static const char* openBrace="{\n";
     62 static const char* closeClass="    };\n"
     63                               "}\n";
     64 
     65 static const char* javaClass =  "import java.util.ListResourceBundle;\n\n"
     66                                 "public class ";
     67 
     68 static const char* javaClass1=  " extends ListResourceBundle {\n\n"
     69                                 "    /**\n"
     70                                 "     * Overrides ListResourceBundle \n"
     71                                 "     */\n"
     72                                 "    public final Object[][] getContents() { \n"
     73                                 "          return  contents;\n"
     74                                 "    }\n\n"
     75                                 "    private static Object[][] contents = {\n";
     76 /*static const char* javaClassICU= " extends ListResourceBundle {\n\n"
     77                                  "    public %s  () {\n"
     78                                  "          super.contents = data;\n"
     79                                  "    }\n"
     80                                  "    static final Object[][] data = new Object[][] { \n";*/
     81 static int tabCount = 3;
     82 
     83 static FileStream* out=NULL;
     84 static struct SRBRoot* srBundle ;
     85 /*static const char* outDir = NULL;*/
     86 
     87 static const char* bName=NULL;
     88 static const char* pName=NULL;
     89 
     90 static void write_tabs(FileStream* os){
     91     int i=0;
     92     for(;i<=tabCount;i++){
     93         T_FileStream_write(os,"    ",4);
     94     }
     95 }
     96 
     97 #define ZERO 0x30
     98 
     99 static const char* enc ="";
    100 static UConverter* conv = NULL;
    101 
    102 static int32_t
    103 uCharsToChars( char* target,int32_t targetLen, UChar* source, int32_t sourceLen,UErrorCode* status){
    104     int i=0, j=0;
    105     char str[30]={'\0'};
    106     while(i<sourceLen){
    107         if (source[i] == '\n') {
    108             if (j + 2 < targetLen) {
    109                 uprv_strcat(target, "\\n");
    110             }
    111             j += 2;
    112         }else if(source[i]==0x0D){
    113             if(j+2<targetLen){
    114                 uprv_strcat(target,"\\f");
    115             }
    116             j+=2;
    117         }else if(source[i] == '"'){
    118             if(source[i-1]=='\''){
    119                 if(j+2<targetLen){
    120                     uprv_strcat(target,"\\");
    121                     target[j+1]= (char)source[i];
    122                 }
    123                 j+=2;
    124             }else if(source[i-1]!='\\'){
    125 
    126                 if(j+2<targetLen){
    127                     uprv_strcat(target,"\\");
    128                     target[j+1]= (char)source[i];
    129                 }
    130                 j+=2;
    131             }else if(source[i-1]=='\\'){
    132                 target[j++]= (char)source[i];
    133             }
    134         }else if(source[i]=='\\'){
    135             if(i+1<sourceLen){
    136                 switch(source[i+1]){
    137                 case ',':
    138                 case '!':
    139                 case '?':
    140                 case '#':
    141                 case '.':
    142                 case '%':
    143                 case '&':
    144                 case ':':
    145                 case ';':
    146                     if(j+2<targetLen){
    147                        uprv_strcat(target,"\\\\");
    148                     }
    149                     j+=2;
    150                     break;
    151                 case '"':
    152                 case '\'':
    153                     if(j+3<targetLen){
    154                        uprv_strcat(target,"\\\\\\");
    155                     }
    156                     j+=3;
    157                     break;
    158                 default :
    159                     if(j<targetLen){
    160                         target[j]=(char)source[i];
    161                     }
    162                     j++;
    163                     break;
    164                 }
    165             }else{
    166                 if(j<targetLen){
    167                     uprv_strcat(target,"\\\\");
    168                 }
    169                 j+=2;
    170             }
    171         }else if(source[i]>=0x20 && source[i]<0x7F/*ASCII*/){
    172             if(j<targetLen){
    173                 target[j] = (char) source[i];
    174             }
    175             j++;
    176         }else{
    177             if(*enc =='\0' || source[i]==0x0000){
    178                 uprv_strcpy(str,"\\u");
    179                 itostr(str+2,source[i],16,4);
    180                 if(j+6<targetLen){
    181                     uprv_strcat(target,str);
    182                 }
    183                 j+=6;
    184             }else{
    185                 char dest[30] = {0};
    186                 int retVal=ucnv_fromUChars(conv,dest,30,source+i,1,status);
    187                 if(U_FAILURE(*status)){
    188                     return 0;
    189                 }
    190                 if(j+retVal<targetLen){
    191                     uprv_strcat(target,dest);
    192                 }
    193                 j+=retVal;
    194             }
    195         }
    196         i++;
    197     }
    198     return j;
    199 }
    200 
    201 
    202 static uint32_t
    203 strrch(const char* source,uint32_t sourceLen,char find){
    204     const char* tSourceEnd =source + (sourceLen-1);
    205     while(tSourceEnd>= source){
    206         if(*tSourceEnd==find){
    207             return (uint32_t)(tSourceEnd-source);
    208         }
    209         tSourceEnd--;
    210     }
    211     return (uint32_t)(tSourceEnd-source);
    212 }
    213 
    214 static int32_t getColumnCount(int32_t len){
    215     int32_t columnCount = 80;
    216     int32_t maxLines = 3000;
    217     int32_t adjustedLen = len*5; /* assume that every codepoint is represented in \uXXXX format*/
    218     /*
    219      * calculate the number of lines that
    220      * may be required if column count is 80
    221      */
    222     if (maxLines  < (adjustedLen / columnCount) ){
    223         columnCount = adjustedLen / maxLines;
    224     }
    225     return columnCount;
    226 }
    227 static void
    228 str_write_java( uint16_t* src, int32_t srcLen, UBool printEndLine, UErrorCode *status){
    229 
    230     uint32_t length = srcLen*8;
    231     uint32_t bufLen = 0;
    232     uint32_t columnCount;
    233     char* buf = (char*) malloc(sizeof(char)*length);
    234 
    235     if(buf == NULL) {
    236         *status = U_MEMORY_ALLOCATION_ERROR;
    237         return;
    238     }
    239 
    240     columnCount = getColumnCount(srcLen);
    241     memset(buf,0,length);
    242 
    243     bufLen = uCharsToChars(buf,length,src,srcLen,status);
    244 
    245     if(printEndLine)
    246         write_tabs(out);
    247 
    248     if(U_FAILURE(*status)){
    249         uprv_free(buf);
    250         return;
    251     }
    252 
    253     if(bufLen+(tabCount*4) > columnCount  ){
    254         uint32_t len = 0;
    255         char* current = buf;
    256         uint32_t add;
    257         while(len < bufLen){
    258             add = columnCount-(tabCount*4)-5/* for ", +\n */;
    259             current = buf +len;
    260             if (add < (bufLen-len)) {
    261                 uint32_t idx = strrch(current,add,'\\');
    262                 if (idx > add) {
    263                     idx = add;
    264                 } else {
    265                     int32_t num =idx-1;
    266                     uint32_t seqLen;
    267                     while(num>0){
    268                         if(current[num]=='\\'){
    269                             num--;
    270                         }else{
    271                             break;
    272                         }
    273                     }
    274                     if ((idx-num)%2==0) {
    275                         idx--;
    276                     }
    277                     seqLen = (current[idx+1]=='u') ? 6 : 2;
    278                     if ((add-idx) < seqLen) {
    279                         add = idx + seqLen;
    280                     }
    281                 }
    282             }
    283             T_FileStream_write(out,"\"",1);
    284             if(len+add<bufLen){
    285                 T_FileStream_write(out,current,add);
    286                 T_FileStream_write(out,"\" +\n",4);
    287                 write_tabs(out);
    288             }else{
    289                 T_FileStream_write(out,current,bufLen-len);
    290             }
    291             len+=add;
    292         }
    293     }else{
    294         T_FileStream_write(out,"\"",1);
    295         T_FileStream_write(out, buf,bufLen);
    296     }
    297     if(printEndLine){
    298         T_FileStream_write(out,"\",\n",3);
    299     }else{
    300         T_FileStream_write(out,"\"",1);
    301     }
    302     uprv_free(buf);
    303 }
    304 
    305 /* Writing Functions */
    306 static void
    307 string_write_java(struct SResource *res,UErrorCode *status) {
    308     char resKeyBuffer[8];
    309     const char *resname = res_getKeyString(srBundle, res, resKeyBuffer);
    310 
    311     str_write_java(res->u.fString.fChars,res->u.fString.fLength,TRUE,status);
    312 
    313 	if(resname != NULL && uprv_strcmp(resname,"Rule")==0)
    314 	{
    315         UChar* buf = (UChar*) uprv_malloc(sizeof(UChar)*res->u.fString.fLength);
    316         uprv_memcpy(buf,res->u.fString.fChars,res->u.fString.fLength);
    317         uprv_free(buf);
    318     }
    319 
    320 }
    321 
    322 static void
    323 array_write_java( struct SResource *res, UErrorCode *status) {
    324 
    325     uint32_t  i         = 0;
    326     const char* arr ="new String[] { \n";
    327     struct SResource *current = NULL;
    328     UBool allStrings    = TRUE;
    329 
    330     if (U_FAILURE(*status)) {
    331         return;
    332     }
    333 
    334     if (res->u.fArray.fCount > 0) {
    335 
    336         current = res->u.fArray.fFirst;
    337         i = 0;
    338         while(current != NULL){
    339             if(current->fType!=URES_STRING){
    340                 allStrings = FALSE;
    341                 break;
    342             }
    343             current= current->fNext;
    344         }
    345 
    346         current = res->u.fArray.fFirst;
    347         if(allStrings==FALSE){
    348             const char* object = "new Object[]{\n";
    349             write_tabs(out);
    350             T_FileStream_write(out, object, (int32_t)uprv_strlen(object));
    351             tabCount++;
    352         }else{
    353             write_tabs(out);
    354             T_FileStream_write(out, arr, (int32_t)uprv_strlen(arr));
    355             tabCount++;
    356         }
    357         while (current != NULL) {
    358             /*if(current->fType==URES_STRING){
    359                 write_tabs(out);
    360             }*/
    361             res_write_java(current, status);
    362             if(U_FAILURE(*status)){
    363                 return;
    364             }
    365             i++;
    366             current = current->fNext;
    367         }
    368         T_FileStream_write(out,"\n",1);
    369 
    370         tabCount--;
    371         write_tabs(out);
    372         T_FileStream_write(out,"},\n",3);
    373 
    374     } else {
    375         write_tabs(out);
    376         T_FileStream_write(out,arr,(int32_t)uprv_strlen(arr));
    377         write_tabs(out);
    378         T_FileStream_write(out,"},\n",3);
    379     }
    380 }
    381 
    382 static void
    383 intvector_write_java( struct SResource *res, UErrorCode *status) {
    384     uint32_t i = 0;
    385     const char* intArr = "new int[] {\n";
    386     /* const char* intC   = "new Integer(";   */
    387     const char* stringArr = "new String[]{\n";
    388     char resKeyBuffer[8];
    389     const char *resname = res_getKeyString(srBundle, res, resKeyBuffer);
    390     char buf[100];
    391     int len =0;
    392     buf[0]=0;
    393     write_tabs(out);
    394 
    395     if(resname != NULL && uprv_strcmp(resname,"DateTimeElements")==0){
    396         T_FileStream_write(out, stringArr, (int32_t)uprv_strlen(stringArr));
    397         tabCount++;
    398         for(i = 0; i<res->u.fIntVector.fCount; i++) {
    399             write_tabs(out);
    400             len=itostr(buf,res->u.fIntVector.fArray[i],10,0);
    401             T_FileStream_write(out,"\"",1);
    402             T_FileStream_write(out,buf,len);
    403             T_FileStream_write(out,"\",",2);
    404             T_FileStream_write(out,"\n",1);
    405         }
    406     }else{
    407         T_FileStream_write(out, intArr, (int32_t)uprv_strlen(intArr));
    408         tabCount++;
    409         for(i = 0; i<res->u.fIntVector.fCount; i++) {
    410             write_tabs(out);
    411             /* T_FileStream_write(out, intC, (int32_t)uprv_strlen(intC)); */
    412             len=itostr(buf,res->u.fIntVector.fArray[i],10,0);
    413             T_FileStream_write(out,buf,len);
    414             /* T_FileStream_write(out,"),",2);  */
    415             /* T_FileStream_write(out,"\n",1);  */
    416             T_FileStream_write(out,",\n",2);
    417         }
    418     }
    419     tabCount--;
    420     write_tabs(out);
    421     T_FileStream_write(out,"},\n",3);
    422 }
    423 
    424 static void
    425 int_write_java(struct SResource *res,UErrorCode *status) {
    426     const char* intC   =  "new Integer(";
    427     char buf[100];
    428     int len =0;
    429     buf[0]=0;
    430 
    431     /* write the binary data */
    432     write_tabs(out);
    433     T_FileStream_write(out, intC, (int32_t)uprv_strlen(intC));
    434     len=itostr(buf, res->u.fIntValue.fValue, 10, 0);
    435     T_FileStream_write(out,buf,len);
    436     T_FileStream_write(out,"),\n",3 );
    437 
    438 }
    439 
    440 static void
    441 bytes_write_java( struct SResource *res, UErrorCode *status) {
    442 	const char* type  = "new byte[] {";
    443 	const char* byteDecl = "%i, ";
    444     char byteBuffer[100] = { 0 };
    445 	uint8_t*  byteArray = NULL;
    446     int byteIterator = 0;
    447 
    448     int32_t srcLen=res->u.fBinaryValue.fLength;
    449 
    450     if(srcLen>0 )
    451 	{
    452         byteArray = res->u.fBinaryValue.fData;
    453 
    454         write_tabs(out);
    455         T_FileStream_write(out, type, (int32_t)uprv_strlen(type));
    456         T_FileStream_write(out, "\n", 1);
    457         tabCount++;
    458 
    459 		for (;byteIterator<srcLen;byteIterator++)
    460 		{
    461             if (byteIterator%16 == 0)
    462 			{
    463 			    write_tabs(out);
    464 			}
    465 
    466 			if (byteArray[byteIterator] < 128)
    467 			{
    468                 sprintf(byteBuffer, byteDecl, byteArray[byteIterator]);
    469 			}
    470 			else
    471 			{
    472                 sprintf(byteBuffer, byteDecl, (byteArray[byteIterator]-256));
    473 			}
    474 
    475             T_FileStream_write(out, byteBuffer, (int32_t)uprv_strlen(byteBuffer));
    476 
    477 			if (byteIterator%16 == 15)
    478 			{
    479                 T_FileStream_write(out, "\n", 1);
    480 			}
    481 
    482 		}
    483 
    484         if (((byteIterator-1)%16) != 15)
    485 		{
    486             T_FileStream_write(out, "\n", 1);
    487 	    }
    488 
    489 		tabCount--;
    490         write_tabs(out);
    491 		T_FileStream_write(out, "},\n", 3);
    492 
    493 	}
    494 	else
    495     {
    496 		/* Empty array */
    497         write_tabs(out);
    498         T_FileStream_write(out,type,(int32_t)uprv_strlen(type));
    499 		T_FileStream_write(out,"},\n",3);
    500     }
    501 
    502 }
    503 
    504 static UBool start = TRUE;
    505 
    506 static void
    507 table_write_java(struct SResource *res, UErrorCode *status) {
    508     uint32_t  i         = 0;
    509     struct SResource *current = NULL;
    510     const char* obj = "new Object[][]{\n";
    511 
    512     if (U_FAILURE(*status)) {
    513         return ;
    514     }
    515 
    516     if (res->u.fTable.fCount > 0) {
    517         if(start==FALSE){
    518             write_tabs(out);
    519             T_FileStream_write(out, obj, (int32_t)uprv_strlen(obj));
    520             tabCount++;
    521         }
    522         start = FALSE;
    523         current = res->u.fTable.fFirst;
    524         i       = 0;
    525 
    526 
    527         while (current != NULL) {
    528             char currentKeyBuffer[8];
    529             const char *currentKeyString = res_getKeyString(srBundle, current, currentKeyBuffer);
    530 
    531             assert(i < res->u.fTable.fCount);
    532             write_tabs(out);
    533 
    534             T_FileStream_write(out, openBrace, 2);
    535 
    536 
    537             tabCount++;
    538 
    539             write_tabs(out);
    540             if(currentKeyString != NULL) {
    541                 T_FileStream_write(out, "\"", 1);
    542                 T_FileStream_write(out, currentKeyString,
    543                                    (int32_t)uprv_strlen(currentKeyString));
    544                 T_FileStream_write(out, "\",\n", 2);
    545 
    546                 T_FileStream_write(out, "\n", 1);
    547             }
    548             res_write_java(current, status);
    549             if(U_FAILURE(*status)){
    550                 return;
    551             }
    552             i++;
    553             current = current->fNext;
    554             tabCount--;
    555             write_tabs(out);
    556             T_FileStream_write(out, "},\n", 3);
    557         }
    558         if(tabCount>4){
    559             tabCount--;
    560             write_tabs(out);
    561             T_FileStream_write(out, "},\n", 3);
    562         }
    563 
    564     } else {
    565         write_tabs(out);
    566         T_FileStream_write(out,obj,(int32_t)uprv_strlen(obj));
    567 
    568         write_tabs(out);
    569         T_FileStream_write(out,"},\n",3);
    570 
    571     }
    572 
    573 }
    574 
    575 void
    576 res_write_java(struct SResource *res,UErrorCode *status) {
    577 
    578     if (U_FAILURE(*status)) {
    579         return ;
    580     }
    581 
    582     if (res != NULL) {
    583         switch (res->fType) {
    584         case URES_STRING:
    585              string_write_java    (res, status);
    586              return;
    587         case URES_ALIAS:
    588              printf("Encountered unsupported resource type %d of alias\n", res->fType);
    589              *status = U_UNSUPPORTED_ERROR;
    590 			 return;
    591         case URES_INT_VECTOR:
    592              intvector_write_java (res, status);
    593              return;
    594         case URES_BINARY:
    595              bytes_write_java     (res, status);
    596              return;
    597         case URES_INT:
    598              int_write_java       (res, status);
    599              return;
    600         case URES_ARRAY:
    601              array_write_java     (res, status);
    602              return;
    603         case URES_TABLE:
    604              table_write_java     (res, status);
    605              return;
    606         default:
    607             break;
    608         }
    609     }
    610 
    611     *status = U_INTERNAL_PROGRAM_ERROR;
    612 }
    613 
    614 void
    615 bundle_write_java(struct SRBRoot *bundle, const char *outputDir,const char* outputEnc,
    616                   char *writtenFilename, int writtenFilenameLen,
    617                   const char* packageName, const char* bundleName,
    618                   UErrorCode *status) {
    619 
    620     char fileName[256] = {'\0'};
    621     char className[256]={'\0'};
    622     /*char constructor[1000] = { 0 };*/
    623     /*UBool j1 =FALSE;*/
    624     /*outDir = outputDir;*/
    625 
    626     start = TRUE;                        /* Reset the start indictor*/
    627 
    628     bName = (bundleName==NULL) ? "LocaleElements" : bundleName;
    629     pName = (packageName==NULL)? "com.ibm.icu.impl.data" : packageName;
    630 
    631     uprv_strcpy(className, bName);
    632     srBundle = bundle;
    633     if(uprv_strcmp(srBundle->fLocale,"root")!=0){
    634         uprv_strcat(className,"_");
    635         uprv_strcat(className,srBundle->fLocale);
    636     }
    637     if(outputDir){
    638         uprv_strcpy(fileName, outputDir);
    639         if(outputDir[uprv_strlen(outputDir)-1] !=U_FILE_SEP_CHAR){
    640             uprv_strcat(fileName,U_FILE_SEP_STRING);
    641         }
    642         uprv_strcat(fileName,className);
    643         uprv_strcat(fileName,".java");
    644     }else{
    645         uprv_strcat(fileName,className);
    646         uprv_strcat(fileName,".java");
    647     }
    648 
    649     if (writtenFilename) {
    650         uprv_strncpy(writtenFilename, fileName, writtenFilenameLen);
    651     }
    652 
    653     if (U_FAILURE(*status)) {
    654         return;
    655     }
    656 
    657     out= T_FileStream_open(fileName,"w");
    658 
    659     if(out==NULL){
    660         *status = U_FILE_ACCESS_ERROR;
    661         return;
    662     }
    663     if(getIncludeCopyright()){
    664         T_FileStream_write(out, copyRight, (int32_t)uprv_strlen(copyRight));
    665         T_FileStream_write(out, warningMsg, (int32_t)uprv_strlen(warningMsg));
    666     }
    667     T_FileStream_write(out,"package ",(int32_t)uprv_strlen("package "));
    668     T_FileStream_write(out,pName,(int32_t)uprv_strlen(pName));
    669     T_FileStream_write(out,";\n\n",3);
    670     T_FileStream_write(out, javaClass, (int32_t)uprv_strlen(javaClass));
    671     T_FileStream_write(out, className, (int32_t)uprv_strlen(className));
    672 	T_FileStream_write(out, javaClass1, (int32_t)uprv_strlen(javaClass1));
    673 
    674     /* if(j1){
    675           T_FileStream_write(out, javaClass1, (int32_t)uprv_strlen(javaClass1));
    676        }else{
    677            sprintf(constructor,javaClassICU,className);
    678            T_FileStream_write(out, constructor, (int32_t)uprv_strlen(constructor));
    679        }
    680     */
    681 
    682     if(outputEnc && *outputEnc!='\0'){
    683         /* store the output encoding */
    684         enc = outputEnc;
    685         conv=ucnv_open(enc,status);
    686         if(U_FAILURE(*status)){
    687             return;
    688         }
    689     }
    690     res_write_java(bundle->fRoot, status);
    691 
    692     T_FileStream_write(out, closeClass, (int32_t)uprv_strlen(closeClass));
    693 
    694     T_FileStream_close(out);
    695 
    696     ucnv_close(conv);
    697 }
    698