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