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

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

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


Revision 1.1 - (hide annotations) (download)
Tue Aug 26 20:45:25 2003 UTC (20 years, 8 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 edhill 1.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