diff options
Diffstat (limited to 'camel/camel-mime-filter.c')
-rw-r--r-- | camel/camel-mime-filter.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/camel/camel-mime-filter.c b/camel/camel-mime-filter.c new file mode 100644 index 0000000000..de34a4c973 --- /dev/null +++ b/camel/camel-mime-filter.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2000 Helix Code Inc. + * + * Authors: Michael Zucchi <notzed@helixcode.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "camel-mime-filter.h" + +struct _CamelMimeFilterPrivate { + char *inbuf; + size_t inlen; +}; + +#define PRE_HEAD (64) +#define BACK_HEAD (64) +#define _PRIVATE(o) (((CamelMimeFilter *)(o))->priv) +#define FCLASS(o) ((CamelMimeFilterClass *)((GtkObject *)(o))->klass) + +static void camel_mime_filter_class_init (CamelMimeFilterClass *klass); +static void camel_mime_filter_init (CamelMimeFilter *obj); + +static GtkObjectClass *camel_mime_filter_parent; + +enum SIGNALS { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +camel_mime_filter_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "CamelMimeFilter", + sizeof (CamelMimeFilter), + sizeof (CamelMimeFilterClass), + (GtkClassInitFunc) camel_mime_filter_class_init, + (GtkObjectInitFunc) camel_mime_filter_init, + (GtkArgSetFunc) NULL, + (GtkArgGetFunc) NULL + }; + + type = gtk_type_unique (gtk_object_get_type (), &type_info); + } + + return type; +} + +static void +finalise(GtkObject *o) +{ + CamelMimeFilter *f = (CamelMimeFilter *)o; + struct _CamelMimeFilterPrivate *p = _PRIVATE(f); + + g_free(f->outreal); + g_free(f->backbuf); + g_free(p->inbuf); + g_free(p); + + ((GtkObjectClass *)camel_mime_filter_parent)->finalize (o); +} + +static void +complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace) +{ + /* default - do nothing */ +} + +static void +camel_mime_filter_class_init (CamelMimeFilterClass *klass) +{ + GtkObjectClass *object_class = (GtkObjectClass *) klass; + + camel_mime_filter_parent = gtk_type_class (gtk_object_get_type ()); + + object_class->finalize = finalise; + + klass->complete = complete; + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); +} + +static void +camel_mime_filter_init (CamelMimeFilter *obj) +{ + obj->outreal = NULL; + obj->outbuf = NULL; + obj->outsize = 0; + + obj->backbuf = NULL; + obj->backsize = 0; + obj->backlen = 0; + + _PRIVATE(obj) = g_malloc0(sizeof(*obj->priv)); +} + +/** + * camel_mime_filter_new: + * + * Create a new CamelMimeFilter object. + * + * Return value: A new CamelMimeFilter widget. + **/ +CamelMimeFilter * +camel_mime_filter_new (void) +{ + CamelMimeFilter *new = CAMEL_MIME_FILTER ( gtk_type_new (camel_mime_filter_get_type ())); + return new; +} + +static void filter_run(CamelMimeFilter *f, + char *in, size_t len, size_t prespace, + char **out, size_t *outlen, size_t *outprespace, + void (*filterfunc)(CamelMimeFilter *f, + char *in, size_t len, size_t prespace, + char **out, size_t *outlen, size_t *outprespace)) +{ + struct _CamelMimeFilterPrivate *p; + + /* + here we take a performance hit, if the input buffer doesn't + have the pre-space required. We make a buffer that does ... + */ + if (prespace < f->backlen) { + int newlen = len+prespace; + p = _PRIVATE(f); + if (p->inlen < newlen) { + /* NOTE: g_realloc copies data, we dont need that (slower) */ + g_free(p->inbuf); + p->inbuf = g_malloc(newlen+PRE_HEAD); + p->inlen = newlen+PRE_HEAD; + } + /* copy to end of structure */ + memcpy(p->inbuf+p->inlen - len, in, len); + in = p->inbuf+p->inlen - len; + prespace = p->inlen - len; + } + + /* preload any backed up data */ + if (f->backlen > 0) { + memcpy(in-f->backlen, f->backbuf, f->backlen); + in -= f->backlen; + prespace -= f->backlen; + f->backlen = 0; + } + + filterfunc(f, in, len, prespace, out, outlen, outprespace); +} + +void camel_mime_filter_filter(CamelMimeFilter *f, + char *in, size_t len, size_t prespace, + char **out, size_t *outlen, size_t *outprespace) +{ + if (FCLASS(f)->filter) + filter_run(f, in, len, prespace, out, outlen, outprespace, FCLASS(f)->filter); + else + g_error("Filter function unplmenented in class"); +} + +void camel_mime_filter_complete(CamelMimeFilter *f, + char *in, size_t len, size_t prespace, + char **out, size_t *outlen, size_t *outprespace) +{ + if (FCLASS(f)->complete) + filter_run(f, in, len, prespace, out, outlen, outprespace, FCLASS(f)->complete); +} + +void camel_mime_filter_reset(CamelMimeFilter *f) +{ + if (FCLASS(f)->reset) { + FCLASS(f)->reset(f); + } + + /* could free some buffers, if they are really big? */ + f->backlen = 0; +} + +/* sets number of bytes backed up on the input, new calls replace previous ones */ +void camel_mime_filter_backup(CamelMimeFilter *f, char *data, size_t length) +{ + if (f->backsize < length) { + /* g_realloc copies data, unnecessary overhead */ + g_free(f->backbuf); + f->backbuf = g_malloc(length+BACK_HEAD); + f->backsize = length+BACK_HEAD; + } + f->backlen = length; + memcpy(f->backbuf, data, length); +} + +/* ensure this much size available for filter output (if required) */ +void camel_mime_filter_set_size(CamelMimeFilter *f, size_t size, int keep) +{ + if (f->outsize < size) { + int offset = f->outptr - f->outreal; + if (keep) { + f->outreal = g_realloc(f->outreal, size + PRE_HEAD*4); + } else { + g_free(f->outreal); + f->outreal = g_malloc(size + PRE_HEAD*4); + } + f->outptr = f->outreal + offset; + f->outbuf = f->outreal + PRE_HEAD*4; + f->outsize = size; + /* this could be offset from the end of the structure, but + this should be good enough */ + f->outpre = PRE_HEAD*4; + } +} + |