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 * 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