Imported Upstream version 58.1
[platform/upstream/icu.git] / source / tools / genrb / wrtjava.cpp
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 }