kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

buf.c (3709B)



      1 /*
      2  * Copyright (c) 2013-2022 Joris Vink <joris@coders.se>
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #include <sys/types.h>
     18 
     19 #include <string.h>
     20 #include <stdio.h>
     21 #include <stdarg.h>
     22 #include <stdlib.h>
     23 
     24 #include "kore.h"
     25 
     26 struct kore_buf *
     27 kore_buf_alloc(size_t initial)
     28 {
     29 	struct kore_buf		*buf;
     30 
     31 	buf = kore_malloc(sizeof(*buf));
     32 	kore_buf_init(buf, initial);
     33 	buf->flags = KORE_BUF_OWNER_API;
     34 
     35 	return (buf);
     36 }
     37 
     38 void
     39 kore_buf_init(struct kore_buf *buf, size_t initial)
     40 {
     41 	if (initial > 0)
     42 		buf->data = kore_malloc(initial);
     43 	else
     44 		buf->data = NULL;
     45 
     46 	buf->length = initial;
     47 	buf->offset = 0;
     48 	buf->flags = 0;
     49 }
     50 
     51 void
     52 kore_buf_cleanup(struct kore_buf *buf)
     53 {
     54 	kore_free(buf->data);
     55 	buf->data = NULL;
     56 	buf->offset = 0;
     57 	buf->length = 0;
     58 }
     59 
     60 void
     61 kore_buf_free(struct kore_buf *buf)
     62 {
     63 	kore_buf_cleanup(buf);
     64 	if (buf->flags & KORE_BUF_OWNER_API)
     65 		kore_free(buf);
     66 }
     67 
     68 void
     69 kore_buf_append(struct kore_buf *buf, const void *data, size_t len)
     70 {
     71 	if ((buf->offset + len) < len)
     72 		fatal("overflow in kore_buf_append");
     73 
     74 	if ((buf->offset + len) > buf->length) {
     75 		buf->length += len;
     76 		buf->data = kore_realloc(buf->data, buf->length);
     77 	}
     78 
     79 	memcpy((buf->data + buf->offset), data, len);
     80 	buf->offset += len;
     81 }
     82 
     83 void
     84 kore_buf_appendv(struct kore_buf *buf, const char *fmt, va_list args)
     85 {
     86 	int		l;
     87 	va_list		copy;
     88 	char		*b, sb[BUFSIZ];
     89 
     90 	va_copy(copy, args);
     91 
     92 	l = vsnprintf(sb, sizeof(sb), fmt, args);
     93 	if (l == -1)
     94 		fatal("kore_buf_appendv(): vsnprintf error");
     95 
     96 	if ((size_t)l >= sizeof(sb)) {
     97 		l = vasprintf(&b, fmt, copy);
     98 		if (l == -1)
     99 			fatal("kore_buf_appendv(): error or truncation");
    100 	} else {
    101 		b = sb;
    102 	}
    103 
    104 	kore_buf_append(buf, b, l);
    105 	if (b != sb)
    106 		free(b);
    107 
    108 	va_end(copy);
    109 }
    110 
    111 void
    112 kore_buf_appendf(struct kore_buf *buf, const char *fmt, ...)
    113 {
    114 	va_list		args;
    115 
    116 	va_start(args, fmt);
    117 	kore_buf_appendv(buf, fmt, args);
    118 	va_end(args);
    119 }
    120 
    121 char *
    122 kore_buf_stringify(struct kore_buf *buf, size_t *len)
    123 {
    124 	char		c;
    125 
    126 	if (len != NULL)
    127 		*len = buf->offset;
    128 
    129 	c = '\0';
    130 	kore_buf_append(buf, &c, sizeof(c));
    131 
    132 	return ((char *)buf->data);
    133 }
    134 
    135 u_int8_t *
    136 kore_buf_release(struct kore_buf *buf, size_t *len)
    137 {
    138 	u_int8_t	*p;
    139 
    140 	p = buf->data;
    141 	*len = buf->offset;
    142 
    143 	buf->data = NULL;
    144 	kore_buf_free(buf);
    145 
    146 	return (p);
    147 }
    148 
    149 void
    150 kore_buf_replace_string(struct kore_buf *b, const char *src,
    151     const void *dst, size_t len)
    152 {
    153 	char		*key, *end, *tmp, *p;
    154 	size_t		blen, off, off2, nlen, klen;
    155 
    156 	off = 0;
    157 	klen = strlen(src);
    158 	for (;;) {
    159 		blen = b->offset;
    160 		nlen = blen + len;
    161 		p = (char *)b->data;
    162 
    163 		key = kore_mem_find(p + off, b->offset - off, src, klen);
    164 		if (key == NULL)
    165 			break;
    166 
    167 		end = key + klen;
    168 		off = key - p;
    169 		off2 = ((char *)(b->data + b->offset) - end);
    170 
    171 		tmp = kore_malloc(nlen);
    172 		memcpy(tmp, p, off);
    173 		if (dst != NULL)
    174 			memcpy((tmp + off), dst, len);
    175 		memcpy((tmp + off + len), end, off2);
    176 
    177 		kore_free(b->data);
    178 		b->data = (u_int8_t *)tmp;
    179 		b->offset = off + len + off2;
    180 		b->length = nlen;
    181 
    182 		off = off + len;
    183 	}
    184 }
    185 
    186 void
    187 kore_buf_reset(struct kore_buf *buf)
    188 {
    189 	buf->offset = 0;
    190 }