diff options
| author | Tyge Løvset <[email protected]> | 2020-03-29 20:19:34 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2020-03-29 20:19:34 +0200 |
| commit | a8e178e11e4955306d32e4c48be348d50dbcb3df (patch) | |
| tree | f4ea5d741323feeefd95671bad301ced5e113357 | |
| parent | 124f1eaaa8c7e5dafad8f6ba1898b09b38bac9dc (diff) | |
| download | STC-modified-a8e178e11e4955306d32e4c48be348d50dbcb3df.tar.gz STC-modified-a8e178e11e4955306d32e4c48be348d50dbcb3df.zip | |
Add files via upload
| -rw-r--r-- | c_lib/cdefs.h | 13 | ||||
| -rw-r--r-- | c_lib/cgetopt.h | 150 | ||||
| -rw-r--r-- | c_lib/cmap.h | 19 | ||||
| -rw-r--r-- | c_lib/cstring.h | 12 | ||||
| -rw-r--r-- | c_lib/cvector.h | 9 |
5 files changed, 172 insertions, 31 deletions
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 <string.h>
+
+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; \
} \
|
