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