diff options
Diffstat (limited to 'libguile/i18n.c')
-rw-r--r-- | libguile/i18n.c | 238 |
1 files changed, 141 insertions, 97 deletions
diff --git a/libguile/i18n.c b/libguile/i18n.c index 3a6cb0687..b689cafc3 100644 --- a/libguile/i18n.c +++ b/libguile/i18n.c @@ -1098,22 +1098,17 @@ u32_locale_tocase (const scm_t_uint32 *c_s1, size_t len, } - -SCM_DEFINE (scm_char_locale_downcase, "char-locale-downcase", 1, 1, 0, - (SCM chr, SCM locale), - "Return the lowercase character that corresponds to @var{chr} " - "according to either @var{locale} or the current locale.") -#define FUNC_NAME s_scm_char_locale_downcase +static SCM +chr_to_case (SCM chr, scm_t_locale c_locale, + scm_t_uint32 *(*func) (const scm_t_uint32 *, size_t, const char *, + uninorm_t, scm_t_uint32 *, size_t *), + int *err) { int ret; - scm_t_locale c_locale; scm_t_wchar *buf; - scm_t_uint32 *downbuf; - size_t downlen; - SCM str, downchar; - - SCM_VALIDATE_CHAR (1, chr); - SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale); + scm_t_uint32 *convbuf; + size_t convlen; + SCM str, convchar; str = scm_i_make_wide_string (1, &buf); buf[0] = SCM_CHAR (chr); @@ -1121,26 +1116,49 @@ SCM_DEFINE (scm_char_locale_downcase, "char-locale-downcase", 1, 1, 0, if (c_locale != NULL) RUN_IN_LOCALE_SECTION (c_locale, ret = u32_locale_tocase ((scm_t_uint32 *) buf, 1, - &downbuf, - &downlen, u32_tolower)); + &convbuf, + &convlen, func)); else ret = - u32_locale_tocase ((scm_t_uint32 *) buf, 1, &downbuf, - &downlen, u32_tolower); + u32_locale_tocase ((scm_t_uint32 *) buf, 1, &convbuf, + &convlen, func); if (SCM_UNLIKELY (ret != 0)) { - errno = ret; - scm_syserror (FUNC_NAME); + *err = ret; + return NULL; } - if (downlen == 1) - downchar = SCM_MAKE_CHAR ((scm_t_wchar) downbuf[0]); + if (convlen == 1) + convchar = SCM_MAKE_CHAR ((scm_t_wchar) convbuf[0]); else - downchar = chr; - free (downbuf); + convchar = chr; + free (convbuf); + + return convchar; +} + +SCM_DEFINE (scm_char_locale_downcase, "char-locale-downcase", 1, 1, 0, + (SCM chr, SCM locale), + "Return the lowercase character that corresponds to @var{chr} " + "according to either @var{locale} or the current locale.") +#define FUNC_NAME s_scm_char_locale_downcase +{ + scm_t_locale c_locale; + SCM ret; + int err = 0; + + SCM_VALIDATE_CHAR (1, chr); + SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale); - return downchar; + ret = chr_to_case (chr, c_locale, u32_tolower, &err); + + if (err != 0) + { + errno = err; + scm_syserror (FUNC_NAME); + } + return ret; } #undef FUNC_NAME @@ -1150,59 +1168,60 @@ SCM_DEFINE (scm_char_locale_upcase, "char-locale-upcase", 1, 1, 0, "according to either @var{locale} or the current locale.") #define FUNC_NAME s_scm_char_locale_upcase { - int ret; scm_t_locale c_locale; - scm_t_wchar *buf; - scm_t_uint32 *upbuf; - size_t uplen; - SCM str, upchar; + SCM ret; + int err = 0; SCM_VALIDATE_CHAR (1, chr); SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale); - str = scm_i_make_wide_string (1, &buf); - buf[0] = SCM_CHAR (chr); + ret = chr_to_case (chr, c_locale, u32_toupper, &err); - if (c_locale != NULL) - RUN_IN_LOCALE_SECTION (c_locale, ret = - u32_locale_tocase ((scm_t_uint32 *) buf, 1, - &upbuf, - &uplen, u32_toupper)); - else - ret = - u32_locale_tocase ((scm_t_uint32 *) buf, 1, &upbuf, - &uplen, u32_toupper); + if (err != 0) + { + errno = err; + scm_syserror (FUNC_NAME); + } + return ret; +} +#undef FUNC_NAME - if (SCM_UNLIKELY (ret != 0)) +SCM_DEFINE (scm_char_locale_titlecase, "char-locale-titlecase", 1, 1, 0, + (SCM chr, SCM locale), + "Return the titlecase character that corresponds to @var{chr} " + "according to either @var{locale} or the current locale.") +#define FUNC_NAME s_scm_char_locale_titlecase +{ + scm_t_locale c_locale; + SCM ret; + int err = 0; + + SCM_VALIDATE_CHAR (1, chr); + SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale); + + ret = chr_to_case (chr, c_locale, u32_totitle, &err); + + if (err != 0) { - errno = ret; + errno = err; scm_syserror (FUNC_NAME); } - if (uplen == 1) - upchar = SCM_MAKE_CHAR ((scm_t_wchar) upbuf[0]); - else - upchar = chr; - free (upbuf); - return upchar; + return ret; } #undef FUNC_NAME -SCM_DEFINE (scm_string_locale_upcase, "string-locale-upcase", 1, 1, 0, - (SCM str, SCM locale), - "Return a new string that is the uppercase version of " - "@var{str} according to either @var{locale} or the current " - "locale.") -#define FUNC_NAME s_scm_string_locale_upcase +static SCM +str_to_case (SCM str, scm_t_locale c_locale, + scm_t_uint32 *(*func) (const scm_t_uint32 *, size_t, const char *, + uninorm_t, scm_t_uint32 *, size_t *), + int *err) { scm_t_wchar *c_str, *c_buf; - scm_t_uint32 *c_upstr; - size_t len, uplen; + scm_t_uint32 *c_convstr; + size_t len, convlen; int ret; - scm_t_locale c_locale; - SCM upstr; + SCM convstr; - SCM_VALIDATE_STRING (1, str); - SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale); len = scm_i_string_length (str); if (len == 0) return scm_nullstr; @@ -1211,28 +1230,52 @@ SCM_DEFINE (scm_string_locale_upcase, "string-locale-upcase", 1, 1, 0, if (c_locale) RUN_IN_LOCALE_SECTION (c_locale, ret = u32_locale_tocase ((scm_t_uint32 *) c_str, len, - &c_upstr, - &uplen, u32_toupper)); + &c_convstr, + &convlen, func)); else ret = u32_locale_tocase ((scm_t_uint32 *) c_str, len, - &c_upstr, &uplen, u32_toupper); + &c_convstr, &convlen, func); scm_remember_upto_here (str); if (SCM_UNLIKELY (ret != 0)) { - errno = ret; - scm_syserror (FUNC_NAME); + *err = ret; + return NULL; } - upstr = scm_i_make_wide_string (uplen, &c_buf); - memcpy (c_buf, c_upstr, uplen * sizeof (scm_t_wchar)); - free (c_upstr); + convstr = scm_i_make_wide_string (convlen, &c_buf); + memcpy (c_buf, c_convstr, convlen * sizeof (scm_t_wchar)); + free (c_convstr); - scm_i_try_narrow_string (upstr); + scm_i_try_narrow_string (convstr); - return upstr; + return convstr; +} + +SCM_DEFINE (scm_string_locale_upcase, "string-locale-upcase", 1, 1, 0, + (SCM str, SCM locale), + "Return a new string that is the uppercase version of " + "@var{str} according to either @var{locale} or the current " + "locale.") +#define FUNC_NAME s_scm_string_locale_upcase +{ + scm_t_locale c_locale; + SCM ret; + int err = 0; + + SCM_VALIDATE_STRING (1, str); + SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale); + + ret = str_to_case (str, c_locale, u32_toupper, &err); + + if (err != 0) + { + errno = err; + scm_syserror (FUNC_NAME); + } + return ret; } #undef FUNC_NAME @@ -1243,45 +1286,46 @@ SCM_DEFINE (scm_string_locale_downcase, "string-locale-downcase", 1, 1, 0, "locale.") #define FUNC_NAME s_scm_string_locale_downcase { - scm_t_wchar *c_str, *c_buf; - scm_t_uint32 *c_downstr; - size_t len, downlen; - int ret; scm_t_locale c_locale; - SCM downstr; + SCM ret; + int err = 0; SCM_VALIDATE_STRING (1, str); SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale); - len = scm_i_string_length (str); - if (len == 0) - return scm_nullstr; - SCM_STRING_TO_U32_BUF (str, c_str); - if (c_locale) - RUN_IN_LOCALE_SECTION (c_locale, ret = - u32_locale_tocase ((scm_t_uint32 *) c_str, len, - &c_downstr, - &downlen, u32_tolower)); - else - ret = - u32_locale_tocase ((scm_t_uint32 *) c_str, len, - &c_downstr, &downlen, u32_tolower); + ret = str_to_case (str, c_locale, u32_tolower, &err); - scm_remember_upto_here (str); - - if (SCM_UNLIKELY (ret != 0)) + if (err != 0) { - errno = ret; + errno = err; scm_syserror (FUNC_NAME); } + return ret; +} +#undef FUNC_NAME + +SCM_DEFINE (scm_string_locale_titlecase, "string-locale-titlecase", 1, 1, 0, + (SCM str, SCM locale), + "Return a new string that is the title-case version of " + "@var{str} according to either @var{locale} or the current " + "locale.") +#define FUNC_NAME s_scm_string_locale_titlecase +{ + scm_t_locale c_locale; + SCM ret; + int err = 0; - downstr = scm_i_make_wide_string (downlen, &c_buf); - memcpy (c_buf, c_downstr, downlen * sizeof (scm_t_wchar)); - free (c_downstr); + SCM_VALIDATE_STRING (1, str); + SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale); - scm_i_try_narrow_string (downstr); + ret = str_to_case (str, c_locale, u32_totitle, &err); - return downstr; + if (err != 0) + { + errno = err; + scm_syserror (FUNC_NAME); + } + return ret; } #undef FUNC_NAME |