diff options
author | Bruno Haible <bruno@clisp.org> | 2023-05-04 23:27:12 +0200 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2023-05-04 23:29:34 +0200 |
commit | 15880a3da91a0403eb287a84db90b54713ac4a09 (patch) | |
tree | 073cbfb1f015142cf598c710012db0243da45f10 | |
parent | 59f878fa3d175b2d085a01a8df786c9e40be14b9 (diff) | |
download | gnulib-15880a3da91a0403eb287a84db90b54713ac4a09.tar.gz |
c32swidth: New module.
* lib/uchar.in.h (c32swidth): New declaration.
* lib/wcswidth-impl.h: Use macros FUNC, UNIT, CHARACTER_WIDTH.
* lib/wcswidth.c: Define FUNC, UNIT, CHARACTER_WIDTH before including
wcswidth-impl.h.
* lib/c32swidth.c: New file.
* modules/c32swidth: New file.
* m4/uchar_h.m4 (gl_UCHAR_H_REQUIRE_DEFAULTS): Initialize
GNULIB_C32SWIDTH.
* modules/uchar (Makefile.am): Substitute GNULIB_C32SWIDTH.
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | lib/c32swidth.c | 43 | ||||
-rw-r--r-- | lib/uchar.in.h | 19 | ||||
-rw-r--r-- | lib/wcswidth-impl.h | 14 | ||||
-rw-r--r-- | lib/wcswidth.c | 3 | ||||
-rw-r--r-- | m4/uchar_h.m4 | 3 | ||||
-rw-r--r-- | modules/c32swidth | 36 | ||||
-rw-r--r-- | modules/uchar | 1 |
8 files changed, 124 insertions, 8 deletions
@@ -1,5 +1,18 @@ 2023-05-04 Bruno Haible <bruno@clisp.org> + c32swidth: New module. + * lib/uchar.in.h (c32swidth): New declaration. + * lib/wcswidth-impl.h: Use macros FUNC, UNIT, CHARACTER_WIDTH. + * lib/wcswidth.c: Define FUNC, UNIT, CHARACTER_WIDTH before including + wcswidth-impl.h. + * lib/c32swidth.c: New file. + * modules/c32swidth: New file. + * m4/uchar_h.m4 (gl_UCHAR_H_REQUIRE_DEFAULTS): Initialize + GNULIB_C32SWIDTH. + * modules/uchar (Makefile.am): Substitute GNULIB_C32SWIDTH. + +2023-05-04 Bruno Haible <bruno@clisp.org> + wcswidth: Fix result in case of overflow. * lib/wcswidth-impl.h (wcswidth): Continue searching for a non-printing wide character after the total width has become > INT_MAX. diff --git a/lib/c32swidth.c b/lib/c32swidth.c new file mode 100644 index 0000000000..2f7adcf74c --- /dev/null +++ b/lib/c32swidth.c @@ -0,0 +1,43 @@ +/* Determine number of screen columns needed for a size-bounded 32-bit wide string. + Copyright (C) 2023 Free Software Foundation, Inc. + + This file 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. + + This file 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> + +#define IN_C32SWIDTH +/* Specification. */ +#include <uchar.h> + +#if _GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t + +# include <wchar.h> + +_GL_EXTERN_INLINE +int +c32swidth (const char32_t *s, size_t n) +{ + return wcswidth ((const wchar_t *) s, n); +} + +#else + +# include <limits.h> + +# define FUNC c32swidth +# define UNIT char32_t +# define CHARACTER_WIDTH c32width +# include "wcswidth-impl.h" + +#endif diff --git a/lib/uchar.in.h b/lib/uchar.in.h index 3815af4c26..8bf6176b8c 100644 --- a/lib/uchar.in.h +++ b/lib/uchar.in.h @@ -494,6 +494,25 @@ _GL_CXXALIASWARN (c32stombs); #endif +/* Number of screen columns needed for a size-bounded 32-bit wide string. */ +#if @GNULIB_C32SWIDTH@ +# if (_GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t) && !defined IN_C32SWIDTH +_GL_BEGIN_C_LINKAGE +_GL_INLINE _GL_ARG_NONNULL ((1)) int +c32swidth (const char32_t *s, size_t n) +{ + return wcswidth ((const wchar_t *) s, n); +} +_GL_END_C_LINKAGE +# else +_GL_FUNCDECL_SYS (c32swidth, int, (const char32_t *s, size_t n) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (c32swidth, int, (const char32_t *s, size_t n)); +_GL_CXXALIASWARN (c32swidth); +#endif + + /* Converts a 32-bit wide character to unibyte character. Returns the single-byte representation of WC if it exists, or EOF otherwise. */ diff --git a/lib/wcswidth-impl.h b/lib/wcswidth-impl.h index a879bfdd93..34cb0b9814 100644 --- a/lib/wcswidth-impl.h +++ b/lib/wcswidth-impl.h @@ -16,16 +16,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ int -wcswidth (const wchar_t *s, size_t n) +FUNC (const UNIT *s, size_t n) { int count = 0; for (; n > 0; s++, n--) { - wchar_t c = *s; - if (c == (wchar_t)'\0') + UNIT c = *s; + if (c == (UNIT)'\0') break; { - int width = wcwidth (c); + int width = CHARACTER_WIDTH (c); if (width < 0) goto found_nonprinting; if (width > INT_MAX - count) @@ -39,11 +39,11 @@ wcswidth (const wchar_t *s, size_t n) Continue searching for a non-printing wide character. */ for (; n > 0; s++, n--) { - wchar_t c = *s; - if (c == (wchar_t)'\0') + UNIT c = *s; + if (c == (UNIT)'\0') break; { - int width = wcwidth (c); + int width = CHARACTER_WIDTH (c); if (width < 0) goto found_nonprinting; } diff --git a/lib/wcswidth.c b/lib/wcswidth.c index 8188e380fd..408b826c62 100644 --- a/lib/wcswidth.c +++ b/lib/wcswidth.c @@ -22,4 +22,7 @@ #include <limits.h> +#define FUNC wcswidth +#define UNIT wchar_t +#define CHARACTER_WIDTH wcwidth #include "wcswidth-impl.h" diff --git a/m4/uchar_h.m4 b/m4/uchar_h.m4 index 5c04e2a6ee..0a48eb20c4 100644 --- a/m4/uchar_h.m4 +++ b/m4/uchar_h.m4 @@ -1,4 +1,4 @@ -# uchar_h.m4 serial 25 +# uchar_h.m4 serial 26 dnl Copyright (C) 2019-2023 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -221,6 +221,7 @@ AC_DEFUN([gl_UCHAR_H_REQUIRE_DEFAULTS], gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_C32SNRTOMBS]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_C32SRTOMBS]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_C32STOMBS]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_C32SWIDTH]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_C32TOB]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBRTOC32]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSNRTOC32S]) diff --git a/modules/c32swidth b/modules/c32swidth new file mode 100644 index 0000000000..df60f6b473 --- /dev/null +++ b/modules/c32swidth @@ -0,0 +1,36 @@ +Description: +c32swidth() function: Determine the number of screen columns needed for +a size-bounded 32-bit wide string. + +Files: +lib/c32swidth.c +lib/wcswidth-impl.h + +Depends-on: +uchar +wchar +wcswidth +c32width + +configure.ac: +AC_REQUIRE([gl_UCHAR_H]) +dnl Determine REPLACE_MBSTATE_T, from which GNULIB_defined_mbstate_t is +dnl determined. It describes how mbrtoc32 is implemented. +AC_REQUIRE([gl_MBSTATE_T_BROKEN]) +AC_REQUIRE([gl_MBRTOC32_SANITYCHECK]) +gl_UCHAR_MODULE_INDICATOR([c32swidth]) + +Makefile.am: +lib_SOURCES += c32swidth.c + +Include: +<uchar.h> + +Link: +$(LTLIBUNISTRING) when linking with libtool, $(LIBUNISTRING) otherwise + +License: +LGPLv2+ + +Maintainer: +Bruno Haible diff --git a/modules/uchar b/modules/uchar index 3c6f3963b9..948bcd7993 100644 --- a/modules/uchar +++ b/modules/uchar @@ -58,6 +58,7 @@ uchar.h: uchar.in.h $(top_builddir)/config.status $(CXXDEFS_H) -e 's/@''GNULIB_C32SNRTOMBS''@/$(GNULIB_C32SNRTOMBS)/g' \ -e 's/@''GNULIB_C32SRTOMBS''@/$(GNULIB_C32SRTOMBS)/g' \ -e 's/@''GNULIB_C32STOMBS''@/$(GNULIB_C32STOMBS)/g' \ + -e 's/@''GNULIB_C32SWIDTH''@/$(GNULIB_C32SWIDTH)/g' \ -e 's/@''GNULIB_C32TOB''@/$(GNULIB_C32TOB)/g' \ -e 's/@''GNULIB_MBRTOC32''@/$(GNULIB_MBRTOC32)/g' \ -e 's/@''GNULIB_MBSNRTOC32S''@/$(GNULIB_MBSNRTOC32S)/g' \ |