about summary refs log tree commit diff stats
path: root/WWW/Library/Implementation/HTChunk.c
blob: b9490fd6929545a317698589b3e32166c54dc50d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
void console_doesnt_show_online_presence_when_set_none(void** state);
void console_shows_online_presence_when_set_online(void** state);
void console_shows_online_presence_when_set_all(void** state);
void console_doesnt_show_dnd_presence_when_set_none(void** state);
void console_doesnt_show_dnd_presence_when_set_online(void** state);
void console_shows_dnd_presence_when_set_all(void** state);
void handle_message_error_when_no_recipient(void** state);
void handle_message_error_when_recipient_cancel(void** state);
void handle_message_error_when_recipient_cancel_disables_chat_session(void** state);
void handle_message_error_when_recipient_and_no_type(void** state);
void handle_presence_error_when_no_recipient(void** state);
void handle_presence_error_when_from_recipient(void** state);
void handle_offline_removes_chat_session(void** state);
void lost_connection_clears_chat_sessions(void** state);
9'>299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
/*
 * $LynxId: HTChunk.c,v 1.29 2023/04/10 22:58:51 tom Exp $
 *
 *		Chunk handling:	Flexible arrays
 *		===============================
 *
 */

#include <HTUtils.h>
#include <HTChunk.h>

#include <LYLeaks.h>

/*
 *	Initialize a chunk with a certain allocation unit
 */
void HTChunkInit(HTChunk *ch, int grow)
{
    ch->data = 0;
    ch->growby = grow;
    ch->size = 0;
    ch->allocated = 0;
}

/*	Create a chunk with a certain allocation unit
 *	--------------
 */
HTChunk *HTChunkCreate(int grow)
{
    HTChunk *ch = typecalloc(HTChunk);

    if (ch == NULL)
	outofmem(__FILE__, "creation of chunk");

    HTChunkInit(ch, grow);
    return ch;
}

HTChunk *HTChunkCreateMayFail(int grow, int failok)
{
    HTChunk *ch = typecalloc(HTChunk);

    if (ch == NULL) {
	if (!failok) {
	    outofmem(__FILE__, "creation of chunk");
	} else {
	    return ch;
	}
    }

    HTChunkInit(ch, grow);
    ch->failok = failok;
    return ch;
}

/*	Create a chunk with a certain allocation unit and ensured size
 *	--------------
 */
HTChunk *HTChunkCreate2(int grow, size_t needed)
{
    HTChunk *ch = typecalloc(HTChunk);

    if (ch == NULL)
	outofmem(__FILE__, "HTChunkCreate2");

    HTChunkInit(ch, grow);
    if (needed-- > 0) {
	/* Round up */
	ch->allocated = (int) (needed - (needed % (size_t) ch->growby)
			       + (unsigned) ch->growby);
	CTRACE((tfp, "HTChunkCreate2: requested %d, allocate %u\n",
		(int) needed, (unsigned) ch->allocated));
	ch->data = typecallocn(char, (unsigned) ch->allocated);

	if (!ch->data)
	    outofmem(__FILE__, "HTChunkCreate2 data");
    }
    return ch;
}

/*	Clear a chunk of all data
 *	--------------------------
 */
void HTChunkClear(HTChunk *ch)
{
    FREE(ch->data);
    ch->size = 0;
    ch->allocated = 0;
}

/*     Free a chunk (and it's chain, if any)
 *     -------------------------------------
 */
void HTChunkFree(HTChunk *ch)
{
    HTChunk *next;

    do {
	next = ch->next;
	FREE(ch->data);
	FREE(ch);
	ch = next;
    } while (ch != NULL);
}

/*	Realloc the chunk
 *	-----------------
 */
BOOL HTChunkRealloc(HTChunk *ch, int growby)
{
    char *data;

    ch->allocated = ch->allocated + growby;

    data = (ch->data
	    ? typeRealloc(char, ch->data, ch->allocated)
	    : typecallocn(char, ch->allocated));

    if (data) {
	ch->data = data;
    } else if (ch->failok) {
	HTChunkClear(ch);	/* allocation failed, clear all data - kw */
	return FALSE;		/* caller should check ch->allocated - kw */
    } else {
	outofmem(__FILE__, "HTChunkRealloc");
    }
    return TRUE;
}

/*	Append a character
 *	------------------
 */
void HTChunkPutc(HTChunk *ch, unsigned c)
{
    if (ch->size >= ch->allocated) {
	if (!HTChunkRealloc(ch, ch->growby))
	    return;
    }
    ch->data[ch->size++] = (char) c;
}

/* like above but no realloc: extend to another chunk if necessary */
HTChunk *HTChunkPutc2(HTChunk *ch, int c)
{
    if (ch->size >= ch->allocated) {
	HTChunk *chunk = HTChunkCreateMayFail(ch->growby, ch->failok);

	ch->next = chunk;
	ch = chunk;
	HTChunkPutc(ch, UCH(c));
    } else {
	ch->data[ch->size++] = (char) c;
    }
    return ch;
}

/*	Ensure a certain size
 *	---------------------
 */
void HTChunkEnsure(HTChunk *ch, int needed)
{
    if (needed <= ch->allocated)
	return;
    ch->allocated = needed - 1 - ((needed - 1) % ch->growby)
	+ ch->growby;		/* Round up */
    ch->data = (ch->data
		? typeRealloc(char, ch->data, ch->allocated)
		: typecallocn(char, ch->allocated));

    if (ch->data == NULL)
	outofmem(__FILE__, "HTChunkEnsure");
}

/*
 * Append a block of characters.
 */
void HTChunkPutb(HTChunk *ch, const char *b, int l)
{
    if (l <= 0)
	return;
    if (ch->size + l > ch->allocated) {
	int growby = l - (l % ch->growby) + ch->growby;		/* Round up */

	if (!HTChunkRealloc(ch, growby))
	    return;
    }
    MemCpy(ch->data + ch->size, b, l);
    ch->size += l;
}

/* like above but no realloc: extend to another chunk if necessary */
HTChunk *HTChunkPutb2(HTChunk *ch, const char *b, int l)
{
    if (l <= 0)
	return ch;
    if (ch->size + l > ch->allocated) {
	HTChunk *chunk;
	int m = ch->allocated - ch->size;

	if (m != 0 && b != 0) {
	    MemCpy(ch->data + ch->size, b, (unsigned) m);
	    ch->size += m;
	}

	chunk = HTChunkCreateMayFail(ch->growby, ch->failok);
	ch->next = chunk;
	ch = chunk;
	if (b != 0)
	    HTChunkPutb(ch, b + m, l - m);
    } else {
	MemCpy(ch->data + ch->size, b, (unsigned) l);
	ch->size += l;
    }
    return ch;
}

#define PUTC(code)  ch->data[ch->size++] = (char)(code)
#define PUTC2(code) ch->data[ch->size++] = (char)(0x80|(0x3f &(code)))

/*
 * Append a character encoded as UTF-8.
 */
void HTChunkPutUtf8Char(HTChunk *ch, UCode_t code)
{
    int utflen;

    if (TOASCII(code) < 128)
	utflen = 1;
    else if (code < 0x800L) {
	utflen = 2;
    } else if (code < 0x10000L) {
	utflen = 3;
    } else if (code < 0x200000L) {
	utflen = 4;
    } else if (code < 0x4000000L) {
	utflen = 5;
    } else if (code <= 0x7fffffffL) {
	utflen = 6;
    } else
	utflen = 0;

    if (ch->size + utflen > ch->allocated) {
	int growby = (ch->growby >= utflen) ? ch->growby : utflen;

	if (!HTChunkRealloc(ch, growby))
	    return;
    }

    switch (utflen) {
    case 0:
	return;
    case 1:
	ch->data[ch->size++] = (char) code;
	return;
    case 2:
	PUTC(0xc0 | (code >> 6));
	break;
    case 3:
	PUTC(0xe0 | (code >> 12));
	break;
    case 4:
	PUTC(0xf0 | (code >> 18));
	break;
    case 5:
	PUTC(0xf8 | (code >> 24));
	break;
    case 6:
	PUTC(0xfc | (code >> 30));
	break;
    }
    switch (utflen) {
    case 6:
	PUTC2(code >> 24);
	/* FALLTHRU */
    case 5:
	PUTC2(code >> 18);
	/* FALLTHRU */
    case 4:
	PUTC2(code >> 12);
	/* FALLTHRU */
    case 3:
	PUTC2(code >> 6);
	/* FALLTHRU */
    case 2:
	PUTC2(code);
	break;
    }
}

/*	Terminate a chunk
 *	-----------------
 */
void HTChunkTerminate(HTChunk *ch)
{
    HTChunkPutc(ch, (char) 0);
}

/*	Append a string
 *	---------------
 */
void HTChunkPuts(HTChunk *ch, const char *s)
{
    const char *p;

    if (s != NULL) {
	for (p = s; *p; p++) {
	    if (ch->size >= ch->allocated) {
		if (!HTChunkRealloc(ch, ch->growby))
		    break;
	    }
	    ch->data[ch->size++] = *p;
	}
    }
}

/* like above but no realloc: extend to another chunk if necessary */
HTChunk *HTChunkPuts2(HTChunk *ch, const char *s)
{
    const char *p;

    if (s != NULL) {
	for (p = s; *p; p++) {
	    if (ch->size >= ch->allocated) {
		HTChunk *chunk = HTChunkCreateMayFail(ch->growby, ch->failok);

		ch->next = chunk;
		ch = chunk;
		HTChunkPuts(ch, p);
		break;
	    }
	    ch->data[ch->size++] = *p;
	}
    }
    return ch;
}