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