Tue, 23 Aug 2016 13:49:38 +0200
adds UCX + changes how the input file is read (uses an consecutive memory area now)
1.1 --- a/Makefile Tue Aug 23 12:06:46 2016 +0200 1.2 +++ b/Makefile Tue Aug 23 13:49:38 2016 +0200 1.3 @@ -36,10 +36,15 @@ 1.4 SRC += codegens.c 1.5 SRC += ccodegen.c 1.6 SRC += javacodegen.c 1.7 +SRC += ucx/allocator.c 1.8 +SRC += ucx/buffer.c 1.9 +SRC += ucx/list.c 1.10 +SRC += ucx/string.c 1.11 +SRC += ucx/utils.c 1.12 1.13 OBJ = $(SRC:%.c=build/%$(OBJ_EXT)) 1.14 1.15 -all: build build/$(BIN) 1.16 +all: build/ucx build/$(BIN) 1.17 1.18 build/$(BIN): $(OBJ) 1.19 $(LD) -o $@ $^ $(LDFLAGS) 1.20 @@ -47,8 +52,11 @@ 1.21 build/%$(OBJ_EXT): src/%.c 1.22 $(CC) -o $@ $(CFLAGS) -c $< 1.23 1.24 +build/ucx: build 1.25 + $(MKDIR) $@ 1.26 + 1.27 build: 1.28 - $(MKDIR) build 1.29 + $(MKDIR) $@ 1.30 1.31 test: build/$(BIN) 1.32 ./build/$(BIN) test/ctestfile.c -o build/ctest.html \
2.1 --- a/clang.mk Tue Aug 23 12:06:46 2016 +0200 2.2 +++ b/clang.mk Tue Aug 23 13:49:38 2016 +0200 2.3 @@ -27,7 +27,7 @@ 2.4 # 2.5 2.6 # system related 2.7 -MKDIR = mkdir 2.8 +MKDIR = mkdir -p 2.9 RM = rm 2.10 RMFLAGS = -fR 2.11
3.1 --- a/gcc.mk Tue Aug 23 12:06:46 2016 +0200 3.2 +++ b/gcc.mk Tue Aug 23 13:49:38 2016 +0200 3.3 @@ -27,7 +27,7 @@ 3.4 # 3.5 3.6 # system related 3.7 -MKDIR = mkdir 3.8 +MKDIR = mkdir -p 3.9 RM = rm 3.10 RMFLAGS = -fR 3.11
4.1 --- a/src/c2html.c Tue Aug 23 12:06:46 2016 +0200 4.2 +++ b/src/c2html.c Tue Aug 23 13:49:38 2016 +0200 4.3 @@ -28,77 +28,9 @@ 4.4 */ 4.5 #include "c2html.h" 4.6 4.7 -inputfile_t *inputfilebuffer(size_t capacity) { 4.8 - inputfile_t *inputfile = (inputfile_t*) malloc(sizeof(inputfile_t)); 4.9 - inputfile->lines = (char**) malloc(capacity * sizeof(char*)); 4.10 - inputfile->capacity = capacity; 4.11 - inputfile->count = 0; 4.12 - inputfile->maxlinewidth = 0; 4.13 - 4.14 - return inputfile; 4.15 -} 4.16 - 4.17 -void addline(inputfile_t *inputfile, char* line, size_t width) { 4.18 - char *l = (char*) malloc(width+1); 4.19 - memcpy(l, line, width); 4.20 - l[width] = 0; 4.21 - if (inputfile->count >= inputfile->capacity) { 4.22 - inputfile->capacity <<= 1; 4.23 - inputfile->lines = realloc(inputfile->lines, 4.24 - sizeof(char*)*inputfile->capacity); 4.25 - } 4.26 - inputfile->lines[inputfile->count] = l; 4.27 - inputfile->maxlinewidth = 4.28 - width > inputfile->maxlinewidth ? width : inputfile->maxlinewidth; 4.29 - inputfile->count++; 4.30 -} 4.31 - 4.32 -void freeinputfilebuffer(inputfile_t *inputfile) { 4.33 - for (int i = 0 ; i < inputfile->count ; i++) { 4.34 - free(inputfile->lines[i]); 4.35 - } 4.36 - free(inputfile->lines); 4.37 - free(inputfile); 4.38 -} 4.39 - 4.40 -inputfile_t *readinput(char *filename) { 4.41 - 4.42 - int fd = open(filename, O_RDONLY); 4.43 - if (fd == -1) return NULL; 4.44 - 4.45 - inputfile_t *inputfile = inputfilebuffer(512); 4.46 - 4.47 - char buf[INPUTBUF_SIZE]; 4.48 - ssize_t r; 4.49 - 4.50 - size_t maxlinewidth = 256; 4.51 - char *line = (char*) malloc(maxlinewidth); 4.52 - size_t col = 0; 4.53 - 4.54 - while ((r = read(fd, buf, INPUTBUF_SIZE)) > 0) { 4.55 - for (size_t i = 0 ; i < r ; i++) { 4.56 - if (col >= maxlinewidth-4) { 4.57 - maxlinewidth <<= 1; 4.58 - line = realloc(line, maxlinewidth); 4.59 - } 4.60 - 4.61 - if (buf[i] == '\n') { 4.62 - line[col++] = '\n'; 4.63 - line[col] = 0; 4.64 - addline(inputfile, line, col); 4.65 - col = 0; 4.66 - } else { 4.67 - line[col++] = buf[i]; 4.68 - } 4.69 - } 4.70 - } 4.71 - 4.72 - free(line); 4.73 - 4.74 - close(fd); 4.75 - 4.76 - return inputfile; 4.77 -} 4.78 +#include "ucx/buffer.h" 4.79 +#include "ucx/list.h" 4.80 +#include "ucx/utils.h" 4.81 4.82 void printhelp() { 4.83 printf("Formats source code using HTML.\n\nUsage:\n" 4.84 @@ -115,12 +47,6 @@ 4.85 "\n"); 4.86 } 4.87 4.88 -int lnint(size_t lnc) { 4.89 - int w = 1, p = 1; 4.90 - while ((p*=10) < lnc) w++; 4.91 - return w; 4.92 -} 4.93 - 4.94 int copyfile(char *filename, FILE *dest) { 4.95 if (!filename) { 4.96 return 0; 4.97 @@ -136,60 +62,71 @@ 4.98 fclose(src); 4.99 return 0; 4.100 } else { 4.101 - return -1; 4.102 + return 1; 4.103 } 4.104 } 4.105 4.106 #define WRITECONST(stream, out, cstr) out(cstr, 1, sizeof(cstr)-1, stream) 4.107 int formatfile( 4.108 highlighter_t *highlighter, 4.109 - inputfile_t *in, 4.110 - fmt_write_func out, 4.111 + UcxList *in, 4.112 + write_func out, 4.113 void *stream, 4.114 - _Bool showln) { 4.115 - // formats an input file and writes the result to out 4.116 + int showlineno) { 4.117 + size_t lines = ucx_list_size(in); 4.118 4.119 - char *line = malloc(in->maxlinewidth*64); 4.120 + UcxBuffer *line = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND); 4.121 if(!line) { 4.122 return 1; 4.123 } 4.124 WRITECONST(stream, out, "<pre>\n"); 4.125 4.126 - int lnw = lnint(in->count); 4.127 - for (int i = 0 ; i < in->count ; i++) { 4.128 + int lnw; 4.129 + { 4.130 + lnw = 1; 4.131 + int p = 1; 4.132 + while ((p*=10) < lines) lnw++; 4.133 + } 4.134 + 4.135 + size_t lineno = 0; 4.136 + UCX_FOREACH(sourceline, in) { 4.137 + lineno++; 4.138 + /* TODO: backwards compatibility: replace line->space in all occasions 4.139 + * and use UcxBuffer functions 4.140 + */ 4.141 if (highlighter) { 4.142 - highlighter->parser(in->lines[i], line, highlighter); 4.143 + highlighter->parser(sourceline->data, line->space, highlighter); 4.144 } else { 4.145 - char *c = in->lines[i]; 4.146 + char *c = sourceline->data; 4.147 size_t dp = 0; 4.148 while (*c) { 4.149 - dp = writeescapedchar(line, dp, *c); 4.150 + dp = writeescapedchar(line->space, dp, *c); 4.151 c++; 4.152 } 4.153 - line[dp] = '\0'; 4.154 + line->space[dp] = '\0'; 4.155 } 4.156 4.157 // write line number 4.158 - if (showln) { 4.159 + if (showlineno) { 4.160 WRITECONST(stream, out, "<span class=\"c2html-lineno\">"); 4.161 char lnbuf[128]; 4.162 int len; 4.163 // line number link 4.164 len = snprintf(lnbuf, 128, "<a name=\"l%d\" href=\"#l%d\">", 4.165 - i+1, i+1); 4.166 + lineno, lineno); 4.167 out(lnbuf, 1, len, stream); 4.168 // justified line number 4.169 - len = snprintf(lnbuf, 128, "%*d ", lnw, i+1); 4.170 + len = snprintf(lnbuf, 128, "%*d ", lnw, lineno); 4.171 out(lnbuf, 1, len, stream); 4.172 WRITECONST(stream, out, "</a></span> "); 4.173 } 4.174 4.175 // write formated (or plain) code line 4.176 - out(line, 1, strlen(line), stream); 4.177 + out(line->space, 1, strlen(line->space), stream); 4.178 } 4.179 4.180 WRITECONST(stream, out, "</pre>\n"); 4.181 - free(line); 4.182 + ucx_buffer_free(line); 4.183 return 0; 4.184 } 4.185 4.186 @@ -209,15 +146,20 @@ 4.187 highlighter->parser = jparseline; 4.188 } 4.189 4.190 +enum source_type { 4.191 + SOURCE_C, 4.192 + SOURCE_JAVA, 4.193 + SOURCE_PLAIN 4.194 +}; 4.195 + 4.196 int main(int argc, char** argv) { 4.197 int retcode = EXIT_SUCCESS; 4.198 4.199 - settings_t settings; 4.200 + Settings settings; 4.201 memset(&settings, 0, sizeof(settings)); 4.202 - settings.highlight = 1; 4.203 settings.showlinenumbers = 1; 4.204 4.205 - int lang = C2HTML_C; 4.206 + enum source_type sourcetype = SOURCE_C; 4.207 4.208 char optc; 4.209 while ((optc = getopt(argc, argv, "hljo:pH:F:vV")) != -1) { 4.210 @@ -234,10 +176,10 @@ 4.211 settings.headerfile = optarg; 4.212 break; 4.213 case 'j': 4.214 - lang = C2HTML_JAVA; 4.215 + sourcetype = SOURCE_JAVA; 4.216 break; 4.217 case 'p': 4.218 - settings.highlight = 0; 4.219 + sourcetype = SOURCE_PLAIN; 4.220 break; 4.221 case 'l': 4.222 settings.showlinenumbers = 0; 4.223 @@ -282,30 +224,53 @@ 4.224 4.225 highlighter_t highlighter; 4.226 highlighter_t *hptr = &highlighter; 4.227 - switch (lang) { 4.228 - case C2HTML_C: 4.229 + switch (sourcetype) { 4.230 + case SOURCE_C: 4.231 init_c_highlighter(&highlighter); 4.232 break; 4.233 - case C2HTML_JAVA: 4.234 + case SOURCE_JAVA: 4.235 init_java_highlighter(&highlighter); 4.236 break; 4.237 - default: 4.238 + case SOURCE_PLAIN: 4.239 hptr = NULL; 4.240 break; 4.241 - } 4.242 - if (!settings.highlight) { 4.243 - hptr = NULL; 4.244 + default: /* should be unreachable */ 4.245 + fprintf(stderr, "error in enum source_type\n"); 4.246 + retcode = EXIT_FAILURE; 4.247 + goto prog_end; 4.248 } 4.249 4.250 - inputfile_t *inputfile = readinput(settings.infilename); 4.251 + FILE *inputfile = fopen(settings.infilename, "r"); 4.252 if (inputfile) { 4.253 + UcxBuffer *filebuf = ucx_buffer_new(NULL, 4.254 + 2048, UCX_BUFFER_AUTOEXTEND); 4.255 + { 4.256 + const size_t tmpbufsize = 512; 4.257 + char *tmpbuf = malloc(tmpbufsize); 4.258 + ucx_stream_copy(inputfile, filebuf, (read_func) fread, 4.259 + (write_func) ucx_buffer_write, 4.260 + tmpbuf, tmpbufsize, (size_t)-1); 4.261 + free(tmpbuf); 4.262 + } 4.263 + fclose(inputfile); 4.264 + 4.265 + UcxList *inputlines = ucx_list_append(NULL, filebuf->space); 4.266 + for (size_t i = 1 ; i < filebuf->size ; i++) { 4.267 + if (filebuf->space[i] == '\r') { 4.268 + filebuf->space[i] = '\n'; i++; 4.269 + } 4.270 + if (filebuf->space[i] == '\n' && i+1 < filebuf->size) { 4.271 + ucx_list_append(inputlines, filebuf->space+i+1); 4.272 + } 4.273 + } 4.274 + 4.275 formatfile( 4.276 hptr, 4.277 - inputfile, 4.278 - (fmt_write_func)fwrite, 4.279 + inputlines, 4.280 + (write_func) fwrite, 4.281 fout, 4.282 settings.showlinenumbers); 4.283 - freeinputfilebuffer(inputfile); 4.284 + ucx_buffer_free(filebuf); 4.285 } else { 4.286 perror("Error opening input file"); 4.287 retcode = EXIT_FAILURE;
5.1 --- a/src/c2html.h Tue Aug 23 12:06:46 2016 +0200 5.2 +++ b/src/c2html.h Tue Aug 23 13:49:38 2016 +0200 5.3 @@ -46,31 +46,16 @@ 5.4 5.5 #define VERSION_MAJOR 2 5.6 #define VERSION_MINOR 0 5.7 -#define VERSION_DEVELOP 1 // set this to zero for release version 5.8 +#define VERSION_DEVELOP 1 /* set this to zero for release version */ 5.9 5.10 - 5.11 -#define INPUTBUF_SIZE 2048 5.12 - 5.13 -#define C2HTML_C 0 5.14 -#define C2HTML_JAVA 1 5.15 - 5.16 typedef struct { 5.17 char* outfilename; 5.18 char* headerfile; 5.19 char* footerfile; 5.20 char* infilename; 5.21 - int highlight; 5.22 int showlinenumbers; 5.23 -} settings_t; 5.24 +} Settings; 5.25 5.26 -typedef struct { 5.27 - size_t count; 5.28 - size_t capacity; 5.29 - size_t maxlinewidth; 5.30 - char** lines; 5.31 -} inputfile_t; 5.32 - 5.33 -typedef size_t(*fmt_write_func)(const void*, size_t, size_t, void*); 5.34 5.35 #ifdef __cplusplus 5.36 }
6.1 --- a/src/ccodegen.c Tue Aug 23 12:06:46 2016 +0200 6.2 +++ b/src/ccodegen.c Tue Aug 23 13:49:38 2016 +0200 6.3 @@ -53,7 +53,7 @@ 6.4 void cparseline(char *src, char *dest, highlighter_t *hltr) { 6.5 6.6 memset(hltr->word, 0, WORDBUF_SIZE); 6.7 - size_t wp = 0, ifp = 0, sp = 0, dp = 0; 6.8 + size_t wp = 0, ifp = 0, sp = (size_t)-1, dp = 0; 6.9 int isstring = 0, iscomment = 0, isinclude = 0, parseinclude = 0; 6.10 char quote = '\0'; 6.11 int isescaping = 0; 6.12 @@ -64,7 +64,11 @@ 6.13 memcpy_const(dest, dp, "<span class=\"c2html-comment\">"); 6.14 } 6.15 6.16 - for (char c = src[sp] ; c ; c=src[++sp]) { 6.17 + char c; 6.18 + do { 6.19 + c = src[++sp]; 6.20 + if (!c) break; 6.21 + 6.22 /* comments */ 6.23 if (!isstring && c == '/') { 6.24 if (hltr->iscommentml && sp > 0 && src[sp-1] == '*') { 6.25 @@ -185,6 +189,6 @@ 6.26 6.27 isescaping = !isescaping & (c == '\\'); 6.28 } 6.29 - } 6.30 + } while (c != '\n'); 6.31 dest[dp] = 0; 6.32 }
7.1 --- a/src/javacodegen.c Tue Aug 23 12:06:46 2016 +0200 7.2 +++ b/src/javacodegen.c Tue Aug 23 13:49:38 2016 +0200 7.3 @@ -54,7 +54,7 @@ 7.4 7.5 void jparseline(char *src, char *dest, highlighter_t *hltr) { 7.6 memset(hltr->word, 0, WORDBUF_SIZE); 7.7 - size_t wp = 0, sp = 0, dp = 0; 7.8 + size_t wp = 0, sp = (size_t)-1, dp = 0; 7.9 int isstring = 0, iscomment = 0, isimport = 0; 7.10 char quote = '\0'; 7.11 int isescaping = 0; 7.12 @@ -64,7 +64,11 @@ 7.13 memcpy_const(dest, dp, "<span class=\"c2html-comment\">"); 7.14 } 7.15 7.16 - for (char c = src[sp] ; c ; c=src[++sp]) { 7.17 + char c; 7.18 + do { 7.19 + c = src[++sp]; 7.20 + if (!c) break; 7.21 + 7.22 /* comments */ 7.23 if (!isstring && c == '/') { 7.24 if (hltr->iscommentml && sp > 0 && src[sp-1] == '*') { 7.25 @@ -155,6 +159,6 @@ 7.26 7.27 isescaping = !isescaping & (c == '\\'); 7.28 } 7.29 - } 7.30 + } while (c != '\n'); 7.31 dest[dp] = 0; 7.32 }
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/ucx/allocator.c Tue Aug 23 13:49:38 2016 +0200 8.3 @@ -0,0 +1,59 @@ 8.4 +/* 8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 8.6 + * 8.7 + * Copyright 2015 Olaf Wintermann. All rights reserved. 8.8 + * 8.9 + * Redistribution and use in source and binary forms, with or without 8.10 + * modification, are permitted provided that the following conditions are met: 8.11 + * 8.12 + * 1. Redistributions of source code must retain the above copyright 8.13 + * notice, this list of conditions and the following disclaimer. 8.14 + * 8.15 + * 2. Redistributions in binary form must reproduce the above copyright 8.16 + * notice, this list of conditions and the following disclaimer in the 8.17 + * documentation and/or other materials provided with the distribution. 8.18 + * 8.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 8.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 8.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 8.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 8.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 8.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 8.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 8.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 8.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 8.29 + * POSSIBILITY OF SUCH DAMAGE. 8.30 + */ 8.31 + 8.32 +#include <stdlib.h> 8.33 +#include "allocator.h" 8.34 + 8.35 +UcxAllocator default_allocator = { 8.36 + NULL, 8.37 + ucx_default_malloc, 8.38 + ucx_default_calloc, 8.39 + ucx_default_realloc, 8.40 + ucx_default_free 8.41 +}; 8.42 + 8.43 +UcxAllocator *ucx_default_allocator() { 8.44 + UcxAllocator *allocator = &default_allocator; 8.45 + return allocator; 8.46 +} 8.47 + 8.48 +void *ucx_default_malloc(void *ignore, size_t n) { 8.49 + return malloc(n); 8.50 +} 8.51 + 8.52 +void *ucx_default_calloc(void *ignore, size_t n, size_t size) { 8.53 + return calloc(n, size); 8.54 +} 8.55 + 8.56 +void *ucx_default_realloc(void *ignore, void *data, size_t n) { 8.57 + return realloc(data, n); 8.58 +} 8.59 + 8.60 +void ucx_default_free(void *ignore, void *data) { 8.61 + free(data); 8.62 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/ucx/allocator.h Tue Aug 23 13:49:38 2016 +0200 9.3 @@ -0,0 +1,206 @@ 9.4 +/* 9.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 9.6 + * 9.7 + * Copyright 2015 Olaf Wintermann. All rights reserved. 9.8 + * 9.9 + * Redistribution and use in source and binary forms, with or without 9.10 + * modification, are permitted provided that the following conditions are met: 9.11 + * 9.12 + * 1. Redistributions of source code must retain the above copyright 9.13 + * notice, this list of conditions and the following disclaimer. 9.14 + * 9.15 + * 2. Redistributions in binary form must reproduce the above copyright 9.16 + * notice, this list of conditions and the following disclaimer in the 9.17 + * documentation and/or other materials provided with the distribution. 9.18 + * 9.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 9.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 9.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 9.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 9.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 9.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 9.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 9.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 9.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 9.29 + * POSSIBILITY OF SUCH DAMAGE. 9.30 + */ 9.31 +/** 9.32 + * Allocator for custom memory management. 9.33 + * 9.34 + * An UCX allocator consists of a pointer to the memory area / pool and four 9.35 + * function pointers to memory management functions operating on this memory 9.36 + * area / pool. These functions shall behave equivalent to the standard libc 9.37 + * functions <code>malloc(), calloc(), realloc()</code> and <code>free()</code>. 9.38 + * 9.39 + * The signature of the memory management functions is based on the signature 9.40 + * of the respective libc function but each of them takes the pointer to the 9.41 + * memory area / pool as first argument. 9.42 + * 9.43 + * As the pointer to the memory area / pool can be arbitrarily chosen, any data 9.44 + * can be provided to the memory management functions. An UcxMempool is just 9.45 + * one example. 9.46 + * 9.47 + * @see mempool.h 9.48 + * @see UcxMap 9.49 + * 9.50 + * @file allocator.h 9.51 + * @author Mike Becker 9.52 + * @author Olaf Wintermann 9.53 + */ 9.54 + 9.55 +#ifndef UCX_ALLOCATOR_H 9.56 +#define UCX_ALLOCATOR_H 9.57 + 9.58 +#include "ucx.h" 9.59 + 9.60 +#ifdef __cplusplus 9.61 +extern "C" { 9.62 +#endif 9.63 + 9.64 +/** 9.65 + * A function pointer to the allocators <code>malloc()</code> function. 9.66 + * @see UcxAllocator 9.67 + */ 9.68 +typedef void*(*ucx_allocator_malloc)(void *pool, size_t n); 9.69 + 9.70 +/** 9.71 + * A function pointer to the allocators <code>calloc()</code> function. 9.72 + * @see UcxAllocator 9.73 + */ 9.74 +typedef void*(*ucx_allocator_calloc)(void *pool, size_t n, size_t size); 9.75 + 9.76 +/** 9.77 + * A function pointer to the allocators <code>realloc()</code> function. 9.78 + * @see UcxAllocator 9.79 + */ 9.80 +typedef void*(*ucx_allocator_realloc)(void *pool, void *data, size_t n); 9.81 + 9.82 +/** 9.83 + * A function pointer to the allocators <code>free()</code> function. 9.84 + * @see UcxAllocator 9.85 + */ 9.86 +typedef void(*ucx_allocator_free)(void *pool, void *data); 9.87 + 9.88 +/** 9.89 + * UCX allocator data structure containing memory management functions. 9.90 + */ 9.91 +typedef struct { 9.92 + /** Pointer to an area of memory or a complex memory pool. 9.93 + * This pointer will be passed to any memory management function as first 9.94 + * argument. 9.95 + */ 9.96 + void *pool; 9.97 + /** 9.98 + * The <code>malloc()</code> function for this allocator. 9.99 + */ 9.100 + ucx_allocator_malloc malloc; 9.101 + /** 9.102 + * The <code>calloc()</code> function for this allocator. 9.103 + */ 9.104 + ucx_allocator_calloc calloc; 9.105 + /** 9.106 + * The <code>realloc()</code> function for this allocator. 9.107 + */ 9.108 + ucx_allocator_realloc realloc; 9.109 + /** 9.110 + * The <code>free()</code> function for this allocator. 9.111 + */ 9.112 + ucx_allocator_free free; 9.113 +} UcxAllocator; 9.114 + 9.115 +/** 9.116 + * Returns a pointer to the default allocator. 9.117 + * 9.118 + * The default allocator contains wrappers to the standard libc memory 9.119 + * management functions. Use this function to get a pointer to a globally 9.120 + * available allocator. You may also define an own UcxAllocator by assigning 9.121 + * #UCX_ALLOCATOR_DEFAULT to a variable and pass the address of this variable 9.122 + * to any function that takes an UcxAllocator as argument. Note that using 9.123 + * this function is the recommended way of passing a default allocator, thus 9.124 + * it never runs out of scope. 9.125 + * 9.126 + * @return a pointer to the default allocator 9.127 + * 9.128 + * @see UCX_ALLOCATOR_DEFAULT 9.129 + */ 9.130 +UcxAllocator *ucx_default_allocator(); 9.131 + 9.132 +/** 9.133 + * A wrapper for the standard libc <code>malloc()</code> function. 9.134 + * @param ignore ignored (may be used by allocators for pooled memory) 9.135 + * @param n argument passed to <code>malloc()</code> 9.136 + * @return return value of <code>malloc()</code> 9.137 + */ 9.138 +void *ucx_default_malloc(void *ignore, size_t n); 9.139 +/** 9.140 + * A wrapper for the standard libc <code>calloc()</code> function. 9.141 + * @param ignore ignored (may be used by allocators for pooled memory) 9.142 + * @param n argument passed to <code>calloc()</code> 9.143 + * @param size argument passed to <code>calloc()</code> 9.144 + * @return return value of <code>calloc()</code> 9.145 + */ 9.146 +void *ucx_default_calloc(void *ignore, size_t n, size_t size); 9.147 +/** 9.148 + * A wrapper for the standard libc <code>realloc()</code> function. 9.149 + * @param ignore ignored (may be used by allocators for pooled memory) 9.150 + * @param data argumend passed to <code>realloc()</code> 9.151 + * @param n argument passed to <code>realloc()</code> 9.152 + * @return return value of <code>realloc()</code> 9.153 + */ 9.154 +void *ucx_default_realloc(void *ignore, void *data, size_t n); 9.155 +/** 9.156 + * A wrapper for the standard libc <code>free()</code> function. 9.157 + * @param ignore ignored (may be used by allocators for pooled memory) 9.158 + * @param data argument passed to <code>free()</code> 9.159 + */ 9.160 +void ucx_default_free(void *ignore, void *data); 9.161 + 9.162 +/** 9.163 + * Shorthand for calling an allocators malloc function. 9.164 + * @param allocator the allocator to use 9.165 + * @param n size of space to allocate 9.166 + * @return a pointer to the allocated memory area 9.167 + */ 9.168 +#define almalloc(allocator, n) ((allocator)->malloc((allocator)->pool, n)) 9.169 + 9.170 +/** 9.171 + * Shorthand for calling an allocators calloc function. 9.172 + * @param allocator the allocator to use 9.173 + * @param n the count of elements the space should be allocated for 9.174 + * @param size the size of each element 9.175 + * @return a pointer to the allocated memory area 9.176 + */ 9.177 +#define alcalloc(allocator, n, size) \ 9.178 + ((allocator)->calloc((allocator)->pool, n, size)) 9.179 + 9.180 +/** 9.181 + * Shorthand for calling an allocators realloc function. 9.182 + * @param allocator the allocator to use 9.183 + * @param ptr the pointer to the memory area that shall be reallocated 9.184 + * @param n the new size of the allocated memory area 9.185 + * @return a pointer to the reallocated memory area 9.186 + */ 9.187 +#define alrealloc(allocator, ptr, n) \ 9.188 + ((allocator)->realloc((allocator)->pool, ptr, n)) 9.189 + 9.190 +/** 9.191 + * Shorthand for calling an allocators free function. 9.192 + * @param allocator the allocator to use 9.193 + * @param ptr the pointer to the memory area that shall be freed 9.194 + */ 9.195 +#define alfree(allocator, ptr) ((allocator)->free((allocator)->pool, ptr)) 9.196 + 9.197 +/** 9.198 + * Convenient macro for a default allocator <code>struct</code> definition. 9.199 + */ 9.200 +#define UCX_ALLOCATOR_DEFAULT {NULL, \ 9.201 + ucx_default_malloc, ucx_default_calloc, ucx_default_realloc, \ 9.202 + ucx_default_free } 9.203 + 9.204 +#ifdef __cplusplus 9.205 +} 9.206 +#endif 9.207 + 9.208 +#endif /* UCX_ALLOCATOR_H */ 9.209 +
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/ucx/buffer.c Tue Aug 23 13:49:38 2016 +0200 10.3 @@ -0,0 +1,234 @@ 10.4 +/* 10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 10.6 + * 10.7 + * Copyright 2015 Olaf Wintermann. All rights reserved. 10.8 + * 10.9 + * Redistribution and use in source and binary forms, with or without 10.10 + * modification, are permitted provided that the following conditions are met: 10.11 + * 10.12 + * 1. Redistributions of source code must retain the above copyright 10.13 + * notice, this list of conditions and the following disclaimer. 10.14 + * 10.15 + * 2. Redistributions in binary form must reproduce the above copyright 10.16 + * notice, this list of conditions and the following disclaimer in the 10.17 + * documentation and/or other materials provided with the distribution. 10.18 + * 10.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 10.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 10.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 10.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 10.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 10.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 10.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 10.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 10.29 + * POSSIBILITY OF SUCH DAMAGE. 10.30 + */ 10.31 + 10.32 +#include "buffer.h" 10.33 +#include <stdarg.h> 10.34 +#include <stdlib.h> 10.35 +#include <string.h> 10.36 + 10.37 +UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) { 10.38 + UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer)); 10.39 + if (buffer) { 10.40 + buffer->flags = flags; 10.41 + if (!space) { 10.42 + buffer->space = (char*)malloc(capacity); 10.43 + if (!buffer->space) { 10.44 + free(buffer); 10.45 + return NULL; 10.46 + } 10.47 + memset(buffer->space, 0, capacity); 10.48 + buffer->flags |= UCX_BUFFER_AUTOFREE; 10.49 + } else { 10.50 + buffer->space = (char*)space; 10.51 + } 10.52 + buffer->capacity = capacity; 10.53 + buffer->size = 0; 10.54 + 10.55 + buffer->pos = 0; 10.56 + } 10.57 + 10.58 + return buffer; 10.59 +} 10.60 + 10.61 +void ucx_buffer_free(UcxBuffer *buffer) { 10.62 + if ((buffer->flags & UCX_BUFFER_AUTOFREE) == UCX_BUFFER_AUTOFREE) { 10.63 + free(buffer->space); 10.64 + } 10.65 + free(buffer); 10.66 +} 10.67 + 10.68 +UcxBuffer* ucx_buffer_extract( 10.69 + UcxBuffer *src, size_t start, size_t length, int flags) { 10.70 + 10.71 + if (src->size == 0 || length == 0 || start+length > src->capacity) { 10.72 + return NULL; 10.73 + } 10.74 + 10.75 + UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer)); 10.76 + if (dst) { 10.77 + dst->space = (char*)malloc(length); 10.78 + if (!dst->space) { 10.79 + free(dst); 10.80 + return NULL; 10.81 + } 10.82 + dst->capacity = length; 10.83 + dst->size = length; 10.84 + dst->flags = flags | UCX_BUFFER_AUTOFREE; 10.85 + dst->pos = 0; 10.86 + memcpy(dst->space, src->space+start, length); 10.87 + } 10.88 + return dst; 10.89 +} 10.90 + 10.91 +int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) { 10.92 + size_t npos; 10.93 + switch (whence) { 10.94 + case SEEK_CUR: 10.95 + npos = buffer->pos; 10.96 + break; 10.97 + case SEEK_END: 10.98 + npos = buffer->size; 10.99 + break; 10.100 + case SEEK_SET: 10.101 + npos = 0; 10.102 + break; 10.103 + default: 10.104 + return -1; 10.105 + } 10.106 + 10.107 + size_t opos = npos; 10.108 + npos += offset; 10.109 + 10.110 + if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) { 10.111 + return -1; 10.112 + } 10.113 + 10.114 + if (npos >= buffer->size) { 10.115 + return -1; 10.116 + } else { 10.117 + buffer->pos = npos; 10.118 + return 0; 10.119 + } 10.120 + 10.121 +} 10.122 + 10.123 +int ucx_buffer_eof(UcxBuffer *buffer) { 10.124 + return buffer->pos >= buffer->size; 10.125 +} 10.126 + 10.127 +int ucx_buffer_extend(UcxBuffer *buffer, size_t len) { 10.128 + size_t newcap = buffer->capacity; 10.129 + 10.130 + if (buffer->capacity + len < buffer->capacity) { 10.131 + return -1; 10.132 + } 10.133 + 10.134 + while (buffer->capacity + len > newcap) { 10.135 + newcap <<= 1; 10.136 + if (newcap < buffer->capacity) { 10.137 + return -1; 10.138 + } 10.139 + } 10.140 + 10.141 + char *newspace = (char*)realloc(buffer->space, newcap); 10.142 + if (newspace) { 10.143 + memset(newspace+buffer->size, 0, newcap-buffer->size); 10.144 + buffer->space = newspace; 10.145 + buffer->capacity = newcap; 10.146 + } else { 10.147 + return -1; 10.148 + } 10.149 + 10.150 + return 0; 10.151 +} 10.152 + 10.153 +size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, 10.154 + UcxBuffer *buffer) { 10.155 + size_t len = size * nitems; 10.156 + size_t required = buffer->pos + len; 10.157 + if (buffer->pos > required) { 10.158 + return 0; 10.159 + } 10.160 + 10.161 + if (required > buffer->capacity) { 10.162 + if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { 10.163 + if (ucx_buffer_extend(buffer, required - buffer->capacity)) { 10.164 + return 0; 10.165 + } 10.166 + } else { 10.167 + len = buffer->capacity - buffer->pos; 10.168 + if (size > 1) { 10.169 + len -= len%size; 10.170 + } 10.171 + } 10.172 + } 10.173 + 10.174 + if (len == 0) { 10.175 + return len; 10.176 + } 10.177 + 10.178 + memcpy(buffer->space + buffer->pos, ptr, len); 10.179 + buffer->pos += len; 10.180 + if(buffer->pos > buffer->size) { 10.181 + buffer->size = buffer->pos; 10.182 + } 10.183 + 10.184 + return len / size; 10.185 +} 10.186 + 10.187 +size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, 10.188 + UcxBuffer *buffer) { 10.189 + size_t len = size * nitems; 10.190 + if (buffer->pos + len > buffer->size) { 10.191 + len = buffer->size - buffer->pos; 10.192 + if (size > 1) len -= len%size; 10.193 + } 10.194 + 10.195 + if (len <= 0) { 10.196 + return len; 10.197 + } 10.198 + 10.199 + memcpy(ptr, buffer->space + buffer->pos, len); 10.200 + buffer->pos += len; 10.201 + 10.202 + return len / size; 10.203 +} 10.204 + 10.205 +int ucx_buffer_putc(UcxBuffer *buffer, int c) { 10.206 + if(buffer->pos >= buffer->capacity) { 10.207 + if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { 10.208 + if(ucx_buffer_extend(buffer, 1)) { 10.209 + return EOF; 10.210 + } 10.211 + } else { 10.212 + return EOF; 10.213 + } 10.214 + } 10.215 + 10.216 + c &= 0xFF; 10.217 + buffer->space[buffer->pos] = (char) c; 10.218 + buffer->pos++; 10.219 + if(buffer->pos > buffer->size) { 10.220 + buffer->size = buffer->pos; 10.221 + } 10.222 + return c; 10.223 +} 10.224 + 10.225 +int ucx_buffer_getc(UcxBuffer *buffer) { 10.226 + if (ucx_buffer_eof(buffer)) { 10.227 + return EOF; 10.228 + } else { 10.229 + int c = buffer->space[buffer->pos]; 10.230 + buffer->pos++; 10.231 + return c; 10.232 + } 10.233 +} 10.234 + 10.235 +size_t ucx_buffer_puts(UcxBuffer *buffer, char *str) { 10.236 + return ucx_buffer_write((const void*)str, 1, strlen(str), buffer); 10.237 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/ucx/buffer.h Tue Aug 23 13:49:38 2016 +0200 11.3 @@ -0,0 +1,270 @@ 11.4 +/* 11.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 11.6 + * 11.7 + * Copyright 2015 Olaf Wintermann. All rights reserved. 11.8 + * 11.9 + * Redistribution and use in source and binary forms, with or without 11.10 + * modification, are permitted provided that the following conditions are met: 11.11 + * 11.12 + * 1. Redistributions of source code must retain the above copyright 11.13 + * notice, this list of conditions and the following disclaimer. 11.14 + * 11.15 + * 2. Redistributions in binary form must reproduce the above copyright 11.16 + * notice, this list of conditions and the following disclaimer in the 11.17 + * documentation and/or other materials provided with the distribution. 11.18 + * 11.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 11.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 11.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 11.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 11.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 11.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 11.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 11.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 11.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 11.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11.29 + * POSSIBILITY OF SUCH DAMAGE. 11.30 + */ 11.31 + 11.32 +/** 11.33 + * @file buffer.h 11.34 + * 11.35 + * Advanced buffer implementation. 11.36 + * 11.37 + * Instances of UcxBuffer can be used to read from or to write to like one 11.38 + * would do with a stream. This allows the use of ucx_stream_copy() to copy 11.39 + * contents from one buffer to another. 11.40 + * 11.41 + * Some features for convenient use of the buffer 11.42 + * can be enabled. See the documentation of the macro constants for more 11.43 + * information. 11.44 + * 11.45 + * @author Mike Becker 11.46 + * @author Olaf Wintermann 11.47 + */ 11.48 + 11.49 +#ifndef UCX_BUFFER_H 11.50 +#define UCX_BUFFER_H 11.51 + 11.52 +#include "ucx.h" 11.53 +#include <sys/types.h> 11.54 +#include <stdio.h> 11.55 + 11.56 +#ifdef __cplusplus 11.57 +extern "C" { 11.58 +#endif 11.59 + 11.60 +/** 11.61 + * No buffer features enabled (all flags cleared). 11.62 + */ 11.63 +#define UCX_BUFFER_DEFAULT 0x00 11.64 + 11.65 +/** 11.66 + * If this flag is enabled, the buffer will automatically free its contents. 11.67 + */ 11.68 +#define UCX_BUFFER_AUTOFREE 0x01 11.69 + 11.70 +/** 11.71 + * If this flag is enabled, the buffer will automatically extends its capacity. 11.72 + */ 11.73 +#define UCX_BUFFER_AUTOEXTEND 0x02 11.74 + 11.75 +/** UCX Buffer. */ 11.76 +typedef struct { 11.77 + /** A pointer to the buffer contents. */ 11.78 + char *space; 11.79 + /** Current position of the buffer. */ 11.80 + size_t pos; 11.81 + /** Current capacity (i.e. maximum size) of the buffer. */ 11.82 + size_t capacity; 11.83 + /** Current size of the buffer content. */ 11.84 + size_t size; 11.85 + /** 11.86 + * Flag register for buffer features. 11.87 + * @see #UCX_BUFFER_DEFAULT 11.88 + * @see #UCX_BUFFER_AUTOFREE 11.89 + * @see #UCX_BUFFER_AUTOEXTEND 11.90 + */ 11.91 + int flags; 11.92 +} UcxBuffer; 11.93 + 11.94 +/** 11.95 + * Creates a new buffer. 11.96 + * 11.97 + * <b>Note:</b> you may provide <code>NULL</code> as argument for 11.98 + * <code>space</code>. Then this function will allocate the space and enforce 11.99 + * the #UCX_BUFFER_AUTOFREE flag. 11.100 + * 11.101 + * @param space pointer to the memory area, or <code>NULL</code> to allocate 11.102 + * new memory 11.103 + * @param capacity the capacity of the buffer 11.104 + * @param flags buffer features (see UcxBuffer.flags) 11.105 + * @return the new buffer 11.106 + */ 11.107 +UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags); 11.108 + 11.109 +/** 11.110 + * Destroys a buffer. 11.111 + * 11.112 + * If the #UCX_BUFFER_AUTOFREE feature is enabled, the contents of the buffer 11.113 + * are also freed. 11.114 + * 11.115 + * @param buffer the buffer to destroy 11.116 + */ 11.117 +void ucx_buffer_free(UcxBuffer* buffer); 11.118 + 11.119 +/** 11.120 + * Creates a new buffer and fills it with extracted content from another buffer. 11.121 + * 11.122 + * <b>Note:</b> the #UCX_BUFFER_AUTOFREE feature is enforced for the new buffer. 11.123 + * 11.124 + * @param src the source buffer 11.125 + * @param start the start position of extraction 11.126 + * @param length the count of bytes to extract (must not be zero) 11.127 + * @param flags feature mask for the new buffer 11.128 + * @return a new buffer containing the extraction 11.129 + */ 11.130 +UcxBuffer* ucx_buffer_extract(UcxBuffer *src, 11.131 + size_t start, size_t length, int flags); 11.132 + 11.133 +/** 11.134 + * A shorthand macro for the full extraction of the buffer. 11.135 + * 11.136 + * @param src the source buffer 11.137 + * @param flags feature mask for the new buffer 11.138 + * @return a new buffer with the extracted content 11.139 + */ 11.140 +#define ucx_buffer_clone(src,flags) \ 11.141 + ucx_buffer_extract(src, 0, (src)->capacity, flags) 11.142 + 11.143 +/** 11.144 + * Moves the position of the buffer. 11.145 + * 11.146 + * The new position is relative to the <code>whence</code> argument. 11.147 + * 11.148 + * SEEK_SET marks the start of the buffer. 11.149 + * SEEK_CUR marks the current position. 11.150 + * SEEK_END marks the end of the buffer. 11.151 + * 11.152 + * With an offset of zero, this function sets the buffer position to zero 11.153 + * (SEEK_SET), the buffer size (SEEK_END) or leaves the buffer position 11.154 + * unchanged (SEEK_CUR). 11.155 + * 11.156 + * @param buffer 11.157 + * @param offset position offset relative to <code>whence</code> 11.158 + * @param whence one of SEEK_SET, SEEK_CUR or SEEK_END 11.159 + * @return 0 on success, non-zero if the position is invalid 11.160 + * 11.161 + */ 11.162 +int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence); 11.163 + 11.164 +/** 11.165 + * Clears the buffer by resetting the position and deleting the data. 11.166 + * 11.167 + * The data is deleted by a zeroing it with call to <code>memset()</code>. 11.168 + * 11.169 + * @param buffer the buffer to be cleared 11.170 + */ 11.171 +#define ucx_buffer_clear(buffer) memset(buffer->space, 0, buffer->size); \ 11.172 + buffer->size = 0; buffer->pos = 0; 11.173 + 11.174 +/** 11.175 + * Tests, if the buffer position has exceeded the buffer capacity. 11.176 + * 11.177 + * @param buffer the buffer to test 11.178 + * @return non-zero, if the current buffer position has exceeded the last 11.179 + * available byte of the buffer. 11.180 + */ 11.181 +int ucx_buffer_eof(UcxBuffer *buffer); 11.182 + 11.183 + 11.184 +/** 11.185 + * Extends the capacity of the buffer. 11.186 + * 11.187 + * <b>Note:</b> The buffer capacity increased by a power of two. I.e. 11.188 + * the buffer capacity is doubled, as long as it would not hold the current 11.189 + * content plus the additional required bytes. 11.190 + * 11.191 + * <b>Attention:</b> the argument provided is the number of <i>additional</i> 11.192 + * bytes the buffer shall hold. It is <b>NOT</b> the total number of bytes the 11.193 + * buffer shall hold. 11.194 + * 11.195 + * @param buffer the buffer to extend 11.196 + * @param additional_bytes the number of additional bytes the buffer shall 11.197 + * <i>at least</i> hold 11.198 + * @return 0 on success or a non-zero value on failure 11.199 + */ 11.200 +int ucx_buffer_extend(UcxBuffer *buffer, size_t additional_bytes); 11.201 + 11.202 +/** 11.203 + * Writes data to an UcxBuffer. 11.204 + * 11.205 + * The position of the buffer is increased by the number of bytes written. 11.206 + * 11.207 + * @param ptr a pointer to the memory area containing the bytes to be written 11.208 + * @param size the length of one element 11.209 + * @param nitems the element count 11.210 + * @param buffer the UcxBuffer to write to 11.211 + * @return the total count of bytes written 11.212 + */ 11.213 +size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, 11.214 + UcxBuffer *buffer); 11.215 + 11.216 +/** 11.217 + * Reads data from an UcxBuffer. 11.218 + * 11.219 + * The position of the buffer is increased by the number of bytes read. 11.220 + * 11.221 + * @param ptr a pointer to the memory area where to store the read data 11.222 + * @param size the length of one element 11.223 + * @param nitems the element count 11.224 + * @param buffer the UcxBuffer to read from 11.225 + * @return the total number of elements read 11.226 + */ 11.227 +size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, 11.228 + UcxBuffer *buffer); 11.229 + 11.230 +/** 11.231 + * Writes a character to a buffer. 11.232 + * 11.233 + * The least significant byte of the argument is written to the buffer. If the 11.234 + * end of the buffer is reached and #UCX_BUFFER_AUTOEXTEND feature is enabled, 11.235 + * the buffer capacity is extended by ucx_buffer_extend(). If the feature is 11.236 + * disabled or buffer extension fails, <code>EOF</code> is returned. 11.237 + * 11.238 + * On successful write the position of the buffer is increased. 11.239 + * 11.240 + * @param buffer the buffer to write to 11.241 + * @param c the character to write as <code>int</code> value 11.242 + * @return the byte that has bean written as <code>int</code> value or 11.243 + * <code>EOF</code> when the end of the stream is reached and automatic 11.244 + * extension is not enabled or not possible 11.245 + */ 11.246 +int ucx_buffer_putc(UcxBuffer *buffer, int c); 11.247 + 11.248 +/** 11.249 + * Gets a character from a buffer. 11.250 + * 11.251 + * The current position of the buffer is increased after a successful read. 11.252 + * 11.253 + * @param buffer the buffer to read from 11.254 + * @return the character as <code>int</code> value or <code>EOF</code>, if the 11.255 + * end of the buffer is reached 11.256 + */ 11.257 +int ucx_buffer_getc(UcxBuffer *buffer); 11.258 + 11.259 +/** 11.260 + * Writes a string to a buffer. 11.261 + * 11.262 + * @param buffer the buffer 11.263 + * @param str the string 11.264 + * @return the number of bytes written 11.265 + */ 11.266 +size_t ucx_buffer_puts(UcxBuffer *buffer, char *str); 11.267 + 11.268 +#ifdef __cplusplus 11.269 +} 11.270 +#endif 11.271 + 11.272 +#endif /* UCX_BUFFER_H */ 11.273 +
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/src/ucx/list.c Tue Aug 23 13:49:38 2016 +0200 12.3 @@ -0,0 +1,335 @@ 12.4 +/* 12.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 12.6 + * 12.7 + * Copyright 2015 Olaf Wintermann. All rights reserved. 12.8 + * 12.9 + * Redistribution and use in source and binary forms, with or without 12.10 + * modification, are permitted provided that the following conditions are met: 12.11 + * 12.12 + * 1. Redistributions of source code must retain the above copyright 12.13 + * notice, this list of conditions and the following disclaimer. 12.14 + * 12.15 + * 2. Redistributions in binary form must reproduce the above copyright 12.16 + * notice, this list of conditions and the following disclaimer in the 12.17 + * documentation and/or other materials provided with the distribution. 12.18 + * 12.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 12.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 12.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 12.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 12.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 12.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 12.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 12.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 12.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 12.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 12.29 + * POSSIBILITY OF SUCH DAMAGE. 12.30 + */ 12.31 + 12.32 +#include "list.h" 12.33 + 12.34 +UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) { 12.35 + return ucx_list_clone_a(ucx_default_allocator(), l, fnc, data); 12.36 +} 12.37 + 12.38 +UcxList *ucx_list_clone_a(UcxAllocator *alloc, UcxList *l, 12.39 + copy_func fnc, void *data) { 12.40 + UcxList *ret = NULL; 12.41 + while (l) { 12.42 + if (fnc) { 12.43 + ret = ucx_list_append_a(alloc, ret, fnc(l->data, data)); 12.44 + } else { 12.45 + ret = ucx_list_append_a(alloc, ret, l->data); 12.46 + } 12.47 + l = l->next; 12.48 + } 12.49 + return ret; 12.50 +} 12.51 + 12.52 +int ucx_list_equals(const UcxList *l1, const UcxList *l2, 12.53 + cmp_func fnc, void* data) { 12.54 + if (l1 == l2) return 1; 12.55 + 12.56 + while (l1 != NULL && l2 != NULL) { 12.57 + if (fnc == NULL) { 12.58 + if (l1->data != l2->data) return 0; 12.59 + } else { 12.60 + if (fnc(l1->data, l2->data, data) != 0) return 0; 12.61 + } 12.62 + l1 = l1->next; 12.63 + l2 = l2->next; 12.64 + } 12.65 + 12.66 + return (l1 == NULL && l2 == NULL); 12.67 +} 12.68 + 12.69 +void ucx_list_free(UcxList *l) { 12.70 + ucx_list_free_a(ucx_default_allocator(), l); 12.71 +} 12.72 + 12.73 +void ucx_list_free_a(UcxAllocator *alloc, UcxList *l) { 12.74 + UcxList *e = l, *f; 12.75 + while (e != NULL) { 12.76 + f = e; 12.77 + e = e->next; 12.78 + alfree(alloc, f); 12.79 + } 12.80 +} 12.81 + 12.82 +void ucx_list_free_content(UcxList* list, ucx_destructor destr) { 12.83 + while (list != NULL) { 12.84 + destr(list->data); 12.85 + list = list->next; 12.86 + } 12.87 +} 12.88 + 12.89 +UcxList *ucx_list_append(UcxList *l, void *data) { 12.90 + return ucx_list_append_a(ucx_default_allocator(), l, data); 12.91 +} 12.92 + 12.93 +UcxList *ucx_list_append_a(UcxAllocator *alloc, UcxList *l, void *data) { 12.94 + UcxList *nl = (UcxList*) almalloc(alloc, sizeof(UcxList)); 12.95 + if (!nl) { 12.96 + return NULL; 12.97 + } 12.98 + 12.99 + nl->data = data; 12.100 + nl->next = NULL; 12.101 + if (l) { 12.102 + UcxList *t = ucx_list_last(l); 12.103 + t->next = nl; 12.104 + nl->prev = t; 12.105 + return l; 12.106 + } else { 12.107 + nl->prev = NULL; 12.108 + return nl; 12.109 + } 12.110 +} 12.111 + 12.112 +UcxList *ucx_list_prepend(UcxList *l, void *data) { 12.113 + return ucx_list_prepend_a(ucx_default_allocator(), l, data); 12.114 +} 12.115 + 12.116 +UcxList *ucx_list_prepend_a(UcxAllocator *alloc, UcxList *l, void *data) { 12.117 + UcxList *nl = ucx_list_append_a(alloc, NULL, data); 12.118 + if (!nl) { 12.119 + return NULL; 12.120 + } 12.121 + l = ucx_list_first(l); 12.122 + 12.123 + if (l) { 12.124 + nl->next = l; 12.125 + l->prev = nl; 12.126 + } 12.127 + return nl; 12.128 +} 12.129 + 12.130 +UcxList *ucx_list_concat(UcxList *l1, UcxList *l2) { 12.131 + if (l1) { 12.132 + UcxList *last = ucx_list_last(l1); 12.133 + last->next = l2; 12.134 + if (l2) { 12.135 + l2->prev = last; 12.136 + } 12.137 + return l1; 12.138 + } else { 12.139 + return l2; 12.140 + } 12.141 +} 12.142 + 12.143 +UcxList *ucx_list_last(const UcxList *l) { 12.144 + if (l == NULL) return NULL; 12.145 + 12.146 + const UcxList *e = l; 12.147 + while (e->next != NULL) { 12.148 + e = e->next; 12.149 + } 12.150 + return (UcxList*)e; 12.151 +} 12.152 + 12.153 +ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem) { 12.154 + ssize_t index = 0; 12.155 + while (list) { 12.156 + if (list == elem) { 12.157 + return index; 12.158 + } 12.159 + list = list->next; 12.160 + index++; 12.161 + } 12.162 + return -1; 12.163 +} 12.164 + 12.165 +UcxList *ucx_list_get(const UcxList *l, size_t index) { 12.166 + if (l == NULL) return NULL; 12.167 + 12.168 + const UcxList *e = l; 12.169 + while (e->next && index > 0) { 12.170 + e = e->next; 12.171 + index--; 12.172 + } 12.173 + 12.174 + return (UcxList*)(index == 0 ? e : NULL); 12.175 +} 12.176 + 12.177 +ssize_t ucx_list_find(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) { 12.178 + ssize_t index = 0; 12.179 + UCX_FOREACH(e, l) { 12.180 + if (fnc) { 12.181 + if (fnc(elem, e->data, cmpdata) == 0) { 12.182 + return index; 12.183 + } 12.184 + } else { 12.185 + if (elem == e->data) { 12.186 + return index; 12.187 + } 12.188 + } 12.189 + index++; 12.190 + } 12.191 + return -1; 12.192 +} 12.193 + 12.194 +int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) { 12.195 + return ucx_list_find(l, elem, fnc, cmpdata) > -1; 12.196 +} 12.197 + 12.198 +size_t ucx_list_size(const UcxList *l) { 12.199 + if (l == NULL) return 0; 12.200 + 12.201 + const UcxList *e = l; 12.202 + size_t s = 1; 12.203 + while (e->next != NULL) { 12.204 + e = e->next; 12.205 + s++; 12.206 + } 12.207 + 12.208 + return s; 12.209 +} 12.210 + 12.211 +static UcxList *ucx_list_sort_merge(int length, 12.212 + UcxList* restrict ls, UcxList* restrict le, UcxList* restrict re, 12.213 + cmp_func fnc, void* data) { 12.214 + 12.215 + UcxList** sorted = (UcxList**) malloc(sizeof(UcxList*)*length); 12.216 + UcxList *rc, *lc; 12.217 + 12.218 + lc = ls; rc = le; 12.219 + int n = 0; 12.220 + while (lc && lc != le && rc != re) { 12.221 + if (fnc(lc->data, rc->data, data) <= 0) { 12.222 + sorted[n] = lc; 12.223 + lc = lc->next; 12.224 + } else { 12.225 + sorted[n] = rc; 12.226 + rc = rc->next; 12.227 + } 12.228 + n++; 12.229 + } 12.230 + while (lc && lc != le) { 12.231 + sorted[n] = lc; 12.232 + lc = lc->next; 12.233 + n++; 12.234 + } 12.235 + while (rc && rc != re) { 12.236 + sorted[n] = rc; 12.237 + rc = rc->next; 12.238 + n++; 12.239 + } 12.240 + 12.241 + // Update pointer 12.242 + sorted[0]->prev = NULL; 12.243 + for (int i = 0 ; i < length-1 ; i++) { 12.244 + sorted[i]->next = sorted[i+1]; 12.245 + sorted[i+1]->prev = sorted[i]; 12.246 + } 12.247 + sorted[length-1]->next = NULL; 12.248 + 12.249 + UcxList *ret = sorted[0]; 12.250 + free(sorted); 12.251 + return ret; 12.252 +} 12.253 + 12.254 +UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) { 12.255 + if (l == NULL) { 12.256 + return NULL; 12.257 + } 12.258 + 12.259 + UcxList *lc; 12.260 + int ln = 1; 12.261 + 12.262 + UcxList *restrict ls = l, *restrict le, *restrict re; 12.263 + 12.264 + // check how many elements are already sorted 12.265 + lc = ls; 12.266 + while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) { 12.267 + lc = lc->next; 12.268 + ln++; 12.269 + } 12.270 + le = lc->next; 12.271 + 12.272 + if (le == NULL) { 12.273 + return l; // this list is already sorted :) 12.274 + } else { 12.275 + UcxList *rc; 12.276 + int rn = 1; 12.277 + rc = le; 12.278 + // skip already sorted elements 12.279 + while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) { 12.280 + rc = rc->next; 12.281 + rn++; 12.282 + } 12.283 + re = rc->next; 12.284 + 12.285 + // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them 12.286 + UcxList *sorted = ucx_list_sort_merge(ln+rn, 12.287 + ls, le, re, 12.288 + fnc, data); 12.289 + 12.290 + // Something left? Sort it! 12.291 + size_t remainder_length = ucx_list_size(re); 12.292 + if (remainder_length > 0) { 12.293 + UcxList *remainder = ucx_list_sort(re, fnc, data); 12.294 + 12.295 + // merge sorted list with (also sorted) remainder 12.296 + l = ucx_list_sort_merge(ln+rn+remainder_length, 12.297 + sorted, remainder, NULL, fnc, data); 12.298 + } else { 12.299 + // no remainder - we've got our sorted list 12.300 + l = sorted; 12.301 + } 12.302 + 12.303 + return l; 12.304 + } 12.305 +} 12.306 + 12.307 +UcxList *ucx_list_first(const UcxList *l) { 12.308 + if (!l) { 12.309 + return NULL; 12.310 + } 12.311 + 12.312 + const UcxList *e = l; 12.313 + while (e->prev) { 12.314 + e = e->prev; 12.315 + } 12.316 + return (UcxList *)e; 12.317 +} 12.318 + 12.319 +UcxList *ucx_list_remove(UcxList *l, UcxList *e) { 12.320 + return ucx_list_remove_a(ucx_default_allocator(), l, e); 12.321 +} 12.322 + 12.323 +UcxList *ucx_list_remove_a(UcxAllocator *alloc, UcxList *l, UcxList *e) { 12.324 + if (l == e) { 12.325 + l = e->next; 12.326 + } 12.327 + 12.328 + if (e->next) { 12.329 + e->next->prev = e->prev; 12.330 + } 12.331 + 12.332 + if (e->prev) { 12.333 + e->prev->next = e->next; 12.334 + } 12.335 + 12.336 + alfree(alloc, e); 12.337 + return l; 12.338 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/src/ucx/list.h Tue Aug 23 13:49:38 2016 +0200 13.3 @@ -0,0 +1,395 @@ 13.4 +/* 13.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 13.6 + * 13.7 + * Copyright 2015 Olaf Wintermann. All rights reserved. 13.8 + * 13.9 + * Redistribution and use in source and binary forms, with or without 13.10 + * modification, are permitted provided that the following conditions are met: 13.11 + * 13.12 + * 1. Redistributions of source code must retain the above copyright 13.13 + * notice, this list of conditions and the following disclaimer. 13.14 + * 13.15 + * 2. Redistributions in binary form must reproduce the above copyright 13.16 + * notice, this list of conditions and the following disclaimer in the 13.17 + * documentation and/or other materials provided with the distribution. 13.18 + * 13.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 13.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 13.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 13.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 13.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 13.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 13.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 13.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 13.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 13.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 13.29 + * POSSIBILITY OF SUCH DAMAGE. 13.30 + */ 13.31 +/** 13.32 + * Doubly linked list implementation. 13.33 + * 13.34 + * @file list.h 13.35 + * @author Mike Becker 13.36 + * @author Olaf Wintermann 13.37 + */ 13.38 + 13.39 +#ifndef UCX_LIST_H 13.40 +#define UCX_LIST_H 13.41 + 13.42 +#include "ucx.h" 13.43 +#include "allocator.h" 13.44 + 13.45 +#ifdef __cplusplus 13.46 +extern "C" { 13.47 +#endif 13.48 + 13.49 +/** 13.50 + * Loop statement for UCX lists. 13.51 + * 13.52 + * The first argument is the name of the iteration variable. The scope of 13.53 + * this variable is limited to the <code>UCX_FOREACH</code> statement. 13.54 + * 13.55 + * The second argument is a pointer to the list. In most cases this will be the 13.56 + * pointer to the first element of the list, but it may also be an arbitrary 13.57 + * element of the list. The iteration will then start with that element. 13.58 + * 13.59 + * 13.60 + * @param list The first element of the list 13.61 + * @param elem The variable name of the element 13.62 + */ 13.63 +#define UCX_FOREACH(elem,list) \ 13.64 + for (UcxList* elem = list ; elem != NULL ; elem = elem->next) 13.65 + 13.66 +/** 13.67 + * UCX list type. 13.68 + * @see UcxList 13.69 + */ 13.70 +typedef struct UcxList UcxList; 13.71 + 13.72 +/** 13.73 + * UCX list structure. 13.74 + */ 13.75 +struct UcxList { 13.76 + /** 13.77 + * List element payload. 13.78 + */ 13.79 + void *data; 13.80 + /** 13.81 + * Pointer to the next list element or <code>NULL</code>, if this is the 13.82 + * last element. 13.83 + */ 13.84 + UcxList *next; 13.85 + /** 13.86 + * Pointer to the previous list element or <code>NULL</code>, if this is 13.87 + * the first element. 13.88 + */ 13.89 + UcxList *prev; 13.90 +}; 13.91 + 13.92 +/** 13.93 + * Creates an element-wise copy of a list. 13.94 + * 13.95 + * This function clones the specified list by creating new list elements and 13.96 + * copying the data with the specified copy_func(). If no copy_func() is 13.97 + * specified, a shallow copy is created and the new list will reference the 13.98 + * same data as the source list. 13.99 + * 13.100 + * @param list the list to copy 13.101 + * @param cpyfnc a pointer to the function that shall copy an element (may be 13.102 + * <code>NULL</code>) 13.103 + * @param data additional data for the copy_func() 13.104 + * @return a pointer to the copy 13.105 + */ 13.106 +UcxList *ucx_list_clone(UcxList *list, copy_func cpyfnc, void* data); 13.107 + 13.108 +/** 13.109 + * Creates an element-wise copy of a list using an UcxAllocator. 13.110 + * 13.111 + * See ucx_list_clone() for details. 13.112 + * 13.113 + * Keep in mind, that you might want to pass the allocator as an (part of the) 13.114 + * argument for the <code>data</code> parameter, if you want the copy_func() to 13.115 + * make use of the allocator. 13.116 + * 13.117 + * @param allocator the allocator to use 13.118 + * @param list the list to copy 13.119 + * @param cpyfnc a pointer to the function that shall copy an element (may be 13.120 + * <code>NULL</code>) 13.121 + * @param data additional data for the copy_func() 13.122 + * @return a pointer to the copy 13.123 + * @see ucx_list_clone() 13.124 + */ 13.125 +UcxList *ucx_list_clone_a(UcxAllocator *allocator, UcxList *list, 13.126 + copy_func cpyfnc, void* data); 13.127 + 13.128 +/** 13.129 + * Compares two UCX lists element-wise by using a compare function. 13.130 + * 13.131 + * Each element of the two specified lists are compared by using the specified 13.132 + * compare function and the additional data. The type and content of this 13.133 + * additional data depends on the cmp_func() used. 13.134 + * 13.135 + * If the list pointers denote elements within a list, the lists are compared 13.136 + * starting with the denoted elements. Thus any previous elements are not taken 13.137 + * into account. This might be useful to check, if certain list tails match 13.138 + * each other. 13.139 + * 13.140 + * @param list1 the first list 13.141 + * @param list2 the second list 13.142 + * @param cmpfnc the compare function 13.143 + * @param data additional data for the compare function 13.144 + * @return 1, if and only if the two lists equal element-wise, 0 otherwise 13.145 + */ 13.146 +int ucx_list_equals(const UcxList *list1, const UcxList *list2, 13.147 + cmp_func cmpfnc, void* data); 13.148 + 13.149 +/** 13.150 + * Destroys the entire list. 13.151 + * 13.152 + * The members of the list are not automatically freed, so ensure they are 13.153 + * otherwise referenced or destroyed by ucx_list_free_contents(). 13.154 + * Otherwise, a memory leak is likely to occur. 13.155 + * 13.156 + * <b>Caution:</b> the argument <b>MUST</b> denote an entire list (i.e. a call 13.157 + * to ucx_list_first() on the argument must return the argument itself) 13.158 + * 13.159 + * @param list the list to free 13.160 + * @see ucx_list_free_contents() 13.161 + */ 13.162 +void ucx_list_free(UcxList *list); 13.163 + 13.164 +/** 13.165 + * Destroys the entire list using an UcxAllocator. 13.166 + * 13.167 + * See ucx_list_free() for details. 13.168 + * 13.169 + * @param allocator the allocator to use 13.170 + * @param list the list to free 13.171 + * @see ucx_list_free() 13.172 + */ 13.173 +void ucx_list_free_a(UcxAllocator *allocator, UcxList *list); 13.174 + 13.175 +/** 13.176 + * Destroys the contents of the specified list by calling the specified 13.177 + * destructor on each of them. 13.178 + * 13.179 + * Note, that the contents are not usable afterwards and the list should be 13.180 + * destroyed with ucx_list_free(). 13.181 + * 13.182 + * @param list the list for which the contents shall be freed 13.183 + * @param destr the destructor function (e.g. stdlib free()) 13.184 + * @see ucx_list_free() 13.185 + */ 13.186 +void ucx_list_free_content(UcxList* list, ucx_destructor destr); 13.187 + 13.188 + 13.189 +/** 13.190 + * Inserts an element at the end of the list. 13.191 + * 13.192 + * This is generally an O(n) operation, as the end of the list is retrieved with 13.193 + * ucx_list_last(). 13.194 + * 13.195 + * @param list the list where to append the data, or <code>NULL</code> to 13.196 + * create a new list 13.197 + * @param data the data to insert 13.198 + * @return <code>list</code>, if it is not <code>NULL</code> or a pointer to 13.199 + * the newly created list otherwise 13.200 + */ 13.201 +UcxList *ucx_list_append(UcxList *list, void *data); 13.202 + 13.203 +/** 13.204 + * Inserts an element at the end of the list using an UcxAllocator. 13.205 + * 13.206 + * See ucx_list_append() for details. 13.207 + * 13.208 + * @param allocator the allocator to use 13.209 + * @param list the list where to append the data, or <code>NULL</code> to 13.210 + * create a new list 13.211 + * @param data the data to insert 13.212 + * @return <code>list</code>, if it is not <code>NULL</code> or a pointer to 13.213 + * the newly created list otherwise 13.214 + * @see ucx_list_append() 13.215 + */ 13.216 +UcxList *ucx_list_append_a(UcxAllocator *allocator, UcxList *list, void *data); 13.217 + 13.218 +/** 13.219 + * Inserts an element at the beginning of the list. 13.220 + * 13.221 + * You <i>should</i> overwrite the old list pointer by calling 13.222 + * <code>mylist = ucx_list_prepend(mylist, mydata);</code>. However, you may 13.223 + * also perform successive calls of ucx_list_prepend() on the same list pointer, 13.224 + * as this function always searchs for the head of the list with 13.225 + * ucx_list_first(). 13.226 + * 13.227 + * @param list the list where to insert the data or <code>NULL</code> to create 13.228 + * a new list 13.229 + * @param data the data to insert 13.230 + * @return a pointer to the new list head 13.231 + */ 13.232 +UcxList *ucx_list_prepend(UcxList *list, void *data); 13.233 + 13.234 +/** 13.235 + * Inserts an element at the beginning of the list using an UcxAllocator. 13.236 + * 13.237 + * See ucx_list_prepend() for details. 13.238 + * 13.239 + * @param allocator the allocator to use 13.240 + * @param list the list where to insert the data or <code>NULL</code> to create 13.241 + * a new list 13.242 + * @param data the data to insert 13.243 + * @return a pointer to the new list head 13.244 + * @see ucx_list_prepend() 13.245 + */ 13.246 +UcxList *ucx_list_prepend_a(UcxAllocator *allocator, UcxList *list, void *data); 13.247 + 13.248 +/** 13.249 + * Concatenates two lists. 13.250 + * 13.251 + * Either of the two arguments may be <code>NULL</code>. 13.252 + * 13.253 + * This function modifies the references to the next/previous element of 13.254 + * the last/first element of <code>list1</code>/<code> 13.255 + * list2</code>. 13.256 + * 13.257 + * @param list1 first list 13.258 + * @param list2 second list 13.259 + * @return if <code>list1</code> is <code>NULL</code>, <code>list2</code> is 13.260 + * returned, otherwise <code>list1</code> is returned 13.261 + */ 13.262 +UcxList *ucx_list_concat(UcxList *list1, UcxList *list2); 13.263 + 13.264 +/** 13.265 + * Returns the first element of a list. 13.266 + * 13.267 + * If the argument is the list pointer, it is directly returned. Otherwise 13.268 + * this function traverses to the first element of the list and returns the 13.269 + * list pointer. 13.270 + * 13.271 + * @param elem one element of the list 13.272 + * @return the first element of the list, the specified element is a member of 13.273 + */ 13.274 +UcxList *ucx_list_first(const UcxList *elem); 13.275 + 13.276 +/** 13.277 + * Returns the last element of a list. 13.278 + * 13.279 + * If the argument has no successor, it is the last element and therefore 13.280 + * directly returned. Otherwise this function traverses to the last element of 13.281 + * the list and returns it. 13.282 + * 13.283 + * @param elem one element of the list 13.284 + * @return the last element of the list, the specified element is a member of 13.285 + */ 13.286 +UcxList *ucx_list_last(const UcxList *elem); 13.287 + 13.288 +/** 13.289 + * Returns the list element at the specified index. 13.290 + * 13.291 + * @param list the list to retrieve the element from 13.292 + * @param index index of the element to return 13.293 + * @return the element at the specified index or <code>NULL</code>, if the 13.294 + * index is greater than the list size 13.295 + */ 13.296 +UcxList *ucx_list_get(const UcxList *list, size_t index); 13.297 + 13.298 +/** 13.299 + * Returns the index of an element. 13.300 + * 13.301 + * @param list the list where to search for the element 13.302 + * @param elem the element to find 13.303 + * @return the index of the element or -1 if the list does not contain the 13.304 + * element 13.305 + */ 13.306 +ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem); 13.307 + 13.308 +/** 13.309 + * Returns the element count of the list. 13.310 + * 13.311 + * @param list the list whose elements are counted 13.312 + * @return the element count 13.313 + */ 13.314 +size_t ucx_list_size(const UcxList *list); 13.315 + 13.316 +/** 13.317 + * Returns the index of an element containing the specified data. 13.318 + * 13.319 + * This function uses a cmp_func() to compare the data of each list element 13.320 + * with the specified data. If no cmp_func is provided, the pointers are 13.321 + * compared. 13.322 + * 13.323 + * If the list contains the data more than once, the index of the first 13.324 + * occurrence is returned. 13.325 + * 13.326 + * @param list the list where to search for the data 13.327 + * @param elem the element data 13.328 + * @param cmpfnc the compare function 13.329 + * @param data additional data for the compare function 13.330 + * @return the index of the element containing the specified data or -1 if the 13.331 + * data is not found in this list 13.332 + */ 13.333 +ssize_t ucx_list_find(UcxList *list, void *elem, cmp_func cmpfnc, void *data); 13.334 + 13.335 +/** 13.336 + * Checks, if a list contains a specific element. 13.337 + * 13.338 + * An element is found, if ucx_list_find() returns a value greater than -1. 13.339 + * 13.340 + * @param list the list where to search for the data 13.341 + * @param elem the element data 13.342 + * @param cmpfnc the compare function 13.343 + * @param data additional data for the compare function 13.344 + * @return 1, if and only if the list contains the specified element data 13.345 + * @see ucx_list_find() 13.346 + */ 13.347 +int ucx_list_contains(UcxList *list, void *elem, cmp_func cmpfnc, void *data); 13.348 + 13.349 +/** 13.350 + * Sorts an UcxList with natural merge sort. 13.351 + * 13.352 + * This function uses O(n) additional temporary memory for merge operations 13.353 + * that is automatically freed after each merge. 13.354 + * 13.355 + * As the head of the list might change, you <b>MUST</b> call this function 13.356 + * as follows: <code>mylist = ucx_list_sort(mylist, mycmpfnc, mydata);</code>. 13.357 + * 13.358 + * @param list the list to sort 13.359 + * @param cmpfnc the function that shall be used to compare the element data 13.360 + * @param data additional data for the cmp_func() 13.361 + * @return the sorted list 13.362 + */ 13.363 +UcxList *ucx_list_sort(UcxList *list, cmp_func cmpfnc, void *data); 13.364 + 13.365 +/** 13.366 + * Removes an element from the list. 13.367 + * 13.368 + * If the first element is removed, the list pointer changes. So it is 13.369 + * <i>highly recommended</i> to <i>always</i> update the pointer by calling 13.370 + * <code>mylist = ucx_list_remove(mylist, myelem);</code>. 13.371 + * 13.372 + * @param list the list from which the element shall be removed 13.373 + * @param element the element to remove 13.374 + * @return returns the updated list pointer or <code>NULL</code>, if the list 13.375 + * is now empty 13.376 + */ 13.377 +UcxList *ucx_list_remove(UcxList *list, UcxList *element); 13.378 + 13.379 +/** 13.380 + * Removes an element from the list using an UcxAllocator. 13.381 + * 13.382 + * See ucx_list_remove() for details. 13.383 + * 13.384 + * @param allocator the allocator to use 13.385 + * @param list the list from which the element shall be removed 13.386 + * @param element the element to remove 13.387 + * @return returns the updated list pointer or <code>NULL</code>, if the list 13.388 + * @see ucx_list_remove() 13.389 + */ 13.390 +UcxList *ucx_list_remove_a(UcxAllocator *allocator, UcxList *list, 13.391 + UcxList *element); 13.392 + 13.393 +#ifdef __cplusplus 13.394 +} 13.395 +#endif 13.396 + 13.397 +#endif /* UCX_LIST_H */ 13.398 +
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/src/ucx/string.c Tue Aug 23 13:49:38 2016 +0200 14.3 @@ -0,0 +1,381 @@ 14.4 +/* 14.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 14.6 + * 14.7 + * Copyright 2015 Olaf Wintermann. All rights reserved. 14.8 + * 14.9 + * Redistribution and use in source and binary forms, with or without 14.10 + * modification, are permitted provided that the following conditions are met: 14.11 + * 14.12 + * 1. Redistributions of source code must retain the above copyright 14.13 + * notice, this list of conditions and the following disclaimer. 14.14 + * 14.15 + * 2. Redistributions in binary form must reproduce the above copyright 14.16 + * notice, this list of conditions and the following disclaimer in the 14.17 + * documentation and/or other materials provided with the distribution. 14.18 + * 14.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 14.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 14.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 14.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 14.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 14.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 14.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 14.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 14.29 + * POSSIBILITY OF SUCH DAMAGE. 14.30 + */ 14.31 + 14.32 +#include <stdlib.h> 14.33 +#include <string.h> 14.34 +#include <stdarg.h> 14.35 +#include <ctype.h> 14.36 + 14.37 +#include "string.h" 14.38 +#include "allocator.h" 14.39 + 14.40 +sstr_t sstr(char *cstring) { 14.41 + sstr_t string; 14.42 + string.ptr = cstring; 14.43 + string.length = strlen(cstring); 14.44 + return string; 14.45 +} 14.46 + 14.47 +sstr_t sstrn(char *cstring, size_t length) { 14.48 + sstr_t string; 14.49 + string.ptr = cstring; 14.50 + string.length = length; 14.51 + return string; 14.52 +} 14.53 + 14.54 +size_t sstrnlen(size_t n, sstr_t s, ...) { 14.55 + va_list ap; 14.56 + size_t size = s.length; 14.57 + va_start(ap, s); 14.58 + 14.59 + for (size_t i = 1 ; i < n ; i++) { 14.60 + sstr_t str = va_arg(ap, sstr_t); 14.61 + size += str.length; 14.62 + } 14.63 + va_end(ap); 14.64 + 14.65 + return size; 14.66 +} 14.67 + 14.68 +static sstr_t sstrvcat_a( 14.69 + UcxAllocator *a, 14.70 + size_t count, 14.71 + sstr_t s1, 14.72 + sstr_t s2, 14.73 + va_list ap) { 14.74 + sstr_t str; 14.75 + str.ptr = NULL; 14.76 + str.length = 0; 14.77 + if(count < 2) { 14.78 + return str; 14.79 + } 14.80 + 14.81 + sstr_t *strings = (sstr_t*) calloc(count, sizeof(sstr_t)); 14.82 + if(!strings) { 14.83 + return str; 14.84 + } 14.85 + 14.86 + // get all args and overall length 14.87 + strings[0] = s1; 14.88 + strings[1] = s2; 14.89 + size_t strlen = s1.length + s2.length; 14.90 + for (size_t i=2;i<count;i++) { 14.91 + sstr_t s = va_arg (ap, sstr_t); 14.92 + strings[i] = s; 14.93 + strlen += s.length; 14.94 + } 14.95 + 14.96 + // create new string 14.97 + str.ptr = (char*) almalloc(a, strlen + 1); 14.98 + str.length = strlen; 14.99 + if(!str.ptr) { 14.100 + free(strings); 14.101 + str.length = 0; 14.102 + return str; 14.103 + } 14.104 + 14.105 + // concatenate strings 14.106 + size_t pos = 0; 14.107 + for (size_t i=0;i<count;i++) { 14.108 + sstr_t s = strings[i]; 14.109 + memcpy(str.ptr + pos, s.ptr, s.length); 14.110 + pos += s.length; 14.111 + } 14.112 + 14.113 + str.ptr[str.length] = '\0'; 14.114 + 14.115 + free(strings); 14.116 + 14.117 + return str; 14.118 +} 14.119 + 14.120 +sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...) { 14.121 + va_list ap; 14.122 + va_start(ap, s2); 14.123 + sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, s2, ap); 14.124 + va_end(ap); 14.125 + return s; 14.126 +} 14.127 + 14.128 +sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...) { 14.129 + va_list ap; 14.130 + va_start(ap, s2); 14.131 + sstr_t s = sstrvcat_a(a, count, s1, s2, ap); 14.132 + va_end(ap); 14.133 + return s; 14.134 +} 14.135 + 14.136 +sstr_t sstrsubs(sstr_t s, size_t start) { 14.137 + return sstrsubsl (s, start, s.length-start); 14.138 +} 14.139 + 14.140 +sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) { 14.141 + sstr_t new_sstr; 14.142 + if (start >= s.length) { 14.143 + new_sstr.ptr = NULL; 14.144 + new_sstr.length = 0; 14.145 + } else { 14.146 + if (length > s.length-start) { 14.147 + length = s.length-start; 14.148 + } 14.149 + new_sstr.ptr = &s.ptr[start]; 14.150 + new_sstr.length = length; 14.151 + } 14.152 + return new_sstr; 14.153 +} 14.154 + 14.155 +sstr_t sstrchr(sstr_t s, int c) { 14.156 + for(size_t i=0;i<s.length;i++) { 14.157 + if(s.ptr[i] == c) { 14.158 + return sstrsubs(s, i); 14.159 + } 14.160 + } 14.161 + sstr_t n; 14.162 + n.ptr = NULL; 14.163 + n.length = 0; 14.164 + return n; 14.165 +} 14.166 + 14.167 +sstr_t sstrrchr(sstr_t s, int c) { 14.168 + if (s.length > 0) { 14.169 + for(size_t i=s.length;i>0;i--) { 14.170 + if(s.ptr[i-1] == c) { 14.171 + return sstrsubs(s, i-1); 14.172 + } 14.173 + } 14.174 + } 14.175 + sstr_t n; 14.176 + n.ptr = NULL; 14.177 + n.length = 0; 14.178 + return n; 14.179 +} 14.180 + 14.181 +sstr_t sstrstr(sstr_t string, sstr_t match) { 14.182 + if (match.length == 0) { 14.183 + return string; 14.184 + } 14.185 + 14.186 + for (size_t i = 0 ; i < string.length ; i++) { 14.187 + sstr_t substr = sstrsubs(string, i); 14.188 + if (sstrprefix(substr, match)) { 14.189 + return substr; 14.190 + } 14.191 + } 14.192 + 14.193 + sstr_t emptystr; 14.194 + emptystr.length = 0; 14.195 + emptystr.ptr = NULL; 14.196 + return emptystr; 14.197 +} 14.198 + 14.199 +sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) { 14.200 + return sstrsplit_a(ucx_default_allocator(), s, d, n); 14.201 +} 14.202 + 14.203 +sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t s, sstr_t d, ssize_t *n) { 14.204 + if (s.length == 0 || d.length == 0) { 14.205 + *n = -1; 14.206 + return NULL; 14.207 + } 14.208 + 14.209 + sstr_t* result; 14.210 + ssize_t nmax = *n; 14.211 + *n = 1; 14.212 + 14.213 + /* special case: exact match - no processing needed */ 14.214 + if (sstrcmp(s, d) == 0) { 14.215 + *n = 0; 14.216 + return NULL; 14.217 + } 14.218 + sstr_t sv = sstrdup(s); 14.219 + if (sv.length == 0) { 14.220 + *n = -2; 14.221 + return NULL; 14.222 + } 14.223 + 14.224 + for (size_t i = 0 ; i < s.length ; i++) { 14.225 + sstr_t substr = sstrsubs(sv, i); 14.226 + if (sstrprefix(substr, d)) { 14.227 + (*n)++; 14.228 + for (size_t j = 0 ; j < d.length ; j++) { 14.229 + sv.ptr[i+j] = 0; 14.230 + } 14.231 + i += d.length - 1; // -1, because the loop will do a i++ 14.232 + } 14.233 + if ((*n) == nmax) break; 14.234 + } 14.235 + result = (sstr_t*) almalloc(allocator, sizeof(sstr_t)*(*n)); 14.236 + 14.237 + if (result) { 14.238 + char *pptr = sv.ptr; 14.239 + for (ssize_t i = 0 ; i < *n ; i++) { 14.240 + size_t l = strlen(pptr); 14.241 + char* ptr = (char*) almalloc(allocator, l + 1); 14.242 + if (ptr) { 14.243 + memcpy(ptr, pptr, l); 14.244 + ptr[l] = 0; 14.245 + 14.246 + result[i] = sstrn(ptr, l); 14.247 + pptr += l + d.length; 14.248 + } else { 14.249 + for (ssize_t j = i-1 ; j >= 0 ; j--) { 14.250 + alfree(allocator, result[j].ptr); 14.251 + } 14.252 + alfree(allocator, result); 14.253 + *n = -2; 14.254 + break; 14.255 + } 14.256 + } 14.257 + } else { 14.258 + *n = -2; 14.259 + } 14.260 + 14.261 + free(sv.ptr); 14.262 + 14.263 + return result; 14.264 +} 14.265 + 14.266 +int sstrcmp(sstr_t s1, sstr_t s2) { 14.267 + if (s1.length == s2.length) { 14.268 + return memcmp(s1.ptr, s2.ptr, s1.length); 14.269 + } else if (s1.length > s2.length) { 14.270 + return 1; 14.271 + } else { 14.272 + return -1; 14.273 + } 14.274 +} 14.275 + 14.276 +int sstrcasecmp(sstr_t s1, sstr_t s2) { 14.277 + if (s1.length == s2.length) { 14.278 +#ifdef _WIN32 14.279 + return _strnicmp(s1.ptr, s2.ptr, s1.length); 14.280 +#else 14.281 + return strncasecmp(s1.ptr, s2.ptr, s1.length); 14.282 +#endif 14.283 + } else if (s1.length > s2.length) { 14.284 + return 1; 14.285 + } else { 14.286 + return -1; 14.287 + } 14.288 +} 14.289 + 14.290 +sstr_t sstrdup(sstr_t s) { 14.291 + return sstrdup_a(ucx_default_allocator(), s); 14.292 +} 14.293 + 14.294 +sstr_t sstrdup_a(UcxAllocator *allocator, sstr_t s) { 14.295 + sstr_t newstring; 14.296 + newstring.ptr = (char*)almalloc(allocator, s.length + 1); 14.297 + if (newstring.ptr) { 14.298 + newstring.length = s.length; 14.299 + newstring.ptr[newstring.length] = 0; 14.300 + 14.301 + memcpy(newstring.ptr, s.ptr, s.length); 14.302 + } else { 14.303 + newstring.length = 0; 14.304 + } 14.305 + 14.306 + return newstring; 14.307 +} 14.308 + 14.309 +sstr_t sstrtrim(sstr_t string) { 14.310 + sstr_t newstr = string; 14.311 + 14.312 + while (newstr.length > 0 && isspace(*newstr.ptr)) { 14.313 + newstr.ptr++; 14.314 + newstr.length--; 14.315 + } 14.316 + while (newstr.length > 0 && isspace(newstr.ptr[newstr.length-1])) { 14.317 + newstr.length--; 14.318 + } 14.319 + 14.320 + return newstr; 14.321 +} 14.322 + 14.323 +int sstrprefix(sstr_t string, sstr_t prefix) { 14.324 + if (string.length == 0) { 14.325 + return prefix.length == 0; 14.326 + } 14.327 + if (prefix.length == 0) { 14.328 + return 1; 14.329 + } 14.330 + 14.331 + if (prefix.length > string.length) { 14.332 + return 0; 14.333 + } else { 14.334 + return memcmp(string.ptr, prefix.ptr, prefix.length) == 0; 14.335 + } 14.336 +} 14.337 + 14.338 +int sstrsuffix(sstr_t string, sstr_t suffix) { 14.339 + if (string.length == 0) { 14.340 + return suffix.length == 0; 14.341 + } 14.342 + if (suffix.length == 0) { 14.343 + return 1; 14.344 + } 14.345 + 14.346 + if (suffix.length > string.length) { 14.347 + return 0; 14.348 + } else { 14.349 + return memcmp(string.ptr+string.length-suffix.length, 14.350 + suffix.ptr, suffix.length) == 0; 14.351 + } 14.352 +} 14.353 + 14.354 +sstr_t sstrlower(sstr_t string) { 14.355 + sstr_t ret = sstrdup(string); 14.356 + for (size_t i = 0; i < ret.length ; i++) { 14.357 + ret.ptr[i] = tolower(ret.ptr[i]); 14.358 + } 14.359 + return ret; 14.360 +} 14.361 + 14.362 +sstr_t sstrlower_a(UcxAllocator *allocator, sstr_t string) { 14.363 + sstr_t ret = sstrdup_a(allocator, string); 14.364 + for (size_t i = 0; i < ret.length ; i++) { 14.365 + ret.ptr[i] = tolower(ret.ptr[i]); 14.366 + } 14.367 + return ret; 14.368 +} 14.369 + 14.370 +sstr_t sstrupper(sstr_t string) { 14.371 + sstr_t ret = sstrdup(string); 14.372 + for (size_t i = 0; i < ret.length ; i++) { 14.373 + ret.ptr[i] = toupper(ret.ptr[i]); 14.374 + } 14.375 + return ret; 14.376 +} 14.377 + 14.378 +sstr_t sstrupper_a(UcxAllocator *allocator, sstr_t string) { 14.379 + sstr_t ret = sstrdup_a(allocator, string); 14.380 + for (size_t i = 0; i < ret.length ; i++) { 14.381 + ret.ptr[i] = toupper(ret.ptr[i]); 14.382 + } 14.383 + return ret; 14.384 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/src/ucx/string.h Tue Aug 23 13:49:38 2016 +0200 15.3 @@ -0,0 +1,457 @@ 15.4 +/* 15.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 15.6 + * 15.7 + * Copyright 2015 Olaf Wintermann. All rights reserved. 15.8 + * 15.9 + * Redistribution and use in source and binary forms, with or without 15.10 + * modification, are permitted provided that the following conditions are met: 15.11 + * 15.12 + * 1. Redistributions of source code must retain the above copyright 15.13 + * notice, this list of conditions and the following disclaimer. 15.14 + * 15.15 + * 2. Redistributions in binary form must reproduce the above copyright 15.16 + * notice, this list of conditions and the following disclaimer in the 15.17 + * documentation and/or other materials provided with the distribution. 15.18 + * 15.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 15.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 15.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 15.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 15.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 15.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 15.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 15.29 + * POSSIBILITY OF SUCH DAMAGE. 15.30 + */ 15.31 +/** 15.32 + * Bounded string implementation. 15.33 + * 15.34 + * The UCX strings (<code>sstr_t</code>) provide an alternative to C strings. 15.35 + * The main difference to C strings is, that <code>sstr_t</code> does <b>not 15.36 + * need to be <code>NULL</code>-terminated</b>. Instead the length is stored 15.37 + * within the structure. 15.38 + * 15.39 + * When using <code>sstr_t</code>, developers must be full aware of what type 15.40 + * of string (<code>NULL</code>-terminated) or not) they are using, when 15.41 + * accessing the <code>char* ptr</code> directly. 15.42 + * 15.43 + * The UCX string module provides some common string functions, known from 15.44 + * standard libc, working with <code>sstr_t</code>. 15.45 + * 15.46 + * @file string.h 15.47 + * @author Mike Becker 15.48 + * @author Olaf Wintermann 15.49 + */ 15.50 + 15.51 +#ifndef UCX_STRING_H 15.52 +#define UCX_STRING_H 15.53 + 15.54 +#include "ucx.h" 15.55 +#include "allocator.h" 15.56 +#include <stddef.h> 15.57 + 15.58 +/** Shortcut for a <code>sstr_t struct</code> literal. */ 15.59 +#define ST(s) { (char*)s, sizeof(s)-1 } 15.60 + 15.61 +/** Shortcut for the conversion of a C string to a <code>sstr_t</code>. */ 15.62 +#define S(s) sstrn((char*)s, sizeof(s)-1) 15.63 + 15.64 +#ifdef __cplusplus 15.65 +extern "C" { 15.66 +#endif 15.67 + 15.68 +/** 15.69 + * The UCX string structure. 15.70 + */ 15.71 +typedef struct { 15.72 + /** A reference to the string (<b>not necessarily <code>NULL</code> 15.73 + * -terminated</b>) */ 15.74 + char *ptr; 15.75 + /** The length of the string */ 15.76 + size_t length; 15.77 +} sstr_t; 15.78 + 15.79 +/** 15.80 + * Creates a new sstr_t based on a C string. 15.81 + * 15.82 + * The length is implicitly inferred by using a call to <code>strlen()</code>. 15.83 + * 15.84 + * <b>Note:</b> the sstr_t will hold a <i>reference</i> to the C string. If you 15.85 + * do want a copy, use sstrdup() on the return value of this function. 15.86 + * 15.87 + * @param cstring the C string to wrap 15.88 + * @return a new sstr_t containing the C string 15.89 + * 15.90 + * @see sstrn() 15.91 + */ 15.92 +sstr_t sstr(char *cstring); 15.93 + 15.94 +/** 15.95 + * Creates a new sstr_t of the specified length based on a C string. 15.96 + * 15.97 + * <b>Note:</b> the sstr_t will hold a <i>reference</i> to the C string. If you 15.98 + * do want a copy, use sstrdup() on the return value of this function. 15.99 + * 15.100 + * @param cstring the C string to wrap 15.101 + * @param length the length of the string 15.102 + * @return a new sstr_t containing the C string 15.103 + * 15.104 + * @see sstr() 15.105 + * @see S() 15.106 + */ 15.107 +sstr_t sstrn(char *cstring, size_t length); 15.108 + 15.109 + 15.110 +/** 15.111 + * Returns the cumulated length of all specified strings. 15.112 + * 15.113 + * At least one string must be specified. 15.114 + * 15.115 + * <b>Attention:</b> if the count argument does not match the count of the 15.116 + * specified strings, the behavior is undefined. 15.117 + * 15.118 + * @param count the total number of specified strings (so at least 1) 15.119 + * @param string the first string 15.120 + * @param ... all other strings 15.121 + * @return the cumulated length of all strings 15.122 + */ 15.123 +size_t sstrnlen(size_t count, sstr_t string, ...); 15.124 + 15.125 +/** 15.126 + * Concatenates two or more strings. 15.127 + * 15.128 + * The resulting string will be allocated by standard <code>malloc()</code>. 15.129 + * So developers <b>MUST</b> pass the sstr_t.ptr to <code>free()</code>. 15.130 + * 15.131 + * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>- 15.132 + * terminated. 15.133 + * 15.134 + * @param count the total number of strings to concatenate 15.135 + * @param s1 first string 15.136 + * @param s2 second string 15.137 + * @param ... all remaining strings 15.138 + * @return the concatenated string 15.139 + */ 15.140 +sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...); 15.141 + 15.142 +/** 15.143 + * Concatenates two or more strings using an UcxAllocator. 15.144 + * 15.145 + * See sstrcat() for details. 15.146 + * 15.147 + * @param a the allocator to use 15.148 + * @param count the total number of strings to concatenate 15.149 + * @param s1 first string 15.150 + * @param s2 second string 15.151 + * @param ... all remaining strings 15.152 + * @return the concatenated string 15.153 + */ 15.154 +sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...); 15.155 + 15.156 + 15.157 +/** 15.158 + * Returns a substring starting at the specified location. 15.159 + * 15.160 + * <b>Attention:</b> the new string references the same memory area as the 15.161 + * input string and will <b>NOT</b> be <code>NULL</code>-terminated. 15.162 + * Use sstrdup() to get a copy. 15.163 + * 15.164 + * @param string input string 15.165 + * @param start start location of the substring 15.166 + * @return a substring of <code>string</code> starting at <code>start</code> 15.167 + * 15.168 + * @see sstrsubsl() 15.169 + * @see sstrchr() 15.170 + */ 15.171 +sstr_t sstrsubs(sstr_t string, size_t start); 15.172 + 15.173 +/** 15.174 + * Returns a substring with a maximum length starting at the specified location. 15.175 + * 15.176 + * <b>Attention:</b> the new string references the same memory area as the 15.177 + * input string and will <b>NOT</b> be <code>NULL</code>-terminated. 15.178 + * Use sstrdup() to get a copy. 15.179 + * 15.180 + * @param string input string 15.181 + * @param start start location of the substring 15.182 + * @param length the maximum length of the substring 15.183 + * @return a substring of <code>string</code> starting at <code>start</code> 15.184 + * with a maximum length of <code>length</code> 15.185 + * 15.186 + * @see sstrsubs() 15.187 + * @see sstrchr() 15.188 + */ 15.189 +sstr_t sstrsubsl(sstr_t string, size_t start, size_t length); 15.190 + 15.191 +/** 15.192 + * Returns a substring starting at the location of the first occurrence of the 15.193 + * specified character. 15.194 + * 15.195 + * If the string does not contain the character, an empty string is returned. 15.196 + * 15.197 + * @param string the string where to locate the character 15.198 + * @param chr the character to locate 15.199 + * @return a substring starting at the first location of <code>chr</code> 15.200 + * 15.201 + * @see sstrsubs() 15.202 + */ 15.203 +sstr_t sstrchr(sstr_t string, int chr); 15.204 + 15.205 +/** 15.206 + * Returns a substring starting at the location of the last occurrence of the 15.207 + * specified character. 15.208 + * 15.209 + * If the string does not contain the character, an empty string is returned. 15.210 + * 15.211 + * @param string the string where to locate the character 15.212 + * @param chr the character to locate 15.213 + * @return a substring starting at the last location of <code>chr</code> 15.214 + * 15.215 + * @see sstrsubs() 15.216 + */ 15.217 +sstr_t sstrrchr(sstr_t string, int chr); 15.218 + 15.219 +/** 15.220 + * Returns a substring starting at the location of the first occurrence of the 15.221 + * specified string. 15.222 + * 15.223 + * If the string does not contain the other string, an empty string is returned. 15.224 + * 15.225 + * If <code>match</code> is an empty string, the complete <code>string</code> is 15.226 + * returned. 15.227 + * 15.228 + * @param string the string to be scanned 15.229 + * @param match string containing the sequence of characters to match 15.230 + * @return a substring starting at the first occurrence of 15.231 + * <code>match</code>, or an empty string, if the sequence is not 15.232 + * present in <code>string</code> 15.233 + */ 15.234 +sstr_t sstrstr(sstr_t string, sstr_t match); 15.235 + 15.236 +/** 15.237 + * Splits a string into parts by using a delimiter string. 15.238 + * 15.239 + * This function will return <code>NULL</code>, if one of the following happens: 15.240 + * <ul> 15.241 + * <li>the string length is zero</li> 15.242 + * <li>the delimeter length is zero</li> 15.243 + * <li>the string equals the delimeter</li> 15.244 + * <li>memory allocation fails</li> 15.245 + * </ul> 15.246 + * 15.247 + * The integer referenced by <code>count</code> is used as input and determines 15.248 + * the maximum size of the resulting array, i.e. the maximum count of splits to 15.249 + * perform + 1. 15.250 + * 15.251 + * The integer referenced by <code>count</code> is also used as output and is 15.252 + * set to 15.253 + * <ul> 15.254 + * <li>-2, on memory allocation errors</li> 15.255 + * <li>-1, if either the string or the delimiter is an empty string</li> 15.256 + * <li>0, if the string equals the delimiter</li> 15.257 + * <li>1, if the string does not contain the delimiter</li> 15.258 + * <li>the count of array items, otherwise</li> 15.259 + * </ul> 15.260 + * 15.261 + * If the string starts with the delimiter, the first item of the resulting 15.262 + * array will be an empty string. 15.263 + * 15.264 + * If the string ends with the delimiter and the maximum list size is not 15.265 + * exceeded, the last array item will be an empty string. 15.266 + * 15.267 + * <b>Attention:</b> The array pointer <b>AND</b> all sstr_t.ptr of the array 15.268 + * items must be manually passed to <code>free()</code>. Use sstrsplit_a() with 15.269 + * an allocator to managed memory, to avoid this. 15.270 + * 15.271 + * @param string the string to split 15.272 + * @param delim the delimiter string 15.273 + * @param count IN: the maximum size of the resulting array (0 = no limit), 15.274 + * OUT: the actual size of the array 15.275 + * @return a sstr_t array containing the split strings or 15.276 + * <code>NULL</code> on error 15.277 + * 15.278 + * @see sstrsplit_a() 15.279 + */ 15.280 +sstr_t* sstrsplit(sstr_t string, sstr_t delim, ssize_t *count); 15.281 + 15.282 +/** 15.283 + * Performing sstrsplit() using an UcxAllocator. 15.284 + * 15.285 + * <i>Read the description of sstrsplit() for details.</i> 15.286 + * 15.287 + * The memory for the sstr_t.ptr pointers of the array items and the memory for 15.288 + * the sstr_t array itself are allocated by using the UcxAllocator.malloc() 15.289 + * function. 15.290 + * 15.291 + * <b>Note:</b> the allocator is not used for memory that is freed within the 15.292 + * same call of this function (locally scoped variables). 15.293 + * 15.294 + * @param allocator the UcxAllocator used for allocating memory 15.295 + * @param string the string to split 15.296 + * @param delim the delimiter string 15.297 + * @param count IN: the maximum size of the resulting array (0 = no limit), 15.298 + * OUT: the actual size of the array 15.299 + * @return a sstr_t array containing the split strings or 15.300 + * <code>NULL</code> on error 15.301 + * 15.302 + * @see sstrsplit() 15.303 + */ 15.304 +sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t string, sstr_t delim, 15.305 + ssize_t *count); 15.306 + 15.307 +/** 15.308 + * Compares two UCX strings with standard <code>memcmp()</code>. 15.309 + * 15.310 + * At first it compares the sstr_t.length attribute of the two strings. The 15.311 + * <code>memcmp()</code> function is called, if and only if the lengths match. 15.312 + * 15.313 + * @param s1 the first string 15.314 + * @param s2 the second string 15.315 + * @return -1, if the length of s1 is less than the length of s2 or 1, if the 15.316 + * length of s1 is greater than the length of s2 or the result of 15.317 + * <code>memcmp()</code> otherwise (i.e. 0 if the strings match) 15.318 + */ 15.319 +int sstrcmp(sstr_t s1, sstr_t s2); 15.320 + 15.321 +/** 15.322 + * Compares two UCX strings ignoring the case. 15.323 + * 15.324 + * At first it compares the sstr_t.length attribute of the two strings. If and 15.325 + * only if the lengths match, both strings are compared char by char ignoring 15.326 + * the case. 15.327 + * 15.328 + * @param s1 the first string 15.329 + * @param s2 the second string 15.330 + * @return -1, if the length of s1 is less than the length of s2 or 1, if the 15.331 + * length of s1 is greater than the length of s2 or the difference between the 15.332 + * first two differing characters otherwise (i.e. 0 if the strings match and 15.333 + * no characters differ) 15.334 + */ 15.335 +int sstrcasecmp(sstr_t s1, sstr_t s2); 15.336 + 15.337 +/** 15.338 + * Creates a duplicate of the specified string. 15.339 + * 15.340 + * The new sstr_t will contain a copy allocated by standard 15.341 + * <code>malloc()</code>. So developers <b>MUST</b> pass the sstr_t.ptr to 15.342 + * <code>free()</code>. 15.343 + * 15.344 + * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>- 15.345 + * terminated. 15.346 + * 15.347 + * @param string the string to duplicate 15.348 + * @return a duplicate of the string 15.349 + * @see sstrdup_a() 15.350 + */ 15.351 +sstr_t sstrdup(sstr_t string); 15.352 + 15.353 +/** 15.354 + * Creates a duplicate of the specified string using an UcxAllocator. 15.355 + * 15.356 + * The new sstr_t will contain a copy allocated by the allocators 15.357 + * ucx_allocator_malloc function. So it is implementation depended, whether the 15.358 + * returned sstr_t.ptr pointer must be passed to the allocators 15.359 + * ucx_allocator_free function manually. 15.360 + * 15.361 + * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>- 15.362 + * terminated. 15.363 + * 15.364 + * @param allocator a valid instance of an UcxAllocator 15.365 + * @param string the string to duplicate 15.366 + * @return a duplicate of the string 15.367 + * @see sstrdup() 15.368 + */ 15.369 +sstr_t sstrdup_a(UcxAllocator *allocator, sstr_t string); 15.370 + 15.371 +/** 15.372 + * Omits leading and trailing spaces. 15.373 + * 15.374 + * This function returns a new sstr_t containing a trimmed version of the 15.375 + * specified string. 15.376 + * 15.377 + * <b>Note:</b> the new sstr_t references the same memory, thus you 15.378 + * <b>MUST NOT</b> pass the sstr_t.ptr of the return value to 15.379 + * <code>free()</code>. It is also highly recommended to avoid assignments like 15.380 + * <code>mystr = sstrtrim(mystr);</code> as you lose the reference to the 15.381 + * source string. Assignments of this type are only permitted, if the 15.382 + * sstr_t.ptr of the source string does not need to be freed or if another 15.383 + * reference to the source string exists. 15.384 + * 15.385 + * @param string the string that shall be trimmed 15.386 + * @return a new sstr_t containing the trimmed string 15.387 + */ 15.388 +sstr_t sstrtrim(sstr_t string); 15.389 + 15.390 +/** 15.391 + * Checks, if a string has a specific prefix. 15.392 + * @param string the string to check 15.393 + * @param prefix the prefix the string should have 15.394 + * @return 1, if and only if the string has the specified prefix, 0 otherwise 15.395 + */ 15.396 +int sstrprefix(sstr_t string, sstr_t prefix); 15.397 + 15.398 +/** 15.399 + * Checks, if a string has a specific suffix. 15.400 + * @param string the string to check 15.401 + * @param suffix the suffix the string should have 15.402 + * @return 1, if and only if the string has the specified suffix, 0 otherwise 15.403 + */ 15.404 +int sstrsuffix(sstr_t string, sstr_t suffix); 15.405 + 15.406 +/** 15.407 + * Returns a lower case version of a string. 15.408 + * 15.409 + * This function creates a duplicate of the input string, first. See the 15.410 + * documentation of sstrdup() for the implications. 15.411 + * 15.412 + * @param string the input string 15.413 + * @return the resulting lower case string 15.414 + * @see sstrdup() 15.415 + */ 15.416 +sstr_t sstrlower(sstr_t string); 15.417 + 15.418 +/** 15.419 + * Returns a lower case version of a string. 15.420 + * 15.421 + * This function creates a duplicate of the input string, first. See the 15.422 + * documentation of sstrdup_a() for the implications. 15.423 + * 15.424 + * @param allocator the allocator used for duplicating the string 15.425 + * @param string the input string 15.426 + * @return the resulting lower case string 15.427 + * @see sstrdup_a() 15.428 + */ 15.429 +sstr_t sstrlower_a(UcxAllocator *allocator, sstr_t string); 15.430 + 15.431 +/** 15.432 + * Returns a upper case version of a string. 15.433 + * 15.434 + * This function creates a duplicate of the input string, first. See the 15.435 + * documentation of sstrdup() for the implications. 15.436 + * 15.437 + * @param string the input string 15.438 + * @return the resulting upper case string 15.439 + * @see sstrdup() 15.440 + */ 15.441 +sstr_t sstrupper(sstr_t string); 15.442 + 15.443 +/** 15.444 + * Returns a upper case version of a string. 15.445 + * 15.446 + * This function creates a duplicate of the input string, first. See the 15.447 + * documentation of sstrdup_a() for the implications. 15.448 + * 15.449 + * @param allocator the allocator used for duplicating the string 15.450 + * @param string the input string 15.451 + * @return the resulting upper case string 15.452 + * @see sstrdup_a() 15.453 + */ 15.454 +sstr_t sstrupper_a(UcxAllocator *allocator, sstr_t string); 15.455 + 15.456 +#ifdef __cplusplus 15.457 +} 15.458 +#endif 15.459 + 15.460 +#endif /* UCX_STRING_H */
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/src/ucx/ucx.h Tue Aug 23 13:49:38 2016 +0200 16.3 @@ -0,0 +1,138 @@ 16.4 +/* 16.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 16.6 + * 16.7 + * Copyright 2015 Olaf Wintermann. All rights reserved. 16.8 + * 16.9 + * Redistribution and use in source and binary forms, with or without 16.10 + * modification, are permitted provided that the following conditions are met: 16.11 + * 16.12 + * 1. Redistributions of source code must retain the above copyright 16.13 + * notice, this list of conditions and the following disclaimer. 16.14 + * 16.15 + * 2. Redistributions in binary form must reproduce the above copyright 16.16 + * notice, this list of conditions and the following disclaimer in the 16.17 + * documentation and/or other materials provided with the distribution. 16.18 + * 16.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 16.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 16.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 16.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 16.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 16.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 16.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 16.29 + * POSSIBILITY OF SUCH DAMAGE. 16.30 + */ 16.31 +/** 16.32 + * Main UCX Header providing most common definitions. 16.33 + * 16.34 + * @file ucx.h 16.35 + * @author Mike Becker 16.36 + * @author Olaf Wintermann 16.37 + */ 16.38 + 16.39 +#ifndef UCX_H 16.40 +#define UCX_H 16.41 + 16.42 +/** Major UCX version as integer constant. */ 16.43 +#define UCX_VERSION_MAJOR 0 16.44 + 16.45 +/** Minor UCX version as integer constant. */ 16.46 +#define UCX_VERSION_MINOR 9 16.47 + 16.48 +/** The UCX version in format [major].[minor] */ 16.49 +#define UCX_VERSION UCX_VERSION_MAJOR.UCX_VERSION_MINOR 16.50 + 16.51 +#include <stdlib.h> 16.52 + 16.53 +#ifdef _WIN32 16.54 +#if !(defined __ssize_t_defined || defined _SSIZE_T_) 16.55 +#include <BaseTsd.h> 16.56 +typedef SSIZE_T ssize_t; 16.57 +#define __ssize_t_defined 16.58 +#define _SSIZE_T_ 16.59 +#endif /* __ssize_t_defined and _SSIZE_T */ 16.60 +#else /* !_WIN32 */ 16.61 +#include <sys/types.h> 16.62 +#endif /* _WIN32 */ 16.63 + 16.64 +#ifdef __cplusplus 16.65 +#ifndef _Bool 16.66 +#define _Bool bool 16.67 +#define restrict 16.68 +#endif 16.69 +/** Use C naming even when compiling with C++. */ 16.70 +#define UCX_EXTERN extern "C" 16.71 +extern "C" { 16.72 +#else 16.73 +/** Pointless in C. */ 16.74 +#define UCX_EXTERN 16.75 +#endif 16.76 + 16.77 + 16.78 +/** 16.79 + * A function pointer to a destructor function. 16.80 + * @see ucx_mempool_setdestr() 16.81 + * @see ucx_mempool_regdestr() 16.82 + */ 16.83 +typedef void(*ucx_destructor)(void*); 16.84 + 16.85 +/** 16.86 + * Function pointer to a compare function. 16.87 + * 16.88 + * The compare function shall take three arguments: the two values that shall be 16.89 + * compared and optional additional data. 16.90 + * The function shall then return -1 if the first argument is less than the 16.91 + * second argument, 1 if the first argument is greater than the second argument 16.92 + * and 0 if both arguments are equal. If the third argument is 16.93 + * <code>NULL</code>, it shall be ignored. 16.94 + */ 16.95 +typedef int(*cmp_func)(void*,void*,void*); 16.96 + 16.97 +/** 16.98 + * Function pointer to a copy function. 16.99 + * 16.100 + * The copy function shall create a copy of the first argument and may use 16.101 + * additional data provided by the second argument. If the second argument is 16.102 + * <code>NULL</code>, it shall be ignored. 16.103 + 16.104 + * <b>Attention:</b> if pointers returned by functions of this type may be 16.105 + * passed to <code>free()</code> depends on the implementation of the 16.106 + * respective <code>copy_func</code>. 16.107 + */ 16.108 +typedef void*(*copy_func)(void*,void*); 16.109 + 16.110 +/** 16.111 + * Function pointer to a write function. 16.112 + * 16.113 + * The signature of the write function shall be compatible to the signature 16.114 + * of standard <code>fwrite</code>, though it may use arbitrary data types for 16.115 + * source and destination. 16.116 + * 16.117 + * The arguments shall contain (in ascending order): a pointer to the source, 16.118 + * the length of one element, the element count and a pointer to the 16.119 + * destination. 16.120 + */ 16.121 +typedef size_t(*write_func)(const void*, size_t, size_t, void*); 16.122 + 16.123 +/** 16.124 + * Function pointer to a read function. 16.125 + * 16.126 + * The signature of the read function shall be compatible to the signature 16.127 + * of standard <code>fread</code>, though it may use arbitrary data types for 16.128 + * source and destination. 16.129 + * 16.130 + * The arguments shall contain (in ascending order): a pointer to the 16.131 + * destination, the length of one element, the element count and a pointer to 16.132 + * the source. 16.133 + */ 16.134 +typedef size_t(*read_func)(void*, size_t, size_t, void*); 16.135 + 16.136 +#ifdef __cplusplus 16.137 +} 16.138 +#endif 16.139 + 16.140 +#endif /* UCX_H */ 16.141 +
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/src/ucx/utils.c Tue Aug 23 13:49:38 2016 +0200 17.3 @@ -0,0 +1,259 @@ 17.4 +/* 17.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 17.6 + * 17.7 + * Copyright 2015 Olaf Wintermann. All rights reserved. 17.8 + * 17.9 + * Redistribution and use in source and binary forms, with or without 17.10 + * modification, are permitted provided that the following conditions are met: 17.11 + * 17.12 + * 1. Redistributions of source code must retain the above copyright 17.13 + * notice, this list of conditions and the following disclaimer. 17.14 + * 17.15 + * 2. Redistributions in binary form must reproduce the above copyright 17.16 + * notice, this list of conditions and the following disclaimer in the 17.17 + * documentation and/or other materials provided with the distribution. 17.18 + * 17.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 17.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 17.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 17.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 17.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 17.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 17.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 17.29 + * POSSIBILITY OF SUCH DAMAGE. 17.30 + */ 17.31 + 17.32 +#include "utils.h" 17.33 +#include <math.h> 17.34 +#include <stdio.h> 17.35 +#include <limits.h> 17.36 +#include <errno.h> 17.37 + 17.38 +/* COPY FUCNTIONS */ 17.39 +void* ucx_strcpy(void* s, void* data) { 17.40 + char *str = (char*) s; 17.41 + size_t n = 1+strlen(str); 17.42 + char *cpy = (char*) malloc(n); 17.43 + memcpy(cpy, str, n); 17.44 + return cpy; 17.45 +} 17.46 + 17.47 +void* ucx_memcpy(void* m, void* n) { 17.48 + size_t k = *((size_t*)n); 17.49 + void *cpy = malloc(k); 17.50 + memcpy(cpy, m, k); 17.51 + return cpy; 17.52 +} 17.53 + 17.54 +size_t ucx_stream_copy(void *src, void *dest, read_func readfnc, 17.55 + write_func writefnc, char* buf, size_t bufsize, size_t n) { 17.56 + if(n == 0 || bufsize == 0) { 17.57 + return 0; 17.58 + } 17.59 + 17.60 + char *lbuf; 17.61 + size_t ncp = 0; 17.62 + 17.63 + if(buf) { 17.64 + lbuf = buf; 17.65 + } else { 17.66 + lbuf = (char*)malloc(bufsize); 17.67 + if(lbuf == NULL) { 17.68 + return 0; 17.69 + } 17.70 + } 17.71 + 17.72 + size_t r; 17.73 + size_t rn = bufsize > n ? n : bufsize; 17.74 + while((r = readfnc(lbuf, 1, rn, src)) != 0) { 17.75 + r = writefnc(lbuf, 1, r, dest); 17.76 + ncp += r; 17.77 + n -= r; 17.78 + rn = bufsize > n ? n : bufsize; 17.79 + if(r == 0 || n == 0) { 17.80 + break; 17.81 + } 17.82 + } 17.83 + 17.84 + if (lbuf != buf) { 17.85 + free(lbuf); 17.86 + } 17.87 + 17.88 + return ncp; 17.89 +} 17.90 + 17.91 +/* COMPARE FUNCTIONS */ 17.92 + 17.93 +int ucx_strcmp(void *s1, void *s2, void *data) { 17.94 + return strcmp((char*)s1, (char*)s2); 17.95 +} 17.96 + 17.97 +int ucx_strncmp(void *s1, void *s2, void *n) { 17.98 + return strncmp((char*)s1, (char*)s2, *((size_t*) n)); 17.99 +} 17.100 + 17.101 +int ucx_intcmp(void *i1, void *i2, void *data) { 17.102 + int a = *((int*) i1); 17.103 + int b = *((int*) i2); 17.104 + if (a == b) { 17.105 + return 0; 17.106 + } else { 17.107 + return a < b ? -1 : 1; 17.108 + } 17.109 +} 17.110 + 17.111 +int ucx_floatcmp(void *f1, void *f2, void *epsilon) { 17.112 + float a = *((float*) f1); 17.113 + float b = *((float*) f2); 17.114 + float e = !epsilon ? 1e-6f : *((float*)epsilon); 17.115 + if (fabsf(a - b) < e) { 17.116 + return 0; 17.117 + } else { 17.118 + return a < b ? -1 : 1; 17.119 + } 17.120 +} 17.121 + 17.122 +int ucx_doublecmp(void *d1, void *d2, void *epsilon) { 17.123 + double a = *((float*) d1); 17.124 + double b = *((float*) d2); 17.125 + double e = !epsilon ? 1e-14 : *((double*)epsilon); 17.126 + if (fabs(a - b) < e) { 17.127 + return 0; 17.128 + } else { 17.129 + return a < b ? -1 : 1; 17.130 + } 17.131 +} 17.132 + 17.133 +int ucx_ptrcmp(void *ptr1, void *ptr2, void *data) { 17.134 + intptr_t p1 = (intptr_t) ptr1; 17.135 + intptr_t p2 = (intptr_t) ptr2; 17.136 + if (p1 == p2) { 17.137 + return 0; 17.138 + } else { 17.139 + return p1 < p2 ? -1 : 1; 17.140 + } 17.141 +} 17.142 + 17.143 +int ucx_memcmp(void *ptr1, void *ptr2, void *n) { 17.144 + return memcmp(ptr1, ptr2, *((size_t*)n)); 17.145 +} 17.146 + 17.147 +/* PRINTF FUNCTIONS */ 17.148 + 17.149 +#ifdef va_copy 17.150 +#define UCX_PRINTF_BUFSIZE 256 17.151 +#else 17.152 +#pragma message("WARNING: C99 va_copy macro not supported by this platform" \ 17.153 + " - limiting ucx_*printf to 2 KiB") 17.154 +#define UCX_PRINTF_BUFSIZE 0x800 17.155 +#endif 17.156 + 17.157 +int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...) { 17.158 + int ret; 17.159 + va_list ap; 17.160 + va_start(ap, fmt); 17.161 + ret = ucx_vfprintf(stream, wfc, fmt, ap); 17.162 + va_end(ap); 17.163 + return ret; 17.164 +} 17.165 + 17.166 +int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap) { 17.167 + char buf[UCX_PRINTF_BUFSIZE]; 17.168 +#ifdef va_copy 17.169 + va_list ap2; 17.170 + va_copy(ap2, ap); 17.171 + int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); 17.172 + if (ret < 0) { 17.173 + return ret; 17.174 + } else if (ret < UCX_PRINTF_BUFSIZE) { 17.175 + return (int)wfc(buf, 1, ret, stream); 17.176 + } else { 17.177 + if (ret == INT_MAX) { 17.178 + errno = ENOMEM; 17.179 + return -1; 17.180 + } 17.181 + 17.182 + int len = ret + 1; 17.183 + char *newbuf = (char*)malloc(len); 17.184 + if (!newbuf) { 17.185 + return -1; 17.186 + } 17.187 + 17.188 + ret = vsnprintf(newbuf, len, fmt, ap2); 17.189 + if (ret > 0) { 17.190 + ret = (int)wfc(newbuf, 1, ret, stream); 17.191 + } 17.192 + free(newbuf); 17.193 + } 17.194 + return ret; 17.195 +#else 17.196 + int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); 17.197 + if (ret < 0) { 17.198 + return ret; 17.199 + } else if (ret < UCX_PRINTF_BUFSIZE) { 17.200 + return (int)wfc(buf, 1, ret, stream); 17.201 + } else { 17.202 + errno = ENOMEM; 17.203 + return -1; 17.204 + } 17.205 +#endif 17.206 +} 17.207 + 17.208 +sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...) { 17.209 + va_list ap; 17.210 + sstr_t ret; 17.211 + va_start(ap, fmt); 17.212 + ret = ucx_vasprintf(allocator, fmt, ap); 17.213 + va_end(ap); 17.214 + return ret; 17.215 +} 17.216 + 17.217 +sstr_t ucx_vasprintf(UcxAllocator *a, const char *fmt, va_list ap) { 17.218 + sstr_t s; 17.219 + s.ptr = NULL; 17.220 + s.length = 0; 17.221 + char buf[UCX_PRINTF_BUFSIZE]; 17.222 +#ifdef va_copy 17.223 + va_list ap2; 17.224 + va_copy(ap2, ap); 17.225 + int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); 17.226 + if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { 17.227 + s.ptr = (char*)almalloc(a, ret + 1); 17.228 + if (s.ptr) { 17.229 + s.length = (size_t)ret; 17.230 + memcpy(s.ptr, buf, ret); 17.231 + s.ptr[s.length] = '\0'; 17.232 + } 17.233 + } else if (ret == INT_MAX) { 17.234 + errno = ENOMEM; 17.235 + } else { 17.236 + int len = ret + 1; 17.237 + s.ptr = (char*)almalloc(a, len); 17.238 + if (s.ptr) { 17.239 + ret = vsnprintf(s.ptr, len, fmt, ap2); 17.240 + if (ret < 0) { 17.241 + free(s.ptr); 17.242 + s.ptr = NULL; 17.243 + } else { 17.244 + s.length = (size_t)ret; 17.245 + } 17.246 + } 17.247 + } 17.248 +#else 17.249 + int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); 17.250 + if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { 17.251 + s.ptr = (char*)almalloc(a, ret + 1); 17.252 + if (s.ptr) { 17.253 + s.length = (size_t)ret; 17.254 + memcpy(s.ptr, buf, ret); 17.255 + s.ptr[s.length] = '\0'; 17.256 + } 17.257 + } else { 17.258 + errno = ENOMEM; 17.259 + } 17.260 +#endif 17.261 + return s; 17.262 +}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/src/ucx/utils.h Tue Aug 23 13:49:38 2016 +0200 18.3 @@ -0,0 +1,254 @@ 18.4 +/* 18.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 18.6 + * 18.7 + * Copyright 2015 Olaf Wintermann. All rights reserved. 18.8 + * 18.9 + * Redistribution and use in source and binary forms, with or without 18.10 + * modification, are permitted provided that the following conditions are met: 18.11 + * 18.12 + * 1. Redistributions of source code must retain the above copyright 18.13 + * notice, this list of conditions and the following disclaimer. 18.14 + * 18.15 + * 2. Redistributions in binary form must reproduce the above copyright 18.16 + * notice, this list of conditions and the following disclaimer in the 18.17 + * documentation and/or other materials provided with the distribution. 18.18 + * 18.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 18.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 18.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 18.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 18.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 18.29 + * POSSIBILITY OF SUCH DAMAGE. 18.30 + */ 18.31 + 18.32 +/** 18.33 + * @file utils.h 18.34 + * 18.35 + * Compare, copy and printf functions. 18.36 + * 18.37 + * @author Mike Becker 18.38 + * @author Olaf Wintermann 18.39 + */ 18.40 + 18.41 +#ifndef UCX_UTILS_H 18.42 +#define UCX_UTILS_H 18.43 + 18.44 +#ifdef __cplusplus 18.45 +extern "C" { 18.46 +#endif 18.47 + 18.48 +#include "ucx.h" 18.49 +#include "string.h" 18.50 +#include "allocator.h" 18.51 +#include <inttypes.h> 18.52 +#include <string.h> 18.53 +#include <stdarg.h> 18.54 + 18.55 +/** 18.56 + * Copies a string. 18.57 + * @param s the string to copy 18.58 + * @param data omitted 18.59 + * @return a pointer to a copy of s1 that can be passed to free(void*) 18.60 + */ 18.61 +void *ucx_strcpy(void *s, void *data); 18.62 + 18.63 +/** 18.64 + * Copies a memory area. 18.65 + * @param m a pointer to the memory area 18.66 + * @param n a pointer to the size_t containing the size of the memory area 18.67 + * @return a pointer to a copy of the specified memory area that can 18.68 + * be passed to free(void*) 18.69 + */ 18.70 +void *ucx_memcpy(void *m, void *n); 18.71 + 18.72 + 18.73 +/** 18.74 + * Reads data from a stream and writes it to another stream. 18.75 + * 18.76 + * @param src the source stream 18.77 + * @param dest the destination stream 18.78 + * @param rfnc the read function 18.79 + * @param wfnc the write function 18.80 + * @param buf a pointer to the copy buffer or <code>NULL</code> if a buffer 18.81 + * shall be implicitly created on the heap 18.82 + * @param bufsize the size of the copy buffer - if <code>NULL</code> was 18.83 + * provided for <code>buf</code>, this is the size of the buffer that shall be 18.84 + * implicitly created 18.85 + * @param n the maximum number of bytes that shall be copied 18.86 + * @return the total number of bytes copied 18.87 + */ 18.88 +size_t ucx_stream_copy(void *src, void *dest, read_func rfnc, write_func wfnc, 18.89 + char* buf, size_t bufsize, size_t n); 18.90 + 18.91 +/** 18.92 + * Shorthand for ucx_stream_copy using the default copy buffer. 18.93 + * 18.94 + * @param src the source stream 18.95 + * @param dest the destination stream 18.96 + * @param rfnc the read function 18.97 + * @param wfnc the write function 18.98 + * @return total number of bytes copied 18.99 + */ 18.100 +#define ucx_stream_hcopy(src,dest,rfnc,wfnc) ucx_stream_copy(\ 18.101 + src, dest, (read_func)rfnc, (write_func)wfnc, NULL, 0x100, (size_t)-1) 18.102 + 18.103 +/** 18.104 + * Shorthand for ucx_stream_copy using the default copy buffer and a copy limit. 18.105 + * 18.106 + * @param src the source stream 18.107 + * @param dest the destination stream 18.108 + * @param rfnc the read function 18.109 + * @param wfnc the write function 18.110 + * @param n maximum number of bytes that shall be copied 18.111 + * @return total number of bytes copied 18.112 + */ 18.113 +#define ucx_stream_ncopy(src,dest,rfnc,wfnc, n) ucx_stream_copy(\ 18.114 + src, dest, (read_func)rfnc, (write_func)wfnc, NULL, 0x100, n) 18.115 + 18.116 +/** 18.117 + * Wraps the strcmp function. 18.118 + * @param s1 string one 18.119 + * @param s2 string two 18.120 + * @param data omitted 18.121 + * @return the result of strcmp(s1, s2) 18.122 + */ 18.123 +int ucx_strcmp(void *s1, void *s2, void *data); 18.124 + 18.125 +/** 18.126 + * Wraps the strncmp function. 18.127 + * @param s1 string one 18.128 + * @param s2 string two 18.129 + * @param n a pointer to the size_t containing the third strncmp parameter 18.130 + * @return the result of strncmp(s1, s2, *n) 18.131 + */ 18.132 +int ucx_strncmp(void *s1, void *s2, void *n); 18.133 + 18.134 +/** 18.135 + * Compares two integers of type int. 18.136 + * @param i1 pointer to integer one 18.137 + * @param i2 pointer to integer two 18.138 + * @param data omitted 18.139 + * @return -1, if *i1 is less than *i2, 0 if both are equal, 18.140 + * 1 if *i1 is greater than *i2 18.141 + */ 18.142 +int ucx_intcmp(void *i1, void *i2, void *data); 18.143 + 18.144 +/** 18.145 + * Compares two real numbers of type float. 18.146 + * @param f1 pointer to float one 18.147 + * @param f2 pointer to float two 18.148 + * @param data if provided: a pointer to precision (default: 1e-6f) 18.149 + * @return -1, if *f1 is less than *f2, 0 if both are equal, 18.150 + * 1 if *f1 is greater than *f2 18.151 + */ 18.152 + 18.153 +int ucx_floatcmp(void *f1, void *f2, void *data); 18.154 + 18.155 +/** 18.156 + * Compares two real numbers of type double. 18.157 + * @param d1 pointer to double one 18.158 + * @param d2 pointer to double two 18.159 + * @param data if provided: a pointer to precision (default: 1e-14) 18.160 + * @return -1, if *d1 is less than *d2, 0 if both are equal, 18.161 + * 1 if *d1 is greater than *d2 18.162 + */ 18.163 +int ucx_doublecmp(void *d1, void *d2, void *data); 18.164 + 18.165 +/** 18.166 + * Compares two pointers. 18.167 + * @param ptr1 pointer one 18.168 + * @param ptr2 pointer two 18.169 + * @param data omitted 18.170 + * @return -1 if ptr1 is less than ptr2, 0 if both are equal, 18.171 + * 1 if ptr1 is greater than ptr2 18.172 + */ 18.173 +int ucx_ptrcmp(void *ptr1, void *ptr2, void *data); 18.174 + 18.175 +/** 18.176 + * Compares two memory areas. 18.177 + * @param ptr1 pointer one 18.178 + * @param ptr2 pointer two 18.179 + * @param n a pointer to the size_t containing the third parameter for memcmp 18.180 + * @return the result of memcmp(ptr1, ptr2, *n) 18.181 + */ 18.182 +int ucx_memcmp(void *ptr1, void *ptr2, void *n); 18.183 + 18.184 +/** 18.185 + * A <code>printf()</code> like function which writes the output to a stream by 18.186 + * using a write_func(). 18.187 + * @param stream the stream the data is written to 18.188 + * @param wfc the write function 18.189 + * @param fmt format string 18.190 + * @param ... additional arguments 18.191 + * @return the total number of bytes written 18.192 + */ 18.193 +int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...); 18.194 + 18.195 +/** 18.196 + * <code>va_list</code> version of ucx_fprintf(). 18.197 + * @param stream the stream the data is written to 18.198 + * @param wfc the write function 18.199 + * @param fmt format string 18.200 + * @param ap argument list 18.201 + * @return the total number of bytes written 18.202 + * @see ucx_fprintf() 18.203 + */ 18.204 +int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap); 18.205 + 18.206 +/** 18.207 + * A <code>printf()</code> like function which allocates space for a sstr_t 18.208 + * the result is written to. 18.209 + * 18.210 + * <b>Attention</b>: The sstr_t data is allocated with the allocators 18.211 + * ucx_allocator_malloc() function. So it is implementation dependent, if 18.212 + * the returned sstr_t.ptr pointer must be passed to the allocators 18.213 + * ucx_allocator_free() function manually. 18.214 + * 18.215 + * <b>Note</b>: The sstr_t.ptr of the return value will <i>always</i> be 18.216 + * <code>NULL</code>-terminated. 18.217 + * 18.218 + * @param allocator the UcxAllocator used for allocating the result sstr_t 18.219 + * @param fmt format string 18.220 + * @param ... additional arguments 18.221 + * @return a sstr_t containing the formatted string 18.222 + */ 18.223 +sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...); 18.224 + 18.225 +/** Shortcut for ucx_asprintf() with default allocator. */ 18.226 +#define ucx_sprintf(fmt, ...) \ 18.227 + ucx_asprintf(ucx_default_allocator(), fmt, __VA_ARGS__) 18.228 + 18.229 +/** 18.230 + * <code>va_list</code> version of ucx_asprintf(). 18.231 + * 18.232 + * @param allocator the UcxAllocator used for allocating the result sstr_t 18.233 + * @param fmt format string 18.234 + * @param ap argument list 18.235 + * @return a sstr_t containing the formatted string 18.236 + * @see ucx_asprintf() 18.237 + */ 18.238 +sstr_t ucx_vasprintf(UcxAllocator *allocator, const char *fmt, va_list ap); 18.239 + 18.240 +/** 18.241 + * A <code>printf()</code> like function which writes the output to an 18.242 + * UcxBuffer. 18.243 + * 18.244 + * @param buffer the buffer the data is written to 18.245 + * @param ... format string and additional arguments 18.246 + * @return the total number of bytes written 18.247 + * @see ucx_fprintf() 18.248 + */ 18.249 +#define ucx_bprintf(buffer, ...) ucx_fprintf((UcxBuffer*)buffer, \ 18.250 + (write_func)ucx_buffer_write, __VA_ARGS__) 18.251 + 18.252 +#ifdef __cplusplus 18.253 +} 18.254 +#endif 18.255 + 18.256 +#endif /* UCX_UTILS_H */ 18.257 +