diff options
author | Jeffrey Stedfast <fejj@ximian.com> | 2001-09-22 02:41:26 +0000 |
---|---|---|
committer | Jeffrey Stedfast <fejj@src.gnome.org> | 2001-09-22 02:41:26 +0000 |
commit | d29f1d7e19394c8b23401692ca2b4a10ac069afe (patch) | |
tree | 735b9be958ef4e1877a0f95cb5498dc999e7ea58 | |
parent | 7f1c4c30a1f7ce9a29021e82343ceeb33f70fc98 (diff) | |
download | gmime-d29f1d7e19394c8b23401692ca2b4a10ac069afe.tar.gz |
Implemented. (stream_reset): Implemented. (stream_eos): Implemented.
2001-09-21 Jeffrey Stedfast <fejj@ximian.com>
* gmime-stream-buffer.c (g_mime_stream_buffer_gets): Implemented.
(stream_reset): Implemented.
(stream_eos): Implemented.
(stream_write): Reimplemented.
(stream_read): Reimplemented.
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | gmime-stream-buffer.c | 284 | ||||
-rw-r--r-- | gmime-stream-buffer.h | 12 | ||||
-rw-r--r-- | gmime/gmime-stream-buffer.c | 284 | ||||
-rw-r--r-- | gmime/gmime-stream-buffer.h | 12 |
6 files changed, 366 insertions, 236 deletions
@@ -1,5 +1,13 @@ 2001-09-21 Jeffrey Stedfast <fejj@ximian.com> + * gmime-stream-buffer.c (g_mime_stream_buffer_gets): Implemented. + (stream_reset): Implemented. + (stream_eos): Implemented. + (stream_write): Reimplemented. + (stream_read): Reimplemented. + +2001-09-21 Jeffrey Stedfast <fejj@ximian.com> + * gmime-stream-buffer.[c,h]: New stream that buffers reads or writes to/from another stream. Will also implement a gets() method for Charles. diff --git a/Makefile.am b/Makefile.am index b42f4398..29ee6d49 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,6 +28,7 @@ libgmime_la_SOURCES = \ gmime-parser.c \ gmime-part.c \ gmime-stream.c \ + gmime-stream-buffer.c \ gmime-stream-file.c \ gmime-stream-filter.c \ gmime-stream-fs.c \ @@ -52,6 +53,7 @@ gmimeinc_HEADERS = \ gmime-parser.h \ gmime-part.h \ gmime-stream.h \ + gmime-stream-buffer.h \ gmime-stream-file.h \ gmime-stream-filter.c \ gmime-stream-fs.h \ diff --git a/gmime-stream-buffer.c b/gmime-stream-buffer.c index 29d649f9..06f16b78 100644 --- a/gmime-stream-buffer.c +++ b/gmime-stream-buffer.c @@ -23,8 +23,8 @@ #include "gmime-stream-buffer.h" -#define NEWLINE_BUFFER_LEN 1024 -#define BUFFER_GROW_SIZE 1024 +#define BLOCK_BUFFER_LEN 1024 +#define BUFFER_GROW_SIZE 1024 static void stream_destroy (GMimeStream *stream); static ssize_t stream_read (GMimeStream *stream, char *buf, size_t len); @@ -69,49 +69,48 @@ stream_read (GMimeStream *stream, char *buf, size_t len) ssize_t nread = 0; ssize_t n; - if (buffer->mode & GMIME_STREAM_BUFFER_MODE == GMIME_STREAM_BUFFER_READ) { - if (buffer->mode & GMIME_STREAM_BUFFER_NEWLINE) { - newline_read: - n = MIN (buffer->buflen, len); - memcpy (buf + nread, buffer->buffer, n); - buffer->buflen -= n; - nread += n; - len -= n; - if (!buffer->buflen) { - /* buffer more data */ - buffer->buflen = g_mime_stream_read (buffer->source, buffer->buffer, - NEWLINE_BUFFER_LEN); - if (buffer->buflen > 0) - goto newline_read; + again: + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_READ: + n = MIN (buffer->buflen, len); + memcpy (buf + nread, buffer->buffer, n); + buffer->buflen -= n; + nread += n; + len -= n; + if (!buffer->buflen) { + /* buffer more data */ + buffer->buflen = g_mime_stream_read (buffer->source, buffer->buffer, + BLOCK_BUFFER_LEN); + if (buffer->buflen > 0) + goto again; + + buffer->buflen = 0; + } + break; + case GMIME_STREAM_BUFFER_CACHE_READ: + n = MIN (buffer->bufend - buffer->bufptr, len); + memcpy (buf + nread, buffer->bufptr, n); + nread += n; + len -= n; + if (len) { + /* we need to read more data... */ + if ((buffer->bufend - buffer->buffer) + len >= buffer->buflen) { + /* we need our buffer to grow... */ + unsigned int offset = buffer->bufend - buffer->buffer; - buffer->buflen = 0; + buffer->buflen += MAX (BUFFER_GROW_SIZE, len); + buffer->buffer = g_realloc (buffer->buffer, buffer->buflen); + buffer->bufptr = buffer->bufend = buffer->buffer + offset; } - } else { - buffered_read: - n = MIN (buffer->bufend - buffer->bufptr, len); - memcpy (buf + nread, buffer->bufptr, n); - nread += n; - len -= n; - if (len) { - /* we need to read more data... */ - if ((buffer->bufend - buffer->buffer) + len >= buffer->buflen) { - /* we need our buffer to grow... */ - unsigned int offset = buffer->bufend - buffer->buffer; - - buffer->buflen += MAX (BUFFER_GROW_SIZE, len); - buffer->buffer = g_realloc (buffer->buffer, buffer->buflen); - buffer->bufptr = buffer->bufend = buffer->buffer + offset; - } - - n = g_mime_stream_read (buffer->source, buffer->bufptr, - MAX (BUFFER_GROW_SIZE, len)); - if (n > 0) { - buffer->bufend += n; - goto buffered_read; - } + + n = g_mime_stream_read (buffer->source, buffer->bufptr, + MAX (BUFFER_GROW_SIZE, len)); + if (n > 0) { + buffer->bufend += n; + goto again; } } - } else { + default: nread = g_mime_stream_read (buffer->source, buf, len); } @@ -127,27 +126,24 @@ stream_write (GMimeStream *stream, char *buf, size_t len) GMimeStreamBuffer *buffer = (GMimeStreamBuffer *) stream; ssize_t written = 0, n; - if (buffer->mode & GMIME_STREAM_BUFFER_MODE == GMIME_STREAM_BUFFER_WRITE) { - if (buffer->mode & GMIME_STREAM_BUFFER_NEWLINE) { - newline_write: - n = MIN (NEWLINE_BUFFER_LEN - buffer->buflen, len); - memcpy (buffer->buffer + buffer->buflen, buf, n); - buffer->buflen += n; - written += n; - len -= n; - if (len) { - /* flush our buffer... */ - n = g_mime_stream_write (buffer->source, buffer->buffer, NEWLINE_BUFFER_LEN); - if (n > 0) { - memmove (buffer->buffer, buffer->buffer + n, NEWLINE_BUFFER_LEN - n); - goto newline_write; - } + again: + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_WRITE: + n = MIN (BLOCK_BUFFER_LEN - buffer->buflen, len); + memcpy (buffer->buffer + buffer->buflen, buf, n); + buffer->buflen += n; + written += n; + len -= n; + if (len) { + /* flush our buffer... */ + n = g_mime_stream_write (buffer->source, buffer->buffer, BLOCK_BUFFER_LEN); + if (n > 0) { + memmove (buffer->buffer, buffer->buffer + n, BLOCK_BUFFER_LEN - n); + goto again; } - } else { - /* FIXME: what do I do here? */ - written = g_mime_stream_write (buffer->source, buf, len); } - } else { + break; + default: written = g_mime_stream_write (buffer->source, buf, len); } @@ -159,20 +155,16 @@ stream_flush (GMimeStream *stream) { GMimeStreamBuffer *buffer = (GMimeStreamBuffer *) stream; - if (buffer->mode & GMIME_STREAM_BUFFER_MODE == GMIME_STREAM_BUFFER_WRITE) { + if (buffer->mode == GMIME_STREAM_BUFFER_BLOCK_WRITE) { ssize_t written = 0; - if (buffer->mode & GMIME_STREAM_BUFFER_NEWLINE) { - if (!buffer->buflen > 0) { - written = g_mime_stream_write (buffer->source, buffer->buffer, buffer->buflen); - if (written > 0) - buffer->buflen -= written; - - if (buffer->buflen != 0) - return -1; - } - } else { - /* FIXME: what do I do here? */ + if (!buffer->buflen > 0) { + written = g_mime_stream_write (buffer->source, buffer->buffer, buffer->buflen); + if (written > 0) + buffer->buflen -= written; + + if (buffer->buflen != 0) + return -1; } } @@ -187,7 +179,7 @@ stream_close (GMimeStream *stream) g_free (buffer->buffer); buffer->buffer = NULL; - return return g_mime_stream_close (buffer->source); + return g_mime_stream_close (buffer->source); } static gboolean @@ -198,11 +190,15 @@ stream_eos (GMimeStream *stream) eos = g_mime_stream_eos (buffer->source); - if (eos && buffer->mode & GMIME_STREAM_BUFFER_MODE == GMIME_STREAM_BUFFER_READ) { - if (buffer->mode & GMIME_STREAM_BUFFER_NEWLINE) + if (eos) { + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_READ: return buffer->buflen == 0; - else + case GMIME_STREAM_BUFFER_CACHE_READ: return buffer->bufptr == buffer->bufend; + default: + break; + } } return eos; @@ -214,17 +210,23 @@ stream_reset (GMimeStream *stream) GMimeStreamBuffer *buffer = (GMimeStreamBuffer *) stream; int reset; - reset = g_mime_stream_reset (buffer->source); - if (reset == -1) - return -1; - - /* FIXME: make this work right */ - if (buffer->mode & GMIME_STREAM_BUFFER_MODE == GMIME_STREAM_BUFFER_READ) { - if (buffer->mode & GMIME_STREAM_BUFFER_NEWLINE) { - /* FIXME: implement this... */ - } else { - /* FIXME: implement this... */ - } + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_READ: + reset = g_mime_stream_reset (buffer->source); + if (reset == -1) + return -1; + + buffer->buflen = 0; + break; + case GMIME_STREAM_BUFFER_CACHE_READ: + buffer->bufptr = buffer->buffer; + break; + default: + reset = g_mime_stream_reset (buffer->source); + if (reset == -1) + return -1; + + break; } stream->position = stream->bound_start; @@ -264,10 +266,15 @@ stream_substream (GMimeStream *stream, off_t start, off_t end) buffer->source = GMIME_STREAM_BUFFER (stream)->source; g_mime_stream_ref (buffer->source); - if (GMIME_STREAM_BUFFER (stream)->mode & GMIME_STREAM_BUFFER_NEWLINE) { - buffer->buffer = g_malloc (NEWLINE_BUFFER_LEN); - buffer->buflen = NEWLINE_BUFFER_LEN; - } else { + buffer->mode = GMIME_STREAM_BUFFER (stream)->mode; + + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_READ: + case GMIME_STREAM_BUFFER_BLOCK_WRITE: + buffer->buffer = g_malloc (BLOCK_BUFFER_LEN); + buffer->buflen = BLOCK_BUFFER_LEN; + break; + default: buffer->buffer = g_malloc (BUFFER_GROW_SIZE); buffer->buflen = 0; } @@ -275,8 +282,6 @@ stream_substream (GMimeStream *stream, off_t start, off_t end) buffer->bufptr = buffer->buffer; buffer->bufend = buffer->buffer; - buffer->mode = GMIME_STREAM_BUFFER (stream)->mode; - g_mime_stream_construct (GMIME_STREAM (buffer), &template, GMIME_STREAM_BUFFER_TYPE, start, end); @@ -303,10 +308,15 @@ g_mime_stream_buffer_new (GMimeStream *source, GMimeStreamBufferMode mode) buffer->source = source; g_mime_stream_ref (source); - if (GMIME_STREAM_BUFFER (stream)->mode & GMIME_STREAM_BUFFER_NEWLINE) { - buffer->buffer = g_malloc (NEWLINE_BUFFER_LEN); - buffer->buflen = NEWLINE_BUFFER_LEN; - } else { + buffer->mode = mode; + + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_READ: + case GMIME_STREAM_BUFFER_BLOCK_WRITE: + buffer->buffer = g_malloc (BLOCK_BUFFER_LEN); + buffer->buflen = BLOCK_BUFFER_LEN; + break; + default: buffer->buffer = g_malloc (BUFFER_GROW_SIZE); buffer->buflen = 0; } @@ -314,8 +324,6 @@ g_mime_stream_buffer_new (GMimeStream *source, GMimeStreamBufferMode mode) buffer->bufptr = buffer->buffer; buffer->bufend = buffer->buffer; - buffer->mode = mode; - g_mime_stream_construct (GMIME_STREAM (buffer), &template, GMIME_STREAM_BUFFER_TYPE, source->bound_start, @@ -327,7 +335,7 @@ g_mime_stream_buffer_new (GMimeStream *source, GMimeStreamBufferMode mode) /** * g_mime_stream_buffer_gets: - * @stream: buffered stream + * @stream: stream * @buf: line buffer * @max: max length of a line * @@ -341,25 +349,81 @@ g_mime_stream_buffer_new (GMimeStream *source, GMimeStreamBufferMode mode) * on fail. **/ ssize_t -g_mime_stream_buffer_gets (GMimeStreamBuffer *stream, char *buf, size_t max) +g_mime_stream_buffer_gets (GMimeStream *stream, char *buf, size_t max) { - char *outptr, *outend, *inptr, *inend, c; + char *outptr, *outend, *inptr, *inend, c = '\0'; ssize_t nread; g_return_val_if_fail (stream != NULL, -1); - g_return_val_if_fail (GMIME_IS_STREAM_BUFFER (stream), -1); - - if (stream->mode & GMIME_STREAM_BUFFER_MODE == GMIME_STREAM_BUFFER_WRITE) { - g_warning ("You can't gets() on a stream that buffers writes."); - return -1; - } outptr = buf; outend = buf + max - 1; - if (stream->mode && GMIME_STREAM_BUFFER_NEWLINE) { + if (GMIME_IS_STREAM_BUFFER (stream)) { + GMimeStreamBuffer *buffer = GMIME_STREAM_BUFFER (stream); + again: + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_READ: + inptr = buffer->buffer; + inend = buffer->buffer + buffer->buflen; + while (outptr < outend && (c = *inptr) != '\n' && inptr < inend) + *outptr++ = *inptr++; + + memmove (buffer->buffer, inptr, inend - inptr); + buffer->buflen = inend - inptr; + + if (!buffer->buflen && outptr < outend && c != '\n') { + /* buffer more data */ + buffer->buflen = g_mime_stream_read (buffer->source, buffer->buffer, + BLOCK_BUFFER_LEN); + if (buffer->buflen < 0) { + buffer->buflen = 0; + break; + } + + goto again; + } + break; + case GMIME_STREAM_BUFFER_CACHE_READ: + inptr = buffer->bufptr; + inend = buffer->bufend; + while (outptr < outend && (c = *inptr) != '\n' && inptr < inend) + *outptr++ = *inptr++; + + buffer->bufptr = inptr; + + if (inptr == inend && outptr < outend && c != '\n') { + /* buffer more data */ + unsigned int offset = buffer->bufend - buffer->buffer; + + buffer->buflen += MAX (BUFFER_GROW_SIZE, outend - outptr + 1); + buffer->buffer = g_realloc (buffer->buffer, buffer->buflen); + buffer->bufptr = buffer->bufend = buffer->buffer + offset; + nread = g_mime_stream_read (buffer->source, buffer->bufptr, + MAX (BUFFER_GROW_SIZE, outend - outptr + 1)); + if (nread < 0) + break; + + buffer->bufend += nread; + + goto again; + } + break; + default: + goto slow_and_painful; + break; + } } else { - /* this is the easy one... */ + /* ugh...do it the slow and painful way... */ + slow_and_painful: + while (outptr < outend && c != '\n' && (nread = g_mime_stream_read (stream, &c, 1)) == 1) + *outptr++ = c; } + + if (c == '\n') + *outptr++ = c; + *outptr = '\0'; + + return (outptr - buf); } diff --git a/gmime-stream-buffer.h b/gmime-stream-buffer.h index c3d74397..e6de4cb4 100644 --- a/gmime-stream-buffer.h +++ b/gmime-stream-buffer.h @@ -32,13 +32,9 @@ extern "C" { #include "gmime-stream.h" typedef enum { - GMIME_STREAM_BUFFER_BUFFER = 0x00, - GMIME_STREAM_BUFFER_NEWLINE, - - GMIME_STREAM_BUFFER_READ = 0x00, - GMIME_STREAM_BUFFER_WRITE = 0xf0, - - GMIME_STREAM_BUFFER_MODE = 0xf0, + GMIME_STREAM_BUFFER_CACHE_READ, + GMIME_STREAM_BUFFER_BLOCK_READ, + GMIME_STREAM_BUFFER_BLOCK_WRITE, } GMimeStreamBufferMode; typedef struct _GMimeStreamBuffer { @@ -61,7 +57,7 @@ typedef struct _GMimeStreamBuffer { GMimeStream *g_mime_stream_buffer_new (GMimeStream *source, GMimeStreamBufferMode mode); -ssize_t g_mime_stream_buffer_gets (GMimeStreamBuffer *stream, char *buf, size_t max); +ssize_t g_mime_stream_buffer_gets (GMimeStream *stream, char *buf, size_t max); #ifdef __cplusplus } diff --git a/gmime/gmime-stream-buffer.c b/gmime/gmime-stream-buffer.c index 29d649f9..06f16b78 100644 --- a/gmime/gmime-stream-buffer.c +++ b/gmime/gmime-stream-buffer.c @@ -23,8 +23,8 @@ #include "gmime-stream-buffer.h" -#define NEWLINE_BUFFER_LEN 1024 -#define BUFFER_GROW_SIZE 1024 +#define BLOCK_BUFFER_LEN 1024 +#define BUFFER_GROW_SIZE 1024 static void stream_destroy (GMimeStream *stream); static ssize_t stream_read (GMimeStream *stream, char *buf, size_t len); @@ -69,49 +69,48 @@ stream_read (GMimeStream *stream, char *buf, size_t len) ssize_t nread = 0; ssize_t n; - if (buffer->mode & GMIME_STREAM_BUFFER_MODE == GMIME_STREAM_BUFFER_READ) { - if (buffer->mode & GMIME_STREAM_BUFFER_NEWLINE) { - newline_read: - n = MIN (buffer->buflen, len); - memcpy (buf + nread, buffer->buffer, n); - buffer->buflen -= n; - nread += n; - len -= n; - if (!buffer->buflen) { - /* buffer more data */ - buffer->buflen = g_mime_stream_read (buffer->source, buffer->buffer, - NEWLINE_BUFFER_LEN); - if (buffer->buflen > 0) - goto newline_read; + again: + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_READ: + n = MIN (buffer->buflen, len); + memcpy (buf + nread, buffer->buffer, n); + buffer->buflen -= n; + nread += n; + len -= n; + if (!buffer->buflen) { + /* buffer more data */ + buffer->buflen = g_mime_stream_read (buffer->source, buffer->buffer, + BLOCK_BUFFER_LEN); + if (buffer->buflen > 0) + goto again; + + buffer->buflen = 0; + } + break; + case GMIME_STREAM_BUFFER_CACHE_READ: + n = MIN (buffer->bufend - buffer->bufptr, len); + memcpy (buf + nread, buffer->bufptr, n); + nread += n; + len -= n; + if (len) { + /* we need to read more data... */ + if ((buffer->bufend - buffer->buffer) + len >= buffer->buflen) { + /* we need our buffer to grow... */ + unsigned int offset = buffer->bufend - buffer->buffer; - buffer->buflen = 0; + buffer->buflen += MAX (BUFFER_GROW_SIZE, len); + buffer->buffer = g_realloc (buffer->buffer, buffer->buflen); + buffer->bufptr = buffer->bufend = buffer->buffer + offset; } - } else { - buffered_read: - n = MIN (buffer->bufend - buffer->bufptr, len); - memcpy (buf + nread, buffer->bufptr, n); - nread += n; - len -= n; - if (len) { - /* we need to read more data... */ - if ((buffer->bufend - buffer->buffer) + len >= buffer->buflen) { - /* we need our buffer to grow... */ - unsigned int offset = buffer->bufend - buffer->buffer; - - buffer->buflen += MAX (BUFFER_GROW_SIZE, len); - buffer->buffer = g_realloc (buffer->buffer, buffer->buflen); - buffer->bufptr = buffer->bufend = buffer->buffer + offset; - } - - n = g_mime_stream_read (buffer->source, buffer->bufptr, - MAX (BUFFER_GROW_SIZE, len)); - if (n > 0) { - buffer->bufend += n; - goto buffered_read; - } + + n = g_mime_stream_read (buffer->source, buffer->bufptr, + MAX (BUFFER_GROW_SIZE, len)); + if (n > 0) { + buffer->bufend += n; + goto again; } } - } else { + default: nread = g_mime_stream_read (buffer->source, buf, len); } @@ -127,27 +126,24 @@ stream_write (GMimeStream *stream, char *buf, size_t len) GMimeStreamBuffer *buffer = (GMimeStreamBuffer *) stream; ssize_t written = 0, n; - if (buffer->mode & GMIME_STREAM_BUFFER_MODE == GMIME_STREAM_BUFFER_WRITE) { - if (buffer->mode & GMIME_STREAM_BUFFER_NEWLINE) { - newline_write: - n = MIN (NEWLINE_BUFFER_LEN - buffer->buflen, len); - memcpy (buffer->buffer + buffer->buflen, buf, n); - buffer->buflen += n; - written += n; - len -= n; - if (len) { - /* flush our buffer... */ - n = g_mime_stream_write (buffer->source, buffer->buffer, NEWLINE_BUFFER_LEN); - if (n > 0) { - memmove (buffer->buffer, buffer->buffer + n, NEWLINE_BUFFER_LEN - n); - goto newline_write; - } + again: + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_WRITE: + n = MIN (BLOCK_BUFFER_LEN - buffer->buflen, len); + memcpy (buffer->buffer + buffer->buflen, buf, n); + buffer->buflen += n; + written += n; + len -= n; + if (len) { + /* flush our buffer... */ + n = g_mime_stream_write (buffer->source, buffer->buffer, BLOCK_BUFFER_LEN); + if (n > 0) { + memmove (buffer->buffer, buffer->buffer + n, BLOCK_BUFFER_LEN - n); + goto again; } - } else { - /* FIXME: what do I do here? */ - written = g_mime_stream_write (buffer->source, buf, len); } - } else { + break; + default: written = g_mime_stream_write (buffer->source, buf, len); } @@ -159,20 +155,16 @@ stream_flush (GMimeStream *stream) { GMimeStreamBuffer *buffer = (GMimeStreamBuffer *) stream; - if (buffer->mode & GMIME_STREAM_BUFFER_MODE == GMIME_STREAM_BUFFER_WRITE) { + if (buffer->mode == GMIME_STREAM_BUFFER_BLOCK_WRITE) { ssize_t written = 0; - if (buffer->mode & GMIME_STREAM_BUFFER_NEWLINE) { - if (!buffer->buflen > 0) { - written = g_mime_stream_write (buffer->source, buffer->buffer, buffer->buflen); - if (written > 0) - buffer->buflen -= written; - - if (buffer->buflen != 0) - return -1; - } - } else { - /* FIXME: what do I do here? */ + if (!buffer->buflen > 0) { + written = g_mime_stream_write (buffer->source, buffer->buffer, buffer->buflen); + if (written > 0) + buffer->buflen -= written; + + if (buffer->buflen != 0) + return -1; } } @@ -187,7 +179,7 @@ stream_close (GMimeStream *stream) g_free (buffer->buffer); buffer->buffer = NULL; - return return g_mime_stream_close (buffer->source); + return g_mime_stream_close (buffer->source); } static gboolean @@ -198,11 +190,15 @@ stream_eos (GMimeStream *stream) eos = g_mime_stream_eos (buffer->source); - if (eos && buffer->mode & GMIME_STREAM_BUFFER_MODE == GMIME_STREAM_BUFFER_READ) { - if (buffer->mode & GMIME_STREAM_BUFFER_NEWLINE) + if (eos) { + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_READ: return buffer->buflen == 0; - else + case GMIME_STREAM_BUFFER_CACHE_READ: return buffer->bufptr == buffer->bufend; + default: + break; + } } return eos; @@ -214,17 +210,23 @@ stream_reset (GMimeStream *stream) GMimeStreamBuffer *buffer = (GMimeStreamBuffer *) stream; int reset; - reset = g_mime_stream_reset (buffer->source); - if (reset == -1) - return -1; - - /* FIXME: make this work right */ - if (buffer->mode & GMIME_STREAM_BUFFER_MODE == GMIME_STREAM_BUFFER_READ) { - if (buffer->mode & GMIME_STREAM_BUFFER_NEWLINE) { - /* FIXME: implement this... */ - } else { - /* FIXME: implement this... */ - } + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_READ: + reset = g_mime_stream_reset (buffer->source); + if (reset == -1) + return -1; + + buffer->buflen = 0; + break; + case GMIME_STREAM_BUFFER_CACHE_READ: + buffer->bufptr = buffer->buffer; + break; + default: + reset = g_mime_stream_reset (buffer->source); + if (reset == -1) + return -1; + + break; } stream->position = stream->bound_start; @@ -264,10 +266,15 @@ stream_substream (GMimeStream *stream, off_t start, off_t end) buffer->source = GMIME_STREAM_BUFFER (stream)->source; g_mime_stream_ref (buffer->source); - if (GMIME_STREAM_BUFFER (stream)->mode & GMIME_STREAM_BUFFER_NEWLINE) { - buffer->buffer = g_malloc (NEWLINE_BUFFER_LEN); - buffer->buflen = NEWLINE_BUFFER_LEN; - } else { + buffer->mode = GMIME_STREAM_BUFFER (stream)->mode; + + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_READ: + case GMIME_STREAM_BUFFER_BLOCK_WRITE: + buffer->buffer = g_malloc (BLOCK_BUFFER_LEN); + buffer->buflen = BLOCK_BUFFER_LEN; + break; + default: buffer->buffer = g_malloc (BUFFER_GROW_SIZE); buffer->buflen = 0; } @@ -275,8 +282,6 @@ stream_substream (GMimeStream *stream, off_t start, off_t end) buffer->bufptr = buffer->buffer; buffer->bufend = buffer->buffer; - buffer->mode = GMIME_STREAM_BUFFER (stream)->mode; - g_mime_stream_construct (GMIME_STREAM (buffer), &template, GMIME_STREAM_BUFFER_TYPE, start, end); @@ -303,10 +308,15 @@ g_mime_stream_buffer_new (GMimeStream *source, GMimeStreamBufferMode mode) buffer->source = source; g_mime_stream_ref (source); - if (GMIME_STREAM_BUFFER (stream)->mode & GMIME_STREAM_BUFFER_NEWLINE) { - buffer->buffer = g_malloc (NEWLINE_BUFFER_LEN); - buffer->buflen = NEWLINE_BUFFER_LEN; - } else { + buffer->mode = mode; + + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_READ: + case GMIME_STREAM_BUFFER_BLOCK_WRITE: + buffer->buffer = g_malloc (BLOCK_BUFFER_LEN); + buffer->buflen = BLOCK_BUFFER_LEN; + break; + default: buffer->buffer = g_malloc (BUFFER_GROW_SIZE); buffer->buflen = 0; } @@ -314,8 +324,6 @@ g_mime_stream_buffer_new (GMimeStream *source, GMimeStreamBufferMode mode) buffer->bufptr = buffer->buffer; buffer->bufend = buffer->buffer; - buffer->mode = mode; - g_mime_stream_construct (GMIME_STREAM (buffer), &template, GMIME_STREAM_BUFFER_TYPE, source->bound_start, @@ -327,7 +335,7 @@ g_mime_stream_buffer_new (GMimeStream *source, GMimeStreamBufferMode mode) /** * g_mime_stream_buffer_gets: - * @stream: buffered stream + * @stream: stream * @buf: line buffer * @max: max length of a line * @@ -341,25 +349,81 @@ g_mime_stream_buffer_new (GMimeStream *source, GMimeStreamBufferMode mode) * on fail. **/ ssize_t -g_mime_stream_buffer_gets (GMimeStreamBuffer *stream, char *buf, size_t max) +g_mime_stream_buffer_gets (GMimeStream *stream, char *buf, size_t max) { - char *outptr, *outend, *inptr, *inend, c; + char *outptr, *outend, *inptr, *inend, c = '\0'; ssize_t nread; g_return_val_if_fail (stream != NULL, -1); - g_return_val_if_fail (GMIME_IS_STREAM_BUFFER (stream), -1); - - if (stream->mode & GMIME_STREAM_BUFFER_MODE == GMIME_STREAM_BUFFER_WRITE) { - g_warning ("You can't gets() on a stream that buffers writes."); - return -1; - } outptr = buf; outend = buf + max - 1; - if (stream->mode && GMIME_STREAM_BUFFER_NEWLINE) { + if (GMIME_IS_STREAM_BUFFER (stream)) { + GMimeStreamBuffer *buffer = GMIME_STREAM_BUFFER (stream); + again: + switch (buffer->mode) { + case GMIME_STREAM_BUFFER_BLOCK_READ: + inptr = buffer->buffer; + inend = buffer->buffer + buffer->buflen; + while (outptr < outend && (c = *inptr) != '\n' && inptr < inend) + *outptr++ = *inptr++; + + memmove (buffer->buffer, inptr, inend - inptr); + buffer->buflen = inend - inptr; + + if (!buffer->buflen && outptr < outend && c != '\n') { + /* buffer more data */ + buffer->buflen = g_mime_stream_read (buffer->source, buffer->buffer, + BLOCK_BUFFER_LEN); + if (buffer->buflen < 0) { + buffer->buflen = 0; + break; + } + + goto again; + } + break; + case GMIME_STREAM_BUFFER_CACHE_READ: + inptr = buffer->bufptr; + inend = buffer->bufend; + while (outptr < outend && (c = *inptr) != '\n' && inptr < inend) + *outptr++ = *inptr++; + + buffer->bufptr = inptr; + + if (inptr == inend && outptr < outend && c != '\n') { + /* buffer more data */ + unsigned int offset = buffer->bufend - buffer->buffer; + + buffer->buflen += MAX (BUFFER_GROW_SIZE, outend - outptr + 1); + buffer->buffer = g_realloc (buffer->buffer, buffer->buflen); + buffer->bufptr = buffer->bufend = buffer->buffer + offset; + nread = g_mime_stream_read (buffer->source, buffer->bufptr, + MAX (BUFFER_GROW_SIZE, outend - outptr + 1)); + if (nread < 0) + break; + + buffer->bufend += nread; + + goto again; + } + break; + default: + goto slow_and_painful; + break; + } } else { - /* this is the easy one... */ + /* ugh...do it the slow and painful way... */ + slow_and_painful: + while (outptr < outend && c != '\n' && (nread = g_mime_stream_read (stream, &c, 1)) == 1) + *outptr++ = c; } + + if (c == '\n') + *outptr++ = c; + *outptr = '\0'; + + return (outptr - buf); } diff --git a/gmime/gmime-stream-buffer.h b/gmime/gmime-stream-buffer.h index c3d74397..e6de4cb4 100644 --- a/gmime/gmime-stream-buffer.h +++ b/gmime/gmime-stream-buffer.h @@ -32,13 +32,9 @@ extern "C" { #include "gmime-stream.h" typedef enum { - GMIME_STREAM_BUFFER_BUFFER = 0x00, - GMIME_STREAM_BUFFER_NEWLINE, - - GMIME_STREAM_BUFFER_READ = 0x00, - GMIME_STREAM_BUFFER_WRITE = 0xf0, - - GMIME_STREAM_BUFFER_MODE = 0xf0, + GMIME_STREAM_BUFFER_CACHE_READ, + GMIME_STREAM_BUFFER_BLOCK_READ, + GMIME_STREAM_BUFFER_BLOCK_WRITE, } GMimeStreamBufferMode; typedef struct _GMimeStreamBuffer { @@ -61,7 +57,7 @@ typedef struct _GMimeStreamBuffer { GMimeStream *g_mime_stream_buffer_new (GMimeStream *source, GMimeStreamBufferMode mode); -ssize_t g_mime_stream_buffer_gets (GMimeStreamBuffer *stream, char *buf, size_t max); +ssize_t g_mime_stream_buffer_gets (GMimeStream *stream, char *buf, size_t max); #ifdef __cplusplus } |