/* Conversion from and to CP1258.
Copyright (C) 1998-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <dlfcn.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>
#define NELEMS(arr) (sizeof (arr) / sizeof (arr[0]))
/* Definitions used in the body of the `gconv' function. */
#define CHARSET_NAME "CP1258//"
#define FROM_LOOP from_cp1258
#define TO_LOOP to_cp1258
#define DEFINE_INIT 1
#define DEFINE_FINI 1
#define ONE_DIRECTION 0
#define FROM_LOOP_MIN_NEEDED_FROM 1
#define FROM_LOOP_MAX_NEEDED_FROM 1
#define FROM_LOOP_MIN_NEEDED_TO 4
#define FROM_LOOP_MAX_NEEDED_TO 4
#define TO_LOOP_MIN_NEEDED_FROM 4
#define TO_LOOP_MAX_NEEDED_FROM 4
#define TO_LOOP_MIN_NEEDED_TO 1
#define TO_LOOP_MAX_NEEDED_TO 2
#define PREPARE_LOOP \
int saved_state; \
int *statep = &data->__statep->__count;
#define EXTRA_LOOP_ARGS , statep
/* Since we might have to reset input pointer we must be able to save
and restore the state. */
#define SAVE_RESET_STATE(Save) \
if (Save) \
saved_state = *statep; \
else \
*statep = saved_state
/* During CP1258 to UCS4 conversion, the COUNT element of the state
contains the last UCS4 character, shifted by 3 bits. */
/* Since this is a stateful encoding we have to provide code which resets
the output state to the initial state. This has to be done during the
flushing. */
#define EMIT_SHIFT_TO_INIT \
if (data->__statep->__count != 0) \
{ \
if (FROM_DIRECTION) \
{ \
if (__glibc_likely (outbuf + 4 <= outend)) \
{ \
/* Write out the last character. */ \
*((uint32_t *) outbuf) = data->__statep->__count >> 3; \
outbuf += sizeof (uint32_t); \
data->__statep->__count = 0; \
} \
else \
/* We don't have enough room in the output buffer. */ \
status = __GCONV_FULL_OUTPUT; \
} \
else \
/* We don't use shift states in the TO_DIRECTION. */ \
data->__statep->__count = 0; \
}
/* First define the conversion function from CP1258 to UCS4. */
static const uint16_t to_ucs4[128] =
{
/* 0x80 */
0x20AC, 0, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0, 0x2039, 0x0152, 0, 0, 0,
/* 0x90 */
0, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x02DC, 0x2122, 0, 0x203A, 0x0153, 0, 0, 0x0178,
/* 0xA0 */
0x00A0,