~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ibmdb2i/db2i_myconv.h

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Licensed Materials - Property of IBM
 
3
DB2 Storage Engine Enablement
 
4
Copyright IBM Corporation 2007,2008
 
5
All rights reserved
 
6
 
 
7
Redistribution and use in source and binary forms, with or without modification,
 
8
are permitted provided that the following conditions are met: 
 
9
 (a) Redistributions of source code must retain this list of conditions, the
 
10
     copyright notice in section {d} below, and the disclaimer following this
 
11
     list of conditions. 
 
12
 (b) Redistributions in binary form must reproduce this list of conditions, the
 
13
     copyright notice in section (d) below, and the disclaimer following this
 
14
     list of conditions, in the documentation and/or other materials provided
 
15
     with the distribution. 
 
16
 (c) The name of IBM may not be used to endorse or promote products derived from
 
17
     this software without specific prior written permission. 
 
18
 (d) The text of the required copyright notice is: 
 
19
       Licensed Materials - Property of IBM
 
20
       DB2 Storage Engine Enablement 
 
21
       Copyright IBM Corporation 2007,2008 
 
22
       All rights reserved
 
23
 
 
24
THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
 
25
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
26
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 
27
SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
28
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 
29
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
30
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
31
CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 
32
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 
33
OF SUCH DAMAGE.
 
34
*/
 
35
 
 
36
/**
 
37
  @file
 
38
  
 
39
  @brief  A direct map optimization of iconv and related functions
 
40
          This was show to significantly reduce character conversion cost
 
41
          for short strings when compared to calling iconv system code.
 
42
*/
 
43
 
 
44
#ifndef DB2I_MYCONV_H
 
45
#define DB2I_MYCONV_H
 
46
 
 
47
 
 
48
#include <sys/time.h>
 
49
#include <stdlib.h>
 
50
#include <stdio.h>
 
51
#include <wchar.h>
 
52
#include <errno.h>
 
53
#include <iconv.h>
 
54
#include <ctype.h>
 
55
#include <time.h>
 
56
#include <stdarg.h>
 
57
#include <string.h>
 
58
 
 
59
#ifndef TRUE
 
60
#define TRUE    1
 
61
#endif
 
62
 
 
63
#ifndef FALSE
 
64
#define FALSE   0
 
65
#endif
 
66
 
 
67
#ifdef __cplusplus
 
68
#define INTERN  inline
 
69
#define EXTERN  extern "C"
 
70
#else
 
71
#define INTERN  static
 
72
#define EXTERN  extern
 
73
#endif
 
74
 
 
75
 
 
76
/* ANSI integer data types */
 
77
#if defined(__OS400_TGTVRM__)
 
78
/* for DTAMDL(*P128), datamodel(P128): int/long/pointer=4/4/16 */
 
79
/* LLP64:4/4/8 is used for teraspace ?? */
 
80
typedef short                   int16_t;
 
81
typedef unsigned short          uint16_t;
 
82
typedef int                     int32_t;
 
83
typedef unsigned int            uint32_t;
 
84
typedef long long               int64_t;
 
85
typedef unsigned long long      uint64_t;
 
86
#elif defined(PASE)
 
87
/* PASE uses IPL32: int/long/pointer=4/4/4 + long long */
 
88
#elif defined(__64BIT__)
 
89
/* AIX 64 bit uses LP64: int/long/pointer=4/8/8 */
 
90
#endif
 
91
 
 
92
#define CONVERTER_ICONV         1
 
93
#define CONVERTER_DMAP          2
 
94
 
 
95
#define DMAP_S2S                10
 
96
#define DMAP_S2U                20
 
97
#define DMAP_D2U                30
 
98
#define DMAP_E2U                40
 
99
#define DMAP_U2S                120
 
100
#define DMAP_T2S                125
 
101
#define DMAP_U2D                130
 
102
#define DMAP_T2D                135
 
103
#define DMAP_U2E                140
 
104
#define DMAP_T2E                145
 
105
#define DMAP_S28                220
 
106
#define DMAP_D28                230
 
107
#define DMAP_E28                240
 
108
#define DMAP_82S                310
 
109
#define DMAP_82D                320
 
110
#define DMAP_82E                330
 
111
#define DMAP_U28                410
 
112
#define DMAP_82U                420
 
113
#define DMAP_T28                425
 
114
#define DMAP_U2U                510
 
115
 
 
116
 
 
117
typedef struct __dmap_rec       *dmap_t;
 
118
 
 
119
struct __dmap_rec
 
120
{
 
121
  uint32_t              codingSchema;
 
122
  unsigned char *       dmapS2S;        /* SBCS -> SBCS                         */
 
123
  /* The following conversion needs be followed by conversion from UCS-2/UTF-16 to UTF-8   */
 
124
  UniChar *     dmapD12U;       /* DBCS(non-EUC) -> UCS-2/UTF-16        */
 
125
  UniChar *     dmapD22U;       /* DBCS(non-EUC) -> UCS-2/UTF-16        */
 
126
  UniChar *     dmapE02U;       /* EUC/SS0 -> UCS-2/UTF-16              */
 
127
  UniChar *     dmapE12U;       /* EUC/SS1 -> UCS-2/UTF-16              */
 
128
  UniChar *     dmapE22U;       /* EUC/0x8E + SS2 -> UCS-2/UTF-16       */
 
129
  UniChar *     dmapE32U;       /* EUC/0x8F + SS3 -> UCS-2/UTF-16       */
 
130
  uchar *       dmapU2D;        /* UCS-2 -> DBCS                        */
 
131
  uchar *       dmapU2S;        /* UCS-2 -> EUC SS0                     */
 
132
  uchar *       dmapU2M2;       /* UCS-2 -> EUC SS1                     */
 
133
  uchar *       dmapU2M3;       /* UCS-2 -> EUC SS2/SS3                 */
 
134
  /* All of these pointers/tables are not used at the same time.        
 
135
   * You may be able save some space if you consolidate them.
 
136
   */
 
137
  uchar *       dmapS28;        /* SBCS -> UTF-8                        */
 
138
  uchar *       dmapD28;        /* DBCS -> UTF-8                        */
 
139
};
 
140
 
 
141
typedef struct __myconv_rec     *myconv_t;
 
142
struct __myconv_rec
 
143
{
 
144
  uint32_t      converterType;
 
145
  uint32_t      index;          /* for close */
 
146
  union {
 
147
    iconv_t     cnv_iconv;
 
148
    dmap_t      cnv_dmap;
 
149
  };
 
150
  int32_t       allocatedSize;
 
151
  int32_t       fromCcsid;
 
152
  int32_t       toCcsid;
 
153
  UniChar       subD;           /* DBCS substitution char                       */
 
154
  char          subS;           /* SBCS substitution char                       */
 
155
  UniChar       srcSubD;        /* DBCS substitution char of src codepage       */
 
156
  char          srcSubS;        /* SBCS substitution char of src codepage       */
 
157
  char          from    [41+1]; /* codepage name is up to 41 bytes              */
 
158
  char          to      [41+1]; /* codepage name is up to 41 bytes              */
 
159
#ifdef __64BIT__
 
160
  char          reserved[10];   /* align 128 */
 
161
#else
 
162
  char          reserved[14];   /* align 128 */
 
163
#endif
 
164
};
 
165
 
 
166
 
 
167
EXTERN int32_t myconvDebug;
 
168
 
 
169
 
 
170
 
 
171
EXTERN  int     myconvGetES(CCSID);
 
172
EXTERN  int     myconvIsEBCDIC(const char *);
 
173
EXTERN  int     myconvIsASCII(const char *);
 
174
EXTERN  int     myconvIsUnicode(const char *);   /* UTF-8, UTF-16, or UCS-2 */
 
175
EXTERN  int     myconvIsUnicode2(const char *);  /* 2 byte Unicode */
 
176
EXTERN  int     myconvIsUCS2(const char *);
 
177
EXTERN  int     myconvIsUTF16(const char *);
 
178
EXTERN  int     myconvIsUTF8(const char *);
 
179
EXTERN  int     myconvIsEUC(const char *);
 
180
EXTERN  int     myconvIsISO(const char *);
 
181
EXTERN  int     myconvIsSBCS(const char *);
 
182
EXTERN  int     myconvIsDBCS(const char *);
 
183
EXTERN  char    myconvGetSubS(const char *);
 
184
EXTERN  UniChar myconvGetSubD(const char *);
 
185
 
 
186
 
 
187
EXTERN  myconv_t        myconv_open(const char*, const char*, int32_t);
 
188
EXTERN  int             myconv_close(myconv_t);
 
189
 
 
190
INTERN  size_t          myconv_iconv(myconv_t   cd ,
 
191
                                     char**     inBuf,
 
192
                                     size_t*    inBytesLeft,
 
193
                                     char**     outBuf,
 
194
                                     size_t*    outBytesLeft,
 
195
                                     size_t*    numSub)
 
196
{
 
197
  return iconv(cd->cnv_iconv, inBuf, inBytesLeft, outBuf, outBytesLeft);
 
198
}
 
199
 
 
200
INTERN  size_t          myconv_dmap(myconv_t    cd,
 
201
                                    char**      inBuf,
 
202
                                    size_t*     inBytesLeft,
 
203
                                    char**      outBuf,
 
204
                                    size_t*     outBytesLeft,
 
205
                                    size_t*     numSub)
 
206
{
 
207
  if (cd->cnv_dmap->codingSchema == DMAP_S2S) {
 
208
    register unsigned char *   dmapS2S=cd->cnv_dmap->dmapS2S;
 
209
    register int        inLen=*inBytesLeft;
 
210
    register char *     pOut=*outBuf;
 
211
    register char *     pIn=*inBuf;
 
212
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
213
    register char       subS=cd->subS;
 
214
    register size_t     numS=0;
 
215
    while (0 < inLen) {
 
216
      if (pLastOutBuf < pOut)
 
217
        break;
 
218
      if (*pIn == 0x00) {
 
219
        *pOut=0x00;
 
220
      } else {
 
221
        *pOut=dmapS2S[*pIn];
 
222
        if (*pOut == 0x00) {
 
223
          errno=EILSEQ;  /* 116 */
 
224
          *outBytesLeft-=(*inBytesLeft-inLen);
 
225
          *inBytesLeft=inLen;
 
226
          *outBuf=pOut;
 
227
          *inBuf=pIn;
 
228
          *numSub+=numS;
 
229
          return -1;
 
230
        }
 
231
        if (*pOut == subS) {
 
232
          if ((*pOut=dmapS2S[*pIn]) == subS) {
 
233
            if (*pIn != cd->srcSubS)
 
234
              ++numS;
 
235
          }
 
236
        }
 
237
      }
 
238
      ++pIn;
 
239
      --inLen;
 
240
      ++pOut;
 
241
    }
 
242
    *outBytesLeft-=(*inBytesLeft-inLen);
 
243
    *inBytesLeft=inLen;
 
244
    *outBuf=pOut;
 
245
    *inBuf=pIn;
 
246
    *numSub+=numS;
 
247
    return 0;
 
248
 
 
249
  } else if (cd->cnv_dmap->codingSchema == DMAP_E2U) {
 
250
    /* use uchar * instead of UniChar to avoid memcpy */
 
251
    register uchar *    dmapE02U=(uchar *) (cd->cnv_dmap->dmapE02U);
 
252
    register uchar *    dmapE12U=(uchar *) (cd->cnv_dmap->dmapE12U);
 
253
    register uchar *    dmapE22U=(uchar *) (cd->cnv_dmap->dmapE22U);
 
254
    register uchar *    dmapE32U=(uchar *) (cd->cnv_dmap->dmapE32U);
 
255
    register int        inLen=*inBytesLeft;
 
256
    register char *     pOut=*outBuf;
 
257
    register char *     pIn=*inBuf;
 
258
    register int        offset;
 
259
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
260
    register size_t     numS=0;
 
261
    while (0 < inLen) {
 
262
      if (pLastOutBuf < pOut)
 
263
        break;
 
264
      if (*pIn == 0x00) {
 
265
        *pOut=0x00;
 
266
        ++pOut;
 
267
        *pOut=0x00;
 
268
        ++pOut;
 
269
        ++pIn;
 
270
        --inLen;
 
271
      } else {
 
272
        if (*pIn == 0x8E) {      /* SS2 */
 
273
          if (inLen < 2) {
 
274
            if (cd->fromCcsid == 33722 ||       /* IBM-eucJP */
 
275
                cd->fromCcsid == 964)           /* IBM-eucTW */
 
276
              errno=EINVAL;  /* 22 */
 
277
            else
 
278
              errno=EILSEQ;  /* 116 */
 
279
            *outBytesLeft-=(pOut-*outBuf);
 
280
            *inBytesLeft=inLen;
 
281
            *outBuf=pOut;
 
282
            *inBuf=pIn;
 
283
            return -1;
 
284
          }
 
285
          ++pIn;
 
286
          if (*pIn < 0xA0) {
 
287
            if (cd->fromCcsid == 964)           /* IBM-eucTW */
 
288
              errno=EINVAL;  /* 22 */
 
289
            else
 
290
              errno=EILSEQ;  /* 116 */
 
291
            *outBytesLeft-=(pOut-*outBuf);
 
292
            *inBytesLeft=inLen;
 
293
            *outBuf=pOut;
 
294
            *inBuf=pIn-1;
 
295
            return -1;
 
296
          }
 
297
          offset=(*pIn - 0xA0);
 
298
          offset<<=1;
 
299
          if (dmapE22U[offset]   == 0x00 &&
 
300
              dmapE22U[offset+1] == 0x00) {     /* 2 bytes */
 
301
            if (inLen < 3) {
 
302
              if (cd->fromCcsid == 964)           /* IBM-eucTW */
 
303
                errno=EINVAL;  /* 22 */
 
304
              else
 
305
                errno=EILSEQ;  /* 116 */
 
306
              *outBytesLeft-=(pOut-*outBuf);
 
307
              *inBytesLeft=inLen;
 
308
              *outBuf=pOut;
 
309
              *inBuf=pIn-1;
 
310
              return -1;
 
311
            }
 
312
            offset=(*pIn - 0xA0) * 0x60 + 0x60;
 
313
            ++pIn;
 
314
            if (*pIn < 0xA0) {
 
315
              if (cd->fromCcsid == 964)           /* IBM-eucTW */
 
316
                errno=EINVAL;  /* 22 */
 
317
              else
 
318
                errno=EILSEQ;  /* 116 */
 
319
              *outBytesLeft-=(pOut-*outBuf);
 
320
              *inBytesLeft=inLen;
 
321
              *outBuf=pOut;
 
322
              *inBuf=pIn-2;
 
323
              return -1;
 
324
            }
 
325
            offset+=(*pIn - 0xA0);
 
326
            offset<<=1;
 
327
            if (dmapE22U[offset] == 0x00 &&
 
328
                dmapE22U[offset+1] == 0x00) {
 
329
              if (cd->fromCcsid == 964)           /* IBM-eucTW */
 
330
                errno=EINVAL;  /* 22 */
 
331
              else
 
332
                errno=EILSEQ;  /* 116 */
 
333
              *outBytesLeft-=(pOut-*outBuf);
 
334
              *inBytesLeft=inLen;
 
335
              *outBuf=pOut;
 
336
              *inBuf=pIn-2;
 
337
              return -1;
 
338
            }
 
339
            *pOut=dmapE22U[offset];
 
340
            ++pOut;
 
341
            *pOut=dmapE22U[offset+1];
 
342
            ++pOut;
 
343
            if (dmapE22U[offset] == 0xFF &&
 
344
                dmapE22U[offset+1] == 0xFD) {
 
345
              if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD)
 
346
                ++numS;
 
347
            }
 
348
            ++pIn;
 
349
            inLen-=3;
 
350
          } else {      /* 1 bytes */
 
351
            *pOut=dmapE22U[offset];
 
352
            ++pOut;
 
353
            *pOut=dmapE22U[offset+1];
 
354
            ++pOut;
 
355
            ++pIn;
 
356
            inLen-=2;
 
357
          }
 
358
        } else if (*pIn == 0x8F) {     /* SS3 */
 
359
          if (inLen < 2) {
 
360
            if (cd->fromCcsid == 33722)   /* IBM-eucJP */
 
361
              errno=EINVAL;  /* 22 */
 
362
            else
 
363
              errno=EILSEQ;  /* 116 */
 
364
            *outBytesLeft-=(pOut-*outBuf);
 
365
            *inBytesLeft=inLen;
 
366
            *outBuf=pOut;
 
367
            *inBuf=pIn;
 
368
            return -1;
 
369
          }
 
370
          ++pIn;
 
371
          if (*pIn < 0xA0) {
 
372
            if (cd->fromCcsid == 970 ||         /* IBM-eucKR */
 
373
                cd->fromCcsid == 964 ||         /* IBM-eucTW */
 
374
                cd->fromCcsid == 1383 ||        /* IBM-eucCN */
 
375
                (cd->fromCcsid == 33722 && 3 <= inLen)) /* IBM-eucJP */
 
376
              errno=EILSEQ;  /* 116 */
 
377
            else
 
378
              errno=EINVAL;  /* 22 */
 
379
            *outBytesLeft-=(pOut-*outBuf);
 
380
            *inBytesLeft=inLen;
 
381
            *outBuf=pOut;
 
382
            *inBuf=pIn-1;
 
383
            return -1;
 
384
          }
 
385
          offset=(*pIn - 0xA0);
 
386
          offset<<=1;
 
387
          if (dmapE32U[offset]   == 0x00 &&
 
388
              dmapE32U[offset+1] == 0x00) { /* 0x8F + 2 bytes */
 
389
            if (inLen < 3) {
 
390
              if (cd->fromCcsid == 33722)
 
391
                errno=EINVAL;  /* 22 */
 
392
              else
 
393
                errno=EILSEQ;  /* 116 */
 
394
              *outBytesLeft-=(pOut-*outBuf);
 
395
              *inBytesLeft=inLen;
 
396
              *outBuf=pOut;
 
397
              *inBuf=pIn-1;
 
398
              return -1;
 
399
            }
 
400
            offset=(*pIn - 0xA0) * 0x60 + 0x60;
 
401
            ++pIn;
 
402
            if (*pIn < 0xA0) {
 
403
              errno=EILSEQ;  /* 116 */
 
404
              *outBytesLeft-=(pOut-*outBuf);
 
405
              *inBytesLeft=inLen;
 
406
              *outBuf=pOut;
 
407
              *inBuf=pIn-2;
 
408
              return -1;
 
409
            }
 
410
            offset+=(*pIn - 0xA0);
 
411
            offset<<=1;
 
412
            if (dmapE32U[offset] == 0x00 &&
 
413
                dmapE32U[offset+1] == 0x00) {
 
414
              errno=EILSEQ;  /* 116 */
 
415
              *outBytesLeft-=(pOut-*outBuf);
 
416
              *inBytesLeft=inLen;
 
417
              *outBuf=pOut;
 
418
              *inBuf=pIn-2;
 
419
              return -1;
 
420
            }
 
421
            *pOut=dmapE32U[offset];
 
422
            ++pOut;
 
423
            *pOut=dmapE32U[offset+1];
 
424
            ++pOut;
 
425
            if (dmapE32U[offset] == 0xFF &&
 
426
                dmapE32U[offset+1] == 0xFD) {
 
427
              if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD)
 
428
                ++numS;
 
429
            }
 
430
            ++pIn;
 
431
            inLen-=3;
 
432
          } else {      /* 0x8F + 1 bytes */
 
433
            *pOut=dmapE32U[offset];
 
434
            ++pOut;
 
435
            *pOut=dmapE32U[offset+1];
 
436
            ++pOut;
 
437
            ++pIn;
 
438
            inLen-=2;
 
439
          }
 
440
 
 
441
        } else {
 
442
          offset=*pIn;
 
443
          offset<<=1;
 
444
          if (dmapE02U[offset]   == 0x00 &&
 
445
              dmapE02U[offset+1] == 0x00) {         /* SS1 */
 
446
            if (inLen < 2) {
 
447
              if ((cd->fromCcsid == 33722 && (*pIn == 0xA0 || (0xA9 <= *pIn && *pIn <= 0xAF) || *pIn == 0xFF)) ||
 
448
                  (cd->fromCcsid == 970 && (*pIn == 0xA0 || *pIn == 0xAD || *pIn == 0xAE || *pIn == 0xAF || *pIn == 0xFF)) ||
 
449
                  (cd->fromCcsid == 964 && (*pIn == 0xA0 || (0xAA <= *pIn && *pIn <= 0xC1) || *pIn == 0xC3 || *pIn == 0xFE || *pIn == 0xFF)) ||
 
450
                  (cd->fromCcsid == 1383 && (*pIn == 0xA0 || *pIn == 0xFF)))
 
451
                errno=EILSEQ;  /* 116 */
 
452
              else
 
453
                errno=EINVAL;  /* 22 */
 
454
              *outBytesLeft-=(pOut-*outBuf);
 
455
              *inBytesLeft=inLen;
 
456
              *outBuf=pOut;
 
457
              *inBuf=pIn;
 
458
              return -1;
 
459
            }
 
460
            if (*pIn < 0xA0) {
 
461
              errno=EILSEQ;  /* 116 */
 
462
              *outBytesLeft-=(pOut-*outBuf);
 
463
              *inBytesLeft=inLen;
 
464
              *outBuf=pOut;
 
465
              *inBuf=pIn;
 
466
              return -1;
 
467
            }
 
468
            offset=(*pIn - 0xA0) * 0x60;
 
469
            ++pIn;
 
470
            if (*pIn < 0xA0) {
 
471
              errno=EILSEQ;  /* 116 */
 
472
              *outBytesLeft-=(pOut-*outBuf);
 
473
              *inBytesLeft=inLen;
 
474
              *outBuf=pOut;
 
475
              *inBuf=pIn-1;
 
476
              return -1;
 
477
            }
 
478
            offset+=(*pIn - 0xA0);
 
479
            offset<<=1;
 
480
            if (dmapE12U[offset] == 0x00 &&
 
481
                dmapE12U[offset+1] == 0x00) {   /* undefined mapping */
 
482
              errno=EILSEQ;  /* 116 */
 
483
              *outBytesLeft-=(pOut-*outBuf);
 
484
              *inBytesLeft=inLen;
 
485
              *outBuf=pOut;
 
486
              *inBuf=pIn-1;
 
487
              return -1;
 
488
            }
 
489
            *pOut=dmapE12U[offset];
 
490
            ++pOut;
 
491
            *pOut=dmapE12U[offset+1];
 
492
            ++pOut;
 
493
            if (dmapE12U[offset] == 0xFF &&
 
494
                dmapE12U[offset+1] == 0xFD) {
 
495
              if (pIn[-1] * 0x100 + pIn[0] != cd->srcSubD)
 
496
                ++numS;
 
497
            }
 
498
            ++pIn;
 
499
            inLen-=2;
 
500
          } else {
 
501
            *pOut=dmapE02U[offset];
 
502
            ++pOut;
 
503
            *pOut=dmapE02U[offset+1];
 
504
            ++pOut;
 
505
            if (dmapE02U[offset] == 0x00 &&
 
506
                dmapE02U[offset+1] == 0x1A) {
 
507
              if (*pIn != cd->srcSubS)
 
508
                ++numS;
 
509
            }
 
510
            ++pIn;
 
511
            --inLen;
 
512
          }
 
513
        }
 
514
      }
 
515
    }
 
516
    *outBytesLeft-=(pOut-*outBuf);
 
517
    *inBytesLeft=inLen;
 
518
    *outBuf=pOut;
 
519
    *inBuf=pIn;
 
520
    *numSub+=numS;
 
521
    return 0;
 
522
 
 
523
 
 
524
  } else if (cd->cnv_dmap->codingSchema == DMAP_E28) {
 
525
    /* use uchar * instead of UniChar to avoid memcpy */
 
526
    register uchar *    dmapE02U=(uchar *) (cd->cnv_dmap->dmapE02U);
 
527
    register uchar *    dmapE12U=(uchar *) (cd->cnv_dmap->dmapE12U);
 
528
    register uchar *    dmapE22U=(uchar *) (cd->cnv_dmap->dmapE22U);
 
529
    register uchar *    dmapE32U=(uchar *) (cd->cnv_dmap->dmapE32U);
 
530
    register int        inLen=*inBytesLeft;
 
531
    register char *     pOut=*outBuf;
 
532
    register char *     pIn=*inBuf;
 
533
    register int        offset;
 
534
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
535
    register size_t     numS=0;
 
536
    register UniChar    in;     /* copy part of U28 */
 
537
    register UniChar    ucs2;
 
538
    while (0 < inLen) {
 
539
      if (pLastOutBuf < pOut)
 
540
        break;
 
541
      if (*pIn == 0x00) {
 
542
        *pOut=0x00;
 
543
        ++pOut;
 
544
        ++pIn;
 
545
        --inLen;
 
546
      } else {
 
547
        if (*pIn == 0x8E) {      /* SS2 */
 
548
          if (inLen < 2) {
 
549
            if (cd->fromCcsid == 33722 ||       /* IBM-eucJP */
 
550
                cd->fromCcsid == 964)           /* IBM-eucTW */
 
551
              errno=EINVAL;  /* 22 */
 
552
            else
 
553
              errno=EILSEQ;  /* 116 */
 
554
            *outBytesLeft-=(pOut-*outBuf);
 
555
            *inBytesLeft=inLen;
 
556
            *outBuf=pOut;
 
557
            *inBuf=pIn;
 
558
            return -1;
 
559
          }
 
560
          ++pIn;
 
561
          if (*pIn < 0xA0) {
 
562
            if (cd->fromCcsid == 964)           /* IBM-eucTW */
 
563
              errno=EINVAL;  /* 22 */
 
564
            else
 
565
              errno=EILSEQ;  /* 116 */
 
566
            *outBytesLeft-=(pOut-*outBuf);
 
567
            *inBytesLeft=inLen;
 
568
            *outBuf=pOut;
 
569
            *inBuf=pIn-1;
 
570
            return -1;
 
571
          }
 
572
          offset=(*pIn - 0xA0);
 
573
          offset<<=1;
 
574
          if (dmapE22U[offset]   == 0x00 &&
 
575
              dmapE22U[offset+1] == 0x00) {     /* 2 bytes */
 
576
            if (inLen < 3) {
 
577
              if (cd->fromCcsid == 964)           /* IBM-eucTW */
 
578
                errno=EINVAL;  /* 22 */
 
579
              else
 
580
                errno=EILSEQ;  /* 116 */
 
581
              *outBytesLeft-=(pOut-*outBuf);
 
582
              *inBytesLeft=inLen;
 
583
              *outBuf=pOut;
 
584
              *inBuf=pIn-1;
 
585
              return -1;
 
586
            }
 
587
            offset=(*pIn - 0xA0) * 0x60 + 0x60;
 
588
            ++pIn;
 
589
            if (*pIn < 0xA0) {
 
590
              if (cd->fromCcsid == 964)           /* IBM-eucTW */
 
591
                errno=EINVAL;  /* 22 */
 
592
              else
 
593
                errno=EILSEQ;  /* 116 */
 
594
              *outBytesLeft-=(pOut-*outBuf);
 
595
              *inBytesLeft=inLen;
 
596
              *outBuf=pOut;
 
597
              *inBuf=pIn-2;
 
598
              return -1;
 
599
            }
 
600
            offset+=(*pIn - 0xA0);
 
601
            offset<<=1;
 
602
            if (dmapE22U[offset] == 0x00 &&
 
603
                dmapE22U[offset+1] == 0x00) {
 
604
              if (cd->fromCcsid == 964)           /* IBM-eucTW */
 
605
                errno=EINVAL;  /* 22 */
 
606
              else
 
607
                errno=EILSEQ;  /* 116 */
 
608
              *outBytesLeft-=(pOut-*outBuf);
 
609
              *inBytesLeft=inLen;
 
610
              *outBuf=pOut;
 
611
              *inBuf=pIn-2;
 
612
              return -1;
 
613
            }
 
614
            in=dmapE22U[offset];
 
615
            in<<=8;
 
616
            in+=dmapE22U[offset+1];
 
617
            if (dmapE22U[offset] == 0xFF &&
 
618
                dmapE22U[offset+1] == 0xFD) {
 
619
              if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD)
 
620
                ++numS;
 
621
            }
 
622
            ++pIn;
 
623
            inLen-=3;
 
624
          } else {      /* 1 bytes */
 
625
            in=dmapE22U[offset];
 
626
            in<<=8;
 
627
            in+=dmapE22U[offset+1];
 
628
            ++pIn;
 
629
            inLen-=2;
 
630
          }
 
631
        } else if (*pIn == 0x8F) {     /* SS3 */
 
632
          if (inLen < 2) {
 
633
            if (cd->fromCcsid == 33722)   /* IBM-eucJP */
 
634
              errno=EINVAL;  /* 22 */
 
635
            else
 
636
              errno=EILSEQ;  /* 116 */
 
637
            *outBytesLeft-=(pOut-*outBuf);
 
638
            *inBytesLeft=inLen;
 
639
            *outBuf=pOut;
 
640
            *inBuf=pIn;
 
641
            return -1;
 
642
          }
 
643
          ++pIn;
 
644
          if (*pIn < 0xA0) {
 
645
            if (cd->fromCcsid == 970 ||         /* IBM-eucKR */
 
646
                cd->fromCcsid == 964 ||         /* IBM-eucTW */
 
647
                cd->fromCcsid == 1383 ||        /* IBM-eucCN */
 
648
                (cd->fromCcsid == 33722 && 3 <= inLen)) /* IBM-eucJP */
 
649
              errno=EILSEQ;  /* 116 */
 
650
            else
 
651
              errno=EINVAL;  /* 22 */
 
652
            *outBytesLeft-=(pOut-*outBuf);
 
653
            *inBytesLeft=inLen;
 
654
            *outBuf=pOut;
 
655
            *inBuf=pIn-1;
 
656
            return -1;
 
657
          }
 
658
          offset=(*pIn - 0xA0);
 
659
          offset<<=1;
 
660
          if (dmapE32U[offset]   == 0x00 &&
 
661
              dmapE32U[offset+1] == 0x00) { /* 0x8F + 2 bytes */
 
662
            if (inLen < 3) {
 
663
              if (cd->fromCcsid == 33722)
 
664
                errno=EINVAL;  /* 22 */
 
665
              else
 
666
                errno=EILSEQ;  /* 116 */
 
667
              *outBytesLeft-=(pOut-*outBuf);
 
668
              *inBytesLeft=inLen;
 
669
              *outBuf=pOut;
 
670
              *inBuf=pIn-1;
 
671
              return -1;
 
672
            }
 
673
            offset=(*pIn - 0xA0) * 0x60 + 0x60;
 
674
            ++pIn;
 
675
            if (*pIn < 0xA0) {
 
676
              errno=EILSEQ;  /* 116 */
 
677
              *outBytesLeft-=(pOut-*outBuf);
 
678
              *inBytesLeft=inLen;
 
679
              *outBuf=pOut;
 
680
              *inBuf=pIn-2;
 
681
              return -1;
 
682
            }
 
683
            offset+=(*pIn - 0xA0);
 
684
            offset<<=1;
 
685
            if (dmapE32U[offset] == 0x00 &&
 
686
                dmapE32U[offset+1] == 0x00) {
 
687
              errno=EILSEQ;  /* 116 */
 
688
              *outBytesLeft-=(pOut-*outBuf);
 
689
              *inBytesLeft=inLen;
 
690
              *outBuf=pOut;
 
691
              *inBuf=pIn-2;
 
692
              return -1;
 
693
            }
 
694
            in=dmapE32U[offset];
 
695
            in<<=8;
 
696
            in+=dmapE32U[offset+1];
 
697
            if (dmapE32U[offset] == 0xFF &&
 
698
                dmapE32U[offset+1] == 0xFD) {
 
699
              if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD)
 
700
                ++numS;
 
701
            }
 
702
            ++pIn;
 
703
            inLen-=3;
 
704
          } else {      /* 0x8F + 1 bytes */
 
705
            in=dmapE32U[offset];
 
706
            in<<=8;
 
707
            in+=dmapE32U[offset+1];
 
708
            ++pIn;
 
709
            inLen-=2;
 
710
          }
 
711
 
 
712
        } else {
 
713
          offset=*pIn;
 
714
          offset<<=1;
 
715
          if (dmapE02U[offset]   == 0x00 &&
 
716
              dmapE02U[offset+1] == 0x00) {         /* SS1 */
 
717
            if (inLen < 2) {
 
718
              if ((cd->fromCcsid == 33722 && (*pIn == 0xA0 || (0xA9 <= *pIn && *pIn <= 0xAF) || *pIn == 0xFF)) ||
 
719
                  (cd->fromCcsid == 970 && (*pIn == 0xA0 || *pIn == 0xAD || *pIn == 0xAE || *pIn == 0xAF || *pIn == 0xFF)) ||
 
720
                  (cd->fromCcsid == 964 && (*pIn == 0xA0 || (0xAA <= *pIn && *pIn <= 0xC1) || *pIn == 0xC3 || *pIn == 0xFE || *pIn == 0xFF)) ||
 
721
                  (cd->fromCcsid == 1383 && (*pIn == 0xA0 || *pIn == 0xFF)))
 
722
                errno=EILSEQ;  /* 116 */
 
723
              else
 
724
                errno=EINVAL;  /* 22 */
 
725
              *outBytesLeft-=(pOut-*outBuf);
 
726
              *inBytesLeft=inLen;
 
727
              *outBuf=pOut;
 
728
              *inBuf=pIn;
 
729
              return -1;
 
730
            }
 
731
            if (*pIn < 0xA0) {
 
732
              errno=EILSEQ;  /* 116 */
 
733
              *outBytesLeft-=(pOut-*outBuf);
 
734
              *inBytesLeft=inLen;
 
735
              *outBuf=pOut;
 
736
              *inBuf=pIn;
 
737
              return -1;
 
738
            }
 
739
            offset=(*pIn - 0xA0) * 0x60;
 
740
            ++pIn;
 
741
            if (*pIn < 0xA0) {
 
742
              errno=EILSEQ;  /* 116 */
 
743
              *outBytesLeft-=(pOut-*outBuf);
 
744
              *inBytesLeft=inLen;
 
745
              *outBuf=pOut;
 
746
              *inBuf=pIn-1;
 
747
              return -1;
 
748
            }
 
749
            offset+=(*pIn - 0xA0);
 
750
            offset<<=1;
 
751
            if (dmapE12U[offset] == 0x00 &&
 
752
                dmapE12U[offset+1] == 0x00) {   /* undefined mapping */
 
753
              errno=EILSEQ;  /* 116 */
 
754
              *outBytesLeft-=(pOut-*outBuf);
 
755
              *inBytesLeft=inLen;
 
756
              *outBuf=pOut;
 
757
              *inBuf=pIn-1;
 
758
              return -1;
 
759
            }
 
760
            in=dmapE12U[offset];
 
761
            in<<=8;
 
762
            in+=dmapE12U[offset+1];
 
763
            if (dmapE12U[offset] == 0xFF &&
 
764
                dmapE12U[offset+1] == 0xFD) {
 
765
              if (pIn[-1] * 0x100 + pIn[0] != cd->srcSubD)
 
766
                ++numS;
 
767
            }
 
768
            ++pIn;
 
769
            inLen-=2;
 
770
          } else {
 
771
            in=dmapE02U[offset];
 
772
            in<<=8;
 
773
            in+=dmapE02U[offset+1];
 
774
            if (dmapE02U[offset] == 0x00 &&
 
775
                dmapE02U[offset+1] == 0x1A) {
 
776
              if (*pIn != cd->srcSubS)
 
777
                ++numS;
 
778
            }
 
779
            ++pIn;
 
780
            --inLen;
 
781
          }
 
782
        }
 
783
        ucs2=in;
 
784
        if ((in & 0xFF80) == 0x0000) {     /* U28: in & 0b1111111110000000 == 0x0000 */
 
785
          *pOut=in;
 
786
          ++pOut;
 
787
        } else if ((in & 0xF800) == 0x0000) {     /* in & 0b1111100000000000 == 0x0000 */
 
788
          register uchar        byte;
 
789
          in>>=6;
 
790
          in&=0x001F;   /* 0b0000000000011111 */
 
791
          in|=0x00C0;   /* 0b0000000011000000 */
 
792
          *pOut=in;
 
793
          ++pOut;
 
794
          byte=ucs2;    /* dmapD12U[offset+1]; */
 
795
          byte&=0x3F;   /* 0b00111111; */
 
796
          byte|=0x80;   /* 0b10000000; */
 
797
          *pOut=byte;
 
798
          ++pOut;
 
799
        } else if ((in & 0xFC00) == 0xD800) {
 
800
          *pOut=0xEF;
 
801
          ++pOut;
 
802
          *pOut=0xBF;
 
803
          ++pOut;
 
804
          *pOut=0xBD;
 
805
          ++pOut;
 
806
        } else {
 
807
          register uchar        byte;
 
808
          register uchar        work;
 
809
          byte=(ucs2>>8);    /* dmapD12U[offset]; */
 
810
          byte>>=4;
 
811
          byte|=0xE0;   /* 0b11100000; */
 
812
          *pOut=byte;
 
813
          ++pOut;
 
814
 
 
815
          byte=(ucs2>>8);    /* dmapD12U[offset]; */
 
816
          byte<<=2;
 
817
          work=ucs2;    /* dmapD12U[offset+1]; */
 
818
          work>>=6;
 
819
          byte|=work;
 
820
          byte&=0x3F;   /* 0b00111111; */
 
821
          byte|=0x80;   /* 0b10000000; */
 
822
          *pOut=byte;
 
823
          ++pOut;
 
824
 
 
825
          byte=ucs2;    /* dmapD12U[offset+1]; */
 
826
          byte&=0x3F;   /* 0b00111111; */
 
827
          byte|=0x80;   /* 0b10000000; */
 
828
          *pOut=byte;
 
829
          ++pOut;
 
830
        }
 
831
        /* end of U28 */
 
832
      }
 
833
    }
 
834
    *outBytesLeft-=(pOut-*outBuf);
 
835
    *inBytesLeft=inLen;
 
836
    *outBuf=pOut;
 
837
    *inBuf=pIn;
 
838
    *numSub+=numS;
 
839
    return 0;
 
840
 
 
841
  } else if (cd->cnv_dmap->codingSchema == DMAP_U2E) {
 
842
    register uchar *    dmapU2S=cd->cnv_dmap->dmapU2S;
 
843
    register uchar *    dmapU2M2=cd->cnv_dmap->dmapU2M2 - 0x80 * 2;
 
844
    register uchar *    dmapU2M3=cd->cnv_dmap->dmapU2M3 - 0x80 * 3;
 
845
    register int        inLen=*inBytesLeft;
 
846
    register char *     pOut=*outBuf;
 
847
    register char *     pIn=*inBuf;
 
848
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
849
    register char       subS=cd->subS;
 
850
    register char *     pSubD=(char *) &(cd->subD);
 
851
    register size_t     numS=0;
 
852
    register size_t     rc=0;
 
853
    while (0 < inLen) {
 
854
      register uint32_t       in;
 
855
      if (inLen == 1) {
 
856
        errno=EINVAL;  /* 22 */
 
857
        *outBytesLeft-=(pOut-*outBuf);
 
858
        *inBytesLeft=inLen;
 
859
        *outBuf=pOut;
 
860
        *inBuf=pIn;
 
861
        return -1;
 
862
      }
 
863
      if (pLastOutBuf < pOut)
 
864
        break;
 
865
      in=pIn[0];
 
866
      in<<=8;
 
867
      in+=pIn[1];
 
868
      if (in == 0x0000) {
 
869
        *pOut=0x00;
 
870
        ++pOut;
 
871
      } else if (in < 0x100 && dmapU2S[in] != 0x0000) {
 
872
        if ((*pOut=dmapU2S[in]) == subS) {
 
873
          if (in != cd->srcSubS)
 
874
            ++numS;
 
875
        }
 
876
        ++pOut;
 
877
      } else {
 
878
        in<<=1;
 
879
        if (dmapU2M2[in] == 0x00) {     /* not found in dmapU2M2 */
 
880
          in*=1.5;
 
881
          if (dmapU2M3[in] == 0x00) {   /* not found in dmapU2M3*/
 
882
            *pOut=pSubD[0];
 
883
            ++pOut;
 
884
            *pOut=pSubD[1];
 
885
            ++pOut;
 
886
            ++numS;
 
887
            ++rc;
 
888
          } else {
 
889
            *pOut=dmapU2M3[in];
 
890
            ++pOut;
 
891
            *pOut=dmapU2M3[1+in];
 
892
            ++pOut;
 
893
            *pOut=dmapU2M3[2+in];
 
894
            ++pOut;
 
895
          }
 
896
        } else {
 
897
          *pOut=dmapU2M2[in];
 
898
          ++pOut;
 
899
          if (dmapU2M2[1+in] == 0x00) {
 
900
            if (*pOut == subS) {
 
901
              in>>=1;
 
902
              if (in != cd->srcSubS)
 
903
                ++numS;
 
904
            }
 
905
          } else {
 
906
            *pOut=dmapU2M2[1+in];
 
907
            ++pOut;
 
908
            if (memcmp(pOut-2, pSubD, 2) == 0) {
 
909
              in>>=1;
 
910
              if (in != cd->srcSubD) {
 
911
                ++numS;
 
912
                ++rc;
 
913
              }
 
914
            }
 
915
          }
 
916
        }
 
917
      }
 
918
      pIn+=2;
 
919
      inLen-=2;
 
920
    }
 
921
    *outBytesLeft-=(pOut-*outBuf);
 
922
    *inBytesLeft=inLen;
 
923
    *outBuf=pOut;
 
924
    *inBuf=pIn;
 
925
    *numSub+=numS;
 
926
    return rc;        /* compatibility to iconv() */
 
927
 
 
928
  } else if (cd->cnv_dmap->codingSchema == DMAP_T2E) {
 
929
    register uchar *    dmapU2S=cd->cnv_dmap->dmapU2S;
 
930
    register uchar *    dmapU2M2=cd->cnv_dmap->dmapU2M2 - 0x80 * 2;
 
931
    register uchar *    dmapU2M3=cd->cnv_dmap->dmapU2M3 - 0x80 * 3;
 
932
    register int        inLen=*inBytesLeft;
 
933
    register char *     pOut=*outBuf;
 
934
    register char *     pIn=*inBuf;
 
935
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
936
    register char       subS=cd->subS;
 
937
    register char *     pSubD=(char *) &(cd->subD);
 
938
    register size_t     numS=0;
 
939
    register size_t     rc=0;
 
940
    while (0 < inLen) {
 
941
      register uint32_t       in;
 
942
      if (inLen == 1) {
 
943
        errno=EINVAL;  /* 22 */
 
944
        *outBytesLeft-=(pOut-*outBuf);
 
945
        *inBytesLeft=inLen-1;
 
946
        *outBuf=pOut;
 
947
        *inBuf=pIn;
 
948
        ++numS;
 
949
        *numSub+=numS;
 
950
        return 0;
 
951
      }
 
952
      if (pLastOutBuf < pOut)
 
953
        break;
 
954
      in=pIn[0];
 
955
      in<<=8;
 
956
      in+=pIn[1];
 
957
      if (in == 0x0000) {
 
958
        *pOut=0x00;
 
959
        ++pOut;
 
960
      } else if (0xD800 <= in && in <= 0xDBFF) { /* first byte of surrogate */
 
961
        errno=EINVAL;   /* 22 */
 
962
        *inBytesLeft=inLen-2;
 
963
        *outBytesLeft-=(pOut-*outBuf);
 
964
        *outBuf=pOut;
 
965
        *inBuf=pIn+2;
 
966
        ++numS;
 
967
        *numSub+=numS;
 
968
        return -1;
 
969
        
 
970
      } else if (0xDC00 <= in && in <= 0xDFFF) { /* second byte of surrogate */
 
971
        errno=EINVAL;   /* 22 */
 
972
        *inBytesLeft=inLen-1;
 
973
        *outBytesLeft-=(pOut-*outBuf);
 
974
        *outBuf=pOut;
 
975
        *inBuf=pIn;
 
976
        ++numS;
 
977
        *numSub+=numS;
 
978
        return -1;
 
979
        
 
980
      } else if (in < 0x100 && dmapU2S[in] != 0x0000) {
 
981
        if ((*pOut=dmapU2S[in]) == subS) {
 
982
          if (in != cd->srcSubS)
 
983
            ++numS;
 
984
        }
 
985
        ++pOut;
 
986
      } else {
 
987
        in<<=1;
 
988
        if (dmapU2M2[in] == 0x00) {     /* not found in dmapU2M2 */
 
989
          in*=1.5;
 
990
          if (dmapU2M3[in] == 0x00) {   /* not found in dmapU2M3*/
 
991
            *pOut=pSubD[0];
 
992
            ++pOut;
 
993
            *pOut=pSubD[1];
 
994
            ++pOut;
 
995
            ++numS;
 
996
            ++rc;
 
997
          } else {
 
998
            *pOut=dmapU2M3[in];
 
999
            ++pOut;
 
1000
            *pOut=dmapU2M3[1+in];
 
1001
            ++pOut;
 
1002
            *pOut=dmapU2M3[2+in];
 
1003
            ++pOut;
 
1004
          }
 
1005
        } else {
 
1006
          *pOut=dmapU2M2[in];
 
1007
          ++pOut;
 
1008
          if (dmapU2M2[1+in] == 0x00) {
 
1009
            if (*pOut == subS) {
 
1010
              in>>=1;
 
1011
              if (in != cd->srcSubS)
 
1012
                ++numS;
 
1013
            }
 
1014
          } else {
 
1015
            *pOut=dmapU2M2[1+in];
 
1016
            ++pOut;
 
1017
            if (memcmp(pOut-2, pSubD, 2) == 0) {
 
1018
              in>>=1;
 
1019
              if (in != cd->srcSubD) {
 
1020
                ++numS;
 
1021
                ++rc;
 
1022
              }
 
1023
            }
 
1024
          }
 
1025
        }
 
1026
      }
 
1027
      pIn+=2;
 
1028
      inLen-=2;
 
1029
    }
 
1030
    *outBytesLeft-=(pOut-*outBuf);
 
1031
    *inBytesLeft=inLen;
 
1032
    *outBuf=pOut;
 
1033
    *inBuf=pIn;
 
1034
    *numSub+=numS;
 
1035
    return 0;
 
1036
 
 
1037
  } else if (cd->cnv_dmap->codingSchema == DMAP_82E) {
 
1038
    register uchar *    dmapU2S=cd->cnv_dmap->dmapU2S;
 
1039
    register uchar *    dmapU2M2=cd->cnv_dmap->dmapU2M2 - 0x80 * 2;
 
1040
    register uchar *    dmapU2M3=cd->cnv_dmap->dmapU2M3 - 0x80 * 3;
 
1041
    register int        inLen=*inBytesLeft;
 
1042
    register char *     pOut=*outBuf;
 
1043
    register char *     pIn=*inBuf;
 
1044
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
1045
    register char       subS=cd->subS;
 
1046
    register char *     pSubD=(char *) &(cd->subD);
 
1047
    register size_t     numS=0;
 
1048
    register size_t     rc=0;
 
1049
    while (0 < inLen) {
 
1050
      register uint32_t in;
 
1051
      uint32_t          in2;
 
1052
      if (pLastOutBuf < pOut)
 
1053
        break;
 
1054
      /* convert from UTF-8 to UCS-2 */
 
1055
      if (*pIn == 0x00) {
 
1056
        in=0x0000;
 
1057
        ++pIn;
 
1058
        --inLen;
 
1059
      } else {                          /* 82U: */
 
1060
        register uchar byte1=*pIn;
 
1061
        if ((byte1 & 0x80) == 0x00) {         /* if (byte1 & 0b10000000 == 0b00000000) { */
 
1062
          /* 1 bytes sequence:  0xxxxxxx => 00000000 0xxxxxxx*/
 
1063
          in=byte1;
 
1064
          ++pIn;
 
1065
          --inLen;
 
1066
        } else if ((byte1 & 0xE0) == 0xC0) {  /* (byte1 & 0b11100000 == 0b11000000) { */
 
1067
          if (inLen < 2) {
 
1068
            errno=EINVAL;  /* 22 */
 
1069
            *outBytesLeft-=(pOut-*outBuf);
 
1070
            *inBytesLeft=inLen;
 
1071
            *outBuf=pOut;
 
1072
            *inBuf=pIn;
 
1073
            *numSub+=numS;
 
1074
            return -1;
 
1075
          }
 
1076
          if (byte1 == 0xC0 || byte1 == 0xC1) {  /* invalid sequence */
 
1077
            errno=EILSEQ;  /* 116 */
 
1078
            *outBytesLeft-=(pOut-*outBuf);
 
1079
            *inBytesLeft=inLen;
 
1080
            *outBuf=pOut;
 
1081
            *inBuf=pIn;
 
1082
            *numSub+=numS;
 
1083
            return -1;
 
1084
          }
 
1085
          /* 2 bytes sequence: 
 
1086
             110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */
 
1087
          register uchar byte2;
 
1088
          ++pIn;
 
1089
          byte2=*pIn;
 
1090
          if ((byte2 & 0xC0) == 0x80) {       /* byte2 & 0b11000000 == 0b10000000) { */
 
1091
            register uchar work=byte1;
 
1092
            work<<=6;
 
1093
            byte2&=0x3F;      /* 0b00111111; */
 
1094
            byte2|=work;
 
1095
              
 
1096
            byte1&=0x1F;      /* 0b00011111; */
 
1097
            byte1>>=2;
 
1098
            in=byte1;
 
1099
            in<<=8;
 
1100
            in+=byte2;
 
1101
            inLen-=2;
 
1102
            ++pIn;
 
1103
          } else { /* invalid sequence */
 
1104
            errno=EILSEQ;  /* 116 */
 
1105
            *outBytesLeft-=(pOut-*outBuf);
 
1106
            *inBytesLeft=inLen;
 
1107
            *outBuf=pOut;
 
1108
            *inBuf=pIn-1;
 
1109
            *numSub+=numS;
 
1110
            return -1;
 
1111
          }
 
1112
        } else if ((byte1 & 0xF0) == 0xE0) {    /* byte1 & 0b11110000 == 0b11100000 */
 
1113
          /* 3 bytes sequence: 
 
1114
             1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */
 
1115
          register uchar byte2;
 
1116
          register uchar byte3;
 
1117
          if (inLen < 3) {
 
1118
            if (inLen == 2 && (pIn[1]  & 0xC0) != 0x80)
 
1119
              errno=EILSEQ;  /* 116 */
 
1120
            else
 
1121
              errno=EINVAL;  /* 22 */
 
1122
            *outBytesLeft-=(pOut-*outBuf);
 
1123
            *inBytesLeft=inLen;
 
1124
            *outBuf=pOut;
 
1125
            *inBuf=pIn;
 
1126
            *numSub+=numS;
 
1127
            return -1;
 
1128
          }
 
1129
          ++pIn;
 
1130
          byte2=*pIn;
 
1131
          ++pIn;
 
1132
          byte3=*pIn;
 
1133
          if ((byte2 & 0xC0) != 0x80 ||
 
1134
              (byte3 & 0xC0) != 0x80 ||
 
1135
              (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */
 
1136
            errno=EILSEQ;  /* 116 */
 
1137
            *outBytesLeft-=(pOut-*outBuf);
 
1138
            *inBytesLeft=inLen;
 
1139
            *outBuf=pOut;
 
1140
            *inBuf=pIn-2;
 
1141
            *numSub+=numS;
 
1142
            return -1;
 
1143
          }
 
1144
          {
 
1145
            register uchar work=byte2;
 
1146
            work<<=6;
 
1147
            byte3&=0x3F;      /* 0b00111111; */
 
1148
            byte3|=work;
 
1149
              
 
1150
            byte2&=0x3F;      /* 0b00111111; */
 
1151
            byte2>>=2;
 
1152
 
 
1153
            byte1<<=4;
 
1154
            in=byte1 | byte2;;
 
1155
            in<<=8;
 
1156
            in+=byte3;
 
1157
            inLen-=3;
 
1158
            ++pIn;
 
1159
          }
 
1160
        } else if ((0xF0 <= byte1 && byte1 <= 0xF4)) {    /* (bytes1 & 11111000) == 0x1110000 */
 
1161
          /* 4 bytes sequence
 
1162
             11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx
 
1163
             where uuuuu = wwww + 1 */
 
1164
          register uchar byte2;
 
1165
          register uchar byte3;
 
1166
          register uchar byte4;
 
1167
          if (inLen < 4) {
 
1168
            if ((inLen >= 2 && (pIn[1]  & 0xC0) != 0x80) ||
 
1169
                (inLen >= 3 && (pIn[2]  & 0xC0) != 0x80) ||
 
1170
                (cd->toCcsid == 13488) )
 
1171
              errno=EILSEQ;  /* 116 */
 
1172
            else
 
1173
              errno=EINVAL;  /* 22 */
 
1174
            *outBytesLeft-=(pOut-*outBuf);
 
1175
            *inBytesLeft=inLen;
 
1176
            *outBuf=pOut;
 
1177
            *inBuf=pIn;
 
1178
            *numSub+=numS;
 
1179
            return -1;
 
1180
          }
 
1181
          ++pIn;
 
1182
          byte2=*pIn;
 
1183
          ++pIn;
 
1184
          byte3=*pIn;
 
1185
          ++pIn;
 
1186
          byte4=*pIn;
 
1187
          if ((byte2 & 0xC0) == 0x80 &&         /* byte2 & 0b11000000 == 0b10000000 */
 
1188
              (byte3 & 0xC0) == 0x80 &&         /* byte3 & 0b11000000 == 0b10000000 */
 
1189
              (byte4 & 0xC0) == 0x80) {         /* byte4 & 0b11000000 == 0b10000000 */
 
1190
            register uchar work=byte2;
 
1191
            if (byte1 == 0xF0 && byte2 < 0x90) {
 
1192
              errno=EILSEQ;  /* 116 */
 
1193
              *outBytesLeft-=(pOut-*outBuf);
 
1194
              *inBytesLeft=inLen;
 
1195
              *outBuf=pOut;
 
1196
              *inBuf=pIn-3;
 
1197
              *numSub+=numS;
 
1198
              return -1;
 
1199
              /* iconv() returns 0 for 0xF4908080 and convert to 0x00 
 
1200
            } else if (byte1 == 0xF4 && byte2 > 0x8F) {
 
1201
              errno=EINVAL;
 
1202
              *outBytesLeft-=(pOut-*outBuf);
 
1203
              *inBytesLeft=inLen;
 
1204
              *outBuf=pOut;
 
1205
              *inBuf=pIn-3;
 
1206
              *numSub+=numS;
 
1207
              return -1;
 
1208
              */
 
1209
            }
 
1210
 
 
1211
            work&=0x30;       /* 0b00110000; */
 
1212
            work>>=4;
 
1213
            byte1&=0x07;      /* 0b00000111; */
 
1214
            byte1<<=2;
 
1215
            byte1+=work;      /* uuuuu */
 
1216
            --byte1;          /* wwww  */
 
1217
 
 
1218
            work=byte1 & 0x0F;
 
1219
            work>>=2;
 
1220
            work+=0xD8;       /* 0b11011011; */
 
1221
            in=work;
 
1222
            in<<=8;
 
1223
 
 
1224
            byte1<<=6;
 
1225
            byte2<<=2;
 
1226
            byte2&=0x3C;      /* 0b00111100; */
 
1227
            work=byte3;
 
1228
            work>>=4;
 
1229
            work&=0x03;       /* 0b00000011; */
 
1230
            work|=byte1;
 
1231
            work|=byte2;
 
1232
            in+=work;
 
1233
 
 
1234
            work=byte3;
 
1235
            work>>=2;
 
1236
            work&=0x03;       /* 0b00000011; */
 
1237
            work|=0xDC;       /* 0b110111xx; */
 
1238
            in2=work;
 
1239
            in2<<=8;
 
1240
 
 
1241
            byte3<<=6;
 
1242
            byte4&=0x3F;      /* 0b00111111; */
 
1243
            byte4|=byte3;
 
1244
            in2+=byte4;
 
1245
            inLen-=4;
 
1246
            ++pIn;
 
1247
#ifdef match_with_GBK
 
1248
            if ((0xD800 == in && in2 < 0xDC80) ||
 
1249
                (0xD840 == in && in2 < 0xDC80) ||
 
1250
                (0xD880 == in && in2 < 0xDC80) ||
 
1251
                (0xD8C0 == in && in2 < 0xDC80) ||
 
1252
                (0xD900 == in && in2 < 0xDC80) ||
 
1253
                (0xD940 == in && in2 < 0xDC80) ||
 
1254
                (0xD980 == in && in2 < 0xDC80) ||
 
1255
                (0xD9C0 == in && in2 < 0xDC80) ||
 
1256
                (0xDA00 == in && in2 < 0xDC80) ||
 
1257
                (0xDA40 == in && in2 < 0xDC80) ||
 
1258
                (0xDA80 == in && in2 < 0xDC80) ||
 
1259
                (0xDAC0 == in && in2 < 0xDC80) ||
 
1260
                (0xDB00 == in && in2 < 0xDC80) ||
 
1261
                (0xDB40 == in && in2 < 0xDC80) ||
 
1262
                (0xDB80 == in && in2 < 0xDC80) ||
 
1263
                (0xDBC0 == in && in2 < 0xDC80)) {
 
1264
#else
 
1265
              if ((0xD800 <= in  && in  <= 0xDBFF) &&
 
1266
                  (0xDC00 <= in2 && in2 <= 0xDFFF)) {
 
1267
#endif
 
1268
              *pOut=subS;
 
1269
              ++pOut;
 
1270
              ++numS;
 
1271
              continue;
 
1272
            }
 
1273
          } else { /* invalid sequence */
 
1274
            errno=EILSEQ;  /* 116 */
 
1275
            *outBytesLeft-=(pOut-*outBuf);
 
1276
            *inBytesLeft=inLen;
 
1277
            *outBuf=pOut;
 
1278
            *inBuf=pIn-3;
 
1279
            *numSub+=numS;
 
1280
            return -1;
 
1281
          }
 
1282
        } else if (0xF5 <= byte1 && byte1 <= 0xFF) { /* minic iconv() behavior */
 
1283
          if (inLen < 4 ||
 
1284
              (inLen >= 4 && byte1 == 0xF8 && pIn[1] < 0x90) ||
 
1285
              pIn[1] < 0x80 || 0xBF < pIn[1] ||
 
1286
              pIn[2] < 0x80 || 0xBF < pIn[2] ||
 
1287
              pIn[3] < 0x80 || 0xBF < pIn[3] ) {
 
1288
            if (inLen == 1)
 
1289
              errno=EINVAL;  /* 22 */
 
1290
            else if (inLen == 2 && (pIn[1]  & 0xC0) != 0x80)
 
1291
              errno=EILSEQ;  /* 116 */
 
1292
            else if (inLen == 3 && ((pIn[1]  & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80))
 
1293
              errno=EILSEQ;  /* 116 */
 
1294
            else if (inLen >= 4 && (byte1 == 0xF8 || (pIn[1]  & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80))
 
1295
              errno=EILSEQ;  /* 116 */
 
1296
            else
 
1297
              errno=EINVAL;  /* 22 */
 
1298
 
 
1299
            *outBytesLeft-=(pOut-*outBuf);
 
1300
            *inBytesLeft=inLen;
 
1301
            *outBuf=pOut;
 
1302
            *inBuf=pIn;
 
1303
            *numSub+=numS;
 
1304
            return -1;
 
1305
          } else if ((pIn[1] == 0x80 || pIn[1] == 0x90 || pIn[1] == 0xA0 || pIn[1] == 0xB0) && 
 
1306
                     pIn[2] < 0x82) {
 
1307
            *pOut=subS;   /* Though returns replacement character, which iconv() does not return. */
 
1308
            ++pOut;
 
1309
            ++numS;
 
1310
            pIn+=4;
 
1311
            inLen-=4;
 
1312
            continue;
 
1313
          } else {
 
1314
            *pOut=pSubD[0];   /* Though returns replacement character, which iconv() does not return. */
 
1315
            ++pOut;
 
1316
            *pOut=pSubD[1];
 
1317
            ++pOut;
 
1318
            ++numS;
 
1319
            pIn+=4;
 
1320
            inLen-=4;
 
1321
            continue;
 
1322
            /* iconv() returns 0 with strange 1 byte converted values */
 
1323
          }
 
1324
 
 
1325
        } else { /* invalid sequence */
 
1326
          errno=EILSEQ;  /* 116 */
 
1327
          *outBytesLeft-=(pOut-*outBuf);
 
1328
          *inBytesLeft=inLen;
 
1329
          *outBuf=pOut;
 
1330
          *inBuf=pIn;
 
1331
          *numSub+=numS;
 
1332
          return -1;
 
1333
        }
 
1334
      }
 
1335
      /* end of UTF-8 to UCS-2 */
 
1336
      if (in == 0x0000) {
 
1337
        *pOut=0x00;
 
1338
        ++pOut;
 
1339
      } else if (in < 0x100 && dmapU2S[in] != 0x0000) {
 
1340
        if ((*pOut=dmapU2S[in]) == subS) {
 
1341
          if (in != cd->srcSubS)
 
1342
            ++numS;
 
1343
        }
 
1344
        ++pOut;
 
1345
      } else {
 
1346
        in<<=1;
 
1347
        if (dmapU2M2[in] == 0x00) {     /* not found in dmapU2M2 */
 
1348
          in*=1.5;
 
1349
          if (dmapU2M3[in] == 0x00) {   /* not found in dmapU2M3*/
 
1350
            *pOut=pSubD[0];
 
1351
            ++pOut;
 
1352
            *pOut=pSubD[1];
 
1353
            ++pOut;
 
1354
            ++numS;
 
1355
            ++rc;
 
1356
          } else {
 
1357
            *pOut=dmapU2M3[in];
 
1358
            ++pOut;
 
1359
            *pOut=dmapU2M3[1+in];
 
1360
            ++pOut;
 
1361
            *pOut=dmapU2M3[2+in];
 
1362
            ++pOut;
 
1363
          }
 
1364
        } else {
 
1365
          *pOut=dmapU2M2[in];
 
1366
          ++pOut;
 
1367
          if (dmapU2M2[1+in] == 0x00) {
 
1368
            if (*pOut == subS) {
 
1369
              in>>=1;
 
1370
              if (in != cd->srcSubS)
 
1371
                ++numS;
 
1372
            }
 
1373
          } else {
 
1374
            *pOut=dmapU2M2[1+in];
 
1375
            ++pOut;
 
1376
            if (memcmp(pOut-2, pSubD, 2) == 0) {
 
1377
              in>>=1;
 
1378
              if (in != cd->srcSubD) {
 
1379
                ++numS;
 
1380
                ++rc;
 
1381
              }
 
1382
            }
 
1383
          }
 
1384
        }
 
1385
      }
 
1386
    }
 
1387
    *outBytesLeft-=(pOut-*outBuf);
 
1388
    *inBytesLeft=inLen;
 
1389
    *outBuf=pOut;
 
1390
    *inBuf=pIn;
 
1391
    *numSub+=numS;
 
1392
    return 0;
 
1393
 
 
1394
  } else if (cd->cnv_dmap->codingSchema == DMAP_S2U) {
 
1395
    /* use uchar * instead of UniChar to avoid memcpy */
 
1396
    register uchar *    dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U);
 
1397
    register int        inLen=*inBytesLeft;
 
1398
    register char *     pOut=*outBuf;
 
1399
    register char *     pIn=*inBuf;
 
1400
    register int        offset;
 
1401
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
1402
    register size_t     numS=0;
 
1403
    while (0 < inLen) {
 
1404
      if (pLastOutBuf < pOut)
 
1405
        break;
 
1406
      if (*pIn == 0x00) {
 
1407
        *pOut=0x00;
 
1408
        ++pOut;
 
1409
        *pOut=0x00;
 
1410
        ++pOut;
 
1411
        ++pIn;
 
1412
        --inLen;
 
1413
      } else {
 
1414
        offset=*pIn;
 
1415
        offset<<=1;
 
1416
        *pOut=dmapD12U[offset];
 
1417
        ++pOut;
 
1418
        *pOut=dmapD12U[offset+1];
 
1419
        ++pOut;
 
1420
        if (dmapD12U[offset]   == 0x00) {
 
1421
          if (dmapD12U[offset+1] == 0x1A) {
 
1422
            if (*pIn != cd->srcSubS)
 
1423
              ++numS;
 
1424
          } else if (dmapD12U[offset+1] == 0x00) {
 
1425
            pOut-=2;
 
1426
            *outBytesLeft-=(pOut-*outBuf);
 
1427
            *inBytesLeft=inLen;
 
1428
            *outBuf=pOut;
 
1429
            *inBuf=pIn;
 
1430
            *numSub+=numS;
 
1431
            return -1;
 
1432
          }
 
1433
        }
 
1434
        ++pIn;
 
1435
        --inLen;
 
1436
      }
 
1437
    }
 
1438
    *outBytesLeft-=(pOut-*outBuf);
 
1439
    *inBytesLeft=inLen;
 
1440
    *outBuf=pOut;
 
1441
    *inBuf=pIn;
 
1442
    *numSub+=numS;
 
1443
    return 0;
 
1444
 
 
1445
  } else if (cd->cnv_dmap->codingSchema == DMAP_S28) {
 
1446
    /* use uchar * instead of UniChar to avoid memcpy */
 
1447
    register uchar *    dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U);
 
1448
    register int        inLen=*inBytesLeft;
 
1449
    register char *     pOut=*outBuf;
 
1450
    register char *     pIn=*inBuf;
 
1451
    register int        offset;
 
1452
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
1453
    register size_t     numS=0;
 
1454
    register UniChar    in;     /* copy part of U28 */
 
1455
    while (0 < inLen) {
 
1456
      if (pLastOutBuf < pOut)
 
1457
        break;
 
1458
      if (*pIn == 0x00) {
 
1459
        *pOut=0x00;
 
1460
        ++pOut;
 
1461
        ++pIn;
 
1462
        --inLen;
 
1463
      } else {
 
1464
        offset=*pIn;
 
1465
        offset<<=1;
 
1466
        in=dmapD12U[offset];
 
1467
        in<<=8;
 
1468
        in+=dmapD12U[offset+1];
 
1469
        if ((in & 0xFF80) == 0x0000) {     /* U28: in & 0b1111111110000000 == 0x0000 */
 
1470
          if (in == 0x000) {
 
1471
            errno=EILSEQ;  /* 116 */
 
1472
            *outBytesLeft-=(pOut-*outBuf);
 
1473
            *inBytesLeft=inLen;
 
1474
            *outBuf=pOut;
 
1475
            *inBuf=pIn;
 
1476
            *numSub+=numS;
 
1477
            return -1;
 
1478
          }
 
1479
          *pOut=in;
 
1480
          ++pOut;
 
1481
        } else if ((in & 0xF800) == 0x0000) {     /* in & 0b1111100000000000 == 0x0000 */
 
1482
          register uchar        byte;
 
1483
          in>>=6;
 
1484
          in&=0x001F;   /* 0b0000000000011111 */
 
1485
          in|=0x00C0;   /* 0b0000000011000000 */
 
1486
          *pOut=in;
 
1487
          ++pOut;
 
1488
          byte=dmapD12U[offset+1];
 
1489
          byte&=0x3F;   /* 0b00111111; */
 
1490
          byte|=0x80;   /* 0b10000000; */
 
1491
          *pOut=byte;
 
1492
          ++pOut;
 
1493
        } else if ((in & 0xFC00) == 0xD800) {    /* There should not be no surrogate character in SBCS. */
 
1494
          *pOut=0xEF;
 
1495
          ++pOut;
 
1496
          *pOut=0xBF;
 
1497
          ++pOut;
 
1498
          *pOut=0xBD;
 
1499
          ++pOut;
 
1500
        } else {
 
1501
          register uchar        byte;
 
1502
          register uchar        work;
 
1503
          byte=dmapD12U[offset];
 
1504
          byte>>=4;
 
1505
          byte|=0xE0;   /* 0b11100000; */
 
1506
          *pOut=byte;
 
1507
          ++pOut;
 
1508
 
 
1509
          byte=dmapD12U[offset];
 
1510
          byte<<=2;
 
1511
          work=dmapD12U[offset+1];
 
1512
          work>>=6;
 
1513
          byte|=work;
 
1514
          byte&=0x3F;   /* 0b00111111; */
 
1515
          byte|=0x80;   /* 0b10000000; */
 
1516
          *pOut=byte;
 
1517
          ++pOut;
 
1518
 
 
1519
          byte=dmapD12U[offset+1];
 
1520
          byte&=0x3F;   /* 0b00111111; */
 
1521
          byte|=0x80;   /* 0b10000000; */
 
1522
          *pOut=byte;
 
1523
          ++pOut;
 
1524
        }
 
1525
        /* end of U28 */
 
1526
        if (dmapD12U[offset]   == 0x00) {
 
1527
          if (dmapD12U[offset+1] == 0x1A) {
 
1528
            if (*pIn != cd->srcSubS)
 
1529
              ++numS;
 
1530
          }
 
1531
        }
 
1532
        ++pIn;
 
1533
        --inLen;
 
1534
      }
 
1535
    }
 
1536
    *outBytesLeft-=(pOut-*outBuf);
 
1537
    *inBytesLeft=inLen;
 
1538
    *outBuf=pOut;
 
1539
    *inBuf=pIn;
 
1540
    *numSub+=numS;
 
1541
    return 0;
 
1542
 
 
1543
  } else if (cd->cnv_dmap->codingSchema == DMAP_U2S) {
 
1544
    register uchar *    dmapU2S=cd->cnv_dmap->dmapU2S;
 
1545
    register int        inLen=*inBytesLeft;
 
1546
    register char *     pOut=*outBuf;
 
1547
    register char *     pIn=*inBuf;
 
1548
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
1549
    register char       subS=cd->subS;
 
1550
    register size_t     numS=0;
 
1551
    while (0 < inLen) {
 
1552
      register uint32_t       in;
 
1553
      if (inLen == 1) {
 
1554
        errno=EINVAL;   /* 22 */
 
1555
 
 
1556
        *inBytesLeft=inLen;
 
1557
        *outBytesLeft-=(pOut-*outBuf);
 
1558
        *outBuf=pOut;
 
1559
        *inBuf=pIn;
 
1560
        return -1;
 
1561
      }
 
1562
      if (pLastOutBuf < pOut)
 
1563
        break;
 
1564
      in=pIn[0];
 
1565
      in<<=8;
 
1566
      in+=pIn[1];
 
1567
      if (in == 0x0000) {
 
1568
        *pOut=0x00;
 
1569
      } else {
 
1570
        if ((*pOut=dmapU2S[in]) == 0x00) {
 
1571
          *pOut=subS;
 
1572
          ++numS;
 
1573
          errno=EINVAL;  /* 22 */
 
1574
        } else if (*pOut == subS) {
 
1575
          if (in != cd->srcSubS)
 
1576
            ++numS;
 
1577
        }
 
1578
      }
 
1579
      ++pOut;
 
1580
      pIn+=2;
 
1581
      inLen-=2;
 
1582
    }
 
1583
    *outBytesLeft-=(pOut-*outBuf);
 
1584
    *inBytesLeft=inLen;
 
1585
    *outBuf=pOut;
 
1586
    *inBuf=pIn;
 
1587
    *numSub+=numS;
 
1588
    return numS;
 
1589
 
 
1590
  } else if (cd->cnv_dmap->codingSchema == DMAP_T2S) {
 
1591
    register uchar *    dmapU2S=cd->cnv_dmap->dmapU2S;
 
1592
    register int        inLen=*inBytesLeft;
 
1593
    register char *     pOut=*outBuf;
 
1594
    register char *     pIn=*inBuf;
 
1595
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
1596
    register char       subS=cd->subS;
 
1597
    register size_t     numS=0;
 
1598
    while (0 < inLen) {
 
1599
      register uint32_t       in;
 
1600
      if (inLen == 1) {
 
1601
        errno=EINVAL;   /* 22 */
 
1602
 
 
1603
        *inBytesLeft=inLen-1;
 
1604
        *outBytesLeft-=(pOut-*outBuf);
 
1605
        *outBuf=pOut;
 
1606
        *inBuf=pIn;
 
1607
        ++numS;
 
1608
        *numSub+=numS;
 
1609
        return 0;
 
1610
      }
 
1611
      if (pLastOutBuf < pOut)
 
1612
        break;
 
1613
      in=pIn[0];
 
1614
      in<<=8;
 
1615
      in+=pIn[1];
 
1616
      if (in == 0x0000) {
 
1617
        *pOut=0x00;
 
1618
 
 
1619
      } else if (0xD800 <= in && in <=  0xDFFF) {     /* 0xD800-0xDFFF, surrogate first and second values */
 
1620
        if (0xDC00 <= in ) {
 
1621
          errno=EINVAL;   /* 22 */
 
1622
          *inBytesLeft=inLen-1;
 
1623
          *outBytesLeft-=(pOut-*outBuf);
 
1624
          *outBuf=pOut;
 
1625
          *inBuf=pIn;
 
1626
          return -1;
 
1627
          
 
1628
        } else if (inLen < 4) {
 
1629
          errno=EINVAL;   /* 22 */
 
1630
          *inBytesLeft=inLen-2;
 
1631
          *outBytesLeft-=(pOut-*outBuf);
 
1632
          *outBuf=pOut;
 
1633
          *inBuf=pIn+2;
 
1634
          return -1;
 
1635
          
 
1636
        } else {
 
1637
          register uint32_t       in2;
 
1638
          in2=pIn[2];
 
1639
          in2<<=8;
 
1640
          in2+=pIn[3];
 
1641
          if (0xDC00 <= in2 && in2 <= 0xDFFF) {   /* second surrogate character =0xDC00 - 0xDFFF*/
 
1642
            *pOut=subS;
 
1643
            ++numS;
 
1644
            pIn+=4;
 
1645
          } else {
 
1646
            errno=EINVAL;   /* 22 */
 
1647
            *inBytesLeft=inLen-1;
 
1648
            *outBytesLeft-=(pOut-*outBuf);
 
1649
            *outBuf=pOut;
 
1650
            *inBuf=pIn;
 
1651
            return -1;
 
1652
          }
 
1653
        }
 
1654
      } else {
 
1655
        if ((*pOut=dmapU2S[in]) == 0x00) {
 
1656
          *pOut=subS;
 
1657
          ++numS;
 
1658
          errno=EINVAL;  /* 22 */
 
1659
        } else if (*pOut == subS) {
 
1660
          if (in != cd->srcSubS)
 
1661
            ++numS;
 
1662
        }
 
1663
      }
 
1664
      ++pOut;
 
1665
      pIn+=2;
 
1666
      inLen-=2;
 
1667
    }
 
1668
    *outBytesLeft-=(pOut-*outBuf);
 
1669
    *inBytesLeft=inLen;
 
1670
    *outBuf=pOut;
 
1671
    *inBuf=pIn;
 
1672
    *numSub+=numS;
 
1673
    return 0;
 
1674
 
 
1675
  } else if (cd->cnv_dmap->codingSchema == DMAP_82S) {
 
1676
    register uchar *    dmapU2S=cd->cnv_dmap->dmapU2S;
 
1677
    register int        inLen=*inBytesLeft;
 
1678
    register char *     pOut=*outBuf;
 
1679
    register char *     pIn=*inBuf;
 
1680
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
1681
    register char       subS=cd->subS;
 
1682
    register size_t     numS=0;
 
1683
    while (0 < inLen) {
 
1684
      register uint32_t         in;
 
1685
      uint32_t                  in2;  /* The second surrogate value */
 
1686
      if (pLastOutBuf < pOut)
 
1687
        break;
 
1688
      /* convert from UTF-8 to UCS-2 */
 
1689
      if (*pIn == 0x00) {
 
1690
        in=0x0000;
 
1691
        ++pIn;
 
1692
        --inLen;
 
1693
      } else {                          /* 82U: */
 
1694
        register uchar byte1=*pIn;
 
1695
        if ((byte1 & 0x80) == 0x00) {         /* if (byte1 & 0b10000000 == 0b00000000) { */
 
1696
          /* 1 bytes sequence:  0xxxxxxx => 00000000 0xxxxxxx*/
 
1697
          in=byte1;
 
1698
          ++pIn;
 
1699
          --inLen;
 
1700
        } else if ((byte1 & 0xE0) == 0xC0) {  /* (byte1 & 0b11100000 == 0b11000000) { */
 
1701
          if (inLen < 2) {
 
1702
            errno=EINVAL;  /* 22 */
 
1703
            *outBytesLeft-=(pOut-*outBuf);
 
1704
            *inBytesLeft=inLen;
 
1705
            *outBuf=pOut;
 
1706
            *inBuf=pIn;
 
1707
            *numSub+=numS;
 
1708
            return -1;
 
1709
          }
 
1710
          if (byte1 == 0xC0 || byte1 == 0xC1) {  /* invalid sequence */
 
1711
            errno=EILSEQ;  /* 116 */
 
1712
            *outBytesLeft-=(pOut-*outBuf);
 
1713
            *inBytesLeft=inLen;
 
1714
            *outBuf=pOut;
 
1715
            *inBuf=pIn;
 
1716
            *numSub+=numS;
 
1717
            return -1;
 
1718
          }
 
1719
          /* 2 bytes sequence: 
 
1720
             110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */
 
1721
          register uchar byte2;
 
1722
          ++pIn;
 
1723
          byte2=*pIn;
 
1724
          if ((byte2 & 0xC0) == 0x80) {       /* byte2 & 0b11000000 == 0b10000000) { */
 
1725
            register uchar work=byte1;
 
1726
            work<<=6;
 
1727
            byte2&=0x3F;      /* 0b00111111; */
 
1728
            byte2|=work;
 
1729
              
 
1730
            byte1&=0x1F;      /* 0b00011111; */
 
1731
            byte1>>=2;
 
1732
            in=byte1;
 
1733
            in<<=8;
 
1734
            in+=byte2;
 
1735
            inLen-=2;
 
1736
            ++pIn;
 
1737
          } else { /* invalid sequence */
 
1738
            errno=EILSEQ;  /* 116 */
 
1739
            *outBytesLeft-=(pOut-*outBuf);
 
1740
            *inBytesLeft=inLen;
 
1741
            *outBuf=pOut;
 
1742
            *inBuf=pIn-1;
 
1743
            *numSub+=numS;
 
1744
            return -1;
 
1745
          }
 
1746
        } else if ((byte1 & 0xF0) == 0xE0) {    /* byte1 & 0b11110000 == 0b11100000 */
 
1747
          /* 3 bytes sequence: 
 
1748
             1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */
 
1749
          register uchar byte2;
 
1750
          register uchar byte3;
 
1751
          if (inLen < 3) {
 
1752
            if (inLen == 2 && (pIn[1]  & 0xC0) != 0x80)
 
1753
              errno=EILSEQ;  /* 116 */
 
1754
            else
 
1755
              errno=EINVAL;  /* 22 */
 
1756
            *outBytesLeft-=(pOut-*outBuf);
 
1757
            *inBytesLeft=inLen;
 
1758
            *outBuf=pOut;
 
1759
            *inBuf=pIn;
 
1760
            *numSub+=numS;
 
1761
            return -1;
 
1762
          }
 
1763
          ++pIn;
 
1764
          byte2=*pIn;
 
1765
          ++pIn;
 
1766
          byte3=*pIn;
 
1767
          if ((byte2 & 0xC0) != 0x80 ||
 
1768
              (byte3 & 0xC0) != 0x80 ||
 
1769
              (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */
 
1770
            errno=EILSEQ;  /* 116 */
 
1771
            *outBytesLeft-=(pOut-*outBuf);
 
1772
            *inBytesLeft=inLen;
 
1773
            *outBuf=pOut;
 
1774
            *inBuf=pIn-2;
 
1775
            *numSub+=numS;
 
1776
            return -1;
 
1777
          }
 
1778
          {
 
1779
            register uchar work=byte2;
 
1780
            work<<=6;
 
1781
            byte3&=0x3F;      /* 0b00111111; */
 
1782
            byte3|=work;
 
1783
              
 
1784
            byte2&=0x3F;      /* 0b00111111; */
 
1785
            byte2>>=2;
 
1786
 
 
1787
            byte1<<=4;
 
1788
            in=byte1 | byte2;;
 
1789
            in<<=8;
 
1790
            in+=byte3;
 
1791
            inLen-=3;
 
1792
            ++pIn;
 
1793
          }
 
1794
        } else if ((0xF0 <= byte1 && byte1 <= 0xF4) ||    /* (bytes1 & 11111000) == 0x1110000 */
 
1795
                   ((byte1&=0xF7) && 0xF0 <= byte1 && byte1 <= 0xF4)) { /* minic iconv() behavior */
 
1796
          /* 4 bytes sequence
 
1797
             11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx
 
1798
             where uuuuu = wwww + 1 */
 
1799
          register uchar byte2;
 
1800
          register uchar byte3;
 
1801
          register uchar byte4;
 
1802
          if (inLen < 4) {
 
1803
            if ((inLen >= 2 && (pIn[1]  & 0xC0) != 0x80) ||
 
1804
                (inLen >= 3 && (pIn[2]  & 0xC0) != 0x80) ||
 
1805
                (cd->toCcsid == 13488) )
 
1806
              errno=EILSEQ;  /* 116 */
 
1807
            else
 
1808
              errno=EINVAL;  /* 22 */
 
1809
            *outBytesLeft-=(pOut-*outBuf);
 
1810
            *inBytesLeft=inLen;
 
1811
            *outBuf=pOut;
 
1812
            *inBuf=pIn;
 
1813
            *numSub+=numS;
 
1814
            return -1;
 
1815
          }
 
1816
          ++pIn;
 
1817
          byte2=*pIn;
 
1818
          ++pIn;
 
1819
          byte3=*pIn;
 
1820
          ++pIn;
 
1821
          byte4=*pIn;
 
1822
          if ((byte2 & 0xC0) == 0x80 &&         /* byte2 & 0b11000000 == 0b10000000 */
 
1823
              (byte3 & 0xC0) == 0x80 &&         /* byte3 & 0b11000000 == 0b10000000 */
 
1824
              (byte4 & 0xC0) == 0x80) {         /* byte4 & 0b11000000 == 0b10000000 */
 
1825
            register uchar work=byte2;
 
1826
            if (byte1 == 0xF0 && byte2 < 0x90) {
 
1827
              errno=EILSEQ;  /* 116 */
 
1828
              *outBytesLeft-=(pOut-*outBuf);
 
1829
              *inBytesLeft=inLen;
 
1830
              *outBuf=pOut;
 
1831
              *inBuf=pIn-3;
 
1832
              *numSub+=numS;
 
1833
              return -1;
 
1834
              /* iconv() returns 0 for 0xF4908080 and convert to 0x00 
 
1835
            } else if (byte1 == 0xF4 && byte2 > 0x8F) {
 
1836
              errno=EINVAL;
 
1837
              *outBytesLeft-=(pOut-*outBuf);
 
1838
              *inBytesLeft=inLen;
 
1839
              *outBuf=pOut;
 
1840
              *inBuf=pIn-3;
 
1841
              *numSub+=numS;
 
1842
              return -1;
 
1843
              */
 
1844
            }
 
1845
 
 
1846
            work&=0x30;       /* 0b00110000; */
 
1847
            work>>=4;
 
1848
            byte1&=0x07;      /* 0b00000111; */
 
1849
            byte1<<=2;
 
1850
            byte1+=work;      /* uuuuu */
 
1851
            --byte1;          /* wwww  */
 
1852
 
 
1853
            work=byte1 & 0x0F;
 
1854
            work>>=2;
 
1855
            work+=0xD8;       /* 0b11011011; */
 
1856
            in=work;
 
1857
            in<<=8;
 
1858
 
 
1859
            byte1<<=6;
 
1860
            byte2<<=2;
 
1861
            byte2&=0x3C;      /* 0b00111100; */
 
1862
            work=byte3;
 
1863
            work>>=4;
 
1864
            work&=0x03;       /* 0b00000011; */
 
1865
            work|=byte1;
 
1866
            work|=byte2;
 
1867
            in+=work;
 
1868
 
 
1869
            work=byte3;
 
1870
            work>>=2;
 
1871
            work&=0x03;       /* 0b00000011; */
 
1872
            work|=0xDC;       /* 0b110111xx; */
 
1873
            in2=work;
 
1874
            in2<<=8;
 
1875
 
 
1876
            byte3<<=6;
 
1877
            byte4&=0x3F;      /* 0b00111111; */
 
1878
            byte4|=byte3;
 
1879
            in2+=byte4;
 
1880
            inLen-=4;
 
1881
            ++pIn;
 
1882
          } else { /* invalid sequence */
 
1883
            errno=EILSEQ;  /* 116 */
 
1884
            *outBytesLeft-=(pOut-*outBuf);
 
1885
            *inBytesLeft=inLen;
 
1886
            *outBuf=pOut;
 
1887
            *inBuf=pIn-3;
 
1888
            *numSub+=numS;
 
1889
            return -1;
 
1890
          }
 
1891
        } else if ((byte1 & 0xF0) == 0xF0) { /* minic iconv() behavior */
 
1892
          if (inLen < 4 ||
 
1893
              pIn[1] < 0x80 || 0xBF < pIn[1] ||
 
1894
              pIn[2] < 0x80 || 0xBF < pIn[2] ||
 
1895
              pIn[3] < 0x80 || 0xBF < pIn[3] ) {
 
1896
            if (inLen == 1)
 
1897
              errno=EINVAL;  /* 22 */
 
1898
            else if (inLen == 2 && (pIn[1]  & 0xC0) != 0x80)
 
1899
              errno=EILSEQ;  /* 116 */
 
1900
            else if (inLen == 3 && ((pIn[1]  & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80))
 
1901
              errno=EILSEQ;  /* 116 */
 
1902
            else if (inLen >= 4 && ((pIn[1]  & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80))
 
1903
              errno=EILSEQ;  /* 116 */
 
1904
            else
 
1905
              errno=EINVAL;  /* 22 */
 
1906
 
 
1907
            *outBytesLeft-=(pOut-*outBuf);
 
1908
            *inBytesLeft=inLen;
 
1909
            *outBuf=pOut;
 
1910
            *inBuf=pIn;
 
1911
            *numSub+=numS;
 
1912
            return -1;
 
1913
          } else {
 
1914
            *pOut=subS;   /* Though returns replacement character, which iconv() does not return. */
 
1915
            ++pOut;
 
1916
            ++numS;
 
1917
            pIn+=4;
 
1918
            inLen-=4;
 
1919
            /* UTF-8_IBM-850 0xF0908080 : converted value does not match, iconv=0x00, dmap=0x7F
 
1920
               UTF-8_IBM-850 0xF0908081 : converted value does not match, iconv=0x01, dmap=0x7F
 
1921
               UTF-8_IBM-850 0xF0908082 : converted value does not match, iconv=0x02, dmap=0x7F
 
1922
               UTF-8_IBM-850 0xF0908083 : converted value does not match, iconv=0x03, dmap=0x7F 
 
1923
               ....
 
1924
               UTF-8_IBM-850 0xF09081BE : converted value does not match, iconv=0x7E, dmap=0x7F
 
1925
               UTF-8_IBM-850 0xF09081BF : converted value does not match, iconv=0x1C, dmap=0x7F
 
1926
               UTF-8_IBM-850 0xF09082A0 : converted value does not match, iconv=0xFF, dmap=0x7F
 
1927
               UTF-8_IBM-850 0xF09082A1 : converted value does not match, iconv=0xAD, dmap=0x7F
 
1928
               ....
 
1929
            */
 
1930
            continue;
 
1931
            /* iconv() returns 0 with strange 1 byte converted values */
 
1932
          }
 
1933
 
 
1934
        } else { /* invalid sequence */
 
1935
          errno=EILSEQ;  /* 116 */
 
1936
          *outBytesLeft-=(pOut-*outBuf);
 
1937
          *inBytesLeft=inLen;
 
1938
          *outBuf=pOut;
 
1939
          *inBuf=pIn;
 
1940
          *numSub+=numS;
 
1941
          return -1;
 
1942
        }
 
1943
      }
 
1944
      /* end of UTF-8 to UCS-2 */
 
1945
      if (in == 0x0000) {
 
1946
        *pOut=0x00;
 
1947
      } else {
 
1948
        if ((*pOut=dmapU2S[in]) == 0x00) {
 
1949
          *pOut=subS;
 
1950
          ++numS;
 
1951
          errno=EINVAL;  /* 22 */
 
1952
        } else if (*pOut == subS) {
 
1953
          if (in != cd->srcSubS) {
 
1954
            ++numS;
 
1955
          }
 
1956
        }
 
1957
      }
 
1958
      ++pOut;
 
1959
    }
 
1960
    *outBytesLeft-=(pOut-*outBuf);
 
1961
    *inBytesLeft=inLen;
 
1962
    *outBuf=pOut;
 
1963
    *inBuf=pIn;
 
1964
    *numSub+=numS;
 
1965
    return 0;
 
1966
 
 
1967
  } else if (cd->cnv_dmap->codingSchema == DMAP_D2U) {
 
1968
    /* use uchar * instead of UniChar to avoid memcpy */
 
1969
    register uchar *    dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U);
 
1970
    register uchar *    dmapD22U=(uchar *) (cd->cnv_dmap->dmapD22U);
 
1971
    register int        inLen=*inBytesLeft;
 
1972
    register char *     pOut=*outBuf;
 
1973
    register char *     pIn=*inBuf;
 
1974
    register int        offset;
 
1975
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
1976
    register size_t   numS=0;
 
1977
    while (0 < inLen) {
 
1978
      if (pLastOutBuf < pOut)
 
1979
        break;
 
1980
      if (*pIn == 0x00) {
 
1981
        *pOut=0x00;
 
1982
        ++pOut;
 
1983
        *pOut=0x00;
 
1984
        ++pOut;
 
1985
        ++pIn;
 
1986
        --inLen;
 
1987
      } else {
 
1988
        offset=*pIn;
 
1989
        offset<<=1;
 
1990
        if (dmapD12U[offset]   == 0x00 &&
 
1991
            dmapD12U[offset+1] == 0x00) {         /* DBCS */
 
1992
          if (inLen < 2) {
 
1993
            if (*pIn == 0x80 || *pIn == 0xFF ||
 
1994
                (cd->fromCcsid == 943 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0xA0 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xEF || *pIn == 0xFD || *pIn == 0xFE)) ||
 
1995
                (cd->fromCcsid == 932 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0x87 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xED || *pIn == 0xEE || *pIn == 0xEF)) ||
 
1996
                (cd->fromCcsid == 1381 && ((0x85 <= *pIn && *pIn <= 0x8B) || (0xAA <= *pIn && *pIn <= 0xAF) || (0xF8 <= *pIn && *pIn <= 0xFE))))
 
1997
              errno=EILSEQ;  /* 116 */
 
1998
            else
 
1999
              errno=EINVAL;  /* 22 */
 
2000
            *outBytesLeft-=(pOut-*outBuf);
 
2001
            *inBytesLeft=inLen;
 
2002
            *outBuf=pOut;
 
2003
            *inBuf=pIn;
 
2004
            return -1;
 
2005
          }
 
2006
          offset-=0x100;
 
2007
          ++pIn;
 
2008
          offset<<=8;
 
2009
          offset+=(*pIn * 2);
 
2010
          if (dmapD22U[offset] == 0x00 &&
 
2011
              dmapD22U[offset+1] == 0x00) {
 
2012
            errno=EILSEQ;  /* 116 */
 
2013
            *outBytesLeft-=(pOut-*outBuf);
 
2014
            *inBytesLeft=inLen;
 
2015
            *outBuf=pOut;
 
2016
            *inBuf=pIn-1;
 
2017
            return -1;
 
2018
          }
 
2019
          *pOut=dmapD22U[offset];
 
2020
          ++pOut;
 
2021
          *pOut=dmapD22U[offset+1];
 
2022
          ++pOut;
 
2023
          if (dmapD22U[offset] == 0xFF &&
 
2024
              dmapD22U[offset+1] == 0xFD) {
 
2025
            if (pIn[-1] * 0x100 + pIn[0] != cd->srcSubD)
 
2026
              ++numS;
 
2027
          }
 
2028
          ++pIn;
 
2029
          inLen-=2;
 
2030
        } else {  /* SBCS */
 
2031
          *pOut=dmapD12U[offset];
 
2032
          ++pOut;
 
2033
          *pOut=dmapD12U[offset+1];
 
2034
          ++pOut;
 
2035
          if (dmapD12U[offset]   == 0x00 &&
 
2036
              dmapD12U[offset+1] == 0x1A) {
 
2037
            if (*pIn != cd->srcSubS)
 
2038
              ++numS;
 
2039
          }
 
2040
          ++pIn;
 
2041
          --inLen;
 
2042
        }
 
2043
      }
 
2044
    }
 
2045
    *outBytesLeft-=(pOut-*outBuf);
 
2046
    *inBytesLeft=inLen;
 
2047
    *outBuf=pOut;
 
2048
    *inBuf=pIn;
 
2049
    *numSub+=numS;
 
2050
    return 0;
 
2051
 
 
2052
  } else if (cd->cnv_dmap->codingSchema == DMAP_D28) {
 
2053
    /* use uchar * instead of UniChar to avoid memcpy */
 
2054
    register uchar *    dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U);
 
2055
    register uchar *    dmapD22U=(uchar *) (cd->cnv_dmap->dmapD22U);
 
2056
    register int        inLen=*inBytesLeft;
 
2057
    register char *     pOut=*outBuf;
 
2058
    register char *     pIn=*inBuf;
 
2059
    register int        offset;
 
2060
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
2061
    register size_t     numS=0;
 
2062
    register UniChar    in;     /* copy part of U28 */
 
2063
    register UniChar    ucs2;
 
2064
    while (0 < inLen) {
 
2065
      if (pLastOutBuf < pOut)
 
2066
        break;
 
2067
      if (*pIn == 0x00) {
 
2068
        *pOut=0x00;
 
2069
        ++pOut;
 
2070
        ++pIn;
 
2071
        --inLen;
 
2072
      } else {
 
2073
        offset=*pIn;
 
2074
        offset<<=1;
 
2075
        if (dmapD12U[offset]   == 0x00 &&
 
2076
            dmapD12U[offset+1] == 0x00) {         /* DBCS */
 
2077
          if (inLen < 2) {
 
2078
            if (*pIn == 0x80 || *pIn == 0xFF ||
 
2079
                (cd->fromCcsid == 943 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0xA0 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xEF || *pIn == 0xFD || *pIn == 0xFE)) ||
 
2080
                (cd->fromCcsid == 932 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0x87 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xED || *pIn == 0xEE || *pIn == 0xEF)) ||
 
2081
                (cd->fromCcsid == 1381 && ((0x85 <= *pIn && *pIn <= 0x8B) || (0xAA <= *pIn && *pIn <= 0xAF) || (0xF8 <= *pIn && *pIn <= 0xFE))))
 
2082
              errno=EILSEQ;  /* 116 */
 
2083
            else
 
2084
              errno=EINVAL;  /* 22 */
 
2085
            *outBytesLeft-=(pOut-*outBuf);
 
2086
            *inBytesLeft=inLen;
 
2087
            *outBuf=pOut;
 
2088
            *inBuf=pIn;
 
2089
            return -1;
 
2090
          }
 
2091
          offset-=0x100;
 
2092
          ++pIn;
 
2093
          offset<<=8;
 
2094
          offset+=(*pIn * 2);
 
2095
          if (dmapD22U[offset] == 0x00 &&
 
2096
              dmapD22U[offset+1] == 0x00) {
 
2097
            errno=EILSEQ;  /* 116 */
 
2098
            *outBytesLeft-=(pOut-*outBuf);
 
2099
            *inBytesLeft=inLen;
 
2100
            *outBuf=pOut;
 
2101
            *inBuf=pIn-1;
 
2102
            return -1;
 
2103
          }
 
2104
          in=dmapD22U[offset];
 
2105
          in<<=8;
 
2106
          in+=dmapD22U[offset+1];
 
2107
          ucs2=in;
 
2108
          if (dmapD22U[offset] == 0xFF &&
 
2109
              dmapD22U[offset+1] == 0xFD) {
 
2110
            if (in != cd->srcSubD)
 
2111
              ++numS;
 
2112
          }
 
2113
          ++pIn;
 
2114
          inLen-=2;
 
2115
        } else {  /* SBCS */
 
2116
          in=dmapD12U[offset];
 
2117
          in<<=8;
 
2118
          in+=dmapD12U[offset+1];
 
2119
          ucs2=in;
 
2120
          if (dmapD12U[offset]   == 0x00 &&
 
2121
              dmapD12U[offset+1] == 0x1A) {
 
2122
            if (in != cd->srcSubS)
 
2123
              ++numS;
 
2124
          }
 
2125
          ++pIn;
 
2126
          --inLen;
 
2127
        }
 
2128
        if ((in & 0xFF80) == 0x0000) {     /* U28: in & 0b1111111110000000 == 0x0000 */
 
2129
          *pOut=in;
 
2130
          ++pOut;
 
2131
        } else if ((in & 0xF800) == 0x0000) {     /* in & 0b1111100000000000 == 0x0000 */
 
2132
          register uchar        byte;
 
2133
          in>>=6;
 
2134
          in&=0x001F;   /* 0b0000000000011111 */
 
2135
          in|=0x00C0;   /* 0b0000000011000000 */
 
2136
          *pOut=in;
 
2137
          ++pOut;
 
2138
          byte=ucs2;    /* dmapD12U[offset+1]; */
 
2139
          byte&=0x3F;   /* 0b00111111; */
 
2140
          byte|=0x80;   /* 0b10000000; */
 
2141
          *pOut=byte;
 
2142
          ++pOut;
 
2143
        } else if ((in & 0xFC00) == 0xD800) {    /* There should not be no surrogate character in SBCS. */
 
2144
          *pOut=0xEF;
 
2145
          ++pOut;
 
2146
          *pOut=0xBF;
 
2147
          ++pOut;
 
2148
          *pOut=0xBD;
 
2149
          ++pOut;
 
2150
        } else {
 
2151
          register uchar        byte;
 
2152
          register uchar        work;
 
2153
          byte=(ucs2>>8);    /* dmapD12U[offset]; */
 
2154
          byte>>=4;
 
2155
          byte|=0xE0;   /* 0b11100000; */
 
2156
          *pOut=byte;
 
2157
          ++pOut;
 
2158
 
 
2159
          byte=(ucs2>>8);    /* dmapD12U[offset]; */
 
2160
          byte<<=2;
 
2161
          work=ucs2;    /* dmapD12U[offset+1]; */
 
2162
          work>>=6;
 
2163
          byte|=work;
 
2164
          byte&=0x3F;   /* 0b00111111; */
 
2165
          byte|=0x80;   /* 0b10000000; */
 
2166
          *pOut=byte;
 
2167
          ++pOut;
 
2168
 
 
2169
          byte=ucs2;    /* dmapD12U[offset+1]; */
 
2170
          byte&=0x3F;   /* 0b00111111; */
 
2171
          byte|=0x80;   /* 0b10000000; */
 
2172
          *pOut=byte;
 
2173
          ++pOut;
 
2174
        }
 
2175
        /* end of U28 */
 
2176
      }
 
2177
    }
 
2178
    *outBytesLeft-=(pOut-*outBuf);
 
2179
    *inBytesLeft=inLen;
 
2180
    *outBuf=pOut;
 
2181
    *inBuf=pIn;
 
2182
    *numSub+=numS;
 
2183
    return 0;
 
2184
 
 
2185
  } else if (cd->cnv_dmap->codingSchema == DMAP_U2D) {
 
2186
    register uchar *    dmapU2D=cd->cnv_dmap->dmapU2D;
 
2187
    register int        inLen=*inBytesLeft;
 
2188
    register char *     pOut=*outBuf;
 
2189
    register char *     pIn=*inBuf;
 
2190
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
2191
    register char       subS=cd->subS;
 
2192
    register char *     pSubD=(char *) &(cd->subD);
 
2193
    register size_t     numS=0;
 
2194
    while (0 < inLen) {
 
2195
      register uint32_t       in;
 
2196
      if (inLen == 1) {
 
2197
        errno=EINVAL;   /* 22 */
 
2198
 
 
2199
        *inBytesLeft=inLen;
 
2200
        *outBytesLeft-=(pOut-*outBuf);
 
2201
        *outBuf=pOut;
 
2202
        *inBuf=pIn;
 
2203
        return -1;
 
2204
      }
 
2205
      if (pLastOutBuf < pOut)
 
2206
        break;
 
2207
      in=pIn[0];
 
2208
      in<<=8;
 
2209
      in+=pIn[1];
 
2210
      if (in == 0x0000) {
 
2211
        *pOut=0x00;
 
2212
        ++pOut;
 
2213
      } else {
 
2214
        in<<=1;
 
2215
        *pOut=dmapU2D[in];
 
2216
        ++pOut;
 
2217
        if (dmapU2D[in+1] == 0x00) {   /* SBCS */
 
2218
          if (*pOut == subS) {
 
2219
            if (in != cd->srcSubS)
 
2220
              ++numS;
 
2221
          }
 
2222
        } else {
 
2223
          *pOut=dmapU2D[in+1];
 
2224
          ++pOut;
 
2225
          if (dmapU2D[in]   == pSubD[0] &&
 
2226
              dmapU2D[in+1] == pSubD[1]) {
 
2227
            in>>=1;
 
2228
            if (in != cd->srcSubD)
 
2229
              ++numS;
 
2230
          }
 
2231
        }
 
2232
      }
 
2233
      pIn+=2;
 
2234
      inLen-=2;
 
2235
    }
 
2236
    *outBytesLeft-=(pOut-*outBuf);
 
2237
    *inBytesLeft=inLen;
 
2238
    *outBuf=pOut;
 
2239
    *inBuf=pIn;
 
2240
    *numSub+=numS;
 
2241
    return numS;        /* to minic iconv() behavior */
 
2242
 
 
2243
  } else if (cd->cnv_dmap->codingSchema == DMAP_T2D) {
 
2244
    register uchar *    dmapU2D=cd->cnv_dmap->dmapU2D;
 
2245
    register int        inLen=*inBytesLeft;
 
2246
    register char *     pOut=*outBuf;
 
2247
    register char *     pIn=*inBuf;
 
2248
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
2249
    register char       subS=cd->subS;
 
2250
    register char *     pSubD=(char *) &(cd->subD);
 
2251
    register size_t     numS=0;
 
2252
    while (0 < inLen) {
 
2253
      register uint32_t       in;
 
2254
      if (inLen == 1) {
 
2255
        errno=EINVAL;  /* 22 */
 
2256
        *inBytesLeft=inLen-1;
 
2257
        *outBytesLeft-=(pOut-*outBuf);
 
2258
        *outBuf=pOut;
 
2259
        *inBuf=pIn;
 
2260
        ++numS;
 
2261
        *numSub+=numS;
 
2262
        return 0;
 
2263
      }
 
2264
      if (pLastOutBuf < pOut)
 
2265
        break;
 
2266
      in=pIn[0];
 
2267
      in<<=8;
 
2268
      in+=pIn[1];
 
2269
      if (in == 0x0000) {
 
2270
        *pOut=0x00;
 
2271
        ++pOut;
 
2272
      } else if (0xD800 <= in && in <= 0xDBFF) { /* first byte of surrogate */
 
2273
        errno=EINVAL;   /* 22 */
 
2274
        *inBytesLeft=inLen-2;
 
2275
        *outBytesLeft-=(pOut-*outBuf);
 
2276
        *outBuf=pOut;
 
2277
        *inBuf=pIn+2;
 
2278
        ++numS;
 
2279
        *numSub+=numS;
 
2280
        return -1;
 
2281
        
 
2282
      } else if (0xDC00 <= in && in <= 0xDFFF) { /* second byte of surrogate */
 
2283
        errno=EINVAL;   /* 22 */
 
2284
        *inBytesLeft=inLen-1;
 
2285
        *outBytesLeft-=(pOut-*outBuf);
 
2286
        *outBuf=pOut;
 
2287
        *inBuf=pIn;
 
2288
        ++numS;
 
2289
        *numSub+=numS;
 
2290
        return -1;
 
2291
        
 
2292
      } else {
 
2293
        in<<=1;
 
2294
        *pOut=dmapU2D[in];
 
2295
        ++pOut;
 
2296
        if (dmapU2D[in+1] == 0x00) {   /* SBCS */
 
2297
          if (*pOut == subS) {
 
2298
            if (in != cd->srcSubS)
 
2299
              ++numS;
 
2300
          }
 
2301
        } else {
 
2302
          *pOut=dmapU2D[in+1];
 
2303
          ++pOut;
 
2304
          if (dmapU2D[in]   == pSubD[0] &&
 
2305
              dmapU2D[in+1] == pSubD[1]) {
 
2306
            in>>=1;
 
2307
            if (in != cd->srcSubD)
 
2308
              ++numS;
 
2309
          }
 
2310
        }
 
2311
      }
 
2312
      pIn+=2;
 
2313
      inLen-=2;
 
2314
    }
 
2315
    *outBytesLeft-=(pOut-*outBuf);
 
2316
    *inBytesLeft=inLen;
 
2317
    *outBuf=pOut;
 
2318
    *inBuf=pIn;
 
2319
    *numSub+=numS;
 
2320
    return 0;        /* to minic iconv() behavior */
 
2321
 
 
2322
  } else if (cd->cnv_dmap->codingSchema == DMAP_82D) {
 
2323
    register uchar *    dmapU2D=cd->cnv_dmap->dmapU2D;
 
2324
    register int        inLen=*inBytesLeft;
 
2325
    register char *     pOut=*outBuf;
 
2326
    register char *     pIn=*inBuf;
 
2327
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
2328
    register char       subS=cd->subS;
 
2329
    register char *     pSubD=(char *) &(cd->subD);
 
2330
    register size_t     numS=0;
 
2331
    while (0 < inLen) {
 
2332
      register uint32_t in;
 
2333
      uint32_t          in2;
 
2334
      if (pLastOutBuf < pOut)
 
2335
        break;
 
2336
      /* convert from UTF-8 to UCS-2 */
 
2337
      if (*pIn == 0x00) {
 
2338
        in=0x0000;
 
2339
        ++pIn;
 
2340
        --inLen;
 
2341
      } else {                          /* 82U: */
 
2342
        register uchar byte1=*pIn;
 
2343
        if ((byte1 & 0x80) == 0x00) {         /* if (byte1 & 0b10000000 == 0b00000000) { */
 
2344
          /* 1 bytes sequence:  0xxxxxxx => 00000000 0xxxxxxx*/
 
2345
          in=byte1;
 
2346
          ++pIn;
 
2347
          --inLen;
 
2348
        } else if ((byte1 & 0xE0) == 0xC0) {  /* (byte1 & 0b11100000 == 0b11000000) { */
 
2349
          if (inLen < 2) {
 
2350
            errno=EINVAL;  /* 22 */
 
2351
            *outBytesLeft-=(pOut-*outBuf);
 
2352
            *inBytesLeft=inLen;
 
2353
            *outBuf=pOut;
 
2354
            *inBuf=pIn;
 
2355
            *numSub+=numS;
 
2356
            return -1;
 
2357
          }
 
2358
          if (byte1 == 0xC0 || byte1 == 0xC1) {  /* invalid sequence */
 
2359
            errno=EILSEQ;  /* 116 */
 
2360
            *outBytesLeft-=(pOut-*outBuf);
 
2361
            *inBytesLeft=inLen;
 
2362
            *outBuf=pOut;
 
2363
            *inBuf=pIn;
 
2364
            *numSub+=numS;
 
2365
            return -1;
 
2366
          }
 
2367
          /* 2 bytes sequence: 
 
2368
             110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */
 
2369
          register uchar byte2;
 
2370
          ++pIn;
 
2371
          byte2=*pIn;
 
2372
          if ((byte2 & 0xC0) == 0x80) {       /* byte2 & 0b11000000 == 0b10000000) { */
 
2373
            register uchar work=byte1;
 
2374
            work<<=6;
 
2375
            byte2&=0x3F;      /* 0b00111111; */
 
2376
            byte2|=work;
 
2377
              
 
2378
            byte1&=0x1F;      /* 0b00011111; */
 
2379
            byte1>>=2;
 
2380
            in=byte1;
 
2381
            in<<=8;
 
2382
            in+=byte2;
 
2383
            inLen-=2;
 
2384
            ++pIn;
 
2385
          } else { /* invalid sequence */
 
2386
            errno=EILSEQ;  /* 116 */
 
2387
            *outBytesLeft-=(pOut-*outBuf);
 
2388
            *inBytesLeft=inLen;
 
2389
            *outBuf=pOut;
 
2390
            *inBuf=pIn-1;
 
2391
            *numSub+=numS;
 
2392
            return -1;
 
2393
          }
 
2394
        } else if ((byte1 & 0xF0) == 0xE0) {    /* byte1 & 0b11110000 == 0b11100000 */
 
2395
          /* 3 bytes sequence: 
 
2396
             1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */
 
2397
          register uchar byte2;
 
2398
          register uchar byte3;
 
2399
          if (inLen < 3) {
 
2400
            if (inLen == 2 && (pIn[1]  & 0xC0) != 0x80)
 
2401
              errno=EILSEQ;  /* 116 */
 
2402
            else
 
2403
              errno=EINVAL;  /* 22 */
 
2404
            *outBytesLeft-=(pOut-*outBuf);
 
2405
            *inBytesLeft=inLen;
 
2406
            *outBuf=pOut;
 
2407
            *inBuf=pIn;
 
2408
            *numSub+=numS;
 
2409
            return -1;
 
2410
          }
 
2411
          ++pIn;
 
2412
          byte2=*pIn;
 
2413
          ++pIn;
 
2414
          byte3=*pIn;
 
2415
          if ((byte2 & 0xC0) != 0x80 ||
 
2416
              (byte3 & 0xC0) != 0x80 ||
 
2417
              (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */
 
2418
            errno=EILSEQ;  /* 116 */
 
2419
            *outBytesLeft-=(pOut-*outBuf);
 
2420
            *inBytesLeft=inLen;
 
2421
            *outBuf=pOut;
 
2422
            *inBuf=pIn-2;
 
2423
            *numSub+=numS;
 
2424
            return -1;
 
2425
          }
 
2426
          {
 
2427
            register uchar work=byte2;
 
2428
            work<<=6;
 
2429
            byte3&=0x3F;      /* 0b00111111; */
 
2430
            byte3|=work;
 
2431
              
 
2432
            byte2&=0x3F;      /* 0b00111111; */
 
2433
            byte2>>=2;
 
2434
 
 
2435
            byte1<<=4;
 
2436
            in=byte1 | byte2;;
 
2437
            in<<=8;
 
2438
            in+=byte3;
 
2439
            inLen-=3;
 
2440
            ++pIn;
 
2441
          }
 
2442
        } else if ((0xF0 <= byte1 && byte1 <= 0xF4)) {    /* (bytes1 & 11111000) == 0x1110000 */
 
2443
          /* 4 bytes sequence
 
2444
             11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx
 
2445
             where uuuuu = wwww + 1 */
 
2446
          register uchar byte2;
 
2447
          register uchar byte3;
 
2448
          register uchar byte4;
 
2449
          if (inLen < 4) {
 
2450
            if ((inLen >= 2 && (pIn[1]  & 0xC0) != 0x80) ||
 
2451
                (inLen >= 3 && (pIn[2]  & 0xC0) != 0x80) ||
 
2452
                (cd->toCcsid == 13488) )
 
2453
              errno=EILSEQ;  /* 116 */
 
2454
            else
 
2455
              errno=EINVAL;  /* 22 */
 
2456
            *outBytesLeft-=(pOut-*outBuf);
 
2457
            *inBytesLeft=inLen;
 
2458
            *outBuf=pOut;
 
2459
            *inBuf=pIn;
 
2460
            *numSub+=numS;
 
2461
            return -1;
 
2462
          }
 
2463
          ++pIn;
 
2464
          byte2=*pIn;
 
2465
          ++pIn;
 
2466
          byte3=*pIn;
 
2467
          ++pIn;
 
2468
          byte4=*pIn;
 
2469
          if ((byte2 & 0xC0) == 0x80 &&         /* byte2 & 0b11000000 == 0b10000000 */
 
2470
              (byte3 & 0xC0) == 0x80 &&         /* byte3 & 0b11000000 == 0b10000000 */
 
2471
              (byte4 & 0xC0) == 0x80) {         /* byte4 & 0b11000000 == 0b10000000 */
 
2472
            register uchar work=byte2;
 
2473
            if (byte1 == 0xF0 && byte2 < 0x90) {
 
2474
              errno=EILSEQ;  /* 116 */
 
2475
              *outBytesLeft-=(pOut-*outBuf);
 
2476
              *inBytesLeft=inLen;
 
2477
              *outBuf=pOut;
 
2478
              *inBuf=pIn-3;
 
2479
              *numSub+=numS;
 
2480
              return -1;
 
2481
              /* iconv() returns 0 for 0xF4908080 and convert to 0x00 
 
2482
            } else if (byte1 == 0xF4 && byte2 > 0x8F) {
 
2483
              errno=EINVAL;
 
2484
              *outBytesLeft-=(pOut-*outBuf);
 
2485
              *inBytesLeft=inLen;
 
2486
              *outBuf=pOut;
 
2487
              *inBuf=pIn-3;
 
2488
              *numSub+=numS;
 
2489
              return -1;
 
2490
              */
 
2491
            }
 
2492
 
 
2493
            work&=0x30;       /* 0b00110000; */
 
2494
            work>>=4;
 
2495
            byte1&=0x07;      /* 0b00000111; */
 
2496
            byte1<<=2;
 
2497
            byte1+=work;      /* uuuuu */
 
2498
            --byte1;          /* wwww  */
 
2499
 
 
2500
            work=byte1 & 0x0F;
 
2501
            work>>=2;
 
2502
            work+=0xD8;       /* 0b11011011; */
 
2503
            in=work;
 
2504
            in<<=8;
 
2505
 
 
2506
            byte1<<=6;
 
2507
            byte2<<=2;
 
2508
            byte2&=0x3C;      /* 0b00111100; */
 
2509
            work=byte3;
 
2510
            work>>=4;
 
2511
            work&=0x03;       /* 0b00000011; */
 
2512
            work|=byte1;
 
2513
            work|=byte2;
 
2514
            in+=work;
 
2515
 
 
2516
            work=byte3;
 
2517
            work>>=2;
 
2518
            work&=0x03;       /* 0b00000011; */
 
2519
            work|=0xDC;       /* 0b110111xx; */
 
2520
            in2=work;
 
2521
            in2<<=8;
 
2522
 
 
2523
            byte3<<=6;
 
2524
            byte4&=0x3F;      /* 0b00111111; */
 
2525
            byte4|=byte3;
 
2526
            in2+=byte4;
 
2527
            inLen-=4;
 
2528
            ++pIn;
 
2529
#ifdef match_with_GBK
 
2530
            if ((0xD800 == in && in2 < 0xDC80) ||
 
2531
                (0xD840 == in && in2 < 0xDC80) ||
 
2532
                (0xD880 == in && in2 < 0xDC80) ||
 
2533
                (0xD8C0 == in && in2 < 0xDC80) ||
 
2534
                (0xD900 == in && in2 < 0xDC80) ||
 
2535
                (0xD940 == in && in2 < 0xDC80) ||
 
2536
                (0xD980 == in && in2 < 0xDC80) ||
 
2537
                (0xD9C0 == in && in2 < 0xDC80) ||
 
2538
                (0xDA00 == in && in2 < 0xDC80) ||
 
2539
                (0xDA40 == in && in2 < 0xDC80) ||
 
2540
                (0xDA80 == in && in2 < 0xDC80) ||
 
2541
                (0xDAC0 == in && in2 < 0xDC80) ||
 
2542
                (0xDB00 == in && in2 < 0xDC80) ||
 
2543
                (0xDB40 == in && in2 < 0xDC80) ||
 
2544
                (0xDB80 == in && in2 < 0xDC80) ||
 
2545
                (0xDBC0 == in && in2 < 0xDC80)) {
 
2546
#else
 
2547
              if ((0xD800 <= in  && in  <= 0xDBFF) &&
 
2548
                  (0xDC00 <= in2 && in2 <= 0xDFFF)) {
 
2549
#endif
 
2550
              *pOut=subS;
 
2551
              ++pOut;
 
2552
              ++numS;
 
2553
              continue;
 
2554
            }
 
2555
          } else { /* invalid sequence */
 
2556
            errno=EILSEQ;  /* 116 */
 
2557
            *outBytesLeft-=(pOut-*outBuf);
 
2558
            *inBytesLeft=inLen;
 
2559
            *outBuf=pOut;
 
2560
            *inBuf=pIn-3;
 
2561
            *numSub+=numS;
 
2562
            return -1;
 
2563
          }
 
2564
        } else if (0xF5 <= byte1 && byte1 <= 0xFF) { /* minic iconv() behavior */
 
2565
          if (inLen < 4 ||
 
2566
              (inLen >= 4 && byte1 == 0xF8 && pIn[1] < 0x90) ||
 
2567
              pIn[1] < 0x80 || 0xBF < pIn[1] ||
 
2568
              pIn[2] < 0x80 || 0xBF < pIn[2] ||
 
2569
              pIn[3] < 0x80 || 0xBF < pIn[3] ) {
 
2570
            if (inLen == 1)
 
2571
              errno=EINVAL;  /* 22 */
 
2572
            else if (inLen == 2 && (pIn[1]  & 0xC0) != 0x80)
 
2573
              errno=EILSEQ;  /* 116 */
 
2574
            else if (inLen == 3 && ((pIn[1]  & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80))
 
2575
              errno=EILSEQ;  /* 116 */
 
2576
            else if (inLen >= 4 && (byte1 == 0xF8 || (pIn[1]  & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80))
 
2577
              errno=EILSEQ;  /* 116 */
 
2578
            else
 
2579
              errno=EINVAL;  /* 22 */
 
2580
 
 
2581
            *outBytesLeft-=(pOut-*outBuf);
 
2582
            *inBytesLeft=inLen;
 
2583
            *outBuf=pOut;
 
2584
            *inBuf=pIn;
 
2585
            *numSub+=numS;
 
2586
            return -1;
 
2587
          } else if ((pIn[1] == 0x80 || pIn[1] == 0x90 || pIn[1] == 0xA0 || pIn[1] == 0xB0) && 
 
2588
                     pIn[2] < 0x82) {
 
2589
            *pOut=subS;   /* Though returns replacement character, which iconv() does not return. */
 
2590
            ++pOut;
 
2591
            ++numS;
 
2592
            pIn+=4;
 
2593
            inLen-=4;
 
2594
            continue;
 
2595
          } else {
 
2596
            *pOut=pSubD[0];   /* Though returns replacement character, which iconv() does not return. */
 
2597
            ++pOut;
 
2598
            *pOut=pSubD[1];
 
2599
            ++pOut;
 
2600
            ++numS;
 
2601
            pIn+=4;
 
2602
            inLen-=4;
 
2603
            continue;
 
2604
            /* iconv() returns 0 with strange 1 byte converted values */
 
2605
          }
 
2606
 
 
2607
        } else { /* invalid sequence */
 
2608
          errno=EILSEQ;  /* 116 */
 
2609
          *outBytesLeft-=(pOut-*outBuf);
 
2610
          *inBytesLeft=inLen;
 
2611
          *outBuf=pOut;
 
2612
          *inBuf=pIn;
 
2613
          *numSub+=numS;
 
2614
          return -1;
 
2615
        }
 
2616
      }
 
2617
      /* end of UTF-8 to UCS-2 */
 
2618
      if (in == 0x0000) {
 
2619
        *pOut=0x00;
 
2620
        ++pOut;
 
2621
      } else {
 
2622
        in<<=1;
 
2623
        *pOut=dmapU2D[in];
 
2624
        ++pOut;
 
2625
        if (dmapU2D[in+1] == 0x00) {   /* SBCS */
 
2626
          if (dmapU2D[in] == subS) {
 
2627
            in>>=1;
 
2628
            if (in != cd->srcSubS)
 
2629
              ++numS;
 
2630
          }
 
2631
        } else {
 
2632
          *pOut=dmapU2D[in+1];
 
2633
          ++pOut;
 
2634
          if (dmapU2D[in]   == pSubD[0] &&
 
2635
              dmapU2D[in+1] == pSubD[1]) {
 
2636
            in>>=1;
 
2637
            if (in != cd->srcSubD)
 
2638
              ++numS;
 
2639
          }
 
2640
        }
 
2641
      }
 
2642
    }
 
2643
    *outBytesLeft-=(pOut-*outBuf);
 
2644
    *inBytesLeft=inLen;
 
2645
    *outBuf=pOut;
 
2646
    *inBuf=pIn;
 
2647
    *numSub+=numS;
 
2648
    return 0;
 
2649
 
 
2650
  } else if (cd->cnv_dmap->codingSchema == DMAP_82U) {
 
2651
    /* See http://unicode.org/versions/corrigendum1.html */
 
2652
    /* convert from UTF-8 to UTF-16 can cover all conversion from UTF-8 to UCS-2 */
 
2653
    register int        inLen=*inBytesLeft;
 
2654
    register char *     pOut=*outBuf;
 
2655
    register char *     pIn=*inBuf;
 
2656
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
2657
    register size_t     numS=0;
 
2658
    while (0 < inLen) {
 
2659
      if (pLastOutBuf < pOut)
 
2660
        break;
 
2661
      if (*pIn == 0x00) {
 
2662
        *pOut=0x00;
 
2663
        ++pOut;
 
2664
        *pOut=0x00;
 
2665
        ++pOut;
 
2666
        ++pIn;
 
2667
        --inLen;
 
2668
      } else {                          /* 82U: */
 
2669
        register uchar byte1=*pIn;
 
2670
        if ((byte1 & 0x80) == 0x00) {         /* if (byte1 & 0b10000000 == 0b00000000) { */
 
2671
          /* 1 bytes sequence:  0xxxxxxx => 00000000 0xxxxxxx*/
 
2672
          *pOut=0x00;
 
2673
          ++pOut;
 
2674
          *pOut=byte1;
 
2675
          ++pOut;
 
2676
          ++pIn;
 
2677
          --inLen;
 
2678
        } else if ((byte1 & 0xE0) == 0xC0) {  /* (byte1 & 0b11100000 == 0b11000000) { */
 
2679
          if (inLen < 2) {
 
2680
            errno=EINVAL;  /* 22 */
 
2681
            *outBytesLeft-=(pOut-*outBuf);
 
2682
            *inBytesLeft=inLen;
 
2683
            *outBuf=pOut;
 
2684
            *inBuf=pIn;
 
2685
            *numSub+=numS;
 
2686
            return -1;
 
2687
          }
 
2688
          if (byte1 == 0xC0 || byte1 == 0xC1) {  /* invalid sequence */
 
2689
            errno=EILSEQ;  /* 116 */
 
2690
            *outBytesLeft-=(pOut-*outBuf);
 
2691
            *inBytesLeft=inLen;
 
2692
            *outBuf=pOut;
 
2693
            *inBuf=pIn;
 
2694
            *numSub+=numS;
 
2695
            return -1;
 
2696
          }
 
2697
          /* 2 bytes sequence: 
 
2698
             110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */
 
2699
          register uchar byte2;
 
2700
          ++pIn;
 
2701
          byte2=*pIn;
 
2702
          if ((byte2 & 0xC0) == 0x80) {       /* byte2 & 0b11000000 == 0b10000000) { */
 
2703
            register uchar work=byte1;
 
2704
            work<<=6;
 
2705
            byte2&=0x3F;      /* 0b00111111; */
 
2706
            byte2|=work;
 
2707
              
 
2708
            byte1&=0x1F;      /* 0b00011111; */
 
2709
            byte1>>=2;
 
2710
            *pOut=byte1;
 
2711
            ++pOut;
 
2712
            *pOut=byte2;
 
2713
            ++pOut;
 
2714
            inLen-=2;
 
2715
            ++pIn;
 
2716
          } else { /* invalid sequence */
 
2717
            errno=EILSEQ;  /* 116 */
 
2718
            *outBytesLeft-=(pOut-*outBuf);
 
2719
            *inBytesLeft=inLen;
 
2720
            *outBuf=pOut;
 
2721
            *inBuf=pIn-1;
 
2722
            *numSub+=numS;
 
2723
            return -1;
 
2724
          }
 
2725
        } else if ((byte1 & 0xF0) == 0xE0) {    /* byte1 & 0b11110000 == 0b11100000 */
 
2726
          /* 3 bytes sequence: 
 
2727
             1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */
 
2728
          register uchar byte2;
 
2729
          register uchar byte3;
 
2730
          if (inLen < 3) {
 
2731
            if (inLen == 2 && (pIn[1]  & 0xC0) != 0x80)
 
2732
              errno=EILSEQ;  /* 116 */
 
2733
            else
 
2734
              errno=EINVAL;  /* 22 */
 
2735
            *outBytesLeft-=(pOut-*outBuf);
 
2736
            *inBytesLeft=inLen;
 
2737
            *outBuf=pOut;
 
2738
            *inBuf=pIn;
 
2739
            *numSub+=numS;
 
2740
            return -1;
 
2741
          }
 
2742
          ++pIn;
 
2743
          byte2=*pIn;
 
2744
          ++pIn;
 
2745
          byte3=*pIn;
 
2746
          if ((byte2 & 0xC0) != 0x80 ||
 
2747
              (byte3 & 0xC0) != 0x80 ||
 
2748
              (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */
 
2749
            errno=EILSEQ;  /* 116 */
 
2750
            *outBytesLeft-=(pOut-*outBuf);
 
2751
            *inBytesLeft=inLen;
 
2752
            *outBuf=pOut;
 
2753
            *inBuf=pIn-2;
 
2754
            *numSub+=numS;
 
2755
            return -1;
 
2756
          }
 
2757
          {
 
2758
            register uchar work=byte2;
 
2759
            work<<=6;
 
2760
            byte3&=0x3F;      /* 0b00111111; */
 
2761
            byte3|=work;
 
2762
              
 
2763
            byte2&=0x3F;      /* 0b00111111; */
 
2764
            byte2>>=2;
 
2765
 
 
2766
            byte1<<=4;
 
2767
            *pOut=byte1 | byte2;;
 
2768
            ++pOut;
 
2769
            *pOut=byte3;
 
2770
            ++pOut;
 
2771
            inLen-=3;
 
2772
            ++pIn;
 
2773
          }
 
2774
        } else if ((0xF0 <= byte1 && byte1 <= 0xF4) ||    /* (bytes1 & 11111000) == 0x1110000 */
 
2775
                   ((byte1&=0xF7) && 0xF0 <= byte1 && byte1 <= 0xF4)) { /* minic iconv() behavior */
 
2776
          /* 4 bytes sequence
 
2777
             11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx
 
2778
             where uuuuu = wwww + 1 */
 
2779
          register uchar byte2;
 
2780
          register uchar byte3;
 
2781
          register uchar byte4;
 
2782
          if (inLen < 4 || cd->toCcsid == 13488) {
 
2783
            if ((inLen >= 2 && (pIn[1]  & 0xC0) != 0x80) ||
 
2784
                (inLen >= 3 && (pIn[2]  & 0xC0) != 0x80) ||
 
2785
                (cd->toCcsid == 13488) )
 
2786
              errno=EILSEQ;  /* 116 */
 
2787
            else
 
2788
              errno=EINVAL;  /* 22 */
 
2789
            *outBytesLeft-=(pOut-*outBuf);
 
2790
            *inBytesLeft=inLen;
 
2791
            *outBuf=pOut;
 
2792
            *inBuf=pIn;
 
2793
            *numSub+=numS;
 
2794
            return -1;
 
2795
          }
 
2796
          ++pIn;
 
2797
          byte2=*pIn;
 
2798
          ++pIn;
 
2799
          byte3=*pIn;
 
2800
          ++pIn;
 
2801
          byte4=*pIn;
 
2802
          if ((byte2 & 0xC0) == 0x80 &&         /* byte2 & 0b11000000 == 0b10000000 */
 
2803
              (byte3 & 0xC0) == 0x80 &&         /* byte3 & 0b11000000 == 0b10000000 */
 
2804
              (byte4 & 0xC0) == 0x80) {         /* byte4 & 0b11000000 == 0b10000000 */
 
2805
            register uchar work=byte2;
 
2806
            if (byte1 == 0xF0 && byte2 < 0x90) {
 
2807
              errno=EILSEQ;  /* 116 */
 
2808
              *outBytesLeft-=(pOut-*outBuf);
 
2809
              *inBytesLeft=inLen;
 
2810
              *outBuf=pOut;
 
2811
              *inBuf=pIn-3;
 
2812
              *numSub+=numS;
 
2813
              return -1;
 
2814
            } else if (byte1 == 0xF4 && byte2 > 0x8F) {
 
2815
              errno=EINVAL;  /* 22 */
 
2816
              *outBytesLeft-=(pOut-*outBuf);
 
2817
              *inBytesLeft=inLen;
 
2818
              *outBuf=pOut;
 
2819
              *inBuf=pIn-3;
 
2820
              *numSub+=numS;
 
2821
              return -1;
 
2822
            }
 
2823
 
 
2824
            work&=0x30;       /* 0b00110000; */
 
2825
            work>>=4;
 
2826
            byte1&=0x07;      /* 0b00000111; */
 
2827
            byte1<<=2;
 
2828
            byte1+=work;      /* uuuuu */
 
2829
            --byte1;          /* wwww  */
 
2830
 
 
2831
            work=byte1 & 0x0F;
 
2832
            work>>=2;
 
2833
            work+=0xD8;       /* 0b11011011; */
 
2834
            *pOut=work;
 
2835
            ++pOut;
 
2836
 
 
2837
            byte1<<=6;
 
2838
            byte2<<=2;
 
2839
            byte2&=0x3C;      /* 0b00111100; */
 
2840
            work=byte3;
 
2841
            work>>=4;
 
2842
            work&=0x03;       /* 0b00000011; */
 
2843
            work|=byte1;
 
2844
            work|=byte2;
 
2845
            *pOut=work;
 
2846
            ++pOut;
 
2847
 
 
2848
            work=byte3;
 
2849
            work>>=2;
 
2850
            work&=0x03;       /* 0b00000011; */
 
2851
            work|=0xDC;       /* 0b110111xx; */
 
2852
            *pOut=work;
 
2853
            ++pOut;
 
2854
 
 
2855
            byte3<<=6;
 
2856
            byte4&=0x3F;      /* 0b00111111; */
 
2857
            byte4|=byte3;
 
2858
            *pOut=byte4;
 
2859
            ++pOut;
 
2860
            inLen-=4;
 
2861
            ++pIn;
 
2862
          } else { /* invalid sequence */
 
2863
            errno=EILSEQ;  /* 116 */
 
2864
            *outBytesLeft-=(pOut-*outBuf);
 
2865
            *inBytesLeft=inLen;
 
2866
            *outBuf=pOut;
 
2867
            *inBuf=pIn-3;
 
2868
            *numSub+=numS;
 
2869
            return -1;
 
2870
          }
 
2871
        } else if ((byte1 & 0xF0) == 0xF0) {
 
2872
          if (cd->toCcsid == 13488) {
 
2873
            errno=EILSEQ;  /* 116 */
 
2874
          } else {
 
2875
            if (inLen == 1)
 
2876
              errno=EINVAL;  /* 22 */
 
2877
            else if (inLen == 2 && (pIn[1]  & 0xC0) != 0x80)
 
2878
              errno=EILSEQ;  /* 116 */
 
2879
            else if (inLen == 3 && ((pIn[1]  & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80))
 
2880
              errno=EILSEQ;  /* 116 */
 
2881
            else if (inLen >= 4 && ((pIn[1]  & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80))
 
2882
              errno=EILSEQ;  /* 116 */
 
2883
            else
 
2884
              errno=EINVAL;  /* 22 */
 
2885
          }
 
2886
          *outBytesLeft-=(pOut-*outBuf);
 
2887
          *inBytesLeft=inLen;
 
2888
          *outBuf=pOut;
 
2889
          *inBuf=pIn;
 
2890
          *numSub+=numS;
 
2891
          return -1;
 
2892
 
 
2893
        } else { /* invalid sequence */
 
2894
          errno=EILSEQ;  /* 116 */
 
2895
          *outBytesLeft-=(pOut-*outBuf);
 
2896
          *inBytesLeft=inLen;
 
2897
          *outBuf=pOut;
 
2898
          *inBuf=pIn;
 
2899
          *numSub+=numS;
 
2900
          return -1;
 
2901
        }
 
2902
      }
 
2903
    }
 
2904
    *outBytesLeft-=(pOut-*outBuf);
 
2905
    *inBytesLeft=inLen;
 
2906
    *outBuf=pOut;
 
2907
    *inBuf=pIn;
 
2908
    *numSub+=numS;
 
2909
    return 0;
 
2910
  } else if (cd->cnv_dmap->codingSchema == DMAP_U28) {
 
2911
    /* See http://unicode.org/versions/corrigendum1.html */
 
2912
    register int        inLen=*inBytesLeft;
 
2913
    register char *     pOut=*outBuf;
 
2914
    register char *     pIn=*inBuf;
 
2915
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
2916
    //    register size_t     numS=0;
 
2917
    while (0 < inLen) {
 
2918
      register uint32_t       in;
 
2919
      if (inLen == 1) {
 
2920
        errno=EINVAL;   /* 22 */
 
2921
        *inBytesLeft=inLen;
 
2922
        *outBytesLeft-=(pOut-*outBuf);
 
2923
        *outBuf=pOut;
 
2924
        *inBuf=pIn;
 
2925
        return -1;
 
2926
      }
 
2927
      if (pLastOutBuf < pOut)
 
2928
        break;
 
2929
      in=pIn[0];
 
2930
      in<<=8;
 
2931
      in+=pIn[1];
 
2932
      if (in == 0x0000) {
 
2933
        *pOut=0x00;
 
2934
        ++pOut;
 
2935
      } else if ((in & 0xFF80) == 0x0000) {     /* U28: in & 0b1111111110000000 == 0x0000 */
 
2936
        *pOut=in;
 
2937
        ++pOut;
 
2938
      } else if ((in & 0xF800) == 0x0000) {     /* in & 0b1111100000000000 == 0x0000 */
 
2939
        register uchar        byte;
 
2940
        in>>=6;
 
2941
        in&=0x001F;   /* 0b0000000000011111 */
 
2942
        in|=0x00C0;   /* 0b0000000011000000 */
 
2943
        *pOut=in;
 
2944
        ++pOut;
 
2945
        byte=pIn[1];
 
2946
        byte&=0x3F;   /* 0b00111111; */
 
2947
        byte|=0x80;   /* 0b10000000; */
 
2948
        *pOut=byte;
 
2949
        ++pOut;
 
2950
      } else {
 
2951
        register uchar        byte;
 
2952
        register uchar        work;
 
2953
        byte=pIn[0];
 
2954
        byte>>=4;
 
2955
        byte|=0xE0;   /* 0b11100000; */
 
2956
        *pOut=byte;
 
2957
        ++pOut;
 
2958
 
 
2959
        byte=pIn[0];
 
2960
        byte<<=2;
 
2961
        work=pIn[1];
 
2962
        work>>=6;
 
2963
        byte|=work;
 
2964
        byte&=0x3F;   /* 0b00111111; */
 
2965
        byte|=0x80;   /* 0b10000000; */
 
2966
        *pOut=byte;
 
2967
        ++pOut;
 
2968
 
 
2969
        byte=pIn[1];
 
2970
        byte&=0x3F;   /* 0b00111111; */
 
2971
        byte|=0x80;   /* 0b10000000; */
 
2972
        *pOut=byte;
 
2973
        ++pOut;
 
2974
      }
 
2975
      pIn+=2;
 
2976
      inLen-=2;
 
2977
    }
 
2978
    *outBytesLeft-=(pOut-*outBuf);
 
2979
    *inBytesLeft=inLen;
 
2980
    *outBuf=pOut;
 
2981
    *inBuf=pIn;
 
2982
    //    *numSub+=numS;
 
2983
    return 0;
 
2984
 
 
2985
  } else if (cd->cnv_dmap->codingSchema == DMAP_T28) {   /* UTF-16_UTF-8 */
 
2986
    /* See http://unicode.org/versions/corrigendum1.html */
 
2987
    register int        inLen=*inBytesLeft;
 
2988
    register char *     pOut=*outBuf;
 
2989
    register char *     pIn=*inBuf;
 
2990
    register char *     pLastOutBuf = *outBuf + *outBytesLeft - 1;
 
2991
    //    register size_t     numS=0;
 
2992
    while (0 < inLen) {
 
2993
      register uint32_t       in;
 
2994
      if (inLen == 1) {
 
2995
        errno=EINVAL;   /* 22 */
 
2996
        *inBytesLeft=0;
 
2997
        *outBytesLeft-=(pOut-*outBuf);
 
2998
        *outBuf=pOut;
 
2999
        *inBuf=pIn;
 
3000
        return 0;
 
3001
      }
 
3002
      if (pLastOutBuf < pOut)
 
3003
        break;
 
3004
      in=pIn[0];
 
3005
      in<<=8;
 
3006
      in+=pIn[1];
 
3007
      if (in == 0x0000) {
 
3008
        *pOut=0x00;
 
3009
        ++pOut;
 
3010
      } else if ((in & 0xFF80) == 0x0000) {     /* U28: in & 0b1111111110000000 == 0x0000 */
 
3011
        *pOut=in;
 
3012
        ++pOut;
 
3013
      } else if ((in & 0xF800) == 0x0000) {     /* in & 0b1111100000000000 == 0x0000 */
 
3014
        register uchar        byte;
 
3015
        in>>=6;
 
3016
        in&=0x001F;   /* 0b0000000000011111 */
 
3017
        in|=0x00C0;   /* 0b0000000011000000 */
 
3018
        *pOut=in;
 
3019
        ++pOut;
 
3020
        byte=pIn[1];
 
3021
        byte&=0x3F;   /* 0b00111111; */
 
3022
        byte|=0x80;   /* 0b10000000; */
 
3023
        *pOut=byte;
 
3024
        ++pOut;
 
3025
      } else if ((in & 0xFC00) == 0xD800) {     /* in & 0b1111110000000000 == 0b1101100000000000, first surrogate character */
 
3026
        if (0xDC00 <= in ) {
 
3027
          errno=EINVAL;   /* 22 */
 
3028
          *inBytesLeft=inLen-1;
 
3029
          *outBytesLeft-=(pOut-*outBuf);
 
3030
          *outBuf=pOut;
 
3031
          *inBuf=pIn;
 
3032
          return -1;
 
3033
          
 
3034
        } else if (inLen < 4) {
 
3035
          errno=EINVAL;   /* 22 */
 
3036
          *inBytesLeft=inLen-2;
 
3037
          *outBytesLeft-=(pOut-*outBuf);
 
3038
          *outBuf=pOut;
 
3039
          *inBuf=pIn+2;
 
3040
          return -1;
 
3041
          
 
3042
        } else if ((pIn[2] & 0xFC) != 0xDC) {     /* pIn[2] & 0b11111100 == 0b11011100, second surrogate character */
 
3043
          errno=EINVAL;   /* 22 */
 
3044
          *inBytesLeft=inLen-2;
 
3045
          *outBytesLeft-=(pOut-*outBuf);
 
3046
          *outBuf=pOut;
 
3047
          *inBuf=pIn+2;
 
3048
          return -1;
 
3049
          
 
3050
        } else {
 
3051
          register uchar        byte;
 
3052
          register uchar        work;
 
3053
          in>>=6;
 
3054
          in&=0x000F;   /* 0b0000000000001111 */
 
3055
          byte=in;      /* wwww  */
 
3056
          ++byte;       /* uuuuu */
 
3057
          work=byte;    /* save uuuuu */
 
3058
          byte>>=2;
 
3059
          byte|=0xF0;   /* 0b11110000; */
 
3060
          *pOut=byte;
 
3061
          ++pOut;
 
3062
 
 
3063
          byte=work;
 
3064
          byte&=0x03;   /* 0b00000011; */
 
3065
          byte<<=4;
 
3066
          byte|=0x80;   /* 0b10000000; */
 
3067
          work=pIn[1];
 
3068
          work&=0x3C;   /* 0b00111100; */
 
3069
          work>>=2;
 
3070
          byte|=work;
 
3071
          *pOut=byte;
 
3072
          ++pOut;
 
3073
 
 
3074
          byte=pIn[1];
 
3075
          byte&=0x03;   /* 0b00000011; */
 
3076
          byte<<=4;
 
3077
          byte|=0x80;   /* 0b10000000; */
 
3078
          work=pIn[2];
 
3079
          work&=0x03;   /* 0b00000011; */
 
3080
          work<<=2;
 
3081
          byte|=work;
 
3082
          work=pIn[3];
 
3083
          work>>=6;
 
3084
          byte|=work;
 
3085
          *pOut=byte;
 
3086
          ++pOut;
 
3087
 
 
3088
          byte=pIn[3];
 
3089
          byte&=0x3F;   /* 0b00111111; */
 
3090
          byte|=0x80;   /* 0b10000000; */
 
3091
          *pOut=byte;
 
3092
          ++pOut;
 
3093
          pIn+=2;
 
3094
          inLen-=2;
 
3095
        }
 
3096
      } else if ((in & 0xFC00) == 0xDC00) {     /* in & 0b11111100 == 0b11011100, second surrogate character */
 
3097
          errno=EINVAL;   /* 22 */
 
3098
          *inBytesLeft=inLen-1;
 
3099
          *outBytesLeft-=(pOut-*outBuf);
 
3100
          *outBuf=pOut;
 
3101
          *inBuf=pIn;
 
3102
          return -1;
 
3103
          
 
3104
      } else {
 
3105
        register uchar        byte;
 
3106
        register uchar        work;
 
3107
        byte=pIn[0];
 
3108
        byte>>=4;
 
3109
        byte|=0xE0;   /* 0b11100000; */
 
3110
        *pOut=byte;
 
3111
        ++pOut;
 
3112
 
 
3113
        byte=pIn[0];
 
3114
        byte<<=2;
 
3115
        work=pIn[1];
 
3116
        work>>=6;
 
3117
        byte|=work;
 
3118
        byte&=0x3F;   /* 0b00111111; */
 
3119
        byte|=0x80;   /* 0b10000000; */
 
3120
        *pOut=byte;
 
3121
        ++pOut;
 
3122
 
 
3123
        byte=pIn[1];
 
3124
        byte&=0x3F;   /* 0b00111111; */
 
3125
        byte|=0x80;   /* 0b10000000; */
 
3126
        *pOut=byte;
 
3127
        ++pOut;
 
3128
      }
 
3129
      pIn+=2;
 
3130
      inLen-=2;
 
3131
    }
 
3132
    *outBytesLeft-=(pOut-*outBuf);
 
3133
    *inBytesLeft=inLen;
 
3134
    *outBuf=pOut;
 
3135
    *inBuf=pIn;
 
3136
    //    *numSub+=numS;
 
3137
    return 0;
 
3138
 
 
3139
  } else if (cd->cnv_dmap->codingSchema == DMAP_U2U) {  /* UTF-16_UCS-2 */
 
3140
    register int        inLen=*inBytesLeft;
 
3141
    register int        outLen=*outBytesLeft;
 
3142
    if (inLen <= outLen) {
 
3143
      memcpy(*outBuf, *inBuf, inLen);
 
3144
      (*outBytesLeft)-=inLen;
 
3145
      (*inBuf)+=inLen;
 
3146
      (*outBuf)+=inLen;
 
3147
      *inBytesLeft=0;
 
3148
      return 0;
 
3149
    }
 
3150
    memcpy(*outBuf, *inBuf, outLen);
 
3151
    (*outBytesLeft)=0;
 
3152
    (*inBuf)+=outLen;
 
3153
    (*outBuf)+=outLen;
 
3154
    *inBytesLeft-=outLen;
 
3155
    return (*inBytesLeft);
 
3156
      
 
3157
  } else {
 
3158
    return -1;
 
3159
  }
 
3160
  return 0;
 
3161
}
 
3162
 
 
3163
 
 
3164
#ifdef DEBUG
 
3165
inline  size_t          myconv(myconv_t cd ,
 
3166
                               char**   inBuf,
 
3167
                               size_t*  inBytesLeft,
 
3168
                               char**   outBuf,
 
3169
                               size_t*  outBytesLeft,
 
3170
                               size_t*  numSub)
 
3171
{
 
3172
  if (cd->converterType == CONVERTER_ICONV) {
 
3173
    return myconv_iconv(cd,inBuf,inBytesLeft,outBuf,outBytesLeft,numSub);
 
3174
  } else if (cd->converterType == CONVERTER_DMAP) {
 
3175
    return myconv_dmap(cd,inBuf,inBytesLeft,outBuf,outBytesLeft,numSub);
 
3176
  }
 
3177
  return -1;
 
3178
}
 
3179
 
 
3180
inline  char *  converterName(int32_t   type)
 
3181
{
 
3182
  if (type == CONVERTER_ICONV)
 
3183
    return "iconv";
 
3184
  else if (type == CONVERTER_DMAP)
 
3185
    return "dmap";
 
3186
  
 
3187
  return "?????";
 
3188
}
 
3189
#else
 
3190
#define myconv(a,b,c,d,e,f) \
 
3191
(((a)->converterType == CONVERTER_ICONV)? myconv_iconv((a),(b),(c),(d),(e),(f)): (((a)->converterType == CONVERTER_DMAP)? myconv_dmap((a),(b),(c),(d),(e),(f)): -1))
 
3192
 
 
3193
 
 
3194
#define converterName(a) \
 
3195
(((a) == CONVERTER_ICONV)? "iconv": ((a) == CONVERTER_DMAP)? "dmap": "?????")
 
3196
#endif
 
3197
 
 
3198
void initMyconv();
 
3199
void cleanupMyconv();
 
3200
 
 
3201
#endif