Mercurial > hg > octave-kai > gnulib-hg
annotate lib/read-file.c @ 6848:2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
* read-file.c (fread_file): Start with buffer allocation of
0 bytes rather than 1 byte; this simplifies the code.
Don't invoke feof; it's not needed. Refactor to avoid duplicate
code to free buffer and save/restore errno.
(internal_read_file): Remove unused local.
author | Simon Josefsson <simon@josefsson.org> |
---|---|
date | Wed, 21 Jun 2006 08:02:40 +0000 |
parents | 19c37b3f23b1 |
children | a88f85e4728f |
rev | line source |
---|---|
6829 | 1 /* read-file.c -- read file contents into a string |
2 Copyright (C) 2006 Free Software Foundation, Inc. | |
3 Written by Simon Josefsson and Bruno Haible. | |
4 | |
5 This program is free software; you can redistribute it and/or modify | |
6 it under the terms of the GNU General Public License as published by | |
7 the Free Software Foundation; either version 2, or (at your option) | |
8 any later version. | |
9 | |
10 This program is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 GNU General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
16 along with this program; if not, write to the Free Software Foundation, | |
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | |
18 | |
19 #ifdef HAVE_CONFIG_H | |
20 # include <config.h> | |
21 #endif | |
22 | |
23 #include "read-file.h" | |
24 | |
25 /* Get realloc, free. */ | |
26 #include <stdlib.h> | |
27 | |
28 /* Get errno. */ | |
29 #include <errno.h> | |
30 | |
31 /* Read a STREAM and return a newly allocated string with the content, | |
32 and set *LENGTH to the length of the string. The string is | |
33 zero-terminated, but the terminating zero byte is not counted in | |
34 *LENGTH. On errors, *LENGTH is undefined, errno preserves the | |
35 values set by system functions (if any), and NULL is returned. */ | |
36 char * | |
37 fread_file (FILE * stream, size_t * length) | |
38 { | |
6848
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
39 char *buf = NULL; |
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
40 size_t alloc = 0; |
6829 | 41 size_t size = 0; |
6848
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
42 int save_errno; |
6829 | 43 |
6848
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
44 for (;;) |
6829 | 45 { |
46 size_t count; | |
6848
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
47 size_t requested; |
6829 | 48 |
49 if (size + BUFSIZ + 1 > alloc) | |
50 { | |
51 char *new_buf; | |
52 | |
53 alloc += alloc / 2; | |
54 if (alloc < size + BUFSIZ + 1) | |
55 alloc = size + BUFSIZ + 1; | |
56 | |
57 new_buf = realloc (buf, alloc); | |
58 if (!new_buf) | |
59 { | |
6848
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
60 save_errno = errno; |
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
61 break; |
6829 | 62 } |
63 | |
64 buf = new_buf; | |
65 } | |
66 | |
6848
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
67 requested = alloc - size - 1; |
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
68 count = fread (buf + size, 1, requested, stream); |
6829 | 69 size += count; |
70 | |
6848
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
71 if (count != requested) |
6829 | 72 { |
6848
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
73 save_errno = errno; |
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
74 if (ferror (stream)) |
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
75 break; |
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
76 buf[size] = '\0'; |
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
77 *length = size; |
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
78 return buf; |
6829 | 79 } |
80 } | |
81 | |
6848
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
82 free (buf); |
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
83 errno = save_errno; |
2a11dd9faacd
2006-06-19 Paul Eggert <eggert@cs.ucla.edu>
Simon Josefsson <simon@josefsson.org>
parents:
6829
diff
changeset
|
84 return NULL; |
6829 | 85 } |
86 | |
87 static char * | |
88 internal_read_file (const char *filename, size_t * length, const char *mode) | |
89 { | |
90 FILE *stream = fopen (filename, mode); | |
91 char *out; | |
92 int save_errno; | |
93 | |
94 if (!stream) | |
95 return NULL; | |
96 | |
97 out = fread_file (stream, length); | |
98 | |
99 save_errno = errno; | |
100 | |
101 if (fclose (stream) != 0) | |
102 { | |
103 if (out) | |
104 { | |
105 save_errno = errno; | |
106 free (out); | |
107 } | |
108 errno = save_errno; | |
109 return NULL; | |
110 } | |
111 | |
112 return out; | |
113 } | |
114 | |
115 /* Open and read the contents of FILENAME, and return a newly | |
116 allocated string with the content, and set *LENGTH to the length of | |
117 the string. The string is zero-terminated, but the terminating | |
118 zero byte is not counted in *LENGTH. On errors, *LENGTH is | |
119 undefined, errno preserves the values set by system functions (if | |
120 any), and NULL is returned. */ | |
121 char * | |
122 read_file (const char *filename, size_t * length) | |
123 { | |
124 return internal_read_file (filename, length, "r"); | |
125 } | |
126 | |
127 /* Open (on non-POSIX systems, in binary mode) and read the contents | |
128 of FILENAME, and return a newly allocated string with the content, | |
129 and set LENGTH to the length of the string. The string is | |
130 zero-terminated, but the terminating zero byte is not counted in | |
131 the LENGTH variable. On errors, *LENGTH is undefined, errno | |
132 preserves the values set by system functions (if any), and NULL is | |
133 returned. */ | |
134 char * | |
135 read_binary_file (const char *filename, size_t * length) | |
136 { | |
137 return internal_read_file (filename, length, "rb"); | |
138 } |