0
|
1 /* File ggets.c - goodgets is a safe alternative to gets */
|
|
2 /* By C.B. Falconer. Public domain 2002-06-22 */
|
|
3 /* attribution appreciated. */
|
|
4
|
|
5 /* Revised 2002-06-26 New prototype.
|
|
6 2002-06-27 Incomplete final lines
|
|
7 2006-06-14 Simplified, using getc, not fgets
|
|
8 2006-06-15 Fixed memory leak at EOF
|
|
9 */
|
|
10
|
|
11 /* fggets and ggets [which is fggets(ln, stdin)] set *ln to
|
|
12 a buffer filled with the next complete line from the text
|
|
13 stream f. The storage has been allocated within fggets,
|
|
14 and is normally reduced to be an exact fit. The trailing
|
|
15 \n has been removed, so the resultant line is ready for
|
|
16 dumping with puts. The buffer will be as large as is
|
|
17 required to hold the complete line.
|
|
18
|
|
19 Note: this means a final file line without a \n terminator
|
|
20 has an effective \n appended, as EOF occurs within the read.
|
|
21
|
|
22 If no error occurs fggets returns 0. If an EOF occurs on
|
|
23 the input file, EOF is returned. For memory allocation
|
|
24 errors some positive value is returned. In this case *ln
|
|
25 may point to a partial line. For other errors memory is
|
|
26 freed and *ln is set to NULL.
|
|
27
|
|
28 Freeing of assigned storage is the callers responsibility
|
|
29 */
|
|
30
|
|
31 #include <stdio.h>
|
|
32 #include <stdlib.h>
|
|
33 #include "ggets.h"
|
|
34
|
|
35 #define INITSIZE 112 /* power of 2 minus 16, helps malloc */
|
|
36 #define DELTASIZE (INITSIZE + 16)
|
|
37
|
|
38 enum {OK = 0, NOMEM};
|
|
39
|
|
40 int fggets(char* *ln, FILE *f)
|
|
41 {
|
|
42 int cursize, ch, ix;
|
|
43 char *buffer, *temp;
|
|
44
|
|
45 *ln = NULL; /* default */
|
44
|
46 if ((buffer = (char *) malloc(INITSIZE)) == NULL) return NOMEM;
|
0
|
47 cursize = INITSIZE;
|
|
48
|
|
49 ix = 0;
|
44
|
50 while ((ch = getc(f)) != EOF && ch != '\n') {
|
0
|
51 if (ix >= (cursize - 1)) { /* extend buffer */
|
|
52 cursize += DELTASIZE;
|
44
|
53 if ((temp = (char *) realloc(buffer, (size_t)cursize)) == NULL) {
|
0
|
54 /* ran out of memory, return partial line */
|
|
55 buffer[ix] = '\0';
|
|
56 *ln = buffer;
|
|
57 return NOMEM;
|
|
58 }
|
|
59 buffer = temp;
|
|
60 }
|
|
61 buffer[ix++] = ch;
|
|
62 }
|
44
|
63
|
|
64 if (ch == EOF && ix == 0) {
|
0
|
65 free(buffer);
|
|
66 return EOF;
|
|
67 }
|
|
68
|
|
69 buffer[ix] = '\0';
|
44
|
70 if ((temp = (char *) realloc(buffer, (size_t)ix + 1)) == NULL) {
|
0
|
71 *ln = buffer; /* without reducing it */
|
|
72 }
|
|
73 else *ln = temp;
|
|
74 return OK;
|
|
75 } /* fggets */
|
|
76 /* End of ggets.c */
|