wrtjava.cpp (21405B)
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 dependency 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 38 void res_write_java(struct SResource *res,UErrorCode *status); 39 40 41 static 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"; 54 static 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"; 65 static const char* openBrace="{\n"; 66 static const char* closeClass=" };\n" 67 "}\n"; 68 69 static const char* javaClass = "import java.util.ListResourceBundle;\n\n" 70 "public class "; 71 72 static 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";*/ 85 static int tabCount = 3; 86 87 static FileStream* out=nullptr; 88 static struct SRBRoot* srBundle ; 89 /*static const char* outDir = nullptr;*/ 90 91 static const char* bName=nullptr; 92 static const char* pName=nullptr; 93 94 static 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 103 static const char* enc =""; 104 static UConverter* conv = nullptr; 105 106 static int32_t 107 uCharsToChars(char *target, int32_t targetLen, const char16_t *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] = static_cast<char>(source[i]); 126 } 127 j+=2; 128 }else if(source[i-1]!='\\'){ 129 if(j+2<targetLen){ 130 uprv_strcat(target,"\\"); 131 target[j + 1] = static_cast<char>(source[i]); 132 } 133 j+=2; 134 }else{ 135 target[j++] = static_cast<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] = static_cast<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] = static_cast<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 205 static uint32_t 206 strrch(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 static_cast<uint32_t>(tSourceEnd - source); 211 } 212 tSourceEnd--; 213 } 214 return static_cast<uint32_t>(tSourceEnd - source); 215 } 216 217 static 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 } 230 static void 231 str_write_java(const char16_t *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 = static_cast<char*>(malloc(sizeof(char) * length)); 237 238 if(buf == nullptr) { 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 // buflen accounts for extra bytes added due to multi byte encoding of 248 // non ASCII characters 249 if(printEndLine) 250 write_tabs(out); 251 252 if(U_FAILURE(*status)){ 253 uprv_free(buf); 254 return; 255 } 256 257 if(bufLen+(tabCount*4) > columnCount ){ 258 uint32_t len = 0; 259 char* current = buf; 260 uint32_t add; 261 while(len < bufLen){ 262 add = columnCount-(tabCount*4)-5/* for ", +\n */; 263 current = buf +len; 264 if (add < (bufLen-len)) { 265 uint32_t idx = strrch(current,add,'\\'); 266 if (idx > add) { 267 idx = add; 268 } else { 269 int32_t num =idx-1; 270 uint32_t seqLen; 271 while(num>0){ 272 if(current[num]=='\\'){ 273 num--; 274 }else{ 275 break; 276 } 277 } 278 if ((idx-num)%2==0) { 279 idx--; 280 } 281 seqLen = (current[idx+1]=='u') ? 6 : 2; 282 if ((add-idx) < seqLen) { 283 add = idx + seqLen; 284 } 285 } 286 } 287 T_FileStream_write(out,"\"",1); 288 uint32_t byteIndex = 0; 289 uint32_t trailBytes = 0; 290 if(len+add<bufLen){ 291 // check the trail bytes to be added to the output line 292 while (byteIndex < add) { 293 if (U8_IS_LEAD(*(current + byteIndex))) { 294 trailBytes = U8_COUNT_TRAIL_BYTES(*(current + byteIndex)); 295 add += trailBytes; 296 } 297 byteIndex++; 298 } 299 T_FileStream_write(out,current,add); 300 if (len + add < bufLen) { 301 T_FileStream_write(out,"\" +\n",4); 302 write_tabs(out); 303 } 304 }else{ 305 T_FileStream_write(out,current,bufLen-len); 306 } 307 len+=add; 308 } 309 }else{ 310 T_FileStream_write(out,"\"",1); 311 T_FileStream_write(out, buf,bufLen); 312 } 313 if(printEndLine){ 314 T_FileStream_write(out,"\",\n",3); 315 }else{ 316 T_FileStream_write(out,"\"",1); 317 } 318 uprv_free(buf); 319 } 320 321 /* Writing Functions */ 322 static void 323 string_write_java(const StringResource *res,UErrorCode *status) { 324 (void)res->getKeyString(srBundle); 325 326 str_write_java(res->getBuffer(), res->length(), true, status); 327 } 328 329 static void 330 array_write_java(const ArrayResource *res, UErrorCode *status) { 331 332 const char* arr ="new String[] { \n"; 333 struct SResource *current = nullptr; 334 UBool allStrings = true; 335 336 if (U_FAILURE(*status)) { 337 return; 338 } 339 340 if (res->fCount > 0) { 341 342 current = res->fFirst; 343 while(current != nullptr){ 344 if(!current->isString()){ 345 allStrings = false; 346 break; 347 } 348 current= current->fNext; 349 } 350 351 current = res->fFirst; 352 if(allStrings==false){ 353 const char* object = "new Object[]{\n"; 354 write_tabs(out); 355 T_FileStream_write(out, object, static_cast<int32_t>(uprv_strlen(object))); 356 tabCount++; 357 }else{ 358 write_tabs(out); 359 T_FileStream_write(out, arr, static_cast<int32_t>(uprv_strlen(arr))); 360 tabCount++; 361 } 362 while (current != nullptr) { 363 /*if(current->isString()){ 364 write_tabs(out); 365 }*/ 366 res_write_java(current, status); 367 if(U_FAILURE(*status)){ 368 return; 369 } 370 current = current->fNext; 371 } 372 T_FileStream_write(out,"\n",1); 373 374 tabCount--; 375 write_tabs(out); 376 T_FileStream_write(out,"},\n",3); 377 378 } else { 379 write_tabs(out); 380 T_FileStream_write(out, arr, static_cast<int32_t>(uprv_strlen(arr))); 381 write_tabs(out); 382 T_FileStream_write(out,"},\n",3); 383 } 384 } 385 386 static void 387 intvector_write_java(const IntVectorResource *res, UErrorCode * /*status*/) { 388 uint32_t i = 0; 389 const char* intArr = "new int[] {\n"; 390 /* const char* intC = "new Integer("; */ 391 const char* stringArr = "new String[]{\n"; 392 const char *resname = res->getKeyString(srBundle); 393 char buf[100]; 394 int len =0; 395 buf[0]=0; 396 write_tabs(out); 397 398 if(resname != nullptr && uprv_strcmp(resname,"DateTimeElements")==0){ 399 T_FileStream_write(out, stringArr, static_cast<int32_t>(uprv_strlen(stringArr))); 400 tabCount++; 401 for(i = 0; i<res->fCount; i++) { 402 write_tabs(out); 403 len=itostr(buf,res->fArray[i],10,0); 404 T_FileStream_write(out,"\"",1); 405 T_FileStream_write(out,buf,len); 406 T_FileStream_write(out,"\",",2); 407 T_FileStream_write(out,"\n",1); 408 } 409 }else{ 410 T_FileStream_write(out, intArr, static_cast<int32_t>(uprv_strlen(intArr))); 411 tabCount++; 412 for(i = 0; i<res->fCount; i++) { 413 write_tabs(out); 414 /* T_FileStream_write(out, intC, (int32_t)uprv_strlen(intC)); */ 415 len=itostr(buf,res->fArray[i],10,0); 416 T_FileStream_write(out,buf,len); 417 /* T_FileStream_write(out,"),",2); */ 418 /* T_FileStream_write(out,"\n",1); */ 419 T_FileStream_write(out,",\n",2); 420 } 421 } 422 tabCount--; 423 write_tabs(out); 424 T_FileStream_write(out,"},\n",3); 425 } 426 427 static void 428 int_write_java(const IntResource *res, UErrorCode * /*status*/) { 429 const char* intC = "new Integer("; 430 char buf[100]; 431 int len =0; 432 buf[0]=0; 433 434 /* write the binary data */ 435 write_tabs(out); 436 T_FileStream_write(out, intC, static_cast<int32_t>(uprv_strlen(intC))); 437 len=itostr(buf, res->fValue, 10, 0); 438 T_FileStream_write(out,buf,len); 439 T_FileStream_write(out,"),\n",3 ); 440 441 } 442 443 static void 444 bytes_write_java(const BinaryResource *res, UErrorCode * /*status*/) { 445 const char* type = "new byte[] {"; 446 const char* byteDecl = "%i, "; 447 char byteBuffer[100] = { 0 }; 448 uint8_t* byteArray = nullptr; 449 int byteIterator = 0; 450 int32_t srcLen=res->fLength; 451 if(srcLen>0 ) 452 { 453 byteArray = res->fData; 454 455 write_tabs(out); 456 T_FileStream_write(out, type, static_cast<int32_t>(uprv_strlen(type))); 457 T_FileStream_write(out, "\n", 1); 458 tabCount++; 459 460 for (;byteIterator<srcLen;byteIterator++) 461 { 462 if (byteIterator%16 == 0) 463 { 464 write_tabs(out); 465 } 466 467 if (byteArray[byteIterator] < 128) 468 { 469 snprintf(byteBuffer, sizeof(byteBuffer), byteDecl, byteArray[byteIterator]); 470 } 471 else 472 { 473 snprintf(byteBuffer, sizeof(byteBuffer), byteDecl, (byteArray[byteIterator]-256)); 474 } 475 476 T_FileStream_write(out, byteBuffer, static_cast<int32_t>(uprv_strlen(byteBuffer))); 477 478 if (byteIterator%16 == 15) 479 { 480 T_FileStream_write(out, "\n", 1); 481 } 482 483 } 484 485 if (((byteIterator-1)%16) != 15) 486 { 487 T_FileStream_write(out, "\n", 1); 488 } 489 490 tabCount--; 491 write_tabs(out); 492 T_FileStream_write(out, "},\n", 3); 493 494 } 495 else 496 { 497 /* Empty array */ 498 write_tabs(out); 499 T_FileStream_write(out, type, static_cast<int32_t>(uprv_strlen(type))); 500 T_FileStream_write(out,"},\n",3); 501 } 502 503 } 504 505 static UBool start = true; 506 507 static void 508 table_write_java(const TableResource *res, UErrorCode *status) { 509 uint32_t i = 0; 510 struct SResource *current = nullptr; 511 const char* obj = "new Object[][]{\n"; 512 513 if (U_FAILURE(*status)) { 514 return ; 515 } 516 517 if (res->fCount > 0) { 518 if(start==false){ 519 write_tabs(out); 520 T_FileStream_write(out, obj, static_cast<int32_t>(uprv_strlen(obj))); 521 tabCount++; 522 } 523 start = false; 524 current = res->fFirst; 525 i = 0; 526 527 528 while (current != nullptr) { 529 const char *currentKeyString = current->getKeyString(srBundle); 530 531 assert(i < res->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 != nullptr) { 541 T_FileStream_write(out, "\"", 1); 542 T_FileStream_write(out, currentKeyString, 543 static_cast<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, static_cast<int32_t>(uprv_strlen(obj))); 567 568 write_tabs(out); 569 T_FileStream_write(out,"},\n",3); 570 571 } 572 573 } 574 575 void 576 res_write_java(struct SResource *res,UErrorCode *status) { 577 578 if (U_FAILURE(*status)) { 579 return ; 580 } 581 582 if (res != nullptr) { 583 switch (res->fType) { 584 case URES_STRING: 585 string_write_java (static_cast<const StringResource *>(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 (static_cast<const IntVectorResource *>(res), status); 593 return; 594 case URES_BINARY: 595 bytes_write_java (static_cast<const BinaryResource *>(res), status); 596 return; 597 case URES_INT: 598 int_write_java (static_cast<const IntResource *>(res), status); 599 return; 600 case URES_ARRAY: 601 array_write_java (static_cast<const ArrayResource *>(res), status); 602 return; 603 case URES_TABLE: 604 table_write_java (static_cast<const TableResource *>(res), status); 605 return; 606 default: 607 break; 608 } 609 } 610 611 *status = U_INTERNAL_PROGRAM_ERROR; 612 } 613 614 void 615 bundle_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 indicator*/ 627 628 bName = (bundleName==nullptr) ? "LocaleElements" : bundleName; 629 pName = (packageName==nullptr)? "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==nullptr){ 660 *status = U_FILE_ACCESS_ERROR; 661 return; 662 } 663 if(getIncludeCopyright()){ 664 T_FileStream_write(out, copyRight, static_cast<int32_t>(uprv_strlen(copyRight))); 665 T_FileStream_write(out, warningMsg, static_cast<int32_t>(uprv_strlen(warningMsg))); 666 } 667 T_FileStream_write(out, "package ", static_cast<int32_t>(uprv_strlen("package "))); 668 T_FileStream_write(out, pName, static_cast<int32_t>(uprv_strlen(pName))); 669 T_FileStream_write(out,";\n\n",3); 670 T_FileStream_write(out, javaClass, static_cast<int32_t>(uprv_strlen(javaClass))); 671 T_FileStream_write(out, className, static_cast<int32_t>(uprv_strlen(className))); 672 T_FileStream_write(out, javaClass1, static_cast<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, static_cast<int32_t>(uprv_strlen(closeClass))); 693 694 T_FileStream_close(out); 695 696 ucnv_close(conv); 697 }