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