Coverage Report

Created: 2026-06-30 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dcmtk/oficonv/libsrc/citrus_euc.c
Line
Count
Source
1
/*-
2
 * Copyright (c)2002 Citrus Project,
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
 * SUCH DAMAGE.
25
 */
26
27
/*-
28
 * Copyright (c) 1993
29
 *  The Regents of the University of California.  All rights reserved.
30
 *
31
 * This code is derived from software contributed to Berkeley by
32
 * Paul Borman at Krystal Technologies.
33
 *
34
 * Redistribution and use in source and binary forms, with or without
35
 * modification, are permitted provided that the following conditions
36
 * are met:
37
 * 1. Redistributions of source code must retain the above copyright
38
 *    notice, this list of conditions and the following disclaimer.
39
 * 2. Redistributions in binary form must reproduce the above copyright
40
 *    notice, this list of conditions and the following disclaimer in the
41
 *    documentation and/or other materials provided with the distribution.
42
 * 3. Neither the name of the University nor the names of its contributors
43
 *    may be used to endorse or promote products derived from this software
44
 *    without specific prior written permission.
45
 *
46
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56
 * SUCH DAMAGE.
57
 */
58
59
#include "dcmtk/config/osconfig.h"
60
#include "citrus_euc.h"
61
62
#include <sys/types.h>
63
#include <errno.h>
64
#include <limits.h>
65
#include <stddef.h>
66
#include <stdio.h>
67
#include <stdlib.h>
68
#include <string.h>
69
#include <wchar.h>
70
71
#include "citrus_bcs.h"
72
#include "citrus_types.h"
73
#include "citrus_module.h"
74
#include "citrus_stdenc.h"
75
76
77
/* ----------------------------------------------------------------------
78
 * private stuffs used by templates
79
 */
80
81
typedef struct {
82
    int  chlen;
83
    char     ch[3];
84
} _EUCState;
85
86
typedef struct {
87
    _citrus_wc_t      bits[4];
88
    _citrus_wc_t      mask;
89
    unsigned     count[4];
90
    unsigned     mb_cur_max;
91
} _EUCEncodingInfo;
92
93
0
#define _SS2    0x008e
94
0
#define _SS3    0x008f
95
96
#define _CEI_TO_EI(_cei_)       (&(_cei_)->ei)
97
#define _CEI_TO_STATE(_cei_, _func_)    (_cei_)->states.s_##_func_
98
99
0
#define _FUNCNAME(m)            _citrus_EUC_##m
100
0
#define _ENCODING_INFO          _EUCEncodingInfo
101
#define _ENCODING_STATE         _EUCState
102
0
#define _ENCODING_MB_CUR_MAX(_ei_)  (_ei_)->mb_cur_max
103
#define _ENCODING_IS_STATE_DEPENDENT    0
104
#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)    0
105
106
107
static __inline int
108
_citrus_EUC_cs(unsigned int c)
109
0
{
110
111
0
    c &= 0xff;
112
113
0
    return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
114
0
}
115
116
/* suppress MSVC 'assignment within conditional expression' warning  */
117
#ifdef _MSC_VER
118
#pragma warning(push)
119
#pragma warning(disable: 4706)
120
#endif
121
122
static __inline int
123
_citrus_EUC_parse_variable(_EUCEncodingInfo *ei, const void *var,
124
    size_t lenvar )
125
0
{
126
0
    char *e;
127
0
    const char *v;
128
0
    int x;
129
0
    (void) lenvar;
130
131
    /* parse variable string */
132
0
    if (!var)
133
0
        return (EFTYPE);
134
135
0
    v = (const char *)var;
136
137
0
    while (*v == ' ' || *v == '\t')
138
0
        ++v;
139
140
0
    ei->mb_cur_max = 1;
141
0
    for (x = 0; x < 4; ++x) {
142
0
        ei->count[x] = (int)_citrus_bcs_strtol(v, (char **)&e, 0);
143
0
        if (v == e || !(v = e) || ei->count[x] < 1 || ei->count[x] > 4) {
144
0
            return (EFTYPE);
145
0
        }
146
0
        if (ei->mb_cur_max < ei->count[x])
147
0
            ei->mb_cur_max = ei->count[x];
148
0
        while (*v == ' ' || *v == '\t')
149
0
            ++v;
150
0
        ei->bits[x] = (int)_citrus_bcs_strtol(v, (char **)&e, 0);
151
0
        if (v == e || !(v = e)) {
152
0
            return (EFTYPE);
153
0
        }
154
0
        while (*v == ' ' || *v == '\t')
155
0
            ++v;
156
0
    }
157
0
    ei->mask = (int)_citrus_bcs_strtol(v, (char **)&e, 0);
158
0
    if (v == e || !(v = e)) {
159
0
        return (EFTYPE);
160
0
    }
161
162
0
    return (0);
163
0
}
164
165
#ifdef _MSC_VER
166
#pragma warning(pop)
167
#endif
168
169
static __inline void
170
/*ARGSUSED*/
171
_citrus_EUC_init_state(_EUCEncodingInfo *ei , _EUCState *s)
172
0
{
173
0
    (void) ei;
174
0
    memset(s, 0, sizeof(*s));
175
0
}
176
177
static int
178
_citrus_EUC_mbrtowc_priv(_EUCEncodingInfo *ei, _citrus_wc_t *pwc, char **s,
179
    size_t n, _EUCState *psenc, size_t *nresult)
180
0
{
181
0
    _citrus_wc_t wchar;
182
0
    int c, chlenbak, cs, len;
183
0
    char *s0, *s1 = NULL;
184
185
0
    s0 = *s;
186
187
0
    if (s0 == NULL) {
188
0
        _citrus_EUC_init_state(ei, psenc);
189
0
        *nresult = 0; /* state independent */
190
0
        return (0);
191
0
    }
192
193
0
    chlenbak = psenc->chlen;
194
195
    /* make sure we have the first byte in the buffer */
196
0
    switch (psenc->chlen) {
197
0
    case 0:
198
0
        if (n < 1)
199
0
            goto restart;
200
0
        psenc->ch[0] = *s0++;
201
0
        psenc->chlen = 1;
202
0
        n--;
203
0
        break;
204
0
    case 1:
205
0
    case 2:
206
0
        break;
207
0
    default:
208
        /* illgeal state */
209
0
        goto encoding_error;
210
0
    }
211
212
0
    c = ei->count[cs = _citrus_EUC_cs(psenc->ch[0] & 0xff)];
213
0
    if (c == 0)
214
0
        goto encoding_error;
215
0
    while (psenc->chlen < c) {
216
0
        if (n < 1)
217
0
            goto restart;
218
0
        psenc->ch[psenc->chlen] = *s0++;
219
0
        psenc->chlen++;
220
0
        n--;
221
0
    }
222
0
    *s = s0;
223
224
0
    switch (cs) {
225
0
    case 3:
226
0
    case 2:
227
        /* skip SS2/SS3 */
228
0
        len = c - 1;
229
0
        s1 = &psenc->ch[1];
230
0
        break;
231
0
    case 1:
232
0
    case 0:
233
0
        len = c;
234
0
        s1 = &psenc->ch[0];
235
0
        break;
236
0
    default:
237
0
        goto encoding_error;
238
0
    }
239
0
    wchar = 0;
240
0
    while (len-- > 0)
241
0
        wchar = (wchar << 8) | (*s1++ & 0xff);
242
0
    wchar = (wchar & ~ei->mask) | ei->bits[cs];
243
244
0
    psenc->chlen = 0;
245
0
    if (pwc)
246
0
        *pwc = wchar;
247
0
    *nresult = wchar ? (size_t)(c - chlenbak) : 0;
248
0
    return (0);
249
250
0
encoding_error:
251
0
    psenc->chlen = 0;
252
0
    *nresult = (size_t)-1;
253
0
    return (EILSEQ);
254
255
0
restart:
256
0
    *nresult = (size_t)-2;
257
0
    *s = s0;
258
0
    return (0);
259
0
}
260
261
static int
262
_citrus_EUC_wcrtomb_priv(_EUCEncodingInfo *ei, char *s, size_t n, _citrus_wc_t wc,
263
    _EUCState *psenc , size_t *nresult)
264
0
{
265
0
    _citrus_wc_t m, nm;
266
0
    unsigned int cs;
267
0
    int ret;
268
0
    int i;
269
270
0
    (void) psenc;
271
0
    m = wc & ei->mask;
272
0
    nm = wc & ~m;
273
274
0
    for (cs = 0; cs < sizeof(ei->count) / sizeof(ei->count[0]); cs++)
275
0
        if (m == ei->bits[cs])
276
0
            break;
277
    /* fallback case - not sure if it is necessary */
278
0
    if (cs == sizeof(ei->count) / sizeof(ei->count[0]))
279
0
        cs = 1;
280
281
0
    i = ei->count[cs];
282
0
    if (n < (unsigned)i) {
283
0
        ret = E2BIG;
284
0
        goto err;
285
0
    }
286
0
    m = (cs) ? 0x80 : 0x00;
287
0
    switch (cs) {
288
0
    case 2:
289
0
        *s++ = _SS2;
290
0
        i--;
291
0
        break;
292
0
    case 3:
293
0
        *s++ = _SS3;
294
0
        i--;
295
0
        break;
296
0
    }
297
298
0
    while (i-- > 0)
299
0
        *s++ = (char)(((nm >> (i << 3)) & 0xff) | m);
300
301
0
    *nresult = (size_t)ei->count[cs];
302
0
    return (0);
303
304
0
err:
305
0
    *nresult = (size_t)-1;
306
0
    return (ret);
307
0
}
308
309
static __inline int
310
/*ARGSUSED*/
311
_citrus_EUC_stdenc_wctocs(_EUCEncodingInfo * ei,
312
    _citrus_csid_t * csid, _citrus_index_t * idx, _citrus_wc_t wc)
313
0
{
314
0
    _citrus_wc_t m, nm;
315
316
0
    m = wc & ei->mask;
317
0
    nm = wc & ~m;
318
319
0
    *csid = (_citrus_csid_t)m;
320
0
    *idx  = (_citrus_index_t)nm;
321
322
0
    return (0);
323
0
}
324
325
static __inline int
326
/*ARGSUSED*/
327
_citrus_EUC_stdenc_cstowc(_EUCEncodingInfo * ei,
328
    _citrus_wc_t * wc, _citrus_csid_t csid, _citrus_index_t idx)
329
0
{
330
331
0
    if ((csid & ~ei->mask) != 0 || (idx & ei->mask) != 0)
332
0
        return (EINVAL);
333
334
0
    *wc = (_citrus_wc_t)csid | (_citrus_wc_t)idx;
335
336
0
    return (0);
337
0
}
338
339
static __inline int
340
/*ARGSUSED*/
341
_citrus_EUC_stdenc_get_state_desc_generic(_EUCEncodingInfo * ei ,
342
    _EUCState * psenc, int * rstate)
343
0
{
344
345
0
    (void) ei;
346
0
    *rstate = (psenc->chlen == 0) ? _CITRUS_STDENC_SDGEN_INITIAL :
347
0
        _CITRUS_STDENC_SDGEN_INCOMPLETE_CHAR;
348
0
    return (0);
349
0
}
350
351
static int
352
/*ARGSUSED*/
353
_citrus_EUC_encoding_module_init(_EUCEncodingInfo * ei,
354
    const void * var, size_t lenvar)
355
0
{
356
357
0
    return (_citrus_EUC_parse_variable(ei, var, lenvar));
358
0
}
359
360
static void
361
/*ARGSUSED*/
362
_citrus_EUC_encoding_module_uninit(_EUCEncodingInfo * ei )
363
0
{
364
0
    (void) ei;
365
0
}
366
367
/* ----------------------------------------------------------------------
368
 * public interface for stdenc
369
 */
370
371
_CITRUS_STDENC_DECLS(EUC);
372
_CITRUS_STDENC_DEF_OPS(EUC);
373
374
#include "citrus_stdenc_template.h"