Skip to content

Commit

Permalink
Add toggle_locale() fcns
Browse files Browse the repository at this point in the history
These are designed to temporarily switch the locale for a cateogry
around some operation that needs it to be different than the current
one.  They will be used in the next commit.

These will eventually replace the more unwieldy
_is_cur_LC_category_utf8() function, which toggles as a side effect
  • Loading branch information
khwilliamson committed May 6, 2021
1 parent 6886991 commit b39dbf4
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 0 deletions.
4 changes: 4 additions & 0 deletions embed.fnc
Expand Up @@ -3254,6 +3254,10 @@ Sr |void |setlocale_failure_panic_i|const unsigned int cat_index \
S |void |set_numeric_radix|const bool use_locale
S |void |new_numeric |NULLOK const char* newnum
S |void |new_LC_ALL |NULLOK const char* unused
S |const char *|toggle_locale_i|const unsigned switch_cat_index \
|NN const char * new_locale
S |void |restore_toggled_locale_i|const unsigned cat_index \
|NULLOK const char * original_locale
ST |bool |is_codeset_name_UTF8|NN const char * name
# ifdef USE_POSIX_2008_LOCALE
S |const char*|emulate_setlocale_i|const unsigned int index \
Expand Down
2 changes: 2 additions & 0 deletions embed.h
Expand Up @@ -1718,11 +1718,13 @@
#define new_ctype(a) S_new_ctype(aTHX_ a)
#define new_numeric(a) S_new_numeric(aTHX_ a)
#define restore_switched_locale(a,b) S_restore_switched_locale(aTHX_ a,b)
#define restore_toggled_locale_i(a,b) S_restore_toggled_locale_i(aTHX_ a,b)
#define save_to_buffer S_save_to_buffer
#define set_numeric_radix(a) S_set_numeric_radix(aTHX_ a)
#define setlocale_failure_panic_i(a,b,c,d,e) S_setlocale_failure_panic_i(aTHX_ a,b,c,d,e)
#define stdize_locale(a,b,c,d) S_stdize_locale(aTHX_ a,b,c,d)
#define switch_category_locale_to_template(a,b,c) S_switch_category_locale_to_template(aTHX_ a,b,c)
#define toggle_locale_i(a,b) S_toggle_locale_i(aTHX_ a,b)
# if defined(USE_POSIX_2008_LOCALE)
#define emulate_setlocale_i(a,b,c,d) S_emulate_setlocale_i(aTHX_ a,b,c,d)
#define find_locale_from_environment(a) S_find_locale_from_environment(aTHX_ a)
Expand Down
77 changes: 77 additions & 0 deletions locale.c
Expand Up @@ -186,6 +186,10 @@ STATIC_ASSERT_DECL(STRLENs(UTF8NESS_PREFIX) == 1);
locale, result)
# endif

# define toggle_locale_c(cat, locale) toggle_locale_i(cat##_INDEX_, locale)
# define restore_toggled_locale_c(cat, locale) \
restore_toggled_locale_i(cat##_INDEX_, locale)

/* Two parallel arrays indexed by our mapping of category numbers into small
* non-negative indexes; first the locale categories Perl uses on this system,
* used to do the inverse mapping. The second array is their names. These
Expand Down Expand Up @@ -4888,6 +4892,79 @@ S_print_bytes_for_locale(pTHX_

# endif /* #ifdef DEBUGGING */

STATIC const char *
S_toggle_locale_i(pTHX_ const unsigned cat_index, const char * new_locale)
{
/* Changes the locale for the category specified by 'index' to 'new_locale,
* if they aren't already the same.
*
* Returns a copy of the name of the original locale for 'cat_index'
* so can be switched back to with the companion function
* restore_toggled_locale_i(), (NULL if no restoral is necessary.) */

const char * locale_to_restore_to = NULL;

PERL_ARGS_ASSERT_TOGGLE_LOCALE_I;
assert(cat_index <= NOMINAL_LC_ALL_INDEX);

/* Find the original locale of the category we may need to change, so that
* it can be restored to later */

locale_to_restore_to = querylocale_i(cat_index);

DEBUG_Lv(PerlIO_printf(Perl_debug_log, "%s:%d: toggle_locale_i: index=%d(%s), wanted=%s, actual=%s\n",
__FILE__, __LINE__, cat_index, category_names[cat_index], new_locale, locale_to_restore_to));

if (! locale_to_restore_to) {
Perl_croak(aTHX_
"panic: %s: %d: Could not find current %s locale, errno=%d\n",
__FILE__, __LINE__, category_names[cat_index], errno);
}

/* If the locales are the same, there's nothing to do */
if (strEQ(locale_to_restore_to, new_locale)) {

DEBUG_Lv(PerlIO_printf(Perl_debug_log, "%s:%d: %s locale unchanged as %s\n",
__FILE__, __LINE__, category_names[cat_index], new_locale));

return NULL;
}

locale_to_restore_to = savepv(locale_to_restore_to);

/* Finally, change the locale to the new one */
void_setlocale_i(cat_index, new_locale);

DEBUG_Lv(PerlIO_printf(Perl_debug_log, "%s: %d: %s locale switched to %s\n",
__FILE__, __LINE__,category_names[cat_index], new_locale));

return locale_to_restore_to;
}

STATIC void
S_restore_toggled_locale_i(pTHX_ const unsigned int cat_index,
const char * restore_locale)
{
/* Restores the locale for LC_category corresponding to cat_indes to
* 'restore_locale' (which is a copy that will be freed by this function),
* or do nothing if the latter parameter is NULL */

PERL_ARGS_ASSERT_RESTORE_TOGGLED_LOCALE_I;
assert(cat_index <= NOMINAL_LC_ALL_INDEX);

if (restore_locale == NULL) {
DEBUG_Lv(PerlIO_printf(Perl_debug_log, "No need to restore %s\n",
category_names[cat_index]));
return;
}

DEBUG_Lv(PerlIO_printf(Perl_debug_log, "%s restoring locale to %s\n",
category_names[cat_index], restore_locale));

void_setlocale_i(cat_index, restore_locale);
Safefree(restore_locale);
}

STATIC const char *
S_switch_category_locale_to_template(pTHX_ const int switch_category,
const int template_category,
Expand Down
5 changes: 5 additions & 0 deletions proto.h
Expand Up @@ -5147,6 +5147,8 @@ STATIC void S_new_numeric(pTHX_ const char* newnum);
#define PERL_ARGS_ASSERT_NEW_NUMERIC
STATIC void S_restore_switched_locale(pTHX_ const int category, const char * const original_locale);
#define PERL_ARGS_ASSERT_RESTORE_SWITCHED_LOCALE
STATIC void S_restore_toggled_locale_i(pTHX_ const unsigned cat_index, const char * original_locale);
#define PERL_ARGS_ASSERT_RESTORE_TOGGLED_LOCALE_I
STATIC const char * S_save_to_buffer(const char * string, const char **buf, Size_t *buf_size)
__attribute__warn_unused_result__;
#define PERL_ARGS_ASSERT_SAVE_TO_BUFFER
Expand All @@ -5162,6 +5164,9 @@ STATIC const char* S_stdize_locale(pTHX_ const int category, const char* input_l
#define PERL_ARGS_ASSERT_STDIZE_LOCALE
STATIC const char* S_switch_category_locale_to_template(pTHX_ const int switch_category, const int template_category, const char * template_locale);
#define PERL_ARGS_ASSERT_SWITCH_CATEGORY_LOCALE_TO_TEMPLATE
STATIC const char * S_toggle_locale_i(pTHX_ const unsigned switch_cat_index, const char * new_locale);
#define PERL_ARGS_ASSERT_TOGGLE_LOCALE_I \
assert(new_locale)
# if defined(USE_POSIX_2008_LOCALE)
STATIC const char* S_emulate_setlocale_i(pTHX_ const unsigned int index, const char* new_locale, const int recalc_LC_ALL, const line_t line);
#define PERL_ARGS_ASSERT_EMULATE_SETLOCALE_I
Expand Down

0 comments on commit b39dbf4

Please sign in to comment.