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