X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/73c04bcfe1096173b00431f0cdc742894b15eef0..0f5d89e82340278ed3d7d50029f37cab2c41a57e:/icuSources/tools/toolutil/package.cpp diff --git a/icuSources/tools/toolutil/package.cpp b/icuSources/tools/toolutil/package.cpp index 2bc9a504..d96c6dd3 100644 --- a/icuSources/tools/toolutil/package.cpp +++ b/icuSources/tools/toolutil/package.cpp @@ -1,12 +1,14 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /* ******************************************************************************* * -* Copyright (C) 1999-2006, International Business Machines +* Copyright (C) 1999-2015, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* * file name: package.cpp -* encoding: US-ASCII +* encoding: UTF-8 * tab size: 8 (not used) * indentation:4 * @@ -31,14 +33,16 @@ #include "swapimpl.h" #include "toolutil.h" #include "package.h" +#include "cmemory.h" #include #include #include -// general definitions ----------------------------------------------------- *** -#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) +static const int32_t kItemsChunk = 256; /* How much to increase the filesarray by each time */ + +// general definitions ----------------------------------------------------- *** /* UDataInfo cf. udata.h */ static const UDataInfo dataInfo={ @@ -302,7 +306,6 @@ static uint8_t * readFile(const char *path, const char *name, int32_t &length, char &type) { char filename[1024]; FILE *file; - uint8_t *data; UErrorCode errorCode; int32_t fileLength, typeEnum; @@ -325,38 +328,42 @@ readFile(const char *path, const char *name, int32_t &length, char &type) { /* allocate the buffer, pad to multiple of 16 */ length=(fileLength+0xf)&~0xf; - data=(uint8_t *)malloc(length); - if(data==NULL) { + icu::LocalMemory data((uint8_t *)uprv_malloc(length)); + if(data.isNull()) { fclose(file); + fprintf(stderr, "icupkg: malloc error allocating %d bytes.\n", (int)length); exit(U_MEMORY_ALLOCATION_ERROR); } /* read the file */ - if(fileLength!=(int32_t)fread(data, 1, fileLength, file)) { + if(fileLength!=(int32_t)fread(data.getAlias(), 1, fileLength, file)) { fprintf(stderr, "icupkg: error reading \"%s\"\n", filename); fclose(file); - free(data); exit(U_FILE_ACCESS_ERROR); } /* pad the file to a multiple of 16 using the usual padding byte */ if(fileLengthname, ((Item *)right)->name); } U_CDECL_END -Package::Package() { +U_NAMESPACE_BEGIN + +Package::Package() + : doAutoPrefix(FALSE), prefixEndsWithType(FALSE) { inPkgName[0]=0; + pkgPrefix[0]=0; inData=NULL; inLength=0; inCharset=U_CHARSET_FAMILY; inIsBigEndian=U_IS_BIG_ENDIAN; itemCount=0; + itemMax=0; + items=NULL; + inStringTop=outStringTop=0; matchMode=0; @@ -402,15 +418,26 @@ Package::Package() { } Package::~Package() { - int32_t index; + int32_t idx; - free(inData); + uprv_free(inData); - for(index=0; index=sizeof(pkgPrefix)) { + fprintf(stderr, "icupkg: --toc_prefix %s too long\n", p); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + strcpy(pkgPrefix, p); } void @@ -486,6 +513,7 @@ Package::readPackage(const char *filename) { offset=0x7fffffff; } else { itemCount=udata_readInt32(ds, *(const int32_t *)inBytes); + setItemCapacity(itemCount); /* resize so there's space */ if(itemCount==0) { offset=4; } else if(length<(4+8*itemCount)) { @@ -503,18 +531,22 @@ Package::readPackage(const char *filename) { } /* do not modify the package length variable until the last item's length is set */ - if(itemCount>0) { + if(itemCount<=0) { + if(doAutoPrefix) { + fprintf(stderr, "icupkg: --auto_toc_prefix[_with_type] but the input package is empty\n"); + exit(U_INVALID_FORMAT_ERROR); + } + } else { char prefix[MAX_PKG_NAME_LENGTH+4]; char *s, *inItemStrings; - int32_t inPkgNameLength, prefixLength, stringsOffset; - if(itemCount>MAX_FILE_COUNT) { - fprintf(stderr, "icupkg: too many items, maximum is %d\n", MAX_FILE_COUNT); + if(itemCount>itemMax) { + fprintf(stderr, "icupkg: too many items, maximum is %d\n", itemMax); exit(U_BUFFER_OVERFLOW_ERROR); } /* swap the item name strings */ - stringsOffset=4+8*itemCount; + int32_t stringsOffset=4+8*itemCount; itemLength=(int32_t)(ds->readUInt32(inEntries[0].dataOffset))-stringsOffset; // don't include padding bytes at the end of the item names @@ -538,10 +570,6 @@ Package::readPackage(const char *filename) { // reset the Item entries memset(items, 0, itemCount*sizeof(Item)); - inPkgNameLength=strlen(inPkgName); - memcpy(prefix, inPkgName, inPkgNameLength); - prefixLength=inPkgNameLength; - /* * Get the common prefix of the items. * New-style ICU .dat packages use tree separators ('/') between package names, @@ -550,18 +578,54 @@ Package::readPackage(const char *filename) { * use an underscore ('_') between package and item names. */ offset=(int32_t)ds->readUInt32(inEntries[0].nameOffset)-stringsOffset; - s=inItemStrings+offset; - if( (int32_t)strlen(s)>=(inPkgNameLength+2) && - 0==memcmp(s, inPkgName, inPkgNameLength) && - s[inPkgNameLength]=='_' - ) { - // old-style .dat package - prefix[prefixLength++]='_'; + s=inItemStrings+offset; // name of the first entry + int32_t prefixLength; + if(doAutoPrefix) { + // Use the first entry's prefix. Must be a new-style package. + const char *prefixLimit=strchr(s, U_TREE_ENTRY_SEP_CHAR); + if(prefixLimit==NULL) { + fprintf(stderr, + "icupkg: --auto_toc_prefix[_with_type] but " + "the first entry \"%s\" does not contain a '%c'\n", + s, U_TREE_ENTRY_SEP_CHAR); + exit(U_INVALID_FORMAT_ERROR); + } + prefixLength=(int32_t)(prefixLimit-s); + if(prefixLength==0 || prefixLength>=UPRV_LENGTHOF(pkgPrefix)) { + fprintf(stderr, + "icupkg: --auto_toc_prefix[_with_type] but " + "the prefix of the first entry \"%s\" is empty or too long\n", + s); + exit(U_INVALID_FORMAT_ERROR); + } + if(prefixEndsWithType && s[prefixLength-1]!=type) { + fprintf(stderr, + "icupkg: --auto_toc_prefix_with_type but " + "the prefix of the first entry \"%s\" does not end with '%c'\n", + s, type); + exit(U_INVALID_FORMAT_ERROR); + } + memcpy(pkgPrefix, s, prefixLength); + pkgPrefix[prefixLength]=0; + memcpy(prefix, s, ++prefixLength); // include the / } else { - // new-style .dat package - prefix[prefixLength++]=U_TREE_ENTRY_SEP_CHAR; - // if it turns out to not contain U_TREE_ENTRY_SEP_CHAR - // then the test in the loop below will fail + // Use the package basename as prefix. + int32_t inPkgNameLength=strlen(inPkgName); + memcpy(prefix, inPkgName, inPkgNameLength); + prefixLength=inPkgNameLength; + + if( (int32_t)strlen(s)>=(inPkgNameLength+2) && + 0==memcmp(s, inPkgName, inPkgNameLength) && + s[inPkgNameLength]=='_' + ) { + // old-style .dat package + prefix[prefixLength++]='_'; + } else { + // new-style .dat package + prefix[prefixLength++]=U_TREE_ENTRY_SEP_CHAR; + // if it turns out to not contain U_TREE_ENTRY_SEP_CHAR + // then the test in the loop below will fail + } } prefix[prefixLength]=0; @@ -574,7 +638,7 @@ Package::readPackage(const char *filename) { if(0!=strncmp(s, prefix, prefixLength) || s[prefixLength]==0) { fprintf(stderr, "icupkg: input .dat item name \"%s\" does not start with \"%s\"\n", s, prefix); - exit(U_UNSUPPORTED_ERROR); + exit(U_INVALID_FORMAT_ERROR); } items[i].name=s+prefixLength; @@ -599,7 +663,7 @@ Package::readPackage(const char *filename) { // set the last item's platform type typeEnum=getTypeEnumForInputData(items[itemCount-1].data, items[itemCount-1].length, &errorCode); if(typeEnum<0 || U_FAILURE(errorCode)) { - fprintf(stderr, "icupkg: not an ICU data file: item \"%s\" in \"%s\"\n", items[i-1].name, filename); + fprintf(stderr, "icupkg: not an ICU data file: item \"%s\" in \"%s\"\n", items[itemCount-1].name, filename); exit(U_INVALID_FORMAT_ERROR); } items[itemCount-1].type=makeTypeLetter(typeEnum); @@ -704,8 +768,17 @@ Package::writePackage(const char *filename, char outType, const char *comment) { // 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(pkgPrefix[0]==0) { + prefixLength=(int32_t)strlen(prefix); + } else { + prefixLength=(int32_t)strlen(pkgPrefix); + memcpy(prefix, pkgPrefix, prefixLength); + if(prefixEndsWithType) { + prefix[prefixLength-1]=outType; + } + } + prefix[prefixLength++]=U_TREE_ENTRY_SEP_CHAR; + prefix[prefixLength]=0; if(dsLocalToOut!=NULL) { dsLocalToOut->swapInvChars(dsLocalToOut, prefix, prefixLength, prefix, &errorCode); if(U_FAILURE(errorCode)) { @@ -822,7 +895,7 @@ Package::writePackage(const char *filename, char outType, const char *comment) { } int32_t -Package::findItem(const char *name, int32_t length) { +Package::findItem(const char *name, int32_t length) const { int32_t i, start, limit; int result; @@ -898,15 +971,15 @@ Package::findItems(const char *pattern) { int32_t Package::findNextItem() { const char *name, *middle, *treeSep; - int32_t index, nameLength, middleLength; + int32_t idx, nameLength, middleLength; if(findNextIndex<0) { return -1; } while(findNextIndex=MAX_FILE_COUNT) { - fprintf(stderr, "icupkg: too many items, maximum is %d\n", MAX_FILE_COUNT); - exit(U_BUFFER_OVERFLOW_ERROR); - } + ensureItemCapacity(); // move the following items down - index=~index; - if(index=0) { +Package::removeItem(int32_t idx) { + if(idx>=0) { // remove the item - if(items[index].isDataOwned) { - free(items[index].data); + if(items[idx].isDataOwned) { + uprv_free(items[idx].data); } // move the following items up - if((index+1)=0) { - removeItem(index); + while((idx=findNextItem())>=0) { + removeItem(idx); } } @@ -1054,7 +1124,7 @@ Package::removeItems(const Package &listPkg) { } void -Package::extractItem(const char *filesPath, const char *outName, int32_t index, char outType) { +Package::extractItem(const char *filesPath, const char *outName, int32_t idx, char outType) { char filename[1024]; UDataSwapper *ds; FILE *file; @@ -1063,10 +1133,10 @@ Package::extractItem(const char *filesPath, const char *outName, int32_t index, uint8_t itemCharset, outCharset; UBool itemIsBigEndian, outIsBigEndian; - if(index<0 || itemCount<=index) { + if(idx<0 || itemCount<=idx) { return; } - pItem=items+index; + pItem=items+idx; // swap the data to the outType // outType==0: don't swap @@ -1078,7 +1148,7 @@ Package::extractItem(const char *filesPath, const char *outName, int32_t index, ds=udata_openSwapper(itemIsBigEndian, itemCharset, outIsBigEndian, outCharset, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "icupkg: udata_openSwapper(item %ld) failed - %s\n", - (long)index, u_errorName(errorCode)); + (long)idx, u_errorName(errorCode)); exit(errorCode); } @@ -1088,10 +1158,11 @@ Package::extractItem(const char *filesPath, const char *outName, int32_t index, // swap the item from its platform properties to the desired ones udata_swap(ds, pItem->data, pItem->length, pItem->data, &errorCode); if(U_FAILURE(errorCode)) { - fprintf(stderr, "icupkg: udata_swap(item %ld) failed - %s\n", (long)index, u_errorName(errorCode)); + fprintf(stderr, "icupkg: udata_swap(item %ld) failed - %s\n", (long)idx, u_errorName(errorCode)); exit(errorCode); } udata_closeSwapper(ds); + pItem->type=outType; } // create the file and write its contents @@ -1111,17 +1182,17 @@ Package::extractItem(const char *filesPath, const char *outName, int32_t index, } void -Package::extractItem(const char *filesPath, int32_t index, char outType) { - extractItem(filesPath, items[index].name, index, outType); +Package::extractItem(const char *filesPath, int32_t idx, char outType) { + extractItem(filesPath, items[idx].name, idx, outType); } void Package::extractItems(const char *filesPath, const char *pattern, char outType) { - int32_t index; + int32_t idx; findItems(pattern); - while((index=findNextItem())>=0) { - extractItem(filesPath, index, outType); + while((idx=findNextItem())>=0) { + extractItem(filesPath, idx, outType); } } @@ -1135,13 +1206,17 @@ Package::extractItems(const char *filesPath, const Package &listPkg, char outTyp } } -void -Package::listItems(FILE *file) { - int32_t i; +int32_t +Package::getItemCount() const { + return itemCount; +} - for(i=0; i0) { + uprv_memcpy(newItems, items, (size_t)itemCount*sizeof(items[0])); + } + itemMax = max; + items = newItems; + uprv_free(oldItems); +} + +void Package::ensureItemCapacity() +{ + if((itemCount+1)>itemMax) { + setItemCapacity(itemCount+kItemsChunk); + } +} + +U_NAMESPACE_END