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 
    310     str_write_java(res->u.fString.fChars,res->u.fString.fLength,TRUE,status);
    311 
    312 	if(res->fKey > 0 && uprv_strcmp(srBundle->fKeys+res->fKey,"Rule")==0)
    313 	{
    314         UChar* buf = (UChar*) uprv_malloc(sizeof(UChar)*res->u.fString.fLength);
    315         uprv_memcpy(buf,res->u.fString.fChars,res->u.fString.fLength);
    316         uprv_free(buf);
    317     }
    318 
    319 }
    320 
    321 static void
    322 array_write_java( struct SResource *res, UErrorCode *status) {
    323 
    324     uint32_t  i         = 0;
    325     const char* arr ="new String[] { \n";
    326     struct SResource *current = NULL;
    327     struct SResource *first =NULL;
    328     UBool decrementTabs = FALSE;
    329     UBool allStrings    = TRUE;
    330 
    331     if (U_FAILURE(*status)) {
    332         return;
    333     }
    334 
    335     if (res->u.fArray.fCount > 0) {
    336 
    337         current = res->u.fArray.fFirst;
    338         i = 0;
    339         while(current != NULL){
    340             if(current->fType!=URES_STRING){
    341                 allStrings = FALSE;
    342                 break;
    343             }
    344             current= current->fNext;
    345         }
    346 
    347         current = res->u.fArray.fFirst;
    348         if(allStrings==FALSE){
    349             const char* object = "new Object[]{\n";
    350             write_tabs(out);
    351             T_FileStream_write(out, object, (int32_t)uprv_strlen(object));
    352             tabCount++;
    353             decrementTabs = TRUE;
    354         }else{
    355             write_tabs(out);
    356             T_FileStream_write(out, arr, (int32_t)uprv_strlen(arr));
    357             tabCount++;
    358         }
    359         first=current;
    360         while (current != NULL) {
    361             /*if(current->fType==URES_STRING){
    362                 write_tabs(out);
    363             }*/
    364             res_write_java(current, status);
    365             if(U_FAILURE(*status)){
    366                 return;
    367             }
    368             i++;
    369             current = current->fNext;
    370         }
    371         T_FileStream_write(out,"\n",1);
    372 
    373         tabCount--;
    374         write_tabs(out);
    375         T_FileStream_write(out,"},\n",3);
    376 
    377     } else {
    378         write_tabs(out);
    379         T_FileStream_write(out,arr,(int32_t)uprv_strlen(arr));
    380         write_tabs(out);
    381         T_FileStream_write(out,"},\n",3);
    382     }
    383 }
    384 
    385 static void
    386 intvector_write_java( struct SResource *res, UErrorCode *status) {
    387     uint32_t i = 0;
    388     const char* intArr = "new int[] {\n";
    389     /* const char* intC   = "new Integer(";   */
    390     const char* stringArr = "new String[]{\n";
    391     char buf[100];
    392     int len =0;
    393     buf[0]=0;
    394     write_tabs(out);
    395 
    396     if(res->fKey > 0 && uprv_strcmp(srBundle->fKeys+res->fKey,"DateTimeElements")==0){
    397         T_FileStream_write(out, stringArr, (int32_t)uprv_strlen(stringArr));
    398         tabCount++;
    399         for(i = 0; i<res->u.fIntVector.fCount; i++) {
    400             write_tabs(out);
    401             len=itostr(buf,res->u.fIntVector.fArray[i],10,0);
    402             T_FileStream_write(out,"\"",1);
    403             T_FileStream_write(out,buf,len);
    404             T_FileStream_write(out,"\",",2);
    405             T_FileStream_write(out,"\n",1);
    406         }
    407     }else{
    408         T_FileStream_write(out, intArr, (int32_t)uprv_strlen(intArr));
    409         tabCount++;
    410         for(i = 0; i<res->u.fIntVector.fCount; i++) {
    411             write_tabs(out);
    412             /* T_FileStream_write(out, intC, (int32_t)uprv_strlen(intC)); */
    413             len=itostr(buf,res->u.fIntVector.fArray[i],10,0);
    414             T_FileStream_write(out,buf,len);
    415             /* T_FileStream_write(out,"),",2);  */
    416             /* T_FileStream_write(out,"\n",1);  */
    417             T_FileStream_write(out,",\n",2);
    418         }
    419     }
    420     tabCount--;
    421     write_tabs(out);
    422     T_FileStream_write(out,"},\n",3);
    423 }
    424 
    425 static void
    426 int_write_java(struct SResource *res,UErrorCode *status) {
    427     const char* intC   =  "new Integer(";
    428     char buf[100];
    429     int len =0;
    430     buf[0]=0;
    431 
    432     /* write the binary data */
    433     write_tabs(out);
    434     T_FileStream_write(out, intC, (int32_t)uprv_strlen(intC));
    435     len=itostr(buf, res->u.fIntValue.fValue, 10, 0);
    436     T_FileStream_write(out,buf,len);
    437     T_FileStream_write(out,"),\n",3 );
    438 
    439 }
    440 
    441 static void
    442 bytes_write_java( struct SResource *res, UErrorCode *status) {
    443 	const char* type  = "new byte[] {";
    444 	const char* byteDecl = "%i, ";
    445     char byteBuffer[100] = { 0 };
    446 	uint8_t*  byteArray = NULL;
    447     int byteIterator = 0;
    448 
    449     int32_t srcLen=res->u.fBinaryValue.fLength;
    450 
    451     if(srcLen>0 )
    452 	{
    453         byteArray = res->u.fBinaryValue.fData;
    454 
    455         write_tabs(out);
    456         T_FileStream_write(out, type, (int32_t)uprv_strlen(type));
    457         T_FileStream_write(out, "\n", 1);
    458         tabCount++;
    459 
    460 		for (;byteIterator<srcLen;byteIterator++)
    461 		{
    462             if (byteIterator%16 == 0)
    463 			{
    464 			    write_tabs(out);
    465 			}
    466 
    467 			if (byteArray[byteIterator] < 128)
    468 			{
    469                 sprintf(byteBuffer, byteDecl, byteArray[byteIterator]);
    470 			}
    471 			else
    472 			{
    473                 sprintf(byteBuffer, byteDecl, (byteArray[byteIterator]-256));
    474 			}
    475 
    476             T_FileStream_write(out, byteBuffer, (int32_t)uprv_strlen(byteBuffer));
    477 
    478 			if (byteIterator%16 == 15)
    479 			{
    480                 T_FileStream_write(out, "\n", 1);
    481 			}
    482 
    483 		}
    484 
    485         if (((byteIterator-1)%16) != 15)
    486 		{
    487             T_FileStream_write(out, "\n", 1);
    488 	    }
    489 
    490 		tabCount--;
    491         write_tabs(out);
    492 		T_FileStream_write(out, "},\n", 3);
    493 
    494 	}
    495 	else
    496     {
    497 		/* Empty array */
    498         write_tabs(out);
    499         T_FileStream_write(out,type,(int32_t)uprv_strlen(type));
    500 		T_FileStream_write(out,"},\n",3);
    501     }
    502 
    503 }
    504 
    505 static UBool start = TRUE;
    506 
    507 static void
    508 table_write_java(struct SResource *res, UErrorCode *status) {
    509     uint32_t  i         = 0;
    510     UBool allStrings =TRUE;
    511     struct SResource *current = NULL;
    512     struct SResource *save = NULL;
    513     const char* obj = "new Object[][]{\n";
    514 
    515     if (U_FAILURE(*status)) {
    516         return ;
    517     }
    518 
    519     if (res->u.fTable.fCount > 0) {
    520         if(start==FALSE){
    521             write_tabs(out);
    522             T_FileStream_write(out, obj, (int32_t)uprv_strlen(obj));
    523             tabCount++;
    524         }
    525         start = FALSE;
    526         save = current = res->u.fTable.fFirst;
    527         i       = 0;
    528 
    529 
    530         while (current != NULL) {
    531             assert(i < res->u.fTable.fCount);
    532             write_tabs(out);
    533 
    534             T_FileStream_write(out, openBrace, 2);
    535 
    536 
    537             tabCount++;
    538             allStrings=FALSE;
    539 
    540             write_tabs(out);
    541             if(current->fKey > 0){
    542                 T_FileStream_write(out, "\"", 1);
    543                 T_FileStream_write(out, srBundle->fKeys+current->fKey,
    544                                    (int32_t)uprv_strlen(srBundle->fKeys+current->fKey));
    545                 T_FileStream_write(out, "\",\n", 2);
    546 
    547                 T_FileStream_write(out, "\n", 1);
    548             }
    549             res_write_java(current, status);
    550             if(U_FAILURE(*status)){
    551                 return;
    552             }
    553             i++;
    554             current = current->fNext;
    555             tabCount--;
    556             write_tabs(out);
    557             T_FileStream_write(out, "},\n", 3);
    558         }
    559         if(tabCount>4){
    560             tabCount--;
    561             write_tabs(out);
    562             T_FileStream_write(out, "},\n", 3);
    563         }
    564 
    565     } else {
    566         write_tabs(out);
    567         T_FileStream_write(out,obj,(int32_t)uprv_strlen(obj));
    568 
    569         write_tabs(out);
    570         T_FileStream_write(out,"},\n",3);
    571 
    572     }
    573 
    574 }
    575 
    576 void
    577 res_write_java(struct SResource *res,UErrorCode *status) {
    578 
    579     if (U_FAILURE(*status)) {
    580         return ;
    581     }
    582 
    583     if (res != NULL) {
    584         switch (res->fType) {
    585         case URES_STRING:
    586              string_write_java    (res, status);
    587              return;
    588         case URES_ALIAS:
    589              printf("Encountered unsupported resource type %d of alias\n", res->fType);
    590              *status = U_UNSUPPORTED_ERROR;
    591 			 return;
    592         case URES_INT_VECTOR:
    593              intvector_write_java (res, status);
    594              return;
    595         case URES_BINARY:
    596              bytes_write_java     (res, status);
    597              return;
    598         case URES_INT:
    599              int_write_java       (res, status);
    600              return;
    601         case URES_ARRAY:
    602              array_write_java     (res, status);
    603              return;
    604         case URES_TABLE:
    605         case URES_TABLE32:
    606              table_write_java     (res, status);
    607              return;
    608         default:
    609             break;
    610         }
    611     }
    612 
    613     *status = U_INTERNAL_PROGRAM_ERROR;
    614 }
    615 
    616 void
    617 bundle_write_java(struct SRBRoot *bundle, const char *outputDir,const char* outputEnc,
    618                   char *writtenFilename, int writtenFilenameLen,
    619                   const char* packageName, const char* bundleName,
    620                   UErrorCode *status) {
    621 
    622     char fileName[256] = {'\0'};
    623     char className[256]={'\0'};
    624     /*char constructor[1000] = { 0 };*/
    625     /*UBool j1 =FALSE;*/
    626     outDir = outputDir;
    627 
    628     start = TRUE;                        /* Reset the start indictor*/
    629 
    630     bName = (bundleName==NULL) ? "LocaleElements" : bundleName;
    631     pName = (packageName==NULL)? "com.ibm.icu.impl.data" : packageName;
    632 
    633     uprv_strcpy(className, bName);
    634     srBundle = bundle;
    635     if(uprv_strcmp(srBundle->fLocale,"root")!=0){
    636         uprv_strcat(className,"_");
    637         uprv_strcat(className,srBundle->fLocale);
    638     }
    639     if(outputDir){
    640         uprv_strcpy(fileName, outputDir);
    641         if(outputDir[uprv_strlen(outputDir)-1] !=U_FILE_SEP_CHAR){
    642             uprv_strcat(fileName,U_FILE_SEP_STRING);
    643         }
    644         uprv_strcat(fileName,className);
    645         uprv_strcat(fileName,".java");
    646     }else{
    647         uprv_strcat(fileName,className);
    648         uprv_strcat(fileName,".java");
    649     }
    650 
    651     if (writtenFilename) {
    652         uprv_strncpy(writtenFilename, fileName, writtenFilenameLen);
    653     }
    654 
    655     if (U_FAILURE(*status)) {
    656         return;
    657     }
    658 
    659     out= T_FileStream_open(fileName,"w");
    660 
    661     if(out==NULL){
    662         *status = U_FILE_ACCESS_ERROR;
    663         return;
    664     }
    665     if(getIncludeCopyright()){
    666         T_FileStream_write(out, copyRight, (int32_t)uprv_strlen(copyRight));
    667         T_FileStream_write(out, warningMsg, (int32_t)uprv_strlen(warningMsg));
    668     }
    669     T_FileStream_write(out,"package ",(int32_t)uprv_strlen("package "));
    670     T_FileStream_write(out,pName,(int32_t)uprv_strlen(pName));
    671     T_FileStream_write(out,";\n\n",3);
    672     T_FileStream_write(out, javaClass, (int32_t)uprv_strlen(javaClass));
    673     T_FileStream_write(out, className, (int32_t)uprv_strlen(className));
    674 	T_FileStream_write(out, javaClass1, (int32_t)uprv_strlen(javaClass1));
    675 
    676     /* if(j1){
    677           T_FileStream_write(out, javaClass1, (int32_t)uprv_strlen(javaClass1));
    678        }else{
    679            sprintf(constructor,javaClassICU,className);
    680            T_FileStream_write(out, constructor, (int32_t)uprv_strlen(constructor));
    681        }
    682     */
    683 
    684     if(outputEnc && *outputEnc!='\0'){
    685         /* store the output encoding */
    686         enc = outputEnc;
    687         conv=ucnv_open(enc,status);
    688         if(U_FAILURE(*status)){
    689             return;
    690         }
    691     }
    692     res_write_java(bundle->fRoot, status);
    693 
    694     T_FileStream_write(out, closeClass, (int32_t)uprv_strlen(closeClass));
    695 
    696     T_FileStream_close(out);
    697 
    698     ucnv_close(conv);
    699 }
    700