~ubuntu-branches/ubuntu/maverick/mysql-5.1/maverick-proposed

« back to all changes in this revision

Viewing changes to storage/ibmdb2i/db2i_myconv.h

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-02-22 14:16:05 UTC
  • mto: This revision was merged to the branch mainline in revision 20.
  • Revision ID: package-import@ubuntu.com-20120222141605-nxlu9yzc6attylc2
Tags: upstream-5.1.61
ImportĀ upstreamĀ versionĀ 5.1.61

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