| // © 2016 and later: Unicode, Inc. and others. |
| // License & terms of use: http://www.unicode.org/copyright.html |
| /* |
| ******************************************************************************* |
| * |
| * Copyright (C) 2000-2015, International Business Machines |
| * Corporation and others. All Rights Reserved. |
| * |
| ******************************************************************************* |
| * |
| * File wrtjava.cpp |
| * |
| * Modification History: |
| * |
| * Date Name Description |
| * 01/11/02 Ram Creation. |
| * 02/12/08 Spieth Fix errant 'new Object[][]{' insertion |
| * 02/19/08 Spieth Removed ICUListResourceBundle dependancy |
| ******************************************************************************* |
| */ |
| |
| #include <assert.h> |
| #include "unicode/unistr.h" |
| #include "reslist.h" |
| #include "unewdata.h" |
| #include "unicode/ures.h" |
| #include "errmsg.h" |
| #include "filestrm.h" |
| #include "cstring.h" |
| #include "unicode/ucnv.h" |
| #include "genrb.h" |
| #include "rle.h" |
| #include "uhash.h" |
| #include "uresimp.h" |
| #include "unicode/ustring.h" |
| #include "unicode/utf8.h" |
| |
| void res_write_java(struct SResource *res,UErrorCode *status); |
| |
| |
| static const char copyRight[] = |
| "/* \n" |
| " *******************************************************************************\n" |
| " *\n" |
| " * Copyright (C) International Business Machines\n" |
| " * Corporation and others. All Rights Reserved.\n" |
| " *\n" |
| " *******************************************************************************\n" |
| " * $" "Source: $ \n" |
| " * $" "Date: $ \n" |
| " * $" "Revision: $ \n" |
| " *******************************************************************************\n" |
| " */\n\n"; |
| static const char warningMsg[] = |
| "/*********************************************************************\n" |
| "######################################################################\n" |
| "\n" |
| " WARNING: This file is generated by genrb Version " GENRB_VERSION ".\n" |
| " If you edit this file, please make sure that, the source\n" |
| " of this file (XXXX.txt in LocaleElements_XXXX.java)\n" |
| " is also edited.\n" |
| "######################################################################\n" |
| " *********************************************************************\n" |
| " */\n\n"; |
| static const char* openBrace="{\n"; |
| static const char* closeClass=" };\n" |
| "}\n"; |
| |
| static const char* javaClass = "import java.util.ListResourceBundle;\n\n" |
| "public class "; |
| |
| static const char* javaClass1= " extends ListResourceBundle {\n\n" |
| " /**\n" |
| " * Overrides ListResourceBundle \n" |
| " */\n" |
| " public final Object[][] getContents() { \n" |
| " return contents;\n" |
| " }\n\n" |
| " private static Object[][] contents = {\n"; |
| /*static const char* javaClassICU= " extends ListResourceBundle {\n\n" |
| " public %s () {\n" |
| " super.contents = data;\n" |
| " }\n" |
| " static final Object[][] data = new Object[][] { \n";*/ |
| static int tabCount = 3; |
| |
| static FileStream* out=NULL; |
| static struct SRBRoot* srBundle ; |
| /*static const char* outDir = NULL;*/ |
| |
| static const char* bName=NULL; |
| static const char* pName=NULL; |
| |
| static void write_tabs(FileStream* os){ |
| int i=0; |
| for(;i<=tabCount;i++){ |
| T_FileStream_write(os," ",4); |
| } |
| } |
| |
| #define ZERO 0x30 |
| |
| static const char* enc =""; |
| static UConverter* conv = NULL; |
| |
| static int32_t |
| uCharsToChars(char *target, int32_t targetLen, const UChar *source, int32_t sourceLen, UErrorCode *status) { |
| int i=0, j=0; |
| char str[30]={'\0'}; |
| while(i<sourceLen){ |
| if (source[i] == '\n') { |
| if (j + 2 < targetLen) { |
| uprv_strcat(target, "\\n"); |
| } |
| j += 2; |
| }else if(source[i]==0x0D){ |
| if(j+2<targetLen){ |
| uprv_strcat(target,"\\f"); |
| } |
| j+=2; |
| }else if(source[i] == '"'){ |
| if(source[i-1]=='\''){ |
| if(j+2<targetLen){ |
| uprv_strcat(target,"\\"); |
| target[j+1]= (char)source[i]; |
| } |
| j+=2; |
| }else if(source[i-1]!='\\'){ |
| |
| if(j+2<targetLen){ |
| uprv_strcat(target,"\\"); |
| target[j+1]= (char)source[i]; |
| } |
| j+=2; |
| }else if(source[i-1]=='\\'){ |
| target[j++]= (char)source[i]; |
| } |
| }else if(source[i]=='\\'){ |
| if(i+1<sourceLen){ |
| switch(source[i+1]){ |
| case ',': |
| case '!': |
| case '?': |
| case '#': |
| case '.': |
| case '%': |
| case '&': |
| case ':': |
| case ';': |
| if(j+2<targetLen){ |
| uprv_strcat(target,"\\\\"); |
| } |
| j+=2; |
| break; |
| case '"': |
| case '\'': |
| if(j+3<targetLen){ |
| uprv_strcat(target,"\\\\\\"); |
| } |
| j+=3; |
| break; |
| default : |
| if(j<targetLen){ |
| target[j]=(char)source[i]; |
| } |
| j++; |
| break; |
| } |
| }else{ |
| if(j<targetLen){ |
| uprv_strcat(target,"\\\\"); |
| } |
| j+=2; |
| } |
| }else if(source[i]>=0x20 && source[i]<0x7F/*ASCII*/){ |
| if(j<targetLen){ |
| target[j] = (char) source[i]; |
| } |
| j++; |
| }else{ |
| if(*enc =='\0' || source[i]==0x0000){ |
| uprv_strcpy(str,"\\u"); |
| itostr(str+2,source[i],16,4); |
| if(j+6<targetLen){ |
| uprv_strcat(target,str); |
| } |
| j+=6; |
| }else{ |
| char dest[30] = {0}; |
| int retVal=ucnv_fromUChars(conv,dest,30,source+i,1,status); |
| if(U_FAILURE(*status)){ |
| return 0; |
| } |
| if(j+retVal<targetLen){ |
| uprv_strcat(target,dest); |
| } |
| j+=retVal; |
| } |
| } |
| i++; |
| } |
| return j; |
| } |
| |
| |
| static uint32_t |
| strrch(const char* source,uint32_t sourceLen,char find){ |
| const char* tSourceEnd =source + (sourceLen-1); |
| while(tSourceEnd>= source){ |
| if(*tSourceEnd==find){ |
| return (uint32_t)(tSourceEnd-source); |
| } |
| tSourceEnd--; |
| } |
| return (uint32_t)(tSourceEnd-source); |
| } |
| |
| static int32_t getColumnCount(int32_t len){ |
| int32_t columnCount = 80; |
| int32_t maxLines = 3000; |
| int32_t adjustedLen = len*5; /* assume that every codepoint is represented in \uXXXX format*/ |
| /* |
| * calculate the number of lines that |
| * may be required if column count is 80 |
| */ |
| if (maxLines < (adjustedLen / columnCount) ){ |
| columnCount = adjustedLen / maxLines; |
| } |
| return columnCount; |
| } |
| static void |
| str_write_java(const UChar *src, int32_t srcLen, UBool printEndLine, UErrorCode *status) { |
| |
| uint32_t length = srcLen*8; |
| uint32_t bufLen = 0; |
| uint32_t columnCount; |
| char* buf = (char*) malloc(sizeof(char)*length); |
| |
| if(buf == NULL) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| return; |
| } |
| |
| columnCount = getColumnCount(srcLen); |
| memset(buf,0,length); |
| |
| bufLen = uCharsToChars(buf,length,src,srcLen,status); |
| // buflen accounts for extra bytes added due to multi byte encoding of |
| // non ASCII characters |
| if(printEndLine) |
| write_tabs(out); |
| |
| if(U_FAILURE(*status)){ |
| uprv_free(buf); |
| return; |
| } |
| |
| if(bufLen+(tabCount*4) > columnCount ){ |
| uint32_t len = 0; |
| char* current = buf; |
| uint32_t add; |
| while(len < bufLen){ |
| add = columnCount-(tabCount*4)-5/* for ", +\n */; |
| current = buf +len; |
| if (add < (bufLen-len)) { |
| uint32_t idx = strrch(current,add,'\\'); |
| if (idx > add) { |
| idx = add; |
| } else { |
| int32_t num =idx-1; |
| uint32_t seqLen; |
| while(num>0){ |
| if(current[num]=='\\'){ |
| num--; |
| }else{ |
| break; |
| } |
| } |
| if ((idx-num)%2==0) { |
| idx--; |
| } |
| seqLen = (current[idx+1]=='u') ? 6 : 2; |
| if ((add-idx) < seqLen) { |
| add = idx + seqLen; |
| } |
| } |
| } |
| T_FileStream_write(out,"\"",1); |
| uint32_t byteIndex = 0; |
| uint32_t trailBytes = 0; |
| if(len+add<bufLen){ |
| // check the trail bytes to be added to the output line |
| while (byteIndex < add) { |
| if (U8_IS_LEAD(*(current + byteIndex))) { |
| trailBytes = U8_COUNT_TRAIL_BYTES(*(current + byteIndex)); |
| add += trailBytes; |
| } |
| byteIndex++; |
| } |
| T_FileStream_write(out,current,add); |
| if (len + add < bufLen) { |
| T_FileStream_write(out,"\" +\n",4); |
| write_tabs(out); |
| } |
| }else{ |
| T_FileStream_write(out,current,bufLen-len); |
| } |
| len+=add; |
| } |
| }else{ |
| T_FileStream_write(out,"\"",1); |
| T_FileStream_write(out, buf,bufLen); |
| } |
| if(printEndLine){ |
| T_FileStream_write(out,"\",\n",3); |
| }else{ |
| T_FileStream_write(out,"\"",1); |
| } |
| uprv_free(buf); |
| } |
| |
| /* Writing Functions */ |
| static void |
| string_write_java(const StringResource *res,UErrorCode *status) { |
| (void)res->getKeyString(srBundle); |
| |
| str_write_java(res->getBuffer(), res->length(), TRUE, status); |
| } |
| |
| static void |
| array_write_java(const ArrayResource *res, UErrorCode *status) { |
| |
| uint32_t i = 0; |
| const char* arr ="new String[] { \n"; |
| struct SResource *current = NULL; |
| UBool allStrings = TRUE; |
| |
| if (U_FAILURE(*status)) { |
| return; |
| } |
| |
| if (res->fCount > 0) { |
| |
| current = res->fFirst; |
| i = 0; |
| while(current != NULL){ |
| if(!current->isString()){ |
| allStrings = FALSE; |
| break; |
| } |
| current= current->fNext; |
| } |
| |
| current = res->fFirst; |
| if(allStrings==FALSE){ |
| const char* object = "new Object[]{\n"; |
| write_tabs(out); |
| T_FileStream_write(out, object, (int32_t)uprv_strlen(object)); |
| tabCount++; |
| }else{ |
| write_tabs(out); |
| T_FileStream_write(out, arr, (int32_t)uprv_strlen(arr)); |
| tabCount++; |
| } |
| while (current != NULL) { |
| /*if(current->isString()){ |
| write_tabs(out); |
| }*/ |
| res_write_java(current, status); |
| if(U_FAILURE(*status)){ |
| return; |
| } |
| i++; |
| current = current->fNext; |
| } |
| T_FileStream_write(out,"\n",1); |
| |
| tabCount--; |
| write_tabs(out); |
| T_FileStream_write(out,"},\n",3); |
| |
| } else { |
| write_tabs(out); |
| T_FileStream_write(out,arr,(int32_t)uprv_strlen(arr)); |
| write_tabs(out); |
| T_FileStream_write(out,"},\n",3); |
| } |
| } |
| |
| static void |
| intvector_write_java(const IntVectorResource *res, UErrorCode * /*status*/) { |
| uint32_t i = 0; |
| const char* intArr = "new int[] {\n"; |
| /* const char* intC = "new Integer("; */ |
| const char* stringArr = "new String[]{\n"; |
| const char *resname = res->getKeyString(srBundle); |
| char buf[100]; |
| int len =0; |
| buf[0]=0; |
| write_tabs(out); |
| |
| if(resname != NULL && uprv_strcmp(resname,"DateTimeElements")==0){ |
| T_FileStream_write(out, stringArr, (int32_t)uprv_strlen(stringArr)); |
| tabCount++; |
| for(i = 0; i<res->fCount; i++) { |
| write_tabs(out); |
| len=itostr(buf,res->fArray[i],10,0); |
| T_FileStream_write(out,"\"",1); |
| T_FileStream_write(out,buf,len); |
| T_FileStream_write(out,"\",",2); |
| T_FileStream_write(out,"\n",1); |
| } |
| }else{ |
| T_FileStream_write(out, intArr, (int32_t)uprv_strlen(intArr)); |
| tabCount++; |
| for(i = 0; i<res->fCount; i++) { |
| write_tabs(out); |
| /* T_FileStream_write(out, intC, (int32_t)uprv_strlen(intC)); */ |
| len=itostr(buf,res->fArray[i],10,0); |
| T_FileStream_write(out,buf,len); |
| /* T_FileStream_write(out,"),",2); */ |
| /* T_FileStream_write(out,"\n",1); */ |
| T_FileStream_write(out,",\n",2); |
| } |
| } |
| tabCount--; |
| write_tabs(out); |
| T_FileStream_write(out,"},\n",3); |
| } |
| |
| static void |
| int_write_java(const IntResource *res, UErrorCode * /*status*/) { |
| const char* intC = "new Integer("; |
| char buf[100]; |
| int len =0; |
| buf[0]=0; |
| |
| /* write the binary data */ |
| write_tabs(out); |
| T_FileStream_write(out, intC, (int32_t)uprv_strlen(intC)); |
| len=itostr(buf, res->fValue, 10, 0); |
| T_FileStream_write(out,buf,len); |
| T_FileStream_write(out,"),\n",3 ); |
| |
| } |
| |
| static void |
| bytes_write_java(const BinaryResource *res, UErrorCode * /*status*/) { |
| const char* type = "new byte[] {"; |
| const char* byteDecl = "%i, "; |
| char byteBuffer[100] = { 0 }; |
| uint8_t* byteArray = NULL; |
| int byteIterator = 0; |
| int32_t srcLen=res->fLength; |
| if(srcLen>0 ) |
| { |
| byteArray = res->fData; |
| |
| write_tabs(out); |
| T_FileStream_write(out, type, (int32_t)uprv_strlen(type)); |
| T_FileStream_write(out, "\n", 1); |
| tabCount++; |
| |
| for (;byteIterator<srcLen;byteIterator++) |
| { |
| if (byteIterator%16 == 0) |
| { |
| write_tabs(out); |
| } |
| |
| if (byteArray[byteIterator] < 128) |
| { |
| sprintf(byteBuffer, byteDecl, byteArray[byteIterator]); |
| } |
| else |
| { |
| sprintf(byteBuffer, byteDecl, (byteArray[byteIterator]-256)); |
| } |
| |
| T_FileStream_write(out, byteBuffer, (int32_t)uprv_strlen(byteBuffer)); |
| |
| if (byteIterator%16 == 15) |
| { |
| T_FileStream_write(out, "\n", 1); |
| } |
| |
| } |
| |
| if (((byteIterator-1)%16) != 15) |
| { |
| T_FileStream_write(out, "\n", 1); |
| } |
| |
| tabCount--; |
| write_tabs(out); |
| T_FileStream_write(out, "},\n", 3); |
| |
| } |
| else |
| { |
| /* Empty array */ |
| write_tabs(out); |
| T_FileStream_write(out,type,(int32_t)uprv_strlen(type)); |
| T_FileStream_write(out,"},\n",3); |
| } |
| |
| } |
| |
| static UBool start = TRUE; |
| |
| static void |
| table_write_java(const TableResource *res, UErrorCode *status) { |
| uint32_t i = 0; |
| struct SResource *current = NULL; |
| const char* obj = "new Object[][]{\n"; |
| |
| if (U_FAILURE(*status)) { |
| return ; |
| } |
| |
| if (res->fCount > 0) { |
| if(start==FALSE){ |
| write_tabs(out); |
| T_FileStream_write(out, obj, (int32_t)uprv_strlen(obj)); |
| tabCount++; |
| } |
| start = FALSE; |
| current = res->fFirst; |
| i = 0; |
| |
| |
| while (current != NULL) { |
| const char *currentKeyString = current->getKeyString(srBundle); |
| |
| assert(i < res->fCount); |
| write_tabs(out); |
| |
| T_FileStream_write(out, openBrace, 2); |
| |
| |
| tabCount++; |
| |
| write_tabs(out); |
| if(currentKeyString != NULL) { |
| T_FileStream_write(out, "\"", 1); |
| T_FileStream_write(out, currentKeyString, |
| (int32_t)uprv_strlen(currentKeyString)); |
| T_FileStream_write(out, "\",\n", 2); |
| |
| T_FileStream_write(out, "\n", 1); |
| } |
| res_write_java(current, status); |
| if(U_FAILURE(*status)){ |
| return; |
| } |
| i++; |
| current = current->fNext; |
| tabCount--; |
| write_tabs(out); |
| T_FileStream_write(out, "},\n", 3); |
| } |
| if(tabCount>4){ |
| tabCount--; |
| write_tabs(out); |
| T_FileStream_write(out, "},\n", 3); |
| } |
| |
| } else { |
| write_tabs(out); |
| T_FileStream_write(out,obj,(int32_t)uprv_strlen(obj)); |
| |
| write_tabs(out); |
| T_FileStream_write(out,"},\n",3); |
| |
| } |
| |
| } |
| |
| void |
| res_write_java(struct SResource *res,UErrorCode *status) { |
| |
| if (U_FAILURE(*status)) { |
| return ; |
| } |
| |
| if (res != NULL) { |
| switch (res->fType) { |
| case URES_STRING: |
| string_write_java (static_cast<const StringResource *>(res), status); |
| return; |
| case URES_ALIAS: |
| printf("Encountered unsupported resource type %d of alias\n", res->fType); |
| *status = U_UNSUPPORTED_ERROR; |
| return; |
| case URES_INT_VECTOR: |
| intvector_write_java (static_cast<const IntVectorResource *>(res), status); |
| return; |
| case URES_BINARY: |
| bytes_write_java (static_cast<const BinaryResource *>(res), status); |
| return; |
| case URES_INT: |
| int_write_java (static_cast<const IntResource *>(res), status); |
| return; |
| case URES_ARRAY: |
| array_write_java (static_cast<const ArrayResource *>(res), status); |
| return; |
| case URES_TABLE: |
| table_write_java (static_cast<const TableResource *>(res), status); |
| return; |
| default: |
| break; |
| } |
| } |
| |
| *status = U_INTERNAL_PROGRAM_ERROR; |
| } |
| |
| 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) { |
| |
| char fileName[256] = {'\0'}; |
| char className[256]={'\0'}; |
| /*char constructor[1000] = { 0 };*/ |
| /*UBool j1 =FALSE;*/ |
| /*outDir = outputDir;*/ |
| |
| start = TRUE; /* Reset the start indictor*/ |
| |
| bName = (bundleName==NULL) ? "LocaleElements" : bundleName; |
| pName = (packageName==NULL)? "com.ibm.icu.impl.data" : packageName; |
| |
| uprv_strcpy(className, bName); |
| srBundle = bundle; |
| if(uprv_strcmp(srBundle->fLocale,"root")!=0){ |
| uprv_strcat(className,"_"); |
| uprv_strcat(className,srBundle->fLocale); |
| } |
| if(outputDir){ |
| uprv_strcpy(fileName, outputDir); |
| if(outputDir[uprv_strlen(outputDir)-1] !=U_FILE_SEP_CHAR){ |
| uprv_strcat(fileName,U_FILE_SEP_STRING); |
| } |
| uprv_strcat(fileName,className); |
| uprv_strcat(fileName,".java"); |
| }else{ |
| uprv_strcat(fileName,className); |
| uprv_strcat(fileName,".java"); |
| } |
| |
| if (writtenFilename) { |
| uprv_strncpy(writtenFilename, fileName, writtenFilenameLen); |
| } |
| |
| if (U_FAILURE(*status)) { |
| return; |
| } |
| |
| out= T_FileStream_open(fileName,"w"); |
| |
| if(out==NULL){ |
| *status = U_FILE_ACCESS_ERROR; |
| return; |
| } |
| if(getIncludeCopyright()){ |
| T_FileStream_write(out, copyRight, (int32_t)uprv_strlen(copyRight)); |
| T_FileStream_write(out, warningMsg, (int32_t)uprv_strlen(warningMsg)); |
| } |
| T_FileStream_write(out,"package ",(int32_t)uprv_strlen("package ")); |
| T_FileStream_write(out,pName,(int32_t)uprv_strlen(pName)); |
| T_FileStream_write(out,";\n\n",3); |
| T_FileStream_write(out, javaClass, (int32_t)uprv_strlen(javaClass)); |
| T_FileStream_write(out, className, (int32_t)uprv_strlen(className)); |
| T_FileStream_write(out, javaClass1, (int32_t)uprv_strlen(javaClass1)); |
| |
| /* if(j1){ |
| T_FileStream_write(out, javaClass1, (int32_t)uprv_strlen(javaClass1)); |
| }else{ |
| sprintf(constructor,javaClassICU,className); |
| T_FileStream_write(out, constructor, (int32_t)uprv_strlen(constructor)); |
| } |
| */ |
| |
| if(outputEnc && *outputEnc!='\0'){ |
| /* store the output encoding */ |
| enc = outputEnc; |
| conv=ucnv_open(enc,status); |
| if(U_FAILURE(*status)){ |
| return; |
| } |
| } |
| res_write_java(bundle->fRoot, status); |
| |
| T_FileStream_write(out, closeClass, (int32_t)uprv_strlen(closeClass)); |
| |
| T_FileStream_close(out); |
| |
| ucnv_close(conv); |
| } |