static int32_t getTypeEnumForInputData(const uint8_t *data, int32_t length, UErrorCode *pErrorCode) { const UDataInfo *pInfo; int32_t infoLength, headerLength; /* getDataInfo() checks for illegal arguments */ pInfo=getDataInfo(data, length, infoLength, headerLength, pErrorCode); if(pInfo==NULL) { return -1; } return makeTypeEnum(pInfo->charsetFamily, (UBool)pInfo->isBigEndian); }
static void makeTypeProps(char type, uint8_t &charset, UBool &isBigEndian) { int32_t typeEnum=makeTypeEnum(type); charset=(uint8_t)(typeEnum>>1); isBigEndian=(UBool)(typeEnum&1); }
static inline char makeTypeLetter(uint8_t charset, UBool isBigEndian) { return types[makeTypeEnum(charset, isBigEndian)]; }
void Package::writePackage(const char *filename, char outType, const char *comment) { char prefix[MAX_PKG_NAME_LENGTH+4]; UDataOffsetTOCEntry entry; UDataSwapper *dsLocalToOut, *ds[TYPE_COUNT]; FILE *file; Item *pItem; char *name; UErrorCode errorCode; int32_t i, length, prefixLength, maxItemLength, basenameOffset, offset, outInt32; uint8_t outCharset; UBool outIsBigEndian; extractPackageName(filename, prefix, MAX_PKG_NAME_LENGTH); // if there is an explicit comment, then use it, else use what's in the current header if(comment!=NULL) { /* get the header size minus the current comment */ DataHeader *pHeader; int32_t length; pHeader=(DataHeader *)header; headerLength=4+pHeader->info.size; length=(int32_t)strlen(comment); if((int32_t)(headerLength+length)>=(int32_t)sizeof(header)) { fprintf(stderr, "icupkg: comment too long\n"); exit(U_BUFFER_OVERFLOW_ERROR); } memcpy(header+headerLength, comment, length+1); headerLength+=length; if(headerLength&0xf) { /* NUL-pad the header to a multiple of 16 */ length=(headerLength+0xf)&~0xf; memset(header+headerLength, 0, length-headerLength); headerLength=length; } pHeader->dataHeader.headerSize=(uint16_t)headerLength; } makeTypeProps(outType, outCharset, outIsBigEndian); // open (TYPE_COUNT-2) swappers // one is a no-op for local type==outType // one type (TYPE_LE) is bogus errorCode=U_ZERO_ERROR; i=makeTypeEnum(outType); ds[TYPE_B]= i==TYPE_B ? NULL : udata_openSwapper(TRUE, U_ASCII_FAMILY, outIsBigEndian, outCharset, &errorCode); ds[TYPE_L]= i==TYPE_L ? NULL : udata_openSwapper(FALSE, U_ASCII_FAMILY, outIsBigEndian, outCharset, &errorCode); ds[TYPE_LE]=NULL; ds[TYPE_E]= i==TYPE_E ? NULL : udata_openSwapper(TRUE, U_EBCDIC_FAMILY, outIsBigEndian, outCharset, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "icupkg: udata_openSwapper() failed - %s\n", u_errorName(errorCode)); exit(errorCode); } for(i=0; i<TYPE_COUNT; ++i) { if(ds[i]!=NULL) { ds[i]->printError=printPackageError; ds[i]->printErrorContext=stderr; } } dsLocalToOut=ds[makeTypeEnum(U_CHARSET_FAMILY, U_IS_BIG_ENDIAN)]; // create the file and write its contents file=fopen(filename, "wb"); if(file==NULL) { fprintf(stderr, "icupkg: unable to create file \"%s\"\n", filename); exit(U_FILE_ACCESS_ERROR); } // swap and write the header if(dsLocalToOut!=NULL) { udata_swapDataHeader(dsLocalToOut, header, headerLength, header, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "icupkg: udata_swapDataHeader(local to out) failed - %s\n", u_errorName(errorCode)); exit(errorCode); } } length=(int32_t)fwrite(header, 1, headerLength, file); if(length!=headerLength) { fprintf(stderr, "icupkg: unable to write complete header to file \"%s\"\n", filename); exit(U_FILE_ACCESS_ERROR); } // prepare and swap the package name with a tree separator // for prepending to item names strcat(prefix, U_TREE_ENTRY_SEP_STRING); prefixLength=(int32_t)strlen(prefix); if(dsLocalToOut!=NULL) { dsLocalToOut->swapInvChars(dsLocalToOut, prefix, prefixLength, prefix, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "icupkg: swapInvChars(output package name) failed - %s\n", u_errorName(errorCode)); exit(errorCode); } // swap and sort the item names (sorting needs to be done in the output charset) dsLocalToOut->swapInvChars(dsLocalToOut, inStrings, inStringTop, inStrings, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "icupkg: swapInvChars(item names) failed - %s\n", u_errorName(errorCode)); exit(errorCode); } sortItems(); } // create the output item names in sorted order, with the package name prepended to each for(i=0; i<itemCount; ++i) { length=(int32_t)strlen(items[i].name); name=allocString(FALSE, length+prefixLength); memcpy(name, prefix, prefixLength); memcpy(name+prefixLength, items[i].name, length+1); items[i].name=name; } // calculate offsets for item names and items, pad to 16-align items // align only the first item; each item's length is a multiple of 16 basenameOffset=4+8*itemCount; offset=basenameOffset+outStringTop; if((length=(offset&15))!=0) { length=16-length; memset(allocString(FALSE, length-1), 0xaa, length); offset+=length; } // write the table of contents // first the itemCount outInt32=itemCount; if(dsLocalToOut!=NULL) { dsLocalToOut->swapArray32(dsLocalToOut, &outInt32, 4, &outInt32, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "icupkg: swapArray32(item count) failed - %s\n", u_errorName(errorCode)); exit(errorCode); } } length=(int32_t)fwrite(&outInt32, 1, 4, file); if(length!=4) { fprintf(stderr, "icupkg: unable to write complete item count to file \"%s\"\n", filename); exit(U_FILE_ACCESS_ERROR); } // then write the item entries (and collect the maxItemLength) maxItemLength=0; for(i=0; i<itemCount; ++i) { entry.nameOffset=(uint32_t)(basenameOffset+(items[i].name-outStrings)); entry.dataOffset=(uint32_t)offset; if(dsLocalToOut!=NULL) { dsLocalToOut->swapArray32(dsLocalToOut, &entry, 8, &entry, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "icupkg: swapArray32(item entry %ld) failed - %s\n", (long)i, u_errorName(errorCode)); exit(errorCode); } } length=(int32_t)fwrite(&entry, 1, 8, file); if(length!=8) { fprintf(stderr, "icupkg: unable to write complete item entry %ld to file \"%s\"\n", (long)i, filename); exit(U_FILE_ACCESS_ERROR); } length=items[i].length; if(length>maxItemLength) { maxItemLength=length; } offset+=length; } // write the item names length=(int32_t)fwrite(outStrings, 1, outStringTop, file); if(length!=outStringTop) { fprintf(stderr, "icupkg: unable to write complete item names to file \"%s\"\n", filename); exit(U_FILE_ACCESS_ERROR); } // write the items for(pItem=items, i=0; i<itemCount; ++pItem, ++i) { int32_t type=makeTypeEnum(pItem->type); if(ds[type]!=NULL) { // swap each item from its platform properties to the desired ones udata_swap( ds[type], pItem->data, pItem->length, pItem->data, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "icupkg: udata_swap(item %ld) failed - %s\n", (long)i, u_errorName(errorCode)); exit(errorCode); } } length=(int32_t)fwrite(pItem->data, 1, pItem->length, file); if(length!=pItem->length) { fprintf(stderr, "icupkg: unable to write complete item %ld to file \"%s\"\n", (long)i, filename); exit(U_FILE_ACCESS_ERROR); } } if(ferror(file)) { fprintf(stderr, "icupkg: unable to write complete file \"%s\"\n", filename); exit(U_FILE_ACCESS_ERROR); } fclose(file); for(i=0; i<TYPE_COUNT; ++i) { udata_closeSwapper(ds[i]); } }