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., 59 Temple Place - Suite 330,
18
* Boston, MA 02111-1307, 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;