1 /*	$NetBSD: vstring_vstream.c,v 1.1.1.1 2009/06/23 10:09:01 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	vstring_vstream 3
6 /* SUMMARY
7 /*	auto-resizing string library, standard I/O interface
8 /* SYNOPSIS
9 /*	#include <vstring_vstream.h>
10 /*
11 /*	int	vstring_get(vp, fp)
12 /*	VSTRING	*vp;
13 /*	VSTREAM	*fp;
14 /*
15 /*	int	vstring_get_nonl(vp, fp)
16 /*	VSTRING	*vp;
17 /*	VSTREAM	*fp;
18 /*
19 /*	int	vstring_get_null(vp, fp)
20 /*	VSTRING	*vp;
21 /*	VSTREAM	*fp;
22 /*
23 /*	int	vstring_get_bound(vp, fp, bound)
24 /*	VSTRING	*vp;
25 /*	VSTREAM	*fp;
26 /*	ssize_t	bound;
27 /*
28 /*	int	vstring_get_nonl_bound(vp, fp, bound)
29 /*	VSTRING	*vp;
30 /*	VSTREAM	*fp;
31 /*	ssize_t	bound;
32 /*
33 /*	int	vstring_get_null_bound(vp, fp, bound)
34 /*	VSTRING	*vp;
35 /*	VSTREAM	*fp;
36 /*	ssize_t	bound;
37 /* DESCRIPTION
38 /*	The routines in this module each read one newline or null-terminated
39 /*	string from an input stream. In all cases the result is either the
40 /*	last character read, typically the record terminator, or VSTREAM_EOF.
41 /*
42 /*	vstring_get() reads one line from the named stream, including the
43 /*	terminating newline character if present.
44 /*
45 /*	vstring_get_nonl() reads a line from the named stream and strips
46 /*	the trailing newline character.
47 /*
48 /*	vstring_get_null() reads a null-terminated string from the named
49 /*	stream.
50 /*
51 /*	the vstring_get<whatever>_bound() routines read no more
52 /*	than \fIbound\fR characters.  Otherwise they behave like the
53 /*	unbounded versions documented above.
54 /* DIAGNOSTICS
55 /*	Fatal errors: memory allocation failure.
56 /*	Panic: improper string bound.
57 /* LICENSE
58 /* .ad
59 /* .fi
60 /*	The Secure Mailer license must be distributed with this software.
61 /* AUTHOR(S)
62 /*	Wietse Venema
63 /*	IBM T.J. Watson Research
64 /*	P.O. Box 704
65 /*	Yorktown Heights, NY 10598, USA
66 /*--*/
67 
68 /* System library. */
69 
70 #include "sys_defs.h"
71 #include <stdio.h>
72 #include <string.h>
73 
74 /* Application-specific. */
75 
76 #include "msg.h"
77 #include "vstring.h"
78 #include "vstream.h"
79 #include "vstring_vstream.h"
80 
81  /*
82   * Macro to return the last character added to a VSTRING, for consistency.
83   */
84 #define VSTRING_GET_RESULT(vp) \
85     (VSTRING_LEN(vp) > 0 ? vstring_end(vp)[-1] : VSTREAM_EOF)
86 
87 /* vstring_get - read line from file, keep newline */
88 
89 int     vstring_get(VSTRING *vp, VSTREAM *fp)
90 {
91     int     c;
92 
93     VSTRING_RESET(vp);
94     while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
95 	VSTRING_ADDCH(vp, c);
96 	if (c == '\n')
97 	    break;
98     }
99     VSTRING_TERMINATE(vp);
100     return (VSTRING_GET_RESULT(vp));
101 }
102 
103 /* vstring_get_nonl - read line from file, strip newline */
104 
105 int     vstring_get_nonl(VSTRING *vp, VSTREAM *fp)
106 {
107     int     c;
108 
109     VSTRING_RESET(vp);
110     while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != '\n')
111 	VSTRING_ADDCH(vp, c);
112     VSTRING_TERMINATE(vp);
113     return (c == '\n' ? c : VSTRING_GET_RESULT(vp));
114 }
115 
116 /* vstring_get_null - read null-terminated string from file */
117 
118 int     vstring_get_null(VSTRING *vp, VSTREAM *fp)
119 {
120     int     c;
121 
122     VSTRING_RESET(vp);
123     while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0)
124 	VSTRING_ADDCH(vp, c);
125     VSTRING_TERMINATE(vp);
126     return (c == 0 ? c : VSTRING_GET_RESULT(vp));
127 }
128 
129 /* vstring_get_bound - read line from file, keep newline, up to bound */
130 
131 int     vstring_get_bound(VSTRING *vp, VSTREAM *fp, ssize_t bound)
132 {
133     int     c;
134 
135     if (bound <= 0)
136 	msg_panic("vstring_get_bound: invalid bound %ld", (long) bound);
137 
138     VSTRING_RESET(vp);
139     while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
140 	VSTRING_ADDCH(vp, c);
141 	if (c == '\n')
142 	    break;
143     }
144     VSTRING_TERMINATE(vp);
145     return (VSTRING_GET_RESULT(vp));
146 }
147 
148 /* vstring_get_nonl_bound - read line from file, strip newline, up to bound */
149 
150 int     vstring_get_nonl_bound(VSTRING *vp, VSTREAM *fp, ssize_t bound)
151 {
152     int     c;
153 
154     if (bound <= 0)
155 	msg_panic("vstring_get_nonl_bound: invalid bound %ld", (long) bound);
156 
157     VSTRING_RESET(vp);
158     while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != '\n')
159 	VSTRING_ADDCH(vp, c);
160     VSTRING_TERMINATE(vp);
161     return (c == '\n' ? c : VSTRING_GET_RESULT(vp));
162 }
163 
164 /* vstring_get_null_bound - read null-terminated string from file */
165 
166 int     vstring_get_null_bound(VSTRING *vp, VSTREAM *fp, ssize_t bound)
167 {
168     int     c;
169 
170     if (bound <= 0)
171 	msg_panic("vstring_get_nonl_bound: invalid bound %ld", (long) bound);
172 
173     VSTRING_RESET(vp);
174     while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0)
175 	VSTRING_ADDCH(vp, c);
176     VSTRING_TERMINATE(vp);
177     return (c == 0 ? c : VSTRING_GET_RESULT(vp));
178 }
179 
180 #ifdef TEST
181 
182  /*
183   * Proof-of-concept test program: copy the source to this module to stdout.
184   */
185 #include <fcntl.h>
186 
187 #define TEXT_VSTREAM    "vstring_vstream.c"
188 
189 int     main(void)
190 {
191     VSTRING *vp = vstring_alloc(1);
192     VSTREAM *fp;
193 
194     if ((fp = vstream_fopen(TEXT_VSTREAM, O_RDONLY, 0)) == 0)
195 	msg_fatal("open %s: %m", TEXT_VSTREAM);
196     while (vstring_fgets(vp, fp))
197 	vstream_fprintf(VSTREAM_OUT, "%s", vstring_str(vp));
198     vstream_fclose(fp);
199     vstream_fflush(VSTREAM_OUT);
200     vstring_free(vp);
201     return (0);
202 }
203 
204 #endif
205