From: Jeff Davis Date: Wed, 10 Dec 2025 19:56:11 +0000 (-0800) Subject: Add pg_iswcased(). X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=630706ced04e3a7a7f0070f4e8fb88f7503a1016;p=postgresql.git Add pg_iswcased(). True if character has multiple case forms. Will be a useful multibyte-aware replacement for char_is_cased(). Reviewed-by: Chao Li Reviewed-by: Peter Eisentraut Discussion: https://postgr.es/m/450ceb6260cad30d7afdf155d991a9caafee7c0d.camel@j-davis.com --- diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c index b00663b9585..70933ee3843 100644 --- a/src/backend/utils/adt/pg_locale.c +++ b/src/backend/utils/adt/pg_locale.c @@ -1588,6 +1588,17 @@ pg_iswxdigit(pg_wchar wc, pg_locale_t locale) return locale->ctype->wc_isxdigit(wc, locale); } +bool +pg_iswcased(pg_wchar wc, pg_locale_t locale) +{ + /* for the C locale, Cased and Alpha are equivalent */ + if (locale->ctype == NULL) + return (wc <= (pg_wchar) 127 && + (pg_char_properties[wc] & PG_ISALPHA)); + else + return locale->ctype->wc_iscased(wc, locale); +} + pg_wchar pg_towupper(pg_wchar wc, pg_locale_t locale) { diff --git a/src/backend/utils/adt/pg_locale_builtin.c b/src/backend/utils/adt/pg_locale_builtin.c index 1021e0d129b..0d4c754a267 100644 --- a/src/backend/utils/adt/pg_locale_builtin.c +++ b/src/backend/utils/adt/pg_locale_builtin.c @@ -185,6 +185,12 @@ wc_isxdigit_builtin(pg_wchar wc, pg_locale_t locale) return pg_u_isxdigit(to_char32(wc), !locale->builtin.casemap_full); } +static bool +wc_iscased_builtin(pg_wchar wc, pg_locale_t locale) +{ + return pg_u_prop_cased(to_char32(wc)); +} + static bool char_is_cased_builtin(char ch, pg_locale_t locale) { @@ -220,6 +226,7 @@ static const struct ctype_methods ctype_methods_builtin = { .wc_isspace = wc_isspace_builtin, .wc_isxdigit = wc_isxdigit_builtin, .char_is_cased = char_is_cased_builtin, + .wc_iscased = wc_iscased_builtin, .wc_tolower = wc_tolower_builtin, .wc_toupper = wc_toupper_builtin, }; diff --git a/src/backend/utils/adt/pg_locale_icu.c b/src/backend/utils/adt/pg_locale_icu.c index f5a0cc8fe41..e8820666b2d 100644 --- a/src/backend/utils/adt/pg_locale_icu.c +++ b/src/backend/utils/adt/pg_locale_icu.c @@ -223,6 +223,12 @@ wc_isxdigit_icu(pg_wchar wc, pg_locale_t locale) return u_isxdigit(wc); } +static bool +wc_iscased_icu(pg_wchar wc, pg_locale_t locale) +{ + return u_hasBinaryProperty(wc, UCHAR_CASED); +} + static const struct ctype_methods ctype_methods_icu = { .strlower = strlower_icu, .strtitle = strtitle_icu, @@ -239,6 +245,7 @@ static const struct ctype_methods ctype_methods_icu = { .wc_isspace = wc_isspace_icu, .wc_isxdigit = wc_isxdigit_icu, .char_is_cased = char_is_cased_icu, + .wc_iscased = wc_iscased_icu, .wc_toupper = toupper_icu, .wc_tolower = tolower_icu, }; diff --git a/src/backend/utils/adt/pg_locale_libc.c b/src/backend/utils/adt/pg_locale_libc.c index fa871690e0c..3d841f818a5 100644 --- a/src/backend/utils/adt/pg_locale_libc.c +++ b/src/backend/utils/adt/pg_locale_libc.c @@ -184,6 +184,13 @@ wc_isxdigit_libc_sb(pg_wchar wc, pg_locale_t locale) #endif } +static bool +wc_iscased_libc_sb(pg_wchar wc, pg_locale_t locale) +{ + return isupper_l((unsigned char) wc, locale->lt) || + islower_l((unsigned char) wc, locale->lt); +} + static bool wc_isdigit_libc_mb(pg_wchar wc, pg_locale_t locale) { @@ -248,6 +255,13 @@ wc_isxdigit_libc_mb(pg_wchar wc, pg_locale_t locale) #endif } +static bool +wc_iscased_libc_mb(pg_wchar wc, pg_locale_t locale) +{ + return iswupper_l((wint_t) wc, locale->lt) || + iswlower_l((wint_t) wc, locale->lt); +} + static bool char_is_cased_libc(char ch, pg_locale_t locale) { @@ -332,6 +346,7 @@ static const struct ctype_methods ctype_methods_libc_sb = { .wc_isspace = wc_isspace_libc_sb, .wc_isxdigit = wc_isxdigit_libc_sb, .char_is_cased = char_is_cased_libc, + .wc_iscased = wc_iscased_libc_sb, .wc_toupper = toupper_libc_sb, .wc_tolower = tolower_libc_sb, }; @@ -357,6 +372,7 @@ static const struct ctype_methods ctype_methods_libc_other_mb = { .wc_isspace = wc_isspace_libc_sb, .wc_isxdigit = wc_isxdigit_libc_sb, .char_is_cased = char_is_cased_libc, + .wc_iscased = wc_iscased_libc_sb, .wc_toupper = toupper_libc_sb, .wc_tolower = tolower_libc_sb, }; @@ -378,6 +394,7 @@ static const struct ctype_methods ctype_methods_libc_utf8 = { .wc_isspace = wc_isspace_libc_mb, .wc_isxdigit = wc_isxdigit_libc_mb, .char_is_cased = char_is_cased_libc, + .wc_iscased = wc_iscased_libc_mb, .wc_toupper = toupper_libc_mb, .wc_tolower = tolower_libc_mb, }; diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h index 50520e50127..832007385d8 100644 --- a/src/include/utils/pg_locale.h +++ b/src/include/utils/pg_locale.h @@ -122,6 +122,7 @@ struct ctype_methods bool (*wc_ispunct) (pg_wchar wc, pg_locale_t locale); bool (*wc_isspace) (pg_wchar wc, pg_locale_t locale); bool (*wc_isxdigit) (pg_wchar wc, pg_locale_t locale); + bool (*wc_iscased) (pg_wchar wc, pg_locale_t locale); pg_wchar (*wc_toupper) (pg_wchar wc, pg_locale_t locale); pg_wchar (*wc_tolower) (pg_wchar wc, pg_locale_t locale); @@ -214,6 +215,7 @@ extern bool pg_iswprint(pg_wchar wc, pg_locale_t locale); extern bool pg_iswpunct(pg_wchar wc, pg_locale_t locale); extern bool pg_iswspace(pg_wchar wc, pg_locale_t locale); extern bool pg_iswxdigit(pg_wchar wc, pg_locale_t locale); +extern bool pg_iswcased(pg_wchar wc, pg_locale_t locale); extern pg_wchar pg_towupper(pg_wchar wc, pg_locale_t locale); extern pg_wchar pg_towlower(pg_wchar wc, pg_locale_t locale);