1*7ec1ec4fSAlex Richardson /*
2*7ec1ec4fSAlex Richardson * Copyright 2012 Guillem Jover <guillem@hadrons.org>
3*7ec1ec4fSAlex Richardson *
4*7ec1ec4fSAlex Richardson * Redistribution and use in source and binary forms, with or without
5*7ec1ec4fSAlex Richardson * modification, are permitted provided that the following conditions
6*7ec1ec4fSAlex Richardson * are met:
7*7ec1ec4fSAlex Richardson * 1. Redistributions of source code must retain the above copyright
8*7ec1ec4fSAlex Richardson * notice, this list of conditions and the following disclaimer.
9*7ec1ec4fSAlex Richardson * 2. Redistributions in binary form must reproduce the above copyright
10*7ec1ec4fSAlex Richardson * notice, this list of conditions and the following disclaimer in the
11*7ec1ec4fSAlex Richardson * documentation and/or other materials provided with the distribution.
12*7ec1ec4fSAlex Richardson * 3. The name of the author may not be used to endorse or promote products
13*7ec1ec4fSAlex Richardson * derived from this software without specific prior written permission.
14*7ec1ec4fSAlex Richardson *
15*7ec1ec4fSAlex Richardson * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16*7ec1ec4fSAlex Richardson * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17*7ec1ec4fSAlex Richardson * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18*7ec1ec4fSAlex Richardson * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*7ec1ec4fSAlex Richardson * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*7ec1ec4fSAlex Richardson * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21*7ec1ec4fSAlex Richardson * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22*7ec1ec4fSAlex Richardson * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23*7ec1ec4fSAlex Richardson * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24*7ec1ec4fSAlex Richardson * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*7ec1ec4fSAlex Richardson */
26*7ec1ec4fSAlex Richardson
27*7ec1ec4fSAlex Richardson #include <sys/cdefs.h>
28*7ec1ec4fSAlex Richardson
29*7ec1ec4fSAlex Richardson #include <stdlib.h>
30*7ec1ec4fSAlex Richardson #include <stdio.h>
31*7ec1ec4fSAlex Richardson #include <wchar.h>
32*7ec1ec4fSAlex Richardson
33*7ec1ec4fSAlex Richardson #include "local-link.h"
34*7ec1ec4fSAlex Richardson
35*7ec1ec4fSAlex Richardson struct filewbuf {
36*7ec1ec4fSAlex Richardson FILE *fp;
37*7ec1ec4fSAlex Richardson wchar_t *wbuf;
38*7ec1ec4fSAlex Richardson size_t len;
39*7ec1ec4fSAlex Richardson };
40*7ec1ec4fSAlex Richardson
41*7ec1ec4fSAlex Richardson #define FILEWBUF_INIT_LEN 128
42*7ec1ec4fSAlex Richardson #define FILEWBUF_POOL_ITEMS 32
43*7ec1ec4fSAlex Richardson
44*7ec1ec4fSAlex Richardson static struct filewbuf fb_pool[FILEWBUF_POOL_ITEMS];
45*7ec1ec4fSAlex Richardson static int fb_pool_cur;
46*7ec1ec4fSAlex Richardson
47*7ec1ec4fSAlex Richardson wchar_t *
fgetwln(FILE * stream,size_t * lenp)48*7ec1ec4fSAlex Richardson fgetwln(FILE *stream, size_t *lenp)
49*7ec1ec4fSAlex Richardson {
50*7ec1ec4fSAlex Richardson struct filewbuf *fb;
51*7ec1ec4fSAlex Richardson wint_t wc;
52*7ec1ec4fSAlex Richardson size_t wused = 0;
53*7ec1ec4fSAlex Richardson
54*7ec1ec4fSAlex Richardson /* Try to diminish the possibility of several fgetwln() calls being
55*7ec1ec4fSAlex Richardson * used on different streams, by using a pool of buffers per file. */
56*7ec1ec4fSAlex Richardson fb = &fb_pool[fb_pool_cur];
57*7ec1ec4fSAlex Richardson if (fb->fp != stream && fb->fp != NULL) {
58*7ec1ec4fSAlex Richardson fb_pool_cur++;
59*7ec1ec4fSAlex Richardson fb_pool_cur %= FILEWBUF_POOL_ITEMS;
60*7ec1ec4fSAlex Richardson fb = &fb_pool[fb_pool_cur];
61*7ec1ec4fSAlex Richardson }
62*7ec1ec4fSAlex Richardson fb->fp = stream;
63*7ec1ec4fSAlex Richardson
64*7ec1ec4fSAlex Richardson while ((wc = fgetwc(stream)) != WEOF) {
65*7ec1ec4fSAlex Richardson if (!fb->len || wused >= fb->len) {
66*7ec1ec4fSAlex Richardson wchar_t *wp;
67*7ec1ec4fSAlex Richardson
68*7ec1ec4fSAlex Richardson if (fb->len)
69*7ec1ec4fSAlex Richardson fb->len *= 2;
70*7ec1ec4fSAlex Richardson else
71*7ec1ec4fSAlex Richardson fb->len = FILEWBUF_INIT_LEN;
72*7ec1ec4fSAlex Richardson
73*7ec1ec4fSAlex Richardson wp = reallocarray(fb->wbuf, fb->len, sizeof(wchar_t));
74*7ec1ec4fSAlex Richardson if (wp == NULL) {
75*7ec1ec4fSAlex Richardson wused = 0;
76*7ec1ec4fSAlex Richardson break;
77*7ec1ec4fSAlex Richardson }
78*7ec1ec4fSAlex Richardson fb->wbuf = wp;
79*7ec1ec4fSAlex Richardson }
80*7ec1ec4fSAlex Richardson
81*7ec1ec4fSAlex Richardson fb->wbuf[wused++] = wc;
82*7ec1ec4fSAlex Richardson
83*7ec1ec4fSAlex Richardson if (wc == L'\n')
84*7ec1ec4fSAlex Richardson break;
85*7ec1ec4fSAlex Richardson }
86*7ec1ec4fSAlex Richardson
87*7ec1ec4fSAlex Richardson *lenp = wused;
88*7ec1ec4fSAlex Richardson return wused ? fb->wbuf : NULL;
89*7ec1ec4fSAlex Richardson }
90*7ec1ec4fSAlex Richardson
91*7ec1ec4fSAlex Richardson libbsd_link_warning(fgetwln,
92*7ec1ec4fSAlex Richardson "This function cannot be safely ported, use fgetwc(3) "
93*7ec1ec4fSAlex Richardson "instead, as it is supported by C99 and POSIX.1-2001.")
94