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