X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/46f4442e9a5a4f3b98b7c1083586332f6a8a99a4..f59164e3d128c7675a4d3934206346a3384e53a5:/icuSources/tools/toolutil/package.cpp?ds=inline diff --git a/icuSources/tools/toolutil/package.cpp b/icuSources/tools/toolutil/package.cpp index c5db3017..47e766ca 100644 --- a/icuSources/tools/toolutil/package.cpp +++ b/icuSources/tools/toolutil/package.cpp @@ -1,7 +1,7 @@ /* ******************************************************************************* * -* Copyright (C) 1999-2007, International Business Machines +* Copyright (C) 1999-2015, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* @@ -31,14 +31,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 +304,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 +326,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(fileLength=sizeof(pkgPrefix)) { + fprintf(stderr, "icupkg: --toc_prefix %s too long\n", p); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + strcpy(pkgPrefix, p); } void @@ -490,6 +511,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)) { @@ -507,18 +529,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 @@ -542,10 +568,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, @@ -554,18 +576,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; @@ -578,7 +636,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; @@ -708,8 +766,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)) { @@ -902,15 +969,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); } } @@ -1058,7 +1122,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; @@ -1067,10 +1131,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 @@ -1082,7 +1146,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); } @@ -1092,10 +1156,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 @@ -1115,17 +1180,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); } } @@ -1214,4 +1279,31 @@ Package::sortItems() { } } +void Package::setItemCapacity(int32_t max) +{ + if(max<=itemMax) { + return; + } + Item *newItems = (Item*)uprv_malloc(max * sizeof(items[0])); + Item *oldItems = items; + if(newItems == NULL) { + fprintf(stderr, "icupkg: Out of memory trying to allocate %lu bytes for %d items\n", + (unsigned long)max*sizeof(items[0]), max); + exit(U_MEMORY_ALLOCATION_ERROR); + } + if(items && itemCount>0) { + 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