intl/icu/source/tools/icuswap/icuswap.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /*
     2 *******************************************************************************
     3 *
     4 *   Copyright (C) 2003-2007, International Business Machines
     5 *   Corporation and others.  All Rights Reserved.
     6 *
     7 *******************************************************************************
     8 *   file name:  icuswap.cpp
     9 *   encoding:   US-ASCII
    10 *   tab size:   8 (not used)
    11 *   indentation:4
    12 *
    13 *   created on: 2003aug08
    14 *   created by: Markus W. Scherer
    15 *
    16 *   This tool takes an ICU data file and "swaps" it, that is, changes its
    17 *   platform properties between big-/little-endianness and ASCII/EBCDIC charset
    18 *   families.
    19 *   The modified data file is written to a new file.
    20 *   Useful as an install-time tool for shipping only one flavor of ICU data
    21 *   and preparing data files for the target platform.
    22 *   Will not work with data DLLs (shared libraries).
    23 */
    25 #include "unicode/utypes.h"
    26 #include "unicode/putil.h"
    27 #include "unicode/udata.h"
    28 #include "cmemory.h"
    29 #include "cstring.h"
    30 #include "uinvchar.h"
    31 #include "uarrsort.h"
    32 #include "ucmndata.h"
    33 #include "udataswp.h"
    34 #include "swapimpl.h"
    35 #include "toolutil.h"
    36 #include "uoptions.h"
    38 #include <stdio.h>
    39 #include <stdlib.h>
    40 #include <string.h>
    42 /* definitions */
    44 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
    45 #define DEFAULT_PADDING_LENGTH 15
    47 static UOption options[]={
    48     UOPTION_HELP_H,
    49     UOPTION_HELP_QUESTION_MARK,
    50     UOPTION_DEF("type", 't', UOPT_REQUIRES_ARG)
    51 };
    53 enum {
    54     OPT_HELP_H,
    55     OPT_HELP_QUESTION_MARK,
    56     OPT_OUT_TYPE
    57 };
    59 static int32_t
    60 fileSize(FILE *f) {
    61     int32_t size;
    63     fseek(f, 0, SEEK_END);
    64     size=(int32_t)ftell(f);
    65     fseek(f, 0, SEEK_SET);
    66     return size;
    67 }
    69 /**
    70  * Swap an ICU .dat package, including swapping of enclosed items.
    71  */
    72 U_CFUNC int32_t U_CALLCONV
    73 udata_swapPackage(const char *inFilename, const char *outFilename,
    74                   const UDataSwapper *ds,
    75                   const void *inData, int32_t length, void *outData,
    76                   UErrorCode *pErrorCode);
    78 U_CDECL_BEGIN
    79 static void U_CALLCONV
    80 printError(void *context, const char *fmt, va_list args) {
    81     vfprintf((FILE *)context, fmt, args);
    82 }
    83 U_CDECL_END
    85 static int
    86 printUsage(const char *pname, UBool ishelp) {
    87     fprintf(stderr,
    88             "%csage: %s [ -h, -?, --help ] -tl|-tb|-te|--type=b|... infilename outfilename\n",
    89             ishelp ? 'U' : 'u', pname);
    90     if(ishelp) {
    91         fprintf(stderr,
    92               "\nOptions: -h, -?, --help    print this message and exit\n"
    93                 "         Read the input file, swap its platform properties according\n"
    94                 "         to the -t or --type option, and write the result to the output file.\n"
    95                 "         -tl               change to little-endian/ASCII charset family\n"
    96                 "         -tb               change to big-endian/ASCII charset family\n"
    97                 "         -te               change to big-endian/EBCDIC charset family\n");
    98     }
   100     return !ishelp;
   101 }
   103 extern int
   104 main(int argc, char *argv[]) {
   105     FILE *in, *out;
   106     const char *pname;
   107     char *data;
   108     int32_t length;
   109     UBool ishelp;
   110     int rc;
   112     UDataSwapper *ds;
   113     const UDataInfo *pInfo;
   114     UErrorCode errorCode;
   115     uint8_t outCharset;
   116     UBool outIsBigEndian;
   118     U_MAIN_INIT_ARGS(argc, argv);
   120     fprintf(stderr, "Warning: icuswap is an obsolete tool and it will be removed in the next ICU release.\nPlease use the icupkg tool instead.\n");
   122     /* get the program basename */
   123     pname=strrchr(argv[0], U_FILE_SEP_CHAR);
   124     if(pname==NULL) {
   125         pname=strrchr(argv[0], '/');
   126     }
   127     if(pname!=NULL) {
   128         ++pname;
   129     } else {
   130         pname=argv[0];
   131     }
   133     argc=u_parseArgs(argc, argv, LENGTHOF(options), options);
   134     ishelp=options[OPT_HELP_H].doesOccur || options[OPT_HELP_QUESTION_MARK].doesOccur;
   135     if(ishelp || argc!=3) {
   136         return printUsage(pname, ishelp);
   137     }
   139     /* parse the output type option */
   140     data=(char *)options[OPT_OUT_TYPE].value;
   141     if(data[0]==0 || data[1]!=0) {
   142         /* the type must be exactly one letter */
   143         return printUsage(pname, FALSE);
   144     }
   145     switch(data[0]) {
   146     case 'l':
   147         outIsBigEndian=FALSE;
   148         outCharset=U_ASCII_FAMILY;
   149         break;
   150     case 'b':
   151         outIsBigEndian=TRUE;
   152         outCharset=U_ASCII_FAMILY;
   153         break;
   154     case 'e':
   155         outIsBigEndian=TRUE;
   156         outCharset=U_EBCDIC_FAMILY;
   157         break;
   158     default:
   159         return printUsage(pname, FALSE);
   160     }
   162     in=out=NULL;
   163     data=NULL;
   165     /* open the input file, get its length, allocate memory for it, read the file */
   166     in=fopen(argv[1], "rb");
   167     if(in==NULL) {
   168         fprintf(stderr, "%s: unable to open input file \"%s\"\n", pname, argv[1]);
   169         rc=2;
   170         goto done;
   171     }
   173     length=fileSize(in);
   174     if(length<DEFAULT_PADDING_LENGTH) {
   175         fprintf(stderr, "%s: empty input file \"%s\"\n", pname, argv[1]);
   176         rc=2;
   177         goto done;
   178     }
   180     /*
   181      * +15: udata_swapPackage() may need to add a few padding bytes to the
   182      * last item if charset swapping is done,
   183      * because the last item may be resorted into the middle and then needs
   184      * additional padding bytes
   185      */
   186     data=(char *)malloc(length+DEFAULT_PADDING_LENGTH);
   187     if(data==NULL) {
   188         fprintf(stderr, "%s: error allocating memory for \"%s\"\n", pname, argv[1]);
   189         rc=2;
   190         goto done;
   191     }
   193     /* set the last 15 bytes to the usual padding byte, see udata_swapPackage() */
   194     uprv_memset(data+length-DEFAULT_PADDING_LENGTH, 0xaa, DEFAULT_PADDING_LENGTH);
   196     if(length!=(int32_t)fread(data, 1, length, in)) {
   197         fprintf(stderr, "%s: error reading \"%s\"\n", pname, argv[1]);
   198         rc=3;
   199         goto done;
   200     }
   202     fclose(in);
   203     in=NULL;
   205     /* swap the data in-place */
   206     errorCode=U_ZERO_ERROR;
   207     ds=udata_openSwapperForInputData(data, length, outIsBigEndian, outCharset, &errorCode);
   208     if(U_FAILURE(errorCode)) {
   209         fprintf(stderr, "%s: udata_openSwapperForInputData(\"%s\") failed - %s\n",
   210                 pname, argv[1], u_errorName(errorCode));
   211         rc=4;
   212         goto done;
   213     }
   215     ds->printError=printError;
   216     ds->printErrorContext=stderr;
   218     /* speculative cast, protected by the following length check */
   219     pInfo=(const UDataInfo *)((const char *)data+4);
   221     if( length>=20 &&
   222         pInfo->dataFormat[0]==0x43 &&   /* dataFormat="CmnD" */
   223         pInfo->dataFormat[1]==0x6d &&
   224         pInfo->dataFormat[2]==0x6e &&
   225         pInfo->dataFormat[3]==0x44
   226     ) {
   227         /*
   228          * swap the .dat package
   229          * udata_swapPackage() needs to rename ToC name entries from the old package
   230          * name to the new one.
   231          * We pass it the filenames, and udata_swapPackage() will extract the
   232          * package names.
   233          */
   234         length=udata_swapPackage(argv[1], argv[2], ds, data, length, data, &errorCode);
   235         udata_closeSwapper(ds);
   236         if(U_FAILURE(errorCode)) {
   237             fprintf(stderr, "%s: udata_swapPackage(\"%s\") failed - %s\n",
   238                     pname, argv[1], u_errorName(errorCode));
   239             rc=4;
   240             goto done;
   241         }
   242     } else {
   243         /* swap the data, which is not a .dat package */
   244         length=udata_swap(ds, data, length, data, &errorCode);
   245         udata_closeSwapper(ds);
   246         if(U_FAILURE(errorCode)) {
   247             fprintf(stderr, "%s: udata_swap(\"%s\") failed - %s\n",
   248                     pname, argv[1], u_errorName(errorCode));
   249             rc=4;
   250             goto done;
   251         }
   252     }
   254     out=fopen(argv[2], "wb");
   255     if(out==NULL) {
   256         fprintf(stderr, "%s: unable to open output file \"%s\"\n", pname, argv[2]);
   257         rc=5;
   258         goto done;
   259     }
   261     if(length!=(int32_t)fwrite(data, 1, length, out)) {
   262         fprintf(stderr, "%s: error writing \"%s\"\n", pname, argv[2]);
   263         rc=6;
   264         goto done;
   265     }
   267     fclose(out);
   268     out=NULL;
   270     /* all done */
   271     rc=0;
   273 done:
   274     if(in!=NULL) {
   275         fclose(in);
   276     }
   277     if(out!=NULL) {
   278         fclose(out);
   279     }
   280     if(data!=NULL) {
   281         free(data);
   282     }
   283     return rc;
   284 }
   286 /* swap .dat package files -------------------------------------------------- */
   288 static int32_t
   289 extractPackageName(const UDataSwapper *ds, const char *filename,
   290                    char pkg[], int32_t capacity,
   291                    UErrorCode *pErrorCode) {
   292     const char *basename;
   293     int32_t len;
   295     if(U_FAILURE(*pErrorCode)) {
   296         return 0;
   297     }
   299     basename=findBasename(filename);
   300     len=(int32_t)uprv_strlen(basename)-4; /* -4: subtract the length of ".dat" */
   302     if(len<=0 || 0!=uprv_strcmp(basename+len, ".dat")) {
   303         udata_printError(ds, "udata_swapPackage(): \"%s\" is not recognized as a package filename (must end with .dat)\n",
   304                          basename);
   305         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
   306         return 0;
   307     }
   309     if(len>=capacity) {
   310         udata_printError(ds, "udata_swapPackage(): the package name \"%s\" is too long (>=%ld)\n",
   311                          (long)capacity);
   312         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
   313         return 0;
   314     }
   316     uprv_memcpy(pkg, basename, len);
   317     pkg[len]=0;
   318     return len;
   319 }
   321 struct ToCEntry {
   322     uint32_t nameOffset, inOffset, outOffset, length;
   323 };
   325 U_CDECL_BEGIN
   326 static int32_t U_CALLCONV
   327 compareToCEntries(const void *context, const void *left, const void *right) {
   328     const char *chars=(const char *)context;
   329     return (int32_t)uprv_strcmp(chars+((const ToCEntry *)left)->nameOffset,
   330                                 chars+((const ToCEntry *)right)->nameOffset);
   331 }
   332 U_CDECL_END
   334 U_CFUNC int32_t U_CALLCONV
   335 udata_swapPackage(const char *inFilename, const char *outFilename,
   336                   const UDataSwapper *ds,
   337                   const void *inData, int32_t length, void *outData,
   338                   UErrorCode *pErrorCode) {
   339     const UDataInfo *pInfo;
   340     int32_t headerSize;
   342     const uint8_t *inBytes;
   343     uint8_t *outBytes;
   345     uint32_t itemCount, offset, i;
   346     int32_t itemLength;
   348     const UDataOffsetTOCEntry *inEntries;
   349     UDataOffsetTOCEntry *outEntries;
   351     ToCEntry *table;
   353     char inPkgName[32], outPkgName[32];
   354     int32_t inPkgNameLength, outPkgNameLength;
   356     /* udata_swapDataHeader checks the arguments */
   357     headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
   358     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
   359         return 0;
   360     }
   362     /* check data format and format version */
   363     pInfo=(const UDataInfo *)((const char *)inData+4);
   364     if(!(
   365         pInfo->dataFormat[0]==0x43 &&   /* dataFormat="CmnD" */
   366         pInfo->dataFormat[1]==0x6d &&
   367         pInfo->dataFormat[2]==0x6e &&
   368         pInfo->dataFormat[3]==0x44 &&
   369         pInfo->formatVersion[0]==1
   370     )) {
   371         udata_printError(ds, "udata_swapPackage(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as an ICU .dat package\n",
   372                          pInfo->dataFormat[0], pInfo->dataFormat[1],
   373                          pInfo->dataFormat[2], pInfo->dataFormat[3],
   374                          pInfo->formatVersion[0]);
   375         *pErrorCode=U_UNSUPPORTED_ERROR;
   376         return 0;
   377     }
   379     /*
   380      * We need to change the ToC name entries so that they have the correct
   381      * package name prefix.
   382      * Extract the package names from the in/out filenames.
   383      */
   384     inPkgNameLength=extractPackageName(
   385                         ds, inFilename,
   386                         inPkgName, (int32_t)sizeof(inPkgName),
   387                         pErrorCode);
   388     outPkgNameLength=extractPackageName(
   389                         ds, outFilename,
   390                         outPkgName, (int32_t)sizeof(outPkgName),
   391                         pErrorCode);
   392     if(U_FAILURE(*pErrorCode)) {
   393         return 0;
   394     }
   396     /*
   397      * It is possible to work with inPkgNameLength!=outPkgNameLength,
   398      * but then the length of the data file would change more significantly,
   399      * which we are not currently prepared for.
   400      */
   401     if(inPkgNameLength!=outPkgNameLength) {
   402         udata_printError(ds, "udata_swapPackage(): the package names \"%s\" and \"%s\" must have the same length\n",
   403                          inPkgName, outPkgName);
   404         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
   405         return 0;
   406     }
   408     inBytes=(const uint8_t *)inData+headerSize;
   409     inEntries=(const UDataOffsetTOCEntry *)(inBytes+4);
   411     if(length<0) {
   412         /* preflighting */
   413         itemCount=ds->readUInt32(*(const uint32_t *)inBytes);
   414         if(itemCount==0) {
   415             /* no items: count only the item count and return */
   416             return headerSize+4;
   417         }
   419         /* read the last item's offset and preflight it */
   420         offset=ds->readUInt32(inEntries[itemCount-1].dataOffset);
   421         itemLength=udata_swap(ds, inBytes+offset, -1, NULL, pErrorCode);
   423         if(U_SUCCESS(*pErrorCode)) {
   424             return headerSize+offset+(uint32_t)itemLength;
   425         } else {
   426             return 0;
   427         }
   428     } else {
   429         /* check that the itemCount fits, then the ToC table, then at least the header of the last item */
   430         length-=headerSize;
   431         if(length<4) {
   432             /* itemCount does not fit */
   433             offset=0xffffffff;
   434             itemCount=0; /* make compilers happy */
   435         } else {
   436             itemCount=ds->readUInt32(*(const uint32_t *)inBytes);
   437             if(itemCount==0) {
   438                 offset=4;
   439             } else if((uint32_t)length<(4+8*itemCount)) {
   440                 /* ToC table does not fit */
   441                 offset=0xffffffff;
   442             } else {
   443                 /* offset of the last item plus at least 20 bytes for its header */
   444                 offset=20+ds->readUInt32(inEntries[itemCount-1].dataOffset);
   445             }
   446         }
   447         if((uint32_t)length<offset) {
   448             udata_printError(ds, "udata_swapPackage(): too few bytes (%d after header) for a .dat package\n",
   449                              length);
   450             *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
   451             return 0;
   452         }
   454         outBytes=(uint8_t *)outData+headerSize;
   456         /* swap the item count */
   457         ds->swapArray32(ds, inBytes, 4, outBytes, pErrorCode);
   459         if(itemCount==0) {
   460             /* no items: just return now */
   461             return headerSize+4;
   462         }
   464         /* swap the item name strings */
   465         offset=4+8*itemCount;
   466         itemLength=(int32_t)(ds->readUInt32(inEntries[0].dataOffset)-offset);
   467         udata_swapInvStringBlock(ds, inBytes+offset, itemLength, outBytes+offset, pErrorCode);
   468         if(U_FAILURE(*pErrorCode)) {
   469             udata_printError(ds, "udata_swapPackage() failed to swap the data item name strings\n");
   470             return 0;
   471         }
   472         /* keep offset and itemLength in case we allocate and copy the strings below */
   474         /* swap the package names into the output charset */
   475         if(ds->outCharset!=U_CHARSET_FAMILY) {
   476             UDataSwapper *ds2;
   477             ds2=udata_openSwapper(TRUE, U_CHARSET_FAMILY, TRUE, ds->outCharset, pErrorCode);
   478             ds2->swapInvChars(ds2, inPkgName, inPkgNameLength, inPkgName, pErrorCode);
   479             ds2->swapInvChars(ds2, outPkgName, outPkgNameLength, outPkgName, pErrorCode);
   480             udata_closeSwapper(ds2);
   481             if(U_FAILURE(*pErrorCode)) {
   482                 udata_printError(ds, "udata_swapPackage() failed to swap the input/output package names\n");
   483             }
   484         }
   486         /* change the prefix of each ToC entry name from the old to the new package name */
   487         {
   488             char *entryName;
   490             for(i=0; i<itemCount; ++i) {
   491                 entryName=(char *)inBytes+ds->readUInt32(inEntries[i].nameOffset);
   493                 if(0==uprv_memcmp(entryName, inPkgName, inPkgNameLength)) {
   494                     uprv_memcpy(entryName, outPkgName, inPkgNameLength);
   495                 } else {
   496                     udata_printError(ds, "udata_swapPackage() failed: ToC item %ld does not have the input package name as a prefix\n",
   497                                      (long)i);
   498                     *pErrorCode=U_INVALID_FORMAT_ERROR;
   499                     return 0;
   500                 }
   501             }
   502         }
   504         /*
   505          * Allocate the ToC table and, if necessary, a temporary buffer for
   506          * pseudo-in-place swapping.
   507          *
   508          * We cannot swap in-place because:
   509          *
   510          * 1. If the swapping of an item fails mid-way, then in-place swapping
   511          * has destroyed its data.
   512          * Out-of-place swapping allows us to then copy its original data.
   513          *
   514          * 2. If swapping changes the charset family, then we must resort
   515          * not only the ToC table but also the data items themselves.
   516          * This requires a permutation and is best done with separate in/out
   517          * buffers.
   518          *
   519          * We swapped the strings above to avoid the malloc below if string swapping fails.
   520          */
   521         if(inData==outData) {
   522             /* +15: prepare for extra padding of a newly-last item */
   523             table=(ToCEntry *)uprv_malloc(itemCount*sizeof(ToCEntry)+length+DEFAULT_PADDING_LENGTH);
   524             if(table!=NULL) {
   525                 outBytes=(uint8_t *)(table+itemCount);
   527                 /* copy the item count and the swapped strings */
   528                 uprv_memcpy(outBytes, inBytes, 4);
   529                 uprv_memcpy(outBytes+offset, inBytes+offset, itemLength);
   530             }
   531         } else {
   532             table=(ToCEntry *)uprv_malloc(itemCount*sizeof(ToCEntry));
   533         }
   534         if(table==NULL) {
   535             udata_printError(ds, "udata_swapPackage(): out of memory allocating %d bytes\n",
   536                              inData==outData ?
   537                                  itemCount*sizeof(ToCEntry)+length+DEFAULT_PADDING_LENGTH :
   538                                  itemCount*sizeof(ToCEntry));
   539             *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
   540             return 0;
   541         }
   542         outEntries=(UDataOffsetTOCEntry *)(outBytes+4);
   544         /* read the ToC table */
   545         for(i=0; i<itemCount; ++i) {
   546             table[i].nameOffset=ds->readUInt32(inEntries[i].nameOffset);
   547             table[i].inOffset=ds->readUInt32(inEntries[i].dataOffset);
   548             if(i>0) {
   549                 table[i-1].length=table[i].inOffset-table[i-1].inOffset;
   550             }
   551         }
   552         table[itemCount-1].length=(uint32_t)length-table[itemCount-1].inOffset;
   554         if(ds->inCharset==ds->outCharset) {
   555             /* no charset swapping, no resorting: keep item offsets the same */
   556             for(i=0; i<itemCount; ++i) {
   557                 table[i].outOffset=table[i].inOffset;
   558             }
   559         } else {
   560             /* charset swapping: resort items by their swapped names */
   562             /*
   563              * Before the actual sorting, we need to make sure that each item
   564              * has a length that is a multiple of 16 bytes so that all items
   565              * are 16-aligned.
   566              * Only the old last item may be missing up to 15 padding bytes.
   567              * Add padding bytes for it.
   568              * Since the icuswap main() function has already allocated enough
   569              * input buffer space and set the last 15 bytes there to 0xaa,
   570              * we only need to increase the total data length and the length
   571              * of the last item here.
   572              */
   573             if((length&0xf)!=0) {
   574                 int32_t delta=16-(length&0xf);
   575                 length+=delta;
   576                 table[itemCount-1].length+=(uint32_t)delta;
   577             }
   579             /* Save the offset before we sort the TOC. */
   580             offset=table[0].inOffset;
   581             /* sort the TOC entries */
   582             uprv_sortArray(table, (int32_t)itemCount, (int32_t)sizeof(ToCEntry),
   583                            compareToCEntries, outBytes, FALSE, pErrorCode);
   585             /*
   586              * Note: Before sorting, the inOffset values were in order.
   587              * Now the outOffset values are in order.
   588              */
   590             /* assign outOffset values */
   591             for(i=0; i<itemCount; ++i) {
   592                 table[i].outOffset=offset;
   593                 offset+=table[i].length;
   594             }
   595         }
   597         /* write the output ToC table */
   598         for(i=0; i<itemCount; ++i) {
   599             ds->writeUInt32(&outEntries[i].nameOffset, table[i].nameOffset);
   600             ds->writeUInt32(&outEntries[i].dataOffset, table[i].outOffset);
   601         }
   603         /* swap each data item */
   604         for(i=0; i<itemCount; ++i) {
   605             /* first copy the item bytes to make sure that unreachable bytes are copied */ 
   606             uprv_memcpy(outBytes+table[i].outOffset, inBytes+table[i].inOffset, table[i].length);
   608             /* swap the item */
   609             udata_swap(ds, inBytes+table[i].inOffset, (int32_t)table[i].length,
   610                           outBytes+table[i].outOffset, pErrorCode);
   612             if(U_FAILURE(*pErrorCode)) {
   613                 if(ds->outCharset==U_CHARSET_FAMILY) {
   614                     udata_printError(ds, "warning: udata_swapPackage() failed to swap item \"%s\"\n"
   615                                          "    at inOffset 0x%x length 0x%x - %s\n"
   616                                          "    the data item will be copied, not swapped\n\n",
   617                                      (char *)outBytes+table[i].nameOffset,
   618                                      table[i].inOffset, table[i].length, u_errorName(*pErrorCode));
   619                 } else {
   620                     udata_printError(ds, "warning: udata_swapPackage() failed to swap an item\n"
   621                                          "    at inOffset 0x%x length 0x%x - %s\n"
   622                                          "    the data item will be copied, not swapped\n\n",
   623                                      table[i].inOffset, table[i].length, u_errorName(*pErrorCode));
   624                 }
   625                 /* reset the error code, copy the data item, and continue */
   626                 *pErrorCode=U_ZERO_ERROR;
   627                 uprv_memcpy(outBytes+table[i].outOffset, inBytes+table[i].inOffset, table[i].length);
   628             }
   629         }
   631         if(inData==outData) {
   632             /* copy the data from the temporary buffer to the in-place buffer */
   633             uprv_memcpy((uint8_t *)outData+headerSize, outBytes, length);
   634         }
   635         uprv_free(table);
   637         return headerSize+length;
   638     }
   639 }
   641 /*
   642  * Hey, Emacs, please set the following:
   643  *
   644  * Local Variables:
   645  * indent-tabs-mode: nil
   646  * End:
   647  *
   648  */

mercurial