Blame time/alt_digit.c

Packit Service 82fcde
/* Helper functions used by strftime/strptime to handle alternate digits.
Packit Service 82fcde
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include "../locale/localeinfo.h"
Packit Service 82fcde
#include <libc-lock.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <wchar.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
Packit Service 82fcde
/* Some of the functions here must not be used while setlocale is called.  */
Packit Service 82fcde
__libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
Packit Service 82fcde
Packit Service 82fcde
#define CURRENT(item) (current->values[_NL_ITEM_INDEX (item)].string)
Packit Service 82fcde
#define CURRENT_WSTR(item) \
Packit Service 82fcde
  ((wchar_t *) current->values[_NL_ITEM_INDEX (item)].wstr)
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
_nl_init_alt_digit (struct __locale_data *current)
Packit Service 82fcde
{
Packit Service 82fcde
  struct lc_time_data *data;
Packit Service 82fcde
Packit Service 82fcde
  if (current->private.time == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      current->private.time = malloc (sizeof *current->private.time);
Packit Service 82fcde
      if (current->private.time == NULL)
Packit Service 82fcde
	return;
Packit Service 82fcde
      memset (current->private.time, 0, sizeof *current->private.time);
Packit Service 82fcde
      current->private.cleanup = &_nl_cleanup_time;
Packit Service 82fcde
    }
Packit Service 82fcde
  data = current->private.time;
Packit Service 82fcde
Packit Service 82fcde
  if (! data->alt_digits_initialized)
Packit Service 82fcde
    {
Packit Service 82fcde
      const char *ptr = CURRENT (ALT_DIGITS);
Packit Service 82fcde
      size_t cnt;
Packit Service 82fcde
Packit Service 82fcde
      data->alt_digits_initialized = 1;
Packit Service 82fcde
Packit Service 82fcde
      if (ptr != NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  data->alt_digits = malloc (100 * sizeof (const char *));
Packit Service 82fcde
	  if (data->alt_digits != NULL)
Packit Service 82fcde
	    for (cnt = 0; cnt < 100; ++cnt)
Packit Service 82fcde
	      {
Packit Service 82fcde
		data->alt_digits[cnt] = ptr;
Packit Service 82fcde
Packit Service 82fcde
		/* Skip digit format. */
Packit Service 82fcde
		ptr = strchr (ptr, '\0') + 1;
Packit Service 82fcde
	      }
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
const char *
Packit Service 82fcde
_nl_get_alt_digit (unsigned int number, struct __locale_data *current)
Packit Service 82fcde
{
Packit Service 82fcde
  const char *result;
Packit Service 82fcde
Packit Service 82fcde
  if (number >= 100 || CURRENT (ALT_DIGITS)[0] == '\0')
Packit Service 82fcde
    return NULL;
Packit Service 82fcde
Packit Service 82fcde
  __libc_rwlock_wrlock (__libc_setlocale_lock);
Packit Service 82fcde
Packit Service 82fcde
  if (current->private.time == NULL
Packit Service 82fcde
      || ! current->private.time->alt_digits_initialized)
Packit Service 82fcde
    _nl_init_alt_digit (current);
Packit Service 82fcde
Packit Service 82fcde
  result = ((current->private.time != NULL
Packit Service 82fcde
	     && current->private.time->alt_digits != NULL)
Packit Service 82fcde
	    ? current->private.time->alt_digits[number]
Packit Service 82fcde
	    : NULL);
Packit Service 82fcde
Packit Service 82fcde
  __libc_rwlock_unlock (__libc_setlocale_lock);
Packit Service 82fcde
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
const wchar_t *
Packit Service 82fcde
_nl_get_walt_digit (unsigned int number, struct __locale_data *current)
Packit Service 82fcde
{
Packit Service 82fcde
  const wchar_t *result = NULL;
Packit Service 82fcde
  struct lc_time_data *data;
Packit Service 82fcde
Packit Service 82fcde
  if (number >= 100 || CURRENT_WSTR (_NL_WALT_DIGITS)[0] == L'\0')
Packit Service 82fcde
    return NULL;
Packit Service 82fcde
Packit Service 82fcde
  __libc_rwlock_wrlock (__libc_setlocale_lock);
Packit Service 82fcde
Packit Service 82fcde
  if (current->private.time == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      current->private.time = malloc (sizeof *current->private.time);
Packit Service 82fcde
      if (current->private.time == NULL)
Packit Service 82fcde
	goto out;
Packit Service 82fcde
      memset (current->private.time, 0, sizeof *current->private.time);
Packit Service 82fcde
      current->private.cleanup = &_nl_cleanup_time;
Packit Service 82fcde
    }
Packit Service 82fcde
  data = current->private.time;
Packit Service 82fcde
Packit Service 82fcde
  if (! data->walt_digits_initialized)
Packit Service 82fcde
    {
Packit Service 82fcde
      const wchar_t *ptr = CURRENT_WSTR (_NL_WALT_DIGITS);
Packit Service 82fcde
      size_t cnt;
Packit Service 82fcde
Packit Service 82fcde
      data->walt_digits_initialized = 1;
Packit Service 82fcde
Packit Service 82fcde
      if (ptr != NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  data->walt_digits = malloc (100 * sizeof (const uint32_t *));
Packit Service 82fcde
	  if (data->walt_digits != NULL)
Packit Service 82fcde
	    for (cnt = 0; cnt < 100; ++cnt)
Packit Service 82fcde
	      {
Packit Service 82fcde
		data->walt_digits[cnt] = ptr;
Packit Service 82fcde
Packit Service 82fcde
		/* Skip digit format. */
Packit Service 82fcde
		ptr = __wcschr (ptr, L'\0') + 1;
Packit Service 82fcde
	      }
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (data->walt_digits != NULL)
Packit Service 82fcde
    result = data->walt_digits[number];
Packit Service 82fcde
Packit Service 82fcde
 out:
Packit Service 82fcde
  __libc_rwlock_unlock (__libc_setlocale_lock);
Packit Service 82fcde
Packit Service 82fcde
  return (wchar_t *) result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
_nl_parse_alt_digit (const char **strp, struct __locale_data *current)
Packit Service 82fcde
{
Packit Service 82fcde
  const char *str = *strp;
Packit Service 82fcde
  int result = -1;
Packit Service 82fcde
  size_t cnt;
Packit Service 82fcde
  size_t maxlen = 0;
Packit Service 82fcde
Packit Service 82fcde
  if (CURRENT_WSTR (_NL_WALT_DIGITS)[0] == L'\0')
Packit Service 82fcde
    return result;
Packit Service 82fcde
Packit Service 82fcde
  __libc_rwlock_wrlock (__libc_setlocale_lock);
Packit Service 82fcde
Packit Service 82fcde
  if (current->private.time == NULL
Packit Service 82fcde
      || ! current->private.time->alt_digits_initialized)
Packit Service 82fcde
    _nl_init_alt_digit (current);
Packit Service 82fcde
Packit Service 82fcde
  if (current->private.time != NULL &&
Packit Service 82fcde
      current->private.time->alt_digits != NULL)
Packit Service 82fcde
    /* Matching is not unambiguous.  The alternative digits could be like
Packit Service 82fcde
       I, II, III, ... and the first one is a substring of the second
Packit Service 82fcde
       and third.  Therefore we must keep on searching until we found
Packit Service 82fcde
       the longest possible match.  Note that this is not specified in
Packit Service 82fcde
       the standard.  */
Packit Service 82fcde
    for (cnt = 0; cnt < 100; ++cnt)
Packit Service 82fcde
      {
Packit Service 82fcde
	const char *const dig = current->private.time->alt_digits[cnt];
Packit Service 82fcde
	size_t len = strlen (dig);
Packit Service 82fcde
Packit Service 82fcde
	if (len > maxlen && strncmp (dig, str, len) == 0)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    maxlen = len;
Packit Service 82fcde
	    result = (int) cnt;
Packit Service 82fcde
	  }
Packit Service 82fcde
      }
Packit Service 82fcde
Packit Service 82fcde
  __libc_rwlock_unlock (__libc_setlocale_lock);
Packit Service 82fcde
Packit Service 82fcde
  if (result != -1)
Packit Service 82fcde
    *strp += maxlen;
Packit Service 82fcde
Packit Service 82fcde
  return result;
Packit Service 82fcde
}