~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/tools/makeconv/genmbcs.c

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
*******************************************************************************
3
 
*
4
 
*   Copyright (C) 2000-2001, International Business Machines
5
 
*   Corporation and others.  All Rights Reserved.
6
 
*
7
 
*******************************************************************************
8
 
*   file name:  genmbcs.c
9
 
*   encoding:   US-ASCII
10
 
*   tab size:   8 (not used)
11
 
*   indentation:4
12
 
*
13
 
*   created on: 2000jul06
14
 
*   created by: Markus W. Scherer
15
 
*/
16
 
 
17
 
#include <stdio.h>
18
 
#include "unicode/utypes.h"
19
 
#include "cstring.h"
20
 
#include "cmemory.h"
21
 
#include "unewdata.h"
22
 
#include "ucnv_cnv.h"
23
 
#include "ucnvmbcs.h"
24
 
#include "makeconv.h"
25
 
#include "genmbcs.h"
26
 
 
27
 
enum {
28
 
    MBCS_STATE_FLAG_DIRECT=1,
29
 
    MBCS_STATE_FLAG_SURROGATES,
30
 
 
31
 
    MBCS_STATE_FLAG_READY=16
32
 
};
33
 
 
34
 
enum {
35
 
    MBCS_STAGE_2_BLOCK_SIZE=0x40, /* 64; 64=1<<6 for 6 bits in stage 2 */
36
 
    MBCS_STAGE_2_BLOCK_SIZE_SHIFT=6, /* log2(MBCS_STAGE_2_BLOCK_SIZE) */
37
 
    MBCS_STAGE_1_SIZE=0x440, /* 0x110000>>10, or 17*64 for one entry per 1k code points */
38
 
    MBCS_STAGE_2_SIZE=0xfbc0, /* 0x10000-MBCS_STAGE_1_SIZE */
39
 
    MBCS_MAX_STAGE_2_TOP=MBCS_STAGE_2_SIZE,
40
 
    MBCS_STAGE_2_MAX_BLOCKS=MBCS_STAGE_2_SIZE>>MBCS_STAGE_2_BLOCK_SIZE_SHIFT,
41
 
 
42
 
    MBCS_STAGE_2_ALL_UNASSIGNED_INDEX=0, /* stage 1 entry for the all-unassigned stage 2 block */
43
 
    MBCS_STAGE_2_FIRST_ASSIGNED=MBCS_STAGE_2_BLOCK_SIZE, /* start of the first stage 2 block after the all-unassigned one */
44
 
 
45
 
    MBCS_MAX_STATE_COUNT=128,
46
 
    MBCS_MAX_FALLBACK_COUNT=1000
47
 
};
48
 
 
49
 
typedef struct MBCSData {
50
 
    NewConverter newConverter;
51
 
 
52
 
    /* toUnicode */
53
 
    int32_t stateTable[MBCS_MAX_STATE_COUNT][256];
54
 
    uint32_t stateFlags[MBCS_MAX_STATE_COUNT],
55
 
             stateOffsetSum[MBCS_MAX_STATE_COUNT];
56
 
    _MBCSToUFallback toUFallbacks[MBCS_MAX_FALLBACK_COUNT];
57
 
    uint16_t *unicodeCodeUnits;
58
 
    _MBCSHeader header;
59
 
    int32_t countToUCodeUnits;
60
 
 
61
 
    /* fromUnicode */
62
 
    uint16_t stage1[MBCS_STAGE_1_SIZE];
63
 
    uint16_t stage2Single[MBCS_STAGE_2_SIZE]; /* stage 2 for single-byte codepages */
64
 
    uint32_t stage2[MBCS_STAGE_2_SIZE]; /* stage 2 for MBCS */
65
 
    uint8_t *fromUBytes;
66
 
    uint32_t stage2Top, stage3Top, maxCharLength;
67
 
} MBCSData;
68
 
 
69
 
/* prototypes */
70
 
static void
71
 
MBCSClose(NewConverter *cnvData);
72
 
 
73
 
static UBool
74
 
MBCSProcessStates(NewConverter *cnvData);
75
 
 
76
 
static UBool
77
 
MBCSAddToUnicode(NewConverter *cnvData,
78
 
                 const uint8_t *bytes, int32_t length,
79
 
                 UChar32 c, uint32_t b,
80
 
                 int8_t isFallback);
81
 
 
82
 
static UBool
83
 
MBCSIsValid(NewConverter *cnvData,
84
 
            const uint8_t *bytes, int32_t length,
85
 
            uint32_t b);
86
 
 
87
 
static UBool
88
 
MBCSSingleAddFromUnicode(NewConverter *cnvData,
89
 
                         const uint8_t *bytes, int32_t length,
90
 
                         UChar32 c, uint32_t b,
91
 
                         int8_t isFallback);
92
 
 
93
 
static UBool
94
 
MBCSAddFromUnicode(NewConverter *cnvData,
95
 
                   const uint8_t *bytes, int32_t length,
96
 
                   UChar32 c, uint32_t b,
97
 
                   int8_t isFallback);
98
 
 
99
 
static void
100
 
MBCSPostprocess(NewConverter *cnvData, const UConverterStaticData *staticData);
101
 
 
102
 
static uint32_t
103
 
MBCSWrite(NewConverter *cnvData, const UConverterStaticData *staticData, UNewDataMemory *pData);
104
 
 
105
 
/* implementation ----------------------------------------------------------- */
106
 
 
107
 
static void
108
 
MBCSInit(MBCSData *mbcsData, uint8_t maxCharLength) {
109
 
    int i;
110
 
 
111
 
    uprv_memset(mbcsData, 0, sizeof(MBCSData));
112
 
 
113
 
    mbcsData->newConverter.close=MBCSClose;
114
 
    mbcsData->newConverter.startMappings=MBCSProcessStates;
115
 
    mbcsData->newConverter.isValid=MBCSIsValid;
116
 
    mbcsData->newConverter.addToUnicode=MBCSAddToUnicode;
117
 
    if(maxCharLength==1) {
118
 
        mbcsData->newConverter.addFromUnicode=MBCSSingleAddFromUnicode;
119
 
    } else {
120
 
        mbcsData->newConverter.addFromUnicode=MBCSAddFromUnicode;
121
 
    }
122
 
    mbcsData->newConverter.finishMappings=MBCSPostprocess;
123
 
    mbcsData->newConverter.write=MBCSWrite;
124
 
 
125
 
    mbcsData->header.version[0]=4;
126
 
    mbcsData->stateFlags[0]=MBCS_STATE_FLAG_DIRECT;
127
 
    mbcsData->stage2Top=MBCS_STAGE_2_FIRST_ASSIGNED; /* after stage 1 and one all-unassigned stage 2 block */
128
 
    mbcsData->stage3Top=16*maxCharLength; /* after one all-unassigned stage 3 block */
129
 
    mbcsData->maxCharLength=maxCharLength;
130
 
    mbcsData->header.flags=maxCharLength-1; /* outputType */
131
 
 
132
 
    /* point all entries in stage 1 to the "all-unassigned" first block in stage 2 */
133
 
    for(i=0; i<MBCS_STAGE_1_SIZE; ++i) {
134
 
        mbcsData->stage1[i]=MBCS_STAGE_2_ALL_UNASSIGNED_INDEX;
135
 
    }
136
 
}
137
 
 
138
 
NewConverter *
139
 
MBCSOpen(uint8_t maxCharLength) {
140
 
    MBCSData *mbcsData=(MBCSData *)uprv_malloc(sizeof(MBCSData));
141
 
    if(mbcsData!=NULL) {
142
 
        MBCSInit(mbcsData, maxCharLength);
143
 
    }
144
 
    return &mbcsData->newConverter;
145
 
}
146
 
 
147
 
static void
148
 
MBCSClose(NewConverter *cnvData) {
149
 
    MBCSData *mbcsData=(MBCSData *)cnvData;
150
 
    if(mbcsData!=NULL) {
151
 
        if(mbcsData->unicodeCodeUnits!=NULL) {
152
 
            uprv_free(mbcsData->unicodeCodeUnits);
153
 
        }
154
 
        if(mbcsData->fromUBytes!=NULL) {
155
 
            uprv_free(mbcsData->fromUBytes);
156
 
        }
157
 
        uprv_free(mbcsData);
158
 
    }
159
 
}
160
 
 
161
 
static const char *
162
 
skipWhitespace(const char *s) {
163
 
    while(*s==' ' || *s=='\t') {
164
 
        ++s;
165
 
    }
166
 
    return s;
167
 
}
168
 
 
169
 
/*
170
 
 * state table row grammar (ebnf-style):
171
 
 * (whitespace is allowed between all tokens)
172
 
 *
173
 
 * row=[[firstentry ','] entry (',' entry)*]
174
 
 * firstentry="initial" | "surrogates"
175
 
 *            (initial state (default for state 0), output is all surrogate pairs)
176
 
 * entry=range [':' nextstate] ['.' action]
177
 
 * range=number ['-' number]
178
 
 * nextstate=number
179
 
 *           (0..7f)
180
 
 * action='u' | 's' | 'p' | 'i'
181
 
 *        (unassigned, state change only, surrogate pair, illegal)
182
 
 * number=(1- or 2-digit hexadecimal number)
183
 
 */
184
 
static const char *
185
 
parseState(const char *s, int32_t state[256], uint32_t *pFlags) {
186
 
    const char *t;
187
 
    uint32_t start, end, i;
188
 
    int32_t entry;
189
 
 
190
 
    /* initialize the state: all illegal with U+ffff */
191
 
    for(i=0; i<256; ++i) {
192
 
        state[i]=MBCS_ENTRY_FINAL(0, MBCS_STATE_ILLEGAL, 0xffff);
193
 
    }
194
 
 
195
 
    /* skip leading white space */
196
 
    s=skipWhitespace(s);
197
 
 
198
 
    /* is there an "initial" or "surrogates" directive? */
199
 
    if(uprv_strncmp("initial", s, 7)==0) {
200
 
        *pFlags=MBCS_STATE_FLAG_DIRECT;
201
 
        s=skipWhitespace(s+7);
202
 
        if(*s++!=',') {
203
 
            return s-1;
204
 
        }
205
 
    } else if(*pFlags==0 && uprv_strncmp("surrogates", s, 10)==0) {
206
 
        *pFlags=MBCS_STATE_FLAG_SURROGATES;
207
 
        s=skipWhitespace(s+10);
208
 
        if(*s++!=',') {
209
 
            return s-1;
210
 
        }
211
 
    } else if(*s==0) {
212
 
        /* empty state row: all-illegal */
213
 
        return NULL;
214
 
    }
215
 
 
216
 
    for(;;) {
217
 
        /* read an entry, the start of the range first */
218
 
        s=skipWhitespace(s);
219
 
        start=uprv_strtoul(s, (char **)&t, 16);
220
 
        if(s==t || 0xff<start) {
221
 
            return s;
222
 
        }
223
 
        s=skipWhitespace(t);
224
 
 
225
 
        /* read the end of the range if there is one */
226
 
        if(*s=='-') {
227
 
            s=skipWhitespace(s+1);
228
 
            end=uprv_strtoul(s, (char **)&t, 16);
229
 
            if(s==t || end<start || 0xff<end) {
230
 
                return s;
231
 
            }
232
 
            s=skipWhitespace(t);
233
 
        } else {
234
 
            end=start;
235
 
        }
236
 
 
237
 
        /* determine the state entrys for this range */
238
 
        if(*s!=':' && *s!='.') {
239
 
            /* the default is: final state with valid entries */
240
 
            entry=MBCS_ENTRY_FINAL(0, MBCS_STATE_VALID_16, 0);
241
 
        } else {
242
 
            entry=MBCS_ENTRY_TRANSITION(0, 0);
243
 
            if(*s==':') {
244
 
                /* get the next state, default to 0 */
245
 
                s=skipWhitespace(s+1);
246
 
                i=uprv_strtoul(s, (char **)&t, 16);
247
 
                if(s!=t) {
248
 
                    if(0x7f<i) {
249
 
                        return s;
250
 
                    }
251
 
                    s=skipWhitespace(t);
252
 
                    entry=MBCS_ENTRY_SET_STATE(entry, i);
253
 
                }
254
 
            }
255
 
 
256
 
            /* get the state action, default to valid */
257
 
            if(*s=='.') {
258
 
                /* this is a final state */
259
 
                entry=MBCS_ENTRY_SET_FINAL(entry);
260
 
 
261
 
                s=skipWhitespace(s+1);
262
 
                if(*s=='u') {
263
 
                    /* unassigned set U+fffe */
264
 
                    entry=MBCS_ENTRY_FINAL_SET_ACTION_VALUE(entry, MBCS_STATE_UNASSIGNED, 0xfffe);
265
 
                    s=skipWhitespace(s+1);
266
 
                } else if(*s=='p') {
267
 
                    if(*pFlags!=MBCS_STATE_FLAG_DIRECT) {
268
 
                        entry=MBCS_ENTRY_FINAL_SET_ACTION(entry, MBCS_STATE_VALID_16_PAIR);
269
 
                    } else {
270
 
                        entry=MBCS_ENTRY_FINAL_SET_ACTION(entry, MBCS_STATE_VALID_16);
271
 
                    }
272
 
                    s=skipWhitespace(s+1);
273
 
                } else if(*s=='s') {
274
 
                    entry=MBCS_ENTRY_FINAL_SET_ACTION(entry, MBCS_STATE_CHANGE_ONLY);
275
 
                    s=skipWhitespace(s+1);
276
 
                } else if(*s=='i') {
277
 
                    /* illegal set U+ffff */
278
 
                    entry=MBCS_ENTRY_FINAL_SET_ACTION_VALUE(entry, MBCS_STATE_ILLEGAL, 0xffff);
279
 
                    s=skipWhitespace(s+1);
280
 
                } else {
281
 
                    /* default to valid */
282
 
                    entry=MBCS_ENTRY_FINAL_SET_ACTION(entry, MBCS_STATE_VALID_16);
283
 
                }
284
 
            } else {
285
 
                /* this is an intermediate state, nothing to do */
286
 
            }
287
 
        }
288
 
 
289
 
        /* adjust "final valid" states according to the state flags */
290
 
        if(MBCS_ENTRY_FINAL_ACTION(entry)==MBCS_STATE_VALID_16) {
291
 
            switch(*pFlags) {
292
 
            case 0:
293
 
                /* no adjustment */
294
 
                break;
295
 
            case MBCS_STATE_FLAG_DIRECT:
296
 
                /* set the valid-direct code point to "unassigned"==0xfffe */
297
 
                entry=MBCS_ENTRY_FINAL_SET_ACTION_VALUE(entry, MBCS_STATE_VALID_DIRECT_16, 0xfffe);
298
 
                break;
299
 
            case MBCS_STATE_FLAG_SURROGATES:
300
 
                entry=MBCS_ENTRY_FINAL_SET_ACTION_VALUE(entry, MBCS_STATE_VALID_16_PAIR, 0);
301
 
                break;
302
 
            default:
303
 
                break;
304
 
            }
305
 
        }
306
 
 
307
 
        /* set this entry for the range */
308
 
        for(i=start; i<=end; ++i) {
309
 
            state[i]=entry;
310
 
        }
311
 
 
312
 
        if(*s==',') {
313
 
            ++s;
314
 
        } else {
315
 
            return *s==0 ? NULL : s;
316
 
        }
317
 
    }
318
 
}
319
 
 
320
 
UBool
321
 
MBCSAddState(NewConverter *cnvData, const char *s) {
322
 
    MBCSData *mbcsData=(MBCSData *)cnvData;
323
 
    const char *error;
324
 
 
325
 
    if(mbcsData->header.countStates==MBCS_MAX_STATE_COUNT) {
326
 
        fprintf(stderr, "error: too many states (maximum %u)\n", MBCS_MAX_STATE_COUNT);
327
 
        return FALSE;
328
 
    }
329
 
 
330
 
    error=parseState(s, mbcsData->stateTable[mbcsData->header.countStates],
331
 
                       &mbcsData->stateFlags[mbcsData->header.countStates]);
332
 
    if(error!=NULL) {
333
 
        fprintf(stderr, "parse error in state definition at '%s'\n", error);
334
 
        return FALSE;
335
 
    }
336
 
 
337
 
    ++mbcsData->header.countStates;
338
 
    return TRUE;
339
 
}
340
 
 
341
 
static int32_t
342
 
sumUpStates(MBCSData *mbcsData) {
343
 
    int32_t entry, sum;
344
 
    int state, cell, count;
345
 
    UBool allStatesReady;
346
 
 
347
 
    /*
348
 
     * Sum up the offsets for all states.
349
 
     * In each final state (where there are only final entries),
350
 
     * the offsets add up directly.
351
 
     * In all other state table rows, for each transition entry to another state,
352
 
     * the offsets sum of that state needs to be added.
353
 
     * This is achieved in at most countStates iterations.
354
 
     */
355
 
    allStatesReady=FALSE;
356
 
    for(count=mbcsData->header.countStates; !allStatesReady && count>=0; --count) {
357
 
        allStatesReady=TRUE;
358
 
        for(state=mbcsData->header.countStates-1; state>=0; --state) {
359
 
            if(!(mbcsData->stateFlags[state]&MBCS_STATE_FLAG_READY)) {
360
 
                allStatesReady=FALSE;
361
 
                sum=0;
362
 
 
363
 
                /* at first, add up only the final delta offsets to keep them <512 */
364
 
                for(cell=0; cell<256; ++cell) {
365
 
                    entry=mbcsData->stateTable[state][cell];
366
 
                    if(MBCS_ENTRY_IS_FINAL(entry)) {
367
 
                        switch(MBCS_ENTRY_FINAL_ACTION(entry)) {
368
 
                        case MBCS_STATE_VALID_16:
369
 
                            mbcsData->stateTable[state][cell]=MBCS_ENTRY_FINAL_SET_VALUE(entry, sum);
370
 
                            sum+=1;
371
 
                            break;
372
 
                        case MBCS_STATE_VALID_16_PAIR:
373
 
                            mbcsData->stateTable[state][cell]=MBCS_ENTRY_FINAL_SET_VALUE(entry, sum);
374
 
                            sum+=2;
375
 
                            break;
376
 
                        default:
377
 
                            /* no addition */
378
 
                            break;
379
 
                        }
380
 
                    }
381
 
                }
382
 
 
383
 
                /* now, add up the delta offsets for the transitional entries */
384
 
                for(cell=0; cell<256; ++cell) {
385
 
                    entry=mbcsData->stateTable[state][cell];
386
 
                    if(MBCS_ENTRY_IS_TRANSITION(entry)) {
387
 
                        if(mbcsData->stateFlags[MBCS_ENTRY_TRANSITION_STATE(entry)]&MBCS_STATE_FLAG_READY) {
388
 
                            mbcsData->stateTable[state][cell]=MBCS_ENTRY_TRANSITION_SET_OFFSET(entry, sum);
389
 
                            sum+=mbcsData->stateOffsetSum[MBCS_ENTRY_TRANSITION_STATE(entry)];
390
 
                        } else {
391
 
                            /* that next state does not have a sum yet, we cannot finish the one for this state */
392
 
                            sum=-1;
393
 
                            break;
394
 
                        }
395
 
                    }
396
 
                }
397
 
 
398
 
                if(sum!=-1) {
399
 
                    mbcsData->stateOffsetSum[state]=sum;
400
 
                    mbcsData->stateFlags[state]|=MBCS_STATE_FLAG_READY;
401
 
                }
402
 
            }
403
 
        }
404
 
    }
405
 
 
406
 
    if(!allStatesReady) {
407
 
        fprintf(stderr, "error: the state table contains loops\n");
408
 
        return -1;
409
 
    }
410
 
 
411
 
    /*
412
 
     * For all "direct" (i.e., initial) states>0,
413
 
     * the offsets need to be increased by the sum of
414
 
     * the previous initial states.
415
 
     */
416
 
    sum=mbcsData->stateOffsetSum[0];
417
 
    for(state=1; state<(int)mbcsData->header.countStates; ++state) {
418
 
        if((mbcsData->stateFlags[state]&0xf)==MBCS_STATE_FLAG_DIRECT) {
419
 
            int32_t sum2=sum;
420
 
            sum+=mbcsData->stateOffsetSum[state];
421
 
            for(cell=0; cell<256; ++cell) {
422
 
                entry=mbcsData->stateTable[state][cell];
423
 
                if(MBCS_ENTRY_IS_TRANSITION(entry)) {
424
 
                    mbcsData->stateTable[state][cell]=MBCS_ENTRY_TRANSITION_ADD_OFFSET(entry, sum2);
425
 
                }
426
 
            }
427
 
        }
428
 
    }
429
 
    if(VERBOSE) {
430
 
        printf("the total number of offsets is 0x%lx=%ld\n",
431
 
            (unsigned long)sum, (long)sum);
432
 
    }
433
 
 
434
 
    /* round up to the next even number to have the following data 32-bit-aligned */
435
 
    sum=(sum+1)&~1;
436
 
    return mbcsData->countToUCodeUnits=sum;
437
 
}
438
 
 
439
 
static UBool
440
 
MBCSProcessStates(NewConverter *cnvData) {
441
 
    MBCSData *mbcsData=(MBCSData *)cnvData;
442
 
    int32_t i, entry, sum;
443
 
    int state, cell;
444
 
 
445
 
    /*
446
 
     * first make sure that all "next state" values are within limits
447
 
     * and that all next states after final ones have the "direct"
448
 
     * flag of initial states
449
 
     */
450
 
    for(state=mbcsData->header.countStates-1; state>=0; --state) {
451
 
        for(cell=0; cell<256; ++cell) {
452
 
            entry=mbcsData->stateTable[state][cell];
453
 
            if((uint8_t)MBCS_ENTRY_STATE(entry)>=mbcsData->header.countStates) {
454
 
                fprintf(stderr, "error: state table entry [%x][%x] has a next state of %x that is too high\n",
455
 
                    state, cell, MBCS_ENTRY_STATE(entry));
456
 
                return FALSE;
457
 
            }
458
 
            if(MBCS_ENTRY_IS_FINAL(entry) && (mbcsData->stateFlags[MBCS_ENTRY_STATE(entry)]&0xf)!=MBCS_STATE_FLAG_DIRECT) {
459
 
                fprintf(stderr, "error: state table entry [%x][%x] is final but has a non-initial next state of %x\n",
460
 
                    state, cell, MBCS_ENTRY_STATE(entry));
461
 
                return FALSE;
462
 
            } else if(MBCS_ENTRY_IS_TRANSITION(entry) && (mbcsData->stateFlags[MBCS_ENTRY_STATE(entry)]&0xf)==MBCS_STATE_FLAG_DIRECT) {
463
 
                fprintf(stderr, "error: state table entry [%x][%x] is not final but has an initial next state of %x\n",
464
 
                    state, cell, MBCS_ENTRY_STATE(entry));
465
 
                return FALSE;
466
 
            }
467
 
        }
468
 
    }
469
 
 
470
 
    /* is this an SI/SO (like EBCDIC-stateful) state table? */
471
 
    if(mbcsData->header.countStates>=2 && (mbcsData->stateFlags[1]&0xf)==MBCS_STATE_FLAG_DIRECT) {
472
 
        if(mbcsData->maxCharLength!=2) {
473
 
            fprintf(stderr, "error: SI/SO codepages must have max 2 bytes/char (not %x)\n", mbcsData->maxCharLength);
474
 
            return FALSE;
475
 
        }
476
 
        if(mbcsData->header.countStates<3) {
477
 
            fprintf(stderr, "error: SI/SO codepages must have at least 3 states (not %x)\n", mbcsData->header.countStates);
478
 
            return FALSE;
479
 
        }
480
 
        /* are the SI/SO all in the right places? */
481
 
        if( mbcsData->stateTable[0][0xe]==MBCS_ENTRY_FINAL(1, MBCS_STATE_CHANGE_ONLY, 0) &&
482
 
            mbcsData->stateTable[0][0xf]==MBCS_ENTRY_FINAL(0, MBCS_STATE_CHANGE_ONLY, 0) &&
483
 
            mbcsData->stateTable[1][0xe]==MBCS_ENTRY_FINAL(1, MBCS_STATE_CHANGE_ONLY, 0) &&
484
 
            mbcsData->stateTable[1][0xf]==MBCS_ENTRY_FINAL(0, MBCS_STATE_CHANGE_ONLY, 0)
485
 
        ) {
486
 
            mbcsData->header.flags=MBCS_OUTPUT_2_SISO;
487
 
        } else {
488
 
            fprintf(stderr, "error: SI/SO codepages must have in states 0 and 1 transitions e:1.s, f:0.s\n");
489
 
            return FALSE;
490
 
        }
491
 
        state=2;
492
 
    } else {
493
 
        state=1;
494
 
    }
495
 
 
496
 
    /* check that no unexpected state is a "direct" one */
497
 
    while(state<(int)mbcsData->header.countStates) {
498
 
        if((mbcsData->stateFlags[state]&0xf)==MBCS_STATE_FLAG_DIRECT) {
499
 
            fprintf(stderr, "error: state %d is 'initial' - not supported except for SI/SO codepages\n", state);
500
 
            return FALSE;
501
 
        }
502
 
        ++state;
503
 
    }
504
 
 
505
 
    sum=sumUpStates(mbcsData);
506
 
    if(sum<0) {
507
 
        return FALSE;
508
 
    }
509
 
 
510
 
    /* allocate the code unit array and prefill it with "unassigned" values */
511
 
    if(sum>0) {
512
 
        mbcsData->unicodeCodeUnits=(uint16_t *)uprv_malloc(sum*sizeof(uint16_t));
513
 
        if(mbcsData->unicodeCodeUnits==NULL) {
514
 
            fprintf(stderr, "error: out of memory allocating %ld 16-bit code units\n",
515
 
                (long)sum);
516
 
            return FALSE;
517
 
        }
518
 
        for(i=0; i<sum; ++i) {
519
 
            mbcsData->unicodeCodeUnits[i]=0xfffe;
520
 
        }
521
 
    }
522
 
 
523
 
    /* allocate the codepage mappings and preset the first 16 characters to 0 */
524
 
    if(mbcsData->maxCharLength==1) {
525
 
        /* allocate 64k 16-bit results for single-byte codepages */
526
 
        sum=0x20000;
527
 
    } else {
528
 
        /* allocate 1M * maxCharLength bytes for at most 1M mappings */
529
 
        sum=0x100000*mbcsData->maxCharLength;
530
 
    }
531
 
    mbcsData->fromUBytes=(uint8_t *)uprv_malloc(sum);
532
 
    if(mbcsData->fromUBytes==NULL) {
533
 
        fprintf(stderr, "error: out of memory allocating %ldMB for target mappings\n",
534
 
            (long)sum);
535
 
        return FALSE;
536
 
    }
537
 
    /* initialize the all-unassigned first stage 3 block */
538
 
    uprv_memset(mbcsData->fromUBytes, 0, 64);
539
 
 
540
 
    return TRUE;
541
 
}
542
 
 
543
 
/* find a fallback for this offset; return the index or -1 if not found */
544
 
static int32_t
545
 
findFallback(MBCSData *mbcsData, uint32_t offset) {
546
 
    _MBCSToUFallback *toUFallbacks;
547
 
    int32_t i, limit;
548
 
 
549
 
    limit=mbcsData->header.countToUFallbacks;
550
 
    if(limit==0) {
551
 
        /* shortcut: most codepages do not have fallbacks from codepage to Unicode */
552
 
        return -1;
553
 
    }
554
 
 
555
 
    /* do a linear search for the fallback mapping (the table is not yet sorted) */
556
 
    toUFallbacks=mbcsData->toUFallbacks;
557
 
    for(i=0; i<limit; ++i) {
558
 
        if(offset==toUFallbacks[i].offset) {
559
 
            return i;
560
 
        }
561
 
    }
562
 
    return -1;
563
 
}
564
 
 
565
 
/* return TRUE for success */
566
 
static UBool
567
 
setFallback(MBCSData *mbcsData, uint32_t offset, UChar32 c) {
568
 
    int32_t i=findFallback(mbcsData, offset);
569
 
    if(i>=0) {
570
 
        /* if there is already a fallback for this offset, then overwrite it */
571
 
        mbcsData->toUFallbacks[i].codePoint=c;
572
 
        return TRUE;
573
 
    } else {
574
 
        /* if there is no fallback for this offset, then add one */
575
 
        i=mbcsData->header.countToUFallbacks;
576
 
        if(i>=MBCS_MAX_FALLBACK_COUNT) {
577
 
            fprintf(stderr, "error: too many toUnicode fallbacks, currently at: U+%lx\n", c);
578
 
            return FALSE;
579
 
        } else {
580
 
            mbcsData->toUFallbacks[i].offset=offset;
581
 
            mbcsData->toUFallbacks[i].codePoint=c;
582
 
            mbcsData->header.countToUFallbacks=i+1;
583
 
            return TRUE;
584
 
        }
585
 
    }
586
 
}
587
 
 
588
 
/* remove fallback if there is one with this offset; return the code point if there was such a fallback, otherwise -1 */
589
 
static int32_t
590
 
removeFallback(MBCSData *mbcsData, uint32_t offset) {
591
 
    int32_t i=findFallback(mbcsData, offset);
592
 
    if(i>=0) {
593
 
        _MBCSToUFallback *toUFallbacks;
594
 
        int32_t limit, old;
595
 
 
596
 
        toUFallbacks=mbcsData->toUFallbacks;
597
 
        limit=mbcsData->header.countToUFallbacks;
598
 
        old=(int32_t)toUFallbacks[i].codePoint;
599
 
 
600
 
        /* copy the last fallback entry here to keep the list contiguous */
601
 
        toUFallbacks[i].offset=toUFallbacks[limit-1].offset;
602
 
        toUFallbacks[i].codePoint=toUFallbacks[limit-1].codePoint;
603
 
        mbcsData->header.countToUFallbacks=limit-1;
604
 
        return old;
605
 
    } else {
606
 
        return -1;
607
 
    }
608
 
}
609
 
 
610
 
/*
611
 
 * isFallback is almost a boolean:
612
 
 * 1 (TRUE)  this is a fallback mapping
613
 
 * 0 (FALSE) this is a precise mapping
614
 
 * -1        the precision of this mapping is not specified
615
 
 */
616
 
static UBool
617
 
MBCSAddToUnicode(NewConverter *cnvData,
618
 
                 const uint8_t *bytes, int32_t length,
619
 
                 UChar32 c, uint32_t b,
620
 
                 int8_t isFallback) {
621
 
    MBCSData *mbcsData=(MBCSData *)cnvData;
622
 
    uint32_t offset=0;
623
 
    int32_t i=0, entry, old;
624
 
    uint8_t state=0;
625
 
 
626
 
    if(mbcsData->header.countStates==0) {
627
 
        fprintf(stderr, "error: there is no state information!\n");
628
 
        return FALSE;
629
 
    }
630
 
 
631
 
    /* for SI/SO (like EBCDIC-stateful), double-byte sequences start in state 1 */
632
 
    if(length==2 && (mbcsData->header.flags&0xff)==MBCS_OUTPUT_2_SISO) {
633
 
        state=1;
634
 
    }
635
 
 
636
 
    /*
637
 
     * Walk down the state table like in conversion,
638
 
     * much like getNextUChar().
639
 
     * We assume that c<=0x10ffff.
640
 
     */
641
 
    for(i=0;;) {
642
 
        entry=mbcsData->stateTable[state][bytes[i++]];
643
 
        if(MBCS_ENTRY_IS_TRANSITION(entry)) {
644
 
            if(i==length) {
645
 
                fprintf(stderr, "error: byte sequence too short, ends in non-final state %hu: 0x%02lx (U+%lx)\n",
646
 
                    state, (unsigned long)b, c);
647
 
                return FALSE;
648
 
            }
649
 
            state=(uint8_t)MBCS_ENTRY_TRANSITION_STATE(entry);
650
 
            offset+=MBCS_ENTRY_TRANSITION_OFFSET(entry);
651
 
        } else {
652
 
            if(i<length) {
653
 
                fprintf(stderr, "error: byte sequence too long by %d bytes, final state %hu: 0x%02lx (U+%lx)\n",
654
 
                    (length-i), state, (unsigned long)b, c);
655
 
                return FALSE;
656
 
            }
657
 
            switch(MBCS_ENTRY_FINAL_ACTION(entry)) {
658
 
            case MBCS_STATE_ILLEGAL:
659
 
                fprintf(stderr, "error: byte sequence ends in illegal state at U+%04lx<->0x%02lx\n",
660
 
                    c, (unsigned long)b);
661
 
                return FALSE;
662
 
            case MBCS_STATE_CHANGE_ONLY:
663
 
                fprintf(stderr, "error: byte sequence ends in state-change-only at U+%04lx<->0x%02lx\n",
664
 
                    c, (unsigned long)b);
665
 
                return FALSE;
666
 
            case MBCS_STATE_UNASSIGNED:
667
 
                fprintf(stderr, "error: byte sequence ends in unassigned state at U+%04lx<->0x%02lx\n",
668
 
                    c, (unsigned long)b);
669
 
                return FALSE;
670
 
            case MBCS_STATE_FALLBACK_DIRECT_16:
671
 
            case MBCS_STATE_VALID_DIRECT_16:
672
 
            case MBCS_STATE_FALLBACK_DIRECT_20:
673
 
            case MBCS_STATE_VALID_DIRECT_20:
674
 
                if(MBCS_ENTRY_SET_STATE(entry, 0)!=MBCS_ENTRY_FINAL(0, MBCS_STATE_VALID_DIRECT_16, 0xfffe)) {
675
 
                    /* the "direct" action's value is not "valid-direct-16-unassigned" any more */
676
 
                    if(MBCS_ENTRY_FINAL_ACTION(entry)==MBCS_STATE_VALID_DIRECT_16 || MBCS_ENTRY_FINAL_ACTION(entry)==MBCS_STATE_FALLBACK_DIRECT_16) {
677
 
                        old=MBCS_ENTRY_FINAL_VALUE(entry);
678
 
                    } else {
679
 
                        old=0x10000+MBCS_ENTRY_FINAL_VALUE(entry);
680
 
                    }
681
 
                    if(isFallback>=0) {
682
 
                        fprintf(stderr, "error: duplicate codepage byte sequence at U+%04lx<->0x%02lx see U+%04lx\n",
683
 
                            c, (unsigned long)b, (long)old);
684
 
                        return FALSE;
685
 
                    } else if(VERBOSE) {
686
 
                        fprintf(stderr, "duplicate codepage byte sequence at U+%04lx<->0x%02lx see U+%04lx\n",
687
 
                            c, (unsigned long)b, (long)old);
688
 
                    }
689
 
                    /*
690
 
                     * Continue after the above warning
691
 
                     * if the precision of the mapping is unspecified.
692
 
                     */
693
 
                }
694
 
                /* reassign the correct action code */
695
 
                entry=MBCS_ENTRY_FINAL_SET_ACTION(entry, (MBCS_STATE_VALID_DIRECT_16+(isFallback>0 ? 2 : 0)+(c>=0x10000 ? 1 : 0)));
696
 
 
697
 
                /* put the code point into bits 22..7 for BMP, c-0x10000 into 26..7 for others */
698
 
                if(c<=0xffff) {
699
 
                    entry=MBCS_ENTRY_FINAL_SET_VALUE(entry, c);
700
 
                } else {
701
 
                    entry=MBCS_ENTRY_FINAL_SET_VALUE(entry, c-0x10000);
702
 
                }
703
 
                mbcsData->stateTable[state][bytes[i-1]]=entry;
704
 
                break;
705
 
            case MBCS_STATE_VALID_16:
706
 
                /* bits 26..16 are not used, 0 */
707
 
                /* bits 15..7 contain the final offset delta to one 16-bit code unit */
708
 
                offset+=MBCS_ENTRY_FINAL_VALUE_16(entry);
709
 
                /* check that this byte sequence is still unassigned */
710
 
                if((old=mbcsData->unicodeCodeUnits[offset])!=0xfffe || (old=removeFallback(mbcsData, offset))!=-1) {
711
 
                    if(isFallback>=0) {
712
 
                        fprintf(stderr, "error: duplicate codepage byte sequence at U+%04lx<->0x%02lx see U+%04lx\n",
713
 
                            c, (unsigned long)b, (long)old);
714
 
                        return FALSE;
715
 
                    } else if(VERBOSE) {
716
 
                        fprintf(stderr, "duplicate codepage byte sequence at U+%04lx<->0x%02lx see U+%04lx\n",
717
 
                            c, (unsigned long)b, (long)old);
718
 
                    }
719
 
                }
720
 
                if(c>=0x10000) {
721
 
                    fprintf(stderr, "error: code point does not fit into valid-16-bit state at U+%04lx<->0x%02lx\n",
722
 
                        c, (unsigned long)b);
723
 
                    return FALSE;
724
 
                }
725
 
                if(isFallback>0) {
726
 
                    /* assign only if there is no precise mapping */
727
 
                    if(mbcsData->unicodeCodeUnits[offset]==0xfffe) {
728
 
                        return setFallback(mbcsData, offset, c);
729
 
                    }
730
 
                } else {
731
 
                    mbcsData->unicodeCodeUnits[offset]=(uint16_t)c;
732
 
                }
733
 
                break;
734
 
            case MBCS_STATE_VALID_16_PAIR:
735
 
                /* bits 26..16 are not used, 0 */
736
 
                /* bits 15..7 contain the final offset delta to two 16-bit code units */
737
 
                offset+=MBCS_ENTRY_FINAL_VALUE_16(entry);
738
 
                /* check that this byte sequence is still unassigned */
739
 
                old=mbcsData->unicodeCodeUnits[offset];
740
 
                if(old<0xfffe) {
741
 
                    int32_t real;
742
 
                    if(old<0xd800) {
743
 
                        real=old;
744
 
                    } else if(old<=0xdfff) {
745
 
                        real=0x10000+((old&0x3ff)<<10)+((mbcsData->unicodeCodeUnits[offset+1])&0x3ff);
746
 
                    } else /* old<=0xe001 */ {
747
 
                        real=mbcsData->unicodeCodeUnits[offset+1];
748
 
                    }
749
 
                    if(isFallback>=0) {
750
 
                        fprintf(stderr, "error: duplicate codepage byte sequence at U+%04lx<->0x%02lx see U+%04lx\n",
751
 
                            c, (unsigned long)b, (long)real);
752
 
                        return FALSE;
753
 
                    } else if(VERBOSE) {
754
 
                        fprintf(stderr, "duplicate codepage byte sequence at U+%04lx<->0x%02lx see U+%04lx\n",
755
 
                            c, (unsigned long)b, (long)real);
756
 
                    }
757
 
                }
758
 
                if(isFallback>0) {
759
 
                    /* assign only if there is no precise mapping */
760
 
                    if(old<=0xdbff || old==0xe000) {
761
 
                        /* do nothing */
762
 
                    } else if(c<=0xffff) {
763
 
                        /* set a BMP fallback code point as a pair with 0xe001 */
764
 
                        mbcsData->unicodeCodeUnits[offset++]=0xe001;
765
 
                        mbcsData->unicodeCodeUnits[offset]=(uint16_t)c;
766
 
                    } else {
767
 
                        /* set a fallback surrogate pair with two second surrogates */
768
 
                        mbcsData->unicodeCodeUnits[offset++]=(uint16_t)(0xdbc0+(c>>10));
769
 
                        mbcsData->unicodeCodeUnits[offset]=(uint16_t)(0xdc00+(c&0x3ff));
770
 
                    }
771
 
                } else {
772
 
                    if(c<0xd800) {
773
 
                        /* set a BMP code point */
774
 
                        mbcsData->unicodeCodeUnits[offset]=(uint16_t)c;
775
 
                    } else if(c<=0xffff) {
776
 
                        /* set a BMP code point above 0xd800 as a pair with 0xe000 */
777
 
                        mbcsData->unicodeCodeUnits[offset++]=0xe000;
778
 
                        mbcsData->unicodeCodeUnits[offset]=(uint16_t)c;
779
 
                    } else {
780
 
                        /* set a surrogate pair */
781
 
                        mbcsData->unicodeCodeUnits[offset++]=(uint16_t)(0xd7c0+(c>>10));
782
 
                        mbcsData->unicodeCodeUnits[offset]=(uint16_t)(0xdc00+(c&0x3ff));
783
 
                    }
784
 
                }
785
 
                break;
786
 
            default:
787
 
                /* reserved, must never occur */
788
 
                fprintf(stderr, "internal error: byte sequence reached reserved action code, entry0x%02lx: 0x%02lx (U+%lx)\n",
789
 
                    (unsigned long)entry, (unsigned long)b, c);
790
 
                return FALSE;
791
 
            }
792
 
 
793
 
            return TRUE;
794
 
        }
795
 
    }
796
 
}
797
 
 
798
 
/* is this byte sequence valid? (this is almost the same as MBCSAddToUnicode()) */
799
 
static UBool
800
 
MBCSIsValid(NewConverter *cnvData,
801
 
            const uint8_t *bytes, int32_t length,
802
 
            uint32_t b) {
803
 
    MBCSData *mbcsData=(MBCSData *)cnvData;
804
 
    uint32_t offset=0;
805
 
    int32_t i=0, entry;
806
 
    uint8_t state=0;
807
 
 
808
 
    if(mbcsData->header.countStates==0) {
809
 
        fprintf(stderr, "error: there is no state information!\n");
810
 
        return FALSE;
811
 
    }
812
 
 
813
 
    /* for SI/SO (like EBCDIC-stateful), double-byte sequences start in state 1 */
814
 
    if(length==2 && (mbcsData->header.flags&0xff)==MBCS_OUTPUT_2_SISO) {
815
 
        state=1;
816
 
    }
817
 
 
818
 
    /*
819
 
     * Walk down the state table like in conversion,
820
 
     * much like getNextUChar().
821
 
     * We assume that c<=0x10ffff.
822
 
     */
823
 
    for(i=0;;) {
824
 
        entry=mbcsData->stateTable[state][bytes[i++]];
825
 
        if(MBCS_ENTRY_IS_TRANSITION(entry)) {
826
 
            if(i==length) {
827
 
                fprintf(stderr, "error: byte sequence too short, ends in non-final state %hu: 0x%02lx\n",
828
 
                    state, (unsigned long)b);
829
 
                return FALSE;
830
 
            }
831
 
            state=(uint8_t)MBCS_ENTRY_TRANSITION_STATE(entry);
832
 
            offset+=MBCS_ENTRY_TRANSITION_OFFSET(entry);
833
 
        } else {
834
 
            if(i<length) {
835
 
                fprintf(stderr, "error: byte sequence too long by %d bytes, final state %hu: 0x%02lx\n",
836
 
                    (length-i), state, (unsigned long)b);
837
 
                return FALSE;
838
 
            }
839
 
            switch(MBCS_ENTRY_FINAL_ACTION(entry)) {
840
 
            case MBCS_STATE_ILLEGAL:
841
 
                fprintf(stderr, "error: byte sequence ends in illegal state: 0x%02lx\n",
842
 
                    (unsigned long)b);
843
 
                return FALSE;
844
 
            case MBCS_STATE_CHANGE_ONLY:
845
 
                fprintf(stderr, "error: byte sequence ends in state-change-only: 0x%02lx\n",
846
 
                    (unsigned long)b);
847
 
                return FALSE;
848
 
            case MBCS_STATE_UNASSIGNED:
849
 
                fprintf(stderr, "error: byte sequence ends in unassigned state: 0x%02lx\n",
850
 
                    (unsigned long)b);
851
 
                return FALSE;
852
 
            case MBCS_STATE_FALLBACK_DIRECT_16:
853
 
            case MBCS_STATE_VALID_DIRECT_16:
854
 
            case MBCS_STATE_FALLBACK_DIRECT_20:
855
 
            case MBCS_STATE_VALID_DIRECT_20:
856
 
            case MBCS_STATE_VALID_16:
857
 
            case MBCS_STATE_VALID_16_PAIR:
858
 
                return TRUE;
859
 
            default:
860
 
                /* reserved, must never occur */
861
 
                fprintf(stderr, "internal error: byte sequence reached reserved action code, entry0x%02lx: 0x%02lx\n",
862
 
                    (long)entry, (unsigned long)b);
863
 
                return FALSE;
864
 
            }
865
 
        }
866
 
    }
867
 
}
868
 
 
869
 
static UBool
870
 
MBCSSingleAddFromUnicode(NewConverter *cnvData,
871
 
                         const uint8_t *bytes, int32_t length,
872
 
                         UChar32 c, uint32_t b,
873
 
                         int8_t isFallback) {
874
 
    MBCSData *mbcsData=(MBCSData *)cnvData;
875
 
    uint16_t *p;
876
 
    uint32_t index;
877
 
    uint16_t old;
878
 
 
879
 
    /*
880
 
     * Walk down the triple-stage compact array ("trie") and
881
 
     * allocate parts as necessary.
882
 
     * Note that the first stage 2 and 3 blocks are reserved for all-unassigned mappings.
883
 
     * We assume that length<=maxCharLength and that c<=0x10ffff.
884
 
     */
885
 
 
886
 
    /* inspect stage 1 */
887
 
    index=c>>10;
888
 
    if(mbcsData->stage1[index]==MBCS_STAGE_2_ALL_UNASSIGNED_INDEX) {
889
 
        /* allocate another block in stage 2 */
890
 
        if(mbcsData->stage2Top>=MBCS_MAX_STAGE_2_TOP) {
891
 
            fprintf(stderr, "error: too many stage 2 entries at U+%04lx<->0x%02lx\n",
892
 
                c, (unsigned long)b);
893
 
            return FALSE;
894
 
        }
895
 
 
896
 
        /*
897
 
         * each stage 2 block contains 64 16-bit words:
898
 
         * 6 code point bits 9..4 with 1 stage 3 index
899
 
         */
900
 
        mbcsData->stage1[index]=(uint16_t)mbcsData->stage2Top;
901
 
        mbcsData->stage2Top+=MBCS_STAGE_2_BLOCK_SIZE;
902
 
    }
903
 
 
904
 
    /* inspect stage 2 */
905
 
    index=(uint32_t)mbcsData->stage1[index]+((c>>4)&0x3f);
906
 
    if(mbcsData->stage2Single[index]==0) {
907
 
        /* allocate another block in stage 3 */
908
 
        if(mbcsData->stage3Top>=0x10000) {
909
 
            fprintf(stderr, "error: too many code points at U+%04lx<->0x%02lx\n",
910
 
                c, (unsigned long)b);
911
 
            return FALSE;
912
 
        }
913
 
        /* each block has 16 uint16_t entries */
914
 
        mbcsData->stage2Single[index]=(uint16_t)mbcsData->stage3Top;
915
 
        uprv_memset(mbcsData->fromUBytes+2*mbcsData->stage3Top, 0, 32);
916
 
        mbcsData->stage3Top+=16;
917
 
    }
918
 
 
919
 
    /* write the codepage entry into stage 3 and get the previous entry */
920
 
    p=(uint16_t *)mbcsData->fromUBytes+mbcsData->stage2Single[index]+(c&0xf);
921
 
    old=*p;
922
 
    if(isFallback<=0) {
923
 
        *p=(uint16_t)(0xf00|b);
924
 
    } else if(IS_PRIVATE_USE(c)) {
925
 
        *p=(uint16_t)(0xc00|b);
926
 
    } else {
927
 
        *p=(uint16_t)(0x800|b);
928
 
    }
929
 
 
930
 
    /* check that this Unicode code point was still unassigned */
931
 
    if(old>=0xf00) {
932
 
        if(isFallback>=0) {
933
 
            fprintf(stderr, "error: duplicate Unicode code point at U+%04lx<->0x%02lx see 0x%02x\n",
934
 
                c, (unsigned long)b, old);
935
 
            return FALSE;
936
 
        } else if(VERBOSE) {
937
 
            fprintf(stderr, "duplicate Unicode code point at U+%04lx<->0x%02lx see 0x%02x\n",
938
 
                c, (unsigned long)b, old);
939
 
        }
940
 
        /* continue after the above warning if the precision of the mapping is unspecified */
941
 
    }
942
 
 
943
 
    return TRUE;
944
 
}
945
 
 
946
 
static UBool
947
 
MBCSAddFromUnicode(NewConverter *cnvData,
948
 
                   const uint8_t *bytes, int32_t length,
949
 
                   UChar32 c, uint32_t b,
950
 
                   int8_t isFallback) {
951
 
    MBCSData *mbcsData=(MBCSData *)cnvData;
952
 
    uint8_t *p;
953
 
    uint32_t index, old;
954
 
 
955
 
    if( (mbcsData->header.flags&0xff)==MBCS_OUTPUT_2_SISO &&
956
 
        (*bytes==0xe || *bytes==0xf)
957
 
    ) {
958
 
        fprintf(stderr, "error: illegal mapping to SI or SO for SI/SO codepage: U+%04lx<->0x%02lx\n",
959
 
            c, (unsigned long)b);
960
 
        return FALSE;
961
 
    }
962
 
    /*
963
 
     * Walk down the triple-stage compact array ("trie") and
964
 
     * allocate parts as necessary.
965
 
     * Note that the first stage 2 and 3 blocks are reserved for
966
 
     * all-unassigned mappings.
967
 
     * We assume that length<=maxCharLength and that c<=0x10ffff.
968
 
     */
969
 
 
970
 
    /* inspect stage 1 */
971
 
    index=c>>10;
972
 
    if(mbcsData->stage1[index]==MBCS_STAGE_2_ALL_UNASSIGNED_INDEX) {
973
 
        /* allocate another block in stage 2 */
974
 
        if(mbcsData->stage2Top>=MBCS_MAX_STAGE_2_TOP) {
975
 
            fprintf(stderr, "error: too many stage 2 entries at U+%04lx<->0x%02lx\n",
976
 
                c, (unsigned long)b);
977
 
            return FALSE;
978
 
        }
979
 
 
980
 
        /*
981
 
         * each stage 2 block contains 64 32-bit words:
982
 
         * 6 code point bits 9..4 with value with bits 31..16 "assigned" flags and bits 15..0 stage 3 index
983
 
         */
984
 
        mbcsData->stage1[index]=(uint16_t)mbcsData->stage2Top;
985
 
        mbcsData->stage2Top+=MBCS_STAGE_2_BLOCK_SIZE;
986
 
    }
987
 
 
988
 
    /* inspect stage 2 */
989
 
    index=mbcsData->stage1[index]+((c>>4)&0x3f);
990
 
    if(mbcsData->stage2[index]==0) {
991
 
        /* allocate another block in stage 3 */
992
 
        if(mbcsData->stage3Top>=0x100000*mbcsData->maxCharLength) {
993
 
            fprintf(stderr, "error: too many code points at U+%04lx<->0x%02lx\n",
994
 
                c, (unsigned long)b);
995
 
            return FALSE;
996
 
        }
997
 
        /* each block has 16*maxCharLength bytes */
998
 
        mbcsData->stage2[index]=(mbcsData->stage3Top/16)/mbcsData->maxCharLength;
999
 
        uprv_memset(mbcsData->fromUBytes+mbcsData->stage3Top, 0, 16*mbcsData->maxCharLength);
1000
 
        mbcsData->stage3Top+=16*mbcsData->maxCharLength;
1001
 
    }
1002
 
 
1003
 
    /* write the codepage bytes into stage 3 and get the previous bytes */
1004
 
    old=0;
1005
 
    p=mbcsData->fromUBytes+(16*(uint32_t)(uint16_t)mbcsData->stage2[index]+(c&0xf))*mbcsData->maxCharLength;
1006
 
    switch(mbcsData->maxCharLength) {
1007
 
    case 2:
1008
 
        old=*(uint16_t *)p;
1009
 
        *(uint16_t *)p=(uint16_t)b;
1010
 
        break;
1011
 
    case 3:
1012
 
        old=(uint32_t)*p<<16;
1013
 
        *p++=(uint8_t)(b>>16);
1014
 
        old|=(uint32_t)*p<<8;
1015
 
        *p++=(uint8_t)(b>>8);
1016
 
        old|=*p;
1017
 
        *p=(uint8_t)b;
1018
 
        break;
1019
 
    case 4:
1020
 
        old=*(uint32_t *)p;
1021
 
        *(uint32_t *)p=b;
1022
 
        break;
1023
 
    default:
1024
 
        /* will never occur */
1025
 
        break;
1026
 
    }
1027
 
 
1028
 
    /* check that this Unicode code point was still unassigned */
1029
 
    if((mbcsData->stage2[index]&(1UL<<(16+(c&0xf))))!=0 || old!=0) {
1030
 
        if(isFallback>=0) {
1031
 
            fprintf(stderr, "error: duplicate Unicode code point at U+%04lx<->0x%02lx see 0x%02lx\n",
1032
 
                c, (unsigned long)b, (unsigned long)old);
1033
 
            return FALSE;
1034
 
        } else if(VERBOSE) {
1035
 
            fprintf(stderr, "duplicate Unicode code point at U+%04lx<->0x%02lx see 0x%02lx\n",
1036
 
                c, (unsigned long)b, (unsigned long)old);
1037
 
        }
1038
 
        /* continue after the above warning if the precision of the mapping is
1039
 
           unspecified */
1040
 
    }
1041
 
    if(isFallback<=0) {
1042
 
        /* set the "assigned" flag */
1043
 
        mbcsData->stage2[index]|=(1UL<<(16+(c&0xf)));
1044
 
    }
1045
 
 
1046
 
    return TRUE;
1047
 
}
1048
 
 
1049
 
static int
1050
 
compareFallbacks(const void *fb1, const void *fb2) {
1051
 
    return ((const _MBCSToUFallback *)fb1)->offset-((const _MBCSToUFallback *)fb2)->offset;
1052
 
}
1053
 
 
1054
 
/*
1055
 
 * This function tries to compact toUnicode tables for 2-byte codepages
1056
 
 * by finding lead bytes with all-unassigned trail bytes and adding another state
1057
 
 * for them.
1058
 
 */
1059
 
static void
1060
 
compactToUnicode2(MBCSData *mbcsData) {
1061
 
    int32_t (*oldStateTable)[256];
1062
 
    uint16_t count[256];
1063
 
    uint16_t *oldUnicodeCodeUnits;
1064
 
    int32_t entry, offset, oldOffset, trailOffset, oldTrailOffset, savings, sum;
1065
 
    int32_t i, j, leadState, trailState, newState, fallback;
1066
 
    uint16_t unit;
1067
 
 
1068
 
    /* find the lead state */
1069
 
    if((mbcsData->header.flags&0xff)==MBCS_OUTPUT_2_SISO) {
1070
 
        /* use the DBCS lead state for SI/SO codepages */
1071
 
        leadState=1;
1072
 
    } else {
1073
 
        leadState=0;
1074
 
    }
1075
 
 
1076
 
    /* find the main trail state: the most used target state */
1077
 
    uprv_memset(count, 0, sizeof(count));
1078
 
    for(i=0; i<256; ++i) {
1079
 
        entry=mbcsData->stateTable[leadState][i];
1080
 
        if(MBCS_ENTRY_IS_TRANSITION(entry)) {
1081
 
            ++count[MBCS_ENTRY_TRANSITION_STATE(entry)];
1082
 
        }
1083
 
    }
1084
 
    trailState=0;
1085
 
    for(i=1; i<(int)mbcsData->header.countStates; ++i) {
1086
 
        if(count[i]>count[trailState]) {
1087
 
            trailState=i;
1088
 
        }
1089
 
    }
1090
 
 
1091
 
    /* count possible savings from lead bytes with all-unassigned results in all trail bytes */
1092
 
    uprv_memset(count, 0, sizeof(count));
1093
 
    savings=0;
1094
 
    /* for each lead byte */
1095
 
    for(i=0; i<256; ++i) {
1096
 
        entry=mbcsData->stateTable[leadState][i];
1097
 
        if(MBCS_ENTRY_IS_TRANSITION(entry) && (MBCS_ENTRY_TRANSITION_STATE(entry))==trailState) {
1098
 
            /* the offset is different for each lead byte */
1099
 
            offset=MBCS_ENTRY_TRANSITION_OFFSET(entry);
1100
 
            /* for each trail byte for this lead byte */
1101
 
            for(j=0; j<256; ++j) {
1102
 
                entry=mbcsData->stateTable[trailState][j];
1103
 
                switch(MBCS_ENTRY_FINAL_ACTION(entry)) {
1104
 
                case MBCS_STATE_VALID_16:
1105
 
                    entry=offset+MBCS_ENTRY_FINAL_VALUE_16(entry);
1106
 
                    if(mbcsData->unicodeCodeUnits[entry]==0xfffe && findFallback(mbcsData, entry)<0) {
1107
 
                        ++count[i];
1108
 
                    } else {
1109
 
                        j=999; /* do not count for this lead byte because there are assignments */
1110
 
                    }
1111
 
                    break;
1112
 
                case MBCS_STATE_VALID_16_PAIR:
1113
 
                    entry=offset+MBCS_ENTRY_FINAL_VALUE_16(entry);
1114
 
                    if(mbcsData->unicodeCodeUnits[entry]==0xfffe) {
1115
 
                        count[i]+=2;
1116
 
                    } else {
1117
 
                        j=999; /* do not count for this lead byte because there are assignments */
1118
 
                    }
1119
 
                    break;
1120
 
                default:
1121
 
                    break;
1122
 
                }
1123
 
            }
1124
 
            if(j==256) {
1125
 
                /* all trail bytes for this lead byte are unassigned */
1126
 
                savings+=count[i];
1127
 
            } else {
1128
 
                count[i]=0;
1129
 
            }
1130
 
        }
1131
 
    }
1132
 
    /* subtract from the possible savings the cost of an additional state */
1133
 
    savings=savings*2-1024; /* count bytes, not 16-bit words */
1134
 
    if(savings<=0) {
1135
 
        return;
1136
 
    }
1137
 
    if(VERBOSE) {
1138
 
        printf("compacting toUnicode data saves %ld bytes\n", (long)savings);
1139
 
    }
1140
 
    if(mbcsData->header.countStates>=MBCS_MAX_STATE_COUNT) {
1141
 
        fprintf(stderr, "cannot compact toUnicode because the maximum number of states is reached\n");
1142
 
        return;
1143
 
    }
1144
 
 
1145
 
    /* make a copy of the state table */
1146
 
    oldStateTable=(int32_t (*)[256])uprv_malloc(mbcsData->header.countStates*1024);
1147
 
    if(oldStateTable==NULL) {
1148
 
        fprintf(stderr, "cannot compact toUnicode: out of memory\n");
1149
 
        return;
1150
 
    }
1151
 
    uprv_memcpy(oldStateTable, mbcsData->stateTable, mbcsData->header.countStates*1024);
1152
 
 
1153
 
    /* add the new state */
1154
 
    /*
1155
 
     * this function does not catch the degenerate case where all lead bytes
1156
 
     * have all-unassigned trail bytes and the lead state could be removed
1157
 
     */
1158
 
    newState=mbcsData->header.countStates++;
1159
 
    mbcsData->stateFlags[newState]=0;
1160
 
    /* copy the old trail state, turning all assigned states into unassigned ones */
1161
 
    for(i=0; i<256; ++i) {
1162
 
        entry=mbcsData->stateTable[trailState][i];
1163
 
        switch(MBCS_ENTRY_FINAL_ACTION(entry)) {
1164
 
        case MBCS_STATE_VALID_16:
1165
 
        case MBCS_STATE_VALID_16_PAIR:
1166
 
            mbcsData->stateTable[newState][i]=MBCS_ENTRY_FINAL_SET_ACTION_VALUE(entry, MBCS_STATE_UNASSIGNED, 0xfffe);
1167
 
            break;
1168
 
        default:
1169
 
            mbcsData->stateTable[newState][i]=entry;
1170
 
            break;
1171
 
        }
1172
 
    }
1173
 
 
1174
 
    /* in the lead state, redirect all lead bytes with all-unassigned trail bytes to the new state */
1175
 
    for(i=0; i<256; ++i) {
1176
 
        if(count[i]>0) {
1177
 
            mbcsData->stateTable[leadState][i]=MBCS_ENTRY_SET_STATE(mbcsData->stateTable[leadState][i], newState);
1178
 
        }
1179
 
    }
1180
 
 
1181
 
    /* sum up the new state table */
1182
 
    for(i=0; i<(int)mbcsData->header.countStates; ++i) {
1183
 
        mbcsData->stateFlags[i]&=~MBCS_STATE_FLAG_READY;
1184
 
    }
1185
 
    sum=sumUpStates(mbcsData);
1186
 
 
1187
 
    /* allocate a new, smaller code units array */
1188
 
    oldUnicodeCodeUnits=mbcsData->unicodeCodeUnits;
1189
 
    if(sum==0) {
1190
 
        mbcsData->unicodeCodeUnits=NULL;
1191
 
        if(oldUnicodeCodeUnits!=NULL) {
1192
 
            uprv_free(oldUnicodeCodeUnits);
1193
 
        }
1194
 
        uprv_free(oldStateTable);
1195
 
        return;
1196
 
    }
1197
 
    mbcsData->unicodeCodeUnits=(uint16_t *)uprv_malloc(sum*sizeof(uint16_t));
1198
 
    if(mbcsData->unicodeCodeUnits==NULL) {
1199
 
        fprintf(stderr, "cannot compact toUnicode: out of memory allocating %ld 16-bit code units\n",
1200
 
            (long)sum);
1201
 
        /* revert to the old state table */
1202
 
        mbcsData->unicodeCodeUnits=oldUnicodeCodeUnits;
1203
 
        --mbcsData->header.countStates;
1204
 
        uprv_memcpy(mbcsData->stateTable, oldStateTable, mbcsData->header.countStates*1024);
1205
 
        uprv_free(oldStateTable);
1206
 
        return;
1207
 
    }
1208
 
    for(i=0; i<sum; ++i) {
1209
 
        mbcsData->unicodeCodeUnits[i]=0xfffe;
1210
 
    }
1211
 
 
1212
 
    /* copy the code units for all assigned characters */
1213
 
    /*
1214
 
     * The old state table has the same lead _and_ trail states for assigned characters!
1215
 
     * The differences are in the offsets, and in the trail states for some unassigned characters.
1216
 
     * For each character with an assigned state in the new table, it was assigned in the old one.
1217
 
     * Only still-assigned characters are copied.
1218
 
     * Note that fallback mappings need to get their offset values adjusted.
1219
 
     */
1220
 
 
1221
 
    /* for each initial state */
1222
 
    for(leadState=0; leadState<(int)mbcsData->header.countStates; ++leadState) {
1223
 
        if((mbcsData->stateFlags[leadState]&0xf)==MBCS_STATE_FLAG_DIRECT) {
1224
 
            /* for each lead byte from there */
1225
 
            for(i=0; i<256; ++i) {
1226
 
                entry=mbcsData->stateTable[leadState][i];
1227
 
                if(MBCS_ENTRY_IS_TRANSITION(entry)) {
1228
 
                    trailState=(uint8_t)MBCS_ENTRY_TRANSITION_STATE(entry);
1229
 
                    /* the new state does not have assigned states */
1230
 
                    if(trailState!=newState) {
1231
 
                        trailOffset=MBCS_ENTRY_TRANSITION_OFFSET(entry);
1232
 
                        oldTrailOffset=MBCS_ENTRY_TRANSITION_OFFSET(oldStateTable[leadState][i]);
1233
 
                        /* for each trail byte */
1234
 
                        for(j=0; j<256; ++j) {
1235
 
                            entry=mbcsData->stateTable[trailState][j];
1236
 
                            /* copy assigned-character code units and adjust fallback offsets */
1237
 
                            switch(MBCS_ENTRY_FINAL_ACTION(entry)) {
1238
 
                            case MBCS_STATE_VALID_16:
1239
 
                                offset=trailOffset+MBCS_ENTRY_FINAL_VALUE_16(entry);
1240
 
                                /* find the old offset according to the old state table */
1241
 
                                oldOffset=oldTrailOffset+MBCS_ENTRY_FINAL_VALUE_16(oldStateTable[trailState][j]);
1242
 
                                unit=mbcsData->unicodeCodeUnits[offset]=oldUnicodeCodeUnits[oldOffset];
1243
 
                                if(unit==0xfffe && (fallback=findFallback(mbcsData, oldOffset))>=0) {
1244
 
                                    mbcsData->toUFallbacks[fallback].offset=0x80000000|offset;
1245
 
                                }
1246
 
                                break;
1247
 
                            case MBCS_STATE_VALID_16_PAIR:
1248
 
                                offset=trailOffset+MBCS_ENTRY_FINAL_VALUE_16(entry);
1249
 
                                /* find the old offset according to the old state table */
1250
 
                                oldOffset=oldTrailOffset+MBCS_ENTRY_FINAL_VALUE_16(oldStateTable[trailState][j]);
1251
 
                                mbcsData->unicodeCodeUnits[offset++]=oldUnicodeCodeUnits[oldOffset++];
1252
 
                                mbcsData->unicodeCodeUnits[offset]=oldUnicodeCodeUnits[oldOffset];
1253
 
                                break;
1254
 
                            default:
1255
 
                                break;
1256
 
                            }
1257
 
                        }
1258
 
                    }
1259
 
                }
1260
 
            }
1261
 
        }
1262
 
    }
1263
 
 
1264
 
    /* remove temporary flags from fallback offsets that protected them from being modified twice */
1265
 
    sum=mbcsData->header.countToUFallbacks;
1266
 
    for(i=0; i<sum; ++i) {
1267
 
        mbcsData->toUFallbacks[i].offset&=0x7fffffff;
1268
 
    }
1269
 
 
1270
 
    /* free temporary memory */
1271
 
    uprv_free(oldUnicodeCodeUnits);
1272
 
    uprv_free(oldStateTable);
1273
 
}
1274
 
 
1275
 
/*
1276
 
 * recursive sub-function of compactToUnicodeHelper()
1277
 
 * returns:
1278
 
 * >0 number of bytes that are used in unicodeCodeUnits[] that could be saved,
1279
 
 *    if all sequences from this state are unassigned, returns the
1280
 
 * <0 there are assignments in unicodeCodeUnits[]
1281
 
 * 0  no use of unicodeCodeUnits[]
1282
 
 */
1283
 
static int32_t
1284
 
findUnassigned(MBCSData *mbcsData, int32_t state, int32_t offset, uint32_t b) {
1285
 
    int32_t i, entry, savings, localSavings, belowSavings;
1286
 
    UBool haveAssigned;
1287
 
 
1288
 
    localSavings=belowSavings=0;
1289
 
    haveAssigned=FALSE;
1290
 
    for(i=0; i<256; ++i) {
1291
 
        entry=mbcsData->stateTable[state][i];
1292
 
        if(MBCS_ENTRY_IS_TRANSITION(entry)) {
1293
 
            savings=findUnassigned(mbcsData, MBCS_ENTRY_TRANSITION_STATE(entry), offset+MBCS_ENTRY_TRANSITION_OFFSET(entry), (b<<8)|(uint32_t)i);
1294
 
            if(savings<0) {
1295
 
                haveAssigned=TRUE;
1296
 
            } else if(savings>0) {
1297
 
                printf("    all-unassigned sequences from prefix 0x%02lx state %ld use %ld bytes\n",
1298
 
                    (unsigned long)((b<<8)|i), (long)state, (long)savings);
1299
 
                belowSavings+=savings;
1300
 
            }
1301
 
        } else if(!haveAssigned) {
1302
 
            switch(MBCS_ENTRY_FINAL_ACTION(entry)) {
1303
 
            case MBCS_STATE_VALID_16:
1304
 
                entry=offset+MBCS_ENTRY_FINAL_VALUE_16(entry);
1305
 
                if(mbcsData->unicodeCodeUnits[entry]==0xfffe && findFallback(mbcsData, entry)<0) {
1306
 
                    localSavings+=2;
1307
 
                } else {
1308
 
                    haveAssigned=TRUE;
1309
 
                }
1310
 
                break;
1311
 
            case MBCS_STATE_VALID_16_PAIR:
1312
 
                entry=offset+MBCS_ENTRY_FINAL_VALUE_16(entry);
1313
 
                if(mbcsData->unicodeCodeUnits[entry]==0xfffe) {
1314
 
                    localSavings+=4;
1315
 
                } else {
1316
 
                    haveAssigned=TRUE;
1317
 
                }
1318
 
                break;
1319
 
            default:
1320
 
                break;
1321
 
            }
1322
 
        }
1323
 
    }
1324
 
    if(haveAssigned) {
1325
 
        return -1;
1326
 
    } else {
1327
 
        return localSavings+belowSavings;
1328
 
    }
1329
 
}
1330
 
 
1331
 
/* helper function for finding compaction opportunities */
1332
 
static void
1333
 
compactToUnicodeHelper(MBCSData *mbcsData) {
1334
 
    int32_t state, savings;
1335
 
 
1336
 
    if(!VERBOSE) {
1337
 
        return;
1338
 
    }
1339
 
 
1340
 
    /* for each initial state */
1341
 
    for(state=0; state<(int)mbcsData->header.countStates; ++state) {
1342
 
        if((mbcsData->stateFlags[state]&0xf)==MBCS_STATE_FLAG_DIRECT) {
1343
 
            savings=findUnassigned(mbcsData, state, 0, 0);
1344
 
            if(savings>0) {
1345
 
                printf("    all-unassigned sequences from initial state %ld use %ld bytes\n",
1346
 
                    (long)state, (long)savings);
1347
 
            }
1348
 
        }
1349
 
    }
1350
 
}
1351
 
 
1352
 
static UBool
1353
 
transformEUC(MBCSData *mbcsData) {
1354
 
    uint8_t *p8;
1355
 
    uint32_t i, value, oldLength=mbcsData->maxCharLength, old3Top=mbcsData->stage3Top, new3Top;
1356
 
    uint8_t b;
1357
 
 
1358
 
    if(oldLength<3) {
1359
 
        return FALSE;
1360
 
    }
1361
 
 
1362
 
    /* careful: 2-byte and 4-byte codes are stored in platform endianness! */
1363
 
 
1364
 
    /* test if all first bytes are in {0, 0x8e, 0x8f} */
1365
 
    p8=mbcsData->fromUBytes;
1366
 
 
1367
 
#if !U_IS_BIG_ENDIAN
1368
 
    if(oldLength==4) {
1369
 
        p8+=3;
1370
 
    }
1371
 
#endif
1372
 
 
1373
 
    for(i=0; i<old3Top; i+=oldLength) {
1374
 
        b=p8[i];
1375
 
        if(b!=0 && b!=0x8e && b!=0x8f) {
1376
 
            /* some first byte does not fit the EUC pattern, nothing to be done */
1377
 
            return FALSE;
1378
 
        }
1379
 
    }
1380
 
    /* restore p if it was modified above */
1381
 
    p8=mbcsData->fromUBytes;
1382
 
 
1383
 
    /* modify outputType and adjust stage3Top */
1384
 
    mbcsData->header.flags=MBCS_OUTPUT_3_EUC+oldLength-3;
1385
 
    mbcsData->stage3Top=new3Top=(old3Top*(oldLength-1))/oldLength;
1386
 
 
1387
 
    /*
1388
 
     * EUC-encode all byte sequences;
1389
 
     * see "CJKV Information Processing" (1st ed. 1999) from Ken Lunde, O'Reilly,
1390
 
     * p. 161 in chapter 4 "Encoding Methods"
1391
 
     *
1392
 
     * This also must reverse the byte order if the platform is little-endian!
1393
 
     */
1394
 
    if(oldLength==3) {
1395
 
        uint16_t *q=(uint16_t *)p8;
1396
 
        for(i=0; i<old3Top; i+=oldLength) {
1397
 
            b=*p8;
1398
 
            if(b==0) {
1399
 
                /* short sequences are stored directly */
1400
 
                /* code set 0 or 1 */
1401
 
                (*q++)=(uint16_t)((p8[1]<<8)|p8[2]);
1402
 
            } else if(b==0x8e) {
1403
 
                /* code set 2 */
1404
 
                (*q++)=(uint16_t)(((p8[1]&0x7f)<<8)|p8[2]);
1405
 
            } else /* b==0x8f */ {
1406
 
                /* code set 3 */
1407
 
                (*q++)=(uint16_t)((p8[1]<<8)|(p8[2]&0x7f));
1408
 
            }
1409
 
            p8+=3;
1410
 
        }
1411
 
    } else /* oldLength==4 */ {
1412
 
        uint8_t *q=p8;
1413
 
        uint32_t *p32=(uint32_t *)p8;
1414
 
        for(i=0; i<old3Top; i+=4) {
1415
 
            value=(*p32++);
1416
 
            if(value<=0xffffff) {
1417
 
                /* short sequences are stored directly */
1418
 
                /* code set 0 or 1 */
1419
 
                (*q++)=(uint8_t)(value>>16);
1420
 
                (*q++)=(uint8_t)(value>>8);
1421
 
                (*q++)=(uint8_t)value;
1422
 
            } else if(value<=0x8effffff) {
1423
 
                /* code set 2 */
1424
 
                (*q++)=(uint8_t)((value>>16)&0x7f);
1425
 
                (*q++)=(uint8_t)(value>>8);
1426
 
                (*q++)=(uint8_t)value;
1427
 
            } else /* first byte is 0x8f */ {
1428
 
                /* code set 3 */
1429
 
                (*q++)=(uint8_t)(value>>16);
1430
 
                (*q++)=(uint8_t)((value>>8)&0x7f);
1431
 
                (*q++)=(uint8_t)value;
1432
 
            }
1433
 
        }
1434
 
    }
1435
 
 
1436
 
    return TRUE;
1437
 
}
1438
 
 
1439
 
/*
1440
 
 * Compact stage 2 for SBCS by overlapping adjacent stage 2 blocks as far
1441
 
 * as possible. Overlapping is done on unassigned head and tail
1442
 
 * parts of blocks in steps of MBCS_STAGE_2_MULTIPLIER.
1443
 
 * Stage 1 indexes need to be adjusted accordingly.
1444
 
 * This function is very similar to genprops/store.c/compactStage().
1445
 
 */
1446
 
static void
1447
 
singleCompactStage2(MBCSData *mbcsData) {
1448
 
    /* this array maps the ordinal number of a stage 2 block to its new stage 1 index */
1449
 
    uint16_t map[MBCS_STAGE_2_MAX_BLOCKS];
1450
 
    uint16_t i, start, prevEnd, newStart;
1451
 
 
1452
 
    /* enter the all-unassigned first stage 2 block into the map */
1453
 
    map[0]=MBCS_STAGE_2_ALL_UNASSIGNED_INDEX;
1454
 
 
1455
 
    /* begin with the first block after the all-unassigned one */
1456
 
    start=newStart=MBCS_STAGE_2_FIRST_ASSIGNED;
1457
 
    while(start<mbcsData->stage2Top) {
1458
 
        prevEnd=(uint16_t)(newStart-1);
1459
 
 
1460
 
        /* find the size of the overlap */
1461
 
        for(i=0; i<MBCS_STAGE_2_BLOCK_SIZE && mbcsData->stage2Single[start+i]==0 && mbcsData->stage2Single[prevEnd-i]==0; ++i) {}
1462
 
 
1463
 
        if(i>0) {
1464
 
            map[start>>MBCS_STAGE_2_BLOCK_SIZE_SHIFT]=(uint16_t)(newStart-i);
1465
 
 
1466
 
            /* move the non-overlapping indexes to their new positions */
1467
 
            start+=i;
1468
 
            for(i=(uint16_t)(MBCS_STAGE_2_BLOCK_SIZE-i); i>0; --i) {
1469
 
                mbcsData->stage2Single[newStart++]=mbcsData->stage2Single[start++];
1470
 
            }
1471
 
        } else if(newStart<start) {
1472
 
            /* move the indexes to their new positions */
1473
 
            map[start>>MBCS_STAGE_2_BLOCK_SIZE_SHIFT]=newStart;
1474
 
            for(i=MBCS_STAGE_2_BLOCK_SIZE; i>0; --i) {
1475
 
                mbcsData->stage2Single[newStart++]=mbcsData->stage2Single[start++];
1476
 
            }
1477
 
        } else /* no overlap && newStart==start */ {
1478
 
            map[start>>MBCS_STAGE_2_BLOCK_SIZE_SHIFT]=start;
1479
 
            start=newStart+=MBCS_STAGE_2_BLOCK_SIZE;
1480
 
        }
1481
 
    }
1482
 
 
1483
 
    /* adjust stage2Top */
1484
 
    if(VERBOSE && newStart<mbcsData->stage2Top) {
1485
 
        printf("compacting stage 2 from stage2Top=0x%lx to 0x%lx, saving %ld bytes\n",
1486
 
                (unsigned long)mbcsData->stage2Top, (unsigned long)newStart,
1487
 
                (long)(mbcsData->stage2Top-newStart)*2);
1488
 
    }
1489
 
    mbcsData->stage2Top=newStart;
1490
 
 
1491
 
    /* now adjust stage 1 */
1492
 
    for(i=0; i<MBCS_STAGE_1_SIZE; ++i) {
1493
 
        mbcsData->stage1[i]=map[mbcsData->stage1[i]>>MBCS_STAGE_2_BLOCK_SIZE_SHIFT];
1494
 
    }
1495
 
}
1496
 
 
1497
 
/* Compact stage 3 for SBCS - same algorithm as above. */
1498
 
static void
1499
 
singleCompactStage3(MBCSData *mbcsData) {
1500
 
    uint16_t *stage3=(uint16_t *)mbcsData->fromUBytes;
1501
 
 
1502
 
    /* this array maps the ordinal number of a stage 3 block to its new stage 2 index */
1503
 
    uint16_t map[0x1000];
1504
 
    uint16_t i, start, prevEnd, newStart;
1505
 
 
1506
 
    /* enter the all-unassigned first stage 3 block into the map */
1507
 
    map[0]=0;
1508
 
 
1509
 
    /* begin with the first block after the all-unassigned one */
1510
 
    start=newStart=16;
1511
 
    while(start<mbcsData->stage3Top) {
1512
 
        prevEnd=(uint16_t)(newStart-1);
1513
 
 
1514
 
        /* find the size of the overlap */
1515
 
        for(i=0; i<16 && stage3[start+i]==0 && stage3[prevEnd-i]==0; ++i) {}
1516
 
 
1517
 
        if(i>0) {
1518
 
            map[start>>4]=(uint16_t)(newStart-i);
1519
 
 
1520
 
            /* move the non-overlapping indexes to their new positions */
1521
 
            start+=i;
1522
 
            for(i=(uint16_t)(16-i); i>0; --i) {
1523
 
                stage3[newStart++]=stage3[start++];
1524
 
            }
1525
 
        } else if(newStart<start) {
1526
 
            /* move the indexes to their new positions */
1527
 
            map[start>>4]=newStart;
1528
 
            for(i=16; i>0; --i) {
1529
 
                stage3[newStart++]=stage3[start++];
1530
 
            }
1531
 
        } else /* no overlap && newStart==start */ {
1532
 
            map[start>>4]=start;
1533
 
            start=newStart+=16;
1534
 
        }
1535
 
    }
1536
 
 
1537
 
    /* adjust stage3Top */
1538
 
    if(VERBOSE && newStart<mbcsData->stage3Top) {
1539
 
        printf("compacting stage 3 from stage3Top=0x%lx to 0x%lx, saving %ld bytes\n",
1540
 
                (unsigned long)mbcsData->stage3Top, (unsigned long)newStart,
1541
 
                (long)(mbcsData->stage3Top-newStart)*2);
1542
 
    }
1543
 
    mbcsData->stage3Top=newStart;
1544
 
 
1545
 
    /* now adjust stage 2 */
1546
 
    for(i=0; i<mbcsData->stage2Top; ++i) {
1547
 
        mbcsData->stage2Single[i]=map[mbcsData->stage2Single[i]>>4];
1548
 
    }
1549
 
}
1550
 
 
1551
 
/*
1552
 
 * Compact stage 2 by overlapping adjacent stage 2 blocks as far
1553
 
 * as possible. Overlapping is done on unassigned head and tail
1554
 
 * parts of blocks in steps of MBCS_STAGE_2_MULTIPLIER.
1555
 
 * Stage 1 indexes need to be adjusted accordingly.
1556
 
 * This function is very similar to genprops/store.c/compactStage().
1557
 
 */
1558
 
static void
1559
 
compactStage2(MBCSData *mbcsData) {
1560
 
    /* this array maps the ordinal number of a stage 2 block to its new stage 1 index */
1561
 
    uint16_t map[MBCS_STAGE_2_MAX_BLOCKS];
1562
 
    uint16_t i, start, prevEnd, newStart;
1563
 
 
1564
 
    /* enter the all-unassigned first stage 2 block into the map */
1565
 
    map[0]=MBCS_STAGE_2_ALL_UNASSIGNED_INDEX;
1566
 
 
1567
 
    /* begin with the first block after the all-unassigned one */
1568
 
    start=newStart=MBCS_STAGE_2_FIRST_ASSIGNED;
1569
 
    while(start<mbcsData->stage2Top) {
1570
 
        prevEnd=(uint16_t)(newStart-1);
1571
 
 
1572
 
        /* find the size of the overlap */
1573
 
        for(i=0; i<MBCS_STAGE_2_BLOCK_SIZE && mbcsData->stage2[start+i]==0 && mbcsData->stage2[prevEnd-i]==0; ++i) {}
1574
 
 
1575
 
        if(i>0) {
1576
 
            map[start>>MBCS_STAGE_2_BLOCK_SIZE_SHIFT]=(uint16_t)(newStart-i);
1577
 
 
1578
 
            /* move the non-overlapping indexes to their new positions */
1579
 
            start+=i;
1580
 
            for(i=(uint16_t)(MBCS_STAGE_2_BLOCK_SIZE-i); i>0; --i) {
1581
 
                mbcsData->stage2[newStart++]=mbcsData->stage2[start++];
1582
 
            }
1583
 
        } else if(newStart<start) {
1584
 
            /* move the indexes to their new positions */
1585
 
            map[start>>MBCS_STAGE_2_BLOCK_SIZE_SHIFT]=newStart;
1586
 
            for(i=MBCS_STAGE_2_BLOCK_SIZE; i>0; --i) {
1587
 
                mbcsData->stage2[newStart++]=mbcsData->stage2[start++];
1588
 
            }
1589
 
        } else /* no overlap && newStart==start */ {
1590
 
            map[start>>MBCS_STAGE_2_BLOCK_SIZE_SHIFT]=start;
1591
 
            start=newStart+=MBCS_STAGE_2_BLOCK_SIZE;
1592
 
        }
1593
 
    }
1594
 
 
1595
 
    /* adjust stage2Top */
1596
 
    if(VERBOSE && newStart<mbcsData->stage2Top) {
1597
 
        printf("compacting stage 2 from stage2Top=0x%lx to 0x%lx, saving %ld bytes\n",
1598
 
                (unsigned long)mbcsData->stage2Top, (unsigned long)newStart,
1599
 
                (long)(mbcsData->stage2Top-newStart)*4);
1600
 
    }
1601
 
    mbcsData->stage2Top=newStart;
1602
 
 
1603
 
    /* now adjust stage 1 */
1604
 
    for(i=0; i<MBCS_STAGE_1_SIZE; ++i) {
1605
 
        mbcsData->stage1[i]=map[mbcsData->stage1[i]>>MBCS_STAGE_2_BLOCK_SIZE_SHIFT];
1606
 
    }
1607
 
}
1608
 
 
1609
 
static void
1610
 
MBCSPostprocess(NewConverter *cnvData, const UConverterStaticData *staticData) {
1611
 
    MBCSData *mbcsData=(MBCSData *)cnvData;
1612
 
    int32_t entry;
1613
 
    int state, cell;
1614
 
 
1615
 
    /* this needs to be printed before the EUC transformation because later maxCharLength might not be correct */
1616
 
    if(VERBOSE) {
1617
 
        printf("number of codepage characters in 16-blocks: 0x%lx=%lu\n",
1618
 
               (unsigned long)mbcsData->stage3Top/mbcsData->maxCharLength,
1619
 
               (unsigned long)mbcsData->stage3Top/mbcsData->maxCharLength);
1620
 
    }
1621
 
 
1622
 
    /* test each state table entry */
1623
 
    for(state=0; state<(int)mbcsData->header.countStates; ++state) {
1624
 
        for(cell=0; cell<256; ++cell) {
1625
 
            entry=mbcsData->stateTable[state][cell];
1626
 
            /*
1627
 
             * if the entry is a final one with an MBCS_STATE_VALID_DIRECT_16 action code
1628
 
             * and the code point is "unassigned" (0xfffe), then change it to
1629
 
             * the "unassigned" action code with bits 26..23 set to zero and U+fffe.
1630
 
             */
1631
 
            if(MBCS_ENTRY_SET_STATE(entry, 0)==MBCS_ENTRY_FINAL(0, MBCS_STATE_VALID_DIRECT_16, 0xfffe)) {
1632
 
                mbcsData->stateTable[state][cell]=MBCS_ENTRY_FINAL_SET_ACTION(entry, MBCS_STATE_UNASSIGNED);
1633
 
            }
1634
 
        }
1635
 
    }
1636
 
 
1637
 
    /* try to compact the toUnicode tables */
1638
 
    if(mbcsData->maxCharLength==2) {
1639
 
        compactToUnicode2(mbcsData);
1640
 
    } else if(mbcsData->maxCharLength>2) {
1641
 
        compactToUnicodeHelper(mbcsData);
1642
 
    }
1643
 
 
1644
 
    /* sort toUFallbacks */
1645
 
    /*
1646
 
     * It should be safe to sort them before compactToUnicode2() is called,
1647
 
     * because it should not change the relative order of the offset values
1648
 
     * that it adjusts, but they need to be sorted at some point, and
1649
 
     * it is safest here.
1650
 
     */
1651
 
    if(mbcsData->header.countToUFallbacks>0) {
1652
 
        qsort(mbcsData->toUFallbacks, mbcsData->header.countToUFallbacks, sizeof(_MBCSToUFallback), compareFallbacks);
1653
 
    }
1654
 
 
1655
 
    /* try to compact the fromUnicode tables */
1656
 
    transformEUC(mbcsData);
1657
 
    if(mbcsData->maxCharLength==1) {
1658
 
        singleCompactStage3(mbcsData);
1659
 
        singleCompactStage2(mbcsData);
1660
 
    } else {
1661
 
        compactStage2(mbcsData);
1662
 
    }
1663
 
}
1664
 
 
1665
 
static uint32_t
1666
 
MBCSWrite(NewConverter *cnvData, const UConverterStaticData *staticData, UNewDataMemory *pData) {
1667
 
    MBCSData *mbcsData=(MBCSData *)cnvData;
1668
 
    int32_t i, stage1Top;
1669
 
 
1670
 
    /* adjust stage 1 entries to include the size of stage 1 in the offsets to stage 2 */
1671
 
    if(mbcsData->maxCharLength==1) {
1672
 
        if(staticData->unicodeMask&UCNV_HAS_SUPPLEMENTARY) {
1673
 
            stage1Top=MBCS_STAGE_1_SIZE; /* 0x440==1088 */
1674
 
        } else {
1675
 
            stage1Top=0x40; /* 0x40==64 */
1676
 
        }
1677
 
        for(i=0; i<stage1Top; ++i) {
1678
 
            mbcsData->stage1[i]+=(uint16_t)stage1Top;
1679
 
        }
1680
 
 
1681
 
        /* stage2Top has counted 16-bit results, now we need to count bytes */
1682
 
        mbcsData->stage2Top*=2;
1683
 
 
1684
 
        /* stage3Top has counted 16-bit results, now we need to count bytes */
1685
 
        mbcsData->stage3Top*=2;
1686
 
    } else {
1687
 
        if(staticData->unicodeMask&UCNV_HAS_SUPPLEMENTARY) {
1688
 
            stage1Top=MBCS_STAGE_1_SIZE; /* 0x440==1088 */
1689
 
        } else {
1690
 
            stage1Top=0x40; /* 0x40==64 */
1691
 
        }
1692
 
        for(i=0; i<stage1Top; ++i) {
1693
 
            mbcsData->stage1[i]+=(uint16_t)stage1Top/2; /* stage 2 contains 32-bit entries, stage 1 16-bit entries */
1694
 
        }
1695
 
 
1696
 
        /* stage2Top has counted 32-bit results, now we need to count bytes */
1697
 
        mbcsData->stage2Top*=4;
1698
 
 
1699
 
        /* stage3Top has already counted bytes */
1700
 
    }
1701
 
 
1702
 
    /* round up stage2Top and stage3Top so that the sizes of all data blocks are multiples of 4 */
1703
 
    mbcsData->stage2Top=(mbcsData->stage2Top+3)&~3;
1704
 
    mbcsData->stage3Top=(mbcsData->stage3Top+3)&~3;
1705
 
 
1706
 
    /* fill the header */
1707
 
    mbcsData->header.offsetToUCodeUnits=
1708
 
        sizeof(_MBCSHeader)+
1709
 
        mbcsData->header.countStates*1024+
1710
 
        mbcsData->header.countToUFallbacks*sizeof(_MBCSToUFallback);
1711
 
    mbcsData->header.offsetFromUTable=
1712
 
        mbcsData->header.offsetToUCodeUnits+
1713
 
        mbcsData->countToUCodeUnits*2;
1714
 
    mbcsData->header.offsetFromUBytes=
1715
 
        mbcsData->header.offsetFromUTable+
1716
 
        stage1Top*2+
1717
 
        mbcsData->stage2Top;
1718
 
 
1719
 
    /* write the MBCS data */
1720
 
    udata_writeBlock(pData, &mbcsData->header, sizeof(_MBCSHeader));
1721
 
    udata_writeBlock(pData, mbcsData->stateTable, mbcsData->header.countStates*1024);
1722
 
    udata_writeBlock(pData, mbcsData->toUFallbacks, mbcsData->header.countToUFallbacks*sizeof(_MBCSToUFallback));
1723
 
    udata_writeBlock(pData, mbcsData->unicodeCodeUnits, mbcsData->countToUCodeUnits*2);
1724
 
    udata_writeBlock(pData, mbcsData->stage1, stage1Top*2);
1725
 
    if(mbcsData->maxCharLength==1) {
1726
 
        udata_writeBlock(pData, mbcsData->stage2Single, mbcsData->stage2Top);
1727
 
    } else {
1728
 
        udata_writeBlock(pData, mbcsData->stage2, mbcsData->stage2Top);
1729
 
    }
1730
 
    udata_writeBlock(pData, mbcsData->fromUBytes, mbcsData->stage3Top);
1731
 
 
1732
 
    /* return the number of bytes that should have been written */
1733
 
    return mbcsData->header.offsetFromUBytes+mbcsData->stage3Top;
1734
 
}