/[MITgcm]/MITgcm/tools/mpack-1.6/part.c
ViewVC logotype

Contents of /MITgcm/tools/mpack-1.6/part.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (show annotations) (download)
Tue Aug 26 20:45:25 2003 UTC (20 years, 7 months ago) by edhill
Branch: MAIN
CVS Tags: checkpoint58l_post, checkpoint51k_post, checkpoint57t_post, checkpoint57o_post, checkpoint52l_pre, checkpoint52e_pre, hrcube4, checkpoint58e_post, mitgcm_mapl_00, checkpoint52n_post, checkpoint52j_post, checkpoint53d_post, checkpoint58u_post, checkpoint58w_post, checkpoint54a_pre, checkpoint51o_pre, checkpoint57m_post, checkpoint55c_post, checkpoint54e_post, checkpoint52e_post, checkpoint57s_post, checkpoint51n_pre, checkpoint54a_post, checkpoint53c_post, checkpoint57k_post, checkpoint55d_pre, checkpoint57d_post, checkpoint51l_post, checkpoint57g_post, checkpoint51q_post, checkpoint57b_post, checkpoint57c_pre, checkpoint51j_post, checkpoint58r_post, checkpoint55j_post, checkpoint56b_post, checkpoint57i_post, checkpoint57y_post, hrcube_1, checkpoint57e_post, branch-netcdf, checkpoint52d_pre, checkpoint52l_post, checkpoint55h_post, checkpoint58n_post, checkpoint53b_post, checkpoint58x_post, checkpoint52k_post, checkpoint52b_pre, checkpoint57g_pre, checkpoint54b_post, checkpoint53b_pre, checkpoint55b_post, checkpoint58t_post, checkpoint58h_post, checkpoint54d_post, checkpoint56c_post, checkpoint52m_post, checkpoint57y_pre, checkpoint55, checkpoint53a_post, checkpoint57f_pre, checkpoint57a_post, checkpoint54, checkpoint58q_post, checkpoint54f_post, checkpoint57v_post, checkpoint55g_post, checkpoint51o_post, checkpoint51p_post, checkpoint58j_post, checkpoint52a_pre, checkpoint59e, checkpoint59d, checkpoint59g, checkpoint59f, checkpoint59a, checkpoint55f_post, checkpoint59c, checkpoint59b, checkpoint59m, checkpoint59l, checkpoint59n, checkpoint59i, checkpoint59h, checkpoint59k, checkpoint59j, checkpoint57r_post, checkpoint59, checkpoint58, checkpoint57a_pre, checkpoint55i_post, checkpoint57, checkpoint56, checkpoint51i_post, checkpoint53, checkpoint52, checkpoint51f_post, checkpoint52d_post, eckpoint57e_pre, checkpoint51r_post, checkpoint52a_post, checkpoint57h_done, checkpoint58f_post, checkpoint52b_post, checkpoint53g_post, checkpoint52f_post, branchpoint-genmake2, checkpoint57x_post, checkpoint57n_post, checkpoint52c_post, checkpoint58d_post, checkpoint58c_post, checkpoint57w_post, checkpoint57p_post, checkpint57u_post, checkpoint57f_post, checkpoint58a_post, checkpoint51h_pre, checkpoint51l_pre, checkpoint58i_post, checkpoint57q_post, checkpoint51g_post, checkpoint58g_post, ecco_c52_e35, hrcube5, checkpoint58o_post, checkpoint57z_post, checkpoint57c_post, checkpoint58y_post, checkpoint55e_post, checkpoint58k_post, checkpoint52i_post, checkpoint52j_pre, checkpoint58v_post, checkpoint53f_post, checkpoint55a_post, checkpoint51t_post, checkpoint53d_pre, checkpoint54c_post, checkpoint58s_post, checkpoint58p_post, checkpoint51n_post, checkpoint57j_post, checkpoint58b_post, checkpoint57h_pre, checkpoint51i_pre, checkpoint58m_post, checkpoint57l_post, checkpoint52i_pre, checkpoint51u_post, checkpoint52h_pre, checkpoint52f_pre, checkpoint57h_post, hrcube_2, hrcube_3, checkpoint56a_post, checkpoint51m_post, checkpoint51s_post, checkpoint55d_post
Branch point for: branch-nonh, branch-genmake2, tg2-branch, checkpoint51n_branch, netcdf-sm0
File MIME type: text/plain
Initial check-in of the CMU "mpack" utility.  This allows us to (portably)
send MITgcm output as MIME-encoded email messages and will be used by the
"testreport" script.  The CMU license is basically an "AS-IS" statement.

1 /*
2 * Read MIME body-part, stopping on boundaries.
3 */
4 /* (C) Copyright 1994 by Carnegie Mellon University
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify, distribute, and sell this software
8 * and its documentation for any purpose is hereby granted without
9 * fee, provided that the above copyright notice appear in all copies
10 * and that both that copyright notice and this permission notice
11 * appear in supporting documentation, and that the name of Carnegie
12 * Mellon University not be used in advertising or publicity
13 * pertaining to distribution of the software without specific,
14 * written prior permission. Carnegie Mellon University makes no
15 * representations about the suitability of this software for any
16 * purpose. It is provided "as is" without express or implied
17 * warranty.
18 *
19 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
20 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
22 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
24 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
25 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26 * SOFTWARE.
27 */
28
29 #include <stdio.h>
30 #include <string.h>
31
32 #include "part.h"
33 #include "xmalloc.h"
34
35 #define BUFSIZE 1024 /* must be > PART_MAX_BOUNDARY_LEN */
36 #define GROWBOUNDARY 20
37
38 static int pendingboundary(struct part *part);
39
40 /*
41 * Create, initialize, and return a new struct part pointer
42 * for the input file 'infile'.
43 */
44 struct part *part_init(FILE *infile)
45 {
46 static struct part zeropart;
47 struct part *newpart;
48
49 newpart = (struct part *)xmalloc(sizeof(struct part));
50 *newpart = zeropart;
51 newpart->infile = infile;
52 newpart->buf = (unsigned char *)xmalloc(BUFSIZE);
53 newpart->buf_alloc = BUFSIZE;
54
55 return newpart;
56 }
57
58 /*
59 * Close and free 'part'.
60 */
61 int part_close(struct part *part)
62 {
63 fclose(part->infile);
64 if (part->buf) free(part->buf);
65 if (part->boundary) free(part->boundary);
66 }
67
68 /*
69 * Return the multipart depth of 'part'. Top-level is '0'.
70 */
71 int
72 part_depth(struct part *part)
73 {
74 return part->boundary_num;
75 }
76
77 /*
78 * Add to 'part' the multipart boundary 'boundary'.
79 */
80 int
81 part_addboundary(struct part *part, char *boundary)
82 {
83 /* Grow boundary array if necessary */
84 if (part->boundary_num == part->boundary_alloc) {
85 part->boundary_alloc += GROWBOUNDARY;
86 part->boundary = (char (*)[PART_MAX_BOUNDARY_LEN+1])
87 xrealloc((char *)part->boundary,
88 part->boundary_alloc * (PART_MAX_BOUNDARY_LEN+1));
89 part->boundary_length = (int *)
90 xrealloc((char *)part->boundary_length,
91 part->boundary_alloc * sizeof(int));
92 }
93
94 strncpy(part->boundary[part->boundary_num], boundary,
95 PART_MAX_BOUNDARY_LEN);
96 part->boundary[part->boundary_num][PART_MAX_BOUNDARY_LEN] = '\0';
97 part->boundary_length[part->boundary_num] =
98 strlen(part->boundary[part->boundary_num]);
99 part->boundary_num++;
100 if (part->boundary_seen+1 == part->boundary_num) {
101 part->boundary_seen++;
102 }
103 }
104
105 /*
106 * Private function that is only called from the part_getc() macro.
107 *
108 * Fills the input buffer for 'part' if necessary. Returns the next
109 * input character or EOF if at a boundary or end of file.
110 */
111 int
112 part_fill(struct part *part)
113 {
114 /* part_getc() decremented this before calling us, put it back */
115 part->cnt++;
116
117 /* Return EOF if we saw a boundary */
118 if (part->boundary_seen < part->boundary_num) return EOF;
119
120 /* Fill buffer if it is empty */
121 if (part->cnt == 0) {
122 part->ptr = part->buf;
123 part->cnt = fread(part->buf, 1, part->buf_alloc, part->infile);
124 if (part->cnt == 0) {
125 part->boundary_seen = 0;
126 return EOF;
127 }
128 }
129
130 /* If there is a newline, see if it is followed by a boundary */
131 if (part->ptr[0] == '\n' && pendingboundary(part)) {
132 return EOF;
133 }
134
135 part->cnt--;
136 return *part->ptr++;
137 }
138
139 /*
140 * Read a line into the array 's', of size 'n', from 'part'.
141 * Reads until 'n'-1 characters are read, a newline is read, or
142 * an EOF is encountered. The array is then nul-terminated and returned.
143 * If the first character read is an EOF, then a null pointer is instead
144 * returned.
145 */
146 char *
147 part_gets(char *s, int n, struct part *part)
148 {
149 int c;
150 char *p = s;
151
152 if (n == 0) return 0;
153 n--;
154 while (n-- && (c = part_getc(part)) != EOF) {
155 *p++ = c;
156 if (c == '\n') break;
157 }
158 if (p == s) return 0;
159 *p++ = '\0';
160 return s;
161 }
162
163 /*
164 * Push back the string 's' into the input buffer of 'part'.
165 * Leaves room in the input buffer to push back an additional single
166 * character using the prot_ungetc() macro.
167 */
168 int
169 part_ungets(char *s, struct part *part)
170 {
171 int len = strlen(s);
172 int i;
173
174 /* Grow buffer if necessary */
175 if (part->cnt + len + 1 > part->buf_alloc) {
176 i = part->ptr - part->buf;
177 part->buf_alloc = part->cnt + len + 1;
178 part->buf = (unsigned char *)
179 xrealloc((char *)part->buf, part->buf_alloc);
180 part->ptr = part->buf + i;
181 }
182
183 /* Move current data down to make room for new data if necessary */
184 if (len + 1 > part->ptr - part->buf) {
185 for (i = part->cnt-1; i >= 0; i--) {
186 part->buf[len+1+i] = part->ptr[i];
187 }
188 part->ptr = part->buf + len + 1;
189 }
190
191 /* Copy in the new data */
192 part->ptr -= len;
193 part->cnt += len;
194 for (i = 0; i < len; i++) {
195 part->ptr[i] = s[i];
196 }
197 }
198
199 /*
200 * Reset the saw-boundary state of 'part' and set up to read next
201 * body-part Returns nonzero iff the pending boundary was a final
202 * boundary of the current multipart.
203 */
204 int
205 part_readboundary(struct part *part)
206 {
207 int c;
208 int sawfinal = 0;
209
210 if (part->boundary_seen < part->boundary_num-1) {
211 /* We saw an enclosing boundary. Signal end of multipart, but
212 * don't skip over the boundary.
213 */
214 part->boundary_num--;
215 return 1;
216 }
217
218 /* Deal with EOF on input stream */
219 if (part->cnt == 0) return 1;
220
221 /* Skip over delimiter, reset the "saw boundary" state */
222 part->ptr += part->boundary_length[part->boundary_seen] + 3;
223 part->cnt -= part->boundary_length[part->boundary_seen] + 3;
224 part->boundary_seen = part->boundary_num;
225
226 /* Check for two dashes, which indicate a final delimiter */
227 c = part_getc(part);
228 if (c == '-') {
229 c = part_getc(part);
230 if (c == '-') {
231 sawfinal = 1;
232 part->boundary_num--;
233 }
234 }
235
236 /* Eat rest of the boundary line */
237 while (c != '\n' && c != EOF) {
238 c = part_getc(part);
239 }
240
241 return sawfinal;
242 }
243
244
245 /*
246 * Return nonzero and set the saw-boundary state iff 'part'
247 * is positioned at a boundary.
248 */
249 static int
250 pendingboundary(struct part *part)
251 {
252 int bufleft;
253 int i;
254
255 /* Fill buffer if we don't have enough to do our look ahead */
256 if (part->cnt < 3 ||
257 (part->cnt < PART_MAX_BOUNDARY_LEN+3 && part->ptr[1] == '-' &&
258 part->ptr[2] == '-')) {
259
260 bufleft = part->buf_alloc - part->cnt - (part->ptr - part->buf);
261
262 /* If not enough room, move everything to beginning of buffer */
263 if (part->ptr!=part->buf && bufleft + part->cnt < PART_MAX_BOUNDARY_LEN+3) {
264 for (i = 0; i < part->cnt; i++) {
265 part->buf[i] = part->ptr[i];
266 }
267 part->ptr = part->buf;
268 bufleft = part->buf_alloc - part->cnt;
269 }
270
271 /* Read in more data */
272 part->cnt += fread(part->ptr+part->cnt, 1, bufleft, part->infile);
273 }
274
275 /* If no "--", it's not a boundary */
276 if (part->cnt < 3 || part->ptr[1] != '-' || part->ptr[2] != '-') {
277 return 0;
278 }
279
280 for (i = 0; i < part->boundary_num; i++) {
281 if (part->cnt - 3 >= part->boundary_length[i] &&
282 !strncmp((char *)part->ptr+3, part->boundary[i],
283 part->boundary_length[i])) {
284 break;
285 }
286 }
287
288 if (i == part->boundary_num) return 0;
289
290 /* Saw boundary, index 'i' */
291 part->boundary_seen = i;
292 return 1;
293 }

  ViewVC Help
Powered by ViewVC 1.1.22