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