Ejemplo n.º 1
0
/* Convert the multibyte character at S, which is no longer
   than N characters, to its `wchar_t' representation, placing
   this n *PWC and returning its length.

   Attention: this function should NEVER be intentionally used.
   The interface is completely stupid.  The state is shared between
   all conversion functions.  You should use instead the restartable
   version `mbrtowc'.  */
int
mbtowc (wchar_t *pwc, const char *s, size_t n)
{
  int result;
  static mbstate_t state;

  /* If S is NULL the function has to return null or not null
     depending on the encoding having a state depending encoding or
     not.  */
  if (s == NULL)
    {
      const struct gconv_fcts *fcts;

      /* Get the conversion functions.  */
      fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));

      /* This is an extension in the Unix standard which does not directly
	 violate ISO C.  */
      memset (&state, '\0', sizeof state);

      result = fcts->towc->__stateful;
    }
  else if (*s == '\0')
    {
      if (pwc != NULL)
	*pwc = L'\0';
      result = 0;
    }
  else
    {
      result = __mbrtowc (pwc, s, n, &state);

      /* The `mbrtowc' functions tell us more than we need.  Fold the -1
	 and -2 result into -1.  */
      if (result < 0)
	result = -1;
    }

  return result;
}
Ejemplo n.º 2
0
/* Convert WCHAR into its multibyte character representation,
   putting this in S and returning its length.

   Attention: this function should NEVER be intentionally used.
   The interface is completely stupid.  The state is shared between
   all conversion functions.  You should use instead the restartable
   version `wcrtomb'.  */
int
wctomb (char *s, wchar_t wchar)
{
  /* If S is NULL the function has to return null or not null
     depending on the encoding having a state depending encoding or
     not.  */
  if (s == NULL)
    {
      const struct gconv_fcts *fcts;

      /* Get the conversion functions.  */
      fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));

      /* This is an extension in the Unix standard which does not directly
	 violate ISO C.  */
      memset (&__wctomb_state, '\0', sizeof __wctomb_state);

      return fcts->tomb->__stateful;
    }

  return __wcrtomb (s, wchar, &__wctomb_state);
}
Ejemplo n.º 3
0
/* Return the length of the multibyte character (if there is one)
   at S which is no longer than N characters.
   The ISO C standard says that the `mblen' function must not change
   the state of the `mbtowc' function.  */
int
mblen (const char *s, size_t n)
{
  int result;

  /* If S is NULL the function has to return null or not null
     depending on the encoding having a state depending encoding or
     not.  */
  if (s == NULL)
    {
      const struct gconv_fcts *fcts;

      /* Get the conversion functions.  */
      fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));

      /* Reset the state.  */
      memset (&state, '\0', sizeof state);

      result = fcts->towc->__stateful;
    }
  else if (*s == '\0')
    /* According to the ISO C 89 standard this is the expected behaviour.  */
    result = 0;
  else
    {
      memset (&state, '\0', sizeof state);

      result = __mbrtowc (NULL, s, n, &state);

      /* The `mbrtowc' functions tell us more than we need.  Fold the -1
	 and -2 result into -1.  */
      if (result < 0)
	result = -1;
    }

  return result;
}
Ejemplo n.º 4
0
wctype_t
__wctype (const char *property)
{
  const char *names;
  unsigned int result;
  size_t proplen = strlen (property);
  size_t i;

  names = _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS_NAMES);
  for (result = 0; ; result++)
    {
      size_t nameslen = strlen (names);

      if (proplen == nameslen && memcmp (property, names, proplen) == 0)
	break;

      names += nameslen + 1;
      if (names[0] == '\0')
	return 0;
    }

  i = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_CLASS_OFFSET) + result;
  return (wctype_t) _NL_CURRENT_DATA (LC_CTYPE)->values[i].string;
}
Ejemplo n.º 5
0
wctrans_t
__wctrans (const char *property)
{
  const char *names;
  size_t cnt;
  size_t i;

  names = _NL_CURRENT (LC_CTYPE, _NL_CTYPE_MAP_NAMES);
  cnt = 0;
  while (names[0] != '\0')
    {
      if (strcmp (property, names) == 0)
	break;

      names = strchr (names, '\0') + 1;
      ++cnt;
    }

  if (names[0] == '\0')
    return 0;

  i = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_OFFSET) + cnt;
  return (wctrans_t) _NL_CURRENT_DATA (LC_CTYPE)->values[i].string;
}
size_t
__wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
{
  char buf[MB_CUR_MAX];
  struct __gconv_step_data data;
  int status;
  size_t result;
  size_t dummy;
  const struct gconv_fcts *fcts;

  /* Set information for this step.  */
  data.__invocation_counter = 0;
  data.__internal_use = 1;
  data.__flags = __GCONV_IS_LAST;
  data.__statep = ps ?: &state;
  data.__trans = NULL;

  /* A first special case is if S is NULL.  This means put PS in the
     initial state.  */
  if (s == NULL)
    {
      s = buf;
      wc = L'\0';
    }

  /* Tell where we want to have the result.  */
  data.__outbuf = (unsigned char *) s;
  data.__outbufend = (unsigned char *) s + MB_CUR_MAX;

  /* Get the conversion functions.  */
  fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));
  __gconv_fct fct = fcts->tomb->__fct;
#ifdef PTR_DEMANGLE
  if (fcts->tomb->__shlib_handle != NULL)
    PTR_DEMANGLE (fct);
#endif

  /* If WC is the NUL character we write into the output buffer the byte
     sequence necessary for PS to get into the initial state, followed
     by a NUL byte.  */
  if (wc == L'\0')
    {
      status = DL_CALL_FCT (fct, (fcts->tomb, &data, NULL, NULL,
				  NULL, &dummy, 1, 1));

      if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT)
	*data.__outbuf++ = '\0';
    }
  else
    {
      /* Do a normal conversion.  */
      const unsigned char *inbuf = (const unsigned char *) &wc;

      status = DL_CALL_FCT (fct,
			    (fcts->tomb, &data, &inbuf,
			     inbuf + sizeof (wchar_t), NULL, &dummy, 0, 1));
    }

  /* There must not be any problems with the conversion but illegal input
     characters.  The output buffer must be large enough, otherwise the
     definition of MB_CUR_MAX is not correct.  All the other possible
     errors also must not happen.  */
  assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
	  || status == __GCONV_ILLEGAL_INPUT
	  || status == __GCONV_INCOMPLETE_INPUT
	  || status == __GCONV_FULL_OUTPUT);

  if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
      || status == __GCONV_FULL_OUTPUT)
    result = data.__outbuf - (unsigned char *) s;
  else
    {
      result = (size_t) -1;
      __set_errno (EILSEQ);
    }

  return result;
}
Ejemplo n.º 7
0
wint_t
__btowc (int c)
{
  const struct gconv_fcts *fcts;

  /* If the parameter does not fit into one byte or it is the EOF value
     we can give the answer now.  */
  if (c < SCHAR_MIN || c > UCHAR_MAX || c == EOF)
    return WEOF;

  /* We know that only ASCII compatible encodings are used for the
     locale and that the wide character encoding is ISO 10646.  */
  if (isascii (c))
    return (wint_t) c;

  /* Get the conversion functions.  */
  fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));
  __gconv_btowc_fct btowc_fct = fcts->towc->__btowc_fct;
#ifdef PTR_DEMANGLE
  if (fcts->towc->__shlib_handle != NULL)
    PTR_DEMANGLE (btowc_fct);
#endif

  if (__builtin_expect (fcts->towc_nsteps == 1, 1)
      && __builtin_expect (btowc_fct != NULL, 1))
    {
      /* Use the shortcut function.  */
      return DL_CALL_FCT (btowc_fct, (fcts->towc, (unsigned char) c));
    }
  else
    {
      /* Fall back to the slow but generic method.  */
      wchar_t result;
      struct __gconv_step_data data;
      unsigned char inbuf[1];
      const unsigned char *inptr = inbuf;
      size_t dummy;
      int status;

      /* Tell where we want the result.  */
      data.__outbuf = (unsigned char *) &result;
      data.__outbufend = data.__outbuf + sizeof (wchar_t);
      data.__invocation_counter = 0;
      data.__internal_use = 1;
      data.__flags = __GCONV_IS_LAST;
      data.__statep = &data.__state;

      /* Make sure we start in the initial state.  */
      memset (&data.__state, '\0', sizeof (mbstate_t));

      /* Create the input string.  */
      inbuf[0] = c;

      __gconv_fct fct = fcts->towc->__fct;
#ifdef PTR_DEMANGLE
      if (fcts->towc->__shlib_handle != NULL)
	PTR_DEMANGLE (fct);
#endif
      status = DL_CALL_FCT (fct, (fcts->towc, &data, &inptr, inptr + 1,
				  NULL, &dummy, 0, 1));

      if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT
	  && status != __GCONV_EMPTY_INPUT)
	/* The conversion failed.  */
	result = WEOF;

      return result;
    }
}
Ejemplo n.º 8
0
size_t
__mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
{
  wchar_t buf[1];
  struct __gconv_step_data data;
  int status;
  size_t result;
  size_t dummy;
  const unsigned char *inbuf, *endbuf;
  char *outbuf = (char *) (pwc ?: buf);
  const struct gconv_fcts *fcts;

  /* Set information for this step.  */
  data.__invocation_counter = 0;
  data.__internal_use = 1;
  data.__flags = __GCONV_IS_LAST;
  data.__statep = ps ?: &state;
  data.__trans = NULL;

  /* A first special case is if S is NULL.  This means put PS in the
     initial state.  */
  if (s == NULL)
    {
      outbuf = (char *) buf;
      s = "";
      n = 1;
    }

  /* Tell where we want the result.  */
  data.__outbuf = outbuf;
  data.__outbufend = outbuf + sizeof (wchar_t);

  /* Get the conversion functions.  */
  fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));

  /* Do a normal conversion.  */
  inbuf = (const unsigned char *) s;
  endbuf = inbuf + n;
  if (__builtin_expect (endbuf < inbuf, 0))
    endbuf = (const unsigned char *) ~(uintptr_t) 0;
  status = DL_CALL_FCT (fcts->towc->__fct,
			(fcts->towc, &data, &inbuf, endbuf,
			 NULL, &dummy, 0, 1));

  /* There must not be any problems with the conversion but illegal input
     characters.  The output buffer must be large enough, otherwise the
     definition of MB_CUR_MAX is not correct.  All the other possible
     errors also must not happen.  */
  assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
	  || status == __GCONV_ILLEGAL_INPUT
	  || status == __GCONV_INCOMPLETE_INPUT
	  || status == __GCONV_FULL_OUTPUT);

  if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
      || status == __GCONV_FULL_OUTPUT)
    {
      if (data.__outbuf != (unsigned char *) outbuf
	  && *(wchar_t *) outbuf == L'\0')
	{
	  /* The converted character is the NUL character.  */
	  assert (__mbsinit (data.__statep));
	  result = 0;
	}
      else
	result = inbuf - (const unsigned char *) s;
    }
  else if (status == __GCONV_INCOMPLETE_INPUT)
    result = (size_t) -2;
  else
    {
      result = (size_t) -1;
      __set_errno (EILSEQ);
    }

  return result;
}
Ejemplo n.º 9
0
size_t
mbrtoc16 (char16_t *pc16, const char *s, size_t n, mbstate_t *ps)
{
  if (ps == NULL)
    ps = &state;

  /* The standard text does not say that S being NULL means the state
     is reset even if the second half of a surrogate still have to be
     returned.  In fact, the error code description indicates
     otherwise.  Therefore always first try to return a second
     half.  */
  if (ps->__count & 0x80000000)
    {
      /* We have to return the second word for a surrogate.  */
      ps->__count &= 0x7fffffff;
      *pc16 = ps->__value.__wch;
      ps->__value.__wch = L'\0';
      return (size_t) -3;
    }

  wchar_t wc;
  struct __gconv_step_data data;
  int status;
  size_t result;
  size_t dummy;
  const unsigned char *inbuf, *endbuf;
  unsigned char *outbuf = (unsigned char *) &wc;
  const struct gconv_fcts *fcts;

  /* Set information for this step.  */
  data.__invocation_counter = 0;
  data.__internal_use = 1;
  data.__flags = __GCONV_IS_LAST;
  data.__statep = ps;
  data.__trans = NULL;

  /* A first special case is if S is NULL.  This means put PS in the
     initial state.  */
  if (s == NULL)
    {
      pc16 = NULL;
      s = "";
      n = 1;
    }

  /* Tell where we want the result.  */
  data.__outbuf = outbuf;
  data.__outbufend = outbuf + sizeof (wchar_t);

  /* Get the conversion functions.  */
  fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));

  /* Do a normal conversion.  */
  inbuf = (const unsigned char *) s;
  endbuf = inbuf + n;
  if (__glibc_unlikely (endbuf < inbuf))
    {
      endbuf = (const unsigned char *) ~(uintptr_t) 0;
      if (endbuf == inbuf)
	goto ilseq;
    }
  __gconv_fct fct = fcts->towc->__fct;
#ifdef PTR_DEMANGLE
  if (fcts->towc->__shlib_handle != NULL)
    PTR_DEMANGLE (fct);
#endif

  status = DL_CALL_FCT (fct, (fcts->towc, &data, &inbuf, endbuf,
			      NULL, &dummy, 0, 1));

  /* There must not be any problems with the conversion but illegal input
     characters.  The output buffer must be large enough, otherwise the
     definition of MB_CUR_MAX is not correct.  All the other possible
     errors also must not happen.  */
  assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
	  || status == __GCONV_ILLEGAL_INPUT
	  || status == __GCONV_INCOMPLETE_INPUT
	  || status == __GCONV_FULL_OUTPUT);

  if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
      || status == __GCONV_FULL_OUTPUT)
    {
      result = inbuf - (const unsigned char *) s;

      if (wc < 0x10000)
	{
	  if (pc16 != NULL)
	    *pc16 = wc;

	  if (data.__outbuf != outbuf && wc == L'\0')
	    {
	      /* The converted character is the NUL character.  */
	      assert (__mbsinit (data.__statep));
	      result = 0;
	    }
	}
      else
	{
	  /* This is a surrogate.  */
	  if (pc16 != NULL)
	    *pc16 = 0xd7c0 + (wc >> 10);

	  ps->__count |= 0x80000000;
	  ps->__value.__wch = 0xdc00 + (wc & 0x3ff);
	}
    }