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