Use spaces for indentation, not tabs.
[gnulib.git] / lib / wcsnrtombs.c
1 /* Convert wide string to string.
2    Copyright (C) 2008 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 #include <config.h>
19
20 /* Specification.  */
21 #include <wchar.h>
22
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27
28 extern mbstate_t _gl_wcsrtombs_state;
29
30 size_t
31 wcsnrtombs (char *dest, const wchar_t **srcp, size_t srclen, size_t len, mbstate_t *ps)
32 {
33   if (ps == NULL)
34     ps = &_gl_wcsrtombs_state;
35   {
36     const wchar_t *src = *srcp;
37     size_t cur_max = MB_CUR_MAX;
38     char buf[64];
39
40     if (!(cur_max <= sizeof (buf)))
41       abort ();
42
43     if (dest != NULL)
44       {
45         char *destptr = dest;
46
47         for (; srclen > 0 && len > 0; src++, srclen--)
48           {
49             wchar_t wc = *src;
50             size_t ret = wcrtomb (len >= cur_max ? destptr : buf, wc, ps);
51
52             if (ret == (size_t)(-1))
53               goto bad_input;
54             if (!(ret <= cur_max))
55               abort ();
56             if (len < ret)
57               break;
58             if (len < cur_max)
59               memcpy (destptr, buf, ret);
60             if (wc == 0)
61               {
62                 src = NULL;
63                 /* Here mbsinit (ps).  */
64                 break;
65               }
66             destptr += ret;
67             len -= ret;
68           }
69         *srcp = src;
70         return destptr - dest;
71       }
72     else
73       {
74         /* Ignore dest and len, don't store *srcp at the end, and
75            don't clobber *ps.  */
76         mbstate_t state = *ps;
77         size_t totalcount = 0;
78
79         for (; srclen > 0; src++, srclen--)
80           {
81             wchar_t wc = *src;
82             size_t ret = wcrtomb (buf, wc, &state);
83
84             if (ret == (size_t)(-1))
85               goto bad_input2;
86             if (wc == 0)
87               {
88                 /* Here mbsinit (&state).  */
89                 break;
90               }
91             totalcount += ret;
92           }
93         return totalcount;
94       }
95
96    bad_input:
97     *srcp = src;
98    bad_input2:
99     errno = EILSEQ;
100     return (size_t)(-1);
101   }
102 }