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