From a8e178e11e4955306d32e4c48be348d50dbcb3df Mon Sep 17 00:00:00 2001 From: Tyge Løvset <60263450+tylo-work@users.noreply.github.com> Date: Sun, 29 Mar 2020 20:19:34 +0200 Subject: Add files via upload --- c_lib/cdefs.h | 13 +++-- c_lib/cgetopt.h | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ c_lib/cmap.h | 19 +++---- c_lib/cstring.h | 12 ++--- c_lib/cvector.h | 9 +--- 5 files changed, 172 insertions(+), 31 deletions(-) create mode 100644 c_lib/cgetopt.h diff --git a/c_lib/cdefs.h b/c_lib/cdefs.h index 54244d40..8c657d96 100644 --- a/c_lib/cdefs.h +++ b/c_lib/cdefs.h @@ -36,10 +36,13 @@ #define c_OVERLOAD_SELECT(NAME, NUM) c_CAT( NAME ## _, NUM) #define c_MACRO_OVERLOAD(NAME, ...) c_OVERLOAD_SELECT(NAME, c_VA_ARG_SIZE(__VA_ARGS__))(__VA_ARGS__) -// #define foo(...) c_MACRO_OVERLOAD(foo, __VA_ARGS__) -// #define foo_1(X) foo_2(X, 100) -// #define foo_2(X, Y) X + Y + +#define c_new(...) c_MACRO_OVERLOAD(c_new, __VA_ARGS__) +#define c_new_1(T) ((T *) malloc(sizeof(T))) +#define c_new_2(T, n) ((T *) malloc(sizeof(T) * (n))) + +#define c_struct(S) typedef struct S S; struct S #define c_npos ((size_t) -1) #define c_max_alloca (1000) #define c_swap(T, x, y) { T __t = x; x = y; y = __t; } @@ -65,9 +68,5 @@ static inline uint32_t c_defaultHash(const void *data, size_t len) { return h; } -// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ -static inline uint32_t c_reduce(uint32_t x, uint32_t N) { - return ((uint64_t) x * (uint64_t) N) >> 32 ; -} #endif diff --git a/c_lib/cgetopt.h b/c_lib/cgetopt.h new file mode 100644 index 00000000..58917fc8 --- /dev/null +++ b/c_lib/cgetopt.h @@ -0,0 +1,150 @@ +#ifndef CGETOPT_H +#define CGETOPT_H + +#include + +enum { + c_optarg_none = 0, + c_optarg_required = 1, + c_optarg_optional = 2 +}; +typedef struct { + int ind; /* equivalent to optind */ + int opt; /* equivalent to optopt */ + char *arg; /* equivalent to optarg */ + int longidx; /* index of a long option; or -1 if short */ + /* private variables not intended for external uses */ + int i, pos, n_args; +} c_getopt_t; + +typedef struct { + char *name; + int has_arg; + int val; +} c_longopt_t; + +static const c_getopt_t c_getopt_init = {1, 0, 0, -1, 1, 0, 0}; + +static void c_getopt_permute(char *argv[], int j, int n) /* move argv[j] over n elements to the left */ +{ + int k; + char *p = argv[j]; + for (k = 0; k < n; ++k) + argv[j - k] = argv[j - k - 1]; + argv[j - k] = p; +} + +/** + * Parse command-line options and arguments + * + * This fuction has a similar interface to GNU's getopt_long(). Each call + * parses one option and returns the option name. s->arg points to the option + * argument if present. The function returns -1 when all command-line arguments + * are parsed. In this case, s->ind is the index of the first non-option + * argument. + * + * @param s status; shall be initialized to c_getopt_init on the first call + * @param argc length of argv[] + * @param argv list of command-line arguments; argv[0] is ignored + * @param permute non-zero to move options ahead of non-option arguments + * @param ostr option string + * @param longopts long options + * + * @return ASCII for a short option; c_longopt_t::val for a long option; -1 if + * argv[] is fully processed; '?' for an unknown option or an ambiguous + * long option; ':' if an option argument is missing + */ +static int c_getopt(c_getopt_t *s, int argc, char *argv[], int permute, const char *ostr, const c_longopt_t *longopts) +{ + int opt = -1, i0, j; + if (permute) { + while (s->i < argc && (argv[s->i][0] != '-' || argv[s->i][1] == '\0')) + ++s->i, ++s->n_args; + } + s->arg = 0, s->longidx = -1, i0 = s->i; + if (s->i >= argc || argv[s->i][0] != '-' || argv[s->i][1] == '\0') { + s->ind = s->i - s->n_args; + return -1; + } + if (argv[s->i][0] == '-' && argv[s->i][1] == '-') { /* "--" or a long option */ + if (argv[s->i][2] == '\0') { /* a bare "--" */ + c_getopt_permute(argv, s->i, s->n_args); + ++s->i, s->ind = s->i - s->n_args; + return -1; + } + s->opt = 0, opt = '?', s->pos = -1; + if (longopts) { /* parse long options */ + int k, n_exact = 0, n_partial = 0; + const c_longopt_t *o = 0, *o_exact = 0, *o_partial = 0; + for (j = 2; argv[s->i][j] != '\0' && argv[s->i][j] != '='; ++j) {} /* find the end of the option name */ + for (k = 0; longopts[k].name != 0; ++k) + if (strncmp(&argv[s->i][2], longopts[k].name, j - 2) == 0) { + if (longopts[k].name[j - 2] == 0) ++n_exact, o_exact = &longopts[k]; + else ++n_partial, o_partial = &longopts[k]; + } + if (n_exact > 1 || (n_exact == 0 && n_partial > 1)) return '?'; + o = n_exact == 1? o_exact : n_partial == 1? o_partial : 0; + if (o) { + s->opt = opt = o->val, s->longidx = o - longopts; + if (argv[s->i][j] == '=') s->arg = &argv[s->i][j + 1]; + if (o->has_arg == 1 && argv[s->i][j] == '\0') { + if (s->i < argc - 1) s->arg = argv[++s->i]; + else opt = ':'; /* missing option argument */ + } + } + } + } else { /* a short option */ + const char *p; + if (s->pos == 0) s->pos = 1; + opt = s->opt = argv[s->i][s->pos++]; + p = strchr((char*)ostr, opt); + if (p == 0) { + opt = '?'; /* unknown option */ + } else if (p[1] == ':') { + if (argv[s->i][s->pos] == 0) { + if (s->i < argc - 1) s->arg = argv[++s->i]; + else opt = ':'; /* missing option argument */ + } else s->arg = &argv[s->i][s->pos]; + s->pos = -1; + } + } + if (s->pos < 0 || argv[s->i][s->pos] == 0) { + ++s->i, s->pos = 0; + if (s->n_args > 0) /* permute */ + for (j = i0; j < s->i; ++j) + c_getopt_permute(argv, j, s->n_args); + } + s->ind = s->i - s->n_args; + return opt; +} + +/* // demo: + int main(int argc, char *argv[]) + { + static c_longopt_t longopts[] = { + { "foo", c_optarg_none, 301 }, + { "bar", c_optarg_required, 302 }, + { "opt", c_optarg_optional, 303 }, + { NULL, 0, 0 } + }; + c_getopt_t opt = c_getopt_init; + int i, c; + while ((c = c_getopt(&opt, argc, argv, 1, "xy:", longopts)) >= 0) { + if (c == 'x') printf("-x\n"); + else if (c == 'y') printf("-y %s\n", opt.arg); + else if (c == 301) printf("--foo\n"); + else if (c == 302) printf("--bar %s\n", opt.arg? opt.arg : "(null)"); + else if (c == 303) printf("--opt %s\n", opt.arg? opt.arg : "(null)"); + else if (c == '?') printf("unknown opt: -%c\n", opt.opt? opt.opt : ':'); + else if (c == ':') printf("missing arg: -%c\n", opt.opt? opt.opt : ':'); + } + printf("Non-option arguments:"); + for (i = opt.ind; i < argc; ++i) + printf(" %s", argv[i]); + putchar('\n'); + return 0; + } +*/ + + +#endif \ No newline at end of file diff --git a/c_lib/cmap.h b/c_lib/cmap.h index 16b5b38e..153acb5b 100644 --- a/c_lib/cmap.h +++ b/c_lib/cmap.h @@ -25,7 +25,7 @@ #include "cvector.h" -#define cmap_initializer {cvector_initializer, 0, 90, 0} + #define cmap_size(map) ((size_t) (map)._size) #define cmap_bucketCount(map) cvector_capacity((map)._table) @@ -52,6 +52,11 @@ typedef struct CMapEntry_##tag CMapEntry_##tag enum {cmapentry_HASH=0x7fff, cmapentry_USED=0x8000}; #define cmapentry_noCompare(x, y) (0) +// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ +static inline uint32_t cmap_reduce(uint32_t x, uint32_t N) { + return ((uint64_t) x * (uint64_t) N) >> 32 ; +} + // CMap: #define declare_CMap(...) c_MACRO_OVERLOAD(declare_CMap, __VA_ARGS__) @@ -94,16 +99,12 @@ typedef struct CMap_##tag { \ uint8_t maxLoadPercent; \ uint8_t shrinkLimitPercent; \ } CMap_##tag; \ +static const CMap_##tag cmap_##tag##_init = {{NULL}, 0, 90, 0}; \ \ typedef struct cmap_##tag##_iter_t { \ CMapEntry_##tag *item, *_end; \ } cmap_##tag##_iter_t; \ \ -static inline CMap_##tag cmap_##tag##_init(void) { \ - CMap_##tag map = cmap_initializer; \ - return map; \ -} \ - \ static inline void cmap_##tag##_destroy(CMap_##tag* self) { \ if (cmap_size(*self)) { \ size_t cap = _cvector_capacity(self->_table); \ @@ -139,7 +140,7 @@ static inline void cmap_##tag##_setShrinkLimitFactor(CMap_##tag* self, double li static inline size_t cmap_##tag##_bucket(CMap_##tag* self, cmap_##tag##_rawkey_t* const rawKey, uint32_t* hxPtr) { \ uint32_t hash = keyHashRaw(rawKey, sizeof(cmap_##tag##_rawkey_t)), hx = (hash & cmapentry_HASH) | cmapentry_USED; \ size_t cap = cvector_capacity(self->_table); \ - size_t idx = c_reduce(hash, cap); \ + size_t idx = cmap_reduce(hash, cap); \ CMapEntry_##tag* slot = self->_table.data; \ while (slot[idx].hashx && (slot[idx].hashx != hx || !keyEqualsRaw((RawKey* const) keyGetRaw(&slot[idx].key), rawKey))) { \ if (++idx == cap) idx = 0; \ @@ -192,7 +193,7 @@ static inline CMapEntry_##tag* cmap_##tag##_insert(CMap_##tag* self, CMapEntry_# static inline size_t cmap_##tag##_reserve(CMap_##tag* self, size_t size) { \ size_t oldcap = cvector_capacity(self->_table), newcap = 1 + (size / 2) * 2; \ if (cmap_size(*self) >= newcap * self->maxLoadPercent * 0.01) return oldcap; \ - CVector_map_##tag vec = cvector_initializer; \ + CVector_map_##tag vec = cvector_map_##tag##_init; \ cvector_map_##tag##_reserve(&vec, newcap); \ memset(vec.data, 0, sizeof(CMapEntry_##tag) * newcap); \ cvector_map_##tag##_swap(&self->_table, &vec); \ @@ -221,7 +222,7 @@ static inline bool cmap_##tag##_erase(CMap_##tag* self, cmap_##tag##_rawkey_t ra if (++j == cap) j = 0; /* j %= cap; is slow */ \ if (! slot[j].hashx) \ break; \ - k = c_reduce(keyHashRaw((RawKey* const) keyGetRaw(&slot[j].key), sizeof(cmap_##tag##_rawkey_t)), cap); \ + k = cmap_reduce(keyHashRaw((RawKey* const) keyGetRaw(&slot[j].key), sizeof(cmap_##tag##_rawkey_t)), cap); \ if ((j < i) ^ (k <= i) ^ (k > j)) /* is k outside (i, j]? */ \ slot[i] = slot[j], i = j; \ } while (true); \ diff --git a/c_lib/cstring.h b/c_lib/cstring.h index 92cb1555..d0719cb6 100644 --- a/c_lib/cstring.h +++ b/c_lib/cstring.h @@ -38,12 +38,13 @@ typedef struct CString { static size_t _cstring_null_rep[] = {0, 0, 0}; #define _cstring_rep(cs) (((size_t *) (cs).str) - 2) -#define cstring_initializer {(char* ) (_cstring_null_rep + 2)} #define cstring_size(cs) ((size_t) _cstring_rep(cs)[0]) #define cstring_capacity(cs) ((size_t) _cstring_rep(cs)[1]) #define cstring_npos c_npos +static const CString cstring_init = {(char* ) &_cstring_null_rep[2]}; + static inline void cstring_reserve(CString* self, size_t cap) { size_t len = cstring_size(*self), oldcap = cstring_capacity(*self); if (cap > oldcap) { @@ -60,13 +61,8 @@ static inline void cstring_destroy(CString* self) { } } -static inline CString cstring_init(void) { - CString cs = cstring_initializer; - return cs; -} - static inline CString cstring_makeN(const char* str, size_t len) { - CString cs = cstring_initializer; + CString cs = cstring_init; if (len) { cstring_reserve(&cs, len); memcpy(cs.str, str, len); @@ -84,7 +80,7 @@ static inline CString cstring_makeCopy(CString cs) { } static inline void cstring_clear(CString* self) { - CString cs = cstring_initializer; + CString cs = cstring_init; cstring_destroy(self); *self = cs; } diff --git a/c_lib/cvector.h b/c_lib/cvector.h index aafa7c7f..3297a076 100644 --- a/c_lib/cvector.h +++ b/c_lib/cvector.h @@ -28,7 +28,6 @@ #include "cdefs.h" -#define cvector_initializer {NULL} #define cvector_size(cv) _cvector_safe_size((cv).data) #define cvector_capacity(cv) _cvector_safe_capacity((cv).data) #define cvector_empty(cv) (_cvector_safe_size((cv).data) == 0) @@ -47,16 +46,12 @@ typedef struct CVector_##tag { \ Value* data; \ } CVector_##tag; \ +static const CVector_##tag cvector_##tag##_init = {NULL}; \ \ typedef struct cvector_##tag##_iter_t { \ Value* item; \ } cvector_##tag##_iter_t; \ \ -static inline CVector_##tag cvector_##tag##_init(void) { \ - CVector_##tag cv = cvector_initializer; \ - return cv; \ -} \ - \ static inline void cvector_##tag##_swap(CVector_##tag* a, CVector_##tag* b) { \ Value* data = a->data; a->data = b->data; b->data = data; \ } \ @@ -79,7 +74,7 @@ static inline void cvector_##tag##_reserve(CVector_##tag* self, size_t cap) { \ } \ \ static inline void cvector_##tag##_clear(CVector_##tag* self) { \ - CVector_##tag cv = cvector_initializer; \ + CVector_##tag cv = cvector_##tag##_init; \ cvector_##tag##_destroy(self); \ *self = cv; \ } \ -- cgit v1.2.3