From b70d9ca086c7a2a8dd3536a396d846a074ea9c02 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 20 Oct 2020 23:15:32 +0200 Subject: Added cfmt.h and some smaller fixes. --- stc/carray.h | 12 ++--- stc/ccommon.h | 8 ++-- stc/cfmt.h | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ stc/clist.h | 2 +- stc/cmap.h | 2 +- stc/cstr.h | 58 ++++++++++++++-------- stc/cvec.h | 8 ++-- 7 files changed, 206 insertions(+), 36 deletions(-) create mode 100644 stc/cfmt.h diff --git a/stc/carray.h b/stc/carray.h index 5df7add8..5ff95513 100644 --- a/stc/carray.h +++ b/stc/carray.h @@ -143,18 +143,18 @@ _carray3_size(const size_t* zdim) {return zdim[0] * zdim[-1] * zdim[-2];} } \ \ STC_INLINE carray1##X \ - carray1##X##_from(Value* array, bool own, size_t xdim) { \ - carray1##X a = {array, xdim | (own ? _carray_OWN : 0)}; \ + carray1##X##_from(Value* array, size_t xdim) { \ + carray1##X a = {array, xdim}; \ return a; \ } \ STC_INLINE carray2##X \ - carray2##X##_from(Value* array, bool own, size_t ydim, size_t xdim) { \ - carray2##X a = {array, xdim | (own ? _carray_OWN : 0), ydim}; \ + carray2##X##_from(Value* array, size_t ydim, size_t xdim) { \ + carray2##X a = {array, xdim, ydim}; \ return a; \ } \ STC_INLINE carray3##X \ - carray3##X##_from(Value* array, bool own, size_t zdim, size_t ydim, size_t xdim) { \ - carray3##X a = {array, xdim | (own ? _carray_OWN : 0), ydim, zdim}; \ + carray3##X##_from(Value* array, size_t zdim, size_t ydim, size_t xdim) { \ + carray3##X a = {array, xdim, ydim, zdim}; \ return a; \ } \ \ diff --git a/stc/ccommon.h b/stc/ccommon.h index 65c4b41a..5b35459b 100644 --- a/stc/ccommon.h +++ b/stc/ccommon.h @@ -23,6 +23,8 @@ #ifndef CCOMMON__H__ #define CCOMMON__H__ +#define __USE_MINGW_ANSI_STDIO 1 + #include #include #include @@ -52,8 +54,8 @@ /* Macro overloading feature support: https://rextester.com/ONP80107 */ #define _c_CAT( A, B ) A ## B #define _c_EXPAND(...) __VA_ARGS__ -#define _c_ARG_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, N,...) N -#define _c_RSEQ_N 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +#define _c_ARG_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, N,...) N +#define _c_RSEQ_N 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 #define _c_APPLY_ARG_N(ARGS) _c_EXPAND(_c_ARG_N ARGS) #define _c_VA_ARG_SIZE(...) _c_EXPAND(_c_APPLY_ARG_N((__VA_ARGS__, _c_RSEQ_N))) #define _c_OVERLOAD_SELECT(NAME, NUM) _c_CAT( NAME ## _, NUM) @@ -101,7 +103,7 @@ #define c_break_with continue #define c_withfile(f, open) for (FILE *f = open; f; fclose(f), f = NULL) -#define c_withbuffer(type, b, n) c_withbuffer_x(type, b, n, 512) +#define c_withbuffer(type, b, n) c_withbuffer_x(type, b, n, 256) #define c_withbuffer_x(type, b, n, BYTES) \ for (type __b[((BYTES) - 1) / sizeof(type) + 1], \ *b = (n) * sizeof *b > (BYTES) ? c_new_2(type, n) : __b; \ diff --git a/stc/cfmt.h b/stc/cfmt.h new file mode 100644 index 00000000..d0d86026 --- /dev/null +++ b/stc/cfmt.h @@ -0,0 +1,152 @@ +/* MIT License + * + * Copyright (c) 2020 Tyge Løvset, NORCE, www.norceresearch.no + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef CFMT__H__ +#define CFMT__H__ + +#include + +// https://gist.github.com/alexameen/6550d892338626964a870e408d1e8912 +// https://gist.github.com/alexameen/4440e4bcad557a464dcc9ff884763049 + +#define _cfmt_fn(x) _Generic ((x), \ + FILE*: fprintf, \ + int: _cfmt_printf, \ + char *: sprintf, \ + cstr_t *: cstr_fmt) + +#define _cfmt(x) _Generic ((x), \ + char: "c", \ + unsigned char: "hhu", \ + short: "hd", \ + unsigned short: "hu", \ + int: "d", \ + unsigned int: "u", \ + long int: "ld", \ + unsigned long int: "lu", \ + long long int: "lld", \ + unsigned long long int: "llu", \ + float: "g", \ + double: "g", \ + long double: "Lg", \ + char *: "s", \ + void *: "p") + + +#define c_print(...) c_MACRO_OVERLOAD(c_print, __VA_ARGS__) +#define c_print_3(to, fmt, c) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c)); \ + _cfmt_fn(to)(to, _fm, c); free(_fm); } while (0) +#define c_print_4(to, fmt, c, d) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d)); \ + _cfmt_fn(to)(to, _fm, c, d); free(_fm); } while (0) +#define c_print_5(to, fmt, c, d, e) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e)); \ + _cfmt_fn(to)(to, _fm, c, d, e); free(_fm); } while (0) +#define c_print_6(to, fmt, c, d, e, f) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e), _cfmt(f)); \ + _cfmt_fn(to)(to, _fm, c, d, e, f); free(_fm); } while (0) +#define c_print_7(to, fmt, c, d, e, f, g) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e), _cfmt(f), _cfmt(g)); \ + _cfmt_fn(to)(to, _fm, c, d, e, f, g); free(_fm); } while (0) +#define c_print_8(to, fmt, c, d, e, f, g, h) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e), _cfmt(f), _cfmt(g), _cfmt(h)); \ + _cfmt_fn(to)(to, _fm, c, d, e, f, g, h); free(_fm); } while (0) +#define c_print_9(to, fmt, c, d, e, f, g, h, i) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e), _cfmt(f), _cfmt(g), _cfmt(h), _cfmt(i)); \ + _cfmt_fn(to)(to, _fm, c, d, e, f, g, h, i); free(_fm); } while (0) +#define c_print_10(to, fmt, c, d, e, f, g, h, i, j) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e), _cfmt(f), _cfmt(g), _cfmt(h), _cfmt(i), _cfmt(j)); \ + _cfmt_fn(to)(to, _fm, c, d, e, f, g, h, i, j); free(_fm); } while (0) +#define c_print_11(to, fmt, c, d, e, f, g, h, i, j, k) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e), _cfmt(f), _cfmt(g), _cfmt(h), _cfmt(i), _cfmt(j), _cfmt(k)); \ + _cfmt_fn(to)(to, _fm, c, d, e, f, g, h, i, j, k); free(_fm); } while (0) +#define c_print_12(to, fmt, c, d, e, f, g, h, i, j, k, m) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e), _cfmt(f), _cfmt(g), _cfmt(h), _cfmt(i), _cfmt(j), _cfmt(k), _cfmt(m)); \ + _cfmt_fn(to)(to, _fm, c, d, e, f, g, h, i, j, k, m); free(_fm); } while (0) +#define c_print_13(to, fmt, c, d, e, f, g, h, i, j, k, m, n) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e), _cfmt(f), _cfmt(g), _cfmt(h), _cfmt(i), _cfmt(j), _cfmt(k), _cfmt(m), _cfmt(n)); \ + _cfmt_fn(to)(to, _fm, c, d, e, f, g, h, i, j, k, m, n); free(_fm); } while (0) +#define c_print_14(to, fmt, c, d, e, f, g, h, i, j, k, m, n, o) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e), _cfmt(f), _cfmt(g), _cfmt(h), _cfmt(i), _cfmt(j), _cfmt(k), _cfmt(m), _cfmt(n), _cfmt(o)); \ + _cfmt_fn(to)(to, _fm, c, d, e, f, g, h, i, j, k, m, n, o); free(_fm); } while (0) +#define c_print_15(to, fmt, c, d, e, f, g, h, i, j, k, m, n, o, p) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e), _cfmt(f), _cfmt(g), _cfmt(h), _cfmt(i), _cfmt(j), _cfmt(k), _cfmt(m), _cfmt(n), _cfmt(o), _cfmt(p)); \ + _cfmt_fn(to)(to, _fm, c, d, e, f, g, h, i, j, k, m, n, o, p); free(_fm); } while (0) +#define c_print_16(to, fmt, c, d, e, f, g, h, i, j, k, m, n, o, p, q) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e), _cfmt(f), _cfmt(g), _cfmt(h), _cfmt(i), _cfmt(j), _cfmt(k), _cfmt(m), _cfmt(n), _cfmt(o), _cfmt(p), _cfmt(p)); \ + _cfmt_fn(to)(to, _fm, c, d, e, f, g, h, i, j, k, m, n, o, p, q); free(_fm); } while (0) +#define c_print_17(to, fmt, c, d, e, f, g, h, i, j, k, m, n, o, p, q, r) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e), _cfmt(f), _cfmt(g), _cfmt(h), _cfmt(i), _cfmt(j), _cfmt(k), _cfmt(m), _cfmt(n), _cfmt(o), _cfmt(p), _cfmt(p), _cfmt(r)); \ + _cfmt_fn(to)(to, _fm, c, d, e, f, g, h, i, j, k, m, n, o, p, q, r); free(_fm); } while (0) +#define c_print_18(to, fmt, c, d, e, f, g, h, i, j, k, m, n, o, p, q, r, s) \ + do { char *_fm = _cfmt_conv(fmt, _cfmt(c), _cfmt(d), _cfmt(e), _cfmt(f), _cfmt(g), _cfmt(h), _cfmt(i), _cfmt(j), _cfmt(k), _cfmt(m), _cfmt(n), _cfmt(o), _cfmt(p), _cfmt(p), _cfmt(r), _cfmt(s)); \ + _cfmt_fn(to)(to, _fm, c, d, e, f, g, h, i, j, k, m, n, o, p, q, r, s); free(_fm); } while (0) + +STC_API char * +_cfmt_conv(const char *fmt, ...); +STC_INLINE void +_cfmt_printf(int s, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + vfprintf(s ? stderr : stdout, fmt, args); + va_end(args); +} + +#if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) + +#include +#include + +STC_DEF char * +_cfmt_conv(const char *fmt, ...) { + char *fmt2 = strcpy((char *) malloc(strlen(fmt) * 2), fmt), *p = fmt2, *f, ch; + va_list args; + va_start(args, fmt); + do { + switch ((ch = *fmt)) { + case '}': + if (fmt[1] == '}') ++fmt; + break; + case '{': + if (fmt[1] == '{') { ++fmt; break; } + if (fmt[1] == ':' || fmt[1] == '}') { + *p++ = '%'; + fmt += 1 + (fmt[1] == ':'); + while (*fmt != '}' && *fmt) *p++ = *fmt++; + f = va_arg(args, char *); + if (!strchr("csdioxXufFeEaAgGnp", fmt[-1])) + while (*f) *p++ = *f++; + fmt += (*fmt == '}'); + continue; + } + break; + } + *p++ = *fmt++; + } while (ch); + va_end(args); + return fmt2; +} + +#endif + +#endif \ No newline at end of file diff --git a/stc/clist.h b/stc/clist.h index 3b4a3642..a9b363a0 100644 --- a/stc/clist.h +++ b/stc/clist.h @@ -23,8 +23,8 @@ #ifndef CLIST__H__ #define CLIST__H__ -#include #include "ccommon.h" +#include /* Circular Singly-linked Lists. diff --git a/stc/cmap.h b/stc/cmap.h index ed1511f7..87bc62cd 100644 --- a/stc/cmap.h +++ b/stc/cmap.h @@ -49,9 +49,9 @@ int main(void) { #ifndef CMAP__H__ #define CMAP__H__ +#include "ccommon.h" #include #include -#include "ccommon.h" #define cmap_INIT {NULL, NULL, 0, 0, 0.85f, 0.15f} #define cmap_empty(m) ((m).size == 0) diff --git a/stc/cstr.h b/stc/cstr.h index 07164ebe..1e8a62dd 100644 --- a/stc/cstr.h +++ b/stc/cstr.h @@ -23,11 +23,11 @@ #ifndef CSTR__H__ #define CSTR__H__ +#include "ccommon.h" #include /* malloc */ #include #include #include /* vsnprintf */ -#include "ccommon.h" typedef struct cstr { char* str; } cstr_t; typedef struct { char *val; } cstr_iter_t; @@ -44,6 +44,8 @@ STC_API cstr_t cstr_from_n(const char* str, size_t len); STC_API cstr_t cstr_from_fmt(const char* fmt, ...); +STC_API void +cstr_fmt(cstr_t* self, const char* fmt, ...); STC_API size_t cstr_reserve(cstr_t* self, size_t cap); STC_API void @@ -242,41 +244,55 @@ STC_DEF cstr_t cstr_from_n(const char* str, size_t len) { if (len == 0) return cstr_init(); size_t *rep = (size_t *) c_malloc(_cstr_mem(len)); - cstr_t s = {(char *) memcpy(rep + 2, str, len)}; + cstr_t s = {strncpy((char *)(rep + 2), str, len)}; s.str[rep[0] = len] = '\0'; rep[1] = _cstr_cap(len); return s; } +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable: 4996) +#endif + STC_DEF cstr_t cstr_from_fmt(const char* fmt, ...) { - #if defined(__clang__) - # pragma clang diagnostic push - # pragma clang diagnostic ignored "-Wdeprecated-declarations" - #elif defined(_MSC_VER) - # pragma warning(push) - # pragma warning(disable: 4996) - #endif - cstr_t tmp = cstr_init(); + cstr_t ret = cstr_init(); va_list args, args2; va_start(args, fmt); va_copy(args2, args); int len = vsnprintf(NULL, (size_t)0, fmt, args); va_end(args); - if (len > 0) { - tmp = cstr_with_capacity(len); - vsprintf(tmp.str, fmt, args2); - _cstr_size(tmp) = len; - } + cstr_reserve(&ret, len); + vsprintf(ret.str, fmt, args2); va_end(args2); - return tmp; - #if defined(__clang__) - # pragma clang diagnostic pop - #elif defined(_MSC_VER) - # pragma warning(pop) - #endif + _cstr_size(ret) = len; + return ret; +} + +STC_DEF void +cstr_fmt(cstr_t* self, const char* fmt, ...) { + va_list args, args2; + va_start(args, fmt); + va_copy(args2, args); + int len = vsnprintf(NULL, (size_t)0, fmt, args); + va_end(args); + cstr_reserve(self, len); + vsprintf(self->str, fmt, args2); + va_end(args2); + _cstr_size(*self) = len; } +#if defined(__clang__) +# pragma clang diagnostic pop +#elif defined(_MSC_VER) +# pragma warning(pop) +#endif + + STC_DEF cstr_t* cstr_assign_n(cstr_t* self, const char* str, size_t len) { if (len || cstr_capacity(*self)) { diff --git a/stc/cvec.h b/stc/cvec.h index dcd44294..ea535c84 100644 --- a/stc/cvec.h +++ b/stc/cvec.h @@ -23,9 +23,9 @@ #ifndef CVEC__H__ #define CVEC__H__ +#include "ccommon.h" #include #include -#include "ccommon.h" #define cvec_INIT {NULL} #define cvec_size(v) _cvec_safe_size((v).data) @@ -102,7 +102,7 @@ } \ \ STC_API cvec_##X##_iter_t \ - cvec_##X##_insert_range_p(cvec_##X* self, cvec_##X##_value_t* pos, cvec_##X##_value_t* pfirst, cvec_##X##_value_t* pfinish); \ + cvec_##X##_insert_range_p(cvec_##X* self, cvec_##X##_value_t* pos, const cvec_##X##_value_t* pfirst, const cvec_##X##_value_t* pfinish); \ \ STC_INLINE cvec_##X##_iter_t \ cvec_##X##_insert_range(cvec_##X* self, cvec_##X##_iter_t pos, cvec_##X##_iter_t first, cvec_##X##_iter_t finish) { \ @@ -187,7 +187,7 @@ cvec_##X##_idx(cvec_##X v, cvec_##X##_iter_t it) {return it.val - v.data;} \ \ _c_implement_cvec_7(X, Value, valueDestroy, RawValue, valueCompareRaw, valueToRaw, valueFromRaw) \ - typedef cvec_##X cvec_##X##_t + typedef cvec_##X cvec_##X##_t /* -------------------------- IMPLEMENTATION ------------------------- */ @@ -240,7 +240,7 @@ } \ \ STC_DEF cvec_##X##_iter_t \ - cvec_##X##_insert_range_p(cvec_##X* self, cvec_##X##_value_t* pos, cvec_##X##_value_t* first, cvec_##X##_value_t* finish) { \ + cvec_##X##_insert_range_p(cvec_##X* self, cvec_##X##_value_t* pos, const cvec_##X##_value_t* first, const cvec_##X##_value_t* finish) { \ size_t len = finish - first, idx = pos - self->data, size = cvec_size(*self); \ c_withbuffer (cvec_##X##_value_t, buf, len) { \ for (size_t i=0; i