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