• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 *******************************************************************************
3 *
4 *   Copyright (C) 2000-2009, International Business Machines
5 *   Corporation and others.  All Rights Reserved.
6 *
7 *******************************************************************************
8 *
9 * File wrtjava.c
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 "reslist.h"
22 #include "unewdata.h"
23 #include "unicode/ures.h"
24 #include "errmsg.h"
25 #include "filestrm.h"
26 #include "cstring.h"
27 #include "unicode/ucnv.h"
28 #include "genrb.h"
29 #include "rle.h"
30 #include "ucol_tok.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,UChar * source,int32_t sourceLen,UErrorCode * status)104 uCharsToChars( char* target,int32_t targetLen, 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(uint16_t * src,int32_t srcLen,UBool printEndLine,UErrorCode * status)229 str_write_java( uint16_t* 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(struct SResource * res,UErrorCode * status)308 string_write_java(struct SResource *res,UErrorCode *status) {
309     char resKeyBuffer[8];
310     const char *resname = res_getKeyString(srBundle, res, resKeyBuffer);
311 
312     str_write_java(res->u.fString.fChars,res->u.fString.fLength,TRUE,status);
313 
314 	if(resname != NULL && uprv_strcmp(resname,"Rule")==0)
315 	{
316         UChar* buf = (UChar*) uprv_malloc(sizeof(UChar)*res->u.fString.fLength);
317         uprv_memcpy(buf,res->u.fString.fChars,res->u.fString.fLength);
318         uprv_free(buf);
319     }
320 
321 }
322 
323 static void
array_write_java(struct SResource * res,UErrorCode * status)324 array_write_java( struct SResource *res, UErrorCode *status) {
325 
326     uint32_t  i         = 0;
327     const char* arr ="new String[] { \n";
328     struct SResource *current = NULL;
329     struct SResource *first =NULL;
330     UBool decrementTabs = FALSE;
331     UBool allStrings    = TRUE;
332 
333     if (U_FAILURE(*status)) {
334         return;
335     }
336 
337     if (res->u.fArray.fCount > 0) {
338 
339         current = res->u.fArray.fFirst;
340         i = 0;
341         while(current != NULL){
342             if(current->fType!=URES_STRING){
343                 allStrings = FALSE;
344                 break;
345             }
346             current= current->fNext;
347         }
348 
349         current = res->u.fArray.fFirst;
350         if(allStrings==FALSE){
351             const char* object = "new Object[]{\n";
352             write_tabs(out);
353             T_FileStream_write(out, object, (int32_t)uprv_strlen(object));
354             tabCount++;
355             decrementTabs = TRUE;
356         }else{
357             write_tabs(out);
358             T_FileStream_write(out, arr, (int32_t)uprv_strlen(arr));
359             tabCount++;
360         }
361         first=current;
362         while (current != NULL) {
363             /*if(current->fType==URES_STRING){
364                 write_tabs(out);
365             }*/
366             res_write_java(current, status);
367             if(U_FAILURE(*status)){
368                 return;
369             }
370             i++;
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,(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(struct SResource * res,UErrorCode * status)388 intvector_write_java( struct SResource *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     char resKeyBuffer[8];
394     const char *resname = res_getKeyString(srBundle, res, resKeyBuffer);
395     char buf[100];
396     int len =0;
397     buf[0]=0;
398     write_tabs(out);
399 
400     if(resname != NULL && uprv_strcmp(resname,"DateTimeElements")==0){
401         T_FileStream_write(out, stringArr, (int32_t)uprv_strlen(stringArr));
402         tabCount++;
403         for(i = 0; i<res->u.fIntVector.fCount; i++) {
404             write_tabs(out);
405             len=itostr(buf,res->u.fIntVector.fArray[i],10,0);
406             T_FileStream_write(out,"\"",1);
407             T_FileStream_write(out,buf,len);
408             T_FileStream_write(out,"\",",2);
409             T_FileStream_write(out,"\n",1);
410         }
411     }else{
412         T_FileStream_write(out, intArr, (int32_t)uprv_strlen(intArr));
413         tabCount++;
414         for(i = 0; i<res->u.fIntVector.fCount; i++) {
415             write_tabs(out);
416             /* T_FileStream_write(out, intC, (int32_t)uprv_strlen(intC)); */
417             len=itostr(buf,res->u.fIntVector.fArray[i],10,0);
418             T_FileStream_write(out,buf,len);
419             /* T_FileStream_write(out,"),",2);  */
420             /* T_FileStream_write(out,"\n",1);  */
421             T_FileStream_write(out,",\n",2);
422         }
423     }
424     tabCount--;
425     write_tabs(out);
426     T_FileStream_write(out,"},\n",3);
427 }
428 
429 static void
int_write_java(struct SResource * res,UErrorCode * status)430 int_write_java(struct SResource *res,UErrorCode *status) {
431     const char* intC   =  "new Integer(";
432     char buf[100];
433     int len =0;
434     buf[0]=0;
435 
436     /* write the binary data */
437     write_tabs(out);
438     T_FileStream_write(out, intC, (int32_t)uprv_strlen(intC));
439     len=itostr(buf, res->u.fIntValue.fValue, 10, 0);
440     T_FileStream_write(out,buf,len);
441     T_FileStream_write(out,"),\n",3 );
442 
443 }
444 
445 static void
bytes_write_java(struct SResource * res,UErrorCode * status)446 bytes_write_java( struct SResource *res, UErrorCode *status) {
447 	const char* type  = "new byte[] {";
448 	const char* byteDecl = "%i, ";
449     char byteBuffer[100] = { 0 };
450 	uint8_t*  byteArray = NULL;
451     int byteIterator = 0;
452 
453     int32_t srcLen=res->u.fBinaryValue.fLength;
454 
455     if(srcLen>0 )
456 	{
457         byteArray = res->u.fBinaryValue.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
table_write_java(struct SResource * res,UErrorCode * status)512 table_write_java(struct SResource *res, UErrorCode *status) {
513     uint32_t  i         = 0;
514     UBool allStrings =TRUE;
515     struct SResource *current = NULL;
516     struct SResource *save = NULL;
517     const char* obj = "new Object[][]{\n";
518 
519     if (U_FAILURE(*status)) {
520         return ;
521     }
522 
523     if (res->u.fTable.fCount > 0) {
524         if(start==FALSE){
525             write_tabs(out);
526             T_FileStream_write(out, obj, (int32_t)uprv_strlen(obj));
527             tabCount++;
528         }
529         start = FALSE;
530         save = current = res->u.fTable.fFirst;
531         i       = 0;
532 
533 
534         while (current != NULL) {
535             char currentKeyBuffer[8];
536             const char *currentKeyString = res_getKeyString(srBundle, current, currentKeyBuffer);
537 
538             assert(i < res->u.fTable.fCount);
539             write_tabs(out);
540 
541             T_FileStream_write(out, openBrace, 2);
542 
543 
544             tabCount++;
545             allStrings=FALSE;
546 
547             write_tabs(out);
548             if(currentKeyString != NULL) {
549                 T_FileStream_write(out, "\"", 1);
550                 T_FileStream_write(out, currentKeyString,
551                                    (int32_t)uprv_strlen(currentKeyString));
552                 T_FileStream_write(out, "\",\n", 2);
553 
554                 T_FileStream_write(out, "\n", 1);
555             }
556             res_write_java(current, status);
557             if(U_FAILURE(*status)){
558                 return;
559             }
560             i++;
561             current = current->fNext;
562             tabCount--;
563             write_tabs(out);
564             T_FileStream_write(out, "},\n", 3);
565         }
566         if(tabCount>4){
567             tabCount--;
568             write_tabs(out);
569             T_FileStream_write(out, "},\n", 3);
570         }
571 
572     } else {
573         write_tabs(out);
574         T_FileStream_write(out,obj,(int32_t)uprv_strlen(obj));
575 
576         write_tabs(out);
577         T_FileStream_write(out,"},\n",3);
578 
579     }
580 
581 }
582 
583 void
res_write_java(struct SResource * res,UErrorCode * status)584 res_write_java(struct SResource *res,UErrorCode *status) {
585 
586     if (U_FAILURE(*status)) {
587         return ;
588     }
589 
590     if (res != NULL) {
591         switch (res->fType) {
592         case URES_STRING:
593              string_write_java    (res, status);
594              return;
595         case URES_ALIAS:
596              printf("Encountered unsupported resource type %d of alias\n", res->fType);
597              *status = U_UNSUPPORTED_ERROR;
598 			 return;
599         case URES_INT_VECTOR:
600              intvector_write_java (res, status);
601              return;
602         case URES_BINARY:
603              bytes_write_java     (res, status);
604              return;
605         case URES_INT:
606              int_write_java       (res, status);
607              return;
608         case URES_ARRAY:
609              array_write_java     (res, status);
610              return;
611         case URES_TABLE:
612              table_write_java     (res, status);
613              return;
614         default:
615             break;
616         }
617     }
618 
619     *status = U_INTERNAL_PROGRAM_ERROR;
620 }
621 
622 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)623 bundle_write_java(struct SRBRoot *bundle, const char *outputDir,const char* outputEnc,
624                   char *writtenFilename, int writtenFilenameLen,
625                   const char* packageName, const char* bundleName,
626                   UErrorCode *status) {
627 
628     char fileName[256] = {'\0'};
629     char className[256]={'\0'};
630     /*char constructor[1000] = { 0 };*/
631     /*UBool j1 =FALSE;*/
632     outDir = outputDir;
633 
634     start = TRUE;                        /* Reset the start indictor*/
635 
636     bName = (bundleName==NULL) ? "LocaleElements" : bundleName;
637     pName = (packageName==NULL)? "com.ibm.icu.impl.data" : packageName;
638 
639     uprv_strcpy(className, bName);
640     srBundle = bundle;
641     if(uprv_strcmp(srBundle->fLocale,"root")!=0){
642         uprv_strcat(className,"_");
643         uprv_strcat(className,srBundle->fLocale);
644     }
645     if(outputDir){
646         uprv_strcpy(fileName, outputDir);
647         if(outputDir[uprv_strlen(outputDir)-1] !=U_FILE_SEP_CHAR){
648             uprv_strcat(fileName,U_FILE_SEP_STRING);
649         }
650         uprv_strcat(fileName,className);
651         uprv_strcat(fileName,".java");
652     }else{
653         uprv_strcat(fileName,className);
654         uprv_strcat(fileName,".java");
655     }
656 
657     if (writtenFilename) {
658         uprv_strncpy(writtenFilename, fileName, writtenFilenameLen);
659     }
660 
661     if (U_FAILURE(*status)) {
662         return;
663     }
664 
665     out= T_FileStream_open(fileName,"w");
666 
667     if(out==NULL){
668         *status = U_FILE_ACCESS_ERROR;
669         return;
670     }
671     if(getIncludeCopyright()){
672         T_FileStream_write(out, copyRight, (int32_t)uprv_strlen(copyRight));
673         T_FileStream_write(out, warningMsg, (int32_t)uprv_strlen(warningMsg));
674     }
675     T_FileStream_write(out,"package ",(int32_t)uprv_strlen("package "));
676     T_FileStream_write(out,pName,(int32_t)uprv_strlen(pName));
677     T_FileStream_write(out,";\n\n",3);
678     T_FileStream_write(out, javaClass, (int32_t)uprv_strlen(javaClass));
679     T_FileStream_write(out, className, (int32_t)uprv_strlen(className));
680 	T_FileStream_write(out, javaClass1, (int32_t)uprv_strlen(javaClass1));
681 
682     /* if(j1){
683           T_FileStream_write(out, javaClass1, (int32_t)uprv_strlen(javaClass1));
684        }else{
685            sprintf(constructor,javaClassICU,className);
686            T_FileStream_write(out, constructor, (int32_t)uprv_strlen(constructor));
687        }
688     */
689 
690     if(outputEnc && *outputEnc!='\0'){
691         /* store the output encoding */
692         enc = outputEnc;
693         conv=ucnv_open(enc,status);
694         if(U_FAILURE(*status)){
695             return;
696         }
697     }
698     res_write_java(bundle->fRoot, status);
699 
700     T_FileStream_write(out, closeClass, (int32_t)uprv_strlen(closeClass));
701 
702     T_FileStream_close(out);
703 
704     ucnv_close(conv);
705 }
706