/*		FILE WRITER			HTWrite.c
**		===========
**
*/
#include "../config.h"
#include "HTWriter.h"

#define BUFFER_SIZE 4096	/* Tradeoff */

#include "HTUtils.h"
#include "tcp.h"
#include <stdio.h>

#ifndef DISABLE_TRACE
char adbuf[1024];
extern int httpTrace;
extern int www2Trace;
#endif

/*		HTML Object
**		-----------
*/
struct _HTStream {
	WWW_CONST HTStreamClass *isa;
	int soc;
	char *write_pointer;
	char buffer[BUFFER_SIZE];
};


/*	Write the buffer out to the socket
**	----------------------------------
*/
PRIVATE void flush (HTStream *me)
{
    char *read_pointer 	= me->buffer;
    char *write_pointer = me->write_pointer;
    int status;

    while (read_pointer < write_pointer) {
	status = NETWRITE(me->soc, me->buffer, write_pointer - read_pointer);
#ifndef DISABLE_TRACE
	if (httpTrace) {
	    strncpy(adbuf, me->buffer, write_pointer - read_pointer);
	    adbuf[write_pointer - read_pointer] = '\0';
	    fprintf(stderr, "%s", adbuf);
	}
#endif
	if (status < 0) {
#ifndef DISABLE_TRACE
	    if (www2Trace)
		fprintf(stderr, "HTWrite: Error on socket output stream!\n");
#endif
	    return;
	}
	read_pointer += status;
    }
    me->write_pointer = me->buffer;
}


/*_________________________________________________________________________
**
**			A C T I O N 	R O U T I N E S
*/

/*	Character handling
**	------------------
*/
PRIVATE void HTWriter_put_character (HTStream *me, char c)
{
    if (me->write_pointer == &me->buffer[BUFFER_SIZE])
	flush(me);
    *me->write_pointer++ = c;
}


/*	String handling
**	---------------
**
**	Strings must be smaller than this buffer size.
*/
PRIVATE void HTWriter_put_string (HTStream *me, WWW_CONST char *s)
{
    int l = strlen(s);

    if (me->write_pointer + l > &me->buffer[BUFFER_SIZE])
	flush(me);
    strcpy(me->write_pointer, s);
    me->write_pointer += l;
}


/*	Buffer write.  Buffers can (and should!) be big.
**	------------
*/
PRIVATE void HTWriter_write (HTStream *me, WWW_CONST char *s, int l)
{
    WWW_CONST char *read_pointer = s;
    WWW_CONST char *write_pointer = s + l;
    int status;

    flush(me);		/* First get rid of our buffer */

    while (read_pointer < write_pointer) {
        status = NETWRITE(me->soc, read_pointer, write_pointer - read_pointer);
#ifndef DISABLE_TRACE
	if (httpTrace) {
	    strncpy(adbuf, me->buffer, write_pointer - read_pointer);
	    adbuf[write_pointer - read_pointer] = '\0';
	    fprintf(stderr, "%s", adbuf);
	}
#endif
	if (status < 0) {
#ifndef DISABLE_TRACE
	    if (www2Trace)
		fprintf(stderr, "HTWriter_write: Error on socket output!\n");
#endif
	    return;
	}
	read_pointer += status;
    }
}


/*	Free an HTML object
**	-------------------
**
**	Note that the SGML parsing context is freed, but the created object is
**	not, as it takes on an existence of its own unless explicitly freed.
*/
PRIVATE void HTWriter_free (HTStream *me)
{
    NETCLOSE(me->soc);
    free(me);
}

/*	End writing
*/
PRIVATE void HTWriter_end_document (HTStream *me)
{
    flush(me);
}

PRIVATE void HTWriter_handle_interrupt (HTStream *me)
{
}


/*	Structured Object Class
**	-----------------------
*/
/* As opposed to print, etc. */
PRIVATE WWW_CONST HTStreamClass HTWriter = {
	"SocketWriter",
	HTWriter_free,
	HTWriter_end_document,
	HTWriter_put_character, 	HTWriter_put_string,
	HTWriter_write,
        HTWriter_handle_interrupt
};


/*	Subclass-specific Methods
**	-------------------------
*/
PUBLIC HTStream *HTWriter_new (int soc)
{
    HTStream *me = (HTStream *)malloc(sizeof(*me));

    if (!me)
	outofmem(__FILE__, "HTWriter_new");
    me->isa = &HTWriter;
    me->soc = soc;
    me->write_pointer = me->buffer;
    return me;
}
