From 8ec4ae09a82c0f742d4b72d2ed0a9802ca9c5816 Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Sun, 19 Nov 2023 15:30:48 -0700 Subject: [PATCH] locale.c: Use parallel array to simplify This allows the numeric fields returned by localeconv() to have the same logic as the string fields, simplifying the code a bit. They weren't previously handled the same because one category doesn't have any numeric fields. But this is now handled by creating an array and making its corresponding element NULL, so the strings and numeric fields are handled in the same way. --- embed.fnc | 12 ++++++------ locale.c | 51 ++++++++++++++++++++++++++++----------------------- proto.h | 2 +- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/embed.fnc b/embed.fnc index f5b28286bbe0..828567a08b0f 100644 --- a/embed.fnc +++ b/embed.fnc @@ -4405,12 +4405,12 @@ Sf |char * |strftime_tm |NN const char *fmt \ |NN const struct tm *mytm # if defined(HAS_LOCALECONV) S |HV * |my_localeconv |const int item -S |void |populate_hash_from_localeconv \ - |NN HV *hv \ - |NN const char *locale \ - |const PERL_UINT_FAST8_T which_mask \ - |NN const lconv_offset_t *strings[2] \ - |NULLOK const lconv_offset_t *integers +S |void |populate_hash_from_localeconv \ + |NN HV *hv \ + |NN const char *locale \ + |const PERL_UINT_FAST8_T which_mask \ + |NN const lconv_offset_t *strings[2] \ + |NULLOK const lconv_offset_t *integers[2] # endif # if defined(USE_LOCALE) S |const char *|calculate_LC_ALL_string \ diff --git a/locale.c b/locale.c index 98665a8c9cfb..4b24bdeee630 100644 --- a/locale.c +++ b/locale.c @@ -5452,6 +5452,13 @@ S_my_localeconv(pTHX_ const int item) lconv_monetary_strings }; + /* The LC_MONETARY category also has some integer-valued fields, whose + * information is kept in a separate parallel array to 'strings' */ + const lconv_offset_t * integers[2] = { + NULL, + lconv_integers + }; + /* If we aren't paying attention to a given category, use LC_CTYPE instead; * If not paying attention to that either, the code below should end up not * using this. Make sure that things blow up if that avoidance gets lost, @@ -5497,10 +5504,6 @@ S_my_localeconv(pTHX_ const int item) * what we are working on at the moment */ const char * locale; - /* The LC_MONETARY category also has some integer-valued fields, whose - * information is kept in a separate list */ - const lconv_offset_t * integers = lconv_integers; - # ifdef HAS_SOME_LANGINFO /* If the only use-case for this is the full localeconv(), the 'item' @@ -5566,7 +5569,6 @@ S_my_localeconv(pTHX_ const int item) strings[NUMERIC_OFFSET] = thousands_sep_string; numeric_common: - integers = NULL; index_bits = OFFSET_TO_BIT(NUMERIC_OFFSET); locale = numeric_locale = PL_numeric_name; break; @@ -5586,7 +5588,7 @@ S_my_localeconv(pTHX_ const int item) } strings[MONETARY_OFFSET] = CURRENCY_SYMBOL_ADDRESS; - integers = P_CS_PRECEDES_ADDRESS; + integers[MONETARY_OFFSET] = P_CS_PRECEDES_ADDRESS; index_bits = OFFSET_TO_BIT(MONETARY_OFFSET); break; @@ -5652,10 +5654,7 @@ S_my_localeconv(pTHX_ const int item) populate_hash_from_localeconv(hv, numeric_locale, OFFSET_TO_BIT(NUMERIC_OFFSET), - strings, - NULL /* There are no NUMERIC integer - fields */ - ); + strings, integers); } /* Here, the hash has been completely populated. @@ -5725,12 +5724,14 @@ S_my_localeconv(pTHX_ const int item) SvUTF8_on(*value); } } - } /* End of fixing up UTF8ness */ + if (integers[i] == NULL) { + continue; + } - /* Examine each integer */ - for (; integers; integers++) { - const char * name = integers->name; + /* And each integer */ + for (const lconv_offset_t *intp = integers[i]; intp->name; intp++) { + const char * name = intp->name; if (! name) { /* Reached the end */ break; @@ -5745,6 +5746,7 @@ S_my_localeconv(pTHX_ const int item) if (SvIV(*value) == CHAR_MAX) { sv_setiv(*value, -1); } + } } return hv; @@ -5766,8 +5768,8 @@ S_populate_hash_from_localeconv(pTHX_ HV * hv, * monetary */ const lconv_offset_t * strings[2], - /* And to the monetary integer fields */ - const lconv_offset_t * integers) + /* And similarly the integer fields */ + const lconv_offset_t * integers[2]) { PERL_ARGS_ASSERT_POPULATE_HASH_FROM_LOCALECONV; PERL_UNUSED_ARG(which_mask); /* Some configurations don't use this; @@ -5916,14 +5918,17 @@ S_populate_hash_from_localeconv(pTHX_ HV * hv, category_strings++; } - /* Add any int fields to the HV* */ - if (i == MONETARY_OFFSET && integers) { - while (integers->name) { + /* Add any int fields to the HV*. */ + if (integers[i]) { + const lconv_offset_t * current = integers[i]; + while (current->name) { const char value = *((const char *)( lcbuf_as_string - + integers->offset)); - (void) hv_store(hv, integers->name, - strlen(integers->name), newSViv(value), 0); - integers++; + + current->offset)); + (void) hv_store(hv, + current->name, strlen(current->name), + newSViv(value), + 0); + current++; } } } /* End of loop through the fields */ diff --git a/proto.h b/proto.h index f71f72f91751..2d8366a30e17 100644 --- a/proto.h +++ b/proto.h @@ -7023,7 +7023,7 @@ S_my_localeconv(pTHX_ const int item); # define PERL_ARGS_ASSERT_MY_LOCALECONV STATIC void -S_populate_hash_from_localeconv(pTHX_ HV *hv, const char *locale, const PERL_UINT_FAST8_T which_mask, const lconv_offset_t *strings[2], const lconv_offset_t *integers); +S_populate_hash_from_localeconv(pTHX_ HV *hv, const char *locale, const PERL_UINT_FAST8_T which_mask, const lconv_offset_t *strings[2], const lconv_offset_t *integers[2]); # define PERL_ARGS_ASSERT_POPULATE_HASH_FROM_LOCALECONV \ assert(hv); assert(locale); assert(strings)