From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/1541 Path: news.gmane.org!not-for-mail From: Rich Felker Newsgroups: gmane.linux.lib.musl.general Subject: portable fgetln Date: Sat, 11 Aug 2012 20:24:50 -0400 Message-ID: <20120812002450.GA17066@brightrain.aerifal.cx> Reply-To: musl@lists.openwall.com NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="zYM0uCDKw75PZbzx" X-Trace: dough.gmane.org 1344731042 4504 80.91.229.3 (12 Aug 2012 00:24:02 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Sun, 12 Aug 2012 00:24:02 +0000 (UTC) To: musl@lists.openwall.com Original-X-From: musl-return-1542-gllmg-musl=m.gmane.org@lists.openwall.com Sun Aug 12 02:24:03 2012 Return-path: Envelope-to: gllmg-musl@plane.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by plane.gmane.org with smtp (Exim 4.69) (envelope-from ) id 1T0LyL-0005wY-Ru for gllmg-musl@plane.gmane.org; Sun, 12 Aug 2012 02:24:01 +0200 Original-Received: (qmail 26317 invoked by uid 550); 12 Aug 2012 00:24:00 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Original-Received: (qmail 26309 invoked from network); 12 Aug 2012 00:24:00 -0000 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Xref: news.gmane.org gmane.linux.lib.musl.general:1541 Archived-At: --zYM0uCDKw75PZbzx Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi all, Based on a discussion on #musl about the merits of fgetln as an efficient (probably optimal) way to do line-based stdio processing if the implementation is good, I got to wondering if it's viable to use the interface in programs intended to be portable, i.e. if it could be written portably for use on any stdio implementation or at least any POSIX one. Here's the result -- a sample portable implementation that keeps a separate buffer for each fd, or for each FILE* when the stream lacks an associated fd. It has some limitations, but it seems to meet the interface contract and avoids using a single static buffer that would render if non-thread-safe. Rich --zYM0uCDKw75PZbzx Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="portable_fgetln.c" #define _POSIX_C_SOURCE 200809L #include #include #include struct entry { struct entry *next; int fd; FILE *f; char *buf; }; struct entry *table[64]; #define K (sizeof table / sizeof table[0]) pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER; char *fgetln(FILE *f, size_t *l) { int fd, h; struct entry *p; ssize_t cnt; char *ret = 0; flockfile(f); fd = fileno(f); h = fd % K; pthread_rwlock_rdlock(&lock); for (p=table[h]; p && (p->fd!=fd || (fd<0 && p->f!=f)); p=p->next); if (!p) { if (!(p = calloc(sizeof *p, 1))) { pthread_rwlock_unlock(&lock); funlockfile(f); return 0; } p->fd = fd; p->f = f; pthread_rwlock_unlock(&lock); pthread_rwlock_wrlock(&lock); p->next = table[h]; table[h] = p; } pthread_rwlock_unlock(&lock); cnt = getline(&p->buf, (size_t[]){0}, f); if (cnt >= 0) { *l = cnt; ret = p->buf; } funlockfile(f); return ret; } --zYM0uCDKw75PZbzx--