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