Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/iconv/lib/ces_euc.c')
-rw-r--r--newlib/libc/iconv/lib/ces_euc.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/newlib/libc/iconv/lib/ces_euc.c b/newlib/libc/iconv/lib/ces_euc.c
new file mode 100644
index 000000000..dc5000c2d
--- /dev/null
+++ b/newlib/libc/iconv/lib/ces_euc.c
@@ -0,0 +1,208 @@
+/*-
+ * Copyright (c) 1999,2000
+ * Konstantin Chuguev. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * iconv (Charset Conversion Library) v2.0
+ */
+#ifdef ENABLE_ICONV
+
+#include "deps.h"
+#include <_ansi.h>
+#include <sys/types.h>
+#include <stddef.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <wchar.h>
+#include <reent.h>
+#include "local.h"
+
+typedef struct {
+ int nccs;
+ struct iconv_ccs ccs[1];
+} iconv_ces_euc_state;
+
+int
+_DEFUN(iconv_euc_init, (rptr, data, desc_data, num),
+ struct _reent *rptr _AND
+ _VOID_PTR *data _AND
+ _CONST _VOID_PTR desc_data _AND
+ size_t num)
+{
+ size_t stsz = sizeof(iconv_ces_euc_state) +
+ sizeof(struct iconv_ccs) * (num - 1);
+ int i;
+ iconv_ces_euc_state *state = (iconv_ces_euc_state *)_malloc_r(rptr, stsz);
+
+ if (state == NULL)
+ return __errno_r(rptr);
+ for (i = 0; i < num; i++) {
+ int res = iconv_ccs_init(rptr, &(state->ccs[i]),
+ ((_CONST iconv_ces_euc_ccs *) desc_data)[i].name);
+ if (res) {
+ while (--i >= 0)
+ state->ccs[i].close(rptr, &(state->ccs[i]));
+ _free_r(rptr, state);
+ return res;
+ }
+ }
+ state->nccs = num;
+ (iconv_ces_euc_state *)*data = state;
+ return 0;
+}
+
+int
+_DEFUN(iconv_euc_close, (rptr, data),
+ struct _reent *rptr _AND
+ _VOID_PTR data)
+{
+#define state ((iconv_ces_euc_state *)data)
+ int i, res = 0;
+
+ for (i = 0; i < state->nccs; i++)
+ res = state->ccs[i].close(rptr, &(state->ccs[i])) || res;
+ _free_r(rptr, data);
+ return res;
+#undef state
+}
+
+#define is_7_14bit(data) ((data)->nbits & 7)
+#define is_7bit(data) ((data)->nbits & 1)
+
+ssize_t
+_DEFUN(iconv_euc_convert_from_ucs, (ces, in, outbuf, outbytesleft),
+ struct iconv_ces *ces _AND
+ ucs_t in _AND
+ unsigned char **outbuf _AND
+ size_t *outbytesleft)
+{
+ iconv_ces_euc_state *euc_state;
+ size_t bytes;
+ int i;
+
+ if (in == UCS_CHAR_NONE)
+ return 1; /* No state reinitialization for table charsets */
+ if (iconv_char32bit(in))
+ return -1;
+ euc_state = (iconv_ces_euc_state *)(ces->data);
+ for (i = 0; i < euc_state->nccs; i++) {
+ _CONST iconv_ces_euc_ccs *ccsattr;
+ _CONST struct iconv_ccs *ccs = &(euc_state->ccs[i]);
+ ucs_t res = ICONV_CCS_CONVERT_FROM_UCS(ccs, in);
+
+ if (res == UCS_CHAR_INVALID)
+ continue;
+ ccsattr = &(((_CONST iconv_ces_euc_ccs *)(ces->desc->data))[i]);
+ if (i) {
+ if (is_7_14bit(ccs))
+ res |= is_7bit(ccs) ? 0x80 : 0x8080;
+ else if (!(res & 0x8080))
+ continue;
+ } else if (res & 0x8080)
+ continue;
+ bytes = (res & 0xFF00 ? 2 : 1) + ccsattr->prefixlen;
+ if (*outbytesleft < bytes)
+ return 0; /* No space in the output buffer */
+ if (ccsattr->prefixlen) {
+ memcpy(*outbuf, ccsattr->prefix, ccsattr->prefixlen);
+ (*outbuf) += ccsattr->prefixlen;
+ }
+ if (res & 0xFF00)
+ *(*outbuf)++ = (unsigned char)(res >> 8);
+ *(*outbuf)++ = (unsigned char)res;
+ *outbytesleft -= bytes;
+ return 1;
+ }
+ return -1; /* No character in output charset */
+}
+
+static ucs_t
+_DEFUN(cvt2ucs, (ccs, inbuf, inbytesleft, hi_plane, bufptr),
+ struct iconv_ccs *ccs _AND
+ _CONST unsigned char *inbuf _AND
+ size_t inbytesleft _AND
+ int hi_plane _AND
+ _CONST unsigned char **bufptr)
+{
+ size_t bytes = ccs->nbits > 8 ? 2 : 1;
+ ucs_t ch = *(_CONST unsigned char *)inbuf++;
+
+ if (inbytesleft < bytes)
+ return UCS_CHAR_NONE; /* Not enough bytes in the input buffer */
+ if (bytes == 2)
+ ch = (ch << 8) | *(_CONST unsigned char *)inbuf++;
+ *bufptr = inbuf;
+ if (hi_plane) {
+ if (!(ch & 0x8080))
+ return UCS_CHAR_INVALID;
+ if (is_7_14bit(ccs))
+ ch &= 0x7F7F;
+ } else if (ch & 0x8080)
+ return UCS_CHAR_INVALID;
+ return ICONV_CCS_CONVERT_TO_UCS(ccs, ch);
+}
+
+ucs_t
+_DEFUN(iconv_euc_convert_to_ucs, (ces, inbuf, inbytesleft),
+ struct iconv_ces *ces _AND
+ _CONST unsigned char **inbuf _AND
+ size_t *inbytesleft)
+{
+ iconv_ces_euc_state *euc_state =
+ (iconv_ces_euc_state *)(ces->data);
+ ucs_t res = UCS_CHAR_INVALID;
+ _CONST unsigned char *ptr;
+ int i;
+
+ if (**inbuf & 0x80) {
+ for (i = 1; i < euc_state->nccs; i++) {
+ _CONST iconv_ces_euc_ccs *ccsattr =
+ &(((_CONST iconv_ces_euc_ccs *)
+ (ces->desc->data))[i]);
+ if (ccsattr->prefixlen + 1 > *inbytesleft)
+ return UCS_CHAR_NONE;
+ if (ccsattr->prefixlen &&
+ memcmp(*inbuf, ccsattr->prefix, ccsattr->prefixlen))
+ continue;
+ res = cvt2ucs(&(euc_state->ccs[i]),
+ *inbuf + ccsattr->prefixlen,
+ *inbytesleft - ccsattr->prefixlen,
+ 1, &ptr);
+ if (res != UCS_CHAR_INVALID)
+ break;
+ }
+ if (res == UCS_CHAR_INVALID)
+ ptr = *inbuf + 1;
+ } else
+ res = cvt2ucs(euc_state->ccs, *inbuf, *inbytesleft, 0, &ptr);
+ if (res == UCS_CHAR_NONE)
+ return res; /* Not enough bytes in the input buffer */
+ *inbytesleft -= ptr - *inbuf;
+ *inbuf = ptr;
+ return res;
+}
+
+#endif /* #ifdef ENABLE_ICONV */
+