1 /* @(#)getdelim.c	1.5 20/09/22 Copyright 2015-2020 J. Schilling */
2 /*
3  *	Copyright (c) 2015-2020 J. Schilling
4  *
5  */
6 /*
7  * The contents of this file are subject to the terms of the
8  * Common Development and Distribution License, Version 1.0 only
9  * (the "License").  You may not use this file except in compliance
10  * with the License.
11  *
12  * See the file CDDL.Schily.txt in this distribution for details.
13  * A copy of the CDDL is also available via the Internet at
14  * http://www.opensource.org/licenses/cddl1.txt
15  *
16  * When distributing Covered Code, include this CDDL HEADER in each
17  * file and include the License file CDDL.Schily.txt from this distribution.
18  */
19 
20 #define	FAST_GETC_PUTC
21 #include "schilyio.h"
22 #include <schily/stdlib.h>
23 
24 #ifndef	HAVE_GETDELIM
25 EXPORT	ssize_t	getdelim	__PR((char **, size_t *, int, FILE *));
26 
27 #define	DEF_LINE_SIZE	128
28 
29 EXPORT ssize_t
getdelim(bufp,lenp,delim,f)30 getdelim(bufp, lenp, delim, f)
31 			char	**bufp;
32 			size_t	*lenp;
33 	register	int	delim;
34 	register	FILE	*f;
35 {
36 	register char	*lp;
37 	register char	*ep;
38 	register size_t line_size;
39 	register char	*line;
40 #if	defined(HAVE_USG_STDIO) || defined(FAST_GETC_PUTC)
41 		char	*p;
42 #else
43 	register int	c;
44 #endif
45 
46 	if (bufp == NULL || lenp == NULL ||
47 	    delim < 0 || delim > UINT8_MAX) {
48 		seterrno(EINVAL);
49 		return (-1);
50 	}
51 
52 	line_size = *lenp;
53 	line = *bufp;
54 	if (line == NULL || line_size == 0) {
55 		if (line_size == 0)
56 			line_size = DEF_LINE_SIZE;
57 		line = (char *) malloc(line_size);
58 		if (line == NULL)
59 			return (-1);
60 		*bufp = line;
61 		*lenp = line_size;
62 	}
63 	/* read until EOF or delim encountered */
64 	lp = line;
65 	ep = &line[line_size - 1];
66 	do {
67 #if	defined(HAVE_USG_STDIO) || defined(FAST_GETC_PUTC)
68 		size_t	n;
69 
70 		if ((__js_fp f)->_cnt <= 0) {
71 			if (usg_filbuf(f) == EOF)
72 				break;
73 			(__js_fp f)->_cnt++;
74 			(__js_fp f)->_ptr--;
75 		}
76 
77 		n = ep - lp;
78 		if (n > (__js_fp f)->_cnt)
79 			n = (__js_fp f)->_cnt;
80 		p = movecbytes((__js_fp f)->_ptr, lp, delim, n);
81 		if (p) {
82 			n = p - lp;
83 		}
84 		(__js_fp f)->_ptr += n;
85 		(__js_fp f)->_cnt -= n;
86 		lp += n;
87 #else
88 		c = getc(f);
89 		if (c == EOF)
90 			break;
91 		*lp++ = c;
92 #endif
93 		if (lp >= ep) {
94 			ep = line;
95 			line_size += DEF_LINE_SIZE;
96 			line = (char *) realloc(line, line_size);
97 			if (line == NULL) {
98 				*lp = '\0';
99 				return (-1);
100 			}
101 			lp = line + (lp - ep);
102 			ep = &line[line_size - 1];
103 			*bufp = line;
104 			*lenp = line_size;
105 		}
106 #if	defined(HAVE_USG_STDIO) || defined(FAST_GETC_PUTC)
107 	} while (p == NULL);
108 #else
109 	} while (c != delim);
110 #endif
111 	*lp = '\0';
112 	line_size = lp - line;
113 	if (line_size > SSIZE_T_MAX) {
114 #ifdef	EOVERFLOW
115 		seterrno(EOVERFLOW);
116 #else
117 		seterrno(EINVAL);
118 #endif
119 		return (-1);
120 	}
121 	return (line_size ? line_size : -1);
122 }
123 #endif	/* HAVE_GETDELIM */
124