summaryrefslogtreecommitdiffstats
path: root/lib/unistring/unistr
diff options
context:
space:
mode:
Diffstat (limited to 'lib/unistring/unistr')
-rw-r--r--lib/unistring/unistr/u-cpy.h42
-rw-r--r--lib/unistring/unistr/u16-cpy.c34
-rw-r--r--lib/unistring/unistr/u16-mbtouc-unsafe-aux.c60
-rw-r--r--lib/unistring/unistr/u16-mbtouc-unsafe.c71
-rw-r--r--lib/unistring/unistr/u16-mbtoucr.c63
-rw-r--r--lib/unistring/unistr/u16-to-u8.c145
-rw-r--r--lib/unistring/unistr/u16-uctomb-aux.c67
-rw-r--r--lib/unistring/unistr/u16-uctomb.c81
-rw-r--r--lib/unistring/unistr/u32-cpy.c34
-rw-r--r--lib/unistring/unistr/u32-mbtouc-unsafe.c53
-rw-r--r--lib/unistring/unistr/u32-to-u8.c139
-rw-r--r--lib/unistring/unistr/u32-uctomb.c56
-rw-r--r--lib/unistring/unistr/u8-check.c86
-rw-r--r--lib/unistring/unistr/u8-cpy.c34
-rw-r--r--lib/unistring/unistr/u8-mbtouc-unsafe-aux.c148
-rw-r--r--lib/unistring/unistr/u8-mbtouc-unsafe.c159
-rw-r--r--lib/unistring/unistr/u8-mbtoucr.c151
-rw-r--r--lib/unistring/unistr/u8-to-u16.c145
-rw-r--r--lib/unistring/unistr/u8-to-u32.c134
-rw-r--r--lib/unistring/unistr/u8-uctomb-aux.c69
-rw-r--r--lib/unistring/unistr/u8-uctomb.c88
21 files changed, 1859 insertions, 0 deletions
diff --git a/lib/unistring/unistr/u-cpy.h b/lib/unistring/unistr/u-cpy.h
new file mode 100644
index 0000000..25c2ba5
--- /dev/null
+++ b/lib/unistring/unistr/u-cpy.h
@@ -0,0 +1,42 @@
+/* Copy piece of UTF-8/UTF-16/UTF-32 string.
+ Copyright (C) 1999, 2002, 2006, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+UNIT *
+FUNC (UNIT *dest, const UNIT *src, size_t n)
+{
+#if 0
+ UNIT *destptr = dest;
+
+ for (; n > 0; n--)
+ *destptr++ = *src++;
+#else
+ if (n > 0)
+ memcpy ((char *) dest, (const char *) src, n * sizeof (UNIT));
+#endif
+ return dest;
+}
diff --git a/lib/unistring/unistr/u16-cpy.c b/lib/unistring/unistr/u16-cpy.c
new file mode 100644
index 0000000..ba3e44c
--- /dev/null
+++ b/lib/unistring/unistr/u16-cpy.c
@@ -0,0 +1,34 @@
+/* Copy piece of UTF-16 string.
+ Copyright (C) 1999, 2002, 2006, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+#define FUNC u16_cpy
+#define UNIT uint16_t
+#include "u-cpy.h"
diff --git a/lib/unistring/unistr/u16-mbtouc-unsafe-aux.c b/lib/unistring/unistr/u16-mbtouc-unsafe-aux.c
new file mode 100644
index 0000000..3b415a2
--- /dev/null
+++ b/lib/unistring/unistr/u16-mbtouc-unsafe-aux.c
@@ -0,0 +1,60 @@
+/* Conversion UTF-16 to UCS-4.
+ Copyright (C) 2001-2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2001.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+#if defined IN_LIBUNISTRING || HAVE_INLINE
+
+int
+u16_mbtouc_unsafe_aux (ucs4_t *puc, const uint16_t *s, size_t n)
+{
+ uint16_t c = *s;
+
+ if (c < 0xdc00)
+ {
+ if (n >= 2)
+ {
+ if (s[1] >= 0xdc00 && s[1] < 0xe000)
+ {
+ *puc = 0x10000 + ((c - 0xd800) << 10) + (s[1] - 0xdc00);
+ return 2;
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ }
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 1;
+}
+
+#endif
diff --git a/lib/unistring/unistr/u16-mbtouc-unsafe.c b/lib/unistring/unistr/u16-mbtouc-unsafe.c
new file mode 100644
index 0000000..74d83ab
--- /dev/null
+++ b/lib/unistring/unistr/u16-mbtouc-unsafe.c
@@ -0,0 +1,71 @@
+/* Look at first character in UTF-16 string.
+ Copyright (C) 1999-2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2001.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#if defined IN_LIBUNISTRING
+/* Tell unistr.h to declare u16_mbtouc_unsafe as 'extern', not
+ 'static inline'. */
+# include "unistring-notinline.h"
+#endif
+
+/* Specification. */
+#include "unistr.h"
+
+#if !HAVE_INLINE
+
+int
+u16_mbtouc_unsafe (ucs4_t *puc, const uint16_t *s, size_t n)
+{
+ uint16_t c = *s;
+
+ if (c < 0xd800 || c >= 0xe000)
+ {
+ *puc = c;
+ return 1;
+ }
+ if (c < 0xdc00)
+ {
+ if (n >= 2)
+ {
+ if (s[1] >= 0xdc00 && s[1] < 0xe000)
+ {
+ *puc = 0x10000 + ((c - 0xd800) << 10) + (s[1] - 0xdc00);
+ return 2;
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ }
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 1;
+}
+
+#endif
diff --git a/lib/unistring/unistr/u16-mbtoucr.c b/lib/unistring/unistr/u16-mbtoucr.c
new file mode 100644
index 0000000..04f96ac
--- /dev/null
+++ b/lib/unistring/unistr/u16-mbtoucr.c
@@ -0,0 +1,63 @@
+/* Look at first character in UTF-16 string, returning an error code.
+ Copyright (C) 1999-2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2001.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+int
+u16_mbtoucr (ucs4_t *puc, const uint16_t *s, size_t n)
+{
+ uint16_t c = *s;
+
+ if (c < 0xd800 || c >= 0xe000)
+ {
+ *puc = c;
+ return 1;
+ }
+ if (c < 0xdc00)
+ {
+ if (n >= 2)
+ {
+ if (s[1] >= 0xdc00 && s[1] < 0xe000)
+ {
+ *puc = 0x10000 + ((c - 0xd800) << 10) + (s[1] - 0xdc00);
+ return 2;
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ *puc = 0xfffd;
+ return -2;
+ }
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return -1;
+}
diff --git a/lib/unistring/unistr/u16-to-u8.c b/lib/unistring/unistr/u16-to-u8.c
new file mode 100644
index 0000000..e6268f5
--- /dev/null
+++ b/lib/unistring/unistr/u16-to-u8.c
@@ -0,0 +1,145 @@
+/* Convert UTF-16 string to UTF-8 string.
+ Copyright (C) 2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+#define FUNC u16_to_u8
+#define SRC_UNIT uint16_t
+#define DST_UNIT uint8_t
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+DST_UNIT *
+FUNC (const SRC_UNIT *s, size_t n, DST_UNIT *resultbuf, size_t *lengthp)
+{
+ const SRC_UNIT *s_end = s + n;
+ /* Output string accumulator. */
+ DST_UNIT *result;
+ size_t allocated;
+ size_t length;
+
+ if (resultbuf != NULL)
+ {
+ result = resultbuf;
+ allocated = *lengthp;
+ }
+ else
+ {
+ result = NULL;
+ allocated = 0;
+ }
+ length = 0;
+ /* Invariants:
+ result is either == resultbuf or == NULL or malloc-allocated.
+ If length > 0, then result != NULL. */
+
+ while (s < s_end)
+ {
+ ucs4_t uc;
+ int count;
+
+ /* Fetch a Unicode character from the input string. */
+ count = u16_mbtoucr (&uc, s, s_end - s);
+ if (count < 0)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ errno = EILSEQ;
+ return NULL;
+ }
+ s += count;
+
+ /* Store it in the output string. */
+ count = u8_uctomb (result + length, uc, allocated - length);
+ if (count == -1)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ errno = EILSEQ;
+ return NULL;
+ }
+ if (count == -2)
+ {
+ DST_UNIT *memory;
+
+ allocated = (allocated > 0 ? 2 * allocated : 12);
+ if (length + 6 > allocated)
+ allocated = length + 6;
+ if (result == resultbuf || result == NULL)
+ memory = (DST_UNIT *) malloc (allocated * sizeof (DST_UNIT));
+ else
+ memory =
+ (DST_UNIT *) realloc (result, allocated * sizeof (DST_UNIT));
+
+ if (memory == NULL)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ errno = ENOMEM;
+ return NULL;
+ }
+ if (result == resultbuf && length > 0)
+ memcpy ((char *) memory, (char *) result,
+ length * sizeof (DST_UNIT));
+ result = memory;
+ count = u8_uctomb (result + length, uc, allocated - length);
+ if (count < 0)
+ abort ();
+ }
+ length += count;
+ }
+
+ if (length == 0)
+ {
+ if (result == NULL)
+ {
+ /* Return a non-NULL value. NULL means error. */
+ result = (DST_UNIT *) malloc (1);
+ if (result == NULL)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+ }
+ else if (result != resultbuf && length < allocated)
+ {
+ /* Shrink the allocated memory if possible. */
+ DST_UNIT *memory;
+
+ memory = (DST_UNIT *) realloc (result, length * sizeof (DST_UNIT));
+ if (memory != NULL)
+ result = memory;
+ }
+
+ *lengthp = length;
+ return result;
+}
diff --git a/lib/unistring/unistr/u16-uctomb-aux.c b/lib/unistring/unistr/u16-uctomb-aux.c
new file mode 100644
index 0000000..5294030
--- /dev/null
+++ b/lib/unistring/unistr/u16-uctomb-aux.c
@@ -0,0 +1,67 @@
+/* Conversion UCS-4 to UTF-16.
+ Copyright (C) 2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+int
+u16_uctomb_aux (uint16_t *s, ucs4_t uc, ptrdiff_t n)
+{
+ if (uc < 0xd800)
+ {
+ /* The case n >= 1 is already handled by the caller. */
+ }
+ else if (uc < 0x10000)
+ {
+ if (uc >= 0xe000)
+ {
+ if (n >= 1)
+ {
+ s[0] = uc;
+ return 1;
+ }
+ }
+ else
+ return -1;
+ }
+ else
+ {
+ if (uc < 0x110000)
+ {
+ if (n >= 2)
+ {
+ s[0] = 0xd800 + ((uc - 0x10000) >> 10);
+ s[1] = 0xdc00 + ((uc - 0x10000) & 0x3ff);
+ return 2;
+ }
+ }
+ else
+ return -1;
+ }
+ return -2;
+}
diff --git a/lib/unistring/unistr/u16-uctomb.c b/lib/unistring/unistr/u16-uctomb.c
new file mode 100644
index 0000000..2a009d0
--- /dev/null
+++ b/lib/unistring/unistr/u16-uctomb.c
@@ -0,0 +1,81 @@
+/* Store a character in UTF-16 string.
+ Copyright (C) 2002, 2005-2006, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#if defined IN_LIBUNISTRING
+/* Tell unistr.h to declare u16_uctomb as 'extern', not 'static inline'. */
+# include "unistring-notinline.h"
+#endif
+
+/* Specification. */
+#include "unistr.h"
+
+#if !HAVE_INLINE
+
+int
+u16_uctomb (uint16_t *s, ucs4_t uc, ptrdiff_t n)
+{
+ if (uc < 0xd800)
+ {
+ if (n > 0)
+ {
+ s[0] = uc;
+ return 1;
+ }
+ /* else return -2, below. */
+ }
+ else if (uc < 0x10000)
+ {
+ if (uc >= 0xe000)
+ {
+ if (n >= 1)
+ {
+ s[0] = uc;
+ return 1;
+ }
+ }
+ else
+ return -1;
+ }
+ else
+ {
+ if (uc < 0x110000)
+ {
+ if (n >= 2)
+ {
+ s[0] = 0xd800 + ((uc - 0x10000) >> 10);
+ s[1] = 0xdc00 + ((uc - 0x10000) & 0x3ff);
+ return 2;
+ }
+ }
+ else
+ return -1;
+ }
+ return -2;
+}
+
+#endif
diff --git a/lib/unistring/unistr/u32-cpy.c b/lib/unistring/unistr/u32-cpy.c
new file mode 100644
index 0000000..2ad503c
--- /dev/null
+++ b/lib/unistring/unistr/u32-cpy.c
@@ -0,0 +1,34 @@
+/* Copy piece of UTF-32 string.
+ Copyright (C) 1999, 2002, 2006, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+#define FUNC u32_cpy
+#define UNIT uint32_t
+#include "u-cpy.h"
diff --git a/lib/unistring/unistr/u32-mbtouc-unsafe.c b/lib/unistring/unistr/u32-mbtouc-unsafe.c
new file mode 100644
index 0000000..23d1512
--- /dev/null
+++ b/lib/unistring/unistr/u32-mbtouc-unsafe.c
@@ -0,0 +1,53 @@
+/* Look at first character in UTF-32 string.
+ Copyright (C) 2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#if defined IN_LIBUNISTRING
+/* Tell unistr.h to declare u32_mbtouc_unsafe as 'extern', not
+ 'static inline'. */
+# include "unistring-notinline.h"
+#endif
+
+/* Specification. */
+#include "unistr.h"
+
+#if !HAVE_INLINE
+
+int
+u32_mbtouc_unsafe (ucs4_t *puc, const uint32_t *s, size_t n)
+{
+ uint32_t c = *s;
+
+ if (c < 0xd800 || (c >= 0xe000 && c < 0x110000))
+ *puc = c;
+ else
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 1;
+}
+
+#endif
diff --git a/lib/unistring/unistr/u32-to-u8.c b/lib/unistring/unistr/u32-to-u8.c
new file mode 100644
index 0000000..064edcf
--- /dev/null
+++ b/lib/unistring/unistr/u32-to-u8.c
@@ -0,0 +1,139 @@
+/* Convert UTF-32 string to UTF-8 string.
+ Copyright (C) 2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+#define FUNC u32_to_u8
+#define SRC_UNIT uint32_t
+#define DST_UNIT uint8_t
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+DST_UNIT *
+FUNC (const SRC_UNIT *s, size_t n, DST_UNIT *resultbuf, size_t *lengthp)
+{
+ const SRC_UNIT *s_end = s + n;
+ /* Output string accumulator. */
+ DST_UNIT *result;
+ size_t allocated;
+ size_t length;
+
+ if (resultbuf != NULL)
+ {
+ result = resultbuf;
+ allocated = *lengthp;
+ }
+ else
+ {
+ result = NULL;
+ allocated = 0;
+ }
+ length = 0;
+ /* Invariants:
+ result is either == resultbuf or == NULL or malloc-allocated.
+ If length > 0, then result != NULL. */
+
+ while (s < s_end)
+ {
+ ucs4_t uc;
+ int count;
+
+ /* Fetch a Unicode character from the input string. */
+ uc = *s++;
+ /* No need to call the safe variant u32_mbtouc, because
+ u8_uctomb will verify uc anyway. */
+
+ /* Store it in the output string. */
+ count = u8_uctomb (result + length, uc, allocated - length);
+ if (count == -1)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ errno = EILSEQ;
+ return NULL;
+ }
+ if (count == -2)
+ {
+ DST_UNIT *memory;
+
+ allocated = (allocated > 0 ? 2 * allocated : 12);
+ if (length + 6 > allocated)
+ allocated = length + 6;
+ if (result == resultbuf || result == NULL)
+ memory = (DST_UNIT *) malloc (allocated * sizeof (DST_UNIT));
+ else
+ memory =
+ (DST_UNIT *) realloc (result, allocated * sizeof (DST_UNIT));
+
+ if (memory == NULL)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ errno = ENOMEM;
+ return NULL;
+ }
+ if (result == resultbuf && length > 0)
+ memcpy ((char *) memory, (char *) result,
+ length * sizeof (DST_UNIT));
+ result = memory;
+ count = u8_uctomb (result + length, uc, allocated - length);
+ if (count < 0)
+ abort ();
+ }
+ length += count;
+ }
+
+ if (length == 0)
+ {
+ if (result == NULL)
+ {
+ /* Return a non-NULL value. NULL means error. */
+ result = (DST_UNIT *) malloc (1);
+ if (result == NULL)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+ }
+ else if (result != resultbuf && length < allocated)
+ {
+ /* Shrink the allocated memory if possible. */
+ DST_UNIT *memory;
+
+ memory = (DST_UNIT *) realloc (result, length * sizeof (DST_UNIT));
+ if (memory != NULL)
+ result = memory;
+ }
+
+ *lengthp = length;
+ return result;
+}
diff --git a/lib/unistring/unistr/u32-uctomb.c b/lib/unistring/unistr/u32-uctomb.c
new file mode 100644
index 0000000..2a64a93
--- /dev/null
+++ b/lib/unistring/unistr/u32-uctomb.c
@@ -0,0 +1,56 @@
+/* Store a character in UTF-32 string.
+ Copyright (C) 2002, 2005-2006, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#if defined IN_LIBUNISTRING
+/* Tell unistr.h to declare u32_uctomb as 'extern', not 'static inline'. */
+# include "unistring-notinline.h"
+#endif
+
+/* Specification. */
+#include "unistr.h"
+
+#if !HAVE_INLINE
+
+int
+u32_uctomb (uint32_t *s, ucs4_t uc, ptrdiff_t n)
+{
+ if (uc < 0xd800 || (uc >= 0xe000 && uc < 0x110000))
+ {
+ if (n > 0)
+ {
+ *s = uc;
+ return 1;
+ }
+ else
+ return -2;
+ }
+ else
+ return -1;
+}
+
+#endif
diff --git a/lib/unistring/unistr/u8-check.c b/lib/unistring/unistr/u8-check.c
new file mode 100644
index 0000000..c1d69ee
--- /dev/null
+++ b/lib/unistring/unistr/u8-check.c
@@ -0,0 +1,86 @@
+/* Check UTF-8 string.
+ Copyright (C) 2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+const uint8_t *
+u8_check (const uint8_t *s, size_t n)
+{
+ const uint8_t *s_end = s + n;
+
+ while (s < s_end)
+ {
+ /* Keep in sync with unistr.h and u8-mbtouc-aux.c. */
+ uint8_t c = *s;
+
+ if (c < 0x80)
+ {
+ s++;
+ continue;
+ }
+ if (c >= 0xc2)
+ {
+ if (c < 0xe0)
+ {
+ if (s + 2 <= s_end
+ && (s[1] ^ 0x80) < 0x40)
+ {
+ s += 2;
+ continue;
+ }
+ }
+ else if (c < 0xf0)
+ {
+ if (s + 3 <= s_end
+ && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+ && (c >= 0xe1 || s[1] >= 0xa0)
+ && (c != 0xed || s[1] < 0xa0))
+ {
+ s += 3;
+ continue;
+ }
+ }
+ else if (c < 0xf8)
+ {
+ if (s + 4 <= s_end
+ && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+ && (s[3] ^ 0x80) < 0x40
+ && (c >= 0xf1 || s[1] >= 0x90)
+ && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90)))
+ {
+ s += 4;
+ continue;
+ }
+ }
+ }
+ /* invalid or incomplete multibyte character */
+ return s;
+ }
+ return NULL;
+}
diff --git a/lib/unistring/unistr/u8-cpy.c b/lib/unistring/unistr/u8-cpy.c
new file mode 100644
index 0000000..ec77c4c
--- /dev/null
+++ b/lib/unistring/unistr/u8-cpy.c
@@ -0,0 +1,34 @@
+/* Copy piece of UTF-8 string.
+ Copyright (C) 2002, 2006, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+#define FUNC u8_cpy
+#define UNIT uint8_t
+#include "u-cpy.h"
diff --git a/lib/unistring/unistr/u8-mbtouc-unsafe-aux.c b/lib/unistring/unistr/u8-mbtouc-unsafe-aux.c
new file mode 100644
index 0000000..b24dfcc
--- /dev/null
+++ b/lib/unistring/unistr/u8-mbtouc-unsafe-aux.c
@@ -0,0 +1,148 @@
+/* Conversion UTF-8 to UCS-4.
+ Copyright (C) 2001-2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2001.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+#if defined IN_LIBUNISTRING || HAVE_INLINE
+
+int
+u8_mbtouc_unsafe_aux (ucs4_t *puc, const uint8_t *s, size_t n)
+{
+ uint8_t c = *s;
+
+ if (c >= 0xc2)
+ {
+ if (c < 0xe0)
+ {
+ if (n >= 2)
+ {
+ if ((s[1] ^ 0x80) < 0x40)
+ {
+ *puc = ((unsigned int) (c & 0x1f) << 6)
+ | (unsigned int) (s[1] ^ 0x80);
+ return 2;
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ *puc = 0xfffd;
+ return 1;
+ }
+ }
+ else if (c < 0xf0)
+ {
+ if (n >= 3)
+ {
+ if ((s[1] ^ 0x80) < 0x40)
+ {
+ if ((s[2] ^ 0x80) < 0x40)
+ {
+ if ((c >= 0xe1 || s[1] >= 0xa0)
+ && (c != 0xed || s[1] < 0xa0))
+ {
+ *puc = ((unsigned int) (c & 0x0f) << 12)
+ | ((unsigned int) (s[1] ^ 0x80) << 6)
+ | (unsigned int) (s[2] ^ 0x80);
+ return 3;
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 3;
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 2;
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ *puc = 0xfffd;
+ if (n == 1 || (s[1] ^ 0x80) >= 0x40)
+ return 1;
+ else
+ return 2;
+ }
+ }
+ else if (c < 0xf8)
+ {
+ if (n >= 4)
+ {
+ if ((s[1] ^ 0x80) < 0x40)
+ {
+ if ((s[2] ^ 0x80) < 0x40)
+ {
+ if ((s[3] ^ 0x80) < 0x40)
+ {
+ if ((c >= 0xf1 || s[1] >= 0x90)
+ && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90))
+ )
+ {
+ *puc = ((unsigned int) (c & 0x07) << 18)
+ | ((unsigned int) (s[1] ^ 0x80) << 12)
+ | ((unsigned int) (s[2] ^ 0x80) << 6)
+ | (unsigned int) (s[3] ^ 0x80);
+ return 4;
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 4;
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 3;
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 2;
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ *puc = 0xfffd;
+ if (n == 1 || (s[1] ^ 0x80) >= 0x40)
+ return 1;
+ else if (n == 2 || (s[2] ^ 0x80) >= 0x40)
+ return 2;
+ else
+ return 3;
+ }
+ }
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 1;
+}
+
+#endif
diff --git a/lib/unistring/unistr/u8-mbtouc-unsafe.c b/lib/unistring/unistr/u8-mbtouc-unsafe.c
new file mode 100644
index 0000000..b98a0b9
--- /dev/null
+++ b/lib/unistring/unistr/u8-mbtouc-unsafe.c
@@ -0,0 +1,159 @@
+/* Look at first character in UTF-8 string.
+ Copyright (C) 1999-2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2001.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#if defined IN_LIBUNISTRING
+/* Tell unistr.h to declare u8_mbtouc_unsafe as 'extern', not
+ 'static inline'. */
+# include "unistring-notinline.h"
+#endif
+
+/* Specification. */
+#include "unistr.h"
+
+#if !HAVE_INLINE
+
+int
+u8_mbtouc_unsafe (ucs4_t *puc, const uint8_t *s, size_t n)
+{
+ uint8_t c = *s;
+
+ if (c < 0x80)
+ {
+ *puc = c;
+ return 1;
+ }
+ else if (c >= 0xc2)
+ {
+ if (c < 0xe0)
+ {
+ if (n >= 2)
+ {
+ if ((s[1] ^ 0x80) < 0x40)
+ {
+ *puc = ((unsigned int) (c & 0x1f) << 6)
+ | (unsigned int) (s[1] ^ 0x80);
+ return 2;
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ *puc = 0xfffd;
+ return 1;
+ }
+ }
+ else if (c < 0xf0)
+ {
+ if (n >= 3)
+ {
+ if ((s[1] ^ 0x80) < 0x40)
+ {
+ if ((s[2] ^ 0x80) < 0x40)
+ {
+ if ((c >= 0xe1 || s[1] >= 0xa0)
+ && (c != 0xed || s[1] < 0xa0))
+ {
+ *puc = ((unsigned int) (c & 0x0f) << 12)
+ | ((unsigned int) (s[1] ^ 0x80) << 6)
+ | (unsigned int) (s[2] ^ 0x80);
+ return 3;
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 3;
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 2;
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ *puc = 0xfffd;
+ if (n == 1 || (s[1] ^ 0x80) >= 0x40)
+ return 1;
+ else
+ return 2;
+ }
+ }
+ else if (c < 0xf8)
+ {
+ if (n >= 4)
+ {
+ if ((s[1] ^ 0x80) < 0x40)
+ {
+ if ((s[2] ^ 0x80) < 0x40)
+ {
+ if ((s[3] ^ 0x80) < 0x40)
+ {
+ if ((c >= 0xf1 || s[1] >= 0x90)
+ && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90))
+ )
+ {
+ *puc = ((unsigned int) (c & 0x07) << 18)
+ | ((unsigned int) (s[1] ^ 0x80) << 12)
+ | ((unsigned int) (s[2] ^ 0x80) << 6)
+ | (unsigned int) (s[3] ^ 0x80);
+ return 4;
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 4;
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 3;
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 2;
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ *puc = 0xfffd;
+ if (n == 1 || (s[1] ^ 0x80) >= 0x40)
+ return 1;
+ else if (n == 2 || (s[2] ^ 0x80) >= 0x40)
+ return 2;
+ else
+ return 3;
+ }
+ }
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return 1;
+}
+
+#endif
diff --git a/lib/unistring/unistr/u8-mbtoucr.c b/lib/unistring/unistr/u8-mbtoucr.c
new file mode 100644
index 0000000..47d63d4
--- /dev/null
+++ b/lib/unistring/unistr/u8-mbtoucr.c
@@ -0,0 +1,151 @@
+/* Look at first character in UTF-8 string, returning an error code.
+ Copyright (C) 1999-2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2001.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+int
+u8_mbtoucr (ucs4_t *puc, const uint8_t *s, size_t n)
+{
+ uint8_t c = *s;
+
+ if (c < 0x80)
+ {
+ *puc = c;
+ return 1;
+ }
+ else if (c >= 0xc2)
+ {
+ if (c < 0xe0)
+ {
+ if (n >= 2)
+ {
+ if ((s[1] ^ 0x80) < 0x40)
+ {
+ *puc = ((unsigned int) (c & 0x1f) << 6)
+ | (unsigned int) (s[1] ^ 0x80);
+ return 2;
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ *puc = 0xfffd;
+ return -2;
+ }
+ }
+ else if (c < 0xf0)
+ {
+ if (n >= 2)
+ {
+ if ((s[1] ^ 0x80) < 0x40
+ && (c >= 0xe1 || s[1] >= 0xa0)
+ && (c != 0xed || s[1] < 0xa0))
+ {
+ if (n >= 3)
+ {
+ if ((s[2] ^ 0x80) < 0x40)
+ {
+ *puc = ((unsigned int) (c & 0x0f) << 12)
+ | ((unsigned int) (s[1] ^ 0x80) << 6)
+ | (unsigned int) (s[2] ^ 0x80);
+ return 3;
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ *puc = 0xfffd;
+ return -2;
+ }
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ *puc = 0xfffd;
+ return -2;
+ }
+ }
+ else if (c < 0xf8)
+ {
+ if (n >= 2)
+ {
+ if ((s[1] ^ 0x80) < 0x40
+ && (c >= 0xf1 || s[1] >= 0x90)
+ && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90)))
+ {
+ if (n >= 3)
+ {
+ if ((s[2] ^ 0x80) < 0x40)
+ {
+ if (n >= 4)
+ {
+ if ((s[3] ^ 0x80) < 0x40)
+ {
+ *puc = ((unsigned int) (c & 0x07) << 18)
+ | ((unsigned int) (s[1] ^ 0x80) << 12)
+ | ((unsigned int) (s[2] ^ 0x80) << 6)
+ | (unsigned int) (s[3] ^ 0x80);
+ return 4;
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ *puc = 0xfffd;
+ return -2;
+ }
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ *puc = 0xfffd;
+ return -2;
+ }
+ }
+ /* invalid multibyte character */
+ }
+ else
+ {
+ /* incomplete multibyte character */
+ *puc = 0xfffd;
+ return -2;
+ }
+ }
+ }
+ /* invalid multibyte character */
+ *puc = 0xfffd;
+ return -1;
+}
diff --git a/lib/unistring/unistr/u8-to-u16.c b/lib/unistring/unistr/u8-to-u16.c
new file mode 100644
index 0000000..ef728ff
--- /dev/null
+++ b/lib/unistring/unistr/u8-to-u16.c
@@ -0,0 +1,145 @@
+/* Convert UTF-8 string to UTF-16 string.
+ Copyright (C) 2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+#define FUNC u8_to_u16
+#define SRC_UNIT uint8_t
+#define DST_UNIT uint16_t
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+DST_UNIT *
+FUNC (const SRC_UNIT *s, size_t n, DST_UNIT *resultbuf, size_t *lengthp)
+{
+ const SRC_UNIT *s_end = s + n;
+ /* Output string accumulator. */
+ DST_UNIT *result;
+ size_t allocated;
+ size_t length;
+
+ if (resultbuf != NULL)
+ {
+ result = resultbuf;
+ allocated = *lengthp;
+ }
+ else
+ {
+ result = NULL;
+ allocated = 0;
+ }
+ length = 0;
+ /* Invariants:
+ result is either == resultbuf or == NULL or malloc-allocated.
+ If length > 0, then result != NULL. */
+
+ while (s < s_end)
+ {
+ ucs4_t uc;
+ int count;
+
+ /* Fetch a Unicode character from the input string. */
+ count = u8_mbtoucr (&uc, s, s_end - s);
+ if (count < 0)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ errno = EILSEQ;
+ return NULL;
+ }
+ s += count;
+
+ /* Store it in the output string. */
+ count = u16_uctomb (result + length, uc, allocated - length);
+ if (count == -1)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ errno = EILSEQ;
+ return NULL;
+ }
+ if (count == -2)
+ {
+ DST_UNIT *memory;
+
+ allocated = (allocated > 0 ? 2 * allocated : 12);
+ if (length + 2 > allocated)
+ allocated = length + 2;
+ if (result == resultbuf || result == NULL)
+ memory = (DST_UNIT *) malloc (allocated * sizeof (DST_UNIT));
+ else
+ memory =
+ (DST_UNIT *) realloc (result, allocated * sizeof (DST_UNIT));
+
+ if (memory == NULL)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ errno = ENOMEM;
+ return NULL;
+ }
+ if (result == resultbuf && length > 0)
+ memcpy ((char *) memory, (char *) result,
+ length * sizeof (DST_UNIT));
+ result = memory;
+ count = u16_uctomb (result + length, uc, allocated - length);
+ if (count < 0)
+ abort ();
+ }
+ length += count;
+ }
+
+ if (length == 0)
+ {
+ if (result == NULL)
+ {
+ /* Return a non-NULL value. NULL means error. */
+ result = (DST_UNIT *) malloc (1);
+ if (result == NULL)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+ }
+ else if (result != resultbuf && length < allocated)
+ {
+ /* Shrink the allocated memory if possible. */
+ DST_UNIT *memory;
+
+ memory = (DST_UNIT *) realloc (result, length * sizeof (DST_UNIT));
+ if (memory != NULL)
+ result = memory;
+ }
+
+ *lengthp = length;
+ return result;
+}
diff --git a/lib/unistring/unistr/u8-to-u32.c b/lib/unistring/unistr/u8-to-u32.c
new file mode 100644
index 0000000..b947c6c
--- /dev/null
+++ b/lib/unistring/unistr/u8-to-u32.c
@@ -0,0 +1,134 @@
+/* Convert UTF-8 string to UTF-32 string.
+ Copyright (C) 2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+#define FUNC u8_to_u32
+#define SRC_UNIT uint8_t
+#define DST_UNIT uint32_t
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+DST_UNIT *
+FUNC (const SRC_UNIT *s, size_t n, DST_UNIT *resultbuf, size_t *lengthp)
+{
+ const SRC_UNIT *s_end = s + n;
+ /* Output string accumulator. */
+ DST_UNIT *result;
+ size_t allocated;
+ size_t length;
+
+ if (resultbuf != NULL)
+ {
+ result = resultbuf;
+ allocated = *lengthp;
+ }
+ else
+ {
+ result = NULL;
+ allocated = 0;
+ }
+ length = 0;
+ /* Invariants:
+ result is either == resultbuf or == NULL or malloc-allocated.
+ If length > 0, then result != NULL. */
+
+ while (s < s_end)
+ {
+ ucs4_t uc;
+ int count;
+
+ /* Fetch a Unicode character from the input string. */
+ count = u8_mbtoucr (&uc, s, s_end - s);
+ if (count < 0)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ errno = EILSEQ;
+ return NULL;
+ }
+ s += count;
+
+ /* Store it in the output string. */
+ if (length + 1 > allocated)
+ {
+ DST_UNIT *memory;
+
+ allocated = (allocated > 0 ? 2 * allocated : 12);
+ if (length + 1 > allocated)
+ allocated = length + 1;
+ if (result == resultbuf || result == NULL)
+ memory = (DST_UNIT *) malloc (allocated * sizeof (DST_UNIT));
+ else
+ memory =
+ (DST_UNIT *) realloc (result, allocated * sizeof (DST_UNIT));
+
+ if (memory == NULL)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ errno = ENOMEM;
+ return NULL;
+ }
+ if (result == resultbuf && length > 0)
+ memcpy ((char *) memory, (char *) result,
+ length * sizeof (DST_UNIT));
+ result = memory;
+ }
+ result[length++] = uc;
+ }
+
+ if (length == 0)
+ {
+ if (result == NULL)
+ {
+ /* Return a non-NULL value. NULL means error. */
+ result = (DST_UNIT *) malloc (1);
+ if (result == NULL)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+ }
+ else if (result != resultbuf && length < allocated)
+ {
+ /* Shrink the allocated memory if possible. */
+ DST_UNIT *memory;
+
+ memory = (DST_UNIT *) realloc (result, length * sizeof (DST_UNIT));
+ if (memory != NULL)
+ result = memory;
+ }
+
+ *lengthp = length;
+ return result;
+}
diff --git a/lib/unistring/unistr/u8-uctomb-aux.c b/lib/unistring/unistr/u8-uctomb-aux.c
new file mode 100644
index 0000000..3e4e29c
--- /dev/null
+++ b/lib/unistring/unistr/u8-uctomb-aux.c
@@ -0,0 +1,69 @@
+/* Conversion UCS-4 to UTF-8.
+ Copyright (C) 2002, 2006-2007, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistr.h"
+
+#include "attribute.h"
+
+int
+u8_uctomb_aux (uint8_t *s, ucs4_t uc, ptrdiff_t n)
+{
+ int count;
+
+ if (uc < 0x80)
+ /* The case n >= 1 is already handled by the caller. */
+ return -2;
+ else if (uc < 0x800)
+ count = 2;
+ else if (uc < 0x10000)
+ {
+ if (uc < 0xd800 || uc >= 0xe000)
+ count = 3;
+ else
+ return -1;
+ }
+ else if (uc < 0x110000)
+ count = 4;
+ else
+ return -1;
+
+ if (n < count)
+ return -2;
+
+ switch (count) /* note: code falls through cases! */
+ {
+ case 4: s[3] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x10000;
+ FALLTHROUGH;
+ case 3: s[2] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x800;
+ FALLTHROUGH;
+ case 2: s[1] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0xc0;
+ /*case 1:*/ s[0] = uc;
+ }
+ return count;
+}
diff --git a/lib/unistring/unistr/u8-uctomb.c b/lib/unistring/unistr/u8-uctomb.c
new file mode 100644
index 0000000..55ff3d6
--- /dev/null
+++ b/lib/unistring/unistr/u8-uctomb.c
@@ -0,0 +1,88 @@
+/* Store a character in UTF-8 string.
+ Copyright (C) 2002, 2005-2006, 2009-2021 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2002.
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#if defined IN_LIBUNISTRING
+/* Tell unistr.h to declare u8_uctomb as 'extern', not 'static inline'. */
+# include "unistring-notinline.h"
+#endif
+
+/* Specification. */
+#include "unistr.h"
+
+#include "attribute.h"
+
+#if !HAVE_INLINE
+
+int
+u8_uctomb (uint8_t *s, ucs4_t uc, ptrdiff_t n)
+{
+ if (uc < 0x80)
+ {
+ if (n > 0)
+ {
+ s[0] = uc;
+ return 1;
+ }
+ /* else return -2, below. */
+ }
+ else
+ {
+ int count;
+
+ if (uc < 0x800)
+ count = 2;
+ else if (uc < 0x10000)
+ {
+ if (uc < 0xd800 || uc >= 0xe000)
+ count = 3;
+ else
+ return -1;
+ }
+ else if (uc < 0x110000)
+ count = 4;
+ else
+ return -1;
+
+ if (n >= count)
+ {
+ switch (count) /* note: code falls through cases! */
+ {
+ case 4: s[3] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x10000;
+ FALLTHROUGH;
+ case 3: s[2] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x800;
+ FALLTHROUGH;
+ case 2: s[1] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0xc0;
+ /*case 1:*/ s[0] = uc;
+ }
+ return count;
+ }
+ }
+ return -2;
+}
+
+#endif