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