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