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
This commit is contained in:
jwz%mozilla.org 1998-08-09 03:49:12 +00:00
Родитель 8ec2164a59
Коммит 4e53d461b5
8 изменённых файлов: 582 добавлений и 506 удалений

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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)
{

Просмотреть файл

@ -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)

308
lib/xp/xp_linebuf.c Normal file
Просмотреть файл

@ -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;
}

55
lib/xp/xp_linebuf.h Normal file
Просмотреть файл

@ -0,0 +1,55 @@
/* -*- 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.h --- general line-buffering and de-buffering of text streams.
Created: Jamie Zawinski <jwz@mozilla.org>, 8-Aug-98.
*/
#ifndef __XP_LINEBUF_H__
#define __XP_LINEBUF_H__
#include "xp_core.h"
XP_BEGIN_PROTOS
extern int XP_GrowBuffer (uint32 desired_size, uint32 element_size,
uint32 quantum, char **buffer, uint32 *size);
extern 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);
extern 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);
XP_END_PROTOS
#endif /* __XP_LINEBUF_H__ */

Просмотреть файл

@ -22,13 +22,14 @@ LIBRARY_NAME = netutil
CSRCS = \
mkreg.c \
mkbuf.c \
$(NULL)
EXPORTS=mkreg.h
EXPORTS=mkreg.h mkbuf.h
include $(DEPTH)/config/config.mk
REQUIRES = network
REQUIRES = network xp
include $(DEPTH)/config/rules.mk

169
network/util/mkbuf.c Normal file
Просмотреть файл

@ -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 <jwz@mozilla.org>, 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;
}

42
network/util/mkbuf.h Normal file
Просмотреть файл

@ -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 <jwz@mozilla.org>, 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__ */