2 * Copyright (C) 2000 Ximian Inc.
4 * Authors: Michael Zucchi <notzed@ximian.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU Lesser General Public
8 * License as published by the Free Software Foundation.
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 GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
23 #include "camel-mime-filter.h"
25 /*#define MALLOC_CHECK */ /* for some malloc checking, requires mcheck enabled */
27 /* only suitable for glibc */
32 struct _CamelMimeFilterPrivate {
38 #define BACK_HEAD (64)
39 #define _PRIVATE(o) (((CamelMimeFilter *)(o))->priv)
40 #define FCLASS(o) ((CamelMimeFilterClass *)(CAMEL_OBJECT_GET_CLASS(o)))
42 static CamelObjectClass *camel_mime_filter_parent;
44 static void complete (CamelMimeFilter *mf, char *in, size_t len,
45 size_t prespace, char **out, size_t *outlen,
49 camel_mime_filter_class_init (CamelMimeFilterClass *klass)
51 camel_mime_filter_parent = camel_type_get_global_classfuncs (camel_object_get_type ());
53 klass->complete = complete;
57 camel_mime_filter_init (CamelMimeFilter *obj)
67 _PRIVATE(obj) = g_malloc0(sizeof(*obj->priv));
71 camel_mime_filter_finalize(CamelObject *o)
73 CamelMimeFilter *f = (CamelMimeFilter *)o;
74 struct _CamelMimeFilterPrivate *p = _PRIVATE(f);
83 camel_mime_filter_get_type (void)
85 static CamelType camel_mime_filter_type = CAMEL_INVALID_TYPE;
87 if (camel_mime_filter_type == CAMEL_INVALID_TYPE) {
88 camel_mime_filter_type = camel_type_register (CAMEL_OBJECT_TYPE, "CamelMimeFilter",
89 sizeof (CamelMimeFilter),
90 sizeof (CamelMimeFilterClass),
91 (CamelObjectClassInitFunc) camel_mime_filter_class_init,
93 (CamelObjectInitFunc) camel_mime_filter_init,
94 (CamelObjectFinalizeFunc) camel_mime_filter_finalize);
97 return camel_mime_filter_type;
101 complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace)
103 /* default - do nothing */
108 * camel_mime_filter_new:
110 * Create a new #CamelMimeFilter object.
112 * Returns a new #CamelMimeFilter
115 camel_mime_filter_new (void)
117 CamelMimeFilter *new = CAMEL_MIME_FILTER ( camel_object_new (camel_mime_filter_get_type ()));
126 int status = mprobe(p);
130 printf("Memory underrun at %p\n", p);
133 printf("Memory overrun at %p\n", p);
136 printf("Double free %p\n", p);
143 static void filter_run(CamelMimeFilter *f,
144 char *in, size_t len, size_t prespace,
145 char **out, size_t *outlen, size_t *outprespace,
146 void (*filterfunc)(CamelMimeFilter *f,
147 char *in, size_t len, size_t prespace,
148 char **out, size_t *outlen, size_t *outprespace))
150 struct _CamelMimeFilterPrivate *p;
153 checkmem(f->outreal);
154 checkmem(f->backbuf);
157 here we take a performance hit, if the input buffer doesn't
158 have the pre-space required. We make a buffer that does ...
160 if (prespace < f->backlen) {
161 int newlen = len+prespace+f->backlen;
163 if (p->inlen < newlen) {
164 /* NOTE: g_realloc copies data, we dont need that (slower) */
166 p->inbuf = g_malloc(newlen+PRE_HEAD);
167 p->inlen = newlen+PRE_HEAD;
169 /* copy to end of structure */
170 memcpy(p->inbuf+p->inlen - len, in, len);
171 in = p->inbuf+p->inlen - len;
172 prespace = p->inlen - len;
176 checkmem(f->outreal);
177 checkmem(f->backbuf);
180 /* preload any backed up data */
181 if (f->backlen > 0) {
182 memcpy(in-f->backlen, f->backbuf, f->backlen);
185 prespace -= f->backlen;
189 filterfunc(f, in, len, prespace, out, outlen, outprespace);
192 checkmem(f->outreal);
193 checkmem(f->backbuf);
200 * camel_mime_filter_filter:
201 * @filter: a #CamelMimeFilter object
203 * @len: length of @in
204 * @prespace: amount of prespace
205 * @out: pointer to the output buffer (to be set)
206 * @outlen: pointer to the length of the output buffer (to be set)
207 * @outprespace: pointer to the output prespace length (to be set)
209 * Passes the input buffer, @in, through @filter and generates an
210 * output buffer, @out.
213 camel_mime_filter_filter (CamelMimeFilter *filter,
214 char *in, size_t len, size_t prespace,
215 char **out, size_t *outlen, size_t *outprespace)
217 if (FCLASS(filter)->filter)
218 filter_run(filter, in, len, prespace, out, outlen, outprespace, FCLASS(filter)->filter);
220 g_error("Filter function unplmenented in class");
225 * camel_mime_filter_complete:
226 * @filter: a #CamelMimeFilter object
228 * @len: length of @in
229 * @prespace: amount of prespace
230 * @out: pointer to the output buffer (to be set)
231 * @outlen: pointer to the length of the output buffer (to be set)
232 * @outprespace: pointer to the output prespace length (to be set)
234 * Passes the input buffer, @in, through @filter and generates an
235 * output buffer, @out and makes sure that all data is flushed to the
236 * output buffer. This must be the last filtering call made, no
237 * further calls to #camel_mime_filter_filter may be called on @filter
238 * until @filter has been reset using #camel_mime_filter_reset.
241 camel_mime_filter_complete (CamelMimeFilter *filter,
242 char *in, size_t len, size_t prespace,
243 char **out, size_t *outlen, size_t *outprespace)
245 if (FCLASS(filter)->complete)
246 filter_run(filter, in, len, prespace, out, outlen, outprespace, FCLASS(filter)->complete);
251 * camel_mime_filter_reset:
252 * @filter: a #CamelMimeFilter object
254 * Resets the state on @filter so that it may be used again.
257 camel_mime_filter_reset(CamelMimeFilter *filter)
259 if (FCLASS(filter)->reset) {
260 FCLASS(filter)->reset(filter);
263 /* could free some buffers, if they are really big? */
269 * camel_mime_filter_backup:
270 * @filter: a #camelMimeFilter object
271 * @data: data buffer to backup
272 * @length: length of @data
274 * Saves @data to be used as prespace input data to the next call to
275 * #camel_mime_filter_filter or #camel_mime_filter_complete.
277 * Note: New calls replace old data.
280 camel_mime_filter_backup(CamelMimeFilter *filter, const char *data, size_t length)
282 if (filter->backsize < length) {
283 /* g_realloc copies data, unnecessary overhead */
284 g_free(filter->backbuf);
285 filter->backbuf = g_malloc(length+BACK_HEAD);
286 filter->backsize = length+BACK_HEAD;
288 filter->backlen = length;
289 memcpy(filter->backbuf, data, length);
294 * camel_mime_filter_set_size:
295 * @filter: a #camelMimeFilter object
296 * @size: requested amount of storage space
297 * @keep: %TRUE to keep existing buffered data or %FALSE otherwise
299 * Ensure that @filter has enough storage space to store @size bytes
303 camel_mime_filter_set_size(CamelMimeFilter *filter, size_t size, int keep)
305 if (filter->outsize < size) {
306 int offset = filter->outptr - filter->outreal;
308 filter->outreal = g_realloc(filter->outreal, size + PRE_HEAD*4);
310 g_free(filter->outreal);
311 filter->outreal = g_malloc(size + PRE_HEAD*4);
313 filter->outptr = filter->outreal + offset;
314 filter->outbuf = filter->outreal + PRE_HEAD*4;
315 filter->outsize = size;
316 /* this could be offset from the end of the structure, but
317 this should be good enough */
318 filter->outpre = PRE_HEAD*4;