/* parse the output type option */
data = const_cast<char*>(options[OPT_OUT_TYPE].value); if(data[0]==0 || data[1]!=0) { /* the type must be exactly one letter */ return printUsage(pname, false);
} switch(data[0]) { case'l':
outIsBigEndian=false;
outCharset=U_ASCII_FAMILY; break; case'b':
outIsBigEndian=true;
outCharset=U_ASCII_FAMILY; break; case'e':
outIsBigEndian=true;
outCharset=U_EBCDIC_FAMILY; break; default: return printUsage(pname, false);
}
in=out=nullptr;
data=nullptr;
/* open the input file, get its length, allocate memory for it, read the file */
in=fopen(argv[1], "rb"); if(in==nullptr) {
fprintf(stderr, "%s: unable to open input file \"%s\"\n", pname, argv[1]);
rc=2; goto done;
}
/* * +15: udata_swapPackage() may need to add a few padding bytes to the * last item if charset swapping is done, * because the last item may be resorted into the middle and then needs * additional padding bytes
*/
data = static_cast<char*>(malloc(length + DEFAULT_PADDING_LENGTH)); if(data==nullptr) {
fprintf(stderr, "%s: error allocating memory for \"%s\"\n", pname, argv[1]);
rc=2; goto done;
}
/* set the last 15 bytes to the usual padding byte, see udata_swapPackage() */
uprv_memset(data+length-DEFAULT_PADDING_LENGTH, 0xaa, DEFAULT_PADDING_LENGTH);
basename=findBasename(filename);
len = static_cast<int32_t>(uprv_strlen(basename)) - 4; /* -4: subtract the length of ".dat" */
if(len<=0 || 0!=uprv_strcmp(basename+len, ".dat")) {
udata_printError(ds, "udata_swapPackage(): \"%s\" is not recognized as a package filename (must end with .dat)\n",
basename);
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return0;
}
if(len>=capacity) {
udata_printError(ds, "udata_swapPackage(): the package name \"%s\" is too long (>=%ld)\n", static_cast<long>(capacity));
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return0;
}
/* check data format and format version */
pInfo=(const UDataInfo *)((constchar *)inData+4); if(!(
pInfo->dataFormat[0]==0x43 && /* dataFormat="CmnD" */
pInfo->dataFormat[1]==0x6d &&
pInfo->dataFormat[2]==0x6e &&
pInfo->dataFormat[3]==0x44 &&
pInfo->formatVersion[0]==1
)) {
udata_printError(ds, "udata_swapPackage(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as an ICU .dat package\n",
pInfo->dataFormat[0], pInfo->dataFormat[1],
pInfo->dataFormat[2], pInfo->dataFormat[3],
pInfo->formatVersion[0]);
*pErrorCode=U_UNSUPPORTED_ERROR; return0;
}
/* * We need to change the ToC name entries so that they have the correct * package name prefix. * Extract the package names from the in/out filenames.
*/
inPkgNameLength=extractPackageName(
ds, inFilename,
inPkgName, (int32_t)sizeof(inPkgName),
pErrorCode);
outPkgNameLength=extractPackageName(
ds, outFilename,
outPkgName, (int32_t)sizeof(outPkgName),
pErrorCode); if(U_FAILURE(*pErrorCode)) { return0;
}
/* * It is possible to work with inPkgNameLength!=outPkgNameLength, * but then the length of the data file would change more significantly, * which we are not currently prepared for.
*/ if(inPkgNameLength!=outPkgNameLength) {
udata_printError(ds, "udata_swapPackage(): the package names \"%s\" and \"%s\" must have the same length\n",
inPkgName, outPkgName);
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return0;
}
if(length<0) { /* preflighting */
itemCount=ds->readUInt32(*(const uint32_t *)inBytes); if(itemCount==0) { /* no items: count only the item count and return */ return headerSize+4;
}
/* read the last item's offset and preflight it */
offset=ds->readUInt32(inEntries[itemCount-1].dataOffset);
itemLength=udata_swap(ds, inBytes+offset, -1, nullptr, pErrorCode);
if(U_SUCCESS(*pErrorCode)) { return headerSize+offset+(uint32_t)itemLength;
} else { return0;
}
} else { /* check that the itemCount fits, then the ToC table, then at least the header of the last item */
length-=headerSize; if(length<4) { /* itemCount does not fit */
offset=0xffffffff;
itemCount=0; /* make compilers happy */
} else {
itemCount=ds->readUInt32(*(const uint32_t *)inBytes); if(itemCount==0) {
offset=4;
} elseif((uint32_t)length<(4+8*itemCount)) { /* ToC table does not fit */
offset=0xffffffff;
} else { /* offset of the last item plus at least 20 bytes for its header */
offset=20+ds->readUInt32(inEntries[itemCount-1].dataOffset);
}
} if((uint32_t)length<offset) {
udata_printError(ds, "udata_swapPackage(): too few bytes (%d after header) for a .dat package\n",
length);
*pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; return0;
}
if(itemCount==0) { /* no items: just return now */ return headerSize+4;
}
/* swap the item name strings */
offset=4+8*itemCount;
itemLength=(int32_t)(ds->readUInt32(inEntries[0].dataOffset)-offset);
udata_swapInvStringBlock(ds, inBytes+offset, itemLength, outBytes+offset, pErrorCode); if(U_FAILURE(*pErrorCode)) {
udata_printError(ds, "udata_swapPackage() failed to swap the data item name strings\n"); return0;
} /* keep offset and itemLength in case we allocate and copy the strings below */
/* swap the package names into the output charset */ if(ds->outCharset!=U_CHARSET_FAMILY) {
UDataSwapper *ds2;
ds2=udata_openSwapper(true, U_CHARSET_FAMILY, true, ds->outCharset, pErrorCode);
ds2->swapInvChars(ds2, inPkgName, inPkgNameLength, inPkgName, pErrorCode);
ds2->swapInvChars(ds2, outPkgName, outPkgNameLength, outPkgName, pErrorCode);
udata_closeSwapper(ds2); if(U_FAILURE(*pErrorCode)) {
udata_printError(ds, "udata_swapPackage() failed to swap the input/output package names\n");
}
}
/* change the prefix of each ToC entry name from the old to the new package name */
{ char *entryName;
if(0==uprv_memcmp(entryName, inPkgName, inPkgNameLength)) {
uprv_memcpy(entryName, outPkgName, inPkgNameLength);
} else {
udata_printError(ds, "udata_swapPackage() failed: ToC item %ld does not have the input package name as a prefix\n",
(long)i);
*pErrorCode=U_INVALID_FORMAT_ERROR; return0;
}
}
}
/* * Allocate the ToC table and, if necessary, a temporary buffer for * pseudo-in-place swapping. * * We cannot swap in-place because: * * 1. If the swapping of an item fails mid-way, then in-place swapping * has destroyed its data. * Out-of-place swapping allows us to then copy its original data. * * 2. If swapping changes the charset family, then we must resort * not only the ToC table but also the data items themselves. * This requires a permutation and is best done with separate in/out * buffers. * * We swapped the strings above to avoid the malloc below if string swapping fails.
*/ if(inData==outData) { /* +15: prepare for extra padding of a newly-last item */
table=(ToCEntry *)uprv_malloc(itemCount*sizeof(ToCEntry)+length+DEFAULT_PADDING_LENGTH); if(table!=nullptr) {
outBytes=(uint8_t *)(table+itemCount);
/* copy the item count and the swapped strings */
uprv_memcpy(outBytes, inBytes, 4);
uprv_memcpy(outBytes+offset, inBytes+offset, itemLength);
}
} else {
table=(ToCEntry *)uprv_malloc(itemCount*sizeof(ToCEntry));
} if(table==nullptr) {
udata_printError(ds, "udata_swapPackage(): out of memory allocating %d bytes\n",
inData==outData ?
itemCount*sizeof(ToCEntry)+length+DEFAULT_PADDING_LENGTH :
itemCount*sizeof(ToCEntry));
*pErrorCode=U_MEMORY_ALLOCATION_ERROR; return0;
}
outEntries=(UDataOffsetTOCEntry *)(outBytes+4);
if(ds->inCharset==ds->outCharset) { /* no charset swapping, no resorting: keep item offsets the same */ for(i=0; i<itemCount; ++i) {
table[i].outOffset=table[i].inOffset;
}
} else { /* charset swapping: resort items by their swapped names */
/* * Before the actual sorting, we need to make sure that each item * has a length that is a multiple of 16 bytes so that all items * are 16-aligned. * Only the old last item may be missing up to 15 padding bytes. * Add padding bytes for it. * Since the icuswap main() function has already allocated enough * input buffer space and set the last 15 bytes there to 0xaa, * we only need to increase the total data length and the length * of the last item here.
*/ if((length&0xf)!=0) {
int32_t delta=16-(length&0xf);
length+=delta;
table[itemCount-1].length+=(uint32_t)delta;
}
/* Save the offset before we sort the TOC. */
offset=table[0].inOffset; /* sort the TOC entries */
uprv_sortArray(table, (int32_t)itemCount, (int32_t)sizeof(ToCEntry),
compareToCEntries, outBytes, false, pErrorCode);
/* * Note: Before sorting, the inOffset values were in order. * Now the outOffset values are in order.
*/
/* swap each data item */ for(i=0; i<itemCount; ++i) { /* first copy the item bytes to make sure that unreachable bytes are copied */
uprv_memcpy(outBytes+table[i].outOffset, inBytes+table[i].inOffset, table[i].length);
/* swap the item */
udata_swap(ds, inBytes+table[i].inOffset, (int32_t)table[i].length,
outBytes+table[i].outOffset, pErrorCode);
if(U_FAILURE(*pErrorCode)) { if(ds->outCharset==U_CHARSET_FAMILY) {
udata_printError(ds, "warning: udata_swapPackage() failed to swap item \"%s\"\n" " at inOffset 0x%x length 0x%x - %s\n" " the data item will be copied, not swapped\n\n",
(char *)outBytes+table[i].nameOffset,
table[i].inOffset, table[i].length, u_errorName(*pErrorCode));
} else {
udata_printError(ds, "warning: udata_swapPackage() failed to swap an item\n" " at inOffset 0x%x length 0x%x - %s\n" " the data item will be copied, not swapped\n\n",
table[i].inOffset, table[i].length, u_errorName(*pErrorCode));
} /* reset the error code, copy the data item, and continue */
*pErrorCode=U_ZERO_ERROR;
uprv_memcpy(outBytes+table[i].outOffset, inBytes+table[i].inOffset, table[i].length);
}
}
if(inData==outData) { /* copy the data from the temporary buffer to the in-place buffer */
uprv_memcpy((uint8_t *)outData+headerSize, outBytes, length);
}
uprv_free(table);
return headerSize+length;
}
}
/* * Hey, Emacs, please set the following: * * Local Variables: * indent-tabs-mode: nil * End: *
*/
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-07)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.