From a97ce513e031b29a47965b740be14fb9a84277fc Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Fri, 23 Nov 2012 21:19:45 +0100 Subject: [PATCH] Add new fgetwln() function Man page taken from FreeBSD. --- include/bsd/wchar.h | 2 + man/Makefile.am | 1 + man/fgetwln.3 | 117 ++++++++++++++++++++++++++++++++++++++++++++ src/Makefile.am | 1 + src/fgetwln.c | 87 ++++++++++++++++++++++++++++++++ src/libbsd.map | 1 + 6 files changed, 209 insertions(+) create mode 100644 man/fgetwln.3 create mode 100644 src/fgetwln.c diff --git a/include/bsd/wchar.h b/include/bsd/wchar.h index 9b16f53..a7e25bf 100644 --- a/include/bsd/wchar.h +++ b/include/bsd/wchar.h @@ -38,6 +38,8 @@ #include __BEGIN_DECLS +wchar_t *fgetwln(FILE *stream, size_t *len); + size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size); size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t size); __END_DECLS diff --git a/man/Makefile.am b/man/Makefile.am index 6881f12..eb9c133 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -24,6 +24,7 @@ dist_man_MANS = \ dehumanize_number.3 \ expand_number.3 \ fgetln.3 \ + fgetwln.3 \ flopen.3 \ fmtcheck.3 \ fparseln.3 \ diff --git a/man/fgetwln.3 b/man/fgetwln.3 new file mode 100644 index 0000000..0372d21 --- /dev/null +++ b/man/fgetwln.3 @@ -0,0 +1,117 @@ +.\" Copyright (c) 1990, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)fgetln.3 8.3 (Berkeley) 4/19/94 +.\" $FreeBSD$ +.\" +.Dd July 16, 2004 +.Dt FGETWLN 3 +.Os +.Sh NAME +.Nm fgetwln +.Nd get a line of wide characters from a stream +.Sh LIBRARY +.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd) +.Lb libbsd +.Sh SYNOPSIS +.In stdio.h +.In bsd/wchar.h +.Ft wchar_t * +.Fn fgetwln "FILE * restrict stream" "size_t * restrict len" +.Sh DESCRIPTION +The +.Fn fgetwln +function +returns a pointer to the next line from the stream referenced by +.Fa stream . +This line is +.Em not +a standard wide character string as it does not end with a terminating +null wide character. +The length of the line, including the final newline, +is stored in the memory location to which +.Fa len +points. +(Note, however, that if the line is the last +in a file that does not end in a newline, +the returned text will not contain a newline.) +.Sh RETURN VALUES +Upon successful completion a pointer is returned; +this pointer becomes invalid after the next +.Tn I/O +operation on +.Fa stream +(whether successful or not) +or as soon as the stream is closed. +Otherwise, +.Dv NULL +is returned. +The +.Fn fgetwln +function +does not distinguish between end-of-file and error; the routines +.Xr feof 3 +and +.Xr ferror 3 +must be used +to determine which occurred. +If an error occurs, the global variable +.Va errno +is set to indicate the error. +The end-of-file condition is remembered, even on a terminal, and all +subsequent attempts to read will return +.Dv NULL +until the condition is +cleared with +.Xr clearerr 3 . +.Pp +The text to which the returned pointer points may be modified, +provided that no changes are made beyond the returned size. +These changes are lost as soon as the pointer becomes invalid. +.Sh ERRORS +.Bl -tag -width Er +.It Bq Er EBADF +The argument +.Fa stream +is not a stream open for reading. +.El +.Pp +The +.Fn fgetwln +function +may also fail and set +.Va errno +for any of the errors specified for the routines +.Xr mbrtowc 3 , +.Xr realloc 3 , +or +.Xr read 2 . +.Sh SEE ALSO +.Xr ferror 3 , +.Xr fgetln 3 , +.Xr fgetws 3 , +.Xr fopen 3 diff --git a/src/Makefile.am b/src/Makefile.am index 2146438..95ebbb9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,6 +43,7 @@ libbsd_la_SOURCES = \ err.c \ expand_number.c \ fgetln.c \ + fgetwln.c \ flopen.c \ fmtcheck.c \ fparseln.c \ diff --git a/src/fgetwln.c b/src/fgetwln.c new file mode 100644 index 0000000..2473932 --- /dev/null +++ b/src/fgetwln.c @@ -0,0 +1,87 @@ +/* + * Copyright © 2012 Guillem Jover + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include + +struct filewbuf { + FILE *fp; + wchar_t *wbuf; + size_t len; +}; + +#define FILEWBUF_INIT_LEN 128 +#define FILEWBUF_POOL_ITEMS 32 + +static struct filewbuf fb_pool[FILEWBUF_POOL_ITEMS]; +static int fb_pool_cur; + +wchar_t * +fgetwln(FILE *stream, size_t *lenp) +{ + struct filewbuf *fb; + wint_t wc; + size_t wused = 0; + + /* Try to diminish the possibility of several fgetwln() calls being + * used on different streams, by using a pool of buffers per file. */ + fb = &fb_pool[fb_pool_cur]; + if (fb->fp != stream && fb->fp != NULL) { + fb_pool_cur++; + fb_pool_cur %= FILEWBUF_POOL_ITEMS; + fb = &fb_pool[fb_pool_cur]; + } + fb->fp = stream; + + while ((wc = fgetwc(stream)) != WEOF) { + if (!fb->len || wused > fb->len) { + wchar_t *wp; + + if (fb->len) + fb->len *= 2; + else + fb->len = FILEWBUF_INIT_LEN; + + wp = realloc(fb->wbuf, fb->len * sizeof(wchar_t)); + if (wp == NULL) { + wused = 0; + break; + } + fb->wbuf = wp; + } + + fb->wbuf[wused++] = wc; + + if (wc == L'\n') + break; + } + + *lenp = wused; + return wused ? fb->wbuf : NULL; +} diff --git a/src/libbsd.map b/src/libbsd.map index 488267c..e900ee3 100644 --- a/src/libbsd.map +++ b/src/libbsd.map @@ -96,6 +96,7 @@ LIBBSD_0.4 { } LIBBSD_0.3; LIBBSD_0.5 { + fgetwln; fparseln; strnstr;