btowc.c 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /* Copyright (C) 1996-2026 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <https://www.gnu.org/licenses/>. */
  14. #include <ctype.h>
  15. #include <dlfcn.h>
  16. #include <gconv.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <wchar.h>
  20. #include <wcsmbsload.h>
  21. #include <limits.h>
  22. #include <pointer_guard.h>
  23. wint_t
  24. __btowc (int c)
  25. {
  26. const struct gconv_fcts *fcts;
  27. /* If the parameter does not fit into one byte or it is the EOF value
  28. we can give the answer now. */
  29. if (c < SCHAR_MIN || c > UCHAR_MAX || c == EOF)
  30. return WEOF;
  31. /* We know that only ASCII compatible encodings are used for the
  32. locale and that the wide character encoding is ISO 10646. */
  33. if (isascii (c))
  34. return (wint_t) c;
  35. /* Get the conversion functions. */
  36. fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));
  37. __gconv_btowc_fct btowc_fct = fcts->towc->__btowc_fct;
  38. if (fcts->towc->__shlib_handle != NULL)
  39. PTR_DEMANGLE (btowc_fct);
  40. if (__builtin_expect (fcts->towc_nsteps == 1, 1)
  41. && __builtin_expect (btowc_fct != NULL, 1))
  42. {
  43. /* Use the shortcut function. */
  44. return DL_CALL_FCT (btowc_fct, (fcts->towc, (unsigned char) c));
  45. }
  46. else
  47. {
  48. /* Fall back to the slow but generic method. */
  49. wchar_t result;
  50. struct __gconv_step_data data;
  51. unsigned char inbuf[1];
  52. const unsigned char *inptr = inbuf;
  53. size_t dummy;
  54. int status;
  55. /* Tell where we want the result. */
  56. data.__outbuf = (unsigned char *) &result;
  57. data.__outbufend = data.__outbuf + sizeof (wchar_t);
  58. data.__invocation_counter = 0;
  59. data.__internal_use = 1;
  60. data.__flags = __GCONV_IS_LAST;
  61. data.__statep = &data.__state;
  62. /* Make sure we start in the initial state. */
  63. memset (&data.__state, '\0', sizeof (mbstate_t));
  64. /* Create the input string. */
  65. inbuf[0] = c;
  66. __gconv_fct fct = fcts->towc->__fct;
  67. if (fcts->towc->__shlib_handle != NULL)
  68. PTR_DEMANGLE (fct);
  69. status = DL_CALL_FCT (fct, (fcts->towc, &data, &inptr, inptr + 1,
  70. NULL, &dummy, 0, 1));
  71. if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT
  72. && status != __GCONV_EMPTY_INPUT)
  73. /* The conversion failed. */
  74. result = WEOF;
  75. return result;
  76. }
  77. }
  78. weak_alias (__btowc, btowc)