re-mark 1.29b-2 as not yet uploaded (merge madness!)
[debian/tar] / gnu / mbsrtowcs-impl.h
1 /* Convert string to wide string.
2    Copyright (C) 2008-2015 Free Software Foundation, Inc.
3    Written by Bruno Haible <bruno@clisp.org>, 2008.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program 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 General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 size_t
19 mbsrtowcs (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps)
20 {
21   if (ps == NULL)
22     ps = &_gl_mbsrtowcs_state;
23   {
24     const char *src = *srcp;
25
26     if (dest != NULL)
27       {
28         wchar_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 }