123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- /* 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) {
- ch->allocated = needed - 1 - ((needed - 1) % ch->growby)
- + ch->growby; /* Round up */
- CTRACE((tfp, "HTChunkCreate2: requested %d, allocate %d\n",
- (int) needed, ch->allocated));
- ch->data = typecallocn(char, 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
- ? (char *) realloc(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, char c)
- {
- if (ch->size >= ch->allocated) {
- if (!HTChunkRealloc(ch, ch->growby))
- return;
- }
- ch->data[ch->size++] = c;
- }
- /* like above but no realloc: extend to another chunk if necessary */
- HTChunk *HTChunkPutc2(HTChunk *ch, char c)
- {
- if (ch->size >= ch->allocated) {
- HTChunk *chunk = HTChunkCreateMayFail(ch->growby, ch->failok);
- ch->next = chunk;
- HTChunkPutc(chunk, c);
- return chunk;
- }
- ch->data[ch->size++] = 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
- ? (char *) realloc(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;
- memcpy(ch->data + ch->size, b, m);
- ch->size += m;
- chunk = HTChunkCreateMayFail(ch->growby, ch->failok);
- ch->next = chunk;
- HTChunkPutb(chunk, b + m, l - m);
- return chunk;
- }
- memcpy(ch->data + ch->size, b, 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))
- return;
- }
- 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;
- HTChunkPuts(chunk, p);
- return chunk;
- }
- ch->data[ch->size++] = *p;
- }
- }
- return ch;
- }
|