mbsrtowcs-impl.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /* Convert string to wide string.
  2. Copyright (C) 2008-2013 Free Software Foundation, Inc.
  3. Written by Bruno Haible <bruno@clisp.org>, 2008.
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. size_t
  15. mbsrtowcs (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps)
  16. {
  17. if (ps == NULL)
  18. ps = &_gl_mbsrtowcs_state;
  19. {
  20. const char *src = *srcp;
  21. if (dest != NULL)
  22. {
  23. wchar_t *destptr = dest;
  24. for (; len > 0; destptr++, len--)
  25. {
  26. size_t src_avail;
  27. size_t ret;
  28. /* An optimized variant of
  29. src_avail = strnlen1 (src, MB_LEN_MAX); */
  30. if (src[0] == '\0')
  31. src_avail = 1;
  32. else if (src[1] == '\0')
  33. src_avail = 2;
  34. else if (src[2] == '\0')
  35. src_avail = 3;
  36. else if (MB_LEN_MAX <= 4 || src[3] == '\0')
  37. src_avail = 4;
  38. else
  39. src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4);
  40. /* Parse the next multibyte character. */
  41. ret = mbrtowc (destptr, src, src_avail, ps);
  42. if (ret == (size_t)(-2))
  43. /* Encountered a multibyte character that extends past a '\0' byte
  44. or that is longer than MB_LEN_MAX bytes. Cannot happen. */
  45. abort ();
  46. if (ret == (size_t)(-1))
  47. goto bad_input;
  48. if (ret == 0)
  49. {
  50. src = NULL;
  51. /* Here mbsinit (ps). */
  52. break;
  53. }
  54. src += ret;
  55. }
  56. *srcp = src;
  57. return destptr - dest;
  58. }
  59. else
  60. {
  61. /* Ignore dest and len, don't store *srcp at the end, and
  62. don't clobber *ps. */
  63. mbstate_t state = *ps;
  64. size_t totalcount = 0;
  65. for (;; totalcount++)
  66. {
  67. size_t src_avail;
  68. size_t ret;
  69. /* An optimized variant of
  70. src_avail = strnlen1 (src, MB_LEN_MAX); */
  71. if (src[0] == '\0')
  72. src_avail = 1;
  73. else if (src[1] == '\0')
  74. src_avail = 2;
  75. else if (src[2] == '\0')
  76. src_avail = 3;
  77. else if (MB_LEN_MAX <= 4 || src[3] == '\0')
  78. src_avail = 4;
  79. else
  80. src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4);
  81. /* Parse the next multibyte character. */
  82. ret = mbrtowc (NULL, src, src_avail, &state);
  83. if (ret == (size_t)(-2))
  84. /* Encountered a multibyte character that extends past a '\0' byte
  85. or that is longer than MB_LEN_MAX bytes. Cannot happen. */
  86. abort ();
  87. if (ret == (size_t)(-1))
  88. goto bad_input2;
  89. if (ret == 0)
  90. {
  91. /* Here mbsinit (&state). */
  92. break;
  93. }
  94. src += ret;
  95. }
  96. return totalcount;
  97. }
  98. bad_input:
  99. *srcp = src;
  100. bad_input2:
  101. errno = EILSEQ;
  102. return (size_t)(-1);
  103. }
  104. }