diff options
author | Jeffrey Stedfast <fejj@ximian.com> | 2001-09-17 05:42:00 +0000 |
---|---|---|
committer | Jeffrey Stedfast <fejj@src.gnome.org> | 2001-09-17 05:42:00 +0000 |
commit | 49b708d32b2d05fde967fdc9d3ee68d36f91ce5e (patch) | |
tree | 5998431fe3cb65de7bdaa33a1e0204e333a7bf7d | |
parent | 54064169b6c139cd8d0f548b98261542bb0b6922 (diff) | |
download | gmime-49b708d32b2d05fde967fdc9d3ee68d36f91ce5e.tar.gz |
Abstract stream class.
2001-09-17 Jeffrey Stedfast <fejj@ximian.com>
* gmime-stream.[c,h]: Abstract stream class.
* gmime-stream-mem.[c,h]: Memory stream.
* gmime-stream-file.[c,h]: File stream.
* gmime-data-wrapper.[c,h]: Data wrapper class. Will be used as
the content object in MIME parts.
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | gmime-data-wrapper.c | 75 | ||||
-rw-r--r-- | gmime-data-wrapper.h | 62 | ||||
-rw-r--r-- | gmime-stream-file.c | 246 | ||||
-rw-r--r-- | gmime-stream-file.h | 53 | ||||
-rw-r--r-- | gmime-stream-mem.c | 286 | ||||
-rw-r--r-- | gmime-stream-mem.h | 56 | ||||
-rw-r--r-- | gmime-stream.c | 328 | ||||
-rw-r--r-- | gmime-stream.h | 94 | ||||
-rw-r--r-- | gmime/gmime-data-wrapper.c | 75 | ||||
-rw-r--r-- | gmime/gmime-data-wrapper.h | 62 | ||||
-rw-r--r-- | gmime/gmime-stream-file.c | 246 | ||||
-rw-r--r-- | gmime/gmime-stream-file.h | 53 | ||||
-rw-r--r-- | gmime/gmime-stream-mem.c | 286 | ||||
-rw-r--r-- | gmime/gmime-stream-mem.h | 56 | ||||
-rw-r--r-- | gmime/gmime-stream.c | 328 | ||||
-rw-r--r-- | gmime/gmime-stream.h | 94 |
17 files changed, 2411 insertions, 0 deletions
@@ -1,3 +1,14 @@ +2001-09-17 Jeffrey Stedfast <fejj@ximian.com> + + * gmime-stream.[c,h]: Abstract stream class. + + * gmime-stream-mem.[c,h]: Memory stream. + + * gmime-stream-file.[c,h]: File stream. + + * gmime-data-wrapper.[c,h]: Data wrapper class. Will be used as + the content object in MIME parts. + 2001-08-23 Jeffrey Stedfast <fejj@ximian.com> * gmime-utils.c (encode_8bit_word): Oops. Add the closing ? char. diff --git a/gmime-data-wrapper.c b/gmime-data-wrapper.c new file mode 100644 index 00000000..493803b0 --- /dev/null +++ b/gmime-data-wrapper.c @@ -0,0 +1,75 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#include "gmime-data-wrapper.h" + + +GMimeDataWrapper * +g_mime_data_wrapper_new (void) +{ + return g_new0 (GMimeDataWrapper, 1); +} + + +GMimeDataWrapper * +g_mime_data_wrapper_new_with_stream (GMimeStream *stream, GMimePartEncodingType encoding) +{ + GMimeDataWrapper *wrapper; + + wrapper = g_new (GMimeDataWrapper, 1); + wrapper->encoding = encoding; + wrapper->stream = stream; + + return wrapper; +} + + +void +g_mime_data_wrapper_destroy (GMimeDataWrapper *wrapper) +{ + if (wrapper) { + if (wrapper->stream) + g_mime_stream_unref (wrapper->stream); + g_free (wrapper); + } +} + + +void +g_mime_data_wrapper_set_stream (GMimeDataWrapper *wrapper, GMimeStream *stream) +{ + g_return_if_fail (wrapper != NULL); + + if (wrapper->stream) + g_mime_stream_unref (wrapper->stream); + wrapper->stream = stream; +} + + +void +g_mime_data_wrapper_set_encoding (GMimeDataWrapper *wrapper, GMimePartEncodingType encoding) +{ + g_return_if_fail (wrapper != NULL); + + wrapper->encoding = encoding; +} diff --git a/gmime-data-wrapper.h b/gmime-data-wrapper.h new file mode 100644 index 00000000..55b9a9c7 --- /dev/null +++ b/gmime-data-wrapper.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef __GMIME_DATA_WRAPPER_H__ +#define __GMIME_DATA_WRAPPER_H__ + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#include <glib.h> +#include <gmime-content-type.h> +#include <gmime-stream.h> + +typedef enum { + GMIME_PART_ENCODING_DEFAULT, + GMIME_PART_ENCODING_7BIT, + GMIME_PART_ENCODING_8BIT, + GMIME_PART_ENCODING_BASE64, + GMIME_PART_ENCODING_QUOTEDPRINTABLE, + GMIME_PART_NUM_ENCODINGS +} GMimePartEncodingType; + +typedef struct _GMimeDataWrapper { + GMimePartEncodingType encoding; + GMimeStream *stream; +} GMimeDataWrapper; + +GMimeDataWrapper *g_mime_data_wrapper_new (void); +GMimeDataWrapper *g_mime_data_wrapper_new_with_stream (GMimeStream *stream, GMimePartEncodingType encoding); + +void g_mime_data_wrapper_destroy (GMimeDataWrapper *wrapper); + +void g_mime_data_wrapper_set_stream (GMimeDataWrapper *wrapper, GMimeStream *stream); +void g_mime_data_wrapper_set_encoding (GMimeDataWrapper *wrapper, GMimePartEncodingType encoding); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GMIME_DATA_WRAPPER_H__ */ diff --git a/gmime-stream-file.c b/gmime-stream-file.c new file mode 100644 index 00000000..a2cdd57b --- /dev/null +++ b/gmime-stream-file.c @@ -0,0 +1,246 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#include "gmime-stream-file.h" + + +static void +stream_destroy (GMimeStream *stream) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + + if (fstream->fp) + fclose (fstream->fp); + + g_free (fstream); +} + +static ssize_t +stream_read (GMimeStream *stream, char *buf, size_t len) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + + if (stream->bound_end == -1 && stream->position > stream->bound_end) + return -1; + + if (stream->bound_end != -1) + len = MIN (stream->bound_end - stream->position, len); + + /* make sure we are at the right position */ + fseek (fstream->fp, stream->position, SEEK_SET); + + return fread (buf, 1, len, fstream->fp); +} + +static ssize_t +stream_write (GMimeStream *stream, char *buf, size_t len) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + + if (stream->bound_end == -1 && stream->position > stream->bound_end) + return -1; + + if (stream->bound_end != -1) + len = MIN (stream->bound_end - stream->position, len); + + return fwrite (buf, 1, len, fstream->fp); +} + +static int +stream_flush (GMimeStream *stream) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + + g_return_val_if_fail (fstream->fp != NULL, -1); + + return fflush (fstream->fp); +} + +static int +stream_close (GMimeStream *stream) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + int ret; + + g_return_val_if_fail (fstream->fp != NULL, -1); + + ret = fclose (fstream->fp); + if (ret != -1) + fstream->fs = NULL; + + return ret; +} + +static gboolean +stream_eos (GMimeStream *stream) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + + g_return_if_fail (fstream->fp != NULL, TRUE); + + return feof (fstream->fp) ? TRUE : FALSE; +} + +static int +stream_reset (GMimeStream *stream) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + + g_return_val_if_fail (fstream->fp != NULL, -1); + + return fseek (fstream->fp, stream->bound_start, SEEK_SET); +} + +static off_t +stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + off_t ret; + + g_return_val_if_fail (fstream->fp != NULL, -1); + + switch (whence) { + case GMIME_STREAM_SEEK_SET: + ret = fseek (fstream->fp, offset + stream->bound_start, SEEK_SET); + break; + case GMIME_STREAM_SEEK_END: + if (offset < 0) { + offset += stream->bound_end; + ret = fseek (fstream->fp, offset, SEEK_SET); + } else { + ret = fseek (fstream->fp, stream->bound_end, SEEK_SET); + } + break; + case GMIME_STREAM_SEEK_CUR: + offset += stream->position; + if (offset < stream->bound_start) { + ret = fseek (fstream->fp, stream->bound_start, SEEK_SET); + } else if (offset > stream->bound_end) { + ret = fseek (fstream->fp, stream->bound_end, SEEK_SET); + } else { + ret = fseek (fstream->fp, offset, SEEK_CUR); + } + } + + stream->position = ftell (fstream->fp); + + return ret; +} + +static off_t +stream_tell (GMimeStream *stream) +{ + return stream->position - stream->bound_start; +} + +static ssize_t +stream_length (GMimeStream *stream) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + off_t len; + + if (stream->bound_start != -1 && stream->bound_end != -1) + return stream->bound_end - stream->bound_start; + + fseek (fstream->fp, 0, SEEK_END); + len = ftell (fstream->fp); + fseek (fstream->fp, stream->position, SEEK_SET); + + return len; +} + + +/** + * g_mime_stream_file_new: + * @fp: + * + **/ +GMimeStream * +g_mime_stream_file_new (FILE *fp) +{ + GMimeStreamFile *fstream; + GMimeStream *stream; + + fstream = g_new0 (GMimeStreamFile, 1); + fstream->fp = fp; + + stream = (GMimeStream *) fstream; + + stream->refcount = 1; + stream->type = GMIME_STREAM_FILE_TYPE; + + stream->position = ftell (fp); + stream->bound_start = stream->position; + stream->bound_end = -1; + + stream->destroy = stream_destroy; + stream->read = stream_read; + stream->write = strea_write; + stream->flush = stream_flush; + stream->close = stream_close; + stream->seek = stream_seek; + stream->tell = stream_tell; + stream->reset = stream_reset; + stream->eos = stream_eos; + + return stream; +} + + +/** + * g_mime_stream_file_new_with_bounds: + * @fp: + * @start: + * @end: + * + **/ +GMimeStream * +g_mime_stream_file_new_with_bounds (FILE *fp, off_t start, off_t end) +{ + GMimeStreamFile *fstream; + GMimeStream *stream; + + file = g_new0 (GMimeStreamFile, 1); + fstream->fp = fp; + + stream = (GMimeStream *) fstream; + + stream->refcount = 1; + stream->type = GMIME_STREAM_FILE_TYPE; + + stream->position = start; + stream->bound_start = start; + stream->bound_end = end; + + stream->destroy = stream_destroy; + stream->read = stream_read; + stream->write = strea_write; + stream->flush = stream_flush; + stream->close = stream_close; + stream->seek = stream_seek; + stream->tell = stream_tell; + stream->reset = stream_reset; + stream->eos = stream_eos; + + return stream; +} diff --git a/gmime-stream-file.h b/gmime-stream-file.h new file mode 100644 index 00000000..65ff3910 --- /dev/null +++ b/gmime-stream-file.h @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef __GMIME_STREAM_FILE_H__ +#define __GMIME_STREAM_FILE_H__ + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#include <glib.h> +#include <stdio.h> +#include <gmime-stream.h> + +typedef struct _GMimeStreamFile { + GMimeStream parent; + + FILE *fp; +} GMimeStreamFile; + +#define GMIME_STREAM_FILE_TYPE g_str_hash ("GMimeStreamFile") +#define GMIME_IS_STREAM_FILE(stream) (((GMimeStream *) stream)->type == GMIME_STREAM_FILE) +#define GMIME_STREAM_FILE(stream) ((GMimeStreamFile *) stream) + +GMimeStream *g_mime_stream_file_new (FILE *fp); +GMimeStream *g_mime_stream_file_new_with_bounds (FILE *fp, off_t start, off_t end); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GMIME_STREAM_FILE_H__ */ diff --git a/gmime-stream-mem.c b/gmime-stream-mem.c new file mode 100644 index 00000000..f2b5cb62 --- /dev/null +++ b/gmime-stream-mem.c @@ -0,0 +1,286 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#include "gmime-stream-mem.h" + + +static void +stream_destroy (GMimeStream *stream) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + + if (mem->owner && mem->buffer) + g_byte_array_free (mem->buffer, TRUE); + + g_free (mem); +} + +static ssize_t +stream_read (GMimeStream *stream, char *buf, size_t len) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + ssize_t n; + + g_return_val_if_fail (stream->position <= stream->bound_end, -1); + + n = MIN (stream->bound_end - stream->position, len); + if (n > 0) { + memcpy (buf, mem->buffer->data, n); + stream->position += n; + } + + return n; +} + +static ssize_t +stream_write (GMimeStream *stream, char *buf, size_t len) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + + g_byte_array_append (mem->buffer, buf, len); + stream->bound_end = mem->buffer->len; + + return len; +} + +static int +stream_flush (GMimeStream *stream) +{ + /* no-op */ +} + +static int +stream_close (GMimeStream *stream) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + + if (mem->owner) + g_byte_array_free (mem->buffer, TRUE); + + mem->buffer = NULL; + stream->position = 0; + + return 0; +} + +static gboolean +stream_eos (GMimeStream *stream) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + + return mem->buffer ? stream->position == stream->bound_end : TRUE; +} + +static int +stream_reset (GMimeStream *stream) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + + stream->position = stream->bound_start; + + return 0; +} + +static off_t +stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + + g_return_val_if_fail (mem->buffer != NULL, -1); + + switch (whence) { + case GMIME_STREAM_SEEK_SET: + stream->position = MIN (offset + stream->bound_start, stream->bound_end); + break; + case GMIME_STREAM_SEEK_END: + stream->position = MAX (offset + stream->bound_end, 0); + break; + case GMIME_STREAM_SEEK_CUR: + stream->position += offset; + if (stream->position < stream->bound_start) + stream->position = stream->bound_start; + else if (stream->position > stream->bound_end) + stream->position = stream->bound_end; + } + + return 0; +} + +static off_t +stream_tell (GMimeStream *stream) +{ + return stream->position - stream->bound_start; +} + +static ssize_t +stream_length (GMimeStream *stream) +{ + return stream->bound_end - stream->bound_start; +} + + +/** + * g_mime_stream_mem_new: + * + **/ +GMimeStream * +g_mime_stream_mem_new (void) +{ + GMimeStreamMem *mem; + GMimeStream *stream; + + mem = g_new0 (GMimeStreamMem, 1); + mem->owner = TRUE; + xmem->buffer = g_byte_array_new (); + + stream = (GMimeStream *) mem; + + stream->refcount = 1; + stream->type = GMIME_STREAM_MEM_TYPE; + + stream->position = 0; + stream->bound_start = 0; + stream->bound_end = 0; + + stream->destroy = stream_destroy; + stream->read = stream_read; + stream->write = strea_write; + stream->flush = stream_flush; + stream->close = stream_close; + stream->reset = stream_reset; + stream->seek = stream_seek; + stream->tell = stream_tell; + stream->eos = stream_eos; + stream->length = stream_length; + + return stream; +} + + +/** + * g_mime_stream_mem_new_with_byte_array: + * @array: + * + **/ +GMimeStream * +g_mime_stream_mem_new_with_byte_array (GByteArray *array) +{ + GMimeStreamMem *mem; + GMimeStream *stream; + + mem = g_new0 (GMimeStreamMem, 1); + mem->owner = TRUE; + mem->buffer = array; + + stream = (GMimeStream *) mem; + + stream->refcount = 1; + stream->type = GMIME_STREAM_MEM_TYPE; + + stream->position = 0; + stream->bound_start = 0; + stream->bound_end = array->len; + + stream->destroy = stream_destroy; + stream->read = stream_read; + stream->write = strea_write; + stream->flush = stream_flush; + stream->close = stream_close; + stream->reset = stream_reset; + stream->seek = stream_seek; + stream->tell = stream_tell; + stream->eos = stream_eos; + stream->length = stream_length; + + return stream; +} + + +/** + * g_mime_stream_mem_new_with_buffer: + * @buffer: + * @len: + * + **/ +GMimeStream * +g_mime_stream_mem_new_with_buffer (const char *buffer, size_t len) +{ + GMimeStreamMem *mem; + GMimeStream *stream; + + mem = g_new0 (GMimeStreamMem, 1); + mem->owner = TRUE; + mem->buffer = g_byte_array_new (); + + g_byte_array_append (mem->buffer, buffer, len); + + stream = (GMimeStream *) mem; + + stream->refcount = 1; + stream->type = GMIME_STREAM_MEM_TYPE; + + stream->position = 0; + stream->bound_start = 0; + stream->bound_end = len; + + stream->destroy = stream_destroy; + stream->read = stream_read; + stream->write = strea_write; + stream->flush = stream_flush; + stream->close = stream_close; + stream->reset = stream_reset; + stream->seek = stream_seek; + stream->tell = stream_tell; + stream->eos = stream_eos; + stream->length = stream_length; + + return stream; +} + + +/** + * g_mime_stream_mem_set_byte_array: + * @mem: + * @array: + * + **/ +void +g_mime_stream_mem_set_byte_array (GMimeStreamMem *mem, GByteArray *array) +{ + GMimeStream *stream; + + g_return_if_fail (mem != NULL); + g_return_if_fail (array != NULL); + + if (mem->buffer) + g_byte_array_free (mem->buffer, TRUE); + + mem->buffer = array; + mem->owner = FALSE; + + stream = (GMimeStream *) mem; + + stream->position = 0; + stream->bound_start = 0; + stream->bound_end = array->len; +} diff --git a/gmime-stream-mem.h b/gmime-stream-mem.h new file mode 100644 index 00000000..d4fe4e54 --- /dev/null +++ b/gmime-stream-mem.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef __GMIME_STREAM_MEM_H__ +#define __GMIME_STREAM_MEM_H__ + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#include <glib.h> +#include <gmime-stream.h> + +typedef struct _GMimeStreamMem { + GMimeStream parent; + + gboolean owner; + GByteArray *buffer; +} GMimeStreamMem; + +#define GMIME_STREAM_MEM_TYPE g_str_hash ("GMimeStreamMem") +#define GMIME_IS_STREAM_MEM(stream) (((GMimeStream *) stream)->type == GMIME_STREAM_MEM) +#define GMIME_STREAM_MEM(stream) ((GMimeStreamMem *) stream) + +GMimeStream *g_mime_stream_mem_new (void); +GMimeStream *g_mime_stream_mem_new_with_byte_array (GByteArray *array); +GMimeStream *g_mime_stream_mem_new_with_buffer (const char *buffer, size_t len); + +void g_mime_stream_mem_set_byte_array (GMimeStreamMem *mem, GByteArray *array); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GMIME_STREAM_MEM_H__ */ diff --git a/gmime-stream.c b/gmime-stream.c new file mode 100644 index 00000000..4798d6d9 --- /dev/null +++ b/gmime-stream.c @@ -0,0 +1,328 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#include "gmime-stream.h" +#include <string.h> + +/** + * g_mime_stream_read: + * @stream: + * @buf: + * @len: + * + * Attempts to read up to @len bytes from @stream into @buf. + * + * Returns the number of bytes read or -1 on fail. + **/ +ssize_t +g_mime_stream_read (GMimeStream *stream, char *buf, size_t len) +{ + g_return_val_if_fail (stream != NULL, -1); + g_return_val_if_fail (buf != NULL, -1); + + return *(stream->read) (stream, buf, len); +} + + +/** + * g_mime_stream_write: + * @stream: + * @buf: + * @len: + * + * Attempts to write up to @len bytes of @buf to @stream. + * + * Returns the number of bytes written or -1 on fail. + **/ +ssize_t +g_mime_stream_write (GMimeStream *stream, char *buf, size_t len) +{ + g_return_val_if_fail (stream != NULL, -1); + g_return_val_if_fail (buf != NULL, -1); + + return *(stream->write) (stream, buf, len); +} + + +/** + * g_mime_stream_flush: + * @stream: + * + * Sync's the stream to disk. + * + * Returns 0 on success or -1 on fail. + **/ +int +g_mime_stream_flush (GMimeStream *stream) +{ + g_return_val_if_fail (stream != NULL, -1); + + return *(stream->flush) (stream); +} + + +/** + * g_mime_stream_close: + * @stream: + * + * Closes the stream. + * + * Returns 0 on success or -1 on fail. + **/ +int +g_mime_stream_close (GMimeStream *stream) +{ + g_return_val_if_fail (stream != NULL, -1); + + return *(stream->close) (stream); +} + + +/** + * g_mime_stream_eos: + * @stream: + * + * Tests the end-of-stream indicator for @stream. + * + * Returns TRUE on EOS or FALSE otherwise. + **/ +gboolean +g_mime_stream_eos (GMimeStream *stream) +{ + g_return_val_if_fail (stream != NULL, TRUE); + + return *(stream->eos) (stream); +} + + +/** + * g_mime_stream_reset: + * @stream: + * + * Resets the stream. + * + * Returns 0 on success or -1 on fail. + **/ +int +g_mime_stream_reset (GMimeStream *stream) +{ + g_return_val_if_fail (stream != NULL, -1); + + return *(stream->reset) (stream); +} + + +/** + * g_mime_stream_seek: + * @stream: + * @offset: + * @whence: + * + * Seek to a position in the stream. + **/ +off_t +g_mime_stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence) +{ + g_return_val_if_fail (stream != NULL, -1); + + return *(stream->seek) (stream, offset, whence); +} + + +/** + * g_mime_stream_tell: + * @stream: + * + * Returns the current position within the stream. + **/ +off_t +g_mime_stream_tell (GMimeStream *stream) +{ + g_return_val_if_fail (stream != NULL, -1); + + return *(stream->tell) (stream); +} + + +/** + * g_mime_stream_length: + * @stream: + * + * Returns the length of the stream or -1 on fail. + **/ +ssize_t +g_mime_stream_length (GMimeStream *stream) +{ + g_return_val_if_fail (stream != NULL, -1); + + return *(stream->length) (stream); +} + + +/** + * g_mime_stream_ref: + * @stream: + * + * Ref's a stream. + **/ +void +g_mime_stream_ref (GMimeStream *stream) +{ + g_return_if_fail (stream != NULL); + + stream->refcount++; +} + + +/** + * g_mime_stream_unref: + * @stream: + * + * Unref's a stream. + **/ +void +g_mime_stream_unref (GMimeStream *stream) +{ + g_return_if_fail (stream != NULL); + + if (stream->refcount <= 1) { + if (stream->user_data && stream->user_data_destroy) + *(stream->user_data_destroy) (stream->user_data); + + *(stream->destroy) (stream); + } else { + stream->refcount--; + } +} + + +/** + * g_mime_stream_set_bounds: + * @stream: + * @start: + * @end: + * + * Set the bounds on a stream. + **/ +void +g_mime_stream_set_bounds (GMimeStream *stream, off_t start, off_t end) +{ + g_return_if_fail (stream != NULL); + + stream->bound_start = start; + stream->bound_end = end; + + if (stream->position < start) + stream->position = start; + else if (stream->position > end) + stream->position = end; +} + + +/** + * g_mime_stream_write_string: + * @stream: + * @string: + * + * Write's @string to @stream. + * + * Returns the number of bytes written. + **/ +ssize_t +g_mime_stream_write_string (GMimeStream *stream, const char *string) +{ + g_return_val_if_fail (stream != NULL, -1); + + return g_mime_stream_write (stream, string, strlen (string)); +} + + +/** + * g_mime_stream_printf: + * @stream: + * @fmt: + * @args: + * + **/ +ssize_t +g_mime_stream_printf (GMimeStream *stream, const char *fmt, ...) +{ + va_list args; + char *string; + ssize_t ret; + + g_return_val_if_fail (stream != NULL, -1); + + va_start (args, fmt); + string = g_strdup_vprintf (args); + va_end (args); + + if (!string) + return -1; + + ret = g_mime_stream_write (stream, string, strlen (string)); + g_free (string); + + return ret; +} + + +/** + * g_mime_stream_write_to_stream: + * @src: + * @dest: + * + * Attempts to write stream @src to stream @dest. + * + * Returns the number of bytes written. + **/ +ssize_t +g_mime_stream_write_to_stream (GMimeStream *src, GMimeStream *dest) +{ + ssize_t nread, nwritten, total = 0; + char buf[4096]; + + g_return_val_if_fail (src != NULL, -1); + g_return_val_if_fail (dest != NULL, -1); + + while (!g_mime_stream_eos (src)) { + nwritten = 0; + nread = g_mime_stream_read (src, buf, sizeof (buf)); + if (nread < 0) + return -1; + + while (nwritten < nread) { + ssize_t len; + + len = g_mime_stream_write (dest, buf + nwritten, nread - nwritten); + if (len < 0) + return -1; + + nwritten += len; + } + + total += nwritten; + } + + return total; +} diff --git a/gmime-stream.h b/gmime-stream.h new file mode 100644 index 00000000..8c61099f --- /dev/null +++ b/gmime-stream.h @@ -0,0 +1,94 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef __GMIME_STREAM_H__ +#define __GMIME_STREAM_H__ + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#include <glib.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdarg.h> + +typedef enum { + GMIME_STREAM_SEEK_SET = SEEK_SET, + GMIME_STREAM_SEEK_CUR = SEEK_CUR, + GMIME_STREAM_SEEK_END = SEEK_END, +} GMimeSeekWhence; + +typedef struct _GMimeStream { + int type; + int refcount; + + off_t position; + off_t bound_start; + off_t bound_end; + + void *user_data; + void (*user_data_destroy) (void *user_data); + + void (*destroy) (GMimeStream *stream); + + ssize_t (*read) (GMimeStream *stream, char *buf, size_t len); + ssize_t (*write) (GMimeStream *stream, char *buf, size_t len); + int (*flush) (GMimeStream *stream); + int (*close) (GMimeStream *stream); + gboolean (*eos) (GMimeStream *stream); + int (*reset) (GMimeStream *stream); + off_t (*seek) (GMimeStream *stream, off_t offset, GMimeSeekWhence whence); + off_t (*tell) (GMimeStream *stream); + ssize_t (*length) (GMimeStream *stream); +} GMimeStream; + +#define GMIME_STREAM(stream) ((GMimeStream *) stream) + +/* public methods */ +ssize_t g_mime_stream_read (GMimeStream *stream, char *buf, size_t len); +ssize_t g_mime_stream_write (GMimeStream *stream, char *buf, size_t len); +int g_mime_stream_flush (GMimeStream *stream); +int g_mime_stream_close (GMimeStream *stream); +gboolean g_mime_stream_eos (GMimeStream *stream); +int g_mime_stream_reset (GMimeStream *stream); +off_t g_mime_stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence); +off_t g_mime_stream_tell (GMimeStream *stream); +ssize_t g_mime_stream_length (GMimeStream *stream); + +void g_mime_stream_ref (GMimeStream *stream); +void g_mime_stream_unref (GMimeStream *stream); + +void g_mime_stream_set_bounds (GMimeStream *stream, off_t start, off_t end); + +ssize_t g_mime_stream_write_string (GMimeStream *stream, const char *string); +ssize_t g_mime_stream_printf (GMimeStream *stream, const char *fmt, ...) G_GNUC_PRINTF (2, 3); + +ssize_t g_mime_stream_write_to_stream (GMimeStream *src, GMimeStream *dest); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GMIME_STREAM_H__ */ diff --git a/gmime/gmime-data-wrapper.c b/gmime/gmime-data-wrapper.c new file mode 100644 index 00000000..493803b0 --- /dev/null +++ b/gmime/gmime-data-wrapper.c @@ -0,0 +1,75 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#include "gmime-data-wrapper.h" + + +GMimeDataWrapper * +g_mime_data_wrapper_new (void) +{ + return g_new0 (GMimeDataWrapper, 1); +} + + +GMimeDataWrapper * +g_mime_data_wrapper_new_with_stream (GMimeStream *stream, GMimePartEncodingType encoding) +{ + GMimeDataWrapper *wrapper; + + wrapper = g_new (GMimeDataWrapper, 1); + wrapper->encoding = encoding; + wrapper->stream = stream; + + return wrapper; +} + + +void +g_mime_data_wrapper_destroy (GMimeDataWrapper *wrapper) +{ + if (wrapper) { + if (wrapper->stream) + g_mime_stream_unref (wrapper->stream); + g_free (wrapper); + } +} + + +void +g_mime_data_wrapper_set_stream (GMimeDataWrapper *wrapper, GMimeStream *stream) +{ + g_return_if_fail (wrapper != NULL); + + if (wrapper->stream) + g_mime_stream_unref (wrapper->stream); + wrapper->stream = stream; +} + + +void +g_mime_data_wrapper_set_encoding (GMimeDataWrapper *wrapper, GMimePartEncodingType encoding) +{ + g_return_if_fail (wrapper != NULL); + + wrapper->encoding = encoding; +} diff --git a/gmime/gmime-data-wrapper.h b/gmime/gmime-data-wrapper.h new file mode 100644 index 00000000..55b9a9c7 --- /dev/null +++ b/gmime/gmime-data-wrapper.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef __GMIME_DATA_WRAPPER_H__ +#define __GMIME_DATA_WRAPPER_H__ + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#include <glib.h> +#include <gmime-content-type.h> +#include <gmime-stream.h> + +typedef enum { + GMIME_PART_ENCODING_DEFAULT, + GMIME_PART_ENCODING_7BIT, + GMIME_PART_ENCODING_8BIT, + GMIME_PART_ENCODING_BASE64, + GMIME_PART_ENCODING_QUOTEDPRINTABLE, + GMIME_PART_NUM_ENCODINGS +} GMimePartEncodingType; + +typedef struct _GMimeDataWrapper { + GMimePartEncodingType encoding; + GMimeStream *stream; +} GMimeDataWrapper; + +GMimeDataWrapper *g_mime_data_wrapper_new (void); +GMimeDataWrapper *g_mime_data_wrapper_new_with_stream (GMimeStream *stream, GMimePartEncodingType encoding); + +void g_mime_data_wrapper_destroy (GMimeDataWrapper *wrapper); + +void g_mime_data_wrapper_set_stream (GMimeDataWrapper *wrapper, GMimeStream *stream); +void g_mime_data_wrapper_set_encoding (GMimeDataWrapper *wrapper, GMimePartEncodingType encoding); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GMIME_DATA_WRAPPER_H__ */ diff --git a/gmime/gmime-stream-file.c b/gmime/gmime-stream-file.c new file mode 100644 index 00000000..a2cdd57b --- /dev/null +++ b/gmime/gmime-stream-file.c @@ -0,0 +1,246 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#include "gmime-stream-file.h" + + +static void +stream_destroy (GMimeStream *stream) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + + if (fstream->fp) + fclose (fstream->fp); + + g_free (fstream); +} + +static ssize_t +stream_read (GMimeStream *stream, char *buf, size_t len) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + + if (stream->bound_end == -1 && stream->position > stream->bound_end) + return -1; + + if (stream->bound_end != -1) + len = MIN (stream->bound_end - stream->position, len); + + /* make sure we are at the right position */ + fseek (fstream->fp, stream->position, SEEK_SET); + + return fread (buf, 1, len, fstream->fp); +} + +static ssize_t +stream_write (GMimeStream *stream, char *buf, size_t len) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + + if (stream->bound_end == -1 && stream->position > stream->bound_end) + return -1; + + if (stream->bound_end != -1) + len = MIN (stream->bound_end - stream->position, len); + + return fwrite (buf, 1, len, fstream->fp); +} + +static int +stream_flush (GMimeStream *stream) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + + g_return_val_if_fail (fstream->fp != NULL, -1); + + return fflush (fstream->fp); +} + +static int +stream_close (GMimeStream *stream) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + int ret; + + g_return_val_if_fail (fstream->fp != NULL, -1); + + ret = fclose (fstream->fp); + if (ret != -1) + fstream->fs = NULL; + + return ret; +} + +static gboolean +stream_eos (GMimeStream *stream) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + + g_return_if_fail (fstream->fp != NULL, TRUE); + + return feof (fstream->fp) ? TRUE : FALSE; +} + +static int +stream_reset (GMimeStream *stream) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + + g_return_val_if_fail (fstream->fp != NULL, -1); + + return fseek (fstream->fp, stream->bound_start, SEEK_SET); +} + +static off_t +stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + off_t ret; + + g_return_val_if_fail (fstream->fp != NULL, -1); + + switch (whence) { + case GMIME_STREAM_SEEK_SET: + ret = fseek (fstream->fp, offset + stream->bound_start, SEEK_SET); + break; + case GMIME_STREAM_SEEK_END: + if (offset < 0) { + offset += stream->bound_end; + ret = fseek (fstream->fp, offset, SEEK_SET); + } else { + ret = fseek (fstream->fp, stream->bound_end, SEEK_SET); + } + break; + case GMIME_STREAM_SEEK_CUR: + offset += stream->position; + if (offset < stream->bound_start) { + ret = fseek (fstream->fp, stream->bound_start, SEEK_SET); + } else if (offset > stream->bound_end) { + ret = fseek (fstream->fp, stream->bound_end, SEEK_SET); + } else { + ret = fseek (fstream->fp, offset, SEEK_CUR); + } + } + + stream->position = ftell (fstream->fp); + + return ret; +} + +static off_t +stream_tell (GMimeStream *stream) +{ + return stream->position - stream->bound_start; +} + +static ssize_t +stream_length (GMimeStream *stream) +{ + GMimeStreamFile *fstream = (GMimeStreamFile *) stream; + off_t len; + + if (stream->bound_start != -1 && stream->bound_end != -1) + return stream->bound_end - stream->bound_start; + + fseek (fstream->fp, 0, SEEK_END); + len = ftell (fstream->fp); + fseek (fstream->fp, stream->position, SEEK_SET); + + return len; +} + + +/** + * g_mime_stream_file_new: + * @fp: + * + **/ +GMimeStream * +g_mime_stream_file_new (FILE *fp) +{ + GMimeStreamFile *fstream; + GMimeStream *stream; + + fstream = g_new0 (GMimeStreamFile, 1); + fstream->fp = fp; + + stream = (GMimeStream *) fstream; + + stream->refcount = 1; + stream->type = GMIME_STREAM_FILE_TYPE; + + stream->position = ftell (fp); + stream->bound_start = stream->position; + stream->bound_end = -1; + + stream->destroy = stream_destroy; + stream->read = stream_read; + stream->write = strea_write; + stream->flush = stream_flush; + stream->close = stream_close; + stream->seek = stream_seek; + stream->tell = stream_tell; + stream->reset = stream_reset; + stream->eos = stream_eos; + + return stream; +} + + +/** + * g_mime_stream_file_new_with_bounds: + * @fp: + * @start: + * @end: + * + **/ +GMimeStream * +g_mime_stream_file_new_with_bounds (FILE *fp, off_t start, off_t end) +{ + GMimeStreamFile *fstream; + GMimeStream *stream; + + file = g_new0 (GMimeStreamFile, 1); + fstream->fp = fp; + + stream = (GMimeStream *) fstream; + + stream->refcount = 1; + stream->type = GMIME_STREAM_FILE_TYPE; + + stream->position = start; + stream->bound_start = start; + stream->bound_end = end; + + stream->destroy = stream_destroy; + stream->read = stream_read; + stream->write = strea_write; + stream->flush = stream_flush; + stream->close = stream_close; + stream->seek = stream_seek; + stream->tell = stream_tell; + stream->reset = stream_reset; + stream->eos = stream_eos; + + return stream; +} diff --git a/gmime/gmime-stream-file.h b/gmime/gmime-stream-file.h new file mode 100644 index 00000000..65ff3910 --- /dev/null +++ b/gmime/gmime-stream-file.h @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef __GMIME_STREAM_FILE_H__ +#define __GMIME_STREAM_FILE_H__ + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#include <glib.h> +#include <stdio.h> +#include <gmime-stream.h> + +typedef struct _GMimeStreamFile { + GMimeStream parent; + + FILE *fp; +} GMimeStreamFile; + +#define GMIME_STREAM_FILE_TYPE g_str_hash ("GMimeStreamFile") +#define GMIME_IS_STREAM_FILE(stream) (((GMimeStream *) stream)->type == GMIME_STREAM_FILE) +#define GMIME_STREAM_FILE(stream) ((GMimeStreamFile *) stream) + +GMimeStream *g_mime_stream_file_new (FILE *fp); +GMimeStream *g_mime_stream_file_new_with_bounds (FILE *fp, off_t start, off_t end); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GMIME_STREAM_FILE_H__ */ diff --git a/gmime/gmime-stream-mem.c b/gmime/gmime-stream-mem.c new file mode 100644 index 00000000..f2b5cb62 --- /dev/null +++ b/gmime/gmime-stream-mem.c @@ -0,0 +1,286 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#include "gmime-stream-mem.h" + + +static void +stream_destroy (GMimeStream *stream) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + + if (mem->owner && mem->buffer) + g_byte_array_free (mem->buffer, TRUE); + + g_free (mem); +} + +static ssize_t +stream_read (GMimeStream *stream, char *buf, size_t len) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + ssize_t n; + + g_return_val_if_fail (stream->position <= stream->bound_end, -1); + + n = MIN (stream->bound_end - stream->position, len); + if (n > 0) { + memcpy (buf, mem->buffer->data, n); + stream->position += n; + } + + return n; +} + +static ssize_t +stream_write (GMimeStream *stream, char *buf, size_t len) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + + g_byte_array_append (mem->buffer, buf, len); + stream->bound_end = mem->buffer->len; + + return len; +} + +static int +stream_flush (GMimeStream *stream) +{ + /* no-op */ +} + +static int +stream_close (GMimeStream *stream) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + + if (mem->owner) + g_byte_array_free (mem->buffer, TRUE); + + mem->buffer = NULL; + stream->position = 0; + + return 0; +} + +static gboolean +stream_eos (GMimeStream *stream) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + + return mem->buffer ? stream->position == stream->bound_end : TRUE; +} + +static int +stream_reset (GMimeStream *stream) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + + stream->position = stream->bound_start; + + return 0; +} + +static off_t +stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence) +{ + GMimeStreamMem *mem = (GMimeStreamMem *) stream; + + g_return_val_if_fail (mem->buffer != NULL, -1); + + switch (whence) { + case GMIME_STREAM_SEEK_SET: + stream->position = MIN (offset + stream->bound_start, stream->bound_end); + break; + case GMIME_STREAM_SEEK_END: + stream->position = MAX (offset + stream->bound_end, 0); + break; + case GMIME_STREAM_SEEK_CUR: + stream->position += offset; + if (stream->position < stream->bound_start) + stream->position = stream->bound_start; + else if (stream->position > stream->bound_end) + stream->position = stream->bound_end; + } + + return 0; +} + +static off_t +stream_tell (GMimeStream *stream) +{ + return stream->position - stream->bound_start; +} + +static ssize_t +stream_length (GMimeStream *stream) +{ + return stream->bound_end - stream->bound_start; +} + + +/** + * g_mime_stream_mem_new: + * + **/ +GMimeStream * +g_mime_stream_mem_new (void) +{ + GMimeStreamMem *mem; + GMimeStream *stream; + + mem = g_new0 (GMimeStreamMem, 1); + mem->owner = TRUE; + xmem->buffer = g_byte_array_new (); + + stream = (GMimeStream *) mem; + + stream->refcount = 1; + stream->type = GMIME_STREAM_MEM_TYPE; + + stream->position = 0; + stream->bound_start = 0; + stream->bound_end = 0; + + stream->destroy = stream_destroy; + stream->read = stream_read; + stream->write = strea_write; + stream->flush = stream_flush; + stream->close = stream_close; + stream->reset = stream_reset; + stream->seek = stream_seek; + stream->tell = stream_tell; + stream->eos = stream_eos; + stream->length = stream_length; + + return stream; +} + + +/** + * g_mime_stream_mem_new_with_byte_array: + * @array: + * + **/ +GMimeStream * +g_mime_stream_mem_new_with_byte_array (GByteArray *array) +{ + GMimeStreamMem *mem; + GMimeStream *stream; + + mem = g_new0 (GMimeStreamMem, 1); + mem->owner = TRUE; + mem->buffer = array; + + stream = (GMimeStream *) mem; + + stream->refcount = 1; + stream->type = GMIME_STREAM_MEM_TYPE; + + stream->position = 0; + stream->bound_start = 0; + stream->bound_end = array->len; + + stream->destroy = stream_destroy; + stream->read = stream_read; + stream->write = strea_write; + stream->flush = stream_flush; + stream->close = stream_close; + stream->reset = stream_reset; + stream->seek = stream_seek; + stream->tell = stream_tell; + stream->eos = stream_eos; + stream->length = stream_length; + + return stream; +} + + +/** + * g_mime_stream_mem_new_with_buffer: + * @buffer: + * @len: + * + **/ +GMimeStream * +g_mime_stream_mem_new_with_buffer (const char *buffer, size_t len) +{ + GMimeStreamMem *mem; + GMimeStream *stream; + + mem = g_new0 (GMimeStreamMem, 1); + mem->owner = TRUE; + mem->buffer = g_byte_array_new (); + + g_byte_array_append (mem->buffer, buffer, len); + + stream = (GMimeStream *) mem; + + stream->refcount = 1; + stream->type = GMIME_STREAM_MEM_TYPE; + + stream->position = 0; + stream->bound_start = 0; + stream->bound_end = len; + + stream->destroy = stream_destroy; + stream->read = stream_read; + stream->write = strea_write; + stream->flush = stream_flush; + stream->close = stream_close; + stream->reset = stream_reset; + stream->seek = stream_seek; + stream->tell = stream_tell; + stream->eos = stream_eos; + stream->length = stream_length; + + return stream; +} + + +/** + * g_mime_stream_mem_set_byte_array: + * @mem: + * @array: + * + **/ +void +g_mime_stream_mem_set_byte_array (GMimeStreamMem *mem, GByteArray *array) +{ + GMimeStream *stream; + + g_return_if_fail (mem != NULL); + g_return_if_fail (array != NULL); + + if (mem->buffer) + g_byte_array_free (mem->buffer, TRUE); + + mem->buffer = array; + mem->owner = FALSE; + + stream = (GMimeStream *) mem; + + stream->position = 0; + stream->bound_start = 0; + stream->bound_end = array->len; +} diff --git a/gmime/gmime-stream-mem.h b/gmime/gmime-stream-mem.h new file mode 100644 index 00000000..d4fe4e54 --- /dev/null +++ b/gmime/gmime-stream-mem.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef __GMIME_STREAM_MEM_H__ +#define __GMIME_STREAM_MEM_H__ + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#include <glib.h> +#include <gmime-stream.h> + +typedef struct _GMimeStreamMem { + GMimeStream parent; + + gboolean owner; + GByteArray *buffer; +} GMimeStreamMem; + +#define GMIME_STREAM_MEM_TYPE g_str_hash ("GMimeStreamMem") +#define GMIME_IS_STREAM_MEM(stream) (((GMimeStream *) stream)->type == GMIME_STREAM_MEM) +#define GMIME_STREAM_MEM(stream) ((GMimeStreamMem *) stream) + +GMimeStream *g_mime_stream_mem_new (void); +GMimeStream *g_mime_stream_mem_new_with_byte_array (GByteArray *array); +GMimeStream *g_mime_stream_mem_new_with_buffer (const char *buffer, size_t len); + +void g_mime_stream_mem_set_byte_array (GMimeStreamMem *mem, GByteArray *array); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GMIME_STREAM_MEM_H__ */ diff --git a/gmime/gmime-stream.c b/gmime/gmime-stream.c new file mode 100644 index 00000000..4798d6d9 --- /dev/null +++ b/gmime/gmime-stream.c @@ -0,0 +1,328 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#include "gmime-stream.h" +#include <string.h> + +/** + * g_mime_stream_read: + * @stream: + * @buf: + * @len: + * + * Attempts to read up to @len bytes from @stream into @buf. + * + * Returns the number of bytes read or -1 on fail. + **/ +ssize_t +g_mime_stream_read (GMimeStream *stream, char *buf, size_t len) +{ + g_return_val_if_fail (stream != NULL, -1); + g_return_val_if_fail (buf != NULL, -1); + + return *(stream->read) (stream, buf, len); +} + + +/** + * g_mime_stream_write: + * @stream: + * @buf: + * @len: + * + * Attempts to write up to @len bytes of @buf to @stream. + * + * Returns the number of bytes written or -1 on fail. + **/ +ssize_t +g_mime_stream_write (GMimeStream *stream, char *buf, size_t len) +{ + g_return_val_if_fail (stream != NULL, -1); + g_return_val_if_fail (buf != NULL, -1); + + return *(stream->write) (stream, buf, len); +} + + +/** + * g_mime_stream_flush: + * @stream: + * + * Sync's the stream to disk. + * + * Returns 0 on success or -1 on fail. + **/ +int +g_mime_stream_flush (GMimeStream *stream) +{ + g_return_val_if_fail (stream != NULL, -1); + + return *(stream->flush) (stream); +} + + +/** + * g_mime_stream_close: + * @stream: + * + * Closes the stream. + * + * Returns 0 on success or -1 on fail. + **/ +int +g_mime_stream_close (GMimeStream *stream) +{ + g_return_val_if_fail (stream != NULL, -1); + + return *(stream->close) (stream); +} + + +/** + * g_mime_stream_eos: + * @stream: + * + * Tests the end-of-stream indicator for @stream. + * + * Returns TRUE on EOS or FALSE otherwise. + **/ +gboolean +g_mime_stream_eos (GMimeStream *stream) +{ + g_return_val_if_fail (stream != NULL, TRUE); + + return *(stream->eos) (stream); +} + + +/** + * g_mime_stream_reset: + * @stream: + * + * Resets the stream. + * + * Returns 0 on success or -1 on fail. + **/ +int +g_mime_stream_reset (GMimeStream *stream) +{ + g_return_val_if_fail (stream != NULL, -1); + + return *(stream->reset) (stream); +} + + +/** + * g_mime_stream_seek: + * @stream: + * @offset: + * @whence: + * + * Seek to a position in the stream. + **/ +off_t +g_mime_stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence) +{ + g_return_val_if_fail (stream != NULL, -1); + + return *(stream->seek) (stream, offset, whence); +} + + +/** + * g_mime_stream_tell: + * @stream: + * + * Returns the current position within the stream. + **/ +off_t +g_mime_stream_tell (GMimeStream *stream) +{ + g_return_val_if_fail (stream != NULL, -1); + + return *(stream->tell) (stream); +} + + +/** + * g_mime_stream_length: + * @stream: + * + * Returns the length of the stream or -1 on fail. + **/ +ssize_t +g_mime_stream_length (GMimeStream *stream) +{ + g_return_val_if_fail (stream != NULL, -1); + + return *(stream->length) (stream); +} + + +/** + * g_mime_stream_ref: + * @stream: + * + * Ref's a stream. + **/ +void +g_mime_stream_ref (GMimeStream *stream) +{ + g_return_if_fail (stream != NULL); + + stream->refcount++; +} + + +/** + * g_mime_stream_unref: + * @stream: + * + * Unref's a stream. + **/ +void +g_mime_stream_unref (GMimeStream *stream) +{ + g_return_if_fail (stream != NULL); + + if (stream->refcount <= 1) { + if (stream->user_data && stream->user_data_destroy) + *(stream->user_data_destroy) (stream->user_data); + + *(stream->destroy) (stream); + } else { + stream->refcount--; + } +} + + +/** + * g_mime_stream_set_bounds: + * @stream: + * @start: + * @end: + * + * Set the bounds on a stream. + **/ +void +g_mime_stream_set_bounds (GMimeStream *stream, off_t start, off_t end) +{ + g_return_if_fail (stream != NULL); + + stream->bound_start = start; + stream->bound_end = end; + + if (stream->position < start) + stream->position = start; + else if (stream->position > end) + stream->position = end; +} + + +/** + * g_mime_stream_write_string: + * @stream: + * @string: + * + * Write's @string to @stream. + * + * Returns the number of bytes written. + **/ +ssize_t +g_mime_stream_write_string (GMimeStream *stream, const char *string) +{ + g_return_val_if_fail (stream != NULL, -1); + + return g_mime_stream_write (stream, string, strlen (string)); +} + + +/** + * g_mime_stream_printf: + * @stream: + * @fmt: + * @args: + * + **/ +ssize_t +g_mime_stream_printf (GMimeStream *stream, const char *fmt, ...) +{ + va_list args; + char *string; + ssize_t ret; + + g_return_val_if_fail (stream != NULL, -1); + + va_start (args, fmt); + string = g_strdup_vprintf (args); + va_end (args); + + if (!string) + return -1; + + ret = g_mime_stream_write (stream, string, strlen (string)); + g_free (string); + + return ret; +} + + +/** + * g_mime_stream_write_to_stream: + * @src: + * @dest: + * + * Attempts to write stream @src to stream @dest. + * + * Returns the number of bytes written. + **/ +ssize_t +g_mime_stream_write_to_stream (GMimeStream *src, GMimeStream *dest) +{ + ssize_t nread, nwritten, total = 0; + char buf[4096]; + + g_return_val_if_fail (src != NULL, -1); + g_return_val_if_fail (dest != NULL, -1); + + while (!g_mime_stream_eos (src)) { + nwritten = 0; + nread = g_mime_stream_read (src, buf, sizeof (buf)); + if (nread < 0) + return -1; + + while (nwritten < nread) { + ssize_t len; + + len = g_mime_stream_write (dest, buf + nwritten, nread - nwritten); + if (len < 0) + return -1; + + nwritten += len; + } + + total += nwritten; + } + + return total; +} diff --git a/gmime/gmime-stream.h b/gmime/gmime-stream.h new file mode 100644 index 00000000..8c61099f --- /dev/null +++ b/gmime/gmime-stream.h @@ -0,0 +1,94 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximain, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef __GMIME_STREAM_H__ +#define __GMIME_STREAM_H__ + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#include <glib.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdarg.h> + +typedef enum { + GMIME_STREAM_SEEK_SET = SEEK_SET, + GMIME_STREAM_SEEK_CUR = SEEK_CUR, + GMIME_STREAM_SEEK_END = SEEK_END, +} GMimeSeekWhence; + +typedef struct _GMimeStream { + int type; + int refcount; + + off_t position; + off_t bound_start; + off_t bound_end; + + void *user_data; + void (*user_data_destroy) (void *user_data); + + void (*destroy) (GMimeStream *stream); + + ssize_t (*read) (GMimeStream *stream, char *buf, size_t len); + ssize_t (*write) (GMimeStream *stream, char *buf, size_t len); + int (*flush) (GMimeStream *stream); + int (*close) (GMimeStream *stream); + gboolean (*eos) (GMimeStream *stream); + int (*reset) (GMimeStream *stream); + off_t (*seek) (GMimeStream *stream, off_t offset, GMimeSeekWhence whence); + off_t (*tell) (GMimeStream *stream); + ssize_t (*length) (GMimeStream *stream); +} GMimeStream; + +#define GMIME_STREAM(stream) ((GMimeStream *) stream) + +/* public methods */ +ssize_t g_mime_stream_read (GMimeStream *stream, char *buf, size_t len); +ssize_t g_mime_stream_write (GMimeStream *stream, char *buf, size_t len); +int g_mime_stream_flush (GMimeStream *stream); +int g_mime_stream_close (GMimeStream *stream); +gboolean g_mime_stream_eos (GMimeStream *stream); +int g_mime_stream_reset (GMimeStream *stream); +off_t g_mime_stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence); +off_t g_mime_stream_tell (GMimeStream *stream); +ssize_t g_mime_stream_length (GMimeStream *stream); + +void g_mime_stream_ref (GMimeStream *stream); +void g_mime_stream_unref (GMimeStream *stream); + +void g_mime_stream_set_bounds (GMimeStream *stream, off_t start, off_t end); + +ssize_t g_mime_stream_write_string (GMimeStream *stream, const char *string); +ssize_t g_mime_stream_printf (GMimeStream *stream, const char *fmt, ...) G_GNUC_PRINTF (2, 3); + +ssize_t g_mime_stream_write_to_stream (GMimeStream *src, GMimeStream *dest); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GMIME_STREAM_H__ */ |