48#define TOU_GET_VERSION() (20240819L)
63#define TOU_DEBUG(...) if (TOU_DBG) { __VA_ARGS__; } else (void)0
69#ifndef TOU_DEBUG_PREFIX
70#define TOU_DEBUG_PREFIX "[:] "
77#define TOU_PRINTD(format, ...) if (TOU_DBG) { fprintf(stdout, TOU_DEBUG_PREFIX format, ##__VA_ARGS__); } else (void)0
85#define _TOU_DEVNULL_FILE "NUL:"
89#define _TOU_DEVNULL_FILE "/dev/null"
102#define nullptr ((void*)0)
106#ifndef TOU_DEFAULT_BLOCKSIZE
107#define TOU_DEFAULT_BLOCKSIZE 4096
111#define TOU_JSON_DATA_VER "1.0"
114#define TOU_XML_DATA_VER "1.0"
129#define TOU_MSTR(s) TOU_STR(s)
136#define TOU_IS_BLANK(c) ((c)==' ' || (c)=='\n' || (c)=='\r' || (c)=='\t')
143#define TOU_ARRSIZE(x) (sizeof(x) / sizeof(x[0]))
155#define TOU_RANDINT(mx, mn) ((int)(((float)rand()/RAND_MAX) * ((mx)-(mn)) + (mn)))
172typedef void* (*tou_func)(
void*);
177typedef void* (*tou_func2)(
void*,
void*);
182typedef void* (*tou_func3)(
void*,
void*,
void*);
197typedef struct tou_llist
202#ifndef TOU_LLIST_SINGLE_ELEM
206#ifndef TOU_LLIST_SINGLE_ELEM
447char*
tou_sfind_n(
const char* str,
const char* kwd,
size_t maxlen);
589#define tou_sisempty(elem, dat) \
591 (elem)->dat == NULL || \
592 tou_strlen(tou_trim_front_pure((elem)->dat)) == 0)
712#define TOU_SILENCE( ... ) \
713 _tou_g_saved_stdout = tou_disable_stdout(); \
715 tou_enable_stdout(_tou_g_saved_stdout);
758#ifndef TOU_LLIST_DAT_ADDR
759#define TOU_LLIST_DAT_ADDR(list, param) ((tou_llist_t**)(&((*(list))->param)))
773#define tou_llist_new(...) ((TOU_DBG ? fprintf(stdout,TOU_DEBUG_PREFIX"Creating new llist :: NULL\n") : (void)0) , NULL)
798#ifndef TOU_LLIST_SINGLE_ELEM
801 char dat1_is_dynalloc
802#ifndef TOU_LLIST_SINGLE_ELEM
803 ,
char dat2_is_dynalloc
838#ifndef TOU_LLIST_SINGLE_ELEM
841 char dat1_is_dynalloc
842#ifndef TOU_LLIST_SINGLE_ELEM
843 ,
char dat2_is_dynalloc
1028#ifndef TOU_LLIST_SINGLE_ELEM
1095#ifndef TOU_LLIST_SINGLE_ELEM
1100#define tou_llist_gather tou_llist_gather_dat1
1117#ifndef tou_llist_print
1118#ifndef TOU_LLIST_SINGLE_ELEM
1120 #define tou_llist_print(llist, dat1_spec, dat2_spec, ...) \
1122 tou_llist_t* copy = tou_llist_get_newest(llist); \
1123 printf("List contents: (%d)\n", tou_llist_len(copy)); \
1125 printf(" |\n "dat1_spec" :: "dat2_spec"\n", copy->dat1, copy->dat2); \
1126 copy = tou_llist_get_older(copy); \
1132 #define tou_llist_print(llist, dat1_spec, ...) \
1134 tou_llist_t* copy = tou_llist_get_newest(llist); \
1135 printf("List contents: (%d)\n", tou_llist_len(copy)); \
1137 printf(" |\n "dat1_spec"\n", copy->dat1); \
1138 copy = tou_llist_get_older(copy); \
1160#ifndef tou_llist_print_tail
1161#ifndef TOU_LLIST_SINGLE_ELEM
1163 #define tou_llist_print_tail(llist, dat1_spec, dat2_spec, ...) \
1165 tou_llist_t* copy = tou_llist_get_oldest(llist); \
1166 printf("List contents: (%d)\n", tou_llist_len(copy)); \
1168 printf(" |\n "dat1_spec" :: "dat2_spec"\n", copy->dat1, copy->dat2); \
1169 copy = tou_llist_get_newer(copy); \
1175 #define tou_llist_print_tail(llist, dat1_spec, ...) \
1177 tou_llist_t* copy = tou_llist_get_oldest(llist); \
1178 printf("List contents: (%d)\n", tou_llist_len(copy)); \
1180 printf(" |\n "dat1_spec"\n", copy->dat1); \
1181 copy = tou_llist_get_newer(copy); \
1330#ifdef TOU_LLIST_SINGLE_ELEM
1331#warning TOU_LLIST_SINGLE_ELEM DEFINED, TOU_INI DISABLED.
1529#ifdef TOU_LLIST_SINGLE_ELEM
1530#warning TOU_LLIST_SINGLE_ELEM DEFINED, PARSERS & CONVERTERS DISABLED.
1590#ifdef TOU_IMPLEMENTATION
1591#if defined(TOU_IMPLEMENTATION_DONE)
1592#pragma error "TOU_IMPLEMENTATION already defined somewhere!"
1595#define TOU_IMPLEMENTATION_DONE
1604size_t tou_strlcpy(
char* dst,
const char* src,
size_t size)
1608 src_len = strlen (src);
1611 size_t dst_len = size - 1;
1612 if (src_len < dst_len)
1614 memcpy (dst, src, dst_len);
1615 dst[dst_len] =
'\0';
1622size_t tou_strlcat(
char* dst,
const char* src,
size_t size)
1624 size_t src_len, dst_len;
1626 src_len = strlen (src);
1627 dst_len = strlen (dst);
1628 if (size > 0 && dst_len < size)
1630 size_t copy_cnt = size - dst_len - 1;
1631 if (src_len < copy_cnt)
1633 memcpy (dst + dst_len, src, copy_cnt);
1634 dst[dst_len + copy_cnt] =
'\0';
1636 return src_len + dst_len;
1651 size_t src_len = strlen(src);
1653 if ((copy = malloc(src_len + 1)) == NULL)
1656 memcpy(copy, src, src_len + 1);
1664 size_t src_len = strlen(src);
1668 size_t copy_len = size;
1669 if (src_len < copy_len)
1671 if ((copy = malloc(copy_len + 1)) == NULL)
1674 memcpy(copy, src, copy_len + 1);
1684 if (*src == (
char)ch)
1702 if (*src == (
char)ch)
1725 if (str == NULL || *str == NULL)
1739 if (str == NULL || *str == NULL)
1742 char* ptr = (*str + strlen(*str) - 1);
1781 char* ptr = (str + strlen(str) - 1);
1797 while (*ptr++ = tolower(*ptr)) ;
1808 while (*ptr++ = toupper(*ptr)) ;
1816 TOU_PRINTD(
"[replace_ch] replacing ('%c'->'%c') \"%s\" => ", oldch, newch, ss);
1828char*
tou_sfind(
const char* src,
const char* kwd)
1835char*
tou_sfind_n(
const char* src,
const char* kwd,
size_t maxlen)
1840 const char* ret_ptr = NULL;
1841 const int kwd_len = strlen(kwd);
1842 const char* kwd_ptr = kwd;
1844 if (kwd_len > maxlen)
1847 while (maxlen + 1 > 0 ){
1848 if (*kwd_ptr ==
'\0') {
1850 ret_ptr = src - kwd_len;
1857 if (*kwd_ptr == *src) {
1867 return (
char*)ret_ptr;
1872char*
tou_sfind_multiple(
const char* str,
const char** kwds,
int n_kwds,
int* found_idx)
1879char*
tou_sfind_multiple_n(
const char* str,
const char** kwds,
int n_kwds,
int* found_idx,
size_t maxlen)
1881 if (str == NULL || kwds == NULL || n_kwds < 1)
1885 if (found_idx) *found_idx = -1;
1889 int kwd_len[n_kwds];
1890 const char* kwd_ptr[n_kwds];
1891 const char* ret_ptr = NULL;
1895 for (
int i = 0; i < n_kwds; i++) {
1896 kwd_ptr[i] = kwds[i];
1900 while (maxlen + 1 > 0 && *str) {
1901 for (
int i = 0; i < n_kwds; i++) {
1903 if (kwd_ptr[i] == NULL)
1905 if (*(kwd_ptr[i]) ==
'\0') {
1907 ret_ptr = str - kwd_len[i];
1910 goto jmp_sfind_multiple_n_break;
1913 if (*(kwd_ptr[i]) == *str) {
1916 kwd_ptr[i] = kwds[i];
1925jmp_sfind_multiple_n_break:
1928 for (
int i = 0; i < n_kwds; i++) {
1929 if (*(kwd_ptr[i]) ==
'\0') {
1930 ret_ptr = str - kwd_len[i];
1936 return (
char*)ret_ptr;
1952 const char* text_ptr = src;
1953 size_t remaining = maxlen - 0;
1955 while ((found =
tou_sfind_multiple_n(text_ptr, kwds, n_kwds, &found_idx, remaining)) != NULL) {
1959 if (cb((
void*)found, (
void*)kwds[found_idx], userdata) == TOU_BREAK) {
1960 TOU_PRINTD(
"[iter_find_multiple_n] breaking early\n");
1964 text_ptr = found +
tou_strlen(kwds[found_idx]);
1965 remaining -= (text_ptr - src);
1980 char* pos_start = str;
1981 char* pos_delim =
tou_sfind(str, delim);
1985 char* buf = malloc(pos_delim-pos_start + 1);
1986 tou_strlcpy(buf, pos_start, pos_delim-pos_start + 1);
1991 pos_start = pos_delim + delim_len;
1992 pos_delim =
tou_sfind(pos_start, delim);
1996 TOU_PRINTD(
"[tou_split] FINAL LEN :: %zu\n", len);
2000 char* buf = malloc(len + 1);
2016 size_t new_size = dst_len + src_len + 1;
2017 dst = realloc(dst, new_size);
2030 char* new_mem = malloc(dst_len + src_len + 1);
2032 memcpy(new_mem, src, src_len);
2033 memcpy(new_mem + src_len, dst, dst_len + 1);
2040char*
tou_sreplace(
char* str,
char* repl_str,
char* with_str)
2047char*
tou_sreplace_n(
char* str,
char* repl_str,
char* with_str,
size_t* len_ptr)
2049 if (!str || !repl_str) {
2050 TOU_PRINTD(
"[tou_sreplace_n] string or replace string NULL\n");
2059 if (len_ptr != NULL) {
2062 if (len == 0 || len > true_len)
2065 char tmp_replaced_ch =
'\0';
2066 if (len < true_len) {
2067 tmp_replaced_ch = str[len];
2071 char* search_ptr = str;
2074 size_t current_size = 0;
2075 const int with_alloc_mult = 4;
2077 size_t copydiff = 0;
2078 char* next_with = NULL;
2080 while ((next_with =
tou_sfind(search_ptr, repl_str)) != NULL)
2082 copydiff = next_with - search_ptr;
2084 if ((tmp_dst = realloc(dst, current_size + copydiff + with_len*with_alloc_mult + 1)) == NULL) {
2085 TOU_PRINTD(
"[tou_sreplace_n] realloc failed (%zu bytes)\n", current_size + copydiff + with_len*with_alloc_mult + 1);
2087 *(dst + current_size) =
'\0';
2092 memcpy(dst + current_size, search_ptr, copydiff);
2093 memcpy(dst + current_size + copydiff, with_str, with_len);
2096 current_size += copydiff + with_len;
2097 search_ptr += copydiff + repl_len;
2102 if ((tmp_dst = realloc(dst, current_size + rest + 1)) == NULL) {
2103 TOU_PRINTD(
"[tou_sreplace_n] last part realloc failed (%zu)\n", current_size + rest + 1);
2109 tmp_dst = dst + current_size;
2111 *(tmp_dst++) = *(search_ptr++);
2113 current_size += rest;
2116 if (tmp_replaced_ch !=
'\0')
2117 str[len] = tmp_replaced_ch;
2120 tmp_dst = realloc(dst, current_size + 1);
2124 *len_ptr = current_size;
2146 if (blocksize < 1 || blocksize > 0xFFFFFF) {
2151 size_t curr_bufsize = 0;
2152 char blockbuf[blocksize];
2153 size_t bytes_read = 0;
2157 memset(blockbuf, 0, blocksize);
2160 size_t cnt = fread(blockbuf, 1, blocksize, fp);
2169 if (cb(blockbuf, (
void*) cnt, userdata) == TOU_BREAK) {
2171 TOU_PRINTD(
"[tou_read_fp_in_blocks] iteration aborted.\n");
2184 char* block = (
char*) blockdata;
2185 size_t size = (size_t) len;
2188 TOU_PRINTD(
"\n[tou_block_store_cb] Block\n=====\n%.*s (...first %d bytes)\n===== (%zu)\n", (size>64)?64:size, block, (size>64)?64:size, size);
2191 char* new_buffer = realloc(data->
buffer, data->
size + size + 1);
2193 TOU_PRINTD(
"[tou_block_store_cb] cannot realloc memory\n");
2196 memcpy(new_buffer + data->
size, block, size);
2197 *(new_buffer + data->
size + size) =
'\0';
2198 data->
buffer = new_buffer;
2200 TOU_PRINTD(
"[tou_block_store_cb] appended block {size=%zu}\n", data->
size);
2204 return (
void*)TOU_CONTINUE;
2211 if (!filename || strlen(filename) == 0 || strcmp(
"stdin", filename) == 0) {
2213 }
else if ((fp = fopen(filename,
"rb")) == NULL) {
2214 TOU_PRINTD(
"[read_file] cannot open '%s' (as \"rb\")\n", filename);
2218 TOU_PRINTD(
"[read_file] reading from: %s\n", (fp==stdin) ?
"STDIN" : filename);
2236 TOU_PRINTD(
"[read_fp] reading from: FILE* %p\n", fp);
2246 *read_len = tmp.
size;
2262 stdout_fd = _dup(1);
2263 FILE* fp_nul = fopen(_TOU_DEVNULL_FILE,
"w");
2264 _dup2(_fileno(fp_nul), 1);
2270 int new = open(_TOU_DEVNULL_FILE, O_WRONLY);
2309#ifndef TOU_LLIST_SINGLE_ELEM
2312 char dat1_is_dynalloc
2313#ifndef TOU_LLIST_SINGLE_ELEM
2314 ,
char dat2_is_dynalloc
2317 if (node_ref == NULL)
2321 tou_llist_t* new_node = malloc(
sizeof(*new_node));
2323 new_node->
prev = NULL;
2324 new_node->
next = NULL;
2326 new_node->
dat1 = dat1;
2328#ifndef TOU_LLIST_SINGLE_ELEM
2329 new_node->
dat2 = dat2;
2334 if (*node_ref == NULL) {
2335 *node_ref = new_node;
2341 if (prev_node->
next == NULL) {
2342 prev_node->
next = new_node;
2343 new_node->
prev = prev_node;
2344 *node_ref = new_node;
2353 new_node->
prev = prev_node;
2354 new_node->
next = previous_next;
2358 prev_node->
next = new_node;
2359 if (previous_next != NULL)
2360 previous_next->
prev = new_node;
2371#ifndef TOU_LLIST_SINGLE_ELEM
2384#ifndef TOU_LLIST_SINGLE_ELEM
2387 char dat1_is_dynalloc,
2388#ifndef TOU_LLIST_SINGLE_ELEM
2389 char dat2_is_dynalloc
2392 if (node_ref == NULL)
2396 tou_llist_t* new_node = malloc(
sizeof(*new_node));
2398 new_node->
prev = NULL;
2399 new_node->
next = NULL;
2401 new_node->
dat1 = dat1;
2403#ifndef TOU_LLIST_SINGLE_ELEM
2404 new_node->
dat2 = dat2;
2410 if (*node_ref == NULL) {
2411 *node_ref = new_node;
2417 if (prev_node->
prev == NULL) {
2418 prev_node->
prev = new_node;
2419 new_node->
next = prev_node;
2427 new_node->
next = prev_node;
2428 new_node->
prev = previous_prev;
2432 prev_node->
prev = new_node;
2433 if (previous_prev != NULL)
2434 previous_prev->
next = new_node;
2443#ifndef TOU_LLIST_SINGLE_ELEM
2456 if (list->
next == NULL) {
2459 while (curr != NULL) {
2462#ifndef TOU_LLIST_SINGLE_ELEM
2473 while (curr != NULL) {
2476#ifndef TOU_LLIST_SINGLE_ELEM
2504 if (!elem)
return NULL;
2523#ifndef TOU_LLIST_SINGLE_ELEM
2534 if (!list)
return NULL;
2546 if (!list)
return NULL;
2572 if (elem == NULL)
return NULL;
2580 if (elem == NULL)
return NULL;
2588 if (elem == NULL)
return NULL;
2596 if (elem == NULL)
return NULL;
2604 return elem == NULL || elem->
next == NULL;
2611 return elem == NULL || elem->
prev == NULL;
2618 if (list == NULL || cb == NULL)
2621 if (list->
next == NULL) {
2643#ifndef TOU_LLIST_SINGLE_ELEM
2652 if (list->
dat1 == dat1)
2654#ifndef TOU_LLIST_SINGLE_ELEM
2655 if (list->
dat2 == dat2)
2667#ifndef TOU_LLIST_SINGLE_ELEM
2672 if (list->
dat1 == dat1)
2693 if (strcmp(list->
dat1, dat1) == 0) {
2699 TOU_PRINTD(
"[llist_find_key] returning NULL\n");
2707 if (list == NULL || cb == NULL)
2711 if ((
size_t) cb(list, userdata) == TOU_BREAK)
2728 if (list->
next == NULL) {
2749 TOU_PRINTD(
"[llist_gather_dat1] received null parameter\n");
2758 TOU_PRINTD(
"[llist_gather_dat1] list has 0 length\n");
2763 if ((gathered = malloc(_len *
sizeof(
void*))) == NULL) {
2764 TOU_PRINTD(
"[llist_gather_dat1] dynamic allocation failed\n");
2768 for (
size_t i = 0; i < _len; i++) {
2769 gathered[i] = list->
dat1;
2780#ifndef TOU_LLIST_SINGLE_ELEM
2784 TOU_PRINTD(
"[llist_gather_dat2] received null parameter\n");
2793 TOU_PRINTD(
"[llist_gather_dat2] list has 0 length\n");
2798 if ((gathered = malloc(_len *
sizeof(
void*))) == NULL) {
2799 TOU_PRINTD(
"[llist_gather_dat2] dynamic allocation failed\n");
2803 for (
size_t i = 0; i < _len; i++) {
2804 gathered[i] = list->
dat2;
2856 if (stack == NULL || *stack == NULL)
2933#ifndef TOU_LLIST_SINGLE_ELEM
2939 TOU_PRINTD(
"ini_parse_fp received empty fp\n");
2944 char line_buf[256+1];
2945 char* line = line_buf;
2948 while (fgets(line, 256+1, fp)) {
2952 if (status == TOU_BREAK) {
2953 TOU_PRINTD(
"Invalid line encountered while parsing (line %zu): %s\n", line_no, line);
2967 TOU_PRINTD(
"ini_parse_buf received empty buffer\n");
2975 const char* nls[] = {
"\r\n",
"\n"};
2984 if (status == TOU_BREAK) {
2985 TOU_PRINTD(
"Invalid line encountered while parsing (line %zu): %s\n", line_no, buf);
2990 buf = pos + strlen(nls[found_idx]);
2997 TOU_PRINTD(
"Invalid line encountered while parsing (line %zu): %s\n", line_no, buf);
3011 if (inicontents == NULL)
3014 return TOU_CONTINUE;
3019 return TOU_CONTINUE;
3025 return TOU_CONTINUE;
3032 size_t line_len = strlen(line);
3039 if (line[line_len - 1] ==
']') {
3040 line[line_len - 1] =
'\0';
3049 TOU_PRINTD(
"Appended section: %s\n", (*inicontents)->dat1);
3050 return TOU_CONTINUE;
3065 int len = strlen(line);
3066 if (line[len - 1] ==
'\n')
3067 line[len - 1] =
'\0';
3073 if (*inicontents == NULL) {
3080 char* val = prop + prop_len;
3092 return TOU_CONTINUE;
3103 section = section->
prev;
3113 if (inicontents == NULL) {
3114 TOU_PRINTD(
"ini_print received empty struct\n");
3120 fprintf(stdout,
"<.INI STRUCTURE>\n");
3121 fprintf(stdout,
" |\n");
3124 props = section->
dat2;
3125 char next_section_ch = (section->
prev == NULL) ?
' ' :
'|';
3126 fprintf(stdout,
" +-> [SECTION] \"%s\"\n", (
char*)section->
dat1);
3128 fprintf(stdout,
" %c |\n", next_section_ch);
3129 fprintf(stdout,
" %c +-> [PROP] \"%s\": \"%s\"\n",
3130 next_section_ch, (
char*)props->
dat1, (
char*)props->
dat2);
3131 props = props->
prev;
3133 fprintf(stdout,
" %c\n", next_section_ch);
3134 section = section->
prev;
3142 if (inicontents == NULL || section_name == NULL) {
3143 TOU_PRINTD(
"ini_get_section received empty params\n");
3149 TOU_PRINTD(
"ini_get_section unable to find given section\n");
3160 if (inicontents == NULL || section_name == NULL || key == NULL) {
3161 TOU_PRINTD(
"ini_get_property received empty params\n");
3167 TOU_PRINTD(
"ini_get_property unable to find given section\n");
3174 TOU_PRINTD(
"ini_get_property unable to find given key\n");
3216 if (inicontents == NULL || *inicontents == NULL || section_name == NULL || key == NULL || new_value == NULL) {
3217 TOU_PRINTD(
"[ini_set] received empty params\n");
3223 TOU_PRINTD(
"[ini_set] section not found, allocating new...\n");
3232 TOU_PRINTD(
"[ini_set] property not found\n");
3246 char* old_value = prop->
dat2;
3247 size_t old_len = strlen(old_value);
3248 size_t new_len = strlen(new_value);
3250 if (new_len > old_len)
3251 old_value = realloc(old_value, new_len + 1);
3254 prop->
dat2 = old_value;
3264 if (inicontents == NULL || fp == NULL) {
3265 TOU_PRINTD(
"[ini_save_fp] received empty params\n");
3271 if (section->
dat1 == NULL) {
3272 TOU_PRINTD(
"[ini_save_fp] Invalid section name encountered\n");
3276 fprintf(fp,
"[%s]", (
char*)section->
dat1);
3278 TOU_PRINTD(
"[ini_save_fp] Error writing to stream\n");
3284 if (prop->
dat1 == NULL || prop->
dat2 == NULL) {
3285 TOU_PRINTD(
"[ini_save_fp] Invalid property data encountered\n");
3288 fprintf(fp,
"\n%s = %s", (
char*)prop->
dat1, (
char*)prop->
dat2);
3293 section = section->
prev;
3303 if (inicontents == NULL || fp == NULL) {
3304 TOU_PRINTD(
"[ini_save_fp_json] received empty params\n");
3311 TOU_PRINTD(
"[ini_save_fp_json] Error writing to stream\n");
3318 if (section->
dat1 == NULL) {
3319 TOU_PRINTD(
"[ini_save_fp_json] Invalid section name encountered\n");
3323 fprintf(fp,
"\n\t\t\"%s\": {", section->
dat1);
3328 if (prop->
dat1 == NULL || prop->
dat2 == NULL) {
3329 TOU_PRINTD(
"[ini_save_fp_json] Invalid property data encountered\n");
3334 fprintf(fp,
"%s\n\t\t\t\"%s\": \"%s\"", (prop==section->
dat2 ?
"":
","), prop->dat1, prop->dat2);
3339 fprintf(fp,
"\n\t\t}%s", (section->
prev==NULL ?
"":
","));
3341 section = section->
prev;
3345 fprintf(fp,
"\n\t}\n}");
3353 if (inicontents == NULL || fp == NULL) {
3354 TOU_PRINTD(
"[ini_save_fp_xml] received empty params\n");
3360 const char* root_tag =
"root";
3361 fprintf(fp,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
3364 TOU_PRINTD(
"[ini_save_fp_xml] Error writing to stream\n");
3369 if (section->
dat1 == NULL) {
3370 TOU_PRINTD(
"[ini_save_fp_xml] Invalid section name encountered\n");
3377 fprintf(fp,
"\n\t<%s len=\"%zu\">", sect_name_tag,
tou_llist_len(prop));
3380 if (prop->
dat1 == NULL || prop->
dat2 == NULL) {
3381 TOU_PRINTD(
"[ini_save_fp_xml] Invalid property data encountered\n");
3387 fprintf(fp,
"\n\t\t<%s>%s</%s>", prop_name_tag, prop->
dat2, prop_name_tag);
3391 fprintf(fp,
"\n\t</%s>", sect_name_tag);
3392 section = section->
prev;
3395 fprintf(fp,
"\n</%s>", root_tag);
3407#ifndef TOU_LLIST_SINGLE_ELEM
3419 size_t psep_len = strlen(param_sep);
3420 size_t kvsep_len = strlen(keyval_sep);
3423 maxlen = strlen(str);
3426 char saved = str[maxlen];
3435 params = params->
prev;
3438 char* trimmed_both = params->
dat1;
3440 size_t both_len = strlen(trimmed_both);
3442 if (strlen(trimmed_both) > 0) {
3446 char* sep =
tou_sfind(trimmed_both, keyval_sep);
3449 char* trimmed_val = sep + kvsep_len;
3454 if (params->
dat2 != NULL)
3457 params->
dat2 = NULL;
3463 size_t trimmed_key_len =
tou_trim_back(&trimmed_both) - trimmed_both;
3464 memmove(params->
dat1, trimmed_both, trimmed_key_len + 1);
3465 params->
dat1 = realloc(params->
dat1, trimmed_key_len + 1);
3472 char prev_was_null = (params->
prev == NULL);
3482 if (!dont) params = params->
prev;
3486 str[maxlen] = saved;
3498 printf(
" \"%s\" : %p\n", params->
dat1, params->
dat2);
#define TOU_PRINTD(format,...)
Debug print, used like printf()
Definition tou.h:77
void * tou_block_store_cb(void *blockdata, void *len, void *userdata)
Appends the given block to the buffer in tou_block_store_struct through realloc().
void tou_enable_stdout(int saved_fd)
Re-enables STDOUT that had been disabled using the saved file descriptor from previous function.
int _tou_g_saved_stdout
Filedescriptor handle local to this compilation unit used with TOU_SILENCE.
Definition tou.h:722
int tou_disable_stdout()
Redirects STDOUT to /dev/null (or NUL: on Windows)
size_t tou_read_fp_in_blocks(FILE *fp, size_t blocksize, tou_func3 cb, void *userdata)
Reads file in blocks, calling user-provided function for each block.
char * tou_read_file(const char *filename, size_t *read_len)
Reads file from filename.
char * tou_read_fp(FILE *fp, size_t *read_len)
Reads from fp.
tou_llist_t * tou_ini_get_section(tou_llist_t *inicontents, const char *section_name)
Returns pointer to the section element matching given 'section_name'.
tou_llist_t * tou_ini_get_property(tou_llist_t *inicontents, const char *section_name, const char *key)
Returns pointer to the property element matching given 'section_name' and 'key'.
int tou_ini_save_fp_xml(tou_llist_t *inicontents, FILE *fp)
Exports .INI structure data as XML to the file stream.
int tou_ini_save_fp_json(tou_llist_t *inicontents, FILE *fp)
Exports .INI structure data as JSON to the file stream.
tou_llist_t * tou_ini_section(tou_llist_t *inicontents, const char *section_name)
Return a pointer to the llist entry of the matching section, or NULL.
void tou_ini_print(tou_llist_t *inicontents)
Prints the contents of the parsed .INI structure to stdout in a structured graphical format.
void * tou_ini_set(tou_llist_t **inicontents, const char *section_name, const char *key, char *new_value)
Sets the contents of 'key' under the given 'section_name' to the specified value, reallocating memory...
tou_llist_t * tou_ini_parse_buffer(char *buf)
Parses given buffer as .INI file and constructs structured data.
void * tou_ini_property(tou_llist_t *section, const char *property_name)
Return the value of the matching property in the given section, or NULL.
void tou_ini_destroy(tou_llist_t *inicontents)
Destroys contents of .INI structure including deallocation of inner structures; assumes head was pass...
int tou_ini_save_fp(tou_llist_t *inicontents, FILE *fp)
Writes .INI structure data to file stream.
tou_llist_t * tou_ini_parse_fp(FILE *fp)
Parses given FILE* as .INI file and constructs structured data.
void * tou_ini_get(tou_llist_t *inicontents, const char *section_name, const char *key)
Returns the contents of 'key' under the given 'section_name'.
int tou_ini_parse_line(tou_llist_t **inicontents, char *line)
Parses a single line as .INI section/property and adds it to structure.
tou_llist_t * tou_llist_remove(tou_llist_t *elem)
Removes an element from llist and deallocates it.
char tou_llist_is_head(tou_llist_t *elem)
Checks if element is head of the list (.next should be NULL)
tou_llist_t * tou_llist_get_newest(tou_llist_t *list)
Returns the element that was added to the list last.
size_t tou_llist_len(tou_llist_t *list)
Goes through the list and returns amount of elements.
tou_llist_t * tou_llist_prepend(tou_llist_t **elem, void *dat1, void *dat2, char dat1_is_dynalloc, char dat2_is_dynalloc)
Prepends a brand new element to the list/given element.
tou_llist_t * tou_llist_find_exact(tou_llist_t *list, void *dat1, void *dat2)
Traverses the list starting from the passed element and tries to find the first matching element by s...
tou_llist_t * tou_llist_pop(tou_llist_t *elem)
Disconnects an element from llist but does not deallocate it.
tou_llist_t * tou_llist_next_older(tou_llist_t **elem)
Updates elem to point to the element added before itself.
tou_llist_t * tou_llist_appendone(tou_llist_t **elem, void *dat1, char dat1_is_dynalloc)
Appends a brand new element to the list/given element which contains only dat1 and if the pointer was...
void ** tou_llist_gather_dat2(tou_llist_t *list, size_t *len)
Constructs a dynamically allocated ARRAY containing only .dat2 properties (stored as void*).
tou_llist_t * tou_llist_get_newer(tou_llist_t *elem)
Returns the element added after elem.
void ** tou_llist_gather_dat1(tou_llist_t *list, size_t *len)
Constructs a dynamically allocated ARRAY containing only .dat1 properties (stored as void*).
tou_llist_t * tou_llist_find_key(tou_llist_t *list, void *dat1)
Traverses the list starting from the passed element and tries to find the first matching element on t...
void tou_llist_free_element(tou_llist_t *elem)
Frees an element and its contents.
tou_llist_t * tou_llist_append(tou_llist_t **elem, void *dat1, void *dat2, char dat1_is_dynalloc, char dat2_is_dynalloc)
Appends a brand new element to the list/given element and updates it in place.
tou_llist_t * tou_llist_next_newer(tou_llist_t **elem)
Updates elem to point to the element added after itself.
tou_llist_t * tou_llist_find_func(tou_llist_t *list, tou_func2 cb, void *userdata)
Traverses the list starting from the passed element and tries to find the first matching element by c...
tou_llist_t * tou_llist_get_tail(tou_llist_t *list)
Traverses the whole list using .prev and returns the first element that was added to list (where ....
tou_llist_t * tou_llist_prependone(tou_llist_t **elem, void *dat1, char dat1_is_dynalloc)
Prepends a brand new element to the list/given element which only contains dat1.
#define tou_llist_new(...)
Creates/initializes new llist.
Definition tou.h:773
void tou_llist_iter(tou_llist_t *list, tou_func cb)
Iterate through and call the specified function for each element Automatically checks whether given e...
tou_llist_t * tou_llist_find_exactone(tou_llist_t *list, void *dat1)
Traverses the list starting from the passed element and tries to find the first matching element by s...
void tou_llist_destroy(tou_llist_t *list)
Traverses elements using .next or .prev and frees each one including copied category string.
tou_llist_t * tou_llist_get_head(tou_llist_t *list)
Traverses the whole list using .next and returns the last element that was added into list (where ....
tou_llist_t * tou_llist_get_oldest(tou_llist_t *list)
Returns the element that was added to the list first.
tou_llist_t * tou_llist_get_older(tou_llist_t *elem)
Returns the element added before elem.
char tou_llist_is_tail(tou_llist_t *elem)
Checks if element is tail of the list (.prev should be NULL)
tou_llist_t * tou_paramparse(char *str, const char *param_sep, const char *keyval_sep)
Parses "parameter string" and returns a llist of key-value pairs, looking at the whole string (strlen...
void tou_paramprint(tou_llist_t *params)
Attempts to print "params" parsed by tou_paramparse or tou_paramparse_n.
tou_llist_t * tou_paramparse_n(char *str, const char *param_sep, const char *keyval_sep, size_t maxlen)
Parses "parameter string" and returns a llist of key-value pairs.
size_t tou_queue_len(tou_llist_t *queue)
Returns the length of the queue.
void * tou_queue_pop(tou_llist_t **queue)
Pops an element from the top of the Queue.
tou_llist_t tou_queue
Make a queue alias for convenience.
Definition tou.h:1250
void tou_queue_destroy(tou_llist_t *queue)
Destroys existing queue object.
tou_llist_t * tou_queue_new()
Creates a new queue object.
void tou_queue_push(tou_llist_t **queue, void *elem)
Pushes a new element to the top of the Queue.
void * tou_stack_pop(tou_llist_t **stack)
Pops an element from the top of the stack.
void tou_stack_destroy(tou_llist_t *stack)
Destroys existing stack object.
tou_llist_t tou_stack
Make a stack alias for convenience.
Definition tou.h:1199
tou_llist_t * tou_stack_new()
Creates a new stack object.
void tou_stack_push(tou_llist_t **stack, void *elem)
Pushes a new element to the top of the stack.
size_t tou_stack_len(tou_llist_t *stack)
Returns the length of the stack.
char * tou_trim_back(char **str)
Trims whitespaces only from the back of the string.
char * tou_sprepend(char *dst, char *src)
(Re)allocates enough memory for src and prepends it to dst
void tou_sfind_iter_multiple_n(const char *src, const char *kwds[], int n_kwds, tou_func3 cb, void *userdata, size_t maxlen)
Iteratively finds occurences of strings in kwds and calls user function for each one,...
char * tou_sreplace(char *str, char *repl_str, char *with_str)
Helper for tou_sreplace that takes the whole string into consideration.
void tou_trim_string_pure(char *str, char **start, char **end)
Returns pointers to the first and last character that are not whitespaces.
char * tou_strchr(const char *src, int ch)
Finds the first occurence of ch in the string and returns pointer to it, or NULL if not found.
char * tou_trim_front(char **str)
Trims whitespaces only from the front of the string.
char * tou_strdup(const char *src)
Strdup implementation; returns a malloc'd copy of the string.
char * tou_strrchr(const char *src, int ch)
Finds the last occurence of ch in the string and returns pointer to it, or NULL if not found.
char * tou_sfind_multiple_n(const char *str, const char **kwds, int n_kwds, int *found_idx, size_t maxlen)
Like tou_sfind_n but searches for more than one string at a time.
char * tou_sfind_multiple(const char *str, const char **kwds, int n_kwds, int *found_idx)
Like tou_sfind but searches for more than one string at a time.
char * tou_trim_string(char **str)
Trims whitespaces from front and back of the string.
char * tou_trim_back_pure(char *str)
Returns pointer to the first byte AFTER the contents of the string, or the NUL byte.
char * tou_trim_front_pure(char *str)
Returns pointer to the first character from the front that isn't a whitespace.
char * tou_replace_ch(char *ss, char oldch, char newch)
Replaces all occurences of oldch with newch
char * tou_sappend(char *dst, char *src)
(Re)allocates enough memory for src and appends it to dst
size_t tou_strlcpy(char *dst, const char *src, size_t size)
Copies string SRC to DST, always places terminator.
char * tou_sreplace_n(char *str, char *repl_str, char *with_str, size_t *len_ptr)
Replaces string repl_str with with_str in the str, testing str up to the character *len_ptr.
tou_llist_t * tou_split(char *str, const char *delim)
Splits string using a delimiter that may be longer than one character.
size_t tou_strlen(const char *str)
Same as strlen() but checks for null pointer.
size_t tou_strlcat(char *dst, const char *src, size_t size)
Concatenates string SRC to DST, always places terminator.
char * tou_sfind_n(const char *str, const char *kwd, size_t maxlen)
Finds start of substring(keyword) in the given char*, looking at a max of maxlen characters.
char * tou_strndup(const char *src, size_t size)
Returns a newly allocated copy of a string, capped at 'size' length (not including '\0'),...
void tou_sfind_iter_multiple(const char *src, const char *kwds[], int n_kwds, tou_func3 cb, void *userdata)
Iteratively finds occurences of strings in kwds and calls user function for each one.
char * tou_sfind(const char *str, const char *kwd)
Finds start of substring(keyword) in the given char*.
char * tou_slower(char *str)
Converts all characters in str to lowercase in-place.
char * tou_supper(char *str)
Converts all characters in str to uppercase in-place.
tou_iter_action
Can be used while iterating to indicate user wishing to abort or continue as normal.
Definition tou.h:161
void *(* tou_func)(void *)
Arbitrary function pointer with 1 parameter.
Definition tou.h:172
#define TOU_JSON_DATA_VER
Data format version when exporting INI to JSON.
Definition tou.h:111
void *(* tou_func2)(void *, void *)
Arbitrary function pointer with 2 parameters.
Definition tou.h:177
#define TOU_MSTR(s)
Helps convert 's' into C literal.
Definition tou.h:129
#define TOU_DEFAULT_BLOCKSIZE
How many bytes to read when reading a file if unspecified.
Definition tou.h:107
void *(* tou_func3)(void *, void *, void *)
Arbitrary function pointer with 3 parameters.
Definition tou.h:182
#define TOU_XML_DATA_VER
Data format version when exporting INI to JSON.
Definition tou.h:114
#define TOU_IS_BLANK(c)
Is character a whitespace char?
Definition tou.h:136
Struct containing buffer and count to be used in block-reading.
Definition tou.h:636
char * buffer
Buffer to append data to.
Definition tou.h:637
size_t size
Length of the buffer contents.
Definition tou.h:638
Linked list struct definition, typedef'd.
Definition tou.h:198
char destroy_dat1
automatically deallocate this data ?
Definition tou.h:205
void * dat2
useful data
Definition tou.h:203
struct tou_llist * next
next element
Definition tou.h:200
char destroy_dat2
automatically deallocate this data ?
Definition tou.h:207
void * dat1
useful data
Definition tou.h:201
struct tou_llist * prev
previous element
Definition tou.h:199
struct tou_llist tou_llist_elem
Make an element alias for convenience.
Definition tou.h:212