From 93ec1cf0fef422b137be7a99fdcdf007c318c71d Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Mon, 23 May 2022 10:08:18 +0200 Subject: locale: Add more cached data to LC_CTYPE This data will be used in number formatting. Reviewed-by: Adhemerval Zanella --- locale/loadlocale.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 3 deletions(-) (limited to 'locale/loadlocale.c') diff --git a/locale/loadlocale.c b/locale/loadlocale.c index 9069bafcd8..d44310b4b5 100644 --- a/locale/loadlocale.c +++ b/locale/loadlocale.c @@ -62,6 +62,61 @@ static const enum value_type *const _nl_value_types[] = #undef DEFINE_CATEGORY }; +/* Fill in LOCDATA->private for the LC_CTYPE category. */ +static void +_nl_intern_locale_data_fill_cache_ctype (struct __locale_data *locdata) +{ + struct lc_ctype_data *data = locdata->private; + + /* Default to no translation. Assumes zero initialization of *data. */ + memset (data->outdigit_bytes, 1, sizeof (data->outdigit_bytes)); + + for (int i = 0; i <= 9; ++i) + { + const char *digit + = locdata->values[_NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT0_MB + i)].string; + unsigned char len; + if (digit[0] != '0' + i || digit[1] != '\0') + { + data->outdigit_translation_needed = true; + len = strlen (locdata->values[_NL_ITEM_INDEX + (_NL_CTYPE_OUTDIGIT0_MB + i)].string); + } + else + len = 1; + data->outdigit_bytes[i] = len; + if (i == 0) + data->outdigit_bytes_all_equal = len; + else if (data->outdigit_bytes_all_equal != len) + data->outdigit_bytes_all_equal = 0; + } +} + +/* Updates data in LOCDATA->private for CATEGORY. */ +static void +_nl_intern_locale_data_fill_cache (int category, struct __locale_data *locdata) +{ + switch (category) + { + case LC_CTYPE: + _nl_intern_locale_data_fill_cache_ctype (locdata); + break; + } +} + +/* Returns the number of bytes allocated of struct __locale_data for + CATEGORY. */ +static size_t +_nl_intern_locale_data_extra_size (int category) +{ + switch (category) + { + case LC_CTYPE: + return sizeof (struct lc_ctype_data); + default: + return 0; + } +} struct __locale_data * _nl_intern_locale_data (int category, const void *data, size_t datasize) @@ -94,14 +149,23 @@ _nl_intern_locale_data (int category, const void *data, size_t datasize) return NULL; } - newdata = malloc (sizeof *newdata - + filedata->nstrings * sizeof (union locale_data_value)); + size_t base_size = (sizeof *newdata + + filedata->nstrings * sizeof (union locale_data_value)); + size_t extra_size = _nl_intern_locale_data_extra_size (category); + + newdata = malloc (base_size + extra_size); if (newdata == NULL) return NULL; newdata->filedata = (void *) filedata; newdata->filesize = datasize; - memset (&newdata->private, 0, sizeof (newdata->private)); + if (extra_size == 0) + newdata->private = NULL; + else + { + newdata->private = (char *) newdata + base_size; + memset (newdata->private, 0, extra_size); + } newdata->usage_count = 0; newdata->use_translit = 0; newdata->nstrings = filedata->nstrings; @@ -157,6 +221,9 @@ _nl_intern_locale_data (int category, const void *data, size_t datasize) } } + if (extra_size > 0) + _nl_intern_locale_data_fill_cache (category, newdata); + return newdata; } -- cgit 1.4.1