From 65f8cfd443f46f7b98342fdd42da73eeb86f2448 Mon Sep 17 00:00:00 2001 From: "jwz%mozilla.org" Date: Sun, 9 Aug 1998 03:49:12 +0000 Subject: [PATCH] in order to make libmime compile without libmsg, moved some utility functions from libmsg/msgutil.c to new files libxp/xp_linebuf.c and libnet/mkbuf.c: msg_GrowBuffer ==> XP_GrowBuffer msg_LineBuffer ==> XP_LineBuffer msg_ReBuffer ==> XP_ReBuffer msg_MakeRebufferingStream ==> NET_MakeRebufferingStream --- lib/libmime/mimestub.c | 132 +-------------- lib/libmsg/msgutils.c | 373 ----------------------------------------- lib/xp/Makefile | 4 + lib/xp/xp_linebuf.c | 308 ++++++++++++++++++++++++++++++++++ lib/xp/xp_linebuf.h | 0 network/util/Makefile | 36 ---- network/util/mkbuf.c | 169 +++++++++++++++++++ network/util/mkbuf.h | 42 +++++ 8 files changed, 524 insertions(+), 540 deletions(-) create mode 100644 lib/xp/xp_linebuf.c create mode 100644 lib/xp/xp_linebuf.h create mode 100644 network/util/mkbuf.c create mode 100644 network/util/mkbuf.h diff --git a/lib/libmime/mimestub.c b/lib/libmime/mimestub.c index dd02487eb25..ff8d9c4dc4a 100644 --- a/lib/libmime/mimestub.c +++ b/lib/libmime/mimestub.c @@ -32,7 +32,7 @@ lib/xp/xp_str.o, and lib/libmsg/addr.o, because those files *actually stand on their own*! - Life kinda s#$%s, but oh well. + Life kinda sucks, but oh well. */ #include "xp.h" @@ -636,40 +636,6 @@ NET_Escape (const char * str, int mask) } -/* from libmsg/msgutils.c */ -int -msg_GrowBuffer (uint32 desired_size, uint32 element_size, uint32 quantum, - char **buffer, uint32 *size) -{ - if (*size <= desired_size) - { - char *new_buf; - uint32 increment = desired_size - *size; - if (increment < quantum) /* always grow by a minimum of N bytes */ - increment = quantum; - -#ifdef TESTFORWIN16 - if (((*size + increment) * (element_size / sizeof(char))) >= 64000) - { - /* Make sure we don't choke on WIN16 */ - XP_ASSERT(0); - return MK_OUT_OF_MEMORY; - } -#endif /* DEBUG */ - - new_buf = (*buffer - ? (char *) XP_REALLOC (*buffer, (*size + increment) - * (element_size / sizeof(char))) - : (char *) XP_ALLOC ((*size + increment) - * (element_size / sizeof(char)))); - if (! new_buf) - return MK_OUT_OF_MEMORY; - *buffer = new_buf; - *size += increment; - } - return 0; -} - XP_List * ExternalURLTypeList=0; @@ -1146,99 +1112,3 @@ msg_convert_and_send_buffer(char* buf, int length, XP_Bool convert_newlines_p, return (*per_line_fn)(buf, length, closure); } - - -/* from libmsg/msgutils.c */ -int -msg_LineBuffer (const char *net_buffer, int32 net_buffer_size, - char **bufferP, uint32 *buffer_sizeP, uint32 *buffer_fpP, - XP_Bool convert_newlines_p, - int32 (*per_line_fn) (char *line, uint32 line_length, - void *closure), - void *closure) -{ - int status = 0; - if (*buffer_fpP > 0 && *bufferP && (*bufferP)[*buffer_fpP - 1] == CR && - net_buffer_size > 0 && net_buffer[0] != LF) { - /* The last buffer ended with a CR. The new buffer does not start - with a LF. This old buffer should be shipped out and discarded. */ - XP_ASSERT(*buffer_sizeP > *buffer_fpP); - if (*buffer_sizeP <= *buffer_fpP) return -1; - status = msg_convert_and_send_buffer(*bufferP, *buffer_fpP, - convert_newlines_p, - per_line_fn, closure); - if (status < 0) return status; - *buffer_fpP = 0; - } - while (net_buffer_size > 0) - { - const char *net_buffer_end = net_buffer + net_buffer_size; - const char *newline = 0; - const char *s; - - - for (s = net_buffer; s < net_buffer_end; s++) - { - /* Move forward in the buffer until the first newline. - Stop when we see CRLF, CR, or LF, or the end of the buffer. - *But*, if we see a lone CR at the *very end* of the buffer, - treat this as if we had reached the end of the buffer without - seeing a line terminator. This is to catch the case of the - buffers splitting a CRLF pair, as in "FOO\r\nBAR\r" "\nBAZ\r\n". - */ - if (*s == CR || *s == LF) - { - newline = s; - if (newline[0] == CR) - { - if (s == net_buffer_end - 1) - { - /* CR at end - wait for the next character. */ - newline = 0; - break; - } - else if (newline[1] == LF) - /* CRLF seen; swallow both. */ - newline++; - } - newline++; - break; - } - } - - /* Ensure room in the net_buffer and append some or all of the current - chunk of data to it. */ - { - const char *end = (newline ? newline : net_buffer_end); - uint32 desired_size = (end - net_buffer) + (*buffer_fpP) + 1; - - if (desired_size >= (*buffer_sizeP)) - { - status = msg_GrowBuffer (desired_size, sizeof(char), 1024, - bufferP, buffer_sizeP); - if (status < 0) return status; - } - XP_MEMCPY ((*bufferP) + (*buffer_fpP), net_buffer, (end - net_buffer)); - (*buffer_fpP) += (end - net_buffer); - } - - /* Now *bufferP contains either a complete line, or as complete - a line as we have read so far. - - If we have a line, process it, and then remove it from `*bufferP'. - Then go around the loop again, until we drain the incoming data. - */ - if (!newline) - return 0; - - status = msg_convert_and_send_buffer(*bufferP, *buffer_fpP, - convert_newlines_p, - per_line_fn, closure); - if (status < 0) return status; - - net_buffer_size -= (newline - net_buffer); - net_buffer = newline; - (*buffer_fpP) = 0; - } - return 0; -} diff --git a/lib/libmsg/msgutils.c b/lib/libmsg/msgutils.c index d24b0e576fc..2abcf7a009f 100644 --- a/lib/libmsg/msgutils.c +++ b/lib/libmsg/msgutils.c @@ -79,379 +79,6 @@ msg_InterruptContext(MWContext* context, XP_Bool safetoo) } -/* Buffer management. - Why do I feel like I've written this a hundred times before? - */ -int -msg_GrowBuffer (uint32 desired_size, uint32 element_size, uint32 quantum, - char **buffer, uint32 *size) -{ - if (*size <= desired_size) - { - char *new_buf; - uint32 increment = desired_size - *size; - if (increment < quantum) /* always grow by a minimum of N bytes */ - increment = quantum; - -#ifdef TESTFORWIN16 - if (((*size + increment) * (element_size / sizeof(char))) >= 64000) - { - /* Be safe on WIN16 */ - XP_ASSERT(0); - return MK_OUT_OF_MEMORY; - } -#endif /* DEBUG */ - - new_buf = (*buffer - ? (char *) XP_REALLOC (*buffer, (*size + increment) - * (element_size / sizeof(char))) - : (char *) XP_ALLOC ((*size + increment) - * (element_size / sizeof(char)))); - if (! new_buf) - return MK_OUT_OF_MEMORY; - *buffer = new_buf; - *size += increment; - } - return 0; -} - - -extern XP_Bool NET_POP3TooEarlyForEnd(int32 len); - -/* Take the given buffer, tweak the newlines at the end if necessary, and - send it off to the given routine. We are guaranteed that the given - buffer has allocated space for at least one more character at the end. */ -static int -msg_convert_and_send_buffer(char* buf, uint32 length, XP_Bool convert_newlines_p, - int32 (*per_line_fn) (char *line, - uint32 line_length, - void *closure), - void *closure) -{ - /* Convert the line terminator to the native form. - */ - char* newline; - - XP_ASSERT(buf && length > 0); - if (!buf || length <= 0) return -1; - newline = buf + length; - - XP_ASSERT(newline[-1] == CR || newline[-1] == LF); - if (newline[-1] != CR && newline[-1] != LF) return -1; - - NET_POP3TooEarlyForEnd(length); /* update count of bytes parsed adding/removing CR or LF*/ - - if (!convert_newlines_p) - { - } -#if (LINEBREAK_LEN == 1) - else if ((newline - buf) >= 2 && - newline[-2] == CR && - newline[-1] == LF) - { - /* CRLF -> CR or LF */ - buf [length - 2] = LINEBREAK[0]; - length--; - } - else if (newline > buf + 1 && - newline[-1] != LINEBREAK[0]) - { - /* CR -> LF or LF -> CR */ - buf [length - 1] = LINEBREAK[0]; - } -#else - else if (((newline - buf) >= 2 && newline[-2] != CR) || - ((newline - buf) >= 1 && newline[-1] != LF)) - { - /* LF -> CRLF or CR -> CRLF */ - length++; - buf[length - 2] = LINEBREAK[0]; - buf[length - 1] = LINEBREAK[1]; - } -#endif - - return (*per_line_fn)(buf, length, closure); -} - - -/* SI::BUFFERED-STREAM-MIXIN - Why do I feel like I've written this a hundred times before? - */ - - -int -msg_LineBuffer (const char *net_buffer, int32 net_buffer_size, - char **bufferP, uint32 *buffer_sizeP, uint32 *buffer_fpP, - XP_Bool convert_newlines_p, - int32 (*per_line_fn) (char *line, uint32 line_length, - void *closure), - void *closure) -{ - int status = 0; - if (*buffer_fpP > 0 && *bufferP && (*bufferP)[*buffer_fpP - 1] == CR && - net_buffer_size > 0 && net_buffer[0] != LF) { - /* The last buffer ended with a CR. The new buffer does not start - with a LF. This old buffer should be shipped out and discarded. */ - XP_ASSERT(*buffer_sizeP > *buffer_fpP); - if (*buffer_sizeP <= *buffer_fpP) return -1; - status = msg_convert_and_send_buffer(*bufferP, *buffer_fpP, - convert_newlines_p, - per_line_fn, closure); - if (status < 0) return status; - *buffer_fpP = 0; - } - while (net_buffer_size > 0) - { - const char *net_buffer_end = net_buffer + net_buffer_size; - const char *newline = 0; - const char *s; - - - for (s = net_buffer; s < net_buffer_end; s++) - { - /* Move forward in the buffer until the first newline. - Stop when we see CRLF, CR, or LF, or the end of the buffer. - *But*, if we see a lone CR at the *very end* of the buffer, - treat this as if we had reached the end of the buffer without - seeing a line terminator. This is to catch the case of the - buffers splitting a CRLF pair, as in "FOO\r\nBAR\r" "\nBAZ\r\n". - */ - if (*s == CR || *s == LF) - { - newline = s; - if (newline[0] == CR) - { - if (s == net_buffer_end - 1) - { - /* CR at end - wait for the next character. */ - newline = 0; - break; - } - else if (newline[1] == LF) - /* CRLF seen; swallow both. */ - newline++; - } - newline++; - break; - } - } - - /* Ensure room in the net_buffer and append some or all of the current - chunk of data to it. */ - { - const char *end = (newline ? newline : net_buffer_end); - uint32 desired_size = (end - net_buffer) + (*buffer_fpP) + 1; - - if (desired_size >= (*buffer_sizeP)) - { - status = msg_GrowBuffer (desired_size, sizeof(char), 1024, - bufferP, buffer_sizeP); - if (status < 0) return status; - } - XP_MEMCPY ((*bufferP) + (*buffer_fpP), net_buffer, (end - net_buffer)); - (*buffer_fpP) += (end - net_buffer); - } - - /* Now *bufferP contains either a complete line, or as complete - a line as we have read so far. - - If we have a line, process it, and then remove it from `*bufferP'. - Then go around the loop again, until we drain the incoming data. - */ - if (!newline) - return 0; - - status = msg_convert_and_send_buffer(*bufferP, *buffer_fpP, - convert_newlines_p, - per_line_fn, closure); - if (status < 0) return status; - - net_buffer_size -= (newline - net_buffer); - net_buffer = newline; - (*buffer_fpP) = 0; - } - return 0; -} - - -/* The opposite of msg_LineBuffer(): takes small buffers and packs them - up into bigger buffers before passing them along. - - Pass in a desired_buffer_size 0 to tell it to flush (for example, in - in the very last call to this function.) - */ -int -msg_ReBuffer (const char *net_buffer, int32 net_buffer_size, - uint32 desired_buffer_size, - char **bufferP, uint32 *buffer_sizeP, uint32 *buffer_fpP, - int32 (*per_buffer_fn) (char *buffer, uint32 buffer_size, - void *closure), - void *closure) -{ - int status = 0; - - if (desired_buffer_size >= (*buffer_sizeP)) - { - status = msg_GrowBuffer (desired_buffer_size, sizeof(char), 1024, - bufferP, buffer_sizeP); - if (status < 0) return status; - } - - do - { - int32 size = *buffer_sizeP - *buffer_fpP; - if (size > net_buffer_size) - size = net_buffer_size; - if (size > 0) - { - XP_MEMCPY ((*bufferP) + (*buffer_fpP), net_buffer, size); - (*buffer_fpP) += size; - net_buffer += size; - net_buffer_size -= size; - } - - if (*buffer_fpP > 0 && - *buffer_fpP >= desired_buffer_size) - { - status = (*per_buffer_fn) ((*bufferP), (*buffer_fpP), closure); - *buffer_fpP = 0; - if (status < 0) return status; - } - } - while (net_buffer_size > 0); - - return 0; -} - - -struct msg_rebuffering_stream_data -{ - uint32 desired_size; - char *buffer; - uint32 buffer_size; - uint32 buffer_fp; - NET_StreamClass *next_stream; -}; - - -static int32 -msg_rebuffering_stream_write_next_chunk (char *buffer, uint32 buffer_size, - void *closure) -{ - struct msg_rebuffering_stream_data *sd = - (struct msg_rebuffering_stream_data *) closure; - XP_ASSERT (sd); - if (!sd) return -1; - if (!sd->next_stream) return -1; - return (*sd->next_stream->put_block) (sd->next_stream, - buffer, buffer_size); -} - -static int -msg_rebuffering_stream_write_chunk (NET_StreamClass *stream, - const char* net_buffer, - int32 net_buffer_size) -{ - struct msg_rebuffering_stream_data *sd = - (struct msg_rebuffering_stream_data *) stream->data_object; - XP_ASSERT (sd); - if (!sd) return -1; - return msg_ReBuffer (net_buffer, net_buffer_size, - sd->desired_size, - &sd->buffer, &sd->buffer_size, &sd->buffer_fp, - msg_rebuffering_stream_write_next_chunk, - sd); -} - - -extern XP_Bool ValidateDocData(MWContext *window_id); - -static void -msg_rebuffering_stream_abort (NET_StreamClass *stream, int status) -{ - struct msg_rebuffering_stream_data *sd = - (struct msg_rebuffering_stream_data *) stream->data_object; - if (!sd) return; - FREEIF (sd->buffer); - if (sd->next_stream) - { - if (ValidateDocData(sd->next_stream->window_id)) /* otherwise doc_data is gone ! */ - (*sd->next_stream->abort) (sd->next_stream, status); - XP_FREE (sd->next_stream); - } - XP_FREE (sd); -} - -static void -msg_rebuffering_stream_complete (NET_StreamClass *stream) -{ - struct msg_rebuffering_stream_data *sd = - (struct msg_rebuffering_stream_data *) stream->data_object; - if (!sd) return; - sd->desired_size = 0; - msg_rebuffering_stream_write_chunk (stream, "", 0); - FREEIF (sd->buffer); - if (sd->next_stream) - { - (*sd->next_stream->complete) (sd->next_stream); - XP_FREE (sd->next_stream); - } - XP_FREE (sd); -} - -static unsigned int -msg_rebuffering_stream_write_ready (NET_StreamClass *stream) -{ - struct msg_rebuffering_stream_data *sd = - (struct msg_rebuffering_stream_data *) stream->data_object; - if (sd && sd->next_stream) - return ((*sd->next_stream->is_write_ready) - (sd->next_stream)); - else - return (MAX_WRITE_READY); -} - -NET_StreamClass * -msg_MakeRebufferingStream (NET_StreamClass *next_stream, - URL_Struct *url, - MWContext *context) -{ - NET_StreamClass *stream; - struct msg_rebuffering_stream_data *sd; - - XP_ASSERT (next_stream); - - TRACEMSG(("Setting up rebuffering stream. Have URL: %s\n", url->address)); - - stream = XP_NEW (NET_StreamClass); - if (!stream) return 0; - - sd = XP_NEW (struct msg_rebuffering_stream_data); - if (! sd) - { - XP_FREE (stream); - return 0; - } - - XP_MEMSET (sd, 0, sizeof(*sd)); - XP_MEMSET (stream, 0, sizeof(*stream)); - - sd->next_stream = next_stream; - sd->desired_size = 10240; - - stream->name = "ReBuffering Stream"; - stream->complete = msg_rebuffering_stream_complete; - stream->abort = msg_rebuffering_stream_abort; - stream->put_block = msg_rebuffering_stream_write_chunk; - stream->is_write_ready = msg_rebuffering_stream_write_ready; - stream->data_object = sd; - stream->window_id = context; - - return stream; -} - - - XP_Bool MSG_RequiresComposeWindow (const char *url) { diff --git a/lib/xp/Makefile b/lib/xp/Makefile index c522275e69b..e77bcea92e9 100644 --- a/lib/xp/Makefile +++ b/lib/xp/Makefile @@ -41,6 +41,7 @@ CSRCS = \ xp_wrap.c \ xpassert.c \ xplocale.c \ + xp_linebuf.c \ $(NULL) else CSRCS = xp_stub.c @@ -53,6 +54,9 @@ CSRCS += \ allxpstr.c \ $(NULL) +EXPORTS=xp_linebuf.h + + REQUIRES = js nspr dbm security img util jtools layer java lay style pref rdf privacy ifeq ($(STAND_ALONE_JAVA),1) diff --git a/lib/xp/xp_linebuf.c b/lib/xp/xp_linebuf.c new file mode 100644 index 00000000000..0836506c13a --- /dev/null +++ b/lib/xp/xp_linebuf.c @@ -0,0 +1,308 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + + +/* xp_linebuf.c -- general line-buffering and de-buffering of text streams. + Used by libmime, llibmsg, and others. + + This stuff used to be in libmsg/msgutils.c, but it's really not + mail-specific. And I had to move it to get libmime to work in the + absence of libmsg, so in the meantime, I changed the prefix from MSG_ + to XP_. + */ + +#include "xp_mcom.h" +#include "xp_linebuf.h" + +extern int MK_OUT_OF_MEMORY; + + +/* Amazingly enough, these seem only to be defined in fe_proto.h, which is + totally the wrong thing to be including here. + */ +#define CR '\015' +#define LF '\012' +#define CRLF "\015\012" + +#ifdef XP_MAC +# define LINEBREAK "\012" +# define LINEBREAK_LEN 1 +#else +# if defined(XP_WIN) || defined(XP_OS2) +# define LINEBREAK "\015\012" +# define LINEBREAK_LEN 2 +# else +# ifdef XP_UNIX +# define LINEBREAK "\012" +# define LINEBREAK_LEN 1 +# endif /* XP_UNIX */ +# endif /* XP_WIN */ +#endif /* XP_MAC */ + + + +/* Buffer management. + Why do I feel like I've written this a hundred times before? + */ +int +XP_GrowBuffer (uint32 desired_size, uint32 element_size, uint32 quantum, + char **buffer, uint32 *size) +{ + if (*size <= desired_size) + { + char *new_buf; + uint32 increment = desired_size - *size; + if (increment < quantum) /* always grow by a minimum of N bytes */ + increment = quantum; + +#ifdef TESTFORWIN16 + if (((*size + increment) * (element_size / sizeof(char))) >= 64000) + { + /* Be safe on WIN16 */ + XP_ASSERT(0); + return MK_OUT_OF_MEMORY; + } +#endif /* DEBUG */ + + new_buf = (*buffer + ? (char *) XP_REALLOC (*buffer, (*size + increment) + * (element_size / sizeof(char))) + : (char *) XP_ALLOC ((*size + increment) + * (element_size / sizeof(char)))); + if (! new_buf) + return MK_OUT_OF_MEMORY; + *buffer = new_buf; + *size += increment; + } + return 0; +} + + +#if 0 /* #### what is this?? and what is it doing here?? */ +extern XP_Bool NET_POP3TooEarlyForEnd(int32 len); +#endif + +/* Take the given buffer, tweak the newlines at the end if necessary, and + send it off to the given routine. We are guaranteed that the given + buffer has allocated space for at least one more character at the end. */ +static int +xp_convert_and_send_buffer(char* buf, uint32 length, + XP_Bool convert_newlines_p, + int32 (*per_line_fn) (char *line, + uint32 line_length, + void *closure), + void *closure) +{ + /* Convert the line terminator to the native form. + */ + char* newline; + + XP_ASSERT(buf && length > 0); + if (!buf || length <= 0) return -1; + newline = buf + length; + + XP_ASSERT(newline[-1] == CR || newline[-1] == LF); + if (newline[-1] != CR && newline[-1] != LF) return -1; + + /* update count of bytes parsed adding/removing CR or LF */ +#if 0 /* #### what is this?? and what is it doing here?? */ + NET_POP3TooEarlyForEnd(length); +#endif + + if (!convert_newlines_p) + { + } +#if (LINEBREAK_LEN == 1) + else if ((newline - buf) >= 2 && + newline[-2] == CR && + newline[-1] == LF) + { + /* CRLF -> CR or LF */ + buf [length - 2] = LINEBREAK[0]; + length--; + } + else if (newline > buf + 1 && + newline[-1] != LINEBREAK[0]) + { + /* CR -> LF or LF -> CR */ + buf [length - 1] = LINEBREAK[0]; + } +#else + else if (((newline - buf) >= 2 && newline[-2] != CR) || + ((newline - buf) >= 1 && newline[-1] != LF)) + { + /* LF -> CRLF or CR -> CRLF */ + length++; + buf[length - 2] = LINEBREAK[0]; + buf[length - 1] = LINEBREAK[1]; + } +#endif + + return (*per_line_fn)(buf, length, closure); +} + + +/* SI::BUFFERED-STREAM-MIXIN + Why do I feel like I've written this a hundred times before? + */ +int +XP_LineBuffer (const char *net_buffer, int32 net_buffer_size, + char **bufferP, uint32 *buffer_sizeP, uint32 *buffer_fpP, + XP_Bool convert_newlines_p, + int32 (*per_line_fn) (char *line, uint32 line_length, + void *closure), + void *closure) +{ + int status = 0; + if (*buffer_fpP > 0 && *bufferP && (*bufferP)[*buffer_fpP - 1] == CR && + net_buffer_size > 0 && net_buffer[0] != LF) { + /* The last buffer ended with a CR. The new buffer does not start + with a LF. This old buffer should be shipped out and discarded. */ + XP_ASSERT(*buffer_sizeP > *buffer_fpP); + if (*buffer_sizeP <= *buffer_fpP) return -1; + status = xp_convert_and_send_buffer(*bufferP, *buffer_fpP, + convert_newlines_p, + per_line_fn, closure); + if (status < 0) return status; + *buffer_fpP = 0; + } + while (net_buffer_size > 0) + { + const char *net_buffer_end = net_buffer + net_buffer_size; + const char *newline = 0; + const char *s; + + + for (s = net_buffer; s < net_buffer_end; s++) + { + /* Move forward in the buffer until the first newline. + Stop when we see CRLF, CR, or LF, or the end of the buffer. + *But*, if we see a lone CR at the *very end* of the buffer, + treat this as if we had reached the end of the buffer without + seeing a line terminator. This is to catch the case of the + buffers splitting a CRLF pair, as in "FOO\r\nBAR\r" "\nBAZ\r\n". + */ + if (*s == CR || *s == LF) + { + newline = s; + if (newline[0] == CR) + { + if (s == net_buffer_end - 1) + { + /* CR at end - wait for the next character. */ + newline = 0; + break; + } + else if (newline[1] == LF) + /* CRLF seen; swallow both. */ + newline++; + } + newline++; + break; + } + } + + /* Ensure room in the net_buffer and append some or all of the current + chunk of data to it. */ + { + const char *end = (newline ? newline : net_buffer_end); + uint32 desired_size = (end - net_buffer) + (*buffer_fpP) + 1; + + if (desired_size >= (*buffer_sizeP)) + { + status = XP_GrowBuffer (desired_size, sizeof(char), 1024, + bufferP, buffer_sizeP); + if (status < 0) return status; + } + XP_MEMCPY ((*bufferP) + (*buffer_fpP), net_buffer, (end - net_buffer)); + (*buffer_fpP) += (end - net_buffer); + } + + /* Now *bufferP contains either a complete line, or as complete + a line as we have read so far. + + If we have a line, process it, and then remove it from `*bufferP'. + Then go around the loop again, until we drain the incoming data. + */ + if (!newline) + return 0; + + status = xp_convert_and_send_buffer(*bufferP, *buffer_fpP, + convert_newlines_p, + per_line_fn, closure); + if (status < 0) return status; + + net_buffer_size -= (newline - net_buffer); + net_buffer = newline; + (*buffer_fpP) = 0; + } + return 0; +} + + +/* The opposite of xp_LineBuffer(): takes small buffers and packs them + up into bigger buffers before passing them along. + + Pass in a desired_buffer_size 0 to tell it to flush (for example, in + in the very last call to this function.) + */ +int +XP_ReBuffer (const char *net_buffer, int32 net_buffer_size, + uint32 desired_buffer_size, + char **bufferP, uint32 *buffer_sizeP, uint32 *buffer_fpP, + int32 (*per_buffer_fn) (char *buffer, uint32 buffer_size, + void *closure), + void *closure) +{ + int status = 0; + + if (desired_buffer_size >= (*buffer_sizeP)) + { + status = XP_GrowBuffer (desired_buffer_size, sizeof(char), 1024, + bufferP, buffer_sizeP); + if (status < 0) return status; + } + + do + { + int32 size = *buffer_sizeP - *buffer_fpP; + if (size > net_buffer_size) + size = net_buffer_size; + if (size > 0) + { + XP_MEMCPY ((*bufferP) + (*buffer_fpP), net_buffer, size); + (*buffer_fpP) += size; + net_buffer += size; + net_buffer_size -= size; + } + + if (*buffer_fpP > 0 && + *buffer_fpP >= desired_buffer_size) + { + status = (*per_buffer_fn) ((*bufferP), (*buffer_fpP), closure); + *buffer_fpP = 0; + if (status < 0) return status; + } + } + while (net_buffer_size > 0); + + return 0; +} + + diff --git a/lib/xp/xp_linebuf.h b/lib/xp/xp_linebuf.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/network/util/Makefile b/network/util/Makefile index 9d9dbff9b5f..e69de29bb2d 100644 --- a/network/util/Makefile +++ b/network/util/Makefile @@ -1,36 +0,0 @@ -#!gmake -# -# The contents of this file are subject to the Netscape Public License -# Version 1.0 (the "NPL"); you may not use this file except in -# compliance with the NPL. You may obtain a copy of the NPL at -# http://www.mozilla.org/NPL/ -# -# Software distributed under the NPL is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL -# for the specific language governing rights and limitations under the -# NPL. -# -# The Initial Developer of this code under the NPL is Netscape -# Communications Corporation. Portions created by Netscape are -# Copyright (C) 1998 Netscape Communications Corporation. All Rights -# Reserved. - -DEPTH = ../.. - -MODULE = network -LIBRARY_NAME = netutil - -CSRCS = \ - mkreg.c \ - $(NULL) - -EXPORTS=mkreg.h - -include $(DEPTH)/config/config.mk - -REQUIRES = network - -include $(DEPTH)/config/rules.mk - - - diff --git a/network/util/mkbuf.c b/network/util/mkbuf.c new file mode 100644 index 00000000000..41ac5b58f2c --- /dev/null +++ b/network/util/mkbuf.c @@ -0,0 +1,169 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + + +/* mkbuf.c --- a netlib stream that buffers data before passing it along. + This is used by libmime and libmsg to undo the effects of line-buffering, + and to pass along larger chunks of data to various stream handlers (e.g., + layout.) + + This stuff used to be in libmsg/msgutils.c, but it's really not + mail-specific. And I had to move it to get libmime to work in the + absence of libmsg, so in the meantime, I changed the prefix from MSG_ + to NET_. + + This depends on XP_ReBuffer (xp_linebuf.c) to do its dirty work. + + Created: Jamie Zawinski , 8-Aug-98. +*/ + +#include "xp_mcom.h" +#include "net.h"; +#include "xp_linebuf.h" +#include "mkbuf.h" + +struct net_rebuffering_stream_data +{ + uint32 desired_size; + char *buffer; + uint32 buffer_size; + uint32 buffer_fp; + NET_StreamClass *next_stream; +}; + +#undef FREEIF +#define FREEIF(obj) do { if (obj) { XP_FREE (obj); obj = 0; }} while (0) + + +static int32 +net_rebuffering_stream_write_next_chunk (char *buffer, uint32 buffer_size, + void *closure) +{ + struct net_rebuffering_stream_data *sd = + (struct net_rebuffering_stream_data *) closure; + XP_ASSERT (sd); + if (!sd) return -1; + if (!sd->next_stream) return -1; + return (*sd->next_stream->put_block) (sd->next_stream, + buffer, buffer_size); +} + +static int +net_rebuffering_stream_write_chunk (NET_StreamClass *stream, + const char* net_buffer, + int32 net_buffer_size) +{ + struct net_rebuffering_stream_data *sd = + (struct net_rebuffering_stream_data *) stream->data_object; + XP_ASSERT (sd); + if (!sd) return -1; + return XP_ReBuffer (net_buffer, net_buffer_size, + sd->desired_size, + &sd->buffer, &sd->buffer_size, &sd->buffer_fp, + net_rebuffering_stream_write_next_chunk, + sd); +} + + +extern XP_Bool ValidateDocData(MWContext *window_id); + +static void +net_rebuffering_stream_abort (NET_StreamClass *stream, int status) +{ + struct net_rebuffering_stream_data *sd = + (struct net_rebuffering_stream_data *) stream->data_object; + if (!sd) return; + FREEIF (sd->buffer); + if (sd->next_stream) + { + if (ValidateDocData(sd->next_stream->window_id)) /* otherwise doc_data + is gone ! */ + (*sd->next_stream->abort) (sd->next_stream, status); + XP_FREE (sd->next_stream); + } + XP_FREE (sd); +} + +static void +net_rebuffering_stream_complete (NET_StreamClass *stream) +{ + struct net_rebuffering_stream_data *sd = + (struct net_rebuffering_stream_data *) stream->data_object; + if (!sd) return; + sd->desired_size = 0; + net_rebuffering_stream_write_chunk (stream, "", 0); + FREEIF (sd->buffer); + if (sd->next_stream) + { + (*sd->next_stream->complete) (sd->next_stream); + XP_FREE (sd->next_stream); + } + XP_FREE (sd); +} + +static unsigned int +net_rebuffering_stream_write_ready (NET_StreamClass *stream) +{ + struct net_rebuffering_stream_data *sd = + (struct net_rebuffering_stream_data *) stream->data_object; + if (sd && sd->next_stream) + return ((*sd->next_stream->is_write_ready) + (sd->next_stream)); + else + return (MAX_WRITE_READY); +} + +NET_StreamClass * +NET_MakeRebufferingStream (NET_StreamClass *next_stream, + URL_Struct *url, + MWContext *context) +{ + NET_StreamClass *stream; + struct net_rebuffering_stream_data *sd; + + XP_ASSERT (next_stream); + + TRACEMSG(("Setting up rebuffering stream. Have URL: %s\n", url->address)); + + stream = XP_NEW (NET_StreamClass); + if (!stream) return 0; + + sd = XP_NEW (struct net_rebuffering_stream_data); + if (! sd) + { + XP_FREE (stream); + return 0; + } + + XP_MEMSET (sd, 0, sizeof(*sd)); + XP_MEMSET (stream, 0, sizeof(*stream)); + + sd->next_stream = next_stream; + sd->desired_size = 10240; + + stream->name = "ReBuffering Stream"; + stream->complete = net_rebuffering_stream_complete; + stream->abort = net_rebuffering_stream_abort; + stream->put_block = net_rebuffering_stream_write_chunk; + stream->is_write_ready = net_rebuffering_stream_write_ready; + stream->data_object = sd; + stream->window_id = context; + + return stream; +} diff --git a/network/util/mkbuf.h b/network/util/mkbuf.h new file mode 100644 index 00000000000..0b883adbf44 --- /dev/null +++ b/network/util/mkbuf.h @@ -0,0 +1,42 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + + +/* mkbuf.h --- a netlib stream that buffers data before passing it along. + This is used by libmime and libmsg to undo the effects of line-buffering, + and to pass along larger chunks of data to various stream handlers (e.g., + layout.) + + Created: Jamie Zawinski , 8-Aug-98. +*/ + +#ifndef __MKBUF_H__ +#define __MKBUF_H__ + +#include "ntypes.h" + +XP_BEGIN_PROTOS + +extern NET_StreamClass *NET_MakeRebufferingStream (NET_StreamClass *next, + URL_Struct *url, + MWContext *context); + +XP_END_PROTOS + +#endif /* __MKBUF_H__ */