summaryrefslogtreecommitdiffhomepage
path: root/include/stc/ccommon.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/stc/ccommon.h')
-rw-r--r--include/stc/ccommon.h180
1 files changed, 94 insertions, 86 deletions
diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h
index d5508807..0a8c439a 100644
--- a/include/stc/ccommon.h
+++ b/include/stc/ccommon.h
@@ -29,17 +29,11 @@
#include <stdbool.h>
#include <string.h>
#include <assert.h>
-#include "priv/altnames.h"
-#include "priv/raii.h"
+typedef long long _llong;
#define c_NPOS INTPTR_MAX
#define c_ZI PRIiPTR
#define c_ZU PRIuPTR
-#if defined STC_NDEBUG || defined NDEBUG
- #define c_ASSERT(expr) (void)(0)
-#else
- #define c_ASSERT(expr) assert(expr)
-#endif
#if defined(_MSC_VER)
#pragma warning(disable: 4116 4996) // unnamed type definition in parentheses
@@ -63,7 +57,7 @@
#define _c_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, \
_14, _15, _16, N, ...) N
-#ifdef __cplusplus
+#ifdef __cplusplus
#include <new>
#define _i_alloc(T) static_cast<T*>(i_malloc(c_sizeof(T)))
#define _i_new(T, ...) new (_i_alloc(T)) T(__VA_ARGS__)
@@ -71,39 +65,45 @@
#define c_LITERAL(T) T
#else
#define _i_alloc(T) ((T*)i_malloc(c_sizeof(T)))
- #define _i_new(T, ...) ((T*)memcpy(_i_alloc(T), (T[]){__VA_ARGS__}, sizeof(T)))
- #define c_new(T, ...) ((T*)memcpy(malloc(sizeof(T)), (T[]){__VA_ARGS__}, sizeof(T)))
+ #define _i_new(T, ...) ((T*)memcpy(_i_alloc(T), ((T[]){__VA_ARGS__}), sizeof(T)))
+ #define c_new(T, ...) ((T*)memcpy(malloc(sizeof(T)), ((T[]){__VA_ARGS__}), sizeof(T)))
#define c_LITERAL(T) (T)
#endif
-#define c_malloc(sz) malloc(c_i2u(sz))
-#define c_calloc(n, sz) calloc(c_i2u(n), c_i2u(sz))
-#define c_realloc(p, sz) realloc(p, c_i2u(sz))
+#define c_new_n(T, n) ((T*)malloc(sizeof(T)*c_i2u_size(n)))
+#define c_malloc(sz) malloc(c_i2u_size(sz))
+#define c_calloc(n, sz) calloc(c_i2u_size(n), c_i2u_size(sz))
+#define c_realloc(p, sz) realloc(p, c_i2u_size(sz))
#define c_free(p) free(p)
#define c_delete(T, ptr) do { T *_tp = ptr; T##_drop(_tp); free(_tp); } while (0)
-#define c_static_assert(b) ((int)(0*sizeof(int[(b) ? 1 : -1])))
+#define c_static_assert(expr) (1 ? 0 : (int)sizeof(int[(expr) ? 1 : -1]))
+#if defined STC_NDEBUG || defined NDEBUG
+ #define c_assert(expr) ((void)0)
+#else
+ #define c_assert(expr) assert(expr)
+#endif
#define c_container_of(p, C, m) ((C*)((char*)(1 ? (p) : &((C*)0)->m) - offsetof(C, m)))
-#define c_const_cast(T, p) ((T)(p) + 0*sizeof((T)0 == (p)))
+#define c_const_cast(T, p) ((T)(1 ? (p) : (T)0))
#define c_swap(T, xp, yp) do { T *_xp = xp, *_yp = yp, \
_tv = *_xp; *_xp = *_yp; *_yp = _tv; } while (0)
+// use with gcc -Wconversion
#define c_sizeof (intptr_t)sizeof
#define c_strlen(s) (intptr_t)strlen(s)
-#define c_strncmp(a, b, ilen) strncmp(a, b, c_i2u(ilen))
-#define c_memcpy(d, s, ilen) memcpy(d, s, c_i2u(ilen))
-#define c_memmove(d, s, ilen) memmove(d, s, c_i2u(ilen))
-#define c_memset(d, val, ilen) memset(d, val, c_i2u(ilen))
-#define c_memcmp(a, b, ilen) memcmp(a, b, c_i2u(ilen))
-
-#define c_u2i(u) ((intptr_t)((u) + 0*sizeof((u) == 1U)))
-#define c_i2u(i) ((size_t)(i) + 0*sizeof((i) == 1))
-#define c_LTu(a, b) ((size_t)(a) < (size_t)(b))
+#define c_strncmp(a, b, ilen) strncmp(a, b, c_i2u_size(ilen))
+#define c_memcpy(d, s, ilen) memcpy(d, s, c_i2u_size(ilen))
+#define c_memmove(d, s, ilen) memmove(d, s, c_i2u_size(ilen))
+#define c_memset(d, val, ilen) memset(d, val, c_i2u_size(ilen))
+#define c_memcmp(a, b, ilen) memcmp(a, b, c_i2u_size(ilen))
+#define c_u2i_size(u) (intptr_t)(1 ? (u) : (size_t)1)
+#define c_i2u_size(i) (size_t)(1 ? (i) : -1)
+#define c_less_unsigned(a, b) ((size_t)(a) < (size_t)(b))
// x and y are i_keyraw* type, defaults to i_key*:
#define c_default_cmp(x, y) (c_default_less(y, x) - c_default_less(x, y))
#define c_default_less(x, y) (*(x) < *(y))
#define c_default_eq(x, y) (*(x) == *(y))
#define c_memcmp_eq(x, y) (memcmp(x, y, sizeof *(x)) == 0)
-#define c_default_hash(x) cfasthash(x, c_sizeof(*(x)))
+#define c_default_hash(x) stc_hash(x, c_sizeof(*(x)))
#define c_default_clone(v) (v)
#define c_default_toraw(vp) (*(vp))
@@ -114,32 +114,31 @@
#define c_no_atomic (1<<1)
#define c_no_clone (1<<2)
#define c_no_emplace (1<<3)
-#define c_no_cmp (1<<4)
-#define c_no_hash (1<<5)
-
+#define c_no_hash (1<<4)
+#define c_use_cmp (1<<5)
/* Function macros and others */
-#define c_make(C, ...) \
- C##_from_n((C##_raw[])__VA_ARGS__, c_sizeof((C##_raw[])__VA_ARGS__)/c_sizeof(C##_raw))
-
#define c_litstrlen(literal) (c_sizeof("" literal) - 1)
#define c_arraylen(a) (intptr_t)(sizeof(a)/sizeof 0[a])
-// Non-owning c-string
-typedef const char* crawstr;
-#define crawstr_clone(s) (s)
-#define crawstr_drop(p) ((void)p)
-#define crawstr_cmp(xp, yp) strcmp(*(xp), *(yp))
-#define crawstr_hash(p) cstrhash(*(p))
+// Non-owning c-string "class"
+typedef const char* ccharptr;
+#define ccharptr_cmp(xp, yp) strcmp(*(xp), *(yp))
+#define ccharptr_hash(p) stc_strhash(*(p))
+#define ccharptr_clone(s) (s)
+#define ccharptr_drop(p) ((void)p)
#define c_sv(...) c_MACRO_OVERLOAD(c_sv, __VA_ARGS__)
-#define c_sv_1(lit) c_sv_2(lit, c_litstrlen(lit))
+#define c_sv_1(literal) c_sv_2(literal, c_litstrlen(literal))
#define c_sv_2(str, n) (c_LITERAL(csview){str, n})
+#define c_SV(sv) (int)(sv).size, (sv).buf // printf("%.*s\n", c_SV(sv));
+
+#define c_rs(literal) c_rs_2(literal, c_litstrlen(literal))
+#define c_rs_2(str, n) (c_LITERAL(crawstr){str, n})
-#define c_SV(sv) (int)(sv).size, (sv).str // print csview: use format "%.*s"
#define c_ROTL(x, k) (x << (k) | x >> (8*sizeof(x) - (k)))
-STC_INLINE uint64_t cfasthash(const void* key, intptr_t len) {
+STC_INLINE uint64_t stc_hash(const void* key, intptr_t len) {
uint32_t u4; uint64_t u8;
switch (len) {
case 8: memcpy(&u8, key, 8); return u8*0xc6a4a7935bd1e99d;
@@ -147,21 +146,21 @@ STC_INLINE uint64_t cfasthash(const void* key, intptr_t len) {
case 0: return 1;
}
const uint8_t *x = (const uint8_t*)key;
- uint64_t h = *x, n = (uint64_t)len >> 3;
+ uint64_t h = (uint64_t)*x << 7, n = (uint64_t)len >> 3;
len &= 7;
while (n--) {
memcpy(&u8, x, 8), x += 8;
- h += u8*0xc6a4a7935bd1e99d;
+ h = (h ^ u8)*0xc6a4a7935bd1e99d;
}
- while (len--) h = (h << 10) - h - *x++;
- return c_ROTL(h, 26) ^ h;
+ while (len--) h = (h ^ *x++)*0x100000001b3;
+ return h ^ c_ROTL(h, 26);
}
-STC_INLINE uint64_t cstrhash(const char *str)
- { return cfasthash(str, c_strlen(str)); }
+STC_INLINE uint64_t stc_strhash(const char *str)
+ { return stc_hash(str, c_strlen(str)); }
-STC_INLINE char* cstrnstrn(const char *str, const char *needle,
- intptr_t slen, const intptr_t nlen) {
+STC_INLINE char* stc_strnstrn(const char *str, intptr_t slen,
+ const char *needle, intptr_t nlen) {
if (!nlen) return (char *)str;
if (nlen > slen) return NULL;
slen -= nlen;
@@ -173,6 +172,16 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle,
return NULL;
}
+STC_INLINE intptr_t stc_nextpow2(intptr_t n) {
+ n--;
+ n |= n >> 1, n |= n >> 2;
+ n |= n >> 4, n |= n >> 8;
+ n |= n >> 16;
+ #if INTPTR_MAX == INT64_MAX
+ n |= n >> 32;
+ #endif
+ return n + 1;
+}
/* Control block macros */
#define c_foreach(...) c_MACRO_OVERLOAD(c_foreach, __VA_ARGS__)
@@ -182,57 +191,56 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle,
for (C##_iter it = start, *_endref = (C##_iter*)(finish).ref \
; it.ref != (C##_value*)_endref; C##_next(&it))
-#define c_foreach_rv(it, C, cnt) \
- for (C##_iter it = {.ref=C##_end(&cnt).end - 1, .end=(cnt).data - 1} \
- ; it.ref != it.end; --it.ref)
-
#define c_forpair(key, val, C, cnt) /* structured binding */ \
for (struct {C##_iter it; const C##_key* key; C##_mapped* val;} _ = {.it=C##_begin(&cnt)} \
; _.it.ref && (_.key = &_.it.ref->first, _.val = &_.it.ref->second) \
; C##_next(&_.it))
-#define c_forrange(...) c_MACRO_OVERLOAD(c_forrange, __VA_ARGS__)
-#define c_forrange_1(stop) c_forrange_3(_c_i, 0, stop)
-#define c_forrange_2(i, stop) c_forrange_3(i, 0, stop)
-#define c_forrange_3(i, start, stop) \
- for (long long i=start, _end=(long long)(stop); i < _end; ++i)
-#define c_forrange_4(i, start, stop, step) \
- for (long long i=start, _inc=step, _end=(long long)(stop) - (_inc > 0) \
+#define c_forrange(...) c_for(long long, __VA_ARGS__)
+#define c_for(...) c_MACRO_OVERLOAD(c_for, __VA_ARGS__)
+#define c_for_2(T, stop) c_for_4(T, _c_i, 0, stop)
+#define c_for_3(T, i, stop) c_for_4(T, i, 0, stop)
+#define c_for_4(T, i, start, stop) \
+ for (T i=start, _end=stop; i < _end; ++i)
+#define c_for_5(T, i, start, stop, step) \
+ for (T i=start, _inc=step, _end=(T)(stop) - (_inc > 0) \
; (_inc > 0) ^ (i > _end); i += _inc)
#ifndef __cplusplus
+ #define c_init(C, ...) \
+ C##_from_n((C##_raw[])__VA_ARGS__, c_sizeof((C##_raw[])__VA_ARGS__)/c_sizeof(C##_raw))
#define c_forlist(it, T, ...) \
- for (struct {T* ref; int size, index;} \
- it = {.ref=(T[])__VA_ARGS__, .size=(int)(sizeof((T[])__VA_ARGS__)/sizeof(T))} \
- ; it.index < it.size; ++it.ref, ++it.index)
+ for (struct {T* ref; int size, index;} \
+ it = {.ref=(T[])__VA_ARGS__, .size=(int)(sizeof((T[])__VA_ARGS__)/sizeof(T))} \
+ ; it.index < it.size; ++it.ref, ++it.index)
#else
- #include <initializer_list>
- #define c_forlist(it, T, ...) \
- for (struct {std::initializer_list<T> _il; std::initializer_list<T>::iterator data, ref; size_t size, index;} \
- it = {._il=__VA_ARGS__, .data=it._il.begin(), .ref=it.data, .size=it._il.size()} \
- ; it.index < it.size; ++it.ref, ++it.index)
+ #include <initializer_list>
+ template <class C, class T>
+ inline C _from_n(C (*func)(const T[], intptr_t), std::initializer_list<T> il)
+ { return func(&*il.begin(), il.size()); }
+
+ #define c_init(C, ...) _from_n<C,C##_raw>(C##_from_n, __VA_ARGS__)
+ #define c_forlist(it, T, ...) \
+ for (struct {std::initializer_list<T> _il; std::initializer_list<T>::iterator ref; size_t size, index;} \
+ it = {._il=__VA_ARGS__, .ref=it._il.begin(), .size=it._il.size()} \
+ ; it.index < it.size; ++it.ref, ++it.index)
#endif
+#define c_defer(...) \
+ for (int _i = 1; _i; _i = 0, __VA_ARGS__)
#define c_drop(C, ...) \
do { c_forlist (_i, C*, {__VA_ARGS__}) C##_drop(*_i.ref); } while(0)
-#endif // CCOMMON_H_INCLUDED
-
-#undef STC_API
-#undef STC_DEF
-
-#if !defined(i_static) && !defined(STC_STATIC) && (defined(i_header) || defined(STC_HEADER) || \
- defined(i_implement) || defined(STC_IMPLEMENT))
- #define STC_API extern
- #define STC_DEF
-#else
- #define i_static
- #define STC_API static inline
- #define STC_DEF static inline
-#endif
-#if defined(STC_EXTERN)
- #define i_extern
-#endif
-#if defined(i_static) || defined(STC_IMPLEMENT)
- #define i_implement
+#if defined(__SIZEOF_INT128__)
+ #define c_umul128(a, b, lo, hi) \
+ do { __uint128_t _z = (__uint128_t)(a)*(b); \
+ *(lo) = (uint64_t)_z, *(hi) = (uint64_t)(_z >> 64U); } while(0)
+#elif defined(_MSC_VER) && defined(_WIN64)
+ #include <intrin.h>
+ #define c_umul128(a, b, lo, hi) ((void)(*(lo) = _umul128(a, b, hi)))
+#elif defined(__x86_64__)
+ #define c_umul128(a, b, lo, hi) \
+ asm("mulq %3" : "=a"(*(lo)), "=d"(*(hi)) : "a"(a), "rm"(b))
#endif
+
+#endif // CCOMMON_H_INCLUDED