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