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