From 6ac1a8ef1cd2a30c75e905087a43f9832b181290 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 87fafd4624d3..e875535cfd35 100644 --- a/embed.fnc +++ b/embed.fnc @@ -4408,12 +4408,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 79fedc2822aa..3a6fbfbc740d 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 + }; + /* This is a mask, with one bit to tell the populate functions to populate * the NUMERIC items; another bit for the MONETARY ones. This way they can * choose which (or both) to populate from */ @@ -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' @@ -5565,7 +5568,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; @@ -5584,7 +5586,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); locale = monetary_locale = querylocale_i(LC_MONETARY_INDEX_); @@ -5651,10 +5653,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. @@ -5724,12 +5723,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; @@ -5744,6 +5745,7 @@ S_my_localeconv(pTHX_ const int item) if (SvIV(*value) == CHAR_MAX) { sv_setiv(*value, -1); } + } } return hv; @@ -5765,8 +5767,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; @@ -5915,14 +5917,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)