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