aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/stdlib')
-rw-r--r--src/stdlib/bools.c42
-rw-r--r--src/stdlib/bools.h4
-rw-r--r--src/stdlib/bytes.c98
-rw-r--r--src/stdlib/c_strings.c76
-rw-r--r--src/stdlib/datatypes.h33
-rw-r--r--src/stdlib/enums.c65
-rw-r--r--src/stdlib/enums.h38
-rw-r--r--src/stdlib/files.c114
-rw-r--r--src/stdlib/files.h24
-rw-r--r--src/stdlib/fpconv.c114
-rw-r--r--src/stdlib/functiontype.c13
-rw-r--r--src/stdlib/functiontype.h33
-rw-r--r--src/stdlib/integers.c620
-rw-r--r--src/stdlib/integers.h271
-rw-r--r--src/stdlib/lists.c569
-rw-r--r--src/stdlib/lists.h233
-rw-r--r--src/stdlib/mapmacro.h4
-rw-r--r--src/stdlib/memory.c25
-rw-r--r--src/stdlib/metamethods.c76
-rw-r--r--src/stdlib/metamethods.h4
-rw-r--r--src/stdlib/nums.c214
-rw-r--r--src/stdlib/optionals.c57
-rw-r--r--src/stdlib/optionals.h40
-rw-r--r--src/stdlib/paths.c556
-rw-r--r--src/stdlib/paths.h5
-rw-r--r--src/stdlib/pointers.c58
-rw-r--r--src/stdlib/pointers.h42
-rw-r--r--src/stdlib/powers.h86
-rw-r--r--src/stdlib/print.c181
-rw-r--r--src/stdlib/print.h95
-rw-r--r--src/stdlib/random.h6
-rw-r--r--src/stdlib/simpleparse.c62
-rw-r--r--src/stdlib/simpleparse.h58
-rw-r--r--src/stdlib/siphash-internals.h73
-rw-r--r--src/stdlib/siphash.c10
-rw-r--r--src/stdlib/siphash.h2
-rw-r--r--src/stdlib/stacktrace.c68
-rw-r--r--src/stdlib/stacktrace.h3
-rw-r--r--src/stdlib/stdlib.c370
-rw-r--r--src/stdlib/stdlib.h114
-rw-r--r--src/stdlib/structs.c85
-rw-r--r--src/stdlib/structs.h38
-rw-r--r--src/stdlib/tables.c327
-rw-r--r--src/stdlib/tables.h163
-rw-r--r--src/stdlib/text.c880
-rw-r--r--src/stdlib/text.h44
-rw-r--r--src/stdlib/types.c21
-rw-r--r--src/stdlib/types.h63
-rw-r--r--src/stdlib/util.h44
49 files changed, 3023 insertions, 3198 deletions
diff --git a/src/stdlib/bools.c b/src/stdlib/bools.c
index 76de49e0..0231e21b 100644
--- a/src/stdlib/bools.c
+++ b/src/stdlib/bools.c
@@ -11,18 +11,14 @@
#include "text.h"
#include "util.h"
-PUREFUNC public Text_t Bool$as_text(const void *b, bool colorize, const TypeInfo_t *info)
-{
+PUREFUNC public Text_t Bool$as_text(const void *b, bool colorize, const TypeInfo_t *info) {
(void)info;
if (!b) return Text("Bool");
- if (colorize)
- return *(Bool_t*)b ? Text("\x1b[35myes\x1b[m") : Text("\x1b[35mno\x1b[m");
- else
- return *(Bool_t*)b ? Text("yes") : Text("no");
+ if (colorize) return *(Bool_t *)b ? Text("\x1b[35myes\x1b[m") : Text("\x1b[35mno\x1b[m");
+ else return *(Bool_t *)b ? Text("yes") : Text("no");
}
-static bool try_parse(Text_t text, Text_t target, bool target_value, Text_t *remainder, bool *result)
-{
+static bool try_parse(Text_t text, Text_t target, bool target_value, Text_t *remainder, bool *result) {
static const Text_t lang = Text("C");
if (text.length < target.length) return false;
Text_t prefix = Text$to(text, Int$from_int64(target.length));
@@ -36,35 +32,33 @@ static bool try_parse(Text_t text, Text_t target, bool target_value, Text_t *rem
}
}
-PUREFUNC public OptionalBool_t Bool$parse(Text_t text, Text_t *remainder)
-{
+PUREFUNC public OptionalBool_t Bool$parse(Text_t text, Text_t *remainder) {
bool result;
if (try_parse(text, Text("yes"), true, remainder, &result)
|| try_parse(text, Text("true"), true, remainder, &result)
- || try_parse(text, Text("on"), true, remainder, &result)
- || try_parse(text, Text("1"), true, remainder, &result)
+ || try_parse(text, Text("on"), true, remainder, &result) || try_parse(text, Text("1"), true, remainder, &result)
|| try_parse(text, Text("no"), false, remainder, &result)
|| try_parse(text, Text("false"), false, remainder, &result)
|| try_parse(text, Text("off"), false, remainder, &result)
|| try_parse(text, Text("0"), false, remainder, &result))
return result;
- else
- return NONE_BOOL;
+ else return NONE_BOOL;
}
-static bool Bool$is_none(const void *b, const TypeInfo_t *info)
-{
+static bool Bool$is_none(const void *b, const TypeInfo_t *info) {
(void)info;
- return *(OptionalBool_t*)b == NONE_BOOL;
+ return *(OptionalBool_t *)b == NONE_BOOL;
}
-public const TypeInfo_t Bool$info = {
- .size=sizeof(bool),
- .align=__alignof__(bool),
- .metamethods={
- .as_text=Bool$as_text,
- .is_none=Bool$is_none,
- },
+public
+const TypeInfo_t Bool$info = {
+ .size = sizeof(bool),
+ .align = __alignof__(bool),
+ .metamethods =
+ {
+ .as_text = Bool$as_text,
+ .is_none = Bool$is_none,
+ },
};
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/bools.h b/src/stdlib/bools.h
index bdf80879..3eac0f0d 100644
--- a/src/stdlib/bools.h
+++ b/src/stdlib/bools.h
@@ -8,8 +8,8 @@
#include "types.h"
#include "util.h"
-#define yes (Bool_t)true
-#define no (Bool_t)false
+#define yes (Bool_t) true
+#define no (Bool_t) false
PUREFUNC Text_t Bool$as_text(const void *b, bool colorize, const TypeInfo_t *type);
OptionalBool_t Bool$parse(Text_t text, Text_t *remainder);
diff --git a/src/stdlib/bytes.c b/src/stdlib/bytes.c
index 5a581e7e..d4bd5ef6 100644
--- a/src/stdlib/bytes.c
+++ b/src/stdlib/bytes.c
@@ -8,15 +8,18 @@
#include "text.h"
#include "util.h"
-public const Byte_t Byte$min = 0;
-public const Byte_t Byte$max = UINT8_MAX;
+public
+const Byte_t Byte$min = 0;
+public
+const Byte_t Byte$max = UINT8_MAX;
-PUREFUNC public Text_t Byte$as_text(const void *b, bool colorize, const TypeInfo_t *info)
-{
+PUREFUNC public Text_t Byte$as_text(const void *b, bool colorize, const TypeInfo_t *info) {
(void)info;
if (!b) return Text("Byte");
- Byte_t byte = *(Byte_t*)b;
- char digits[] = {'0', 'x',
+ Byte_t byte = *(Byte_t *)b;
+ char digits[] = {
+ '0',
+ 'x',
(byte / 16) <= 9 ? '0' + (byte / 16) : 'a' + (byte / 16) - 10,
(byte & 15) <= 9 ? '0' + (byte & 15) : 'a' + (byte & 15) - 10,
'\0',
@@ -26,52 +29,54 @@ PUREFUNC public Text_t Byte$as_text(const void *b, bool colorize, const TypeInfo
return text;
}
-public CONSTFUNC bool Byte$is_between(const Byte_t x, const Byte_t low, const Byte_t high) {
- return low <= x && x <= high;
-}
+public
+CONSTFUNC bool Byte$is_between(const Byte_t x, const Byte_t low, const Byte_t high) { return low <= x && x <= high; }
-public OptionalByte_t Byte$parse(Text_t text, Text_t *remainder)
-{
+public
+OptionalByte_t Byte$parse(Text_t text, Text_t *remainder) {
OptionalInt_t full_int = Int$parse(text, remainder);
- if (full_int.small != 0L
- && Int$compare_value(full_int, I(0)) >= 0
- && Int$compare_value(full_int, I(255)) <= 0) {
- return (OptionalByte_t){.value=Byte$from_int(full_int, true)};
+ if (full_int.small != 0L && Int$compare_value(full_int, I(0)) >= 0 && Int$compare_value(full_int, I(255)) <= 0) {
+ return (OptionalByte_t){.value = Byte$from_int(full_int, true)};
} else {
return NONE_BYTE;
}
}
-public Text_t Byte$hex(Byte_t byte, bool uppercase, bool prefix) {
- struct Text_s text = {.tag=TEXT_ASCII};
+public
+Text_t Byte$hex(Byte_t byte, bool uppercase, bool prefix) {
+ struct Text_s text = {.tag = TEXT_ASCII};
text.ascii = GC_MALLOC_ATOMIC(8);
- char *p = (char*)text.ascii;
+ char *p = (char *)text.ascii;
if (prefix) {
*(p++) = '0';
*(p++) = 'x';
}
if (uppercase) {
- *(p++) = (byte/16) > 9 ? 'A' + (byte/16) - 10 : '0' + (byte/16);
+ *(p++) = (byte / 16) > 9 ? 'A' + (byte / 16) - 10 : '0' + (byte / 16);
*(p++) = (byte & 15) > 9 ? 'A' + (byte & 15) - 10 : '0' + (byte & 15);
} else {
- *(p++) = (byte/16) > 9 ? 'a' + (byte/16) - 10 : '0' + (byte/16);
+ *(p++) = (byte / 16) > 9 ? 'a' + (byte / 16) - 10 : '0' + (byte / 16);
*(p++) = (byte & 15) > 9 ? 'a' + (byte & 15) - 10 : '0' + (byte & 15);
}
text.length = (int64_t)(p - text.ascii);
return text;
}
-public bool Byte$get_bit(Byte_t x, Int_t bit_index) {
- if (Int$compare_value(bit_index, I(1)) < 0)
- fail("Invalid bit index (expected 1 or higher): ", bit_index);
+public
+bool Byte$get_bit(Byte_t x, Int_t bit_index) {
+ if (Int$compare_value(bit_index, I(1)) < 0) fail("Invalid bit index (expected 1 or higher): ", bit_index);
if (Int$compare_value(bit_index, I(8)) > 0)
fail("Bit index is too large! There are only 8 bits in a byte, but index is: ", bit_index);
- return ((x & (Byte_t)(1L << (Int64$from_int(bit_index, true)-1L))) != 0);
+ return ((x & (Byte_t)(1L << (Int64$from_int(bit_index, true) - 1L))) != 0);
}
#ifdef __TINYC__
-#define __builtin_add_overflow(x, y, result) ({ *(result) = (x) + (y); false; })
+#define __builtin_add_overflow(x, y, result) \
+ ({ \
+ *(result) = (x) + (y); \
+ false; \
+ })
#endif
typedef struct {
@@ -82,52 +87,59 @@ typedef struct {
static OptionalByte_t _next_Byte(ByteRange_t *info) {
OptionalByte_t i = info->current;
if (!i.is_none) {
- Byte_t next; bool overflow = __builtin_add_overflow(i.value, info->step, &next);
+ Byte_t next;
+ bool overflow = __builtin_add_overflow(i.value, info->step, &next);
if (overflow || (!info->last.is_none && (info->step >= 0 ? next > info->last.value : next < info->last.value)))
- info->current = (OptionalByte_t){.is_none=true};
- else
- info->current = (OptionalByte_t){.value=next};
+ info->current = (OptionalByte_t){.is_none = true};
+ else info->current = (OptionalByte_t){.value = next};
}
return i;
}
-public CONSTFUNC Closure_t Byte$to(Byte_t first, Byte_t last, OptionalInt8_t step) {
+public
+CONSTFUNC Closure_t Byte$to(Byte_t first, Byte_t last, OptionalInt8_t step) {
ByteRange_t *range = GC_MALLOC(sizeof(ByteRange_t));
- range->current = (OptionalByte_t){.value=first};
- range->last = (OptionalByte_t){.value=last};
+ range->current = (OptionalByte_t){.value = first};
+ range->last = (OptionalByte_t){.value = last};
range->step = step.is_none ? (last >= first ? 1 : -1) : step.value;
- return (Closure_t){.fn=_next_Byte, .userdata=range};
+ return (Closure_t){.fn = _next_Byte, .userdata = range};
}
-public PUREFUNC Byte_t Byte$from_int(Int_t i, bool truncate) {
+public
+PUREFUNC Byte_t Byte$from_int(Int_t i, bool truncate) {
if unlikely (!truncate && Int$compare_value(i, I_small(0xFF)) > 0)
fail("This value is too large to convert to a byte without truncation: ", i);
else if unlikely (!truncate && Int$compare_value(i, I_small(0)) < 0)
fail("Negative values can't be converted to bytes: ", i);
return (Byte_t)(i.small >> 2);
}
-public PUREFUNC Byte_t Byte$from_int64(Int64_t i, bool truncate) {
+public
+PUREFUNC Byte_t Byte$from_int64(Int64_t i, bool truncate) {
if unlikely (!truncate && i != (Int64_t)(Byte_t)i)
fail("This value can't be converted to a byte without truncation: ", i);
return (Byte_t)i;
}
-public PUREFUNC Byte_t Byte$from_int32(Int32_t i, bool truncate) {
+public
+PUREFUNC Byte_t Byte$from_int32(Int32_t i, bool truncate) {
if unlikely (!truncate && i != (Int32_t)(Byte_t)i)
fail("This value can't be converted to a byte without truncation: ", i);
return (Byte_t)i;
}
-public PUREFUNC Byte_t Byte$from_int16(Int16_t i, bool truncate) {
+public
+PUREFUNC Byte_t Byte$from_int16(Int16_t i, bool truncate) {
if unlikely (!truncate && i != (Int16_t)(Byte_t)i)
fail("This value can't be converted to a byte without truncation: ", i);
return (Byte_t)i;
}
-public const TypeInfo_t Byte$info = {
- .size=sizeof(Byte_t),
- .align=__alignof__(Byte_t),
- .metamethods={
- .as_text=Byte$as_text,
- },
+public
+const TypeInfo_t Byte$info = {
+ .size = sizeof(Byte_t),
+ .align = __alignof__(Byte_t),
+ .metamethods =
+ {
+ .as_text = Byte$as_text,
+ },
};
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/c_strings.c b/src/stdlib/c_strings.c
index c2b8efbe..b965f04b 100644
--- a/src/stdlib/c_strings.c
+++ b/src/stdlib/c_strings.c
@@ -12,46 +12,40 @@
#include "text.h"
#include "util.h"
-public Text_t CString$as_text(const void *c_string, bool colorize, const TypeInfo_t *info)
-{
+public
+Text_t CString$as_text(const void *c_string, bool colorize, const TypeInfo_t *info) {
(void)info;
if (!c_string) return Text("CString");
- Text_t text = Text$from_str(*(const char**)c_string);
- return Text$concat(colorize ? Text("\x1b[34mCString\x1b[m(") : Text("CString("), Text$quoted(text, colorize, Text("\"")), Text(")"));
+ Text_t text = Text$from_str(*(const char **)c_string);
+ return Text$concat(colorize ? Text("\x1b[34mCString\x1b[m(") : Text("CString("),
+ Text$quoted(text, colorize, Text("\"")), Text(")"));
}
-PUREFUNC public int32_t CString$compare(const void *x, const void *y, const TypeInfo_t *info)
-{
+PUREFUNC public int32_t CString$compare(const void *x, const void *y, const TypeInfo_t *info) {
(void)info;
- if (x == y)
- return 0;
+ if (x == y) return 0;
- if (!*(const char**)x != !*(const char**)y)
- return (!*(const char**)y) - (!*(const char**)x);
+ if (!*(const char **)x != !*(const char **)y) return (!*(const char **)y) - (!*(const char **)x);
- return strcmp(*(const char**)x, *(const char**)y);
+ return strcmp(*(const char **)x, *(const char **)y);
}
-PUREFUNC public bool CString$equal(const void *x, const void *y, const TypeInfo_t *type)
-{
+PUREFUNC public bool CString$equal(const void *x, const void *y, const TypeInfo_t *type) {
return CString$compare(x, y, type) == 0;
}
-PUREFUNC public uint64_t CString$hash(const void *c_str, const TypeInfo_t *info)
-{
+PUREFUNC public uint64_t CString$hash(const void *c_str, const TypeInfo_t *info) {
(void)info;
- if (!*(const char**)c_str) return 0;
- return siphash24(*(void**)c_str, strlen(*(const char**)c_str));
+ if (!*(const char **)c_str) return 0;
+ return siphash24(*(void **)c_str, strlen(*(const char **)c_str));
}
-PUREFUNC public bool CString$is_none(const void *c_str, const TypeInfo_t *info)
-{
+PUREFUNC public bool CString$is_none(const void *c_str, const TypeInfo_t *info) {
(void)info;
- return *(const char**)c_str == NULL;
+ return *(const char **)c_str == NULL;
}
-static void CString$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *info)
-{
+static void CString$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *info) {
(void)info;
const char *str = *(const char **)obj;
int64_t len = (int64_t)strlen(str);
@@ -59,30 +53,30 @@ static void CString$serialize(const void *obj, FILE *out, Table_t *pointers, con
fwrite(str, sizeof(char), (size_t)len, out);
}
-static void CString$deserialize(FILE *in, void *out, List_t *pointers, const TypeInfo_t *info)
-{
+static void CString$deserialize(FILE *in, void *out, List_t *pointers, const TypeInfo_t *info) {
(void)info;
int64_t len = -1;
Int64$deserialize(in, &len, pointers, &Int64$info);
- char *str = GC_MALLOC_ATOMIC((size_t)len+1);
- if (fread(str, sizeof(char), (size_t)len, in) != (size_t)len)
- fail("Not enough data in stream to deserialize");
- str[len+1] = '\0';
- *(const char**)out = str;
+ char *str = GC_MALLOC_ATOMIC((size_t)len + 1);
+ if (fread(str, sizeof(char), (size_t)len, in) != (size_t)len) fail("Not enough data in stream to deserialize");
+ str[len + 1] = '\0';
+ *(const char **)out = str;
}
-public const TypeInfo_t CString$info = {
- .size=sizeof(const char*),
- .align=__alignof__(const char*),
- .metamethods={
- .hash=CString$hash,
- .compare=CString$compare,
- .equal=CString$equal,
- .as_text=CString$as_text,
- .is_none=CString$is_none,
- .serialize=CString$serialize,
- .deserialize=CString$deserialize,
- },
+public
+const TypeInfo_t CString$info = {
+ .size = sizeof(const char *),
+ .align = __alignof__(const char *),
+ .metamethods =
+ {
+ .hash = CString$hash,
+ .compare = CString$compare,
+ .equal = CString$equal,
+ .as_text = CString$as_text,
+ .is_none = CString$is_none,
+ .serialize = CString$serialize,
+ .deserialize = CString$deserialize,
+ },
};
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/datatypes.h b/src/stdlib/datatypes.h
index e473956e..5d016246 100644
--- a/src/stdlib/datatypes.h
+++ b/src/stdlib/datatypes.h
@@ -12,9 +12,9 @@
#define LIST_REFCOUNT_BITS 3
#define LIST_STRIDE_BITS 12
-#define MAX_FOR_N_BITS(N) ((1L<<(N))-1L)
-#define LIST_MAX_STRIDE MAX_FOR_N_BITS(LIST_STRIDE_BITS-1)
-#define LIST_MIN_STRIDE (~MAX_FOR_N_BITS(LIST_STRIDE_BITS-1))
+#define MAX_FOR_N_BITS(N) ((1L << (N)) - 1L)
+#define LIST_MAX_STRIDE MAX_FOR_N_BITS(LIST_STRIDE_BITS - 1)
+#define LIST_MIN_STRIDE (~MAX_FOR_N_BITS(LIST_STRIDE_BITS - 1))
#define LIST_MAX_DATA_REFCOUNT MAX_FOR_N_BITS(LIST_REFCOUNT_BITS)
#define LIST_MAX_FREE_ENTRIES MAX_FOR_N_BITS(LIST_FREE_BITS)
@@ -41,15 +41,15 @@ typedef struct {
// structs can be passed in two 64-bit registers. C will handle doing the
// bit arithmetic to extract the necessary values, which is cheaper than
// spilling onto the stack and needing to retrieve data from the stack.
- int64_t length:LIST_LENGTH_BITS;
- uint64_t free:LIST_FREE_BITS;
- bool atomic:LIST_ATOMIC_BITS;
- uint8_t data_refcount:LIST_REFCOUNT_BITS;
- int16_t stride:LIST_STRIDE_BITS;
+ int64_t length : LIST_LENGTH_BITS;
+ uint64_t free : LIST_FREE_BITS;
+ bool atomic : LIST_ATOMIC_BITS;
+ uint8_t data_refcount : LIST_REFCOUNT_BITS;
+ int16_t stride : LIST_STRIDE_BITS;
} List_t;
typedef struct {
- uint32_t occupied:1, index:31;
+ uint32_t occupied : 1, index : 31;
uint32_t next_bucket;
} bucket_t;
@@ -57,8 +57,8 @@ typedef struct {
#define TABLE_MAX_DATA_REFCOUNT 3
typedef struct {
- uint32_t count:31, last_free:31;
- uint8_t data_refcount:2;
+ uint32_t count : 31, last_free : 31;
+ uint8_t data_refcount : 2;
bucket_t buckets[];
} bucket_info_t;
@@ -76,9 +76,9 @@ typedef struct {
enum text_type { TEXT_ASCII, TEXT_GRAPHEMES, TEXT_CONCAT, TEXT_BLOB };
typedef struct Text_s {
- int64_t length:54; // Number of grapheme clusters
- uint8_t tag:2;
- uint8_t depth:8;
+ int64_t length : 54; // Number of grapheme clusters
+ uint8_t tag : 2;
+ uint8_t depth : 8;
union {
struct {
const char *ascii;
@@ -117,10 +117,9 @@ typedef struct {
typedef struct {
Byte_t value;
- bool is_none:1;
+ bool is_none : 1;
} OptionalByte_t;
-#define NONE_BYTE ((OptionalByte_t){.is_none=true})
-
+#define NONE_BYTE ((OptionalByte_t){.is_none = true})
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/enums.c b/src/stdlib/enums.c
index ae0c976d..7f7c4284 100644
--- a/src/stdlib/enums.c
+++ b/src/stdlib/enums.c
@@ -11,34 +11,30 @@
CONSTFUNC static ptrdiff_t value_offset(const TypeInfo_t *type) {
ptrdiff_t offset = sizeof(int32_t);
for (int i = 0; i < type->EnumInfo.num_tags; i++) {
- if (type->EnumInfo.tags[i].type)
- offset = MAX(offset, type->EnumInfo.tags[i].type->align);
+ if (type->EnumInfo.tags[i].type) offset = MAX(offset, type->EnumInfo.tags[i].type->align);
}
return offset;
}
-PUREFUNC public uint64_t Enum$hash(const void *obj, const TypeInfo_t *type)
-{
- int32_t tag = *(int32_t*)obj;
+PUREFUNC public uint64_t Enum$hash(const void *obj, const TypeInfo_t *type) {
+ int32_t tag = *(int32_t *)obj;
uint32_t components[2] = {(uint32_t)tag, 0};
- const TypeInfo_t *value = type->EnumInfo.tags[tag-1].type;
+ const TypeInfo_t *value = type->EnumInfo.tags[tag - 1].type;
if (value && value->size > 0) {
components[1] = generic_hash(obj + value_offset(type), value);
}
- return siphash24((void*)components, sizeof(components));
+ return siphash24((void *)components, sizeof(components));
}
-PUREFUNC public int32_t Enum$compare(const void *x, const void *y, const TypeInfo_t *type)
-{
+PUREFUNC public int32_t Enum$compare(const void *x, const void *y, const TypeInfo_t *type) {
if (x == y) return 0;
- int32_t x_tag = *(int32_t*)x;
- int32_t y_tag = *(int32_t*)y;
- if (x_tag != y_tag)
- return x_tag > y_tag ? 1 : -1;
+ int32_t x_tag = *(int32_t *)x;
+ int32_t y_tag = *(int32_t *)y;
+ if (x_tag != y_tag) return x_tag > y_tag ? 1 : -1;
- const TypeInfo_t *value = type->EnumInfo.tags[x_tag-1].type;
+ const TypeInfo_t *value = type->EnumInfo.tags[x_tag - 1].type;
if (value && value->size > 0) {
ptrdiff_t byte_offset = value_offset(type);
return generic_compare(x + byte_offset, y + byte_offset, value);
@@ -46,16 +42,14 @@ PUREFUNC public int32_t Enum$compare(const void *x, const void *y, const TypeInf
return 0;
}
-PUREFUNC public bool Enum$equal(const void *x, const void *y, const TypeInfo_t *type)
-{
+PUREFUNC public bool Enum$equal(const void *x, const void *y, const TypeInfo_t *type) {
if (x == y) return true;
- int32_t x_tag = *(int32_t*)x;
- int32_t y_tag = *(int32_t*)y;
- if (x_tag != y_tag)
- return false;
+ int32_t x_tag = *(int32_t *)x;
+ int32_t y_tag = *(int32_t *)y;
+ if (x_tag != y_tag) return false;
- const TypeInfo_t *value = type->EnumInfo.tags[x_tag-1].type;
+ const TypeInfo_t *value = type->EnumInfo.tags[x_tag - 1].type;
if (value && value->size > 0) {
ptrdiff_t byte_offset = value_offset(type);
return generic_equal(x + byte_offset, y + byte_offset, value);
@@ -63,12 +57,12 @@ PUREFUNC public bool Enum$equal(const void *x, const void *y, const TypeInfo_t *
return true;
}
-public Text_t Enum$as_text(const void *obj, bool colorize, const TypeInfo_t *type)
-{
+public
+Text_t Enum$as_text(const void *obj, bool colorize, const TypeInfo_t *type) {
if (!obj) return Text$from_str(type->EnumInfo.name);
- int32_t tag = *(int32_t*)obj;
- NamedType_t value = type->EnumInfo.tags[tag-1];
+ int32_t tag = *(int32_t *)obj;
+ NamedType_t value = type->EnumInfo.tags[tag - 1];
if (!value.type || value.type->size == 0) {
Text_t text = Text$from_str(value.name);
return colorize ? Texts(Text("\x1b[1m"), text, Text("\x1b[m")) : text;
@@ -77,30 +71,29 @@ public Text_t Enum$as_text(const void *obj, bool colorize, const TypeInfo_t *typ
return generic_as_text(obj + value_offset(type), colorize, value.type);
}
-PUREFUNC public bool Enum$is_none(const void *x, const TypeInfo_t *info)
-{
+PUREFUNC public bool Enum$is_none(const void *x, const TypeInfo_t *info) {
(void)info;
- return *(int32_t*)x == 0;
+ return *(int32_t *)x == 0;
}
-public void Enum$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type)
-{
- int32_t tag = *(int32_t*)obj;
+public
+void Enum$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
+ int32_t tag = *(int32_t *)obj;
Int32$serialize(&tag, out, pointers, &Int32$info);
- NamedType_t value = type->EnumInfo.tags[tag-1];
+ NamedType_t value = type->EnumInfo.tags[tag - 1];
if (value.type && value.type->size > 0) {
_serialize(obj + value_offset(type), out, pointers, value.type);
}
}
-public void Enum$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type)
-{
+public
+void Enum$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type) {
int32_t tag = 0;
Int32$deserialize(in, &tag, pointers, &Int32$info);
- *(int32_t*)outval = tag;
+ *(int32_t *)outval = tag;
- NamedType_t value = type->EnumInfo.tags[tag-1];
+ NamedType_t value = type->EnumInfo.tags[tag - 1];
if (value.type && value.type->size > 0) {
_deserialize(in, outval + value_offset(type), pointers, value.type);
}
diff --git a/src/stdlib/enums.h b/src/stdlib/enums.h
index 8345c527..99a0f615 100644
--- a/src/stdlib/enums.h
+++ b/src/stdlib/enums.h
@@ -15,24 +15,26 @@ PUREFUNC bool Enum$is_none(const void *obj, const TypeInfo_t *type);
void Enum$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type);
void Enum$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type);
-#define Enum$metamethods { \
- .as_text=Enum$as_text, \
- .compare=Enum$compare, \
- .equal=Enum$equal, \
- .hash=Enum$hash, \
- .is_none=Enum$is_none, \
- .serialize=Enum$serialize, \
- .deserialize=Enum$deserialize, \
-}
+#define Enum$metamethods \
+ { \
+ .as_text = Enum$as_text, \
+ .compare = Enum$compare, \
+ .equal = Enum$equal, \
+ .hash = Enum$hash, \
+ .is_none = Enum$is_none, \
+ .serialize = Enum$serialize, \
+ .deserialize = Enum$deserialize, \
+ }
-#define PackedDataEnum$metamethods { \
- .hash=PackedData$hash, \
- .compare=Enum$compare, \
- .equal=PackedData$equal, \
- .as_text=Enum$as_text, \
- .is_none=Enum$is_none, \
- .serialize=Enum$serialize, \
- .deserialize=Enum$deserialize, \
-}
+#define PackedDataEnum$metamethods \
+ { \
+ .hash = PackedData$hash, \
+ .compare = Enum$compare, \
+ .equal = PackedData$equal, \
+ .as_text = Enum$as_text, \
+ .is_none = Enum$is_none, \
+ .serialize = Enum$serialize, \
+ .deserialize = Enum$deserialize, \
+ }
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/files.c b/src/stdlib/files.c
index 87b0205c..08023e0e 100644
--- a/src/stdlib/files.c
+++ b/src/stdlib/files.c
@@ -20,8 +20,8 @@
static const int tabstop = 4;
-public char *resolve_path(const char *path, const char *relative_to, const char *system_path)
-{
+public
+char *resolve_path(const char *path, const char *relative_to, const char *system_path) {
if (!relative_to || streq(relative_to, "/dev/stdin")) relative_to = ".";
if (!path || strlen(path) == 0) return NULL;
@@ -29,7 +29,7 @@ public char *resolve_path(const char *path, const char *relative_to, const char
// it was found in:
char buf[PATH_MAX] = {0};
if (streq(path, "~") || starts_with(path, "~/")) {
- char *resolved = realpath(String(getenv("HOME"), path+1), buf);
+ char *resolved = realpath(String(getenv("HOME"), path + 1), buf);
if (resolved) return GC_strdup(resolved);
} else if (streq(path, ".") || starts_with(path, "./") || starts_with(path, "../")) {
char *relative_dir = dirname(GC_strdup(relative_to));
@@ -49,12 +49,13 @@ public char *resolve_path(const char *path, const char *relative_to, const char
char *resolved = realpath(String(dir, "/", path), buf);
if (resolved) return GC_strdup(resolved);
} else if (dir[0] == '~' && (dir[1] == '\0' || dir[1] == '/')) {
- char *resolved = realpath(String(getenv("HOME"), dir+1, "/", path), buf);
+ char *resolved = realpath(String(getenv("HOME"), dir + 1, "/", path), buf);
if (resolved) return GC_strdup(resolved);
} else if (streq(dir, ".") || strncmp(dir, "./", 2) == 0) {
char *resolved = realpath(String(relative_dir, "/", path), buf);
if (resolved) return GC_strdup(resolved);
- } else if (streq(dir, ".") || streq(dir, "..") || strncmp(dir, "./", 2) == 0 || strncmp(dir, "../", 3) == 0) {
+ } else if (streq(dir, ".") || streq(dir, "..") || strncmp(dir, "./", 2) == 0
+ || strncmp(dir, "../", 3) == 0) {
char *resolved = realpath(String(relative_dir, "/", dir, "/", path), buf);
if (resolved) return GC_strdup(resolved);
} else {
@@ -66,24 +67,23 @@ public char *resolve_path(const char *path, const char *relative_to, const char
return NULL;
}
-public char *file_base_name(const char *path)
-{
+public
+char *file_base_name(const char *path) {
const char *slash = strrchr(path, '/');
if (slash) path = slash + 1;
assert(!isdigit(*path));
const char *end = path + strcspn(path, ".");
size_t len = (size_t)(end - path);
- char *buf = GC_MALLOC_ATOMIC(len+1);
+ char *buf = GC_MALLOC_ATOMIC(len + 1);
strncpy(buf, path, len);
buf[len] = '\0';
return buf;
}
-static file_t *_load_file(const char* filename, FILE *file)
-{
+static file_t *_load_file(const char *filename, FILE *file) {
if (!file) return NULL;
- file_t *ret = new(file_t, .filename=filename);
+ file_t *ret = new (file_t, .filename = filename);
size_t file_size = 0, line_cap = 0;
char *file_buf = NULL, *line_buf = NULL;
@@ -98,7 +98,7 @@ static file_t *_load_file(const char* filename, FILE *file)
}
fclose(file);
- char *copy = GC_MALLOC_ATOMIC(file_size+1);
+ char *copy = GC_MALLOC_ATOMIC(file_size + 1);
memcpy(copy, file_buf, file_size);
copy[file_size] = '\0';
ret->text = copy;
@@ -114,7 +114,7 @@ static file_t *_load_file(const char* filename, FILE *file)
char *cwd = getcwd(buf, sizeof(buf));
size_t cwd_len = strlen(cwd);
if (strncmp(cwd, filename, cwd_len) == 0 && filename[cwd_len] == '/')
- ret->relative_filename = &filename[cwd_len+1];
+ ret->relative_filename = &filename[cwd_len + 1];
}
return ret;
}
@@ -122,8 +122,8 @@ static file_t *_load_file(const char* filename, FILE *file)
//
// Read an entire file into memory.
//
-public file_t *load_file(const char* filename)
-{
+public
+file_t *load_file(const char *filename) {
FILE *file = filename[0] ? fopen(filename, "r") : stdin;
return _load_file(filename, file);
}
@@ -131,30 +131,27 @@ public file_t *load_file(const char* filename)
//
// Create a virtual file from a string.
//
-public file_t *spoof_file(const char* filename, const char *text)
-{
- FILE *file = fmemopen((char*)text, strlen(text)+1, "r");
+public
+file_t *spoof_file(const char *filename, const char *text) {
+ FILE *file = fmemopen((char *)text, strlen(text) + 1, "r");
return _load_file(filename, file);
}
//
// Given a pointer, determine which line number it points to (1-indexed)
//
-public int64_t get_line_number(file_t *f, const char *p)
-{
+public
+int64_t get_line_number(file_t *f, const char *p) {
// Binary search:
- int64_t lo = 0, hi = (int64_t)f->num_lines-1;
+ int64_t lo = 0, hi = (int64_t)f->num_lines - 1;
if (p < f->text) return 0;
int64_t offset = (int64_t)(p - f->text);
while (lo <= hi) {
int64_t mid = (lo + hi) / 2;
int64_t line_offset = f->line_offsets[mid];
- if (line_offset == offset)
- return mid + 1;
- else if (line_offset < offset)
- lo = mid + 1;
- else if (line_offset > offset)
- hi = mid - 1;
+ if (line_offset == offset) return mid + 1;
+ else if (line_offset < offset) lo = mid + 1;
+ else if (line_offset > offset) hi = mid - 1;
}
return lo; // Return the line number whose line starts closest before p
}
@@ -162,33 +159,32 @@ public int64_t get_line_number(file_t *f, const char *p)
//
// Given a pointer, determine which line column it points to.
//
-public int64_t get_line_column(file_t *f, const char *p)
-{
+public
+int64_t get_line_column(file_t *f, const char *p) {
int64_t line_no = get_line_number(f, p);
- int64_t line_offset = f->line_offsets[line_no-1];
+ int64_t line_offset = f->line_offsets[line_no - 1];
return 1 + (int64_t)(p - (f->text + line_offset));
}
//
// Return a pointer to the line with the specified line number (1-indexed)
//
-public const char *get_line(file_t *f, int64_t line_number)
-{
+public
+const char *get_line(file_t *f, int64_t line_number) {
if (line_number == 0 || line_number > (int64_t)f->num_lines) return NULL;
- int64_t line_offset = f->line_offsets[line_number-1];
+ int64_t line_offset = f->line_offsets[line_number - 1];
return f->text + line_offset;
}
//
// Return a value like /foo:line.col
//
-public const char *get_file_pos(file_t *f, const char *p)
-{
+public
+const char *get_file_pos(file_t *f, const char *p) {
return String(f->filename, ":", get_line_number(f, p), ".", get_line_column(f, p));
}
-static int fputc_column(FILE *out, char c, char print_char, int *column)
-{
+static int fputc_column(FILE *out, char c, char print_char, int *column) {
int printed = 0;
if (print_char == '\t') print_char = ' ';
if (c == '\t') {
@@ -206,18 +202,16 @@ static int fputc_column(FILE *out, char c, char print_char, int *column)
//
// Print a span from a file
//
-public int highlight_error(file_t *file, const char *start, const char *end, const char *hl_color, int64_t context_lines, bool use_color)
-{
+public
+int highlight_error(file_t *file, const char *start, const char *end, const char *hl_color, int64_t context_lines,
+ bool use_color) {
if (!file) return 0;
// Handle spans that come from multiple files:
- if (start < file->text || start > file->text + file->len)
- start = end;
- if (end < file->text || end > file->text + file->len)
- end = start;
+ if (start < file->text || start > file->text + file->len) start = end;
+ if (end < file->text || end > file->text + file->len) end = start;
// Just in case neither end of the span came from this file:
- if (end < file->text || end > file->text + file->len)
- start = end = file->text;
+ if (end < file->text || end > file->text + file->len) start = end = file->text;
const char *lineno_prefix, *lineno_suffix, *normal_color, *empty_marker;
bool print_carets = false;
@@ -238,27 +232,25 @@ public int highlight_error(file_t *file, const char *start, const char *end, con
printed += fprint(stderr, file->relative_filename);
}
- if (context_lines == 0)
- return fprint(stderr, hl_color, string_slice(start, (size_t)(end - start)), normal_color);
+ if (context_lines == 0) return fprint(stderr, hl_color, string_slice(start, (size_t)(end - start)), normal_color);
- int64_t start_line = get_line_number(file, start),
- end_line = get_line_number(file, end);
+ int64_t start_line = get_line_number(file, start), end_line = get_line_number(file, end);
- int64_t first_line = start_line - (context_lines - 1),
- last_line = end_line + (context_lines - 1);
+ int64_t first_line = start_line - (context_lines - 1), last_line = end_line + (context_lines - 1);
if (first_line < 1) first_line = 1;
if (last_line > file->num_lines) last_line = file->num_lines;
int digits = 1;
- for (int64_t i = last_line; i > 0; i /= 10) ++digits;
+ for (int64_t i = last_line; i > 0; i /= 10)
+ ++digits;
for (int64_t line_no = first_line; line_no <= last_line; ++line_no) {
if (line_no > first_line + 5 && line_no < last_line - 5) {
if (use_color)
- printed += fprint(stderr, "\x1b[0;2;3;4m ... ", (last_line - first_line) - 11, " lines omitted ... \x1b[m");
- else
- printed += fprint(stderr, " ... ", (last_line - first_line) - 11, " lines omitted ...");
+ printed += fprint(stderr, "\x1b[0;2;3;4m ... ", (last_line - first_line) - 11,
+ " lines omitted ... \x1b[m");
+ else printed += fprint(stderr, " ... ", (last_line - first_line) - 11, " lines omitted ...");
line_no = last_line - 6;
continue;
}
@@ -305,14 +297,10 @@ public int highlight_error(file_t *file, const char *start, const char *end, con
int col = 0;
for (const char *sp = line; *sp && *sp != '\n'; ++sp) {
char print_char;
- if (sp < start)
- print_char = ' ';
- else if (sp == start && sp == end)
- print_char = '^';
- else if (sp >= start && sp < end)
- print_char = '-';
- else
- print_char = ' ';
+ if (sp < start) print_char = ' ';
+ else if (sp == start && sp == end) print_char = '^';
+ else if (sp >= start && sp < end) print_char = '-';
+ else print_char = ' ';
printed += fputc_column(stderr, *sp, print_char, &col);
}
printed += fputs("\n", stderr);
diff --git a/src/stdlib/files.h b/src/stdlib/files.h
index f650f78e..d3e5ebe8 100644
--- a/src/stdlib/files.h
+++ b/src/stdlib/files.h
@@ -16,20 +16,14 @@ typedef struct {
} file_t;
char *resolve_path(const char *path, const char *relative_to, const char *system_path);
-__attribute__((pure, nonnull))
-char *file_base_name(const char *path);
-__attribute__((nonnull))
-file_t *load_file(const char *filename);
-__attribute__((nonnull, returns_nonnull))
-file_t *spoof_file(const char *filename, const char *text);
-__attribute__((pure, nonnull))
-int64_t get_line_number(file_t *f, const char *p);
-__attribute__((pure, nonnull))
-int64_t get_line_column(file_t *f, const char *p);
-__attribute__((pure, nonnull))
-const char *get_line(file_t *f, int64_t line_number);
-__attribute__((pure, nonnull))
-const char *get_file_pos(file_t *f, const char *p);
-int highlight_error(file_t *file, const char *start, const char *end, const char *hl_color, int64_t context_lines, bool use_color);
+__attribute__((pure, nonnull)) char *file_base_name(const char *path);
+__attribute__((nonnull)) file_t *load_file(const char *filename);
+__attribute__((nonnull, returns_nonnull)) file_t *spoof_file(const char *filename, const char *text);
+__attribute__((pure, nonnull)) int64_t get_line_number(file_t *f, const char *p);
+__attribute__((pure, nonnull)) int64_t get_line_column(file_t *f, const char *p);
+__attribute__((pure, nonnull)) const char *get_line(file_t *f, int64_t line_number);
+__attribute__((pure, nonnull)) const char *get_file_pos(file_t *f, const char *p);
+int highlight_error(file_t *file, const char *start, const char *end, const char *hl_color, int64_t context_lines,
+ bool use_color);
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/fpconv.c b/src/stdlib/fpconv.c
index 97699784..8b994cfa 100644
--- a/src/stdlib/fpconv.c
+++ b/src/stdlib/fpconv.c
@@ -6,37 +6,46 @@
#include "fpconv.h"
#include "powers.h"
-#define fracmask 0x000FFFFFFFFFFFFFU
-#define expmask 0x7FF0000000000000U
+#define fracmask 0x000FFFFFFFFFFFFFU
+#define expmask 0x7FF0000000000000U
#define hiddenbit 0x0010000000000000U
-#define signmask 0x8000000000000000U
-#define expbias (1023 + 52)
+#define signmask 0x8000000000000000U
+#define expbias (1023 + 52)
#define absv(n) ((n) < 0 ? -(n) : (n))
#define minv(a, b) ((a) < (b) ? (a) : (b))
-static uint64_t tens[] = {
- 10000000000000000000U, 1000000000000000000U, 100000000000000000U,
- 10000000000000000U, 1000000000000000U, 100000000000000U,
- 10000000000000U, 1000000000000U, 100000000000U,
- 10000000000U, 1000000000U, 100000000U,
- 10000000U, 1000000U, 100000U,
- 10000U, 1000U, 100U,
- 10U, 1U
-};
-
-static inline uint64_t get_dbits(double d)
-{
+static uint64_t tens[] = {10000000000000000000U,
+ 1000000000000000000U,
+ 100000000000000000U,
+ 10000000000000000U,
+ 1000000000000000U,
+ 100000000000000U,
+ 10000000000000U,
+ 1000000000000U,
+ 100000000000U,
+ 10000000000U,
+ 1000000000U,
+ 100000000U,
+ 10000000U,
+ 1000000U,
+ 100000U,
+ 10000U,
+ 1000U,
+ 100U,
+ 10U,
+ 1U};
+
+static inline uint64_t get_dbits(double d) {
union {
- double dbl;
+ double dbl;
uint64_t i;
- } dbl_bits = { d };
+ } dbl_bits = {d};
return dbl_bits.i;
}
-static Fp build_fp(double d)
-{
+static Fp build_fp(double d) {
uint64_t bits = get_dbits(d);
Fp fp;
@@ -54,8 +63,7 @@ static Fp build_fp(double d)
return fp;
}
-static void normalize(Fp* fp)
-{
+static void normalize(Fp *fp) {
while ((fp->frac & hiddenbit) == 0) {
fp->frac <<= 1;
fp->exp--;
@@ -66,10 +74,9 @@ static void normalize(Fp* fp)
fp->exp -= shift;
}
-static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper)
-{
+static void get_normalized_boundaries(Fp *fp, Fp *lower, Fp *upper) {
upper->frac = (fp->frac << 1) + 1;
- upper->exp = fp->exp - 1;
+ upper->exp = fp->exp - 1;
while ((upper->frac & (hiddenbit << 1)) == 0) {
upper->frac <<= 1;
@@ -81,64 +88,55 @@ static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper)
upper->frac <<= u_shift;
upper->exp = upper->exp - u_shift;
-
int l_shift = fp->frac == hiddenbit ? 2 : 1;
lower->frac = (fp->frac << l_shift) - 1;
lower->exp = fp->exp - l_shift;
-
lower->frac <<= lower->exp - upper->exp;
lower->exp = upper->exp;
}
-static Fp multiply(Fp* a, Fp* b)
-{
+static Fp multiply(Fp *a, Fp *b) {
const uint64_t lomask = 0x00000000FFFFFFFF;
- uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask);
+ uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask);
uint64_t al_bh = (a->frac & lomask) * (b->frac >> 32);
uint64_t al_bl = (a->frac & lomask) * (b->frac & lomask);
- uint64_t ah_bh = (a->frac >> 32) * (b->frac >> 32);
+ uint64_t ah_bh = (a->frac >> 32) * (b->frac >> 32);
uint64_t tmp = (ah_bl & lomask) + (al_bh & lomask) + (al_bl >> 32);
/* round up */
tmp += 1U << 31;
- Fp fp = {
- ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32),
- a->exp + b->exp + 64
- };
+ Fp fp = {ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32), a->exp + b->exp + 64};
return fp;
}
-static void round_digit(char* digits, int ndigits, uint64_t delta, uint64_t rem, uint64_t kappa, uint64_t frac)
-{
- while (rem < frac && delta - rem >= kappa &&
- (rem + kappa < frac || frac - rem > rem + kappa - frac)) {
+static void round_digit(char *digits, int ndigits, uint64_t delta, uint64_t rem, uint64_t kappa, uint64_t frac) {
+ while (rem < frac && delta - rem >= kappa && (rem + kappa < frac || frac - rem > rem + kappa - frac)) {
digits[ndigits - 1]--;
rem += kappa;
}
}
-static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K)
-{
+static int generate_digits(Fp *fp, Fp *upper, Fp *lower, char *digits, int *K) {
uint64_t wfrac = upper->frac - fp->frac;
uint64_t delta = upper->frac - lower->frac;
Fp one;
one.frac = 1ULL << -upper->exp;
- one.exp = upper->exp;
+ one.exp = upper->exp;
uint64_t part1 = upper->frac >> -one.exp;
uint64_t part2 = upper->frac & (one.frac - 1);
int idx = 0, kappa = 10;
- uint64_t* divp;
+ uint64_t *divp;
/* 1000000000 */
- for(divp = tens + 10; kappa > 0; divp++) {
+ for (divp = tens + 10; kappa > 0; divp++) {
uint64_t div = *divp;
unsigned digit = part1 / div;
@@ -150,7 +148,7 @@ static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K)
part1 -= digit * div;
kappa--;
- uint64_t tmp = (part1 <<-one.exp) + part2;
+ uint64_t tmp = (part1 << -one.exp) + part2;
if (tmp <= delta) {
*K += kappa;
round_digit(digits, idx, delta, tmp, div << -one.exp, wfrac);
@@ -160,7 +158,7 @@ static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K)
}
/* 10 */
- uint64_t* unit = tens + 18;
+ uint64_t *unit = tens + 18;
while (true) {
part2 *= 10;
@@ -184,8 +182,7 @@ static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K)
}
}
-static int grisu2(double d, char* digits, int* K)
-{
+static int grisu2(double d, char *digits, int *K) {
Fp w = build_fp(d);
Fp lower, upper;
@@ -196,7 +193,7 @@ static int grisu2(double d, char* digits, int* K)
int k;
Fp cp = find_cachedpow10(upper.exp, &k);
- w = multiply(&w, &cp);
+ w = multiply(&w, &cp);
upper = multiply(&upper, &cp);
lower = multiply(&lower, &cp);
@@ -208,8 +205,7 @@ static int grisu2(double d, char* digits, int* K)
return generate_digits(&w, &upper, &lower, digits, K);
}
-static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg)
-{
+static int emit_digits(char *digits, int ndigits, char *dest, int K, bool neg) {
int exp = absv(K + ndigits - 1);
int max_trailing_zeros = 7;
@@ -240,7 +236,7 @@ static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg)
return ndigits + 2 + offset;
- /* fp > 1.0 */
+ /* fp > 1.0 */
} else {
memcpy(dest, digits, (size_t)offset);
dest[offset] = '.';
@@ -288,8 +284,7 @@ static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg)
return idx;
}
-static int filter_special(double fp, char* dest)
-{
+static int filter_special(double fp, char *dest) {
if (fp == 0.0) {
dest[0] = '0';
return 1;
@@ -304,17 +299,20 @@ static int filter_special(double fp, char* dest)
}
if (bits & fracmask) {
- dest[0] = 'n'; dest[1] = 'a'; dest[2] = 'n';
+ dest[0] = 'n';
+ dest[1] = 'a';
+ dest[2] = 'n';
} else {
- dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f';
+ dest[0] = 'i';
+ dest[1] = 'n';
+ dest[2] = 'f';
}
return 3;
}
-int fpconv_dtoa(double d, char dest[24])
-{
+int fpconv_dtoa(double d, char dest[24]) {
char digits[18];
int str_len = 0;
diff --git a/src/stdlib/functiontype.c b/src/stdlib/functiontype.c
index 6d692c6d..a6e12798 100644
--- a/src/stdlib/functiontype.c
+++ b/src/stdlib/functiontype.c
@@ -9,18 +9,17 @@
#include "types.h"
#include "util.h"
-public Text_t Func$as_text(const void *fn, bool colorize, const TypeInfo_t *type)
-{
+public
+Text_t Func$as_text(const void *fn, bool colorize, const TypeInfo_t *type) {
Text_t text = Text$from_str(type->FunctionInfo.type_str);
- if (fn && colorize)
- text = Text$concat(Text("\x1b[32;1m"), text, Text("\x1b[m"));
+ if (fn && colorize) text = Text$concat(Text("\x1b[32;1m"), text, Text("\x1b[m"));
return text;
}
-public PUREFUNC bool Func$is_none(const void *obj, const TypeInfo_t *info)
-{
+public
+PUREFUNC bool Func$is_none(const void *obj, const TypeInfo_t *info) {
(void)info;
- return *(void**)obj == NULL;
+ return *(void **)obj == NULL;
}
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/functiontype.h b/src/stdlib/functiontype.h
index 095d630e..3169cfc9 100644
--- a/src/stdlib/functiontype.h
+++ b/src/stdlib/functiontype.h
@@ -13,20 +13,27 @@ OptionalText_t get_function_name(void *fn);
OptionalText_t get_function_filename(void *fn);
int64_t get_function_line_num(void *fn);
Text_t Func$as_text(const void *fn, bool colorize, const TypeInfo_t *type);
-PUREFUNC bool Func$is_none(const void *obj, const TypeInfo_t*);
+PUREFUNC bool Func$is_none(const void *obj, const TypeInfo_t *);
-#define Func$metamethods { \
- .as_text=Func$as_text, \
- .is_none=Func$is_none, \
- .serialize=cannot_serialize, \
- .deserialize=cannot_deserialize, \
-}
+#define Func$metamethods \
+ { \
+ .as_text = Func$as_text, \
+ .is_none = Func$is_none, \
+ .serialize = cannot_serialize, \
+ .deserialize = cannot_deserialize, \
+ }
-#define Function$info(typestr) &((TypeInfo_t){.size=sizeof(void*), .align=__alignof__(void*), \
- .tag=FunctionInfo, .FunctionInfo.type_str=typestr, \
- .metamethods=Func$metamethods})
-#define Closure$info(typestr) &((TypeInfo_t){.size=sizeof(void*[2]), .align=__alignof__(void*), \
- .tag=FunctionInfo, .FunctionInfo.type_str=typestr, \
- .metamethods=Func$metamethods})
+#define Function$info(typestr) \
+ &((TypeInfo_t){.size = sizeof(void *), \
+ .align = __alignof__(void *), \
+ .tag = FunctionInfo, \
+ .FunctionInfo.type_str = typestr, \
+ .metamethods = Func$metamethods})
+#define Closure$info(typestr) \
+ &((TypeInfo_t){.size = sizeof(void *[2]), \
+ .align = __alignof__(void *), \
+ .tag = FunctionInfo, \
+ .FunctionInfo.type_str = typestr, \
+ .metamethods = Func$metamethods})
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/integers.c b/src/stdlib/integers.c
index e24d984d..93095a70 100644
--- a/src/stdlib/integers.c
+++ b/src/stdlib/integers.c
@@ -17,20 +17,19 @@
#include "text.h"
#include "types.h"
-public int Int$print(FILE *f, Int_t i) {
+public
+int Int$print(FILE *f, Int_t i) {
if (likely(i.small & 1L)) {
- return _print_int(f, (int64_t)((i.small)>>2L));
+ return _print_int(f, (int64_t)((i.small) >> 2L));
} else {
return gmp_fprintf(f, "%Zd", *i.big);
}
}
-static inline Text_t _int64_to_text(int64_t n)
-{
- if (n == INT64_MIN)
- return Text("-9223372036854775808");
+static inline Text_t _int64_to_text(int64_t n) {
+ if (n == INT64_MIN) return Text("-9223372036854775808");
- char buf[21] = {[20]=0}; // Big enough for INT64_MIN + '\0'
+ char buf[21] = {[20] = 0}; // Big enough for INT64_MIN + '\0'
char *p = &buf[19];
bool negative = n < 0;
if (negative) n = -n; // Safe to do because we checked for INT64_MIN earlier
@@ -40,13 +39,13 @@ static inline Text_t _int64_to_text(int64_t n)
n /= 10;
} while (n > 0);
- if (negative)
- *(p--) = '-';
+ if (negative) *(p--) = '-';
return Text$from_strn(p + 1, (size_t)(&buf[19] - p));
}
-public Text_t Int$value_as_text(Int_t i) {
+public
+Text_t Int$value_as_text(Int_t i) {
if (likely(i.small & 1L)) {
return _int64_to_text(i.small >> 2L);
} else {
@@ -55,74 +54,76 @@ public Text_t Int$value_as_text(Int_t i) {
}
}
-public Text_t Int$as_text(const void *i, bool colorize, const TypeInfo_t *info) {
+public
+Text_t Int$as_text(const void *i, bool colorize, const TypeInfo_t *info) {
(void)info;
if (!i) return Text("Int");
- Text_t text = Int$value_as_text(*(Int_t*)i);
+ Text_t text = Int$value_as_text(*(Int_t *)i);
if (colorize) text = Text$concat(Text("\x1b[35m"), text, Text("\x1b[m"));
return text;
}
-static bool Int$is_none(const void *i, const TypeInfo_t *info)
-{
+static bool Int$is_none(const void *i, const TypeInfo_t *info) {
(void)info;
- return ((Int_t*)i)->small == 0L;
+ return ((Int_t *)i)->small == 0L;
}
-public PUREFUNC int32_t Int$compare_value(const Int_t x, const Int_t y) {
- if (likely(x.small & y.small & 1L))
- return (x.small > y.small) - (x.small < y.small);
- else if (x.small & 1)
- return -mpz_cmp_si(*y.big, x.small);
- else if (y.small & 1)
- return mpz_cmp_si(*x.big, y.small);
- else
- return x.big == y.big ? 0 : mpz_cmp(*x.big, *y.big);
+public
+PUREFUNC int32_t Int$compare_value(const Int_t x, const Int_t y) {
+ if (likely(x.small & y.small & 1L)) return (x.small > y.small) - (x.small < y.small);
+ else if (x.small & 1) return -mpz_cmp_si(*y.big, x.small);
+ else if (y.small & 1) return mpz_cmp_si(*x.big, y.small);
+ else return x.big == y.big ? 0 : mpz_cmp(*x.big, *y.big);
}
-public PUREFUNC int32_t Int$compare(const void *x, const void *y, const TypeInfo_t *info) {
+public
+PUREFUNC int32_t Int$compare(const void *x, const void *y, const TypeInfo_t *info) {
(void)info;
- return Int$compare_value(*(Int_t*)x, *(Int_t*)y);
+ return Int$compare_value(*(Int_t *)x, *(Int_t *)y);
}
-public PUREFUNC bool Int$equal_value(const Int_t x, const Int_t y) {
- if (likely((x.small | y.small) & 1L))
- return x.small == y.small;
- else
- return x.big == y.big ? 0 : (mpz_cmp(*x.big, *y.big) == 0);
+public
+PUREFUNC bool Int$equal_value(const Int_t x, const Int_t y) {
+ if (likely((x.small | y.small) & 1L)) return x.small == y.small;
+ else return x.big == y.big ? 0 : (mpz_cmp(*x.big, *y.big) == 0);
}
-public PUREFUNC bool Int$equal(const void *x, const void *y, const TypeInfo_t *info) {
+public
+PUREFUNC bool Int$equal(const void *x, const void *y, const TypeInfo_t *info) {
(void)info;
- return Int$equal_value(*(Int_t*)x, *(Int_t*)y);
+ return Int$equal_value(*(Int_t *)x, *(Int_t *)y);
}
-public CONSTFUNC Int_t Int$clamped(Int_t x, Int_t low, Int_t high) {
+public
+CONSTFUNC Int_t Int$clamped(Int_t x, Int_t low, Int_t high) {
return (Int$compare(&x, &low, &Int$info) <= 0) ? low : (Int$compare(&x, &high, &Int$info) >= 0 ? high : x);
}
-public CONSTFUNC bool Int$is_between(const Int_t x, const Int_t low, const Int_t high) {
+public
+CONSTFUNC bool Int$is_between(const Int_t x, const Int_t low, const Int_t high) {
return Int$compare_value(low, x) <= 0 && Int$compare_value(x, high) <= 0;
}
-public PUREFUNC uint64_t Int$hash(const void *vx, const TypeInfo_t *info) {
+public
+PUREFUNC uint64_t Int$hash(const void *vx, const TypeInfo_t *info) {
(void)info;
- Int_t *x = (Int_t*)vx;
+ Int_t *x = (Int_t *)vx;
if (likely(x->small & 1L)) {
- return siphash24((void*)x, sizeof(Int_t));
+ return siphash24((void *)x, sizeof(Int_t));
} else {
char *str = mpz_get_str(NULL, 16, *x->big);
- return siphash24((void*)str, strlen(str));
+ return siphash24((void *)str, strlen(str));
}
}
-public Text_t Int$hex(Int_t i, Int_t digits_int, bool uppercase, bool prefix) {
- if (Int$is_negative(i))
- return Text$concat(Text("-"), Int$hex(Int$negative(i), digits_int, uppercase, prefix));
+public
+Text_t Int$hex(Int_t i, Int_t digits_int, bool uppercase, bool prefix) {
+ if (Int$is_negative(i)) return Text$concat(Text("-"), Int$hex(Int$negative(i), digits_int, uppercase, prefix));
if (likely(i.small & 1L)) {
uint64_t u64 = (uint64_t)(i.small >> 2);
- return Text$from_str(String(hex(u64, .no_prefix=!prefix, .digits=Int32$from_int(digits_int, false), .uppercase=uppercase)));
+ return Text$from_str(String(
+ hex(u64, .no_prefix = !prefix, .digits = Int32$from_int(digits_int, false), .uppercase = uppercase)));
} else {
char *str = mpz_get_str(NULL, 16, *i.big);
if (uppercase) {
@@ -131,97 +132,88 @@ public Text_t Int$hex(Int_t i, Int_t digits_int, bool uppercase, bool prefix) {
}
int64_t digits = Int64$from_int(digits_int, false);
int64_t needed_zeroes = digits - (int64_t)strlen(str);
- if (needed_zeroes <= 0)
- return prefix ? Text$concat(Text("0x"), Text$from_str(str)) : Text$from_str(str);
+ if (needed_zeroes <= 0) return prefix ? Text$concat(Text("0x"), Text$from_str(str)) : Text$from_str(str);
char *zeroes = GC_MALLOC_ATOMIC((size_t)(needed_zeroes));
memset(zeroes, '0', (size_t)(needed_zeroes));
- if (prefix)
- return Text$concat(Text("0x"), Text$from_str(zeroes), Text$from_str(str));
- else
- return Text$concat(Text$from_str(zeroes), Text$from_str(str));
+ if (prefix) return Text$concat(Text("0x"), Text$from_str(zeroes), Text$from_str(str));
+ else return Text$concat(Text$from_str(zeroes), Text$from_str(str));
}
}
-public Text_t Int$octal(Int_t i, Int_t digits_int, bool prefix) {
- if (Int$is_negative(i))
- return Text$concat(Text("-"), Int$octal(Int$negative(i), digits_int, prefix));
+public
+Text_t Int$octal(Int_t i, Int_t digits_int, bool prefix) {
+ if (Int$is_negative(i)) return Text$concat(Text("-"), Int$octal(Int$negative(i), digits_int, prefix));
if (likely(i.small & 1L)) {
uint64_t u64 = (uint64_t)(i.small >> 2);
- return Text$from_str(String(oct(u64, .no_prefix=!prefix, .digits=Int32$from_int(digits_int, false))));
+ return Text$from_str(String(oct(u64, .no_prefix = !prefix, .digits = Int32$from_int(digits_int, false))));
} else {
int64_t digits = Int64$from_int(digits_int, false);
char *str = mpz_get_str(NULL, 8, *i.big);
int64_t needed_zeroes = digits - (int64_t)strlen(str);
- if (needed_zeroes <= 0)
- return prefix ? Text$concat(Text("0o"), Text$from_str(str)) : Text$from_str(str);
+ if (needed_zeroes <= 0) return prefix ? Text$concat(Text("0o"), Text$from_str(str)) : Text$from_str(str);
char *zeroes = GC_MALLOC_ATOMIC((size_t)(needed_zeroes));
memset(zeroes, '0', (size_t)(needed_zeroes));
- if (prefix)
- return Text$concat(Text("0o"), Text$from_str(zeroes), Text$from_str(str));
- else
- return Text$concat(Text$from_str(zeroes), Text$from_str(str));
+ if (prefix) return Text$concat(Text("0o"), Text$from_str(zeroes), Text$from_str(str));
+ else return Text$concat(Text$from_str(zeroes), Text$from_str(str));
}
}
-public Int_t Int$slow_plus(Int_t x, Int_t y) {
+public
+Int_t Int$slow_plus(Int_t x, Int_t y) {
mpz_t result;
mpz_init_set_int(result, x);
if (y.small & 1L) {
- if (y.small < 0L)
- mpz_sub_ui(result, result, (uint64_t)(-(y.small >> 2L)));
- else
- mpz_add_ui(result, result, (uint64_t)(y.small >> 2L));
+ if (y.small < 0L) mpz_sub_ui(result, result, (uint64_t)(-(y.small >> 2L)));
+ else mpz_add_ui(result, result, (uint64_t)(y.small >> 2L));
} else {
mpz_add(result, result, *y.big);
}
return Int$from_mpz(result);
}
-public Int_t Int$slow_minus(Int_t x, Int_t y) {
+public
+Int_t Int$slow_minus(Int_t x, Int_t y) {
mpz_t result;
mpz_init_set_int(result, x);
if (y.small & 1L) {
- if (y.small < 0L)
- mpz_add_ui(result, result, (uint64_t)(-(y.small >> 2L)));
- else
- mpz_sub_ui(result, result, (uint64_t)(y.small >> 2L));
+ if (y.small < 0L) mpz_add_ui(result, result, (uint64_t)(-(y.small >> 2L)));
+ else mpz_sub_ui(result, result, (uint64_t)(y.small >> 2L));
} else {
mpz_sub(result, result, *y.big);
}
return Int$from_mpz(result);
}
-public Int_t Int$slow_times(Int_t x, Int_t y) {
+public
+Int_t Int$slow_times(Int_t x, Int_t y) {
mpz_t result;
mpz_init_set_int(result, x);
- if (y.small & 1L)
- mpz_mul_si(result, result, y.small >> 2L);
- else
- mpz_mul(result, result, *y.big);
+ if (y.small & 1L) mpz_mul_si(result, result, y.small >> 2L);
+ else mpz_mul(result, result, *y.big);
return Int$from_mpz(result);
}
-public Int_t Int$slow_divided_by(Int_t dividend, Int_t divisor) {
- // Euclidean division, see: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
+public
+Int_t Int$slow_divided_by(Int_t dividend, Int_t divisor) {
+ // Euclidean division, see:
+ // https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
mpz_t quotient, remainder;
mpz_init_set_int(quotient, dividend);
mpz_init_set_int(remainder, divisor);
mpz_tdiv_qr(quotient, remainder, quotient, remainder);
if (mpz_sgn(remainder) < 0) {
bool d_positive = likely(divisor.small & 1L) ? divisor.small > 0x1L : mpz_sgn(*divisor.big) > 0;
- if (d_positive)
- mpz_sub_ui(quotient, quotient, 1);
- else
- mpz_add_ui(quotient, quotient, 1);
+ if (d_positive) mpz_sub_ui(quotient, quotient, 1);
+ else mpz_add_ui(quotient, quotient, 1);
}
return Int$from_mpz(quotient);
}
-public Int_t Int$slow_modulo(Int_t x, Int_t modulus)
-{
+public
+Int_t Int$slow_modulo(Int_t x, Int_t modulus) {
mpz_t result;
mpz_init_set_int(result, x);
mpz_t divisor;
@@ -230,8 +222,8 @@ public Int_t Int$slow_modulo(Int_t x, Int_t modulus)
return Int$from_mpz(result);
}
-public Int_t Int$slow_modulo1(Int_t x, Int_t modulus)
-{
+public
+Int_t Int$slow_modulo1(Int_t x, Int_t modulus) {
mpz_t result;
mpz_init_set_int(result, x);
mpz_sub_ui(result, result, 1);
@@ -242,8 +234,8 @@ public Int_t Int$slow_modulo1(Int_t x, Int_t modulus)
return Int$from_mpz(result);
}
-public Int_t Int$slow_left_shifted(Int_t x, Int_t y)
-{
+public
+Int_t Int$slow_left_shifted(Int_t x, Int_t y) {
mp_bitcnt_t bits = (mp_bitcnt_t)Int64$from_int(y, false);
mpz_t result;
mpz_init_set_int(result, x);
@@ -251,8 +243,8 @@ public Int_t Int$slow_left_shifted(Int_t x, Int_t y)
return Int$from_mpz(result);
}
-public Int_t Int$slow_right_shifted(Int_t x, Int_t y)
-{
+public
+Int_t Int$slow_right_shifted(Int_t x, Int_t y) {
mp_bitcnt_t bits = (mp_bitcnt_t)Int64$from_int(y, false);
mpz_t result;
mpz_init_set_int(result, x);
@@ -260,8 +252,8 @@ public Int_t Int$slow_right_shifted(Int_t x, Int_t y)
return Int$from_mpz(result);
}
-public Int_t Int$slow_bit_and(Int_t x, Int_t y)
-{
+public
+Int_t Int$slow_bit_and(Int_t x, Int_t y) {
mpz_t result;
mpz_init_set_int(result, x);
mpz_t y_mpz;
@@ -270,8 +262,8 @@ public Int_t Int$slow_bit_and(Int_t x, Int_t y)
return Int$from_mpz(result);
}
-public Int_t Int$slow_bit_or(Int_t x, Int_t y)
-{
+public
+Int_t Int$slow_bit_or(Int_t x, Int_t y) {
mpz_t result;
mpz_init_set_int(result, x);
mpz_t y_mpz;
@@ -280,8 +272,8 @@ public Int_t Int$slow_bit_or(Int_t x, Int_t y)
return Int$from_mpz(result);
}
-public Int_t Int$slow_bit_xor(Int_t x, Int_t y)
-{
+public
+Int_t Int$slow_bit_xor(Int_t x, Int_t y) {
mpz_t result;
mpz_init_set_int(result, x);
mpz_t y_mpz;
@@ -290,8 +282,8 @@ public Int_t Int$slow_bit_xor(Int_t x, Int_t y)
return Int$from_mpz(result);
}
-public Int_t Int$slow_negated(Int_t x)
-{
+public
+Int_t Int$slow_negated(Int_t x) {
mpz_t result;
mpz_init_set_int(result, x);
mpz_neg(result, result);
@@ -299,10 +291,9 @@ public Int_t Int$slow_negated(Int_t x)
return Int$from_mpz(result);
}
-public Int_t Int$slow_negative(Int_t x)
-{
- if (likely(x.small & 1L))
- return (Int_t){.small=4L*-((x.small)>>2L) + 1L};
+public
+Int_t Int$slow_negative(Int_t x) {
+ if (likely(x.small & 1L)) return (Int_t){.small = 4L * -((x.small) >> 2L) + 1L};
mpz_t result;
mpz_init_set_int(result, x);
@@ -310,10 +301,9 @@ public Int_t Int$slow_negative(Int_t x)
return Int$from_mpz(result);
}
-public Int_t Int$abs(Int_t x)
-{
- if (likely(x.small & 1L))
- return (Int_t){.small=4L*labs((x.small)>>2L) + 1L};
+public
+Int_t Int$abs(Int_t x) {
+ if (likely(x.small & 1L)) return (Int_t){.small = 4L * labs((x.small) >> 2L) + 1L};
mpz_t result;
mpz_init_set_int(result, x);
@@ -321,53 +311,45 @@ public Int_t Int$abs(Int_t x)
return Int$from_mpz(result);
}
-public Int_t Int$power(Int_t base, Int_t exponent)
-{
+public
+Int_t Int$power(Int_t base, Int_t exponent) {
int64_t exp = Int64$from_int(exponent, false);
- if (unlikely(exp < 0))
- fail("Cannot take a negative power of an integer!");
+ if (unlikely(exp < 0)) fail("Cannot take a negative power of an integer!");
mpz_t result;
mpz_init_set_int(result, base);
mpz_pow_ui(result, result, (uint64_t)exp);
return Int$from_mpz(result);
}
-public Int_t Int$gcd(Int_t x, Int_t y)
-{
- if (likely(x.small & y.small & 0x1L))
- return I_small(Int32$gcd(x.small >> 2L, y.small >> 2L));
+public
+Int_t Int$gcd(Int_t x, Int_t y) {
+ if (likely(x.small & y.small & 0x1L)) return I_small(Int32$gcd(x.small >> 2L, y.small >> 2L));
mpz_t result;
mpz_init(result);
- if (x.small & 0x1L)
- mpz_gcd_ui(result, *y.big, (uint64_t)labs(x.small>>2L));
- else if (y.small & 0x1L)
- mpz_gcd_ui(result, *x.big, (uint64_t)labs(y.small>>2L));
- else
- mpz_gcd(result, *x.big, *y.big);
+ if (x.small & 0x1L) mpz_gcd_ui(result, *y.big, (uint64_t)labs(x.small >> 2L));
+ else if (y.small & 0x1L) mpz_gcd_ui(result, *x.big, (uint64_t)labs(y.small >> 2L));
+ else mpz_gcd(result, *x.big, *y.big);
return Int$from_mpz(result);
}
-public OptionalInt_t Int$sqrt(Int_t i)
-{
- if (Int$compare_value(i, I(0)) < 0)
- return NONE_INT;
+public
+OptionalInt_t Int$sqrt(Int_t i) {
+ if (Int$compare_value(i, I(0)) < 0) return NONE_INT;
mpz_t result;
mpz_init_set_int(result, i);
mpz_sqrt(result, result);
return Int$from_mpz(result);
}
-public bool Int$get_bit(Int_t x, Int_t bit_index)
-{
+public
+bool Int$get_bit(Int_t x, Int_t bit_index) {
mpz_t i;
mpz_init_set_int(i, x);
- if (Int$compare_value(bit_index, I(1)) < 0)
- fail("Invalid bit index (expected 1 or higher): ", bit_index);
- if (Int$compare_value(bit_index, Int$from_int64(INT64_MAX)) > 0)
- fail("Bit index is too large! ", bit_index);
+ if (Int$compare_value(bit_index, I(1)) < 0) fail("Invalid bit index (expected 1 or higher): ", bit_index);
+ if (Int$compare_value(bit_index, Int$from_int64(INT64_MAX)) > 0) fail("Bit index is too large! ", bit_index);
- int is_bit_set = mpz_tstbit(i, (mp_bitcnt_t)(Int64$from_int(bit_index, true)-1));
+ int is_bit_set = mpz_tstbit(i, (mp_bitcnt_t)(Int64$from_int(bit_index, true) - 1));
return (bool)is_bit_set;
}
@@ -376,37 +358,41 @@ typedef struct {
Int_t step;
} IntRange_t;
-static OptionalInt_t _next_int(IntRange_t *info)
-{
+static OptionalInt_t _next_int(IntRange_t *info) {
OptionalInt_t i = info->current;
if (!Int$is_none(&i, &Int$info)) {
Int_t next = Int$plus(i, info->step);
- if (!Int$is_none(&info->last, &Int$info) && Int$compare_value(next, info->last) == Int$compare_value(info->step, I(0)))
+ if (!Int$is_none(&info->last, &Int$info)
+ && Int$compare_value(next, info->last) == Int$compare_value(info->step, I(0)))
next = NONE_INT;
info->current = next;
}
return i;
}
-public PUREFUNC Closure_t Int$to(Int_t first, Int_t last, OptionalInt_t step) {
+public
+PUREFUNC Closure_t Int$to(Int_t first, Int_t last, OptionalInt_t step) {
IntRange_t *range = GC_MALLOC(sizeof(IntRange_t));
range->current = first;
range->last = last;
- range->step = Int$is_none(&step, &Int$info) ?
- Int$compare_value(last, first) >= 0 ? (Int_t){.small=(1L<<2L)|1L} : (Int_t){.small=(-1L>>2L)|1L}
- : step;
- return (Closure_t){.fn=_next_int, .userdata=range};
+ range->step = Int$is_none(&step, &Int$info) ? Int$compare_value(last, first) >= 0
+ ? (Int_t){.small = (1L << 2L) | 1L}
+ : (Int_t){.small = (-1L >> 2L) | 1L}
+ : step;
+ return (Closure_t){.fn = _next_int, .userdata = range};
}
-public PUREFUNC Closure_t Int$onward(Int_t first, Int_t step) {
+public
+PUREFUNC Closure_t Int$onward(Int_t first, Int_t step) {
IntRange_t *range = GC_MALLOC(sizeof(IntRange_t));
range->current = first;
range->last = NONE_INT;
range->step = step;
- return (Closure_t){.fn=_next_int, .userdata=range};
+ return (Closure_t){.fn = _next_int, .userdata = range};
}
-public Int_t Int$from_str(const char *str) {
+public
+Int_t Int$from_str(const char *str) {
mpz_t i;
int result;
if (strncmp(str, "0x", 2) == 0) {
@@ -418,12 +404,12 @@ public Int_t Int$from_str(const char *str) {
} else {
result = mpz_init_set_str(i, str, 10);
}
- if (result != 0)
- return NONE_INT;
+ if (result != 0) return NONE_INT;
return Int$from_mpz(i);
}
-public OptionalInt_t Int$parse(Text_t text, Text_t *remainder) {
+public
+OptionalInt_t Int$parse(Text_t text, Text_t *remainder) {
const char *str = Text$as_c_string(text);
mpz_t i;
int result;
@@ -455,8 +441,8 @@ public OptionalInt_t Int$parse(Text_t text, Text_t *remainder) {
return Int$from_mpz(i);
}
-public bool Int$is_prime(Int_t x, Int_t reps)
-{
+public
+bool Int$is_prime(Int_t x, Int_t reps) {
mpz_t p;
mpz_init_set_int(p, x);
if (unlikely(Int$compare_value(reps, I(9999)) > 0))
@@ -465,8 +451,8 @@ public bool Int$is_prime(Int_t x, Int_t reps)
return (mpz_probab_prime_p(p, reps_int) != 0);
}
-public Int_t Int$next_prime(Int_t x)
-{
+public
+Int_t Int$next_prime(Int_t x) {
mpz_t p;
mpz_init_set_int(p, x);
mpz_nextprime(p, p);
@@ -475,28 +461,25 @@ public Int_t Int$next_prime(Int_t x)
#if __GNU_MP_VERSION >= 6
#if __GNU_MP_VERSION_MINOR >= 3
-public OptionalInt_t Int$prev_prime(Int_t x)
-{
+public
+OptionalInt_t Int$prev_prime(Int_t x) {
mpz_t p;
mpz_init_set_int(p, x);
- if (unlikely(mpz_prevprime(p, p) == 0))
- return NONE_INT;
+ if (unlikely(mpz_prevprime(p, p) == 0)) return NONE_INT;
return Int$from_mpz(p);
}
#endif
#endif
-public Int_t Int$choose(Int_t n, Int_t k)
-{
- if unlikely (Int$compare_value(n, I_small(0)) < 0)
- fail("Negative inputs are not supported for choose()");
+public
+Int_t Int$choose(Int_t n, Int_t k) {
+ if unlikely (Int$compare_value(n, I_small(0)) < 0) fail("Negative inputs are not supported for choose()");
mpz_t ret;
mpz_init(ret);
int64_t k_i64 = Int64$from_int(k, false);
- if unlikely (k_i64 < 0)
- fail("Negative inputs are not supported for choose()");
+ if unlikely (k_i64 < 0) fail("Negative inputs are not supported for choose()");
if likely (n.small & 1L) {
mpz_bin_uiui(ret, (unsigned long)(n.small >> 2L), (unsigned long)k_i64);
@@ -508,21 +491,19 @@ public Int_t Int$choose(Int_t n, Int_t k)
return Int$from_mpz(ret);
}
-public Int_t Int$factorial(Int_t n)
-{
+public
+Int_t Int$factorial(Int_t n) {
mpz_t ret;
mpz_init(ret);
int64_t n_i64 = Int64$from_int(n, false);
- if unlikely (n_i64 < 0)
- fail("Factorials are not defined for negative numbers");
+ if unlikely (n_i64 < 0) fail("Factorials are not defined for negative numbers");
mpz_fac_ui(ret, (unsigned long)n_i64);
return Int$from_mpz(ret);
}
-static void Int$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *info)
-{
+static void Int$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *info) {
(void)info;
- Int_t i = *(Int_t*)obj;
+ Int_t i = *(Int_t *)obj;
if (likely(i.small & 1L)) {
fputc(0, out);
int64_t i64 = i.small >> 2L;
@@ -530,44 +511,45 @@ static void Int$serialize(const void *obj, FILE *out, Table_t *pointers, const T
} else {
fputc(1, out);
mpz_t n;
- mpz_init_set_int(n, *(Int_t*)obj);
+ mpz_init_set_int(n, *(Int_t *)obj);
mpz_out_raw(out, n);
}
}
-static void Int$deserialize(FILE *in, void *obj, List_t *pointers, const TypeInfo_t *info)
-{
+static void Int$deserialize(FILE *in, void *obj, List_t *pointers, const TypeInfo_t *info) {
(void)info;
if (fgetc(in) == 0) {
int64_t i = 0;
Int64$deserialize(in, &i, pointers, &Int64$info);
- *(Int_t*)obj = (Int_t){.small=(i<<2L) | 1L};
+ *(Int_t *)obj = (Int_t){.small = (i << 2L) | 1L};
} else {
mpz_t n;
mpz_init(n);
mpz_inp_raw(n, in);
- *(Int_t*)obj = Int$from_mpz(n);
+ *(Int_t *)obj = Int$from_mpz(n);
}
}
-public const TypeInfo_t Int$info = {
- .size=sizeof(Int_t),
- .align=__alignof__(Int_t),
- .metamethods={
- .compare=Int$compare,
- .equal=Int$equal,
- .hash=Int$hash,
- .as_text=Int$as_text,
- .is_none=Int$is_none,
- .serialize=Int$serialize,
- .deserialize=Int$deserialize,
- },
+public
+const TypeInfo_t Int$info = {
+ .size = sizeof(Int_t),
+ .align = __alignof__(Int_t),
+ .metamethods =
+ {
+ .compare = Int$compare,
+ .equal = Int$equal,
+ .hash = Int$hash,
+ .as_text = Int$as_text,
+ .is_none = Int$is_none,
+ .serialize = Int$serialize,
+ .deserialize = Int$deserialize,
+ },
};
-public void Int64$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *info)
-{
+public
+void Int64$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *info) {
(void)info, (void)pointers;
- int64_t i = *(int64_t*)obj;
+ int64_t i = *(int64_t *)obj;
uint64_t z = (uint64_t)((i << 1L) ^ (i >> 63L)); // Zigzag encode
while (z >= 0x80L) {
fputc((uint8_t)(z | 0x80L), out);
@@ -576,22 +558,22 @@ public void Int64$serialize(const void *obj, FILE *out, Table_t *pointers, const
fputc((uint8_t)z, out);
}
-public void Int64$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *info)
-{
+public
+void Int64$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *info) {
(void)info, (void)pointers;
uint64_t z = 0;
- for(size_t shift = 0; ; shift += 7) {
+ for (size_t shift = 0;; shift += 7) {
uint8_t byte = (uint8_t)fgetc(in);
z |= ((uint64_t)(byte & 0x7F)) << shift;
if ((byte & 0x80) == 0) break;
}
- *(int64_t*)outval = (int64_t)((z >> 1L) ^ -(z & 1L)); // Zigzag decode
+ *(int64_t *)outval = (int64_t)((z >> 1L) ^ -(z & 1L)); // Zigzag decode
}
-public void Int32$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *info)
-{
+public
+void Int32$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *info) {
(void)info, (void)pointers;
- int32_t i = *(int32_t*)obj;
+ int32_t i = *(int32_t *)obj;
uint32_t z = (uint32_t)((i << 1) ^ (i >> 31)); // Zigzag encode
while (z >= 0x80) {
fputc((uint8_t)(z | 0x80), out);
@@ -600,16 +582,16 @@ public void Int32$serialize(const void *obj, FILE *out, Table_t *pointers, const
fputc((uint8_t)z, out);
}
-public void Int32$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *info)
-{
+public
+void Int32$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *info) {
(void)info, (void)pointers;
uint32_t z = 0;
- for(size_t shift = 0; ; shift += 7) {
+ for (size_t shift = 0;; shift += 7) {
uint8_t byte = (uint8_t)fgetc(in);
z |= ((uint32_t)(byte & 0x7F)) << shift;
if ((byte & 0x80) == 0) break;
}
- *(int32_t*)outval = (int32_t)((z >> 1L) ^ -(z & 1L)); // Zigzag decode
+ *(int32_t *)outval = (int32_t)((z >> 1L) ^ -(z & 1L)); // Zigzag decode
}
// The space savings for smaller ints are not worth having:
@@ -619,122 +601,146 @@ public void Int32$deserialize(FILE *in, void *outval, List_t *pointers, const Ty
#define Int8$deserialize NULL
#ifdef __TINYC__
-#define __builtin_add_overflow(x, y, result) ({ *(result) = (x) + (y); false; })
+#define __builtin_add_overflow(x, y, result) \
+ ({ \
+ *(result) = (x) + (y); \
+ false; \
+ })
#endif
-#define DEFINE_INT_TYPE(c_type, KindOfInt, min_val, max_val, to_attr)\
- public Text_t KindOfInt ## $as_text(const void *i, bool colorize, const TypeInfo_t *info) { \
- (void)info; \
- if (!i) return Text(#KindOfInt); \
- Text_t text = _int64_to_text((int64_t)(*(c_type*)i)); \
- return colorize ? Texts(Text("\033[35m"), text, Text("\033[m")) : text; \
- } \
- public PUREFUNC int32_t KindOfInt ## $compare(const void *x, const void *y, const TypeInfo_t *info) { \
- (void)info; \
- return (*(c_type*)x > *(c_type*)y) - (*(c_type*)x < *(c_type*)y); \
- } \
- public PUREFUNC bool KindOfInt ## $equal(const void *x, const void *y, const TypeInfo_t *info) { \
- (void)info; \
- return *(c_type*)x == *(c_type*)y; \
- } \
- public CONSTFUNC bool KindOfInt ## $is_between(const c_type x, const c_type low, const c_type high) { \
- return low <= x && x <= high; \
- } \
- public CONSTFUNC c_type KindOfInt ## $clamped(c_type x, c_type min, c_type max) { \
- return x < min ? min : (x > max ? max : x); \
- } \
- public Text_t KindOfInt ## $hex(c_type i, Int_t digits_int, bool uppercase, bool prefix) { \
- Int_t as_int = Int$from_int64((int64_t)i); \
- return Int$hex(as_int, digits_int, uppercase, prefix); \
- } \
- public Text_t KindOfInt ## $octal(c_type i, Int_t digits_int, bool prefix) { \
- Int_t as_int = Int$from_int64((int64_t)i); \
- return Int$octal(as_int, digits_int, prefix); \
- } \
- public List_t KindOfInt ## $bits(c_type x) { \
- List_t bit_list = (List_t){.data=GC_MALLOC_ATOMIC(sizeof(bool[8*sizeof(c_type)])), .atomic=1, .stride=sizeof(bool), .length=8*sizeof(c_type)}; \
- bool *bits = bit_list.data + sizeof(c_type)*8; \
- for (size_t i = 0; i < 8*sizeof(c_type); i++) { \
- *(bits--) = x & 1; \
- x >>= 1; \
- } \
- return bit_list; \
- } \
- public bool KindOfInt ## $get_bit(c_type x, Int_t bit_index) { \
- if (Int$compare_value(bit_index, I(1)) < 0) \
- fail("Invalid bit index (expected 1 or higher): ", bit_index); \
- if (Int$compare_value(bit_index, Int$from_int64(sizeof(c_type)*8)) > 0) \
- fail("Bit index is too large! There are only ", (uint64_t)sizeof(c_type)*8, " bits, but index is: ", bit_index); \
- return ((x & (c_type)(1L << (Int64$from_int(bit_index, true)-1L))) != 0); \
- } \
- typedef struct { \
- Optional##KindOfInt##_t current, last; \
- KindOfInt##_t step; \
- } KindOfInt##Range_t; \
- static Optional##KindOfInt##_t _next_##KindOfInt(KindOfInt##Range_t *info) \
- { \
- Optional##KindOfInt##_t i = info->current; \
- if (!i.is_none) { \
- KindOfInt##_t next; bool overflow = __builtin_add_overflow(i.value, info->step, &next); \
- if (overflow || (!info->last.is_none && (info->step >= 0 ? next > info->last.value : next < info->last.value))) \
- info->current = (Optional##KindOfInt##_t){.is_none=true}; \
- else \
- info->current = (Optional##KindOfInt##_t){.value=next}; \
- } \
- return i; \
- } \
- public to_attr Closure_t KindOfInt ## $to(c_type first, c_type last, Optional ## KindOfInt ## _t step) { \
- KindOfInt##Range_t *range = GC_MALLOC(sizeof(KindOfInt##Range_t)); \
- range->current = (Optional##KindOfInt##_t){.value=first}; \
- range->last = (Optional##KindOfInt##_t){.value=last}; \
- range->step = step.is_none ? (last >= first ? 1 : -1) : step.value; \
- return (Closure_t){.fn=_next_##KindOfInt, .userdata=range}; \
- } \
- public to_attr Closure_t KindOfInt ## $onward(c_type first, c_type step) { \
- KindOfInt##Range_t *range = GC_MALLOC(sizeof(KindOfInt##Range_t)); \
- range->current = (Optional##KindOfInt##_t){.value=first}; \
- range->last = (Optional##KindOfInt##_t){.is_none=true}; \
- range->step = step; \
- return (Closure_t){.fn=_next_##KindOfInt, .userdata=range}; \
- } \
- public PUREFUNC Optional ## KindOfInt ## _t KindOfInt ## $parse(Text_t text, Text_t *remainder) { \
- OptionalInt_t full_int = Int$parse(text, remainder); \
- if (full_int.small == 0L) return (Optional ## KindOfInt ## _t){.is_none=true}; \
- if (Int$compare_value(full_int, I(min_val)) < 0) { \
- return (Optional ## KindOfInt ## _t){.is_none=true}; \
- } \
- if (Int$compare_value(full_int, I(max_val)) > 0) { \
- return (Optional ## KindOfInt ## _t){.is_none=true}; \
- } \
- return (Optional ## KindOfInt ## _t){.value=KindOfInt##$from_int(full_int, true)}; \
- } \
- public CONSTFUNC c_type KindOfInt ## $gcd(c_type x, c_type y) { \
- if (x == 0 || y == 0) return 0; \
- x = KindOfInt##$abs(x); \
- y = KindOfInt##$abs(y); \
- while (x != y) { \
- if (x > y) x -= y; \
- else y -= x; \
- } \
- return x; \
- } \
- public const c_type KindOfInt##$min = min_val; \
- public const c_type KindOfInt##$max = max_val; \
- public const TypeInfo_t KindOfInt##$info = { \
- .size=sizeof(c_type), \
- .align=__alignof__(c_type), \
- .metamethods={ \
- .compare=KindOfInt##$compare, \
- .as_text=KindOfInt##$as_text, \
- .serialize=KindOfInt##$serialize, \
- .deserialize=KindOfInt##$deserialize, \
- }, \
+#define DEFINE_INT_TYPE(c_type, KindOfInt, min_val, max_val, to_attr) \
+ public \
+ Text_t KindOfInt##$as_text(const void *i, bool colorize, const TypeInfo_t *info) { \
+ (void)info; \
+ if (!i) return Text(#KindOfInt); \
+ Text_t text = _int64_to_text((int64_t)(*(c_type *)i)); \
+ return colorize ? Texts(Text("\033[35m"), text, Text("\033[m")) : text; \
+ } \
+ public \
+ PUREFUNC int32_t KindOfInt##$compare(const void *x, const void *y, const TypeInfo_t *info) { \
+ (void)info; \
+ return (*(c_type *)x > *(c_type *)y) - (*(c_type *)x < *(c_type *)y); \
+ } \
+ public \
+ PUREFUNC bool KindOfInt##$equal(const void *x, const void *y, const TypeInfo_t *info) { \
+ (void)info; \
+ return *(c_type *)x == *(c_type *)y; \
+ } \
+ public \
+ CONSTFUNC bool KindOfInt##$is_between(const c_type x, const c_type low, const c_type high) { \
+ return low <= x && x <= high; \
+ } \
+ public \
+ CONSTFUNC c_type KindOfInt##$clamped(c_type x, c_type min, c_type max) { \
+ return x < min ? min : (x > max ? max : x); \
+ } \
+ public \
+ Text_t KindOfInt##$hex(c_type i, Int_t digits_int, bool uppercase, bool prefix) { \
+ Int_t as_int = Int$from_int64((int64_t)i); \
+ return Int$hex(as_int, digits_int, uppercase, prefix); \
+ } \
+ public \
+ Text_t KindOfInt##$octal(c_type i, Int_t digits_int, bool prefix) { \
+ Int_t as_int = Int$from_int64((int64_t)i); \
+ return Int$octal(as_int, digits_int, prefix); \
+ } \
+ public \
+ List_t KindOfInt##$bits(c_type x) { \
+ List_t bit_list = (List_t){.data = GC_MALLOC_ATOMIC(sizeof(bool[8 * sizeof(c_type)])), \
+ .atomic = 1, \
+ .stride = sizeof(bool), \
+ .length = 8 * sizeof(c_type)}; \
+ bool *bits = bit_list.data + sizeof(c_type) * 8; \
+ for (size_t i = 0; i < 8 * sizeof(c_type); i++) { \
+ *(bits--) = x & 1; \
+ x >>= 1; \
+ } \
+ return bit_list; \
+ } \
+ public \
+ bool KindOfInt##$get_bit(c_type x, Int_t bit_index) { \
+ if (Int$compare_value(bit_index, I(1)) < 0) fail("Invalid bit index (expected 1 or higher): ", bit_index); \
+ if (Int$compare_value(bit_index, Int$from_int64(sizeof(c_type) * 8)) > 0) \
+ fail("Bit index is too large! There are only ", (uint64_t)sizeof(c_type) * 8, \
+ " bits, but index is: ", bit_index); \
+ return ((x & (c_type)(1L << (Int64$from_int(bit_index, true) - 1L))) != 0); \
+ } \
+ typedef struct { \
+ Optional##KindOfInt##_t current, last; \
+ KindOfInt##_t step; \
+ } KindOfInt##Range_t; \
+ static Optional##KindOfInt##_t _next_##KindOfInt(KindOfInt##Range_t *info) { \
+ Optional##KindOfInt##_t i = info->current; \
+ if (!i.is_none) { \
+ KindOfInt##_t next; \
+ bool overflow = __builtin_add_overflow(i.value, info->step, &next); \
+ if (overflow \
+ || (!info->last.is_none && (info->step >= 0 ? next > info->last.value : next < info->last.value))) \
+ info->current = (Optional##KindOfInt##_t){.is_none = true}; \
+ else info->current = (Optional##KindOfInt##_t){.value = next}; \
+ } \
+ return i; \
+ } \
+ public \
+ to_attr Closure_t KindOfInt##$to(c_type first, c_type last, Optional##KindOfInt##_t step) { \
+ KindOfInt##Range_t *range = GC_MALLOC(sizeof(KindOfInt##Range_t)); \
+ range->current = (Optional##KindOfInt##_t){.value = first}; \
+ range->last = (Optional##KindOfInt##_t){.value = last}; \
+ range->step = step.is_none ? (last >= first ? 1 : -1) : step.value; \
+ return (Closure_t){.fn = _next_##KindOfInt, .userdata = range}; \
+ } \
+ public \
+ to_attr Closure_t KindOfInt##$onward(c_type first, c_type step) { \
+ KindOfInt##Range_t *range = GC_MALLOC(sizeof(KindOfInt##Range_t)); \
+ range->current = (Optional##KindOfInt##_t){.value = first}; \
+ range->last = (Optional##KindOfInt##_t){.is_none = true}; \
+ range->step = step; \
+ return (Closure_t){.fn = _next_##KindOfInt, .userdata = range}; \
+ } \
+ public \
+ PUREFUNC Optional##KindOfInt##_t KindOfInt##$parse(Text_t text, Text_t *remainder) { \
+ OptionalInt_t full_int = Int$parse(text, remainder); \
+ if (full_int.small == 0L) return (Optional##KindOfInt##_t){.is_none = true}; \
+ if (Int$compare_value(full_int, I(min_val)) < 0) { \
+ return (Optional##KindOfInt##_t){.is_none = true}; \
+ } \
+ if (Int$compare_value(full_int, I(max_val)) > 0) { \
+ return (Optional##KindOfInt##_t){.is_none = true}; \
+ } \
+ return (Optional##KindOfInt##_t){.value = KindOfInt##$from_int(full_int, true)}; \
+ } \
+ public \
+ CONSTFUNC c_type KindOfInt##$gcd(c_type x, c_type y) { \
+ if (x == 0 || y == 0) return 0; \
+ x = KindOfInt##$abs(x); \
+ y = KindOfInt##$abs(y); \
+ while (x != y) { \
+ if (x > y) x -= y; \
+ else y -= x; \
+ } \
+ return x; \
+ } \
+ public \
+ const c_type KindOfInt##$min = min_val; \
+ public \
+ const c_type KindOfInt##$max = max_val; \
+ public \
+ const TypeInfo_t KindOfInt##$info = { \
+ .size = sizeof(c_type), \
+ .align = __alignof__(c_type), \
+ .metamethods = \
+ { \
+ .compare = KindOfInt##$compare, \
+ .as_text = KindOfInt##$as_text, \
+ .serialize = KindOfInt##$serialize, \
+ .deserialize = KindOfInt##$deserialize, \
+ }, \
};
-DEFINE_INT_TYPE(int64_t, Int64, INT64_MIN, INT64_MAX, __attribute__(()))
-DEFINE_INT_TYPE(int32_t, Int32, INT32_MIN, INT32_MAX, CONSTFUNC)
-DEFINE_INT_TYPE(int16_t, Int16, INT16_MIN, INT16_MAX, CONSTFUNC)
-DEFINE_INT_TYPE(int8_t, Int8, INT8_MIN, INT8_MAX, CONSTFUNC)
+DEFINE_INT_TYPE(int64_t, Int64, INT64_MIN, INT64_MAX, __attribute__(()))
+DEFINE_INT_TYPE(int32_t, Int32, INT32_MIN, INT32_MAX, CONSTFUNC)
+DEFINE_INT_TYPE(int16_t, Int16, INT16_MIN, INT16_MAX, CONSTFUNC)
+DEFINE_INT_TYPE(int8_t, Int8, INT8_MIN, INT8_MAX, CONSTFUNC)
#undef DEFINE_INT_TYPE
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/integers.h b/src/stdlib/integers.h
index 744992dd..a7249495 100644
--- a/src/stdlib/integers.h
+++ b/src/stdlib/integers.h
@@ -2,9 +2,9 @@
// Integer type infos and methods
+#include <gmp.h>
#include <stdbool.h>
#include <stdint.h>
-#include <gmp.h>
#include "datatypes.h"
#include "stdlib.h"
@@ -16,74 +16,72 @@
#define I16(x) ((int16_t)x)
#define I8(x) ((int8_t)x)
-#define DEFINE_INT_TYPE(c_type, type_name) \
- typedef struct { \
- c_type value; \
- bool is_none:1; \
- } Optional ## type_name ## _t; \
- Text_t type_name ## $as_text(const void *i, bool colorize, const TypeInfo_t *type); \
- PUREFUNC int32_t type_name ## $compare(const void *x, const void *y, const TypeInfo_t *type); \
- PUREFUNC bool type_name ## $equal(const void *x, const void *y, const TypeInfo_t *type); \
- Text_t type_name ## $hex(c_type i, Int_t digits, bool uppercase, bool prefix); \
- Text_t type_name ## $octal(c_type i, Int_t digits, bool prefix); \
- List_t type_name ## $bits(c_type x); \
- bool type_name ## $get_bit(c_type x, Int_t bit_index); \
- Closure_t type_name ## $to(c_type first, c_type last, Optional ## type_name ## _t step); \
- Closure_t type_name ## $onward(c_type first, c_type step); \
- PUREFUNC Optional ## type_name ## _t type_name ## $parse(Text_t text, Text_t *remainder); \
- CONSTFUNC bool type_name ## $is_between(const c_type x, const c_type low, const c_type high); \
- CONSTFUNC c_type type_name ## $clamped(c_type x, c_type min, c_type max); \
- MACROLIKE CONSTFUNC c_type type_name ## $from_byte(Byte_t b) { return (c_type)b; } \
- MACROLIKE CONSTFUNC c_type type_name ## $from_bool(Bool_t b) { return (c_type)b; } \
- CONSTFUNC c_type type_name ## $gcd(c_type x, c_type y); \
- extern const c_type type_name ## $min, type_name##$max; \
- extern const TypeInfo_t type_name ## $info; \
- MACROLIKE c_type type_name ## $divided_by(c_type D, c_type d) { \
- c_type q = D/d, r = D%d; \
- q -= (r < 0) * (2*(d > 0) - 1); \
- return q; \
- } \
- MACROLIKE c_type type_name ## $modulo(c_type D, c_type d) { \
- c_type r = D%d; \
- r -= (r < 0) * (2*(d < 0) - 1) * d; \
- return r; \
- } \
- MACROLIKE c_type type_name ## $modulo1(c_type D, c_type d) { \
- return type_name ## $modulo(D-1, d) + 1; \
- } \
- MACROLIKE PUREFUNC c_type type_name ## $wrapping_plus(c_type x, c_type y) { \
- return (c_type)((u##c_type)x + (u##c_type)y); \
- } \
- MACROLIKE PUREFUNC c_type type_name ## $wrapping_minus(c_type x, c_type y) { \
- return (c_type)((u##c_type)x + (u##c_type)y); \
- } \
- MACROLIKE PUREFUNC c_type type_name ## $unsigned_left_shifted(c_type x, c_type y) { \
- return (c_type)((u##c_type)x << y); \
- } \
- MACROLIKE PUREFUNC c_type type_name ## $unsigned_right_shifted(c_type x, c_type y) { \
- return (c_type)((u##c_type)x >> y); \
+#define DEFINE_INT_TYPE(c_type, type_name) \
+ typedef struct { \
+ c_type value; \
+ bool is_none : 1; \
+ } Optional##type_name##_t; \
+ Text_t type_name##$as_text(const void *i, bool colorize, const TypeInfo_t *type); \
+ PUREFUNC int32_t type_name##$compare(const void *x, const void *y, const TypeInfo_t *type); \
+ PUREFUNC bool type_name##$equal(const void *x, const void *y, const TypeInfo_t *type); \
+ Text_t type_name##$hex(c_type i, Int_t digits, bool uppercase, bool prefix); \
+ Text_t type_name##$octal(c_type i, Int_t digits, bool prefix); \
+ List_t type_name##$bits(c_type x); \
+ bool type_name##$get_bit(c_type x, Int_t bit_index); \
+ Closure_t type_name##$to(c_type first, c_type last, Optional##type_name##_t step); \
+ Closure_t type_name##$onward(c_type first, c_type step); \
+ PUREFUNC Optional##type_name##_t type_name##$parse(Text_t text, Text_t *remainder); \
+ CONSTFUNC bool type_name##$is_between(const c_type x, const c_type low, const c_type high); \
+ CONSTFUNC c_type type_name##$clamped(c_type x, c_type min, c_type max); \
+ MACROLIKE CONSTFUNC c_type type_name##$from_byte(Byte_t b) { return (c_type)b; } \
+ MACROLIKE CONSTFUNC c_type type_name##$from_bool(Bool_t b) { return (c_type)b; } \
+ CONSTFUNC c_type type_name##$gcd(c_type x, c_type y); \
+ extern const c_type type_name##$min, type_name##$max; \
+ extern const TypeInfo_t type_name##$info; \
+ MACROLIKE c_type type_name##$divided_by(c_type D, c_type d) { \
+ c_type q = D / d, r = D % d; \
+ q -= (r < 0) * (2 * (d > 0) - 1); \
+ return q; \
+ } \
+ MACROLIKE c_type type_name##$modulo(c_type D, c_type d) { \
+ c_type r = D % d; \
+ r -= (r < 0) * (2 * (d < 0) - 1) * d; \
+ return r; \
+ } \
+ MACROLIKE c_type type_name##$modulo1(c_type D, c_type d) { return type_name##$modulo(D - 1, d) + 1; } \
+ MACROLIKE PUREFUNC c_type type_name##$wrapping_plus(c_type x, c_type y) { \
+ return (c_type)((u##c_type)x + (u##c_type)y); \
+ } \
+ MACROLIKE PUREFUNC c_type type_name##$wrapping_minus(c_type x, c_type y) { \
+ return (c_type)((u##c_type)x + (u##c_type)y); \
+ } \
+ MACROLIKE PUREFUNC c_type type_name##$unsigned_left_shifted(c_type x, c_type y) { \
+ return (c_type)((u##c_type)x << y); \
+ } \
+ MACROLIKE PUREFUNC c_type type_name##$unsigned_right_shifted(c_type x, c_type y) { \
+ return (c_type)((u##c_type)x >> y); \
}
DEFINE_INT_TYPE(int64_t, Int64)
DEFINE_INT_TYPE(int32_t, Int32)
DEFINE_INT_TYPE(int16_t, Int16)
-DEFINE_INT_TYPE(int8_t, Int8)
+DEFINE_INT_TYPE(int8_t, Int8)
#undef DEFINE_INT_TYPE
-#define NONE_INT64 ((OptionalInt64_t){.is_none=true})
-#define NONE_INT32 ((OptionalInt32_t){.is_none=true})
-#define NONE_INT16 ((OptionalInt16_t){.is_none=true})
-#define NONE_INT8 ((OptionalInt8_t){.is_none=true})
+#define NONE_INT64 ((OptionalInt64_t){.is_none = true})
+#define NONE_INT32 ((OptionalInt32_t){.is_none = true})
+#define NONE_INT16 ((OptionalInt16_t){.is_none = true})
+#define NONE_INT8 ((OptionalInt8_t){.is_none = true})
#define Int64$abs(...) I64(labs(__VA_ARGS__))
#define Int32$abs(...) I32(abs(__VA_ARGS__))
#define Int16$abs(...) I16(abs(__VA_ARGS__))
#define Int8$abs(...) I8(abs(__VA_ARGS__))
-void Int64$serialize(const void *obj, FILE *out, Table_t*, const TypeInfo_t*);
-void Int64$deserialize(FILE *in, void *outval, List_t*, const TypeInfo_t*);
-void Int32$serialize(const void *obj, FILE *out, Table_t*, const TypeInfo_t*);
-void Int32$deserialize(FILE *in, void *outval, List_t*, const TypeInfo_t*);
+void Int64$serialize(const void *obj, FILE *out, Table_t *, const TypeInfo_t *);
+void Int64$deserialize(FILE *in, void *outval, List_t *, const TypeInfo_t *);
+void Int32$serialize(const void *obj, FILE *out, Table_t *, const TypeInfo_t *);
+void Int32$deserialize(FILE *in, void *outval, List_t *, const TypeInfo_t *);
Text_t Int$as_text(const void *i, bool colorize, const TypeInfo_t *type);
Text_t Int$value_as_text(Int_t i);
@@ -109,19 +107,17 @@ bool Int$get_bit(Int_t x, Int_t bit_index);
#define BIGGEST_SMALL_INT 0x3fffffff
#define SMALLEST_SMALL_INT -0x40000000
-#define Int$from_mpz(mpz) (\
- mpz_cmpabs_ui(mpz, BIGGEST_SMALL_INT) <= 0 ? ( \
- (Int_t){.small=(mpz_get_si(mpz)<<2L)|1L} \
- ) : ( \
- (Int_t){.big=memcpy(new(mpz_t), &mpz, sizeof(mpz_t))} \
- ))
+#define Int$from_mpz(mpz) \
+ (mpz_cmpabs_ui(mpz, BIGGEST_SMALL_INT) <= 0 ? ((Int_t){.small = (mpz_get_si(mpz) << 2L) | 1L}) \
+ : ((Int_t){.big = memcpy(new (mpz_t), &mpz, sizeof(mpz_t))}))
-#define mpz_init_set_int(mpz, i) do { \
- if likely ((i).small & 1L) mpz_init_set_si(mpz, (i).small >> 2L); \
- else mpz_init_set(mpz, *(i).big); \
-} while (0)
+#define mpz_init_set_int(mpz, i) \
+ do { \
+ if likely ((i).small & 1L) mpz_init_set_si(mpz, (i).small >> 2L); \
+ else mpz_init_set(mpz, *(i).big); \
+ } while (0)
-#define I_small(i) ((Int_t){.small=(int64_t)((uint64_t)(i)<<2L)|1L})
+#define I_small(i) ((Int_t){.small = (int64_t)((uint64_t)(i) << 2L) | 1L})
#define I(i) _Generic(i, int8_t: I_small(i), int16_t: I_small(i), default: Int$from_int64(i))
#define I_is_zero(i) ((i).small == 1L)
@@ -155,116 +151,107 @@ extern const TypeInfo_t Int$info;
MACROLIKE Int_t Int$plus(Int_t x, Int_t y) {
const int64_t z = (int64_t)((uint64_t)x.small + (uint64_t)y.small);
- if likely ((z|2L) == (int32_t)z)
- return (Int_t){.small=(z-1L)};
+ if likely ((z | 2L) == (int32_t)z) return (Int_t){.small = (z - 1L)};
return Int$slow_plus(x, y);
}
MACROLIKE Int_t Int$minus(Int_t x, Int_t y) {
const int64_t z = (int64_t)(((uint64_t)x.small ^ 3L) - (uint64_t)y.small);
- if likely ((z & ~2L) == (int32_t)z)
- return (Int_t){.small=z};
+ if likely ((z & ~2L) == (int32_t)z) return (Int_t){.small = z};
return Int$slow_minus(x, y);
}
MACROLIKE Int_t Int$times(Int_t x, Int_t y) {
if likely ((x.small & y.small) & 1L) {
- const int64_t z = (x.small>>1L) * (y.small>>1L);
- if likely (z == (int32_t)z)
- return (Int_t){.small=z+1L};
+ const int64_t z = (x.small >> 1L) * (y.small >> 1L);
+ if likely (z == (int32_t)z) return (Int_t){.small = z + 1L};
}
return Int$slow_times(x, y);
}
MACROLIKE Int_t Int$divided_by(Int_t x, Int_t y) {
if likely (x.small & y.small & 1L) {
- // Euclidean division, see: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
- const int64_t D = (x.small>>2L);
- const int64_t d = (y.small>>2L);
- int64_t q = D/d, r = D%d;
- q -= (r < 0L) * (2L*(d > 0L) - 1L);
- if likely (q == (int32_t)q)
- return (Int_t){.small=(q<<2L)|1L};
+ // Euclidean division, see:
+ // https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
+ const int64_t D = (x.small >> 2L);
+ const int64_t d = (y.small >> 2L);
+ int64_t q = D / d, r = D % d;
+ q -= (r < 0L) * (2L * (d > 0L) - 1L);
+ if likely (q == (int32_t)q) return (Int_t){.small = (q << 2L) | 1L};
}
return Int$slow_divided_by(x, y);
}
MACROLIKE Int_t Int$modulo(Int_t x, Int_t y) {
if likely (x.small & y.small & 1L) {
- // Euclidean modulus, see: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
- const int64_t D = (x.small>>2L);
- const int64_t d = (y.small>>2L);
- int64_t r = D%d;
- r -= (r < 0L) * (2L*(d < 0L) - 1L) * d;
- return (Int_t){.small=(r<<2L)|1L};
+ // Euclidean modulus, see:
+ // https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
+ const int64_t D = (x.small >> 2L);
+ const int64_t d = (y.small >> 2L);
+ int64_t r = D % d;
+ r -= (r < 0L) * (2L * (d < 0L) - 1L) * d;
+ return (Int_t){.small = (r << 2L) | 1L};
}
return Int$slow_modulo(x, y);
}
MACROLIKE Int_t Int$modulo1(Int_t x, Int_t y) {
if likely (x.small & y.small & 1L) {
- // Euclidean modulus, see: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
- const int64_t D = (x.small>>2L)-1L;
- const int64_t d = (y.small>>2L);
- int64_t r = D%d;
- r -= (r < 0L) * (2L*(d < 0L) - 1L) * d;
- return (Int_t){.small=((r+1L)<<2L)|1L};
+ // Euclidean modulus, see:
+ // https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
+ const int64_t D = (x.small >> 2L) - 1L;
+ const int64_t d = (y.small >> 2L);
+ int64_t r = D % d;
+ r -= (r < 0L) * (2L * (d < 0L) - 1L) * d;
+ return (Int_t){.small = ((r + 1L) << 2L) | 1L};
}
return Int$slow_modulo1(x, y);
}
MACROLIKE Int_t Int$left_shifted(Int_t x, Int_t y) {
if likely (x.small & y.small & 1L) {
- const int64_t z = ((x.small>>2L) << (y.small>>2L))<<2L;
- if likely (z == (int32_t)z)
- return (Int_t){.small=z+1L};
+ const int64_t z = ((x.small >> 2L) << (y.small >> 2L)) << 2L;
+ if likely (z == (int32_t)z) return (Int_t){.small = z + 1L};
}
return Int$slow_left_shifted(x, y);
}
MACROLIKE Int_t Int$right_shifted(Int_t x, Int_t y) {
if likely (x.small & y.small & 1L) {
- const int64_t z = ((x.small>>2L) >> (y.small>>2L))<<2L;
- if likely (z == (int32_t)z)
- return (Int_t){.small=z+1L};
+ const int64_t z = ((x.small >> 2L) >> (y.small >> 2L)) << 2L;
+ if likely (z == (int32_t)z) return (Int_t){.small = z + 1L};
}
return Int$slow_right_shifted(x, y);
}
MACROLIKE Int_t Int$bit_and(Int_t x, Int_t y) {
const int64_t z = x.small & y.small;
- if likely (z & 1L)
- return (Int_t){.small=z};
+ if likely (z & 1L) return (Int_t){.small = z};
return Int$slow_bit_and(x, y);
}
MACROLIKE Int_t Int$bit_or(Int_t x, Int_t y) {
- if likely (x.small & y.small & 1L)
- return (Int_t){.small=(x.small | y.small)};
+ if likely (x.small & y.small & 1L) return (Int_t){.small = (x.small | y.small)};
return Int$slow_bit_or(x, y);
}
MACROLIKE Int_t Int$bit_xor(Int_t x, Int_t y) {
- if likely (x.small & y.small & 1L)
- return (Int_t){.small=(x.small ^ y.small) | 1L};
+ if likely (x.small & y.small & 1L) return (Int_t){.small = (x.small ^ y.small) | 1L};
return Int$slow_bit_xor(x, y);
}
MACROLIKE Int_t Int$negated(Int_t x) {
- if likely (x.small & 1L)
- return (Int_t){.small=(~x.small) ^ 3L};
+ if likely (x.small & 1L) return (Int_t){.small = (~x.small) ^ 3L};
return Int$slow_negated(x);
}
MACROLIKE Int_t Int$negative(Int_t x) {
- if likely (x.small & 1L)
- return (Int_t){.small=((-((x.small)>>2L))<<2L) | 1L};
+ if likely (x.small & 1L) return (Int_t){.small = ((-((x.small) >> 2L)) << 2L) | 1L};
return Int$slow_negative(x);
}
MACROLIKE PUREFUNC bool Int$is_negative(Int_t x) {
- if likely (x.small & 1L)
- return x.small < 0L;
+ if likely (x.small & 1L) return x.small < 0L;
return Int$compare_value(x, I_small(0)) < 0L;
}
@@ -278,42 +265,36 @@ MACROLIKE PUREFUNC bool Int$is_negative(Int_t x) {
MACROLIKE PUREFUNC Int_t Int$from_num(double n, bool truncate) {
mpz_t result;
mpz_init_set_d(result, n);
- if (!truncate && unlikely(mpz_get_d(result) != n))
- fail("Could not convert to an integer without truncation: ", n);
+ if (!truncate && unlikely(mpz_get_d(result) != n)) fail("Could not convert to an integer without truncation: ", n);
return Int$from_mpz(result);
}
MACROLIKE PUREFUNC Int_t Int$from_num32(float n, bool truncate) { return Int$from_num((double)n, truncate); }
MACROLIKE Int_t Int$from_int64(int64_t i) {
- if likely (i >= SMALLEST_SMALL_INT && i <= BIGGEST_SMALL_INT)
- return (Int_t){.small=(i<<2L)|1L};
+ if likely (i >= SMALLEST_SMALL_INT && i <= BIGGEST_SMALL_INT) return (Int_t){.small = (i << 2L) | 1L};
mpz_t result;
mpz_init_set_si(result, i);
return Int$from_mpz(result);
}
MACROLIKE CONSTFUNC Int_t Int$from_int32(Int32_t i) { return Int$from_int64((Int32_t)i); }
MACROLIKE CONSTFUNC Int_t Int$from_int16(Int16_t i) { return I_small(i); }
-MACROLIKE CONSTFUNC Int_t Int$from_int8(Int8_t i) { return I_small(i); }
+MACROLIKE CONSTFUNC Int_t Int$from_int8(Int8_t i) { return I_small(i); }
MACROLIKE CONSTFUNC Int_t Int$from_byte(Byte_t b) { return I_small(b); }
MACROLIKE CONSTFUNC Int_t Int$from_bool(Bool_t b) { return I_small(b); }
// Int64 constructors
MACROLIKE PUREFUNC Int64_t Int64$from_num(Num_t n, bool truncate) {
int64_t i64 = (int64_t)n;
- if (!truncate && unlikely((Num_t)i64 != n))
- fail("Could not convert Num to Int64 without truncation: ", n);
+ if (!truncate && unlikely((Num_t)i64 != n)) fail("Could not convert Num to Int64 without truncation: ", n);
return i64;
}
MACROLIKE PUREFUNC Int64_t Int64$from_num32(Num32_t n, bool truncate) {
int64_t i64 = (int64_t)n;
- if (!truncate && unlikely((Num32_t)i64 != n))
- fail("Could not convert Num32 to Int64 without truncation: ", n);
+ if (!truncate && unlikely((Num32_t)i64 != n)) fail("Could not convert Num32 to Int64 without truncation: ", n);
return i64;
}
MACROLIKE PUREFUNC Int64_t Int64$from_int(Int_t i, bool truncate) {
- if likely (i.small & 1L)
- return (int64_t)(i.small >> 2L);
- if (!truncate && unlikely(!mpz_fits_slong_p(*i.big)))
- fail("Integer is too big to fit in a 64-bit integer: ", i);
+ if likely (i.small & 1L) return (int64_t)(i.small >> 2L);
+ if (!truncate && unlikely(!mpz_fits_slong_p(*i.big))) fail("Integer is too big to fit in a 64-bit integer: ", i);
return mpz_get_si(*i.big);
}
MACROLIKE CONSTFUNC Int64_t Int64$from_int32(Int32_t i) { return (Int64_t)i; }
@@ -323,27 +304,23 @@ MACROLIKE CONSTFUNC Int64_t Int64$from_int8(Int8_t i) { return (Int64_t)i; }
// Int32 constructors
MACROLIKE PUREFUNC Int32_t Int32$from_num(Num_t n, bool truncate) {
int32_t i32 = (int32_t)n;
- if (!truncate && unlikely((Num_t)i32 != n))
- fail("Could not convert Num to Int32 without truncation: ", n);
+ if (!truncate && unlikely((Num_t)i32 != n)) fail("Could not convert Num to Int32 without truncation: ", n);
return i32;
}
MACROLIKE PUREFUNC Int32_t Int32$from_num32(Num32_t n, bool truncate) {
int32_t i32 = (int32_t)n;
- if (!truncate && unlikely((Num32_t)i32 != n))
- fail("Could not convert Num32 to Int32 without truncation: ", n);
+ if (!truncate && unlikely((Num32_t)i32 != n)) fail("Could not convert Num32 to Int32 without truncation: ", n);
return i32;
}
MACROLIKE PUREFUNC Int32_t Int32$from_int(Int_t i, bool truncate) {
int64_t i64 = Int64$from_int(i, truncate);
int32_t i32 = (int32_t)i64;
- if (!truncate && unlikely((int64_t)i32 != i64))
- fail("Integer is too big to fit in a 32-bit integer: ", i);
+ if (!truncate && unlikely((int64_t)i32 != i64)) fail("Integer is too big to fit in a 32-bit integer: ", i);
return i32;
}
MACROLIKE PUREFUNC Int32_t Int32$from_int64(Int64_t i64, bool truncate) {
int32_t i32 = (int32_t)i64;
- if (!truncate && unlikely((int64_t)i32 != i64))
- fail("Integer is too big to fit in a 32-bit integer: ", i64);
+ if (!truncate && unlikely((int64_t)i32 != i64)) fail("Integer is too big to fit in a 32-bit integer: ", i64);
return i32;
}
MACROLIKE CONSTFUNC Int32_t Int32$from_int16(Int16_t i) { return (Int32_t)i; }
@@ -352,8 +329,7 @@ MACROLIKE CONSTFUNC Int32_t Int32$from_int8(Int8_t i) { return (Int32_t)i; }
// Int16 constructors
MACROLIKE PUREFUNC Int16_t Int16$from_num(Num_t n, bool truncate) {
int16_t i16 = (int16_t)n;
- if (!truncate && unlikely((Num_t)i16 != n))
- fail("Could not convert Num to Int16 without truncation: ", n);
+ if (!truncate && unlikely((Num_t)i16 != n)) fail("Could not convert Num to Int16 without truncation: ", n);
return i16;
}
MACROLIKE PUREFUNC Int16_t Int16$from_num32(Num32_t n, bool truncate) {
@@ -365,20 +341,17 @@ MACROLIKE PUREFUNC Int16_t Int16$from_num32(Num32_t n, bool truncate) {
MACROLIKE PUREFUNC Int16_t Int16$from_int(Int_t i, bool truncate) {
int64_t i64 = Int64$from_int(i, truncate);
int16_t i16 = (int16_t)i64;
- if (!truncate && unlikely((int64_t)i16 != i64))
- fail("Integer is too big to fit in a 16-bit integer!");
+ if (!truncate && unlikely((int64_t)i16 != i64)) fail("Integer is too big to fit in a 16-bit integer!");
return i16;
}
MACROLIKE PUREFUNC Int16_t Int16$from_int64(Int64_t i64, bool truncate) {
int16_t i16 = (int16_t)i64;
- if (!truncate && unlikely((int64_t)i16 != i64))
- fail("Integer is too big to fit in a 16-bit integer: ", i64);
+ if (!truncate && unlikely((int64_t)i16 != i64)) fail("Integer is too big to fit in a 16-bit integer: ", i64);
return i16;
}
MACROLIKE PUREFUNC Int16_t Int16$from_int32(Int32_t i32, bool truncate) {
int16_t i16 = (int16_t)i32;
- if (!truncate && unlikely((int32_t)i16 != i32))
- fail("Integer is too big to fit in a 16-bit integer: ", i32);
+ if (!truncate && unlikely((int32_t)i16 != i32)) fail("Integer is too big to fit in a 16-bit integer: ", i32);
return i16;
}
MACROLIKE CONSTFUNC Int16_t Int16$from_int8(Int8_t i) { return (Int16_t)i; }
@@ -386,39 +359,33 @@ MACROLIKE CONSTFUNC Int16_t Int16$from_int8(Int8_t i) { return (Int16_t)i; }
// Int8 constructors
MACROLIKE PUREFUNC Int8_t Int8$from_num(Num_t n, bool truncate) {
int8_t i8 = (int8_t)n;
- if (!truncate && unlikely((Num_t)i8 != n))
- fail("Could not convert Num to Int8 without truncation: ", n);
+ if (!truncate && unlikely((Num_t)i8 != n)) fail("Could not convert Num to Int8 without truncation: ", n);
return i8;
}
MACROLIKE PUREFUNC Int8_t Int8$from_num32(Num32_t n, bool truncate) {
int8_t i8 = (int8_t)n;
- if (!truncate && unlikely((Num32_t)i8 != n))
- fail("Could not convert Num32 to Int8 without truncation: ", n);
+ if (!truncate && unlikely((Num32_t)i8 != n)) fail("Could not convert Num32 to Int8 without truncation: ", n);
return i8;
}
MACROLIKE PUREFUNC Int8_t Int8$from_int(Int_t i, bool truncate) {
int64_t i64 = Int64$from_int(i, truncate);
int8_t i8 = (int8_t)i64;
- if (!truncate && unlikely((int64_t)i8 != i64))
- fail("Integer is too big to fit in an 8-bit integer!");
+ if (!truncate && unlikely((int64_t)i8 != i64)) fail("Integer is too big to fit in an 8-bit integer!");
return i8;
}
MACROLIKE PUREFUNC Int8_t Int8$from_int64(Int64_t i64, bool truncate) {
int8_t i8 = (int8_t)i64;
- if (!truncate && unlikely((int64_t)i8 != i64))
- fail("Integer is too big to fit in a 8-bit integer: ", i64);
+ if (!truncate && unlikely((int64_t)i8 != i64)) fail("Integer is too big to fit in a 8-bit integer: ", i64);
return i8;
}
MACROLIKE PUREFUNC Int8_t Int8$from_int32(Int32_t i32, bool truncate) {
int8_t i8 = (int8_t)i32;
- if (!truncate && unlikely((int32_t)i8 != i32))
- fail("Integer is too big to fit in a 8-bit integer: ", i32);
+ if (!truncate && unlikely((int32_t)i8 != i32)) fail("Integer is too big to fit in a 8-bit integer: ", i32);
return i8;
}
MACROLIKE PUREFUNC Int8_t Int8$from_int16(Int16_t i16, bool truncate) {
int8_t i8 = (int8_t)i16;
- if (!truncate && unlikely((int16_t)i8 != i16))
- fail("Integer is too big to fit in a 8-bit integer: ", i16);
+ if (!truncate && unlikely((int16_t)i8 != i16)) fail("Integer is too big to fit in a 8-bit integer: ", i16);
return i8;
}
#ifdef __GNUC__
diff --git a/src/stdlib/lists.c b/src/stdlib/lists.c
index ce27f822..415e28a5 100644
--- a/src/stdlib/lists.c
+++ b/src/stdlib/lists.c
@@ -6,8 +6,8 @@
#include <stdint.h>
#include <sys/param.h>
-#include "lists.h"
#include "integers.h"
+#include "lists.h"
#include "math.h"
#include "metamethods.h"
#include "optionals.h"
@@ -18,39 +18,37 @@
// Use inline version of siphash code:
#include "siphash-internals.h"
-PUREFUNC static INLINE int64_t get_padded_item_size(const TypeInfo_t *info)
-{
+PUREFUNC static INLINE int64_t get_padded_item_size(const TypeInfo_t *info) {
int64_t size = info->ListInfo.item->size;
- if (info->ListInfo.item->align > 1 && size % info->ListInfo.item->align)
- errx(1, "Item size is not padded!");
+ if (info->ListInfo.item->align > 1 && size % info->ListInfo.item->align) errx(1, "Item size is not padded!");
return size;
}
// Replace the list's .data pointer with a new pointer to a copy of the
// data that is compacted and has a stride of exactly `padded_item_size`
-public void List$compact(List_t *list, int64_t padded_item_size)
-{
+public
+void List$compact(List_t *list, int64_t padded_item_size) {
void *copy = NULL;
if (list->length > 0) {
copy = list->atomic ? GC_MALLOC_ATOMIC((size_t)list->length * (size_t)padded_item_size)
- : GC_MALLOC((size_t)list->length * (size_t)padded_item_size);
+ : GC_MALLOC((size_t)list->length * (size_t)padded_item_size);
if ((int64_t)list->stride == padded_item_size) {
memcpy(copy, list->data, (size_t)list->length * (size_t)padded_item_size);
} else {
for (int64_t i = 0; i < list->length; i++)
- memcpy(copy + i*padded_item_size, list->data + list->stride*i, (size_t)padded_item_size);
+ memcpy(copy + i * padded_item_size, list->data + list->stride * i, (size_t)padded_item_size);
}
}
*list = (List_t){
- .data=copy,
- .length=list->length,
- .stride=padded_item_size,
- .atomic=list->atomic,
+ .data = copy,
+ .length = list->length,
+ .stride = padded_item_size,
+ .atomic = list->atomic,
};
}
-public void List$insert(List_t *list, const void *item, Int_t int_index, int64_t padded_item_size)
-{
+public
+void List$insert(List_t *list, const void *item, Int_t int_index, int64_t padded_item_size) {
int64_t index = Int64$from_int(int_index, false);
if (index <= 0) index = list->length + index + 1;
@@ -61,42 +59,38 @@ public void List$insert(List_t *list, const void *item, Int_t int_index, int64_t
if (!list->data) {
list->free = 4;
list->data = list->atomic ? GC_MALLOC_ATOMIC((size_t)list->free * (size_t)padded_item_size)
- : GC_MALLOC((size_t)list->free * (size_t)padded_item_size);
+ : GC_MALLOC((size_t)list->free * (size_t)padded_item_size);
list->stride = padded_item_size;
} else if (list->free < 1 || list->data_refcount != 0 || (int64_t)list->stride != padded_item_size) {
// Resize policy: +50% growth (clamped between 8 and LIST_MAX_FREE_ENTRIES)
- list->free = MIN(LIST_MAX_FREE_ENTRIES, MAX(8, list->length)/2);
+ list->free = MIN(LIST_MAX_FREE_ENTRIES, MAX(8, list->length) / 2);
void *copy = list->atomic ? GC_MALLOC_ATOMIC((size_t)(list->length + list->free) * (size_t)padded_item_size)
- : GC_MALLOC((size_t)(list->length + list->free) * (size_t)padded_item_size);
- for (int64_t i = 0; i < index-1; i++)
- memcpy(copy + i*padded_item_size, list->data + list->stride*i, (size_t)padded_item_size);
- for (int64_t i = index-1; i < (int64_t)list->length; i++)
- memcpy(copy + (i+1)*padded_item_size, list->data + list->stride*i, (size_t)padded_item_size);
+ : GC_MALLOC((size_t)(list->length + list->free) * (size_t)padded_item_size);
+ for (int64_t i = 0; i < index - 1; i++)
+ memcpy(copy + i * padded_item_size, list->data + list->stride * i, (size_t)padded_item_size);
+ for (int64_t i = index - 1; i < (int64_t)list->length; i++)
+ memcpy(copy + (i + 1) * padded_item_size, list->data + list->stride * i, (size_t)padded_item_size);
list->data = copy;
list->data_refcount = 0;
list->stride = padded_item_size;
} else {
- if (index != list->length+1) {
+ if (index != list->length + 1) {
assert(list->length >= index);
- size_t size = (size_t)((list->length - index + 1)*padded_item_size);
+ size_t size = (size_t)((list->length - index + 1) * padded_item_size);
assert(size < SIZE_MAX);
- memmove(
- list->data + index*padded_item_size,
- list->data + (index-1)*padded_item_size,
- size);
+ memmove(list->data + index * padded_item_size, list->data + (index - 1) * padded_item_size, size);
}
}
assert(list->free > 0);
--list->free;
++list->length;
- memcpy((void*)list->data + (index-1)*padded_item_size, item, (size_t)padded_item_size);
+ memcpy((void *)list->data + (index - 1) * padded_item_size, item, (size_t)padded_item_size);
}
-public void List$insert_all(List_t *list, List_t to_insert, Int_t int_index, int64_t padded_item_size)
-{
+public
+void List$insert_all(List_t *list, List_t to_insert, Int_t int_index, int64_t padded_item_size) {
int64_t index = Int64$from_int(int_index, false);
- if (to_insert.length == 0)
- return;
+ if (to_insert.length == 0) return;
if (!list->data) {
*list = to_insert;
@@ -111,34 +105,33 @@ public void List$insert_all(List_t *list, List_t to_insert, Int_t int_index, int
fail("Invalid insertion index ", index, " for a list with length ", (int64_t)list->length);
if ((int64_t)list->free >= (int64_t)to_insert.length // Adequate free space
- && list->data_refcount == 0 // Not aliased memory
- && (int64_t)list->stride == padded_item_size) { // Contiguous list
+ && list->data_refcount == 0 // Not aliased memory
+ && (int64_t)list->stride == padded_item_size) { // Contiguous list
// If we can fit this within the list's preallocated free space, do that:
list->free -= to_insert.length;
list->length += to_insert.length;
- if (index != list->length+1)
- memmove((void*)list->data + index*padded_item_size,
- list->data + (index-1)*padded_item_size,
- (size_t)((list->length - index + to_insert.length-1)*padded_item_size));
+ if (index != list->length + 1)
+ memmove((void *)list->data + index * padded_item_size, list->data + (index - 1) * padded_item_size,
+ (size_t)((list->length - index + to_insert.length - 1) * padded_item_size));
for (int64_t i = 0; i < to_insert.length; i++)
- memcpy((void*)list->data + (index-1 + i)*padded_item_size,
- to_insert.data + i*to_insert.stride, (size_t)padded_item_size);
+ memcpy((void *)list->data + (index - 1 + i) * padded_item_size, to_insert.data + i * to_insert.stride,
+ (size_t)padded_item_size);
} else {
// Otherwise, allocate a new chunk of memory for the list and populate it:
int64_t new_len = list->length + to_insert.length;
- list->free = MIN(LIST_MAX_FREE_ENTRIES, MAX(8, new_len/4));
+ list->free = MIN(LIST_MAX_FREE_ENTRIES, MAX(8, new_len / 4));
void *data = list->atomic ? GC_MALLOC_ATOMIC((size_t)((new_len + list->free) * padded_item_size))
- : GC_MALLOC((size_t)((new_len + list->free) * padded_item_size));
+ : GC_MALLOC((size_t)((new_len + list->free) * padded_item_size));
void *p = data;
// Copy first chunk of `list` if needed:
if (index > 1) {
if (list->stride == padded_item_size) {
- memcpy(p, list->data, (size_t)((index-1)*padded_item_size));
- p += (index-1)*padded_item_size;
+ memcpy(p, list->data, (size_t)((index - 1) * padded_item_size));
+ p += (index - 1) * padded_item_size;
} else {
- for (int64_t i = 0; i < index-1; i++) {
- memcpy(p, list->data + list->stride*i, (size_t)padded_item_size);
+ for (int64_t i = 0; i < index - 1; i++) {
+ memcpy(p, list->data + list->stride * i, (size_t)padded_item_size);
p += padded_item_size;
}
}
@@ -146,11 +139,11 @@ public void List$insert_all(List_t *list, List_t to_insert, Int_t int_index, int
// Copy `to_insert`
if (to_insert.stride == padded_item_size) {
- memcpy(p, to_insert.data, (size_t)(to_insert.length*padded_item_size));
- p += to_insert.length*padded_item_size;
+ memcpy(p, to_insert.data, (size_t)(to_insert.length * padded_item_size));
+ p += to_insert.length * padded_item_size;
} else {
- for (int64_t i = 0; i < index-1; i++) {
- memcpy(p, to_insert.data + to_insert.stride*i, (size_t)padded_item_size);
+ for (int64_t i = 0; i < index - 1; i++) {
+ memcpy(p, to_insert.data + to_insert.stride * i, (size_t)padded_item_size);
p += padded_item_size;
}
}
@@ -158,11 +151,12 @@ public void List$insert_all(List_t *list, List_t to_insert, Int_t int_index, int
// Copy last chunk of `list` if needed:
if (index < list->length + 1) {
if (list->stride == padded_item_size) {
- memcpy(p, list->data + padded_item_size*(index-1), (size_t)((list->length - index + 1)*padded_item_size));
- p += (list->length - index + 1)*padded_item_size;
+ memcpy(p, list->data + padded_item_size * (index - 1),
+ (size_t)((list->length - index + 1) * padded_item_size));
+ p += (list->length - index + 1) * padded_item_size;
} else {
- for (int64_t i = index-1; i < list->length-1; i++) {
- memcpy(p, list->data + list->stride*i, (size_t)padded_item_size);
+ for (int64_t i = index - 1; i < list->length - 1; i++) {
+ memcpy(p, list->data + list->stride * i, (size_t)padded_item_size);
p += padded_item_size;
}
}
@@ -174,27 +168,27 @@ public void List$insert_all(List_t *list, List_t to_insert, Int_t int_index, int
}
}
-public void List$remove_at(List_t *list, Int_t int_index, Int_t int_count, int64_t padded_item_size)
-{
+public
+void List$remove_at(List_t *list, Int_t int_index, Int_t int_count, int64_t padded_item_size) {
int64_t index = Int64$from_int(int_index, false);
if (index < 1) index = list->length + index + 1;
int64_t count = Int64$from_int(int_count, false);
if (index < 1 || index > (int64_t)list->length || count < 1) return;
- if (count > list->length - index + 1)
- count = (list->length - index) + 1;
+ if (count > list->length - index + 1) count = (list->length - index) + 1;
if (index == 1) {
list->data += list->stride * count;
} else if (index + count > list->length) {
list->free += count;
} else if (list->data_refcount != 0 || (int64_t)list->stride != padded_item_size) {
- void *copy = list->atomic ? GC_MALLOC_ATOMIC((size_t)((list->length-1) * padded_item_size))
- : GC_MALLOC((size_t)((list->length-1) * padded_item_size));
+ void *copy = list->atomic ? GC_MALLOC_ATOMIC((size_t)((list->length - 1) * padded_item_size))
+ : GC_MALLOC((size_t)((list->length - 1) * padded_item_size));
for (int64_t src = 1, dest = 1; src <= (int64_t)list->length; src++) {
if (src < index || src >= index + count) {
- memcpy(copy + (dest - 1)*padded_item_size, list->data + list->stride*(src - 1), (size_t)padded_item_size);
+ memcpy(copy + (dest - 1) * padded_item_size, list->data + list->stride * (src - 1),
+ (size_t)padded_item_size);
++dest;
}
}
@@ -202,26 +196,27 @@ public void List$remove_at(List_t *list, Int_t int_index, Int_t int_count, int64
list->free = 0;
list->data_refcount = 0;
} else {
- memmove((void*)list->data + (index-1)*padded_item_size, list->data + (index-1 + count)*padded_item_size,
- (size_t)((list->length - index + count - 1)*padded_item_size));
+ memmove((void *)list->data + (index - 1) * padded_item_size,
+ list->data + (index - 1 + count) * padded_item_size,
+ (size_t)((list->length - index + count - 1) * padded_item_size));
list->free += count;
}
list->length -= count;
if (list->length == 0) list->data = NULL;
}
-public void List$remove_item(List_t *list, void *item, Int_t max_removals, const TypeInfo_t *type)
-{
+public
+void List$remove_item(List_t *list, void *item, Int_t max_removals, const TypeInfo_t *type) {
int64_t padded_item_size = get_padded_item_size(type);
- const Int_t ZERO = (Int_t){.small=(0<<2)|1};
- const Int_t ONE = (Int_t){.small=(1<<2)|1};
+ const Int_t ZERO = (Int_t){.small = (0 << 2) | 1};
+ const Int_t ONE = (Int_t){.small = (1 << 2) | 1};
const TypeInfo_t *item_type = type->ListInfo.item;
- for (int64_t i = 0; i < list->length; ) {
+ for (int64_t i = 0; i < list->length;) {
if (max_removals.small == ZERO.small) // zero
break;
- if (generic_equal(item, list->data + i*list->stride, item_type)) {
- List$remove_at(list, I(i+1), ONE, padded_item_size);
+ if (generic_equal(item, list->data + i * list->stride, item_type)) {
+ List$remove_at(list, I(i + 1), ONE, padded_item_size);
max_removals = Int$minus(max_removals, ONE);
} else {
i++;
@@ -229,45 +224,41 @@ public void List$remove_item(List_t *list, void *item, Int_t max_removals, const
}
}
-public OptionalInt_t List$find(List_t list, void *item, const TypeInfo_t *type)
-{
+public
+OptionalInt_t List$find(List_t list, void *item, const TypeInfo_t *type) {
const TypeInfo_t *item_type = type->ListInfo.item;
for (int64_t i = 0; i < list.length; i++) {
- if (generic_equal(item, list.data + i*list.stride, item_type))
- return I(i+1);
+ if (generic_equal(item, list.data + i * list.stride, item_type)) return I(i + 1);
}
return NONE_INT;
}
-public OptionalInt_t List$first(List_t list, Closure_t predicate)
-{
- bool (*is_good)(void*, void*) = (void*)predicate.fn;
+public
+OptionalInt_t List$first(List_t list, Closure_t predicate) {
+ bool (*is_good)(void *, void *) = (void *)predicate.fn;
for (int64_t i = 0; i < list.length; i++) {
- if (is_good(list.data + i*list.stride, predicate.userdata))
- return I(i+1);
+ if (is_good(list.data + i * list.stride, predicate.userdata)) return I(i + 1);
}
return NONE_INT;
}
-static Closure_t _sort_comparison = {.fn=NULL};
+static Closure_t _sort_comparison = {.fn = NULL};
-int _compare_closure(const void *a, const void *b)
-{
- typedef int (*comparison_t)(const void*, const void*, void*);
+int _compare_closure(const void *a, const void *b) {
+ typedef int (*comparison_t)(const void *, const void *, void *);
return ((comparison_t)_sort_comparison.fn)(a, b, _sort_comparison.userdata);
}
-public void List$sort(List_t *list, Closure_t comparison, int64_t padded_item_size)
-{
- if (list->data_refcount != 0 || (int64_t)list->stride != padded_item_size)
- List$compact(list, padded_item_size);
+public
+void List$sort(List_t *list, Closure_t comparison, int64_t padded_item_size) {
+ if (list->data_refcount != 0 || (int64_t)list->stride != padded_item_size) List$compact(list, padded_item_size);
_sort_comparison = comparison;
qsort(list->data, (size_t)list->length, (size_t)padded_item_size, _compare_closure);
}
-public List_t List$sorted(List_t list, Closure_t comparison, int64_t padded_item_size)
-{
+public
+List_t List$sorted(List_t list, Closure_t comparison, int64_t padded_item_size) {
List$compact(&list, padded_item_size);
_sort_comparison = comparison;
qsort(list.data, (size_t)list.length, (size_t)padded_item_size, _compare_closure);
@@ -283,13 +274,12 @@ static ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) {
}
#elif defined(__linux__)
// Use getrandom()
-# include <sys/random.h>
+#include <sys/random.h>
#else
- #error "Unsupported platform for secure random number generation"
+#error "Unsupported platform for secure random number generation"
#endif
-static int64_t _default_random_int64(int64_t min, int64_t max, void *userdata)
-{
+static int64_t _default_random_int64(int64_t min, int64_t max, void *userdata) {
(void)userdata;
if (min > max) fail("Random minimum value (", min, ") is larger than the maximum value (", max, ")");
if (min == max) return min;
@@ -303,50 +293,49 @@ static int64_t _default_random_int64(int64_t min, int64_t max, void *userdata)
return (int64_t)((uint64_t)min + (r % range));
}
-public void List$shuffle(List_t *list, OptionalClosure_t random_int64, int64_t padded_item_size)
-{
- if (list->data_refcount != 0 || (int64_t)list->stride != padded_item_size)
- List$compact(list, padded_item_size);
+public
+void List$shuffle(List_t *list, OptionalClosure_t random_int64, int64_t padded_item_size) {
+ if (list->data_refcount != 0 || (int64_t)list->stride != padded_item_size) List$compact(list, padded_item_size);
- typedef int64_t (*rng_fn_t)(int64_t, int64_t, void*);
+ typedef int64_t (*rng_fn_t)(int64_t, int64_t, void *);
rng_fn_t rng_fn = random_int64.fn ? (rng_fn_t)random_int64.fn : _default_random_int64;
char tmp[padded_item_size];
- for (int64_t i = list->length-1; i > 1; i--) {
+ for (int64_t i = list->length - 1; i > 1; i--) {
int64_t j = rng_fn(0, i, random_int64.userdata);
- if unlikely (j < 0 || j > list->length-1)
+ if unlikely (j < 0 || j > list->length - 1)
fail("The provided random number function returned an invalid value: ", j, " (not between 0 and ", i, ")");
- memcpy(tmp, list->data + i*padded_item_size, (size_t)padded_item_size);
- memcpy((void*)list->data + i*padded_item_size, list->data + j*padded_item_size, (size_t)padded_item_size);
- memcpy((void*)list->data + j*padded_item_size, tmp, (size_t)padded_item_size);
+ memcpy(tmp, list->data + i * padded_item_size, (size_t)padded_item_size);
+ memcpy((void *)list->data + i * padded_item_size, list->data + j * padded_item_size, (size_t)padded_item_size);
+ memcpy((void *)list->data + j * padded_item_size, tmp, (size_t)padded_item_size);
}
}
-public List_t List$shuffled(List_t list, Closure_t random_int64, int64_t padded_item_size)
-{
+public
+List_t List$shuffled(List_t list, Closure_t random_int64, int64_t padded_item_size) {
List$compact(&list, padded_item_size);
List$shuffle(&list, random_int64, padded_item_size);
return list;
}
-public void *List$random(List_t list, OptionalClosure_t random_int64)
-{
- if (list.length == 0)
- return NULL; // fail("Cannot get a random item from an empty list!");
+public
+void *List$random(List_t list, OptionalClosure_t random_int64) {
+ if (list.length == 0) return NULL; // fail("Cannot get a random item from an empty list!");
- typedef int64_t (*rng_fn_t)(int64_t, int64_t, void*);
+ typedef int64_t (*rng_fn_t)(int64_t, int64_t, void *);
rng_fn_t rng_fn = random_int64.fn ? (rng_fn_t)random_int64.fn : _default_random_int64;
- int64_t index = rng_fn(0, list.length-1, random_int64.userdata);
- if unlikely (index < 0 || index > list.length-1)
- fail("The provided random number function returned an invalid value: ", index, " (not between 0 and ", (int64_t)list.length, ")");
- return list.data + list.stride*index;
+ int64_t index = rng_fn(0, list.length - 1, random_int64.userdata);
+ if unlikely (index < 0 || index > list.length - 1)
+ fail("The provided random number function returned an invalid value: ", index, " (not between 0 and ",
+ (int64_t)list.length, ")");
+ return list.data + list.stride * index;
}
-public Table_t List$counts(List_t list, const TypeInfo_t *type)
-{
+public
+Table_t List$counts(List_t list, const TypeInfo_t *type) {
Table_t counts = {};
const TypeInfo_t count_type = *Table$info(type->ListInfo.item, &Int$info);
for (int64_t i = 0; i < list.length; i++) {
- void *key = list.data + i*list.stride;
+ void *key = list.data + i * list.stride;
int64_t *count = Table$get(counts, key, &count_type);
int64_t val = count ? *count + 1 : 1;
Table$set(&counts, key, &val, &count_type);
@@ -354,14 +343,13 @@ public Table_t List$counts(List_t list, const TypeInfo_t *type)
return counts;
}
-static double _default_random_num(void *userdata)
-{
+static double _default_random_num(void *userdata) {
(void)userdata;
union {
Num_t num;
uint64_t bits;
- } r = {.bits=0}, one = {.num=1.0};
- assert(getrandom((uint8_t*)&r, sizeof(r), 0) == sizeof(r));
+ } r = {.bits = 0}, one = {.num = 1.0};
+ assert(getrandom((uint8_t *)&r, sizeof(r), 0) == sizeof(r));
// Set r.num to 1.<random-bits>
r.bits &= ~(0xFFFULL << 52);
@@ -369,39 +357,30 @@ static double _default_random_num(void *userdata)
return r.num - 1.0;
}
-public List_t List$sample(List_t list, Int_t int_n, List_t weights, OptionalClosure_t random_num, int64_t padded_item_size)
-{
+public
+List_t List$sample(List_t list, Int_t int_n, List_t weights, OptionalClosure_t random_num, int64_t padded_item_size) {
int64_t n = Int64$from_int(int_n, false);
- if (n < 0)
- fail("Cannot select a negative number of values");
+ if (n < 0) fail("Cannot select a negative number of values");
- if (n == 0)
- return (List_t){};
+ if (n == 0) return (List_t){};
- if (list.length == 0)
- fail("There are no elements in this list!");
+ if (list.length == 0) fail("There are no elements in this list!");
if (weights.length != list.length)
fail("List has ", (int64_t)list.length, " elements, but there are ", (int64_t)weights.length, " weights given");
double total = 0.0;
for (int64_t i = 0; i < weights.length && i < list.length; i++) {
- double weight = *(double*)(weights.data + weights.stride*i);
- if (isinf(weight))
- fail("Infinite weight!");
- else if (isnan(weight))
- fail("NaN weight!");
- else if (weight < 0.0)
- fail("Negative weight!");
- else
- total += weight;
+ double weight = *(double *)(weights.data + weights.stride * i);
+ if (isinf(weight)) fail("Infinite weight!");
+ else if (isnan(weight)) fail("NaN weight!");
+ else if (weight < 0.0) fail("Negative weight!");
+ else total += weight;
}
- if (isinf(total))
- fail("Sample weights have overflowed to infinity");
+ if (isinf(total)) fail("Sample weights have overflowed to infinity");
- if (total == 0.0)
- fail("None of the given weights are nonzero");
+ if (total == 0.0) fail("None of the given weights are nonzero");
double inverse_average = (double)list.length / total;
@@ -411,7 +390,7 @@ public List_t List$sample(List_t list, Int_t int_n, List_t weights, OptionalClos
} aliases[list.length];
for (int64_t i = 0; i < list.length; i++) {
- double weight = i >= weights.length ? 0.0 : *(double*)(weights.data + weights.stride*i);
+ double weight = i >= weights.length ? 0.0 : *(double *)(weights.data + weights.stride * i);
aliases[i].odds = weight * inverse_average;
aliases[i].alias = -1;
}
@@ -435,16 +414,16 @@ public List_t List$sample(List_t list, Int_t int_n, List_t weights, OptionalClos
}
for (int64_t i = small; i < list.length; i++)
- if (aliases[i].alias == -1)
- aliases[i].alias = i;
+ if (aliases[i].alias == -1) aliases[i].alias = i;
- typedef double (*rng_fn_t)(void*);
+ typedef double (*rng_fn_t)(void *);
rng_fn_t rng_fn = random_num.fn ? (rng_fn_t)random_num.fn : _default_random_num;
- List_t selected = {
- .data=list.atomic ? GC_MALLOC_ATOMIC((size_t)(n * padded_item_size)) : GC_MALLOC((size_t)(n * padded_item_size)),
- .length=n,
- .stride=padded_item_size, .atomic=list.atomic};
+ List_t selected = {.data = list.atomic ? GC_MALLOC_ATOMIC((size_t)(n * padded_item_size))
+ : GC_MALLOC((size_t)(n * padded_item_size)),
+ .length = n,
+ .stride = padded_item_size,
+ .atomic = list.atomic};
for (int64_t i = 0; i < n; i++) {
double r = rng_fn(random_num.userdata);
if unlikely (r < 0.0 || r >= 1.0)
@@ -452,85 +431,77 @@ public List_t List$sample(List_t list, Int_t int_n, List_t weights, OptionalClos
r *= (double)list.length;
int64_t index = (int64_t)r;
assert(index >= 0 && index < list.length);
- if ((r - (double)index) > aliases[index].odds)
- index = aliases[index].alias;
- memcpy(selected.data + i*selected.stride, list.data + index*list.stride, (size_t)padded_item_size);
+ if ((r - (double)index) > aliases[index].odds) index = aliases[index].alias;
+ memcpy(selected.data + i * selected.stride, list.data + index * list.stride, (size_t)padded_item_size);
}
return selected;
}
-public List_t List$from(List_t list, Int_t first)
-{
- return List$slice(list, first, I_small(-1));
-}
+public
+List_t List$from(List_t list, Int_t first) { return List$slice(list, first, I_small(-1)); }
-public List_t List$to(List_t list, Int_t last)
-{
- return List$slice(list, I_small(1), last);
-}
+public
+List_t List$to(List_t list, Int_t last) { return List$slice(list, I_small(1), last); }
-public List_t List$by(List_t list, Int_t int_stride, int64_t padded_item_size)
-{
+public
+List_t List$by(List_t list, Int_t int_stride, int64_t padded_item_size) {
int64_t stride = Int64$from_int(int_stride, false);
// In the unlikely event that the stride value would be too large to fit in
// a 15-bit integer, fall back to creating a copy of the list:
- if (unlikely(list.stride*stride < LIST_MIN_STRIDE || list.stride*stride > LIST_MAX_STRIDE)) {
+ if (unlikely(list.stride * stride < LIST_MIN_STRIDE || list.stride * stride > LIST_MAX_STRIDE)) {
void *copy = NULL;
int64_t len = (stride < 0 ? list.length / -stride : list.length / stride) + ((list.length % stride) != 0);
if (len > 0) {
- copy = list.atomic ? GC_MALLOC_ATOMIC((size_t)(len * padded_item_size)) : GC_MALLOC((size_t)(len * padded_item_size));
+ copy = list.atomic ? GC_MALLOC_ATOMIC((size_t)(len * padded_item_size))
+ : GC_MALLOC((size_t)(len * padded_item_size));
void *start = (stride < 0 ? list.data + (list.stride * (list.length - 1)) : list.data);
for (int64_t i = 0; i < len; i++)
- memcpy(copy + i*padded_item_size, start + list.stride*stride*i, (size_t)padded_item_size);
+ memcpy(copy + i * padded_item_size, start + list.stride * stride * i, (size_t)padded_item_size);
}
return (List_t){
- .data=copy,
- .length=len,
- .stride=padded_item_size,
- .atomic=list.atomic,
+ .data = copy,
+ .length = len,
+ .stride = padded_item_size,
+ .atomic = list.atomic,
};
}
- if (stride == 0)
- return (List_t){.atomic=list.atomic};
+ if (stride == 0) return (List_t){.atomic = list.atomic};
return (List_t){
- .atomic=list.atomic,
- .data=(stride < 0 ? list.data + (list.stride * (list.length - 1)) : list.data),
- .length=(stride < 0 ? list.length / -stride : list.length / stride) + ((list.length % stride) != 0),
- .stride=list.stride * stride,
- .data_refcount=list.data_refcount,
+ .atomic = list.atomic,
+ .data = (stride < 0 ? list.data + (list.stride * (list.length - 1)) : list.data),
+ .length = (stride < 0 ? list.length / -stride : list.length / stride) + ((list.length % stride) != 0),
+ .stride = list.stride * stride,
+ .data_refcount = list.data_refcount,
};
}
-public List_t List$slice(List_t list, Int_t int_first, Int_t int_last)
+public
+List_t List$slice(List_t list, Int_t int_first, Int_t int_last)
{
int64_t first = Int64$from_int(int_first, false);
- if (first < 0)
- first = list.length + first + 1;
+ if (first < 0) first = list.length + first + 1;
int64_t last = Int64$from_int(int_last, false);
- if (last < 0)
- last = list.length + last + 1;
+ if (last < 0) last = list.length + last + 1;
- if (last > list.length)
- last = list.length;
+ if (last > list.length) last = list.length;
- if (first < 1 || first > list.length || last == 0)
- return (List_t){.atomic=list.atomic};
+ if (first < 1 || first > list.length || last == 0) return (List_t){.atomic = list.atomic};
return (List_t){
- .atomic=list.atomic,
- .data=list.data + list.stride*(first-1),
- .length=last - first + 1,
- .stride=list.stride,
- .data_refcount=list.data_refcount,
+ .atomic = list.atomic,
+ .data = list.data + list.stride * (first - 1),
+ .length = last - first + 1,
+ .stride = list.stride,
+ .data_refcount = list.data_refcount,
};
}
-public List_t List$reversed(List_t list, int64_t padded_item_size)
-{
+public
+List_t List$reversed(List_t list, int64_t padded_item_size) {
// Just in case negating the stride gives a value that doesn't fit into a
// 15-bit integer, fall back to List$by()'s more general method of copying
// the list. This should only happen if list.stride is MIN_STRIDE to
@@ -540,58 +511,54 @@ public List_t List$reversed(List_t list, int64_t padded_item_size)
List_t reversed = list;
reversed.stride = -list.stride;
- reversed.data = list.data + (list.length-1)*list.stride;
+ reversed.data = list.data + (list.length - 1) * list.stride;
return reversed;
}
-public List_t List$concat(List_t x, List_t y, int64_t padded_item_size)
-{
- void *data = x.atomic ? GC_MALLOC_ATOMIC((size_t)(padded_item_size*(x.length + y.length)))
- : GC_MALLOC((size_t)(padded_item_size*(x.length + y.length)));
+public
+List_t List$concat(List_t x, List_t y, int64_t padded_item_size) {
+ void *data = x.atomic ? GC_MALLOC_ATOMIC((size_t)(padded_item_size * (x.length + y.length)))
+ : GC_MALLOC((size_t)(padded_item_size * (x.length + y.length)));
if (x.stride == padded_item_size) {
- memcpy(data, x.data, (size_t)(padded_item_size*x.length));
+ memcpy(data, x.data, (size_t)(padded_item_size * x.length));
} else {
for (int64_t i = 0; i < x.length; i++)
- memcpy(data + i*padded_item_size, x.data + i*padded_item_size, (size_t)padded_item_size);
+ memcpy(data + i * padded_item_size, x.data + i * padded_item_size, (size_t)padded_item_size);
}
- void *dest = data + padded_item_size*x.length;
+ void *dest = data + padded_item_size * x.length;
if (y.stride == padded_item_size) {
- memcpy(dest, y.data, (size_t)(padded_item_size*y.length));
+ memcpy(dest, y.data, (size_t)(padded_item_size * y.length));
} else {
for (int64_t i = 0; i < y.length; i++)
- memcpy(dest + i*padded_item_size, y.data + i*y.stride, (size_t)padded_item_size);
+ memcpy(dest + i * padded_item_size, y.data + i * y.stride, (size_t)padded_item_size);
}
return (List_t){
- .data=data,
- .length=x.length + y.length,
- .stride=padded_item_size,
- .atomic=x.atomic,
+ .data = data,
+ .length = x.length + y.length,
+ .stride = padded_item_size,
+ .atomic = x.atomic,
};
}
-public bool List$has(List_t list, void *item, const TypeInfo_t *type)
-{
+public
+bool List$has(List_t list, void *item, const TypeInfo_t *type) {
const TypeInfo_t *item_type = type->ListInfo.item;
for (int64_t i = 0; i < list.length; i++) {
- if (generic_equal(list.data + i*list.stride, item, item_type))
- return true;
+ if (generic_equal(list.data + i * list.stride, item, item_type)) return true;
}
return false;
}
-public void List$clear(List_t *list)
-{
- *list = (List_t){.data=0, .length=0};
-}
+public
+void List$clear(List_t *list) { *list = (List_t){.data = 0, .length = 0}; }
-public int32_t List$compare(const void *vx, const void *vy, const TypeInfo_t *type)
-{
- const List_t *x = (List_t*)vx, *y = (List_t*)vy;
+public
+int32_t List$compare(const void *vx, const void *vy, const TypeInfo_t *type) {
+ const List_t *x = (List_t *)vx, *y = (List_t *)vy;
// Early out for lists with the same data, e.g. two copies of the same list:
- if (x->data == y->data && x->stride == y->stride)
- return (x->length > y->length) - (x->length < y->length);
+ if (x->data == y->data && x->stride == y->stride) return (x->length > y->length) - (x->length < y->length);
const TypeInfo_t *item = type->ListInfo.item;
if (item->tag == PointerInfo || !item->metamethods.compare) { // data comparison
@@ -599,128 +566,120 @@ public int32_t List$compare(const void *vx, const void *vy, const TypeInfo_t *ty
if (type->ListInfo.item->align > 1 && item_padded_size % type->ListInfo.item->align)
errx(1, "Item size is not padded!");
- if ((int64_t)x->stride == item_padded_size && (int64_t)y->stride == item_padded_size && item->size == item_padded_size) {
- int32_t cmp = (int32_t)memcmp(x->data, y->data, (size_t)(MIN(x->length, y->length)*item_padded_size));
+ if ((int64_t)x->stride == item_padded_size && (int64_t)y->stride == item_padded_size
+ && item->size == item_padded_size) {
+ int32_t cmp = (int32_t)memcmp(x->data, y->data, (size_t)(MIN(x->length, y->length) * item_padded_size));
if (cmp != 0) return cmp;
} else {
for (int32_t i = 0, len = MIN(x->length, y->length); i < len; i++) {
- int32_t cmp = (int32_t)memcmp(x->data+ x->stride*i, y->data + y->stride*i, (size_t)(item->size));
+ int32_t cmp = (int32_t)memcmp(x->data + x->stride * i, y->data + y->stride * i, (size_t)(item->size));
if (cmp != 0) return cmp;
}
}
} else {
for (int32_t i = 0, len = MIN(x->length, y->length); i < len; i++) {
- int32_t cmp = generic_compare(x->data + x->stride*i, y->data + y->stride*i, item);
+ int32_t cmp = generic_compare(x->data + x->stride * i, y->data + y->stride * i, item);
if (cmp != 0) return cmp;
}
}
return (x->length > y->length) - (x->length < y->length);
}
-public bool List$equal(const void *x, const void *y, const TypeInfo_t *type)
-{
- return x == y || (((List_t*)x)->length == ((List_t*)y)->length && List$compare(x, y, type) == 0);
+public
+bool List$equal(const void *x, const void *y, const TypeInfo_t *type) {
+ return x == y || (((List_t *)x)->length == ((List_t *)y)->length && List$compare(x, y, type) == 0);
}
-public Text_t List$as_text(const void *obj, bool colorize, const TypeInfo_t *type)
-{
- List_t *list = (List_t*)obj;
- if (!list)
- return Text$concat(Text("["), generic_as_text(NULL, false, type->ListInfo.item), Text("]"));
+public
+Text_t List$as_text(const void *obj, bool colorize, const TypeInfo_t *type) {
+ List_t *list = (List_t *)obj;
+ if (!list) return Text$concat(Text("["), generic_as_text(NULL, false, type->ListInfo.item), Text("]"));
const TypeInfo_t *item_type = type->ListInfo.item;
Text_t text = Text("[");
for (int64_t i = 0; i < list->length; i++) {
- if (i > 0)
- text = Text$concat(text, Text(", "));
- Text_t item_text = generic_as_text(list->data + i*list->stride, colorize, item_type);
+ if (i > 0) text = Text$concat(text, Text(", "));
+ Text_t item_text = generic_as_text(list->data + i * list->stride, colorize, item_type);
text = Text$concat(text, item_text);
}
text = Text$concat(text, Text("]"));
return text;
}
-public uint64_t List$hash(const void *obj, const TypeInfo_t *type)
-{
- const List_t *list = (List_t*)obj;
+public
+uint64_t List$hash(const void *obj, const TypeInfo_t *type) {
+ const List_t *list = (List_t *)obj;
const TypeInfo_t *item = type->ListInfo.item;
siphash sh;
siphashinit(&sh, sizeof(uint64_t[list->length]));
- if (item->tag == PointerInfo || (!item->metamethods.hash && item->size == sizeof(void*))) { // Raw data hash
+ if (item->tag == PointerInfo || (!item->metamethods.hash && item->size == sizeof(void *))) { // Raw data hash
for (int64_t i = 0; i < list->length; i++)
- siphashadd64bits(&sh, (uint64_t)(list->data + i*list->stride));
+ siphashadd64bits(&sh, (uint64_t)(list->data + i * list->stride));
} else {
for (int64_t i = 0; i < list->length; i++) {
- uint64_t item_hash = generic_hash(list->data + i*list->stride, item);
+ uint64_t item_hash = generic_hash(list->data + i * list->stride, item);
siphashadd64bits(&sh, item_hash);
}
}
return siphashfinish_last_part(&sh, 0);
}
-static void siftdown(List_t *heap, int64_t startpos, int64_t pos, Closure_t comparison, int64_t padded_item_size)
-{
+static void siftdown(List_t *heap, int64_t startpos, int64_t pos, Closure_t comparison, int64_t padded_item_size) {
assert(pos > 0 && pos < heap->length);
char newitem[padded_item_size];
- memcpy(newitem, heap->data + heap->stride*pos, (size_t)(padded_item_size));
+ memcpy(newitem, heap->data + heap->stride * pos, (size_t)(padded_item_size));
while (pos > startpos) {
int64_t parentpos = (pos - 1) >> 1;
- typedef int32_t (*cmp_fn_t)(void*, void*, void*);
- int32_t cmp = ((cmp_fn_t)comparison.fn)(newitem, heap->data + heap->stride*parentpos, comparison.userdata);
- if (cmp >= 0)
- break;
+ typedef int32_t (*cmp_fn_t)(void *, void *, void *);
+ int32_t cmp = ((cmp_fn_t)comparison.fn)(newitem, heap->data + heap->stride * parentpos, comparison.userdata);
+ if (cmp >= 0) break;
- memcpy(heap->data + heap->stride*pos, heap->data + heap->stride*parentpos, (size_t)(padded_item_size));
+ memcpy(heap->data + heap->stride * pos, heap->data + heap->stride * parentpos, (size_t)(padded_item_size));
pos = parentpos;
}
- memcpy(heap->data + heap->stride*pos, newitem, (size_t)(padded_item_size));
+ memcpy(heap->data + heap->stride * pos, newitem, (size_t)(padded_item_size));
}
-static void siftup(List_t *heap, int64_t pos, Closure_t comparison, int64_t padded_item_size)
-{
+static void siftup(List_t *heap, int64_t pos, Closure_t comparison, int64_t padded_item_size) {
int64_t endpos = heap->length;
int64_t startpos = pos;
assert(pos < endpos);
char old_top[padded_item_size];
- memcpy(old_top, heap->data + heap->stride*pos, (size_t)(padded_item_size));
+ memcpy(old_top, heap->data + heap->stride * pos, (size_t)(padded_item_size));
// Bubble up the smallest leaf node
int64_t limit = endpos >> 1;
while (pos < limit) {
- int64_t childpos = 2*pos + 1; // Smaller of the two child nodes
+ int64_t childpos = 2 * pos + 1; // Smaller of the two child nodes
if (childpos + 1 < endpos) {
- typedef int32_t (*cmp_fn_t)(void*, void*, void*);
- int32_t cmp = ((cmp_fn_t)comparison.fn)(
- heap->data + heap->stride*childpos,
- heap->data + heap->stride*(childpos + 1),
- comparison.userdata);
+ typedef int32_t (*cmp_fn_t)(void *, void *, void *);
+ int32_t cmp = ((cmp_fn_t)comparison.fn)(heap->data + heap->stride * childpos,
+ heap->data + heap->stride * (childpos + 1), comparison.userdata);
childpos += (cmp >= 0);
}
// Move the child node up:
- memcpy(heap->data + heap->stride*pos, heap->data + heap->stride*childpos, (size_t)(padded_item_size));
+ memcpy(heap->data + heap->stride * pos, heap->data + heap->stride * childpos, (size_t)(padded_item_size));
pos = childpos;
}
- memcpy(heap->data + heap->stride*pos, old_top, (size_t)(padded_item_size));
+ memcpy(heap->data + heap->stride * pos, old_top, (size_t)(padded_item_size));
// Shift the node's parents down:
siftdown(heap, startpos, pos, comparison, padded_item_size);
}
-public void List$heap_push(List_t *heap, const void *item, Closure_t comparison, int64_t padded_item_size)
-{
+public
+void List$heap_push(List_t *heap, const void *item, Closure_t comparison, int64_t padded_item_size) {
List$insert(heap, item, I(0), padded_item_size);
if (heap->length > 1) {
- if (heap->data_refcount != 0)
- List$compact(heap, padded_item_size);
- siftdown(heap, 0, heap->length-1, comparison, padded_item_size);
+ if (heap->data_refcount != 0) List$compact(heap, padded_item_size);
+ siftdown(heap, 0, heap->length - 1, comparison, padded_item_size);
}
}
-public void List$heap_pop(List_t *heap, Closure_t comparison, int64_t padded_item_size)
-{
- if (heap->length == 0)
- fail("Attempt to pop from an empty list");
+public
+void List$heap_pop(List_t *heap, Closure_t comparison, int64_t padded_item_size) {
+ if (heap->length == 0) fail("Attempt to pop from an empty list");
if (heap->length == 1) {
*heap = (List_t){};
@@ -728,96 +687,90 @@ public void List$heap_pop(List_t *heap, Closure_t comparison, int64_t padded_ite
heap->data += heap->stride;
--heap->length;
} else {
- if (heap->data_refcount != 0)
- List$compact(heap, padded_item_size);
- memcpy(heap->data, heap->data + heap->stride*(heap->length-1), (size_t)(padded_item_size));
+ if (heap->data_refcount != 0) List$compact(heap, padded_item_size);
+ memcpy(heap->data, heap->data + heap->stride * (heap->length - 1), (size_t)(padded_item_size));
--heap->length;
siftup(heap, 0, comparison, padded_item_size);
}
}
-public void List$heapify(List_t *heap, Closure_t comparison, int64_t padded_item_size)
-{
- if (heap->data_refcount != 0)
- List$compact(heap, padded_item_size);
+public
+void List$heapify(List_t *heap, Closure_t comparison, int64_t padded_item_size) {
+ if (heap->data_refcount != 0) List$compact(heap, padded_item_size);
// It's necessary to bump the refcount because the user's comparison
// function could do stuff that modifies the heap's data.
LIST_INCREF(*heap);
int64_t i, n = heap->length;
- for (i = (n >> 1) - 1 ; i >= 0 ; i--)
+ for (i = (n >> 1) - 1; i >= 0; i--)
siftup(heap, i, comparison, padded_item_size);
LIST_DECREF(*heap);
}
-public Int_t List$binary_search(List_t list, void *target, Closure_t comparison)
-{
- typedef int32_t (*cmp_fn_t)(void*, void*, void*);
- int64_t lo = 0, hi = list.length-1;
+public
+Int_t List$binary_search(List_t list, void *target, Closure_t comparison) {
+ typedef int32_t (*cmp_fn_t)(void *, void *, void *);
+ int64_t lo = 0, hi = list.length - 1;
while (lo <= hi) {
int64_t mid = (lo + hi) / 2;
- int32_t cmp = ((cmp_fn_t)comparison.fn)(
- list.data + list.stride*mid, target, comparison.userdata);
- if (cmp == 0)
- return I(mid+1);
- else if (cmp < 0)
- lo = mid + 1;
- else if (cmp > 0)
- hi = mid - 1;
+ int32_t cmp = ((cmp_fn_t)comparison.fn)(list.data + list.stride * mid, target, comparison.userdata);
+ if (cmp == 0) return I(mid + 1);
+ else if (cmp < 0) lo = mid + 1;
+ else if (cmp > 0) hi = mid - 1;
}
- return I(lo+1); // Return the index where the target would be inserted
+ return I(lo + 1); // Return the index where the target would be inserted
}
-public PUREFUNC bool List$is_none(const void *obj, const TypeInfo_t *info)
-{
+public
+PUREFUNC bool List$is_none(const void *obj, const TypeInfo_t *info) {
(void)info;
- return ((List_t*)obj)->length < 0;
+ return ((List_t *)obj)->length < 0;
}
-public void List$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type)
-{
- List_t list = *(List_t*)obj;
+public
+void List$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
+ List_t list = *(List_t *)obj;
int64_t len = list.length;
Int64$serialize(&len, out, pointers, &Int64$info);
serialize_fn_t item_serialize = type->ListInfo.item->metamethods.serialize;
if (item_serialize) {
for (int64_t i = 0; i < len; i++)
- item_serialize(list.data + i*list.stride, out, pointers, type->ListInfo.item);
+ item_serialize(list.data + i * list.stride, out, pointers, type->ListInfo.item);
} else if (list.stride == type->ListInfo.item->size) {
fwrite(list.data, (size_t)type->ListInfo.item->size, (size_t)len, out);
} else {
for (int64_t i = 0; i < len; i++)
- fwrite(list.data + i*list.stride, (size_t)type->ListInfo.item->size, 1, out);
+ fwrite(list.data + i * list.stride, (size_t)type->ListInfo.item->size, 1, out);
}
}
-public void List$deserialize(FILE *in, void *obj, List_t *pointers, const TypeInfo_t *type)
-{
+public
+void List$deserialize(FILE *in, void *obj, List_t *pointers, const TypeInfo_t *type) {
int64_t len = -1;
Int64$deserialize(in, &len, pointers, &Int64$info);
int64_t padded_size = type->ListInfo.item->size;
if (type->ListInfo.item->align > 0 && padded_size % type->ListInfo.item->align > 0)
padded_size += type->ListInfo.item->align - (padded_size % type->ListInfo.item->align);
List_t list = {
- .length=len,
- .data=GC_MALLOC((size_t)(len*padded_size)),
- .stride=padded_size,
+ .length = len,
+ .data = GC_MALLOC((size_t)(len * padded_size)),
+ .stride = padded_size,
};
deserialize_fn_t item_deserialize = type->ListInfo.item->metamethods.deserialize;
if (item_deserialize) {
for (int64_t i = 0; i < len; i++)
- item_deserialize(in, list.data + i*list.stride, pointers, type->ListInfo.item);
+ item_deserialize(in, list.data + i * list.stride, pointers, type->ListInfo.item);
} else if (list.stride == type->ListInfo.item->size) {
if (fread(list.data, (size_t)type->ListInfo.item->size, (size_t)len, in) != (size_t)len)
fail("Not enough data in stream to deserialize");
} else {
size_t item_size = (size_t)type->ListInfo.item->size;
for (int64_t i = 0; i < len; i++) {
- if (fread(list.data + i*list.stride, item_size, 1, in) != 1)
+ if (fread(list.data + i * list.stride, item_size, 1, in) != 1)
fail("Not enough data in stream to deserialize");
}
}
- *(List_t*)obj = list;
+ *(List_t *)obj = list;
}
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/lists.h b/src/stdlib/lists.h
index a2853e48..afda3d74 100644
--- a/src/stdlib/lists.h
+++ b/src/stdlib/lists.h
@@ -10,88 +10,141 @@
#include "util.h"
// Convert negative indices to back-indexed without branching: index0 = index + (index < 0)*(len+1)) - 1
-#define List_get(item_type, arr_expr, index_expr, start, end) *({ \
- const List_t list = arr_expr; int64_t index = index_expr; \
- int64_t off = index + (index < 0) * (list.length + 1) - 1; \
- if (unlikely(off < 0 || off >= list.length)) \
- fail_source(__SOURCE_FILE__, start, end, "Invalid list index: ", index, " (list has length ", (int64_t)list.length, ")\n"); \
- (item_type*)(list.data + list.stride * off);})
-#define List_get_unchecked(type, x, i) *({ const List_t list = x; int64_t index = i; \
- int64_t off = index + (index < 0) * (list.length + 1) - 1; \
- (type*)(list.data + list.stride * off);})
-#define List_lvalue(item_type, arr_expr, index_expr, start, end) *({ \
- List_t *list = arr_expr; int64_t index = index_expr; \
- int64_t off = index + (index < 0) * (list->length + 1) - 1; \
- if (unlikely(off < 0 || off >= list->length)) \
- fail_source(__SOURCE_FILE__, start, end, "Invalid list index: ", index, " (list has length ", (int64_t)list->length, ")\n"); \
- if (list->data_refcount > 0) \
- List$compact(list, sizeof(item_type)); \
- (item_type*)(list->data + list->stride * off); })
-#define List_lvalue_unchecked(item_type, arr_expr, index_expr) *({ \
- List_t *list = arr_expr; int64_t index = index_expr; \
- int64_t off = index + (index < 0) * (list->length + 1) - 1; \
- if (list->data_refcount > 0) \
- List$compact(list, sizeof(item_type)); \
- (item_type*)(list->data + list->stride * off); })
-#define List_set(item_type, list, index, value, start, end) \
- List_lvalue(item_type, arr_expr, index, start, end) = value
-#define is_atomic(x) _Generic(x, bool: true, int8_t: true, int16_t: true, int32_t: true, int64_t: true, float: true, double: true, default: false)
-#define TypedList(t, ...) ({ t items[] = {__VA_ARGS__}; \
- (List_t){.length=sizeof(items)/sizeof(items[0]), \
- .stride=(int64_t)&items[1] - (int64_t)&items[0], \
- .data=memcpy(GC_MALLOC(sizeof(items)), items, sizeof(items)), \
- .atomic=0, \
- .data_refcount=0}; })
-#define TypedListN(t, N, ...) ({ t items[N] = {__VA_ARGS__}; \
- (List_t){.length=N, \
- .stride=(int64_t)&items[1] - (int64_t)&items[0], \
- .data=memcpy(GC_MALLOC(sizeof(items)), items, sizeof(items)), \
- .atomic=0, \
- .data_refcount=0}; })
-#define List(x, ...) ({ __typeof(x) items[] = {x, __VA_ARGS__}; \
- (List_t){.length=sizeof(items)/sizeof(items[0]), \
- .stride=(int64_t)&items[1] - (int64_t)&items[0], \
- .data=memcpy(is_atomic(x) ? GC_MALLOC_ATOMIC(sizeof(items)) : GC_MALLOC(sizeof(items)), items, sizeof(items)), \
- .atomic=is_atomic(x), \
- .data_refcount=0}; })
+#define List_get(item_type, arr_expr, index_expr, start, end) \
+ *({ \
+ const List_t list = arr_expr; \
+ int64_t index = index_expr; \
+ int64_t off = index + (index < 0) * (list.length + 1) - 1; \
+ if (unlikely(off < 0 || off >= list.length)) \
+ fail_source(__SOURCE_FILE__, start, end, "Invalid list index: ", index, " (list has length ", \
+ (int64_t)list.length, ")\n"); \
+ (item_type *)(list.data + list.stride * off); \
+ })
+#define List_get_unchecked(type, x, i) \
+ *({ \
+ const List_t list = x; \
+ int64_t index = i; \
+ int64_t off = index + (index < 0) * (list.length + 1) - 1; \
+ (type *)(list.data + list.stride * off); \
+ })
+#define List_lvalue(item_type, arr_expr, index_expr, start, end) \
+ *({ \
+ List_t *list = arr_expr; \
+ int64_t index = index_expr; \
+ int64_t off = index + (index < 0) * (list->length + 1) - 1; \
+ if (unlikely(off < 0 || off >= list->length)) \
+ fail_source(__SOURCE_FILE__, start, end, "Invalid list index: ", index, " (list has length ", \
+ (int64_t)list->length, ")\n"); \
+ if (list->data_refcount > 0) List$compact(list, sizeof(item_type)); \
+ (item_type *)(list->data + list->stride * off); \
+ })
+#define List_lvalue_unchecked(item_type, arr_expr, index_expr) \
+ *({ \
+ List_t *list = arr_expr; \
+ int64_t index = index_expr; \
+ int64_t off = index + (index < 0) * (list->length + 1) - 1; \
+ if (list->data_refcount > 0) List$compact(list, sizeof(item_type)); \
+ (item_type *)(list->data + list->stride * off); \
+ })
+#define List_set(item_type, list, index, value, start, end) List_lvalue(item_type, arr_expr, index, start, end) = value
+#define is_atomic(x) \
+ _Generic(x, \
+ bool: true, \
+ int8_t: true, \
+ int16_t: true, \
+ int32_t: true, \
+ int64_t: true, \
+ float: true, \
+ double: true, \
+ default: false)
+#define TypedList(t, ...) \
+ ({ \
+ t items[] = {__VA_ARGS__}; \
+ (List_t){.length = sizeof(items) / sizeof(items[0]), \
+ .stride = (int64_t)&items[1] - (int64_t)&items[0], \
+ .data = memcpy(GC_MALLOC(sizeof(items)), items, sizeof(items)), \
+ .atomic = 0, \
+ .data_refcount = 0}; \
+ })
+#define TypedListN(t, N, ...) \
+ ({ \
+ t items[N] = {__VA_ARGS__}; \
+ (List_t){.length = N, \
+ .stride = (int64_t)&items[1] - (int64_t)&items[0], \
+ .data = memcpy(GC_MALLOC(sizeof(items)), items, sizeof(items)), \
+ .atomic = 0, \
+ .data_refcount = 0}; \
+ })
+#define List(x, ...) \
+ ({ \
+ __typeof(x) items[] = {x, __VA_ARGS__}; \
+ (List_t){.length = sizeof(items) / sizeof(items[0]), \
+ .stride = (int64_t)&items[1] - (int64_t)&items[0], \
+ .data = memcpy(is_atomic(x) ? GC_MALLOC_ATOMIC(sizeof(items)) : GC_MALLOC(sizeof(items)), items, \
+ sizeof(items)), \
+ .atomic = is_atomic(x), \
+ .data_refcount = 0}; \
+ })
// List refcounts use a saturating add, where once it's at the max value, it stays there.
#define LIST_INCREF(list) (list).data_refcount += ((list).data_refcount < LIST_MAX_DATA_REFCOUNT)
#define LIST_DECREF(list) (list).data_refcount -= ((list).data_refcount < LIST_MAX_DATA_REFCOUNT)
-#define LIST_COPY(list) ({ LIST_INCREF(list); list; })
+#define LIST_COPY(list) \
+ ({ \
+ LIST_INCREF(list); \
+ list; \
+ })
-#define List$insert_value(list, item_expr, index, padded_item_size) List$insert(list, (__typeof(item_expr)[1]){item_expr}, index, padded_item_size)
+#define List$insert_value(list, item_expr, index, padded_item_size) \
+ List$insert(list, (__typeof(item_expr)[1]){item_expr}, index, padded_item_size)
void List$insert(List_t *list, const void *item, Int_t index, int64_t padded_item_size);
void List$insert_all(List_t *list, List_t to_insert, Int_t index, int64_t padded_item_size);
void List$remove_at(List_t *list, Int_t index, Int_t count, int64_t padded_item_size);
void List$remove_item(List_t *list, void *item, Int_t max_removals, const TypeInfo_t *type);
-#define List$remove_item_value(list, item_expr, max, type) List$remove_item(list, (__typeof(item_expr)[1]){item_expr}, max, type)
+#define List$remove_item_value(list, item_expr, max, type) \
+ List$remove_item(list, (__typeof(item_expr)[1]){item_expr}, max, type)
-#define List$pop(arr_expr, index_expr, item_type, nonnone_var, nonnone_expr, none_expr) ({ \
- List_t *list = arr_expr; \
- Int_t index = index_expr; \
- int64_t index64 = Int64$from_int(index, false); \
- int64_t off = index64 + (index64 < 0) * (list->length + 1) - 1; \
- (off >= 0 && off < list->length) ? ({ \
- item_type nonnone_var = *(item_type*)(list->data + off*list->stride); \
- List$remove_at(list, index, I_small(1), sizeof(item_type)); \
- nonnone_expr; \
- }) : none_expr; })
+#define List$pop(arr_expr, index_expr, item_type, nonnone_var, nonnone_expr, none_expr) \
+ ({ \
+ List_t *list = arr_expr; \
+ Int_t index = index_expr; \
+ int64_t index64 = Int64$from_int(index, false); \
+ int64_t off = index64 + (index64 < 0) * (list->length + 1) - 1; \
+ (off >= 0 && off < list->length) ? ({ \
+ item_type nonnone_var = *(item_type *)(list->data + off * list->stride); \
+ List$remove_at(list, index, I_small(1), sizeof(item_type)); \
+ nonnone_expr; \
+ }) \
+ : none_expr; \
+ })
OptionalInt_t List$find(List_t list, void *item, const TypeInfo_t *type);
-#define List$find_value(list, item_expr, type) ({ __typeof(item_expr) item = item_expr; List$find(list, &item, type); })
+#define List$find_value(list, item_expr, type) \
+ ({ \
+ __typeof(item_expr) item = item_expr; \
+ List$find(list, &item, type); \
+ })
OptionalInt_t List$first(List_t list, Closure_t predicate);
void List$sort(List_t *list, Closure_t comparison, int64_t padded_item_size);
List_t List$sorted(List_t list, Closure_t comparison, int64_t padded_item_size);
void List$shuffle(List_t *list, OptionalClosure_t random_int64, int64_t padded_item_size);
List_t List$shuffled(List_t list, OptionalClosure_t random_int64, int64_t padded_item_size);
void *List$random(List_t list, OptionalClosure_t random_int64);
-#define List$random_value(list, random_int64, t) ({ List_t _arr = list; if (_arr.length == 0) fail("Cannot get a random value from an empty list!"); *(t*)List$random(_arr, random_int64); })
+#define List$random_value(list, random_int64, t) \
+ ({ \
+ List_t _arr = list; \
+ if (_arr.length == 0) fail("Cannot get a random value from an empty list!"); \
+ *(t *)List$random(_arr, random_int64); \
+ })
List_t List$sample(List_t list, Int_t n, List_t weights, Closure_t random_num, int64_t padded_item_size);
Table_t List$counts(List_t list, const TypeInfo_t *type);
void List$clear(List_t *list);
void List$compact(List_t *list, int64_t padded_item_size);
PUREFUNC bool List$has(List_t list, void *item, const TypeInfo_t *type);
-#define List$has_value(list, item_expr, type) ({ __typeof(item_expr) item = item_expr; List$has(list, &item, type); })
+#define List$has_value(list, item_expr, type) \
+ ({ \
+ __typeof(item_expr) item = item_expr; \
+ List$has(list, &item, type); \
+ })
PUREFUNC List_t List$from(List_t list, Int_t first);
PUREFUNC List_t List$to(List_t list, Int_t last);
PUREFUNC List_t List$by(List_t list, Int_t stride, int64_t padded_item_size);
@@ -101,37 +154,51 @@ List_t List$concat(List_t x, List_t y, int64_t padded_item_size);
PUREFUNC uint64_t List$hash(const void *list, const TypeInfo_t *type);
PUREFUNC int32_t List$compare(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC bool List$equal(const void *x, const void *y, const TypeInfo_t *type);
-PUREFUNC bool List$is_none(const void *obj, const TypeInfo_t*);
+PUREFUNC bool List$is_none(const void *obj, const TypeInfo_t *);
Text_t List$as_text(const void *list, bool colorize, const TypeInfo_t *type);
void List$heapify(List_t *heap, Closure_t comparison, int64_t padded_item_size);
void List$heap_push(List_t *heap, const void *item, Closure_t comparison, int64_t padded_item_size);
-#define List$heap_push_value(heap, _value, comparison, padded_item_size) ({ __typeof(_value) value = _value; List$heap_push(heap, &value, comparison, padded_item_size); })
+#define List$heap_push_value(heap, _value, comparison, padded_item_size) \
+ ({ \
+ __typeof(_value) value = _value; \
+ List$heap_push(heap, &value, comparison, padded_item_size); \
+ })
void List$heap_pop(List_t *heap, Closure_t comparison, int64_t padded_item_size);
-#define List$heap_pop_value(heap, comparison, type, nonnone_var, nonnone_expr, none_expr) \
- ({ List_t *_heap = heap; \
- (_heap->length > 0) ? ({ \
- type nonnone_var = *(type*)_heap->data; \
- List$heap_pop(_heap, comparison, sizeof(type)); \
- nonnone_expr; \
- }) : none_expr; })
+#define List$heap_pop_value(heap, comparison, type, nonnone_var, nonnone_expr, none_expr) \
+ ({ \
+ List_t *_heap = heap; \
+ (_heap->length > 0) ? ({ \
+ type nonnone_var = *(type *)_heap->data; \
+ List$heap_pop(_heap, comparison, sizeof(type)); \
+ nonnone_expr; \
+ }) \
+ : none_expr; \
+ })
Int_t List$binary_search(List_t list, void *target, Closure_t comparison);
-#define List$binary_search_value(list, target, comparison) \
- ({ __typeof(target) _target = target; List$binary_search(list, &_target, comparison); })
+#define List$binary_search_value(list, target, comparison) \
+ ({ \
+ __typeof(target) _target = target; \
+ List$binary_search(list, &_target, comparison); \
+ })
void List$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type);
void List$deserialize(FILE *in, void *obj, List_t *pointers, const TypeInfo_t *type);
-#define List$metamethods { \
- .as_text=List$as_text, \
- .compare=List$compare, \
- .equal=List$equal, \
- .hash=List$hash, \
- .is_none=List$is_none, \
- .serialize=List$serialize, \
- .deserialize=List$deserialize, \
-}
+#define List$metamethods \
+ { \
+ .as_text = List$as_text, \
+ .compare = List$compare, \
+ .equal = List$equal, \
+ .hash = List$hash, \
+ .is_none = List$is_none, \
+ .serialize = List$serialize, \
+ .deserialize = List$deserialize, \
+ }
-#define List$info(item_info) &((TypeInfo_t){.size=sizeof(List_t), .align=__alignof__(List_t), \
- .tag=ListInfo, .ListInfo.item=item_info, \
- .metamethods=List$metamethods})
+#define List$info(item_info) \
+ &((TypeInfo_t){.size = sizeof(List_t), \
+ .align = __alignof__(List_t), \
+ .tag = ListInfo, \
+ .ListInfo.item = item_info, \
+ .metamethods = List$metamethods})
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/mapmacro.h b/src/stdlib/mapmacro.h
index 5ed7a4b7..68834f8f 100644
--- a/src/stdlib/mapmacro.h
+++ b/src/stdlib/mapmacro.h
@@ -9,7 +9,7 @@
#define EVAL2(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL3(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL4(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
-#define EVAL(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
+#define EVAL(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
#define MAP_END(...)
#define MAP_OUT
@@ -21,7 +21,7 @@
#define MAP_NEXT0(test, next, ...) next MAP_OUT
#define MAP_LIST_NEXT1(test, next) MAP_NEXT0(test, MAP_COMMA next, 0)
-#define MAP_LIST_NEXT(test, next) MAP_LIST_NEXT1(MAP_GET_END test, next)
+#define MAP_LIST_NEXT(test, next) MAP_LIST_NEXT1(MAP_GET_END test, next)
#define MAP_LIST0(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST1)(f, peek, __VA_ARGS__)
#define MAP_LIST1(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST0)(f, peek, __VA_ARGS__)
diff --git a/src/stdlib/memory.c b/src/stdlib/memory.c
index a28b0069..90e14261 100644
--- a/src/stdlib/memory.c
+++ b/src/stdlib/memory.c
@@ -1,9 +1,9 @@
// Type info and methods for "Memory" opaque type
+#include <err.h>
#include <gc.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/param.h>
-#include <err.h>
#include "memory.h"
#include "metamethods.h"
@@ -12,21 +12,24 @@
#include "types.h"
#include "util.h"
-public Text_t Memory$as_text(const void *p, bool colorize, const TypeInfo_t *info) {
+public
+Text_t Memory$as_text(const void *p, bool colorize, const TypeInfo_t *info) {
(void)info;
if (!p) return Text("Memory");
- Text_t text = Text$from_str(String("Memory<", *(void**)p, ">"));
+ Text_t text = Text$from_str(String("Memory<", *(void **)p, ">"));
return colorize ? Texts(Text("\x1b[0;34;1m"), text, Text("\x1b[m")) : text;
}
-public const TypeInfo_t Memory$info = {
- .size=0,
- .align=0,
- .metamethods={
- .as_text=Memory$as_text,
- .serialize=cannot_serialize,
- .deserialize=cannot_deserialize,
- },
+public
+const TypeInfo_t Memory$info = {
+ .size = 0,
+ .align = 0,
+ .metamethods =
+ {
+ .as_text = Memory$as_text,
+ .serialize = cannot_serialize,
+ .deserialize = cannot_deserialize,
+ },
};
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/metamethods.c b/src/stdlib/metamethods.c
index 8c755c59..ea06d20b 100644
--- a/src/stdlib/metamethods.c
+++ b/src/stdlib/metamethods.c
@@ -9,52 +9,44 @@
#include "types.h"
#include "util.h"
-PUREFUNC public uint64_t generic_hash(const void *obj, const TypeInfo_t *type)
-{
- if (type->metamethods.hash)
- return type->metamethods.hash(obj, type);
+PUREFUNC public uint64_t generic_hash(const void *obj, const TypeInfo_t *type) {
+ if (type->metamethods.hash) return type->metamethods.hash(obj, type);
- return siphash24((void*)obj, (size_t)(type->size));
+ return siphash24((void *)obj, (size_t)(type->size));
}
-PUREFUNC public int32_t generic_compare(const void *x, const void *y, const TypeInfo_t *type)
-{
+PUREFUNC public int32_t generic_compare(const void *x, const void *y, const TypeInfo_t *type) {
if (x == y) return 0;
- if (type->metamethods.compare)
- return type->metamethods.compare(x, y, type);
+ if (type->metamethods.compare) return type->metamethods.compare(x, y, type);
- return (int32_t)memcmp((void*)x, (void*)y, (size_t)(type->size));
+ return (int32_t)memcmp((void *)x, (void *)y, (size_t)(type->size));
}
-PUREFUNC public bool generic_equal(const void *x, const void *y, const TypeInfo_t *type)
-{
+PUREFUNC public bool generic_equal(const void *x, const void *y, const TypeInfo_t *type) {
if (x == y) return true;
- if (type->metamethods.equal)
- return type->metamethods.equal(x, y, type);
+ if (type->metamethods.equal) return type->metamethods.equal(x, y, type);
return (generic_compare(x, y, type) == 0);
}
-public Text_t generic_as_text(const void *obj, bool colorize, const TypeInfo_t *type)
-{
- if (!type->metamethods.as_text)
- fail("No text metamethod provided for type!");
+public
+Text_t generic_as_text(const void *obj, bool colorize, const TypeInfo_t *type) {
+ if (!type->metamethods.as_text) fail("No text metamethod provided for type!");
return type->metamethods.as_text(obj, colorize, type);
}
-public void _serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type)
-{
- if (type->metamethods.serialize)
- return type->metamethods.serialize(obj, out, pointers, type);
+public
+void _serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
+ if (type->metamethods.serialize) return type->metamethods.serialize(obj, out, pointers, type);
fwrite(obj, (size_t)type->size, 1, out);
}
-public List_t generic_serialize(const void *x, const TypeInfo_t *type)
-{
+public
+List_t generic_serialize(const void *x, const TypeInfo_t *type) {
char *buf = NULL;
size_t size = 0;
FILE *stream = open_memstream(&buf, &size);
@@ -62,31 +54,29 @@ public List_t generic_serialize(const void *x, const TypeInfo_t *type)
_serialize(x, stream, &pointers, type);
fclose(stream);
List_t bytes = {
- .data=GC_MALLOC_ATOMIC(size),
- .length=(int64_t)size,
- .stride=1,
- .atomic=1,
+ .data = GC_MALLOC_ATOMIC(size),
+ .length = (int64_t)size,
+ .stride = 1,
+ .atomic = 1,
};
memcpy(bytes.data, buf, size);
free(buf);
return bytes;
}
-public void _deserialize(FILE *input, void *outval, List_t *pointers, const TypeInfo_t *type)
-{
+public
+void _deserialize(FILE *input, void *outval, List_t *pointers, const TypeInfo_t *type) {
if (type->metamethods.deserialize) {
type->metamethods.deserialize(input, outval, pointers, type);
return;
}
- if (fread(outval, (size_t)type->size, 1, input) != 1)
- fail("Not enough data in stream to deserialize");
+ if (fread(outval, (size_t)type->size, 1, input) != 1) fail("Not enough data in stream to deserialize");
}
-public void generic_deserialize(List_t bytes, void *outval, const TypeInfo_t *type)
-{
- if (bytes.stride != 1)
- List$compact(&bytes, 1);
+public
+void generic_deserialize(List_t bytes, void *outval, const TypeInfo_t *type) {
+ if (bytes.stride != 1) List$compact(&bytes, 1);
FILE *input = fmemopen(bytes.data, (size_t)bytes.length, "r");
List_t pointers = {};
@@ -94,23 +84,21 @@ public void generic_deserialize(List_t bytes, void *outval, const TypeInfo_t *ty
fclose(input);
}
-public int generic_print(const void *obj, bool colorize, const TypeInfo_t *type)
-{
+public
+int generic_print(const void *obj, bool colorize, const TypeInfo_t *type) {
Text_t text = generic_as_text(obj, colorize, type);
return Text$print(stdout, text) + fputc('\n', stdout);
}
-__attribute__((noreturn))
-public void cannot_serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type)
-{
+__attribute__((noreturn)) public
+void cannot_serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
(void)obj, (void)out, (void)pointers;
Text_t typestr = generic_as_text(NULL, false, type);
fail("Values of type ", typestr, " cannot be serialized or deserialized!");
}
-__attribute__((noreturn))
-public void cannot_deserialize(FILE *in, void *obj, List_t *pointers, const TypeInfo_t *type)
-{
+__attribute__((noreturn)) public
+void cannot_deserialize(FILE *in, void *obj, List_t *pointers, const TypeInfo_t *type) {
(void)obj, (void)in, (void)pointers;
Text_t typestr = generic_as_text(NULL, false, type);
fail("Values of type ", typestr, " cannot be serialized or deserialized!");
diff --git a/src/stdlib/metamethods.h b/src/stdlib/metamethods.h
index ca0a1e7e..eda2230e 100644
--- a/src/stdlib/metamethods.h
+++ b/src/stdlib/metamethods.h
@@ -16,7 +16,7 @@ List_t generic_serialize(const void *x, const TypeInfo_t *type);
void _deserialize(FILE *input, void *outval, List_t *pointers, const TypeInfo_t *type);
void generic_deserialize(List_t bytes, void *outval, const TypeInfo_t *type);
int generic_print(const void *obj, bool colorize, const TypeInfo_t *type);
-void cannot_serialize(const void*, FILE*, Table_t*, const TypeInfo_t *type);
-void cannot_deserialize(FILE*, void*, List_t*, const TypeInfo_t *type);
+void cannot_serialize(const void *, FILE *, Table_t *, const TypeInfo_t *type);
+void cannot_deserialize(FILE *, void *, List_t *, const TypeInfo_t *type);
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/nums.c b/src/stdlib/nums.c
index 83166659..05ed14a8 100644
--- a/src/stdlib/nums.c
+++ b/src/stdlib/nums.c
@@ -13,20 +13,21 @@
#include "text.h"
#include "types.h"
-public PUREFUNC Text_t Num$as_text(const void *f, bool colorize, const TypeInfo_t *info) {
+public
+PUREFUNC Text_t Num$as_text(const void *f, bool colorize, const TypeInfo_t *info) {
(void)info;
if (!f) return Text("Num");
char *str = GC_MALLOC_ATOMIC(24);
- int len = fpconv_dtoa(*(double*)f, str);
+ int len = fpconv_dtoa(*(double *)f, str);
static const Text_t color_prefix = Text("\x1b[35m"), color_suffix = Text("\x1b[m");
Text_t text = Text$from_strn(str, (size_t)len);
return colorize ? Texts(color_prefix, text, color_suffix) : text;
-}
+}
-public PUREFUNC int32_t Num$compare(const void *x, const void *y, const TypeInfo_t *info) {
+public
+PUREFUNC int32_t Num$compare(const void *x, const void *y, const TypeInfo_t *info) {
(void)info;
- int64_t rx = *(int64_t*)x,
- ry = *(int64_t*)y;
+ int64_t rx = *(int64_t *)x, ry = *(int64_t *)y;
if (rx == ry) return 0;
@@ -34,14 +35,16 @@ public PUREFUNC int32_t Num$compare(const void *x, const void *y, const TypeInfo
if (ry < 0) ry ^= INT64_MAX;
return (rx > ry) - (rx < ry);
-}
+}
-public PUREFUNC bool Num$equal(const void *x, const void *y, const TypeInfo_t *info) {
+public
+PUREFUNC bool Num$equal(const void *x, const void *y, const TypeInfo_t *info) {
(void)info;
- return *(double*)x == *(double*)y;
-}
+ return *(double *)x == *(double *)y;
+}
-public CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute) {
+public
+CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute) {
if (ratio < 0) ratio = 0;
else if (ratio > 1) ratio = 1;
@@ -56,17 +59,19 @@ public CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute
return (diff < epsilon);
}
-public Text_t Num$percent(double f, double precision) {
+public
+Text_t Num$percent(double f, double precision) {
double d = 100. * f;
d = Num$with_precision(d, precision);
return Texts(Num$as_text(&d, false, &Num$info), Text("%"));
}
-public CONSTFUNC double Num$with_precision(double num, double precision) {
+public
+CONSTFUNC double Num$with_precision(double num, double precision) {
if (precision == 0.0) return num;
// Precision will be, e.g. 0.01 or 100.
if (precision < 1.) {
- double inv = round(1./precision); // Necessary to make the math work
+ double inv = round(1. / precision); // Necessary to make the math work
double k = num * inv;
return round(k) / inv;
} else {
@@ -75,37 +80,34 @@ public CONSTFUNC double Num$with_precision(double num, double precision) {
}
}
-public CONSTFUNC double Num$mod(double num, double modulus) {
- // Euclidean division, see: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
+public
+CONSTFUNC double Num$mod(double num, double modulus) {
+ // Euclidean division, see:
+ // https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
double r = remainder(num, modulus);
- r -= (r < 0) * (2*(modulus < 0) - 1) * modulus;
+ r -= (r < 0) * (2 * (modulus < 0) - 1) * modulus;
return r;
}
-public CONSTFUNC double Num$mod1(double num, double modulus) {
- return 1.0 + Num$mod(num-1, modulus);
-}
+public
+CONSTFUNC double Num$mod1(double num, double modulus) { return 1.0 + Num$mod(num - 1, modulus); }
-public CONSTFUNC double Num$mix(double amount, double x, double y) {
- return (1.0-amount)*x + amount*y;
-}
+public
+CONSTFUNC double Num$mix(double amount, double x, double y) { return (1.0 - amount) * x + amount * y; }
-public CONSTFUNC bool Num$is_between(const double x, const double low, const double high) {
- return low <= x && x <= high;
-}
-public CONSTFUNC double Num$clamped(double x, double low, double high) {
- return (x <= low) ? low : (x >= high ? high : x);
-}
+public
+CONSTFUNC bool Num$is_between(const double x, const double low, const double high) { return low <= x && x <= high; }
+public
+CONSTFUNC double Num$clamped(double x, double low, double high) { return (x <= low) ? low : (x >= high ? high : x); }
-public OptionalNum_t Num$parse(Text_t text, Text_t *remainder) {
+public
+OptionalNum_t Num$parse(Text_t text, Text_t *remainder) {
const char *str = Text$as_c_string(text);
char *end = NULL;
double d = strtod(str, &end);
if (end > str) {
- if (remainder)
- *remainder = Text$from_str(end);
- else if (*end != '\0')
- return nan("none");
+ if (remainder) *remainder = Text$from_str(end);
+ else if (*end != '\0') return nan("none");
return d;
} else {
if (remainder) *remainder = text;
@@ -113,45 +115,54 @@ public OptionalNum_t Num$parse(Text_t text, Text_t *remainder) {
}
}
-public CONSTFUNC bool Num$is_none(const void *n, const TypeInfo_t *info)
-{
+public
+CONSTFUNC bool Num$is_none(const void *n, const TypeInfo_t *info) {
(void)info;
- return isnan(*(Num_t*)n);
-}
-
-public CONSTFUNC bool Num$isinf(double n) { return (fpclassify(n) == FP_INFINITE); }
-public CONSTFUNC bool Num$finite(double n) { return (fpclassify(n) != FP_INFINITE); }
-public CONSTFUNC bool Num$isnan(double n) { return (fpclassify(n) == FP_NAN); }
-
-public const TypeInfo_t Num$info = {
- .size=sizeof(double),
- .align=__alignof__(double),
- .metamethods={
- .compare=Num$compare,
- .equal=Num$equal,
- .as_text=Num$as_text,
- .is_none=Num$is_none,
- },
+ return isnan(*(Num_t *)n);
+}
+
+public
+CONSTFUNC bool Num$isinf(double n) { return (fpclassify(n) == FP_INFINITE); }
+public
+CONSTFUNC bool Num$finite(double n) { return (fpclassify(n) != FP_INFINITE); }
+public
+CONSTFUNC bool Num$isnan(double n) { return (fpclassify(n) == FP_NAN); }
+
+public
+const TypeInfo_t Num$info = {
+ .size = sizeof(double),
+ .align = __alignof__(double),
+ .metamethods =
+ {
+ .compare = Num$compare,
+ .equal = Num$equal,
+ .as_text = Num$as_text,
+ .is_none = Num$is_none,
+ },
};
-public PUREFUNC Text_t Num32$as_text(const void *f, bool colorize, const TypeInfo_t *info) {
+public
+PUREFUNC Text_t Num32$as_text(const void *f, bool colorize, const TypeInfo_t *info) {
(void)info;
if (!f) return Text("Num32");
- double d = (double)(*(float*)f);
+ double d = (double)(*(float *)f);
return Num$as_text(&d, colorize, &Num$info);
}
-public PUREFUNC int32_t Num32$compare(const void *x, const void *y, const TypeInfo_t *info) {
+public
+PUREFUNC int32_t Num32$compare(const void *x, const void *y, const TypeInfo_t *info) {
(void)info;
- return (*(float*)x > *(float*)y) - (*(float*)x < *(float*)y);
-}
+ return (*(float *)x > *(float *)y) - (*(float *)x < *(float *)y);
+}
-public PUREFUNC bool Num32$equal(const void *x, const void *y, const TypeInfo_t *info) {
+public
+PUREFUNC bool Num32$equal(const void *x, const void *y, const TypeInfo_t *info) {
(void)info;
- return *(float*)x == *(float*)y;
+ return *(float *)x == *(float *)y;
}
-public CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute) {
+public
+CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute) {
if (ratio < 0) ratio = 0;
else if (ratio > 1) ratio = 1;
@@ -166,17 +177,19 @@ public CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute)
return (diff < epsilon);
}
-public Text_t Num32$percent(float f, float precision) {
+public
+Text_t Num32$percent(float f, float precision) {
double d = 100. * (double)f;
d = Num$with_precision(d, (double)precision);
return Texts(Num$as_text(&d, false, &Num$info), Text("%"));
}
-public CONSTFUNC float Num32$with_precision(float num, float precision) {
+public
+CONSTFUNC float Num32$with_precision(float num, float precision) {
if (precision == 0.0f) return num;
// Precision will be, e.g. 0.01 or 100.
if (precision < 1.f) {
- float inv = roundf(1.f/precision); // Necessary to make the math work
+ float inv = roundf(1.f / precision); // Necessary to make the math work
float k = num * inv;
return roundf(k) / inv;
} else {
@@ -185,37 +198,35 @@ public CONSTFUNC float Num32$with_precision(float num, float precision) {
}
}
-public CONSTFUNC float Num32$mod(float num, float modulus) {
- // Euclidean division, see: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
+public
+CONSTFUNC float Num32$mod(float num, float modulus) {
+ // Euclidean division, see:
+ // https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
float r = remainderf(num, modulus);
- r -= (r < 0) * (2*(modulus < 0) - 1) * modulus;
+ r -= (r < 0) * (2 * (modulus < 0) - 1) * modulus;
return r;
}
-public CONSTFUNC float Num32$mod1(float num, float modulus) {
- return 1.0f + Num32$mod(num-1, modulus);
-}
+public
+CONSTFUNC float Num32$mod1(float num, float modulus) { return 1.0f + Num32$mod(num - 1, modulus); }
-public CONSTFUNC float Num32$mix(float amount, float x, float y) {
- return (1.0f-amount)*x + amount*y;
-}
+public
+CONSTFUNC float Num32$mix(float amount, float x, float y) { return (1.0f - amount) * x + amount * y; }
-public CONSTFUNC bool Num32$is_between(const float x, const float low, const float high) {
- return low <= x && x <= high;
-}
+public
+CONSTFUNC bool Num32$is_between(const float x, const float low, const float high) { return low <= x && x <= high; }
-public CONSTFUNC float Num32$clamped(float x, float low, float high) {
- return (x <= low) ? low : (x >= high ? high : x);
-}
+public
+CONSTFUNC float Num32$clamped(float x, float low, float high) { return (x <= low) ? low : (x >= high ? high : x); }
-public OptionalNum32_t Num32$parse(Text_t text, Text_t *remainder) {
+public
+OptionalNum32_t Num32$parse(Text_t text, Text_t *remainder) {
const char *str = Text$as_c_string(text);
char *end = NULL;
double d = strtod(str, &end);
if (end > str && end[0] == '\0') {
if (remainder) *remainder = Text$from_str(end);
- else if (*end != '\0')
- return nan("none");
+ else if (*end != '\0') return nan("none");
return d;
} else {
if (remainder) *remainder = text;
@@ -223,25 +234,30 @@ public OptionalNum32_t Num32$parse(Text_t text, Text_t *remainder) {
}
}
-public CONSTFUNC bool Num32$is_none(const void *n, const TypeInfo_t *info)
-{
+public
+CONSTFUNC bool Num32$is_none(const void *n, const TypeInfo_t *info) {
(void)info;
- return isnan(*(Num32_t*)n);
-}
-
-public CONSTFUNC bool Num32$isinf(float n) { return (fpclassify(n) == FP_INFINITE); }
-public CONSTFUNC bool Num32$finite(float n) { return (fpclassify(n) != FP_INFINITE); }
-public CONSTFUNC bool Num32$isnan(float n) { return (fpclassify(n) == FP_NAN); }
-
-public const TypeInfo_t Num32$info = {
- .size=sizeof(float),
- .align=__alignof__(float),
- .metamethods={
- .compare=Num32$compare,
- .equal=Num32$equal,
- .as_text=Num32$as_text,
- .is_none=Num32$is_none,
- },
+ return isnan(*(Num32_t *)n);
+}
+
+public
+CONSTFUNC bool Num32$isinf(float n) { return (fpclassify(n) == FP_INFINITE); }
+public
+CONSTFUNC bool Num32$finite(float n) { return (fpclassify(n) != FP_INFINITE); }
+public
+CONSTFUNC bool Num32$isnan(float n) { return (fpclassify(n) == FP_NAN); }
+
+public
+const TypeInfo_t Num32$info = {
+ .size = sizeof(float),
+ .align = __alignof__(float),
+ .metamethods =
+ {
+ .compare = Num32$compare,
+ .equal = Num32$equal,
+ .as_text = Num32$as_text,
+ .is_none = Num32$is_none,
+ },
};
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/optionals.c b/src/stdlib/optionals.c
index 36683241..a6f943ae 100644
--- a/src/stdlib/optionals.c
+++ b/src/stdlib/optionals.c
@@ -9,22 +9,19 @@
#include "text.h"
#include "util.h"
-public PUREFUNC bool is_none(const void *obj, const TypeInfo_t *non_optional_type)
-{
- if (non_optional_type->metamethods.is_none)
- return non_optional_type->metamethods.is_none(obj, non_optional_type);
+public
+PUREFUNC bool is_none(const void *obj, const TypeInfo_t *non_optional_type) {
+ if (non_optional_type->metamethods.is_none) return non_optional_type->metamethods.is_none(obj, non_optional_type);
const void *dest = (obj + non_optional_type->size);
- return *(bool*)dest;
+ return *(bool *)dest;
}
-PUREFUNC public uint64_t Optional$hash(const void *obj, const TypeInfo_t *type)
-{
+PUREFUNC public uint64_t Optional$hash(const void *obj, const TypeInfo_t *type) {
return is_none(obj, type->OptionalInfo.type) ? 0 : generic_hash(obj, type->OptionalInfo.type);
}
-PUREFUNC public int32_t Optional$compare(const void *x, const void *y, const TypeInfo_t *type)
-{
+PUREFUNC public int32_t Optional$compare(const void *x, const void *y, const TypeInfo_t *type) {
if (x == y) return 0;
bool x_is_null = is_none(x, type->OptionalInfo.type);
bool y_is_null = is_none(y, type->OptionalInfo.type);
@@ -33,8 +30,7 @@ PUREFUNC public int32_t Optional$compare(const void *x, const void *y, const Typ
else return generic_compare(x, y, type->OptionalInfo.type);
}
-PUREFUNC public bool Optional$equal(const void *x, const void *y, const TypeInfo_t *type)
-{
+PUREFUNC public bool Optional$equal(const void *x, const void *y, const TypeInfo_t *type) {
if (x == y) return true;
bool x_is_null = is_none(x, type->OptionalInfo.type);
@@ -44,46 +40,37 @@ PUREFUNC public bool Optional$equal(const void *x, const void *y, const TypeInfo
else return generic_equal(x, y, type->OptionalInfo.type);
}
-public Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo_t *type)
-{
- if (!obj)
- return Text$concat(generic_as_text(obj, colorize, type->OptionalInfo.type), Text("?"));
+public
+Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo_t *type) {
+ if (!obj) return Text$concat(generic_as_text(obj, colorize, type->OptionalInfo.type), Text("?"));
- if (is_none(obj, type->OptionalInfo.type))
- return colorize ? Text("\x1b[31mnone\x1b[m") : Text("none");
+ if (is_none(obj, type->OptionalInfo.type)) return colorize ? Text("\x1b[31mnone\x1b[m") : Text("none");
return generic_as_text(obj, colorize, type->OptionalInfo.type);
}
-public void Optional$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type)
-{
+public
+void Optional$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
bool has_value = !is_none(obj, type->OptionalInfo.type);
assert(fputc((int)has_value, out) != EOF);
- if (has_value)
- _serialize(obj, out, pointers, type->OptionalInfo.type);
+ if (has_value) _serialize(obj, out, pointers, type->OptionalInfo.type);
}
-public void Optional$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type)
-{
+public
+void Optional$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type) {
bool has_value = (bool)fgetc(in);
const TypeInfo_t *nonnull = type->OptionalInfo.type;
if (has_value) {
memset(outval, 0, (size_t)type->size);
_deserialize(in, outval, pointers, nonnull);
} else {
- if (nonnull->tag == TextInfo)
- *(Text_t*)outval = NONE_TEXT;
- else if (nonnull->tag == ListInfo)
- *(List_t*)outval = (List_t){.length=-1};
- else if (nonnull->tag == TableInfo)
- *(Table_t*)outval = (Table_t){.entries={.length=-1}};
- else if (nonnull == &Num$info)
- *(double*)outval = (double)NAN;
- else if (nonnull == &Num32$info)
- *(float*)outval = (float)NAN;
+ if (nonnull->tag == TextInfo) *(Text_t *)outval = NONE_TEXT;
+ else if (nonnull->tag == ListInfo) *(List_t *)outval = (List_t){.length = -1};
+ else if (nonnull->tag == TableInfo) *(Table_t *)outval = (Table_t){.entries = {.length = -1}};
+ else if (nonnull == &Num$info) *(double *)outval = (double)NAN;
+ else if (nonnull == &Num32$info) *(float *)outval = (float)NAN;
else if (nonnull->tag == StructInfo || (nonnull->tag == OpaqueInfo && type->size > nonnull->size))
memset(outval + type->size, -1, (size_t)(type->size - nonnull->size));
- else
- memset(outval, 0, (size_t)type->size);
+ else memset(outval, 0, (size_t)type->size);
}
}
diff --git a/src/stdlib/optionals.h b/src/stdlib/optionals.h
index bd1f63b3..77ce6db4 100644
--- a/src/stdlib/optionals.h
+++ b/src/stdlib/optionals.h
@@ -9,13 +9,13 @@
#include "types.h"
#include "util.h"
-#define NONE_LIST ((List_t){.length=-1})
+#define NONE_LIST ((List_t){.length = -1})
#define NONE_BOOL ((OptionalBool_t)2)
-#define NONE_INT ((OptionalInt_t){.small=0})
-#define NONE_TABLE ((OptionalTable_t){.entries.length=-1})
-#define NONE_CLOSURE ((OptionalClosure_t){.fn=NULL})
-#define NONE_TEXT ((OptionalText_t){.length=-1})
-#define NONE_PATH ((Path_t){.type=PATH_NONE})
+#define NONE_INT ((OptionalInt_t){.small = 0})
+#define NONE_TABLE ((OptionalTable_t){.entries.length = -1})
+#define NONE_CLOSURE ((OptionalClosure_t){.fn = NULL})
+#define NONE_TEXT ((OptionalText_t){.length = -1})
+#define NONE_PATH ((Path_t){.type = PATH_NONE})
PUREFUNC bool is_none(const void *obj, const TypeInfo_t *non_optional_type);
PUREFUNC uint64_t Optional$hash(const void *obj, const TypeInfo_t *type);
@@ -25,17 +25,21 @@ Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo_t *type);
void Optional$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type);
void Optional$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type);
-#define Optional$metamethods { \
- .hash=Optional$hash, \
- .compare=Optional$compare, \
- .equal=Optional$equal, \
- .as_text=Optional$as_text, \
- .serialize=Optional$serialize, \
- .deserialize=Optional$deserialize, \
-}
-
-#define Optional$info(_size, _align, t) &((TypeInfo_t){.size=_size, .align=_align, \
- .tag=OptionalInfo, .OptionalInfo.type=t, \
- .metamethods=Optional$metamethods})
+#define Optional$metamethods \
+ { \
+ .hash = Optional$hash, \
+ .compare = Optional$compare, \
+ .equal = Optional$equal, \
+ .as_text = Optional$as_text, \
+ .serialize = Optional$serialize, \
+ .deserialize = Optional$deserialize, \
+ }
+
+#define Optional$info(_size, _align, t) \
+ &((TypeInfo_t){.size = _size, \
+ .align = _align, \
+ .tag = OptionalInfo, \
+ .OptionalInfo.type = t, \
+ .metamethods = Optional$metamethods})
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/paths.c b/src/stdlib/paths.c
index a14b32c2..efe9f7ad 100644
--- a/src/stdlib/paths.c
+++ b/src/stdlib/paths.c
@@ -17,32 +17,30 @@
#include <unistd.h>
#include <unistr.h>
-#include "lists.h"
#include "enums.h"
#include "integers.h"
+#include "lists.h"
#include "optionals.h"
#include "paths.h"
+#include "print.h"
#include "structs.h"
#include "text.h"
#include "types.h"
#include "util.h"
-#include "print.h"
// Use inline version of the siphash code for performance:
#include "siphash-internals.h"
-static const Path_t HOME_PATH = {.type.$tag=PATH_HOME},
- ROOT_PATH = {.type.$tag=PATH_ABSOLUTE},
- CURDIR_PATH = {.type.$tag=PATH_RELATIVE};
+static const Path_t HOME_PATH = {.type.$tag = PATH_HOME}, ROOT_PATH = {.type.$tag = PATH_ABSOLUTE},
+ CURDIR_PATH = {.type.$tag = PATH_RELATIVE};
-static void clean_components(List_t *components)
-{
- for (int64_t i = 0; i < components->length; ) {
- Text_t *component = (Text_t*)(components->data + i*components->stride);
+static void clean_components(List_t *components) {
+ for (int64_t i = 0; i < components->length;) {
+ Text_t *component = (Text_t *)(components->data + i * components->stride);
if (component->length == 0 || Text$equal_values(*component, Text("."))) {
- List$remove_at(components, I(i+1), I(1), sizeof(Text_t));
+ List$remove_at(components, I(i + 1), I(1), sizeof(Text_t));
} else if (i > 0 && Text$equal_values(*component, Text(".."))) {
- Text_t *prev = (Text_t*)(components->data + (i-1)*components->stride);
+ Text_t *prev = (Text_t *)(components->data + (i - 1) * components->stride);
if (!Text$equal_values(*prev, Text(".."))) {
List$remove_at(components, I(i), I(2), sizeof(Text_t));
i -= 1;
@@ -55,16 +53,15 @@ static void clean_components(List_t *components)
}
}
-public Path_t Path$from_str(const char *str)
-{
+public
+Path_t Path$from_str(const char *str) {
if (!str || str[0] == '\0' || streq(str, "/")) return ROOT_PATH;
else if (streq(str, "~")) return HOME_PATH;
else if (streq(str, ".")) return CURDIR_PATH;
- if (strchr(str, ';') != NULL)
- fail("Path has illegal character (semicolon): ", str);
+ if (strchr(str, ';') != NULL) fail("Path has illegal character (semicolon): ", str);
- Path_t result = {.components={}};
+ Path_t result = {.components = {}};
if (str[0] == '/') {
result.type.$tag = PATH_ABSOLUTE;
str += 1;
@@ -83,12 +80,13 @@ public Path_t Path$from_str(const char *str)
if (component_len > 0) {
if (component_len == 1 && str[0] == '.') {
// ignore /./
- } else if (component_len == 2 && strncmp(str, "..", 2) == 0
- && result.components.length > 1
- && !Text$equal_values(Text(".."), *(Text_t*)(result.components.data + result.components.stride*(result.components.length-1)))) {
+ } else if (component_len == 2 && strncmp(str, "..", 2) == 0 && result.components.length > 1
+ && !Text$equal_values(
+ Text(".."), *(Text_t *)(result.components.data
+ + result.components.stride * (result.components.length - 1)))) {
// Pop off /foo/baz/.. -> /foo
List$remove_at(&result.components, I(result.components.length), I(1), sizeof(Text_t));
- } else {
+ } else {
Text_t component = Text$from_strn(str, component_len);
List$insert_value(&result.components, component, I(0), sizeof(Text_t));
}
@@ -99,25 +97,23 @@ public Path_t Path$from_str(const char *str)
return result;
}
-public Path_t Path$from_text(Text_t text)
-{
- return Path$from_str(Text$as_c_string(text));
-}
+public
+Path_t Path$from_text(Text_t text) { return Path$from_str(Text$as_c_string(text)); }
-public Path_t Path$expand_home(Path_t path)
-{
+public
+Path_t Path$expand_home(Path_t path) {
if (path.type.$tag == PATH_HOME) {
Path_t pwd = Path$from_str(getenv("HOME"));
List_t components = List$concat(pwd.components, path.components, sizeof(Text_t));
assert(components.length == path.components.length + pwd.components.length);
clean_components(&components);
- path = (Path_t){.type.$tag=PATH_ABSOLUTE, .components=components};
+ path = (Path_t){.type.$tag = PATH_ABSOLUTE, .components = components};
}
return path;
}
-public Path_t Path$_concat(int n, Path_t items[n])
-{
+public
+Path_t Path$_concat(int n, Path_t items[n]) {
assert(n > 0);
Path_t result = items[0];
LIST_INCREF(result.components);
@@ -130,10 +126,11 @@ public Path_t Path$_concat(int n, Path_t items[n])
return result;
}
-public Path_t Path$resolved(Path_t path, Path_t relative_to)
-{
- if (path.type.$tag == PATH_RELATIVE && !(relative_to.type.$tag == PATH_RELATIVE && relative_to.components.length == 0)) {
- Path_t result = {.type.$tag=relative_to.type.$tag};
+public
+Path_t Path$resolved(Path_t path, Path_t relative_to) {
+ if (path.type.$tag == PATH_RELATIVE
+ && !(relative_to.type.$tag == PATH_RELATIVE && relative_to.components.length == 0)) {
+ Path_t result = {.type.$tag = relative_to.type.$tag};
result.components = relative_to.components;
LIST_INCREF(result.components);
List$insert_all(&result.components, path.components, I(0), sizeof(Text_t));
@@ -143,87 +140,86 @@ public Path_t Path$resolved(Path_t path, Path_t relative_to)
return path;
}
-public Path_t Path$relative_to(Path_t path, Path_t relative_to)
-{
+public
+Path_t Path$relative_to(Path_t path, Path_t relative_to) {
if (path.type.$tag != relative_to.type.$tag)
- fail("Cannot create a path relative to a different path with a mismatching type: (", path, ") relative to (", relative_to, ")");
+ fail("Cannot create a path relative to a different path with a mismatching type: (", path, ") relative to (",
+ relative_to, ")");
- Path_t result = {.type.$tag=PATH_RELATIVE};
+ Path_t result = {.type.$tag = PATH_RELATIVE};
int64_t shared = 0;
for (; shared < path.components.length && shared < relative_to.components.length; shared++) {
- Text_t *p = (Text_t*)(path.components.data + shared*path.components.stride);
- Text_t *r = (Text_t*)(relative_to.components.data + shared*relative_to.components.stride);
- if (!Text$equal_values(*p, *r))
- break;
+ Text_t *p = (Text_t *)(path.components.data + shared * path.components.stride);
+ Text_t *r = (Text_t *)(relative_to.components.data + shared * relative_to.components.stride);
+ if (!Text$equal_values(*p, *r)) break;
}
for (int64_t i = shared; i < relative_to.components.length; i++)
List$insert_value(&result.components, Text(".."), I(1), sizeof(Text_t));
for (int64_t i = shared; i < path.components.length; i++) {
- Text_t *p = (Text_t*)(path.components.data + i*path.components.stride);
+ Text_t *p = (Text_t *)(path.components.data + i * path.components.stride);
List$insert(&result.components, p, I(0), sizeof(Text_t));
}
- //clean_components(&result.components);
+ // clean_components(&result.components);
return result;
}
-public bool Path$exists(Path_t path)
-{
+public
+bool Path$exists(Path_t path) {
path = Path$expand_home(path);
struct stat sb;
return (stat(Path$as_c_string(path), &sb) == 0);
}
-static INLINE int path_stat(Path_t path, bool follow_symlinks, struct stat *sb)
-{
+static INLINE int path_stat(Path_t path, bool follow_symlinks, struct stat *sb) {
path = Path$expand_home(path);
const char *path_str = Path$as_c_string(path);
return follow_symlinks ? stat(path_str, sb) : lstat(path_str, sb);
}
-public bool Path$is_file(Path_t path, bool follow_symlinks)
-{
+public
+bool Path$is_file(Path_t path, bool follow_symlinks) {
struct stat sb;
int status = path_stat(path, follow_symlinks, &sb);
if (status != 0) return false;
return (sb.st_mode & S_IFMT) == S_IFREG;
}
-public bool Path$is_directory(Path_t path, bool follow_symlinks)
-{
+public
+bool Path$is_directory(Path_t path, bool follow_symlinks) {
struct stat sb;
int status = path_stat(path, follow_symlinks, &sb);
if (status != 0) return false;
return (sb.st_mode & S_IFMT) == S_IFDIR;
}
-public bool Path$is_pipe(Path_t path, bool follow_symlinks)
-{
+public
+bool Path$is_pipe(Path_t path, bool follow_symlinks) {
struct stat sb;
int status = path_stat(path, follow_symlinks, &sb);
if (status != 0) return false;
return (sb.st_mode & S_IFMT) == S_IFIFO;
}
-public bool Path$is_socket(Path_t path, bool follow_symlinks)
-{
+public
+bool Path$is_socket(Path_t path, bool follow_symlinks) {
struct stat sb;
int status = path_stat(path, follow_symlinks, &sb);
if (status != 0) return false;
return (sb.st_mode & S_IFMT) == S_IFSOCK;
}
-public bool Path$is_symlink(Path_t path)
-{
+public
+bool Path$is_symlink(Path_t path) {
struct stat sb;
int status = path_stat(path, false, &sb);
if (status != 0) return false;
return (sb.st_mode & S_IFMT) == S_IFLNK;
}
-public bool Path$can_read(Path_t path)
-{
+public
+bool Path$can_read(Path_t path) {
path = Path$expand_home(path);
const char *path_str = Path$as_c_string(path);
#ifdef _GNU_SOURCE
@@ -233,8 +229,8 @@ public bool Path$can_read(Path_t path)
#endif
}
-public bool Path$can_write(Path_t path)
-{
+public
+bool Path$can_write(Path_t path) {
path = Path$expand_home(path);
const char *path_str = Path$as_c_string(path);
#ifdef _GNU_SOURCE
@@ -244,8 +240,8 @@ public bool Path$can_write(Path_t path)
#endif
}
-public bool Path$can_execute(Path_t path)
-{
+public
+bool Path$can_execute(Path_t path) {
path = Path$expand_home(path);
const char *path_str = Path$as_c_string(path);
#ifdef _GNU_SOURCE
@@ -255,93 +251,86 @@ public bool Path$can_execute(Path_t path)
#endif
}
-public OptionalInt64_t Path$modified(Path_t path, bool follow_symlinks)
-{
+public
+OptionalInt64_t Path$modified(Path_t path, bool follow_symlinks) {
struct stat sb;
int status = path_stat(path, follow_symlinks, &sb);
if (status != 0) return NONE_INT64;
- return (OptionalInt64_t){.value=(int64_t)sb.st_mtime};
+ return (OptionalInt64_t){.value = (int64_t)sb.st_mtime};
}
-public OptionalInt64_t Path$accessed(Path_t path, bool follow_symlinks)
-{
+public
+OptionalInt64_t Path$accessed(Path_t path, bool follow_symlinks) {
struct stat sb;
int status = path_stat(path, follow_symlinks, &sb);
if (status != 0) return NONE_INT64;
- return (OptionalInt64_t){.value=(int64_t)sb.st_atime};
+ return (OptionalInt64_t){.value = (int64_t)sb.st_atime};
}
-public OptionalInt64_t Path$changed(Path_t path, bool follow_symlinks)
-{
+public
+OptionalInt64_t Path$changed(Path_t path, bool follow_symlinks) {
struct stat sb;
int status = path_stat(path, follow_symlinks, &sb);
if (status != 0) return NONE_INT64;
- return (OptionalInt64_t){.value=(int64_t)sb.st_ctime};
+ return (OptionalInt64_t){.value = (int64_t)sb.st_ctime};
}
-static void _write(Path_t path, List_t bytes, int mode, int permissions)
-{
+static void _write(Path_t path, List_t bytes, int mode, int permissions) {
path = Path$expand_home(path);
const char *path_str = Path$as_c_string(path);
int fd = open(path_str, mode, permissions);
- if (fd == -1)
- fail("Could not write to file: ", path_str, "\n", strerror(errno));
+ if (fd == -1) fail("Could not write to file: ", path_str, "\n", strerror(errno));
- if (bytes.stride != 1)
- List$compact(&bytes, 1);
+ if (bytes.stride != 1) List$compact(&bytes, 1);
ssize_t written = write(fd, bytes.data, (size_t)bytes.length);
- if (written != (ssize_t)bytes.length)
- fail("Could not write to file: ", path_str, "\n", strerror(errno));
+ if (written != (ssize_t)bytes.length) fail("Could not write to file: ", path_str, "\n", strerror(errno));
close(fd);
}
-public void Path$write(Path_t path, Text_t text, int permissions)
-{
+public
+void Path$write(Path_t path, Text_t text, int permissions) {
List_t bytes = Text$utf8_bytes(text);
_write(path, bytes, O_WRONLY | O_CREAT | O_TRUNC, permissions);
}
-public void Path$write_bytes(Path_t path, List_t bytes, int permissions)
-{
+public
+void Path$write_bytes(Path_t path, List_t bytes, int permissions) {
_write(path, bytes, O_WRONLY | O_CREAT | O_TRUNC, permissions);
}
-public void Path$append(Path_t path, Text_t text, int permissions)
-{
+public
+void Path$append(Path_t path, Text_t text, int permissions) {
List_t bytes = Text$utf8_bytes(text);
_write(path, bytes, O_WRONLY | O_APPEND | O_CREAT, permissions);
}
-public void Path$append_bytes(Path_t path, List_t bytes, int permissions)
-{
+public
+void Path$append_bytes(Path_t path, List_t bytes, int permissions) {
_write(path, bytes, O_WRONLY | O_APPEND | O_CREAT, permissions);
}
-public OptionalList_t Path$read_bytes(Path_t path, OptionalInt_t count)
-{
+public
+OptionalList_t Path$read_bytes(Path_t path, OptionalInt_t count) {
path = Path$expand_home(path);
int fd = open(Path$as_c_string(path), O_RDONLY);
- if (fd == -1)
- return NONE_LIST;
+ if (fd == -1) return NONE_LIST;
struct stat sb;
- if (fstat(fd, &sb) != 0)
- return NONE_LIST;
+ if (fstat(fd, &sb) != 0) return NONE_LIST;
int64_t const target_count = count.small ? Int64$from_int(count, false) : INT64_MAX;
- if (target_count < 0)
- fail("Cannot read a negative number of bytes!");
+ if (target_count < 0) fail("Cannot read a negative number of bytes!");
if ((sb.st_mode & S_IFMT) == S_IFREG) { // Use memory mapping if it's a real file:
const char *mem = mmap(NULL, (size_t)sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- char *content = GC_MALLOC_ATOMIC((size_t)sb.st_size+1);
+ char *content = GC_MALLOC_ATOMIC((size_t)sb.st_size + 1);
memcpy(content, mem, (size_t)sb.st_size);
content[sb.st_size] = '\0';
close(fd);
if (count.small && (int64_t)sb.st_size < target_count)
fail("Could not read ", target_count, " bytes from ", path, " (only got ", (uint64_t)sb.st_size, ")");
int64_t len = count.small ? target_count : (int64_t)sb.st_size;
- return (List_t){.data=content, .atomic=1, .stride=1, .length=len};
+ return (List_t){.data = content, .atomic = 1, .stride = 1, .length = len};
} else {
size_t capacity = 256, len = 0;
char *content = GC_MALLOC_ATOMIC(capacity);
@@ -354,8 +343,7 @@ public OptionalList_t Path$read_bytes(Path_t path, OptionalInt_t count)
close(fd);
return NONE_LIST;
} else if (just_read == 0) {
- if (errno == EAGAIN || errno == EINTR)
- continue;
+ if (errno == EAGAIN || errno == EINTR) continue;
break;
}
count_remaining -= (int64_t)just_read;
@@ -370,19 +358,19 @@ public OptionalList_t Path$read_bytes(Path_t path, OptionalInt_t count)
close(fd);
if (count.small != 0 && (int64_t)len < target_count)
fail("Could not read ", target_count, " bytes from ", path, " (only got ", (uint64_t)len, ")");
- return (List_t){.data=content, .atomic=1, .stride=1, .length=(int64_t)len};
+ return (List_t){.data = content, .atomic = 1, .stride = 1, .length = (int64_t)len};
}
}
-public OptionalText_t Path$read(Path_t path)
-{
+public
+OptionalText_t Path$read(Path_t path) {
List_t bytes = Path$read_bytes(path, NONE_INT);
if (bytes.length < 0) return NONE_TEXT;
return Text$from_bytes(bytes);
}
-public OptionalText_t Path$owner(Path_t path, bool follow_symlinks)
-{
+public
+OptionalText_t Path$owner(Path_t path, bool follow_symlinks) {
struct stat sb;
int status = path_stat(path, follow_symlinks, &sb);
if (status != 0) return NONE_TEXT;
@@ -390,8 +378,8 @@ public OptionalText_t Path$owner(Path_t path, bool follow_symlinks)
return pw ? Text$from_str(pw->pw_name) : NONE_TEXT;
}
-public OptionalText_t Path$group(Path_t path, bool follow_symlinks)
-{
+public
+OptionalText_t Path$group(Path_t path, bool follow_symlinks) {
struct stat sb;
int status = path_stat(path, follow_symlinks, &sb);
if (status != 0) return NONE_TEXT;
@@ -399,8 +387,8 @@ public OptionalText_t Path$group(Path_t path, bool follow_symlinks)
return gr ? Text$from_str(gr->gr_name) : NONE_TEXT;
}
-public void Path$set_owner(Path_t path, OptionalText_t owner, OptionalText_t group, bool follow_symlinks)
-{
+public
+void Path$set_owner(Path_t path, OptionalText_t owner, OptionalText_t group, bool follow_symlinks) {
uid_t owner_id = (uid_t)-1;
if (owner.length >= 0) {
struct passwd *pwd = getpwnam(Text$as_c_string(owner));
@@ -416,38 +404,34 @@ public void Path$set_owner(Path_t path, OptionalText_t owner, OptionalText_t gro
}
const char *path_str = Path$as_c_string(path);
int result = follow_symlinks ? chown(path_str, owner_id, group_id) : lchown(path_str, owner_id, group_id);
- if (result < 0)
- fail("Could not set owner!");
+ if (result < 0) fail("Could not set owner!");
}
-static int _remove_files(const char *path, const struct stat *sbuf, int type, struct FTW *ftwb)
-{
+static int _remove_files(const char *path, const struct stat *sbuf, int type, struct FTW *ftwb) {
(void)sbuf, (void)ftwb;
switch (type) {
- case FTW_F: case FTW_SL: case FTW_SLN:
+ case FTW_F:
+ case FTW_SL:
+ case FTW_SLN:
if (remove(path) < 0) {
fail("Could not remove file: ", path, " (", strerror(errno), ")");
return -1;
}
return 0;
case FTW_DP:
- if (rmdir(path) != 0)
- fail("Could not remove directory: ", path, " (", strerror(errno), ")");
+ if (rmdir(path) != 0) fail("Could not remove directory: ", path, " (", strerror(errno), ")");
return 0;
- default:
- fail("Could not remove path: ", path, " (not a file or directory)");
- return -1;
+ default: fail("Could not remove path: ", path, " (not a file or directory)"); return -1;
}
}
-public void Path$remove(Path_t path, bool ignore_missing)
-{
+public
+void Path$remove(Path_t path, bool ignore_missing) {
path = Path$expand_home(path);
const char *path_str = Path$as_c_string(path);
struct stat sb;
if (lstat(path_str, &sb) != 0) {
- if (!ignore_missing)
- fail("Could not remove file: ", path_str, " (", strerror(errno), ")");
+ if (!ignore_missing) fail("Could not remove file: ", path_str, " (", strerror(errno), ")");
return;
}
@@ -456,48 +440,40 @@ public void Path$remove(Path_t path, bool ignore_missing)
fail("Could not remove file: ", path_str, " (", strerror(errno), ")");
} else if ((sb.st_mode & S_IFMT) == S_IFDIR) {
const int num_open_fd = 10;
- if (nftw(path_str, _remove_files, num_open_fd, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) < 0)
+ if (nftw(path_str, _remove_files, num_open_fd, FTW_DEPTH | FTW_MOUNT | FTW_PHYS) < 0)
fail("Could not remove directory: %s (%s)", path_str, strerror(errno));
} else {
fail("Could not remove path: ", path_str, " (not a file or directory)");
}
}
-public void Path$create_directory(Path_t path, int permissions)
-{
+public
+void Path$create_directory(Path_t path, int permissions) {
path = Path$expand_home(path);
const char *c_path = Path$as_c_string(path);
int status = mkdir(c_path, (mode_t)permissions);
- if (status != 0 && errno != EEXIST)
- fail("Could not create directory: ", c_path, " (", strerror(errno), ")");
+ if (status != 0 && errno != EEXIST) fail("Could not create directory: ", c_path, " (", strerror(errno), ")");
}
-static List_t _filtered_children(Path_t path, bool include_hidden, mode_t filter)
-{
+static List_t _filtered_children(Path_t path, bool include_hidden, mode_t filter) {
path = Path$expand_home(path);
struct dirent *dir;
List_t children = {};
const char *path_str = Path$as_c_string(path);
size_t path_len = strlen(path_str);
DIR *d = opendir(path_str);
- if (!d)
- fail("Could not open directory: ", path, " (", strerror(errno), ")");
+ if (!d) fail("Could not open directory: ", path, " (", strerror(errno), ")");
- if (path_str[path_len-1] == '/')
- --path_len;
+ if (path_str[path_len - 1] == '/') --path_len;
while ((dir = readdir(d)) != NULL) {
- if (!include_hidden && dir->d_name[0] == '.')
- continue;
- if (streq(dir->d_name, ".") || streq(dir->d_name, ".."))
- continue;
+ if (!include_hidden && dir->d_name[0] == '.') continue;
+ if (streq(dir->d_name, ".") || streq(dir->d_name, "..")) continue;
const char *child_str = String(string_slice(path_str, path_len), "/", dir->d_name);
struct stat sb;
- if (stat(child_str, &sb) != 0)
- continue;
- if (!((sb.st_mode & S_IFMT) & filter))
- continue;
+ if (stat(child_str, &sb) != 0) continue;
+ if (!((sb.st_mode & S_IFMT) & filter)) continue;
Path_t child = Path$from_str(child_str);
List$insert(&children, &child, I(0), sizeof(Path_t));
@@ -506,23 +482,19 @@ static List_t _filtered_children(Path_t path, bool include_hidden, mode_t filter
return children;
}
-public List_t Path$children(Path_t path, bool include_hidden)
-{
- return _filtered_children(path, include_hidden, (mode_t)-1);
-}
+public
+List_t Path$children(Path_t path, bool include_hidden) { return _filtered_children(path, include_hidden, (mode_t)-1); }
-public List_t Path$files(Path_t path, bool include_hidden)
-{
- return _filtered_children(path, include_hidden, S_IFREG);
-}
+public
+List_t Path$files(Path_t path, bool include_hidden) { return _filtered_children(path, include_hidden, S_IFREG); }
-public List_t Path$subdirectories(Path_t path, bool include_hidden)
-{
+public
+List_t Path$subdirectories(Path_t path, bool include_hidden) {
return _filtered_children(path, include_hidden, S_IFDIR);
}
-public Path_t Path$unique_directory(Path_t path)
-{
+public
+Path_t Path$unique_directory(Path_t path) {
path = Path$expand_home(path);
const char *path_str = Path$as_c_string(path);
size_t len = strlen(path_str);
@@ -530,15 +502,14 @@ public Path_t Path$unique_directory(Path_t path)
char buf[PATH_MAX] = {};
memcpy(buf, path_str, len);
buf[len] = '\0';
- if (buf[len-1] == '/')
- buf[--len] = '\0';
+ if (buf[len - 1] == '/') buf[--len] = '\0';
char *created = mkdtemp(buf);
if (!created) fail("Failed to create temporary directory: ", path_str, " (", strerror(errno), ")");
return Path$from_str(created);
}
-public Path_t Path$write_unique_bytes(Path_t path, List_t bytes)
-{
+public
+Path_t Path$write_unique_bytes(Path_t path, List_t bytes) {
path = Path$expand_home(path);
const char *path_str = Path$as_c_string(path);
size_t len = strlen(path_str);
@@ -554,82 +525,73 @@ public Path_t Path$write_unique_bytes(Path_t path, List_t bytes)
++suffixlen;
int fd = mkstemps(buf, suffixlen);
- if (fd == -1)
- fail("Could not write to unique file: ", buf, "\n", strerror(errno));
+ if (fd == -1) fail("Could not write to unique file: ", buf, "\n", strerror(errno));
- if (bytes.stride != 1)
- List$compact(&bytes, 1);
+ if (bytes.stride != 1) List$compact(&bytes, 1);
ssize_t written = write(fd, bytes.data, (size_t)bytes.length);
- if (written != (ssize_t)bytes.length)
- fail("Could not write to file: ", buf, "\n", strerror(errno));
+ if (written != (ssize_t)bytes.length) fail("Could not write to file: ", buf, "\n", strerror(errno));
close(fd);
return Path$from_str(buf);
}
-public Path_t Path$write_unique(Path_t path, Text_t text)
-{
- return Path$write_unique_bytes(path, Text$utf8_bytes(text));
-}
+public
+Path_t Path$write_unique(Path_t path, Text_t text) { return Path$write_unique_bytes(path, Text$utf8_bytes(text)); }
-public Path_t Path$parent(Path_t path)
-{
+public
+Path_t Path$parent(Path_t path) {
if (path.type.$tag == PATH_ABSOLUTE && path.components.length == 0) {
return path;
- } else if (path.components.length > 0 && !Text$equal_values(*(Text_t*)(path.components.data + path.components.stride*(path.components.length-1)),
- Text(".."))) {
- return (Path_t){.type.$tag=path.type.$tag, .components=List$slice(path.components, I(1), I(-2))};
+ } else if (path.components.length > 0
+ && !Text$equal_values(
+ *(Text_t *)(path.components.data + path.components.stride * (path.components.length - 1)),
+ Text(".."))) {
+ return (Path_t){.type.$tag = path.type.$tag, .components = List$slice(path.components, I(1), I(-2))};
} else {
- Path_t result = {.type.$tag=path.type.$tag, .components=path.components};
+ Path_t result = {.type.$tag = path.type.$tag, .components = path.components};
LIST_INCREF(result.components);
List$insert_value(&result.components, Text(".."), I(0), sizeof(Text_t));
return result;
}
}
-public PUREFUNC Text_t Path$base_name(Path_t path)
-{
+public
+PUREFUNC Text_t Path$base_name(Path_t path) {
if (path.components.length >= 1)
- return *(Text_t*)(path.components.data + path.components.stride*(path.components.length-1));
- else if (path.type.$tag == PATH_HOME)
- return Text("~");
- else if (path.type.$tag == PATH_RELATIVE)
- return Text(".");
- else
- return EMPTY_TEXT;
+ return *(Text_t *)(path.components.data + path.components.stride * (path.components.length - 1));
+ else if (path.type.$tag == PATH_HOME) return Text("~");
+ else if (path.type.$tag == PATH_RELATIVE) return Text(".");
+ else return EMPTY_TEXT;
}
-public Text_t Path$extension(Path_t path, bool full)
-{
+public
+Text_t Path$extension(Path_t path, bool full) {
const char *base = Text$as_c_string(Path$base_name(path));
const char *dot = full ? strchr(base + 1, '.') : strrchr(base + 1, '.');
const char *extension = dot ? dot + 1 : "";
return Text$from_str(extension);
}
-public bool Path$has_extension(Path_t path, Text_t extension)
-{
- if (path.components.length < 2)
- return extension.length == 0;
+public
+bool Path$has_extension(Path_t path, Text_t extension) {
+ if (path.components.length < 2) return extension.length == 0;
- Text_t last = *(Text_t*)(path.components.data + path.components.stride*(path.components.length-1));
+ Text_t last = *(Text_t *)(path.components.data + path.components.stride * (path.components.length - 1));
if (extension.length == 0)
return !Text$has(Text$from(last, I(2)), Text(".")) || Text$equal_values(last, Text(".."));
- if (!Text$starts_with(extension, Text("."), NULL))
- extension = Texts(Text("."), extension);
+ if (!Text$starts_with(extension, Text("."), NULL)) extension = Texts(Text("."), extension);
return Text$ends_with(Text$from(last, I(2)), extension, NULL);
}
-public Path_t Path$child(Path_t path, Text_t name)
-{
- if (Text$has(name, Text("/")) || Text$has(name, Text(";")))
- fail("Path name has invalid characters: ", name);
+public
+Path_t Path$child(Path_t path, Text_t name) {
+ if (Text$has(name, Text("/")) || Text$has(name, Text(";"))) fail("Path name has invalid characters: ", name);
Path_t result = {
- .type.$tag=path.type.$tag,
- .components=path.components,
+ .type.$tag = path.type.$tag,
+ .components = path.components,
};
LIST_INCREF(result.components);
List$insert(&result.components, &name, I(0), sizeof(Text_t));
@@ -637,31 +599,27 @@ public Path_t Path$child(Path_t path, Text_t name)
return result;
}
-public Path_t Path$sibling(Path_t path, Text_t name)
-{
- return Path$child(Path$parent(path), name);
-}
+public
+Path_t Path$sibling(Path_t path, Text_t name) { return Path$child(Path$parent(path), name); }
-public Path_t Path$with_extension(Path_t path, Text_t extension, bool replace)
-{
- if (path.components.length == 0)
- fail("A path with no components can't have an extension!");
+public
+Path_t Path$with_extension(Path_t path, Text_t extension, bool replace) {
+ if (path.components.length == 0) fail("A path with no components can't have an extension!");
if (Text$has(extension, Text("/")) || Text$has(extension, Text(";")))
fail("Path extension has invalid characters: ", extension);
Path_t result = {
- .type.$tag=path.type.$tag,
- .components=path.components,
+ .type.$tag = path.type.$tag,
+ .components = path.components,
};
LIST_INCREF(result.components);
- Text_t last = *(Text_t*)(path.components.data + path.components.stride*(path.components.length-1));
+ Text_t last = *(Text_t *)(path.components.data + path.components.stride * (path.components.length - 1));
List$remove_at(&result.components, I(-1), I(1), sizeof(Text_t));
if (replace) {
const char *base = Text$as_c_string(last);
const char *dot = strchr(base + 1, '.');
- if (dot)
- last = Text$from_strn(base, (size_t)(dot - base));
+ if (dot) last = Text$from_strn(base, (size_t)(dot - base));
}
last = Text$concat(last, extension);
@@ -669,16 +627,14 @@ public Path_t Path$with_extension(Path_t path, Text_t extension, bool replace)
return result;
}
-static void _line_reader_cleanup(FILE **f)
-{
+static void _line_reader_cleanup(FILE **f) {
if (f && *f) {
fclose(*f);
*f = NULL;
}
}
-static Text_t _next_line(FILE **f)
-{
+static Text_t _next_line(FILE **f) {
if (!f || !*f) return NONE_TEXT;
char *line = NULL;
@@ -689,43 +645,41 @@ static Text_t _next_line(FILE **f)
return NONE_TEXT;
}
- while (len > 0 && (line[len-1] == '\r' || line[len-1] == '\n'))
+ while (len > 0 && (line[len - 1] == '\r' || line[len - 1] == '\n'))
--len;
- if (u8_check((uint8_t*)line, (size_t)len) != NULL)
- fail("Invalid UTF8!");
+ if (u8_check((uint8_t *)line, (size_t)len) != NULL) fail("Invalid UTF8!");
Text_t line_text = Text$from_strn(line, (size_t)len);
free(line);
return line_text;
}
-public OptionalClosure_t Path$by_line(Path_t path)
-{
+public
+OptionalClosure_t Path$by_line(Path_t path) {
path = Path$expand_home(path);
FILE *f = fopen(Path$as_c_string(path), "r");
- if (f == NULL)
- return NONE_CLOSURE;
+ if (f == NULL) return NONE_CLOSURE;
- FILE **wrapper = GC_MALLOC(sizeof(FILE*));
+ FILE **wrapper = GC_MALLOC(sizeof(FILE *));
*wrapper = f;
- GC_register_finalizer(wrapper, (void*)_line_reader_cleanup, NULL, NULL, NULL);
- return (Closure_t){.fn=(void*)_next_line, .userdata=wrapper};
+ GC_register_finalizer(wrapper, (void *)_line_reader_cleanup, NULL, NULL, NULL);
+ return (Closure_t){.fn = (void *)_next_line, .userdata = wrapper};
}
-public List_t Path$glob(Path_t path)
-{
+public
+List_t Path$glob(Path_t path) {
glob_t glob_result;
int status = glob(Path$as_c_string(path), GLOB_BRACE | GLOB_TILDE, NULL, &glob_result);
- if (status != 0 && status != GLOB_NOMATCH)
- fail("Failed to perform globbing");
+ if (status != 0 && status != GLOB_NOMATCH) fail("Failed to perform globbing");
List_t glob_files = {};
for (size_t i = 0; i < glob_result.gl_pathc; i++) {
size_t len = strlen(glob_result.gl_pathv[i]);
- if ((len >= 2 && glob_result.gl_pathv[i][len-1] == '.' && glob_result.gl_pathv[i][len-2] == '/')
- || (len >= 2 && glob_result.gl_pathv[i][len-1] == '.' && glob_result.gl_pathv[i][len-2] == '.' && glob_result.gl_pathv[i][len-3] == '/'))
+ if ((len >= 2 && glob_result.gl_pathv[i][len - 1] == '.' && glob_result.gl_pathv[i][len - 2] == '/')
+ || (len >= 2 && glob_result.gl_pathv[i][len - 1] == '.' && glob_result.gl_pathv[i][len - 2] == '.'
+ && glob_result.gl_pathv[i][len - 3] == '/'))
continue;
Path_t p = Path$from_str(glob_result.gl_pathv[i]);
List$insert(&glob_files, &p, I(0), sizeof(Path_t));
@@ -733,52 +687,51 @@ public List_t Path$glob(Path_t path)
return glob_files;
}
-public Path_t Path$current_dir(void)
-{
+public
+Path_t Path$current_dir(void) {
char cwd[PATH_MAX];
- if (getcwd(cwd, sizeof(cwd)) == NULL)
- fail("Could not get current working directory");
+ if (getcwd(cwd, sizeof(cwd)) == NULL) fail("Could not get current working directory");
return Path$from_str(cwd);
}
-public PUREFUNC uint64_t Path$hash(const void *obj, const TypeInfo_t *type)
-{
+public
+PUREFUNC uint64_t Path$hash(const void *obj, const TypeInfo_t *type) {
(void)type;
- Path_t *path = (Path_t*)obj;
+ Path_t *path = (Path_t *)obj;
siphash sh;
siphashinit(&sh, (uint64_t)path->type.$tag);
for (int64_t i = 0; i < path->components.length; i++) {
- uint64_t item_hash = Text$hash(path->components.data + i*path->components.stride, &Text$info);
+ uint64_t item_hash = Text$hash(path->components.data + i * path->components.stride, &Text$info);
siphashadd64bits(&sh, item_hash);
}
return siphashfinish_last_part(&sh, (uint64_t)path->components.length);
}
-public PUREFUNC int32_t Path$compare(const void *va, const void *vb, const TypeInfo_t *type)
-{
+public
+PUREFUNC int32_t Path$compare(const void *va, const void *vb, const TypeInfo_t *type) {
(void)type;
- Path_t *a = (Path_t*)va, *b = (Path_t*)vb;
+ Path_t *a = (Path_t *)va, *b = (Path_t *)vb;
int diff = ((int)a->type.$tag - (int)b->type.$tag);
if (diff != 0) return diff;
return List$compare(&a->components, &b->components, List$info(&Text$info));
}
-public PUREFUNC bool Path$equal(const void *va, const void *vb, const TypeInfo_t *type)
-{
+public
+PUREFUNC bool Path$equal(const void *va, const void *vb, const TypeInfo_t *type) {
(void)type;
- Path_t *a = (Path_t*)va, *b = (Path_t*)vb;
+ Path_t *a = (Path_t *)va, *b = (Path_t *)vb;
if (a->type.$tag != b->type.$tag) return false;
return List$equal(&a->components, &b->components, List$info(&Text$info));
}
-public PUREFUNC bool Path$equal_values(Path_t a, Path_t b)
-{
+public
+PUREFUNC bool Path$equal_values(Path_t a, Path_t b) {
if (a.type.$tag != b.type.$tag) return false;
return List$equal(&a.components, &b.components, List$info(&Text$info));
}
-public int Path$print(FILE *f, Path_t path)
-{
+public
+int Path$print(FILE *f, Path_t path) {
if (path.components.length == 0) {
if (path.type.$tag == PATH_ABSOLUTE) return fputs("/", f);
else if (path.type.$tag == PATH_RELATIVE) return fputs(".", f);
@@ -791,91 +744,86 @@ public int Path$print(FILE *f, Path_t path)
} else if (path.type.$tag == PATH_HOME) {
n += fputs("~/", f);
} else if (path.type.$tag == PATH_RELATIVE) {
- if (!Text$equal_values(*(Text_t*)path.components.data, Text("..")))
- n += fputs("./", f);
+ if (!Text$equal_values(*(Text_t *)path.components.data, Text(".."))) n += fputs("./", f);
}
for (int64_t i = 0; i < path.components.length; i++) {
- Text_t *comp = (Text_t*)(path.components.data + i*path.components.stride);
+ Text_t *comp = (Text_t *)(path.components.data + i * path.components.stride);
n += Text$print(f, *comp);
- if (i + 1 < path.components.length)
- n += fputc('/', f);
+ if (i + 1 < path.components.length) n += fputc('/', f);
}
return n;
}
-public const char *Path$as_c_string(Path_t path)
-{
- return String(path);
-}
+public
+const char *Path$as_c_string(Path_t path) { return String(path); }
-public Text_t Path$as_text(const void *obj, bool color, const TypeInfo_t *type)
-{
+public
+Text_t Path$as_text(const void *obj, bool color, const TypeInfo_t *type) {
(void)type;
if (!obj) return Text("Path");
- Path_t *path = (Path_t*)obj;
+ Path_t *path = (Path_t *)obj;
Text_t text = Text$join(Text("/"), path->components);
- if (path->type.$tag == PATH_HOME)
- text = Text$concat(path->components.length > 0 ? Text("~/") : Text("~"), text);
- else if (path->type.$tag == PATH_ABSOLUTE)
- text = Text$concat(Text("/"), text);
- else if (path->type.$tag == PATH_RELATIVE && (path->components.length == 0 || !Text$equal_values(*(Text_t*)(path->components.data), Text(".."))))
+ if (path->type.$tag == PATH_HOME) text = Text$concat(path->components.length > 0 ? Text("~/") : Text("~"), text);
+ else if (path->type.$tag == PATH_ABSOLUTE) text = Text$concat(Text("/"), text);
+ else if (path->type.$tag == PATH_RELATIVE
+ && (path->components.length == 0 || !Text$equal_values(*(Text_t *)(path->components.data), Text(".."))))
text = Text$concat(path->components.length > 0 ? Text("./") : Text("."), text);
- if (color)
- text = Texts(Text("\033[32;1m"), text, Text("\033[m"));
+ if (color) text = Texts(Text("\033[32;1m"), text, Text("\033[m"));
return text;
}
-public CONSTFUNC bool Path$is_none(const void *obj, const TypeInfo_t *type)
-{
+public
+CONSTFUNC bool Path$is_none(const void *obj, const TypeInfo_t *type) {
(void)type;
- return ((Path_t*)obj)->type.$tag == PATH_NONE;
+ return ((Path_t *)obj)->type.$tag == PATH_NONE;
}
-public void Path$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type)
-{
+public
+void Path$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
(void)type;
- Path_t *path = (Path_t*)obj;
+ Path_t *path = (Path_t *)obj;
fputc((int)path->type.$tag, out);
List$serialize(&path->components, out, pointers, List$info(&Text$info));
}
-public void Path$deserialize(FILE *in, void *obj, List_t *pointers, const TypeInfo_t *type)
-{
+public
+void Path$deserialize(FILE *in, void *obj, List_t *pointers, const TypeInfo_t *type) {
(void)type;
Path_t path = {};
path.type.$tag = fgetc(in);
List$deserialize(in, &path.components, pointers, List$info(&Text$info));
- *(Path_t*)obj = path;
-}
-
-public const TypeInfo_t Path$info = {
- .size=sizeof(Path_t),
- .align=__alignof__(Path_t),
- .tag=OpaqueInfo,
- .metamethods={
- .as_text=Path$as_text,
- .hash=Path$hash,
- .compare=Path$compare,
- .equal=Path$equal,
- .is_none=Path$is_none,
- .serialize=Path$serialize,
- .deserialize=Path$deserialize,
- }
-};
-
-public const TypeInfo_t PathType$info = {
- .size=sizeof(PathType_t),
- .align=__alignof__(PathType_t),
- .metamethods=PackedDataEnum$metamethods,
- .tag=EnumInfo,
- .EnumInfo={
- .name="PathType",
- .num_tags=3,
- .tags=((NamedType_t[3]){{.name="Relative"}, {.name="Absolute"}, {.name="Home"}}),
- },
+ *(Path_t *)obj = path;
+}
+
+public
+const TypeInfo_t Path$info = {.size = sizeof(Path_t),
+ .align = __alignof__(Path_t),
+ .tag = OpaqueInfo,
+ .metamethods = {
+ .as_text = Path$as_text,
+ .hash = Path$hash,
+ .compare = Path$compare,
+ .equal = Path$equal,
+ .is_none = Path$is_none,
+ .serialize = Path$serialize,
+ .deserialize = Path$deserialize,
+ }};
+
+public
+const TypeInfo_t PathType$info = {
+ .size = sizeof(PathType_t),
+ .align = __alignof__(PathType_t),
+ .metamethods = PackedDataEnum$metamethods,
+ .tag = EnumInfo,
+ .EnumInfo =
+ {
+ .name = "PathType",
+ .num_tags = 3,
+ .tags = ((NamedType_t[3]){{.name = "Relative"}, {.name = "Absolute"}, {.name = "Home"}}),
+ },
};
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/paths.h b/src/stdlib/paths.h
index 6284e55b..7f0d8830 100644
--- a/src/stdlib/paths.h
+++ b/src/stdlib/paths.h
@@ -15,7 +15,7 @@ Path_t Path$from_text(Text_t text);
const char *Path$as_c_string(Path_t path);
#define Path(str) Path$from_str(str)
Path_t Path$_concat(int n, Path_t items[n]);
-#define Path$concat(...) Path$_concat((int)sizeof((Path_t[]){__VA_ARGS__})/sizeof(Path_t), ((Path_t[]){__VA_ARGS__}))
+#define Path$concat(...) Path$_concat((int)sizeof((Path_t[]){__VA_ARGS__}) / sizeof(Path_t), ((Path_t[]){__VA_ARGS__}))
Path_t Path$resolved(Path_t path, Path_t relative_to);
Path_t Path$relative_to(Path_t path, Path_t relative_to);
Path_t Path$expand_home(Path_t path);
@@ -59,7 +59,7 @@ Path_t Path$current_dir(void);
Closure_t Path$by_line(Path_t path);
List_t Path$glob(Path_t path);
-uint64_t Path$hash(const void *obj, const TypeInfo_t*);
+uint64_t Path$hash(const void *obj, const TypeInfo_t *);
int32_t Path$compare(const void *a, const void *b, const TypeInfo_t *type);
bool Path$equal(const void *a, const void *b, const TypeInfo_t *type);
bool Path$equal_values(Path_t a, Path_t b);
@@ -72,4 +72,3 @@ extern const TypeInfo_t Path$info;
extern const TypeInfo_t PathType$info;
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
-
diff --git a/src/stdlib/pointers.c b/src/stdlib/pointers.c
index 3708da62..e94ede6d 100644
--- a/src/stdlib/pointers.c
+++ b/src/stdlib/pointers.c
@@ -13,22 +13,19 @@
#include "types.h"
#include "util.h"
-public Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *type) {
+public
+Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *type) {
__typeof(type->PointerInfo) ptr_info = type->PointerInfo;
if (!x) {
Text_t typename = generic_as_text(NULL, false, ptr_info.pointed);
- if (colorize)
- return Text$concat(Text("\x1b[34;1m"), Text$from_str(ptr_info.sigil), typename, Text("\x1b[m"));
- else
- return Text$concat(Text$from_str(ptr_info.sigil), typename);
+ if (colorize) return Text$concat(Text("\x1b[34;1m"), Text$from_str(ptr_info.sigil), typename, Text("\x1b[m"));
+ else return Text$concat(Text$from_str(ptr_info.sigil), typename);
}
- const void *ptr = *(const void**)x;
+ const void *ptr = *(const void **)x;
if (!ptr) {
Text_t typename = generic_as_text(NULL, false, ptr_info.pointed);
- if (colorize)
- return Text$concat(Text("\x1b[34;1m!"), typename, Text("\x1b[m"));
- else
- return Text$concat(Text("!"), typename);
+ if (colorize) return Text$concat(Text("\x1b[34;1m!"), typename, Text("\x1b[m"));
+ else return Text$concat(Text("!"), typename);
}
static const void *root = NULL;
@@ -61,38 +58,38 @@ public Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *ty
}
Text_t text;
- if (colorize)
- text = Text$concat(Text("\x1b[34;1m"), Text$from_str(ptr_info.sigil), Text("\x1b[m"), pointed);
- else
- text = Text$concat(Text$from_str(ptr_info.sigil), pointed);
+ if (colorize) text = Text$concat(Text("\x1b[34;1m"), Text$from_str(ptr_info.sigil), Text("\x1b[m"), pointed);
+ else text = Text$concat(Text$from_str(ptr_info.sigil), pointed);
return text;
}
PUREFUNC public int32_t Pointer$compare(const void *x, const void *y, const TypeInfo_t *info) {
(void)info;
- const void *xp = *(const void**)x, *yp = *(const void**)y;
+ const void *xp = *(const void **)x, *yp = *(const void **)y;
return (xp > yp) - (xp < yp);
}
PUREFUNC public bool Pointer$equal(const void *x, const void *y, const TypeInfo_t *info) {
(void)info;
- const void *xp = *(const void**)x, *yp = *(const void**)y;
+ const void *xp = *(const void **)x, *yp = *(const void **)y;
return xp == yp;
}
-PUREFUNC public bool Pointer$is_none(const void *x, const TypeInfo_t *info)
-{
+PUREFUNC public bool Pointer$is_none(const void *x, const TypeInfo_t *info) {
(void)info;
- return *(void**)x == NULL;
+ return *(void **)x == NULL;
}
-public void Pointer$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type)
-{
- void *ptr = *(void**)obj;
+public
+void Pointer$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
+ void *ptr = *(void **)obj;
assert(ptr != NULL);
- const TypeInfo_t ptr_to_int_table = {.size=sizeof(Table_t), .align=__alignof__(Table_t),
- .tag=TableInfo, .TableInfo.key=type, .TableInfo.value=&Int64$info};
+ const TypeInfo_t ptr_to_int_table = {.size = sizeof(Table_t),
+ .align = __alignof__(Table_t),
+ .tag = TableInfo,
+ .TableInfo.key = type,
+ .TableInfo.value = &Int64$info};
int64_t *id_ptr = Table$get(*pointers, &ptr, &ptr_to_int_table);
int64_t id;
@@ -105,23 +102,22 @@ public void Pointer$serialize(const void *obj, FILE *out, Table_t *pointers, con
Int64$serialize(&id, out, pointers, &Int64$info);
- if (!id_ptr)
- _serialize(ptr, out, pointers, type->PointerInfo.pointed);
+ if (!id_ptr) _serialize(ptr, out, pointers, type->PointerInfo.pointed);
}
-public void Pointer$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type)
-{
+public
+void Pointer$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type) {
int64_t id = 0;
Int64$deserialize(in, &id, pointers, &Int64$info);
assert(id != 0);
if (id > pointers->length) {
void *obj = GC_MALLOC((size_t)type->PointerInfo.pointed->size);
- List$insert(pointers, &obj, I(0), sizeof(void*));
+ List$insert(pointers, &obj, I(0), sizeof(void *));
_deserialize(in, obj, pointers, type->PointerInfo.pointed);
- *(void**)outval = obj;
+ *(void **)outval = obj;
} else {
- *(void**)outval = *(void**)(pointers->data + (id-1)*pointers->stride);
+ *(void **)outval = *(void **)(pointers->data + (id - 1) * pointers->stride);
}
}
diff --git a/src/stdlib/pointers.h b/src/stdlib/pointers.h
index 001dc5ce..522a97be 100644
--- a/src/stdlib/pointers.h
+++ b/src/stdlib/pointers.h
@@ -12,25 +12,33 @@
Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *type);
PUREFUNC int32_t Pointer$compare(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC bool Pointer$equal(const void *x, const void *y, const TypeInfo_t *type);
-PUREFUNC bool Pointer$is_none(const void *x, const TypeInfo_t*);
+PUREFUNC bool Pointer$is_none(const void *x, const TypeInfo_t *);
void Pointer$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type);
void Pointer$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type);
-#define Null(t) (t*)NULL
-#define POINTER_TYPE(_sigil, _pointed) (&(TypeInfo_t){\
- .size=sizeof(void*), .align=__alignof__(void*), .tag=PointerInfo, .PointerInfo.sigil=_sigil, .PointerInfo.pointed=_pointed})
-
-#define Pointer$metamethods { \
- .as_text=Pointer$as_text, \
- .compare=Pointer$compare, \
- .equal=Pointer$equal, \
- .is_none=Pointer$is_none, \
- .serialize=Pointer$serialize, \
- .deserialize=Pointer$deserialize, \
-}
-
-#define Pointer$info(sigil_expr, pointed_info) &((TypeInfo_t){.size=sizeof(void*), .align=__alignof__(void*), \
- .tag=PointerInfo, .PointerInfo={.sigil=sigil_expr, .pointed=pointed_info}, \
- .metamethods=Pointer$metamethods})
+#define Null(t) (t *)NULL
+#define POINTER_TYPE(_sigil, _pointed) \
+ (&(TypeInfo_t){.size = sizeof(void *), \
+ .align = __alignof__(void *), \
+ .tag = PointerInfo, \
+ .PointerInfo.sigil = _sigil, \
+ .PointerInfo.pointed = _pointed})
+
+#define Pointer$metamethods \
+ { \
+ .as_text = Pointer$as_text, \
+ .compare = Pointer$compare, \
+ .equal = Pointer$equal, \
+ .is_none = Pointer$is_none, \
+ .serialize = Pointer$serialize, \
+ .deserialize = Pointer$deserialize, \
+ }
+
+#define Pointer$info(sigil_expr, pointed_info) \
+ &((TypeInfo_t){.size = sizeof(void *), \
+ .align = __alignof__(void *), \
+ .tag = PointerInfo, \
+ .PointerInfo = {.sigil = sigil_expr, .pointed = pointed_info}, \
+ .metamethods = Pointer$metamethods})
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/powers.h b/src/stdlib/powers.h
index d1829b60..e9b6a74e 100644
--- a/src/stdlib/powers.h
+++ b/src/stdlib/powers.h
@@ -4,13 +4,12 @@
#include <stdint.h>
-#define npowers 87
-#define steppowers 8
+#define npowers 87
+#define steppowers 8
#define firstpower -348 /* 10 ^ -348 */
-#define expmax -32
-#define expmin -60
-
+#define expmax -32
+#define expmin -60
typedef struct Fp {
uint64_t frac;
@@ -18,54 +17,37 @@ typedef struct Fp {
} Fp;
static const Fp powers_ten[] = {
- { 18054884314459144840U, -1220 }, { 13451937075301367670U, -1193 },
- { 10022474136428063862U, -1166 }, { 14934650266808366570U, -1140 },
- { 11127181549972568877U, -1113 }, { 16580792590934885855U, -1087 },
- { 12353653155963782858U, -1060 }, { 18408377700990114895U, -1034 },
- { 13715310171984221708U, -1007 }, { 10218702384817765436U, -980 },
- { 15227053142812498563U, -954 }, { 11345038669416679861U, -927 },
- { 16905424996341287883U, -901 }, { 12595523146049147757U, -874 },
- { 9384396036005875287U, -847 }, { 13983839803942852151U, -821 },
- { 10418772551374772303U, -794 }, { 15525180923007089351U, -768 },
- { 11567161174868858868U, -741 }, { 17236413322193710309U, -715 },
- { 12842128665889583758U, -688 }, { 9568131466127621947U, -661 },
- { 14257626930069360058U, -635 }, { 10622759856335341974U, -608 },
- { 15829145694278690180U, -582 }, { 11793632577567316726U, -555 },
- { 17573882009934360870U, -529 }, { 13093562431584567480U, -502 },
- { 9755464219737475723U, -475 }, { 14536774485912137811U, -449 },
- { 10830740992659433045U, -422 }, { 16139061738043178685U, -396 },
- { 12024538023802026127U, -369 }, { 17917957937422433684U, -343 },
- { 13349918974505688015U, -316 }, { 9946464728195732843U, -289 },
- { 14821387422376473014U, -263 }, { 11042794154864902060U, -236 },
- { 16455045573212060422U, -210 }, { 12259964326927110867U, -183 },
- { 18268770466636286478U, -157 }, { 13611294676837538539U, -130 },
- { 10141204801825835212U, -103 }, { 15111572745182864684U, -77 },
- { 11258999068426240000U, -50 }, { 16777216000000000000U, -24 },
- { 12500000000000000000U, 3 }, { 9313225746154785156U, 30 },
- { 13877787807814456755U, 56 }, { 10339757656912845936U, 83 },
- { 15407439555097886824U, 109 }, { 11479437019748901445U, 136 },
- { 17105694144590052135U, 162 }, { 12744735289059618216U, 189 },
- { 9495567745759798747U, 216 }, { 14149498560666738074U, 242 },
- { 10542197943230523224U, 269 }, { 15709099088952724970U, 295 },
- { 11704190886730495818U, 322 }, { 17440603504673385349U, 348 },
- { 12994262207056124023U, 375 }, { 9681479787123295682U, 402 },
- { 14426529090290212157U, 428 }, { 10748601772107342003U, 455 },
- { 16016664761464807395U, 481 }, { 11933345169920330789U, 508 },
- { 17782069995880619868U, 534 }, { 13248674568444952270U, 561 },
- { 9871031767461413346U, 588 }, { 14708983551653345445U, 614 },
- { 10959046745042015199U, 641 }, { 16330252207878254650U, 667 },
- { 12166986024289022870U, 694 }, { 18130221999122236476U, 720 },
- { 13508068024458167312U, 747 }, { 10064294952495520794U, 774 },
- { 14996968138956309548U, 800 }, { 11173611982879273257U, 827 },
- { 16649979327439178909U, 853 }, { 12405201291620119593U, 880 },
- { 9242595204427927429U, 907 }, { 13772540099066387757U, 933 },
- { 10261342003245940623U, 960 }, { 15290591125556738113U, 986 },
- { 11392378155556871081U, 1013 }, { 16975966327722178521U, 1039 },
- { 12648080533535911531U, 1066 }
-};
+ {18054884314459144840U, -1220}, {13451937075301367670U, -1193}, {10022474136428063862U, -1166},
+ {14934650266808366570U, -1140}, {11127181549972568877U, -1113}, {16580792590934885855U, -1087},
+ {12353653155963782858U, -1060}, {18408377700990114895U, -1034}, {13715310171984221708U, -1007},
+ {10218702384817765436U, -980}, {15227053142812498563U, -954}, {11345038669416679861U, -927},
+ {16905424996341287883U, -901}, {12595523146049147757U, -874}, {9384396036005875287U, -847},
+ {13983839803942852151U, -821}, {10418772551374772303U, -794}, {15525180923007089351U, -768},
+ {11567161174868858868U, -741}, {17236413322193710309U, -715}, {12842128665889583758U, -688},
+ {9568131466127621947U, -661}, {14257626930069360058U, -635}, {10622759856335341974U, -608},
+ {15829145694278690180U, -582}, {11793632577567316726U, -555}, {17573882009934360870U, -529},
+ {13093562431584567480U, -502}, {9755464219737475723U, -475}, {14536774485912137811U, -449},
+ {10830740992659433045U, -422}, {16139061738043178685U, -396}, {12024538023802026127U, -369},
+ {17917957937422433684U, -343}, {13349918974505688015U, -316}, {9946464728195732843U, -289},
+ {14821387422376473014U, -263}, {11042794154864902060U, -236}, {16455045573212060422U, -210},
+ {12259964326927110867U, -183}, {18268770466636286478U, -157}, {13611294676837538539U, -130},
+ {10141204801825835212U, -103}, {15111572745182864684U, -77}, {11258999068426240000U, -50},
+ {16777216000000000000U, -24}, {12500000000000000000U, 3}, {9313225746154785156U, 30},
+ {13877787807814456755U, 56}, {10339757656912845936U, 83}, {15407439555097886824U, 109},
+ {11479437019748901445U, 136}, {17105694144590052135U, 162}, {12744735289059618216U, 189},
+ {9495567745759798747U, 216}, {14149498560666738074U, 242}, {10542197943230523224U, 269},
+ {15709099088952724970U, 295}, {11704190886730495818U, 322}, {17440603504673385349U, 348},
+ {12994262207056124023U, 375}, {9681479787123295682U, 402}, {14426529090290212157U, 428},
+ {10748601772107342003U, 455}, {16016664761464807395U, 481}, {11933345169920330789U, 508},
+ {17782069995880619868U, 534}, {13248674568444952270U, 561}, {9871031767461413346U, 588},
+ {14708983551653345445U, 614}, {10959046745042015199U, 641}, {16330252207878254650U, 667},
+ {12166986024289022870U, 694}, {18130221999122236476U, 720}, {13508068024458167312U, 747},
+ {10064294952495520794U, 774}, {14996968138956309548U, 800}, {11173611982879273257U, 827},
+ {16649979327439178909U, 853}, {12405201291620119593U, 880}, {9242595204427927429U, 907},
+ {13772540099066387757U, 933}, {10261342003245940623U, 960}, {15290591125556738113U, 986},
+ {11392378155556871081U, 1013}, {16975966327722178521U, 1039}, {12648080533535911531U, 1066}};
-static Fp find_cachedpow10(int exp, int* k)
-{
+static Fp find_cachedpow10(int exp, int *k) {
const double one_log_ten = 0.30102999566398114;
int approx = -(exp + npowers) * one_log_ten;
diff --git a/src/stdlib/print.c b/src/stdlib/print.c
index 8e2dd862..d246c9c3 100644
--- a/src/stdlib/print.c
+++ b/src/stdlib/print.c
@@ -8,9 +8,9 @@
#include "print.h"
#include "util.h"
-public int _print_int(FILE *f, int64_t n)
-{
- char buf[21] = {[20]=0}; // Big enough for INT64_MIN + '\0'
+public
+int _print_int(FILE *f, int64_t n) {
+ char buf[21] = {[20] = 0}; // Big enough for INT64_MIN + '\0'
char *p = &buf[19];
bool negative = n < 0;
@@ -19,15 +19,14 @@ public int _print_int(FILE *f, int64_t n)
n /= 10;
} while (n > 0);
- if (negative)
- *(p--) = '-';
+ if (negative) *(p--) = '-';
return fwrite(p + 1, sizeof(char), (size_t)(&buf[19] - p), f);
}
-public int _print_uint(FILE *f, uint64_t n)
-{
- char buf[21] = {[20]=0}; // Big enough for UINT64_MAX + '\0'
+public
+int _print_uint(FILE *f, uint64_t n) {
+ char buf[21] = {[20] = 0}; // Big enough for UINT64_MAX + '\0'
char *p = &buf[19];
do {
@@ -38,8 +37,8 @@ public int _print_uint(FILE *f, uint64_t n)
return fwrite(p + 1, sizeof(char), (size_t)(&buf[19] - p), f);
}
-public int _print_hex(FILE *f, hex_format_t hex)
-{
+public
+int _print_hex(FILE *f, hex_format_t hex) {
int printed = 0;
if (!hex.no_prefix) printed += fputs("0x", f);
if (hex.digits > 0) {
@@ -50,24 +49,21 @@ public int _print_hex(FILE *f, hex_format_t hex)
printed += fputc('0', f);
}
}
- char buf[9] = {[8]='\0'}; // Enough space for FFFFFFFF + '\0'
+ char buf[9] = {[8] = '\0'}; // Enough space for FFFFFFFF + '\0'
char *p = &buf[7];
do {
uint8_t digit = hex.n % 16;
- if (digit <= 9)
- *(p--) = '0' + digit;
- else if (hex.uppercase)
- *(p--) = 'A' + digit - 10;
- else
- *(p--) = 'a' + digit - 10;
+ if (digit <= 9) *(p--) = '0' + digit;
+ else if (hex.uppercase) *(p--) = 'A' + digit - 10;
+ else *(p--) = 'a' + digit - 10;
hex.n /= 16;
} while (hex.n > 0);
printed += (int)fwrite(p + 1, sizeof(char), (size_t)(&buf[7] - p), f);
return printed;
}
-public int _print_oct(FILE *f, oct_format_t oct)
-{
+public
+int _print_oct(FILE *f, oct_format_t oct) {
int printed = 0;
if (!oct.no_prefix) printed += fputs("0o", f);
if (oct.digits > 0) {
@@ -76,7 +72,7 @@ public int _print_oct(FILE *f, oct_format_t oct)
for (; oct.digits > 0; oct.digits -= 1)
printed += fputc('0', f);
}
- char buf[12] = {[11]='\0'}; // Enough space for octal UINT64_MAX + '\0'
+ char buf[12] = {[11] = '\0'}; // Enough space for octal UINT64_MAX + '\0'
char *p = &buf[10];
do {
*(p--) = '0' + (oct.n % 8);
@@ -86,25 +82,24 @@ public int _print_oct(FILE *f, oct_format_t oct)
return printed;
}
-public int _print_double(FILE *f, double n)
-{
+public
+int _print_double(FILE *f, double n) {
static char buf[24];
int len = fpconv_dtoa(n, buf);
return (int)fwrite(buf, sizeof(char), (size_t)len, f);
}
-public int _print_hex_double(FILE *f, hex_double_t hex)
-{
- if (hex.d != hex.d)
- return fputs("NAN", f);
- else if (hex.d == 1.0/0.0)
- return fputs("INF", f);
- else if (hex.d == -1.0/0.0)
- return fputs("-INF", f);
- else if (hex.d == 0.0)
- return fputs("0.0", f);
+public
+int _print_hex_double(FILE *f, hex_double_t hex) {
+ if (hex.d != hex.d) return fputs("NAN", f);
+ else if (hex.d == 1.0 / 0.0) return fputs("INF", f);
+ else if (hex.d == -1.0 / 0.0) return fputs("-INF", f);
+ else if (hex.d == 0.0) return fputs("0.0", f);
- union { double d; uint64_t u; } bits = { .d = hex.d };
+ union {
+ double d;
+ uint64_t u;
+ } bits = {.d = hex.d};
int sign = (bits.u >> 63) & 1ull;
int exp = (int)((bits.u >> 52) & 0x7FF) - 1023ull;
@@ -161,30 +156,27 @@ public int _print_hex_double(FILE *f, hex_double_t hex)
return fwrite(buf, sizeof(char), (size_t)(p - buf), f);
}
-public int _print_char(FILE *f, char c)
-{
+public
+int _print_char(FILE *f, char c) {
#define ESC(e) "'\\" e "'"
- const char *named[256] = {['\'']=ESC("'"), ['\\']=ESC("\\"),
- ['\n']=ESC("n"), ['\t']=ESC("t"), ['\r']=ESC("r"),
- ['\033']=ESC("e"), ['\v']=ESC("v"), ['\a']=ESC("a"), ['\b']=ESC("b")};
+ const char *named[256] = {
+ ['\''] = ESC("'"), ['\\'] = ESC("\\"), ['\n'] = ESC("n"), ['\t'] = ESC("t"), ['\r'] = ESC("r"),
+ ['\033'] = ESC("e"), ['\v'] = ESC("v"), ['\a'] = ESC("a"), ['\b'] = ESC("b")};
const char *name = named[(uint8_t)c];
- if (name != NULL)
- return fputs(name, f);
- else if (isprint(c))
-
- return fputc('\'', f) + fputc(c, f) + fputc('\'', f);
+ if (name != NULL) return fputs(name, f);
+ else if (isprint(c)) return fputc('\'', f) + fputc(c, f) + fputc('\'', f);
else
- return (fputs("'\\x", f) + _print_hex(f, hex((uint64_t)c, .digits=2, .no_prefix=true, .uppercase=true))
+ return (fputs("'\\x", f) + _print_hex(f, hex((uint64_t)c, .digits = 2, .no_prefix = true, .uppercase = true))
+ fputs("'", f));
#undef ESC
}
-public int _print_quoted(FILE *f, quoted_t quoted)
-{
+public
+int _print_quoted(FILE *f, quoted_t quoted) {
#define ESC(e) "\\" e
- const char *named[256] = {['"']=ESC("\""), ['\\']=ESC("\\"),
- ['\n']=ESC("n"), ['\t']=ESC("t"), ['\r']=ESC("r"),
- ['\033']=ESC("e"), ['\v']=ESC("v"), ['\a']=ESC("a"), ['\b']=ESC("b")};
+ const char *named[256] = {
+ ['"'] = ESC("\""), ['\\'] = ESC("\\"), ['\n'] = ESC("n"), ['\t'] = ESC("t"), ['\r'] = ESC("r"),
+ ['\033'] = ESC("e"), ['\v'] = ESC("v"), ['\a'] = ESC("a"), ['\b'] = ESC("b")};
int printed = fputc('"', f);
for (const char *p = quoted.str; *p; p++) {
const char *name = named[(uint8_t)*p];
@@ -193,7 +185,8 @@ public int _print_quoted(FILE *f, quoted_t quoted)
} else if (isprint(*p) || (uint8_t)*p > 0x7F) {
printed += fputc(*p, f);
} else {
- printed += fputs("\\x", f) + _print_hex(f, hex((uint64_t)*p, .digits=2, .no_prefix=true, .uppercase=true));
+ printed +=
+ fputs("\\x", f) + _print_hex(f, hex((uint64_t)*p, .digits = 2, .no_prefix = true, .uppercase = true));
}
}
printed += fputc('"', f);
@@ -202,52 +195,56 @@ public int _print_quoted(FILE *f, quoted_t quoted)
}
#if defined(__GLIBC__) && defined(_GNU_SOURCE)
- // GLIBC has fopencookie()
- static ssize_t _gc_stream_write(void *cookie, const char *buf, size_t size) {
- gc_stream_t *stream = (gc_stream_t *)cookie;
- if (stream->position + size + 1 > *stream->size)
- *stream->buffer = GC_REALLOC(*stream->buffer, (*stream->size += MAX(MAX(16UL, *stream->size/2UL), size + 1UL)));
- memcpy(&(*stream->buffer)[stream->position], buf, size);
- stream->position += size;
- (*stream->buffer)[stream->position] = '\0';
- return (ssize_t)size;
- }
+// GLIBC has fopencookie()
+static ssize_t _gc_stream_write(void *cookie, const char *buf, size_t size) {
+ gc_stream_t *stream = (gc_stream_t *)cookie;
+ if (stream->position + size + 1 > *stream->size)
+ *stream->buffer =
+ GC_REALLOC(*stream->buffer, (*stream->size += MAX(MAX(16UL, *stream->size / 2UL), size + 1UL)));
+ memcpy(&(*stream->buffer)[stream->position], buf, size);
+ stream->position += size;
+ (*stream->buffer)[stream->position] = '\0';
+ return (ssize_t)size;
+}
- public FILE *gc_memory_stream(char **buf, size_t *size) {
- gc_stream_t *stream = GC_MALLOC(sizeof(gc_stream_t));
- stream->size = size;
- stream->buffer = buf;
- *stream->size = 16;
- *stream->buffer = GC_MALLOC_ATOMIC(*stream->size);
- (*stream->buffer)[0] = '\0';
- stream->position = 0;
- cookie_io_functions_t functions = {.write = _gc_stream_write};
- return fopencookie(stream, "w", functions);
- }
+public
+FILE *gc_memory_stream(char **buf, size_t *size) {
+ gc_stream_t *stream = GC_MALLOC(sizeof(gc_stream_t));
+ stream->size = size;
+ stream->buffer = buf;
+ *stream->size = 16;
+ *stream->buffer = GC_MALLOC_ATOMIC(*stream->size);
+ (*stream->buffer)[0] = '\0';
+ stream->position = 0;
+ cookie_io_functions_t functions = {.write = _gc_stream_write};
+ return fopencookie(stream, "w", functions);
+}
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
- // BSDs have funopen() and fwopen()
- static int _gc_stream_write(void *cookie, const char *buf, int size) {
- gc_stream_t *stream = (gc_stream_t *)cookie;
- if (stream->position + size + 1 > *stream->size)
- *stream->buffer = GC_REALLOC(*stream->buffer, (*stream->size += MAX(MAX(16UL, *stream->size/2UL), size + 1UL)));
- memcpy(&(*stream->buffer)[stream->position], buf, size);
- stream->position += size;
- (*stream->buffer)[stream->position] = '\0';
- return size;
- }
+// BSDs have funopen() and fwopen()
+static int _gc_stream_write(void *cookie, const char *buf, int size) {
+ gc_stream_t *stream = (gc_stream_t *)cookie;
+ if (stream->position + size + 1 > *stream->size)
+ *stream->buffer =
+ GC_REALLOC(*stream->buffer, (*stream->size += MAX(MAX(16UL, *stream->size / 2UL), size + 1UL)));
+ memcpy(&(*stream->buffer)[stream->position], buf, size);
+ stream->position += size;
+ (*stream->buffer)[stream->position] = '\0';
+ return size;
+}
- public FILE *gc_memory_stream(char **buf, size_t *size) {
- gc_stream_t *stream = GC_MALLOC(sizeof(gc_stream_t));
- stream->size = size;
- stream->buffer = buf;
- *stream->size = 16;
- *stream->buffer = GC_MALLOC_ATOMIC(*stream->size);
- (*stream->buffer)[0] = '\0';
- stream->position = 0;
- return fwopen(stream, _gc_stream_write);
- }
+public
+FILE *gc_memory_stream(char **buf, size_t *size) {
+ gc_stream_t *stream = GC_MALLOC(sizeof(gc_stream_t));
+ stream->size = size;
+ stream->buffer = buf;
+ *stream->size = 16;
+ *stream->buffer = GC_MALLOC_ATOMIC(*stream->size);
+ (*stream->buffer)[0] = '\0';
+ stream->position = 0;
+ return fwopen(stream, _gc_stream_write);
+}
#else
-# error "This platform doesn't support fopencookie() or funopen()!"
+#error "This platform doesn't support fopencookie() or funopen()!"
#endif
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/print.h b/src/stdlib/print.h
index 56953866..c7e59f8b 100644
--- a/src/stdlib/print.h
+++ b/src/stdlib/print.h
@@ -38,19 +38,19 @@ typedef struct {
bool uppercase;
int digits;
} hex_format_t;
-#define hex(x, ...) ((hex_format_t){.n=x, __VA_ARGS__})
+#define hex(x, ...) ((hex_format_t){.n = x, __VA_ARGS__})
typedef struct {
double d;
} hex_double_t;
-#define hex_double(x, ...) ((hex_double_t){.d=x, __VA_ARGS__})
+#define hex_double(x, ...) ((hex_double_t){.d = x, __VA_ARGS__})
typedef struct {
uint64_t n;
bool no_prefix;
int digits;
} oct_format_t;
-#define oct(x, ...) ((oct_format_t){.n=x, __VA_ARGS__})
+#define oct(x, ...) ((oct_format_t){.n = x, __VA_ARGS__})
typedef struct {
const char *str;
@@ -67,7 +67,7 @@ typedef struct {
char c;
int length;
} repeated_char_t;
-#define repeated_char(ch, len) ((repeated_char_t){.c=ch, .length=len})
+#define repeated_char(ch, len) ((repeated_char_t){.c = ch, .length = len})
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#define FMT64 "ll"
@@ -87,7 +87,9 @@ PRINT_FN _print_bool(FILE *f, bool b) { return fputs(b ? "yes" : "no", f); }
PRINT_FN _print_str(FILE *f, const char *s) { return fputs(s ? s : "(null)", f); }
int _print_char(FILE *f, char c);
int _print_quoted(FILE *f, quoted_t quoted);
-PRINT_FN _print_string_slice(FILE *f, string_slice_t slice) { return slice.str ? fwrite(slice.str, 1, slice.length, f) : (size_t)fputs("(null)", f); }
+PRINT_FN _print_string_slice(FILE *f, string_slice_t slice) {
+ return slice.str ? fwrite(slice.str, 1, slice.length, f) : (size_t)fputs("(null)", f);
+}
PRINT_FN _print_repeated_char(FILE *f, repeated_char_t repeated) {
int len = 0;
for (int n = 0; n < repeated.length; n++)
@@ -99,31 +101,32 @@ extern int Text$print(FILE *stream, Text_t text);
extern int Path$print(FILE *stream, Path_t path);
extern int Int$print(FILE *f, Int_t i);
#ifndef _fprint1
-#define _fprint1(f, x) _Generic((x), \
- char*: _print_str, \
- const char*: _print_str, \
- char: _print_char, \
- bool: _print_bool, \
- int64_t: _print_int, \
- int32_t: _print_int, \
- int16_t: _print_int, \
- int8_t: _print_int, \
- uint64_t: _print_uint, \
- uint32_t: _print_uint, \
- uint16_t: _print_uint, \
- uint8_t: _print_uint, \
- float: _print_float, \
- double: _print_double, \
- hex_format_t: _print_hex, \
- hex_double_t: _print_hex_double, \
- oct_format_t: _print_oct, \
- quoted_t: _print_quoted, \
- string_slice_t: _print_string_slice, \
- repeated_char_t: _print_repeated_char, \
- Text_t: Text$print, \
- Path_t: Path$print, \
- Int_t: Int$print, \
- void*: _print_pointer)(f, x)
+#define _fprint1(f, x) \
+ _Generic((x), \
+ char *: _print_str, \
+ const char *: _print_str, \
+ char: _print_char, \
+ bool: _print_bool, \
+ int64_t: _print_int, \
+ int32_t: _print_int, \
+ int16_t: _print_int, \
+ int8_t: _print_int, \
+ uint64_t: _print_uint, \
+ uint32_t: _print_uint, \
+ uint16_t: _print_uint, \
+ uint8_t: _print_uint, \
+ float: _print_float, \
+ double: _print_double, \
+ hex_format_t: _print_hex, \
+ hex_double_t: _print_hex_double, \
+ oct_format_t: _print_oct, \
+ quoted_t: _print_quoted, \
+ string_slice_t: _print_string_slice, \
+ repeated_char_t: _print_repeated_char, \
+ Text_t: Text$print, \
+ Path_t: Path$print, \
+ Int_t: Int$print, \
+ void *: _print_pointer)(f, x)
#endif
typedef struct {
@@ -135,19 +138,31 @@ typedef struct {
FILE *gc_memory_stream(char **buf, size_t *size);
#define _print(x) _n += _fprint1(_printing, x)
-#define _fprint(f, ...) ({ FILE *_printing = f; int _n = 0; MAP_LIST(_print, __VA_ARGS__); _n; })
+#define _fprint(f, ...) \
+ ({ \
+ FILE *_printing = f; \
+ int _n = 0; \
+ MAP_LIST(_print, __VA_ARGS__); \
+ _n; \
+ })
#define fprint(f, ...) _fprint(f, __VA_ARGS__, "\n")
#define print(...) fprint(stdout, __VA_ARGS__)
#define fprint_inline(f, ...) _fprint(f, __VA_ARGS__)
#define print_inline(...) fprint_inline(stdout, __VA_ARGS__)
-#define String(...) ({ \
- char *_buf = NULL; \
- size_t _size = 0; \
- FILE *_stream = gc_memory_stream(&_buf, &_size); \
- assert(_stream); \
- _fprint(_stream, __VA_ARGS__); \
- fflush(_stream); \
- _buf; })
-#define print_err(...) ({ fprint(stderr, "\033[31;1m", __VA_ARGS__, "\033[m"); exit(EXIT_FAILURE); })
+#define String(...) \
+ ({ \
+ char *_buf = NULL; \
+ size_t _size = 0; \
+ FILE *_stream = gc_memory_stream(&_buf, &_size); \
+ assert(_stream); \
+ _fprint(_stream, __VA_ARGS__); \
+ fflush(_stream); \
+ _buf; \
+ })
+#define print_err(...) \
+ ({ \
+ fprint(stderr, "\033[31;1m", __VA_ARGS__, "\033[m"); \
+ exit(EXIT_FAILURE); \
+ })
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/random.h b/src/stdlib/random.h
index 8509dbd7..1a6e89a5 100644
--- a/src/stdlib/random.h
+++ b/src/stdlib/random.h
@@ -1,5 +1,5 @@
-#include <stdint.h>
#include <assert.h>
+#include <stdint.h>
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
#include <stdlib.h>
@@ -10,9 +10,9 @@ static ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) {
}
#elif defined(__linux__)
// Use getrandom()
-# include <sys/random.h>
+#include <sys/random.h>
#else
- #error "Unsupported platform for secure random number generation"
+#error "Unsupported platform for secure random number generation"
#endif
static int64_t random_range(int64_t low, int64_t high) {
diff --git a/src/stdlib/simpleparse.c b/src/stdlib/simpleparse.c
index 1ee64036..3929c32b 100644
--- a/src/stdlib/simpleparse.c
+++ b/src/stdlib/simpleparse.c
@@ -26,41 +26,42 @@ static bool _match_word(const char **str, const char *target) {
return false;
}
-public const char *simpleparse(const char *str, int n, parse_type_e types[n], void *destinations[n])
-{
+public
+const char *simpleparse(const char *str, int n, parse_type_e types[n], void *destinations[n]) {
for (int i = 0; i < n; i++) {
switch (types[i]) {
case PARSE_SOME_OF: {
- if (destinations[i]) str += strspn(str, (char*)destinations[i]);
+ if (destinations[i]) str += strspn(str, (char *)destinations[i]);
break;
}
case PARSE_LITERAL: {
- const char *target = (const char*)destinations[i];
+ const char *target = (const char *)destinations[i];
if (target) {
- if (strncmp(str, target, strlen(target)) != 0)
- return str;
+ if (strncmp(str, target, strlen(target)) != 0) return str;
str += strlen(target);
}
break;
}
case PARSE_STRING: {
size_t len;
- static const char matching_pair[256] = {[(int)'(']=')', [(int)'{']='}', [(int)'[']=']',
- [(int)'"']='"', [(int)'\'']='\'', [(int)'`']='`', [(int)'<']='>'};
- if (i > 0 && i + 1 < n && types[i-1] == PARSE_LITERAL && types[i+1] == PARSE_LITERAL
- && destinations[i-1] && destinations[i+1]
- && strlen((char*)destinations[i-1]) == 1 && strlen((char*)destinations[i+1]) == 1
- && *(char*)destinations[i+1] == matching_pair[(int)*(char*)destinations[i-1]]) {
+ static const char matching_pair[256] = {[(int)'('] = ')', [(int)'{'] = '}', [(int)'['] = ']',
+ [(int)'"'] = '"', [(int)'\''] = '\'', [(int)'`'] = '`',
+ [(int)'<'] = '>'};
+ if (i > 0 && i + 1 < n && types[i - 1] == PARSE_LITERAL && types[i + 1] == PARSE_LITERAL
+ && destinations[i - 1] && destinations[i + 1] && strlen((char *)destinations[i - 1]) == 1
+ && strlen((char *)destinations[i + 1]) == 1
+ && *(char *)destinations[i + 1] == matching_pair[(int)*(char *)destinations[i - 1]]) {
len = 0;
- char special_characters[4] = {'\\', *(char*)destinations[i-1], *(char*)destinations[i+1], 0};
- for (int depth = 1; depth > 0; ) {
+ char special_characters[4] = {'\\', *(char *)destinations[i - 1], *(char *)destinations[i + 1], 0};
+ for (int depth = 1; depth > 0;) {
len += strcspn(str + len, special_characters);
if (str[len] == '\0') {
return str;
} else if (str[len] == '\\'
- && (special_characters[1] == '"' || special_characters[1] == '\'' || special_characters[1] == '`')) {
- if (str[len+1] == '\0') return str;
- len += 2;
+ && (special_characters[1] == '"' || special_characters[1] == '\''
+ || special_characters[1] == '`')) {
+ if (str[len + 1] == '\0') return str;
+ len += 2;
} else if (str[len] == special_characters[2]) { // Check for closing quotes before opening quotes
depth -= 1;
if (depth > 0) len += 1;
@@ -70,8 +71,8 @@ public const char *simpleparse(const char *str, int n, parse_type_e types[n], vo
len += 1;
}
}
- } else if (i + 1 < n && types[i+1] == PARSE_LITERAL) {
- const char *terminator = (const char*)destinations[i+1];
+ } else if (i + 1 < n && types[i + 1] == PARSE_LITERAL) {
+ const char *terminator = (const char *)destinations[i + 1];
if (terminator) {
const char *end = strstr(str, terminator);
if (!end) return str;
@@ -79,16 +80,17 @@ public const char *simpleparse(const char *str, int n, parse_type_e types[n], vo
} else {
len = strlen(str);
}
- } else if (i + 1 < n && types[i+1] == PARSE_SOME_OF) {
- len = destinations[i+1] ? strcspn(str, (char*)destinations[i+1]) : strlen(str);;
+ } else if (i + 1 < n && types[i + 1] == PARSE_SOME_OF) {
+ len = destinations[i + 1] ? strcspn(str, (char *)destinations[i + 1]) : strlen(str);
+ ;
} else {
len = strlen(str);
}
if (destinations[i]) {
- char *matched = GC_MALLOC_ATOMIC(len+1);
+ char *matched = GC_MALLOC_ATOMIC(len + 1);
memcpy(matched, str, len);
matched[len] = '\0';
- *(const char**)destinations[i] = matched;
+ *(const char **)destinations[i] = matched;
}
str += len;
break;
@@ -97,7 +99,7 @@ public const char *simpleparse(const char *str, int n, parse_type_e types[n], vo
char *end = NULL;
double val = strtod(str, &end);
if (end == str) return str;
- if (destinations[i]) *(double*)destinations[i] = val;
+ if (destinations[i]) *(double *)destinations[i] = val;
str = end;
break;
}
@@ -105,15 +107,17 @@ public const char *simpleparse(const char *str, int n, parse_type_e types[n], vo
char *end = NULL;
long val = strtol(str, &end, 10);
if (end == str) return str;
- if (destinations[i]) *(long*)destinations[i] = val;
+ if (destinations[i]) *(long *)destinations[i] = val;
str = end;
break;
}
case PARSE_BOOL: {
- if (_match_word(&str, "true") || _match_word(&str, "yes") || _match_word(&str, "on") || _match_word(&str, "1")) {
- if (destinations[i]) *(bool*)destinations[i] = true;
- } else if (_match_word(&str, "false") || _match_word(&str, "no") || _match_word(&str, "off") || _match_word(&str, "0")) {
- if (destinations[i]) *(bool*)destinations[i] = false;
+ if (_match_word(&str, "true") || _match_word(&str, "yes") || _match_word(&str, "on")
+ || _match_word(&str, "1")) {
+ if (destinations[i]) *(bool *)destinations[i] = true;
+ } else if (_match_word(&str, "false") || _match_word(&str, "no") || _match_word(&str, "off")
+ || _match_word(&str, "0")) {
+ if (destinations[i]) *(bool *)destinations[i] = false;
} else {
return str;
}
diff --git a/src/stdlib/simpleparse.h b/src/stdlib/simpleparse.h
index da077e20..d35a8b3b 100644
--- a/src/stdlib/simpleparse.h
+++ b/src/stdlib/simpleparse.h
@@ -22,30 +22,42 @@
#include "mapmacro.h"
-typedef struct { char c; } some_char_t;
-#define PARSE_SOME_OF(chars) ((some_char_t*)chars)
+typedef struct {
+ char c;
+} some_char_t;
+#define PARSE_SOME_OF(chars) ((some_char_t *)chars)
#define PARSE_WHITESPACE PARSE_SOME_OF(" \t\r\n\v")
-typedef enum {PARSE_LITERAL, PARSE_LONG, PARSE_DOUBLE, PARSE_BOOL, PARSE_STRING, PARSE_SOME_OF} parse_type_e;
-
-typedef struct { parse_type_e type; void *dest; } parse_element_t;
-
-#define _parse_type(dest) _Generic((dest), \
- some_char_t*: PARSE_SOME_OF, \
- const char*: PARSE_LITERAL, \
- char*: PARSE_LITERAL, \
- const char**: PARSE_STRING, \
- char**: PARSE_STRING, \
- double*: PARSE_DOUBLE, \
- long*: PARSE_LONG, \
- bool*: PARSE_BOOL)
-
-#define as_void_star(x) ((void*)x)
-#define strparse(str, ...) simpleparse(str, sizeof((const void*[]){__VA_ARGS__})/sizeof(void*), (parse_type_e[]){MAP_LIST(_parse_type, __VA_ARGS__)}, (void*[]){MAP_LIST(as_void_star, __VA_ARGS__)})
-#define fparse(file, ...) ({ char *_file_contents = NULL; size_t _capacity; \
- ssize_t _just_read = getdelim(&_file_contents, &_capacity, '\0', file); \
- const char *_parse_err = _just_read > 0 ? strparse(_file_contents, __VA_ARGS__) : "No such file"; \
- if (_file_contents) free(_file_contents); \
- _parse_err; })
+typedef enum { PARSE_LITERAL, PARSE_LONG, PARSE_DOUBLE, PARSE_BOOL, PARSE_STRING, PARSE_SOME_OF } parse_type_e;
+
+typedef struct {
+ parse_type_e type;
+ void *dest;
+} parse_element_t;
+
+#define _parse_type(dest) \
+ _Generic((dest), \
+ some_char_t *: PARSE_SOME_OF, \
+ const char *: PARSE_LITERAL, \
+ char *: PARSE_LITERAL, \
+ const char **: PARSE_STRING, \
+ char **: PARSE_STRING, \
+ double *: PARSE_DOUBLE, \
+ long *: PARSE_LONG, \
+ bool *: PARSE_BOOL)
+
+#define as_void_star(x) ((void *)x)
+#define strparse(str, ...) \
+ simpleparse(str, sizeof((const void *[]){__VA_ARGS__}) / sizeof(void *), \
+ (parse_type_e[]){MAP_LIST(_parse_type, __VA_ARGS__)}, (void *[]){MAP_LIST(as_void_star, __VA_ARGS__)})
+#define fparse(file, ...) \
+ ({ \
+ char *_file_contents = NULL; \
+ size_t _capacity; \
+ ssize_t _just_read = getdelim(&_file_contents, &_capacity, '\0', file); \
+ const char *_parse_err = _just_read > 0 ? strparse(_file_contents, __VA_ARGS__) : "No such file"; \
+ if (_file_contents) free(_file_contents); \
+ _parse_err; \
+ })
const char *simpleparse(const char *str, int n, parse_type_e types[n], void *destinations[n]);
diff --git a/src/stdlib/siphash-internals.h b/src/stdlib/siphash-internals.h
index b359cea7..c8ec1142 100644
--- a/src/stdlib/siphash-internals.h
+++ b/src/stdlib/siphash-internals.h
@@ -51,24 +51,25 @@ struct siphash {
uint64_t v1;
uint64_t v2;
uint64_t v3;
- uint64_t b;
+ uint64_t b;
};
typedef struct siphash siphash;
-#define ROTATE(x, b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) )
+#define ROTATE(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
-#define HALF_ROUND(a,b,c,d,s,t) \
- a += b; c += d; \
- b = ROTATE(b, s) ^ a; \
- d = ROTATE(d, t) ^ c; \
+#define HALF_ROUND(a, b, c, d, s, t) \
+ a += b; \
+ c += d; \
+ b = ROTATE(b, s) ^ a; \
+ d = ROTATE(d, t) ^ c; \
a = ROTATE(a, 32);
-#define DOUBLE_ROUND(v0,v1,v2,v3) \
- HALF_ROUND(v0,v1,v2,v3,13,16); \
- HALF_ROUND(v2,v1,v0,v3,17,21); \
- HALF_ROUND(v0,v1,v2,v3,13,16); \
- HALF_ROUND(v2,v1,v0,v3,17,21);
+#define DOUBLE_ROUND(v0, v1, v2, v3) \
+ HALF_ROUND(v0, v1, v2, v3, 13, 16); \
+ HALF_ROUND(v2, v1, v0, v3, 17, 21); \
+ HALF_ROUND(v0, v1, v2, v3, 13, 16); \
+ HALF_ROUND(v2, v1, v0, v3, 17, 21);
-MACROLIKE void siphashinit (siphash *sh, size_t src_sz) {
+MACROLIKE void siphashinit(siphash *sh, size_t src_sz) {
const uint64_t k0 = TOMO_HASH_KEY[0];
const uint64_t k1 = TOMO_HASH_KEY[1];
sh->b = (uint64_t)src_sz << 56;
@@ -77,20 +78,20 @@ MACROLIKE void siphashinit (siphash *sh, size_t src_sz) {
sh->v2 = k0 ^ 0x6c7967656e657261ULL;
sh->v3 = k1 ^ 0x7465646279746573ULL;
}
-MACROLIKE void siphashadd64bits (siphash *sh, const uint64_t in) {
+MACROLIKE void siphashadd64bits(siphash *sh, const uint64_t in) {
const uint64_t mi = in;
sh->v3 ^= mi;
- DOUBLE_ROUND(sh->v0,sh->v1,sh->v2,sh->v3);
+ DOUBLE_ROUND(sh->v0, sh->v1, sh->v2, sh->v3);
sh->v0 ^= mi;
}
-MACROLIKE uint64_t siphashfinish_last_part (siphash *sh, uint64_t t) {
+MACROLIKE uint64_t siphashfinish_last_part(siphash *sh, uint64_t t) {
sh->b |= t;
sh->v3 ^= sh->b;
- DOUBLE_ROUND(sh->v0,sh->v1,sh->v2,sh->v3);
+ DOUBLE_ROUND(sh->v0, sh->v1, sh->v2, sh->v3);
sh->v0 ^= sh->b;
sh->v2 ^= 0xff;
- DOUBLE_ROUND(sh->v0,sh->v1,sh->v2,sh->v3);
- DOUBLE_ROUND(sh->v0,sh->v1,sh->v2,sh->v3);
+ DOUBLE_ROUND(sh->v0, sh->v1, sh->v2, sh->v3);
+ DOUBLE_ROUND(sh->v0, sh->v1, sh->v2, sh->v3);
return (sh->v0 ^ sh->v1) ^ (sh->v2 ^ sh->v3);
}
/* This union helps us avoid doing weird things with pointers that can cause old
@@ -99,26 +100,26 @@ MACROLIKE uint64_t siphashfinish_last_part (siphash *sh, uint64_t t) {
union SipHash64_union {
uint64_t u64;
uint32_t u32;
- uint8_t u8[8];
+ uint8_t u8[8];
};
-MACROLIKE uint64_t siphashfinish (siphash *sh, const uint8_t *src, size_t src_sz) {
- union SipHash64_union t = { 0 };
+MACROLIKE uint64_t siphashfinish(siphash *sh, const uint8_t *src, size_t src_sz) {
+ union SipHash64_union t = {0};
switch (src_sz) {
- /* Falls through */
- case 7: t.u8[6] = src[6];
- /* Falls through */
- case 6: t.u8[5] = src[5];
- /* Falls through */
- case 5: t.u8[4] = src[4];
- /* Falls through */
- case 4: t.u8[3] = src[3];
- /* Falls through */
- case 3: t.u8[2] = src[2];
- /* Falls through */
- case 2: t.u8[1] = src[1];
- /* Falls through */
- case 1: t.u8[0] = src[0];
- default: break;
+ /* Falls through */
+ case 7: t.u8[6] = src[6];
+ /* Falls through */
+ case 6: t.u8[5] = src[5];
+ /* Falls through */
+ case 5: t.u8[4] = src[4];
+ /* Falls through */
+ case 4: t.u8[3] = src[3];
+ /* Falls through */
+ case 3: t.u8[2] = src[2];
+ /* Falls through */
+ case 2: t.u8[1] = src[1];
+ /* Falls through */
+ case 1: t.u8[0] = src[0];
+ default: break;
}
return siphashfinish_last_part(sh, t.u64);
}
diff --git a/src/stdlib/siphash.c b/src/stdlib/siphash.c
index 274b3195..9af845e7 100644
--- a/src/stdlib/siphash.c
+++ b/src/stdlib/siphash.c
@@ -5,7 +5,8 @@
#include "siphash.h"
#include "util.h"
-public uint64_t TOMO_HASH_KEY[2] = {23, 42}; // Randomized in tomo_init()
+public
+uint64_t TOMO_HASH_KEY[2] = {23, 42}; // Randomized in tomo_init()
/* <MIT License>
Copyright (c) 2013 Marek Majkowski <marek@popcount.org>
@@ -53,10 +54,10 @@ PUREFUNC public uint64_t siphash24(const uint8_t *src, size_t src_sz) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
#endif
- const uint64_t *in = (uint64_t*)src;
+ const uint64_t *in = (uint64_t *)src;
/* Find largest src_sz evenly divisible by 8 bytes. */
const ptrdiff_t src_sz_nearest_8bits = ((ptrdiff_t)src_sz >> 3) << 3;
- const uint64_t *goal = (uint64_t*)(src + src_sz_nearest_8bits);
+ const uint64_t *goal = (uint64_t *)(src + src_sz_nearest_8bits);
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
@@ -74,7 +75,8 @@ PUREFUNC public uint64_t siphash24(const uint8_t *src, size_t src_sz) {
uint64_t in_64;
memcpy(&in_64, in, sizeof(uint64_t));
siphashadd64bits(&sh, in_64);
- in += 8; src_sz -= 8;
+ in += 8;
+ src_sz -= 8;
}
return siphashfinish(&sh, (uint8_t *)in, src_sz);
}
diff --git a/src/stdlib/siphash.h b/src/stdlib/siphash.h
index 67bad582..3dbef0fd 100644
--- a/src/stdlib/siphash.h
+++ b/src/stdlib/siphash.h
@@ -2,8 +2,8 @@
// An implementation of the SipHash algorithm.
-#include <stdint.h>
#include <stddef.h>
+#include <stdint.h>
#include "util.h"
diff --git a/src/stdlib/stacktrace.c b/src/stdlib/stacktrace.c
index f408d753..9f01a4bf 100644
--- a/src/stdlib/stacktrace.c
+++ b/src/stdlib/stacktrace.c
@@ -1,6 +1,6 @@
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
-#endif
+#endif
#include <dlfcn.h>
#include <err.h>
@@ -19,8 +19,7 @@
extern bool USE_COLOR;
-static void fprint_context(FILE *out, const char *filename, int lineno, int context_before, int context_after)
-{
+static void fprint_context(FILE *out, const char *filename, int lineno, int context_before, int context_after) {
FILE *f = fopen(filename, "r");
if (!f) return;
char *line = NULL;
@@ -33,35 +32,31 @@ static void fprint_context(FILE *out, const char *filename, int lineno, int cont
num_width += 1;
while ((nread = getline(&line, &size, f)) != -1) {
- if (line[strlen(line)-1] == '\n')
- line[strlen(line)-1] = '\0';
+ if (line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = '\0';
if (cur_line >= lineno - context_before) {
int w = 1;
- for (int n = cur_line; n >= 10; n /= 10) w += 1;
+ for (int n = cur_line; n >= 10; n /= 10)
+ w += 1;
if (USE_COLOR) {
fprint(out, cur_line == lineno ? "\033[31;1m>\033[m " : " ", "\033[2m",
- repeated_char(' ', num_width-w),
- cur_line, "\033(0\x78\033(B", cur_line == lineno ? "\033[0;31;1m" : "\033[0m",
- line, "\033[m");
+ repeated_char(' ', num_width - w), cur_line, "\033(0\x78\033(B",
+ cur_line == lineno ? "\033[0;31;1m" : "\033[0m", line, "\033[m");
} else {
- fprint(out, cur_line == lineno ? "> " : " ",
- repeated_char(' ', num_width-w),
- cur_line, "| ", line);
+ fprint(out, cur_line == lineno ? "> " : " ", repeated_char(' ', num_width - w), cur_line, "| ", line);
}
}
cur_line += 1;
- if (cur_line > lineno + context_after)
- break;
+ if (cur_line > lineno + context_after) break;
}
if (line) free(line);
fclose(f);
}
-static void _print_stack_frame(FILE *out, const char *cwd, const char *install_dir, const char *function, const char *filename, int lineno)
-{
+static void _print_stack_frame(FILE *out, const char *cwd, const char *install_dir, const char *function,
+ const char *filename, int lineno) {
if (function == NULL) {
fprint(out, USE_COLOR ? "\033[2m...unknown function...\033[m" : "...unknown function...");
return;
@@ -71,7 +66,7 @@ static void _print_stack_frame(FILE *out, const char *cwd, const char *install_d
if (function[0] == '\0') function = "???";
char *function_display = GC_MALLOC_ATOMIC(strlen(function));
- memcpy(function_display, function, strlen(function)+1);
+ memcpy(function_display, function, strlen(function) + 1);
char *last_dollar = strrchr(function_display, '$');
if (last_dollar) *last_dollar = '\0';
for (char *p = function_display; *p; p++) {
@@ -79,14 +74,12 @@ static void _print_stack_frame(FILE *out, const char *cwd, const char *install_d
}
if (filename) {
- if (strncmp(filename, cwd, strlen(cwd)) == 0)
- filename += strlen(cwd);
+ if (strncmp(filename, cwd, strlen(cwd)) == 0) filename += strlen(cwd);
fprint_inline(out, USE_COLOR ? "\033[1mIn \033[33m" : "In ", function_display, USE_COLOR ? "()\033[37m" : "()");
if (install_dir[0] && strncmp(filename, install_dir, strlen(install_dir)) == 0)
fprint_inline(out, USE_COLOR ? " in library \033[35m" : " in library ", filename, ":", lineno);
- else
- fprint(out, USE_COLOR ? " in \033[35m" : " in ", filename, ":", lineno);
+ else fprint(out, USE_COLOR ? " in \033[35m" : " in ", filename, ":", lineno);
fprint(out, USE_COLOR ? "\033[m" : "");
fprint_context(out, filename, lineno, 3, 1);
} else {
@@ -94,48 +87,41 @@ static void _print_stack_frame(FILE *out, const char *cwd, const char *install_d
}
}
-__attribute__ ((noinline))
-public void print_stacktrace(FILE *out, int offset)
-{
+__attribute__((noinline)) public
+void print_stacktrace(FILE *out, int offset) {
char cwd[PATH_MAX];
- if (getcwd(cwd, sizeof(cwd)) == NULL)
- errx(1, "Path too large!");
+ if (getcwd(cwd, sizeof(cwd)) == NULL) errx(1, "Path too large!");
size_t cwd_len = strlen(cwd);
- if (cwd_len + 2 > sizeof(cwd))
- errx(1, "Path too large!");
+ if (cwd_len + 2 > sizeof(cwd)) errx(1, "Path too large!");
cwd[cwd_len++] = '/';
cwd[cwd_len] = '\0';
- const char *install_dir = TOMO_PREFIX"/share/tomo_"TOMO_VERSION"/installed/";
+ const char *install_dir = TOMO_PREFIX "/share/tomo_" TOMO_VERSION "/installed/";
static void *stack[1024];
- int64_t size = (int64_t)backtrace(stack, sizeof(stack)/sizeof(stack[0]));
+ int64_t size = (int64_t)backtrace(stack, sizeof(stack) / sizeof(stack[0]));
char **strings = backtrace_symbols(stack, size);
bool main_func_onwards = false;
- for (int64_t i = size-1; i > offset; i--) {
+ for (int64_t i = size - 1; i > offset; i--) {
Dl_info info;
- void *call_address = stack[i]-1;
+ void *call_address = stack[i] - 1;
if (dladdr(call_address, &info) && info.dli_fname) {
const char *file = info.dli_fname;
uintptr_t frame_offset = (uintptr_t)call_address - (uintptr_t)info.dli_fbase;
- FILE *fp = popen(String("addr2line -f -e '", file, "' ", (void*)frame_offset, " 2>/dev/null"), "r");
+ FILE *fp = popen(String("addr2line -f -e '", file, "' ", (void *)frame_offset, " 2>/dev/null"), "r");
if (fp) {
const char *function = NULL, *filename = NULL;
long line_num = 0;
if (fparse(fp, &function, "\n", &filename, ":", &line_num) == NULL) {
- if (starts_with(function, "main$"))
- main_func_onwards = true;
- if (main_func_onwards)
- _print_stack_frame(out, cwd, install_dir, function, filename, line_num);
+ if (starts_with(function, "main$")) main_func_onwards = true;
+ if (main_func_onwards) _print_stack_frame(out, cwd, install_dir, function, filename, line_num);
} else {
- if (main_func_onwards)
- _print_stack_frame(out, cwd, install_dir, NULL, NULL, line_num);
+ if (main_func_onwards) _print_stack_frame(out, cwd, install_dir, NULL, NULL, line_num);
}
pclose(fp);
}
} else {
- if (main_func_onwards)
- _print_stack_frame(out, cwd, install_dir, NULL, NULL, 0);
+ if (main_func_onwards) _print_stack_frame(out, cwd, install_dir, NULL, NULL, 0);
}
if (main_func_onwards && i - 1 > offset) fputs("\n", out);
}
diff --git a/src/stdlib/stacktrace.h b/src/stdlib/stacktrace.h
index 828bbe98..36e81bea 100644
--- a/src/stdlib/stacktrace.h
+++ b/src/stdlib/stacktrace.h
@@ -1,5 +1,4 @@
#pragma once
#include <stdio.h>
-__attribute__ ((noinline))
-void print_stacktrace(FILE *out, int offset);
+__attribute__((noinline)) void print_stacktrace(FILE *out, int offset);
diff --git a/src/stdlib/stdlib.c b/src/stdlib/stdlib.c
index 159acdb3..411ce300 100644
--- a/src/stdlib/stdlib.c
+++ b/src/stdlib/stdlib.c
@@ -37,16 +37,17 @@ static ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) {
}
#elif defined(__linux__)
// Use getrandom()
-# include <sys/random.h>
+#include <sys/random.h>
#else
- #error "Unsupported platform for secure random number generation"
+#error "Unsupported platform for secure random number generation"
#endif
-public bool USE_COLOR;
-public Text_t TOMO_VERSION_TEXT = Text(TOMO_VERSION);
+public
+bool USE_COLOR;
+public
+Text_t TOMO_VERSION_TEXT = Text(TOMO_VERSION);
-static _Noreturn void signal_handler(int sig, siginfo_t *info, void *userdata)
-{
+static _Noreturn void signal_handler(int sig, siginfo_t *info, void *userdata) {
(void)info, (void)userdata;
assert(sig == SIGILL);
fflush(stdout);
@@ -58,107 +59,92 @@ static _Noreturn void signal_handler(int sig, siginfo_t *info, void *userdata)
_exit(1);
}
-public void tomo_init(void)
-{
- GC_INIT();
- USE_COLOR = getenv("COLOR") ? strcmp(getenv("COLOR"), "1") == 0 : isatty(STDOUT_FILENO);
- if (getenv("NO_COLOR") && getenv("NO_COLOR")[0] != '\0')
- USE_COLOR = false;
-
- setlocale(LC_ALL, "");
- assert(getrandom(TOMO_HASH_KEY, sizeof(TOMO_HASH_KEY), 0) == sizeof(TOMO_HASH_KEY));
-
- struct sigaction sigact;
- sigact.sa_sigaction = signal_handler;
- sigemptyset(&sigact.sa_mask);
- sigact.sa_flags = 0;
- sigaction(SIGILL, &sigact, (struct sigaction *)NULL);
+public
+void tomo_init(void) {
+ GC_INIT();
+ USE_COLOR = getenv("COLOR") ? strcmp(getenv("COLOR"), "1") == 0 : isatty(STDOUT_FILENO);
+ if (getenv("NO_COLOR") && getenv("NO_COLOR")[0] != '\0') USE_COLOR = false;
+
+ setlocale(LC_ALL, "");
+ assert(getrandom(TOMO_HASH_KEY, sizeof(TOMO_HASH_KEY), 0) == sizeof(TOMO_HASH_KEY));
+
+ struct sigaction sigact;
+ sigact.sa_sigaction = signal_handler;
+ sigemptyset(&sigact.sa_mask);
+ sigact.sa_flags = 0;
+ sigaction(SIGILL, &sigact, (struct sigaction *)NULL);
}
-static bool parse_single_arg(const TypeInfo_t *info, char *arg, void *dest)
-{
+static bool parse_single_arg(const TypeInfo_t *info, char *arg, void *dest) {
if (!arg) return false;
- if (info->tag == OptionalInfo && streq(arg, "none"))
- return true;
+ if (info->tag == OptionalInfo && streq(arg, "none")) return true;
while (info->tag == OptionalInfo)
info = info->OptionalInfo.type;
if (info == &Int$info) {
OptionalInt_t parsed = Int$from_str(arg);
- if (parsed.small != 0)
- *(OptionalInt_t*)dest = parsed;
+ if (parsed.small != 0) *(OptionalInt_t *)dest = parsed;
return parsed.small != 0;
} else if (info == &Int64$info) {
OptionalInt64_t parsed = Int64$parse(Text$from_str(arg), NULL);
- if (!parsed.is_none)
- *(OptionalInt64_t*)dest = parsed;
+ if (!parsed.is_none) *(OptionalInt64_t *)dest = parsed;
return !parsed.is_none;
} else if (info == &Int32$info) {
OptionalInt32_t parsed = Int32$parse(Text$from_str(arg), NULL);
- if (!parsed.is_none)
- *(OptionalInt32_t*)dest = parsed;
+ if (!parsed.is_none) *(OptionalInt32_t *)dest = parsed;
return !parsed.is_none;
} else if (info == &Int16$info) {
OptionalInt16_t parsed = Int16$parse(Text$from_str(arg), NULL);
- if (!parsed.is_none)
- *(OptionalInt16_t*)dest = parsed;
+ if (!parsed.is_none) *(OptionalInt16_t *)dest = parsed;
return !parsed.is_none;
} else if (info == &Int8$info) {
OptionalInt8_t parsed = Int8$parse(Text$from_str(arg), NULL);
- if (!parsed.is_none)
- *(OptionalInt8_t*)dest = parsed;
+ if (!parsed.is_none) *(OptionalInt8_t *)dest = parsed;
return !parsed.is_none;
} else if (info == &Bool$info) {
OptionalBool_t parsed = Bool$parse(Text$from_str(arg), NULL);
- if (parsed != NONE_BOOL)
- *(OptionalBool_t*)dest = parsed;
+ if (parsed != NONE_BOOL) *(OptionalBool_t *)dest = parsed;
return parsed != NONE_BOOL;
} else if (info == &Num$info) {
OptionalNum_t parsed = Num$parse(Text$from_str(arg), NULL);
- if (!isnan(parsed))
- *(OptionalNum_t*)dest = parsed;
+ if (!isnan(parsed)) *(OptionalNum_t *)dest = parsed;
return !isnan(parsed);
} else if (info == &Num32$info) {
OptionalNum32_t parsed = Num32$parse(Text$from_str(arg), NULL);
- if (!isnan(parsed))
- *(OptionalNum32_t*)dest = parsed;
+ if (!isnan(parsed)) *(OptionalNum32_t *)dest = parsed;
return !isnan(parsed);
} else if (info == &Path$info) {
- *(OptionalPath_t*)dest = Path$from_str(arg);
+ *(OptionalPath_t *)dest = Path$from_str(arg);
return true;
} else if (info->tag == TextInfo) {
- *(OptionalText_t*)dest = Text$from_str(arg);
+ *(OptionalText_t *)dest = Text$from_str(arg);
return true;
} else if (info->tag == EnumInfo) {
for (int t = 0; t < info->EnumInfo.num_tags; t++) {
NamedType_t named = info->EnumInfo.tags[t];
size_t len = strlen(named.name);
if (strncmp(arg, named.name, len) == 0 && (arg[len] == '\0' || arg[len] == ':')) {
- *(int32_t*)dest = (t + 1);
+ *(int32_t *)dest = (t + 1);
// Simple tag (no associated data):
if (!named.type || (named.type->tag == StructInfo && named.type->StructInfo.num_fields == 0))
return true;
// Single-argument tag:
- if (arg[len] != ':')
- print_err("Invalid value for ", t, ".", named.name, ": ", arg);
+ if (arg[len] != ':') print_err("Invalid value for ", t, ".", named.name, ": ", arg);
size_t offset = sizeof(int32_t);
if (named.type->align > 0 && offset % (size_t)named.type->align > 0)
offset += (size_t)named.type->align - (offset % (size_t)named.type->align);
- if (!parse_single_arg(named.type, arg + len + 1, dest + offset))
- return false;
+ if (!parse_single_arg(named.type, arg + len + 1, dest + offset)) return false;
return true;
}
}
print_err("Invalid value for ", info->EnumInfo.name, ": ", arg);
} else if (info->tag == StructInfo) {
- if (info->StructInfo.num_fields == 0)
- return true;
- else if (info->StructInfo.num_fields == 1)
- return parse_single_arg(info->StructInfo.fields[0].type, arg, dest);
+ if (info->StructInfo.num_fields == 0) return true;
+ else if (info->StructInfo.num_fields == 1) return parse_single_arg(info->StructInfo.fields[0].type, arg, dest);
Text_t t = generic_as_text(NULL, false, info);
print_err("Unsupported multi-argument struct type for argument parsing: ", t);
@@ -173,41 +159,36 @@ static bool parse_single_arg(const TypeInfo_t *info, char *arg, void *dest)
return false;
}
-static List_t parse_list(const TypeInfo_t *item_info, int n, char *args[])
-{
+static List_t parse_list(const TypeInfo_t *item_info, int n, char *args[]) {
int64_t padded_size = item_info->size;
if ((padded_size % item_info->align) > 0)
padded_size = padded_size + item_info->align - (padded_size % item_info->align);
List_t items = {
- .stride=padded_size,
- .length=n,
- .data=GC_MALLOC((size_t)(padded_size*n)),
+ .stride = padded_size,
+ .length = n,
+ .data = GC_MALLOC((size_t)(padded_size * n)),
};
for (int i = 0; i < n; i++) {
- bool success = parse_single_arg(item_info, args[i], items.data + items.stride*i);
- if (!success)
- print_err("Couldn't parse argument: ", args[i]);
+ bool success = parse_single_arg(item_info, args[i], items.data + items.stride * i);
+ if (!success) print_err("Couldn't parse argument: ", args[i]);
}
return items;
}
// Arguments take the form key=value, with a guarantee that there is an '='
-static Table_t parse_table(const TypeInfo_t *table, int n, char *args[])
-{
+static Table_t parse_table(const TypeInfo_t *table, int n, char *args[]) {
const TypeInfo_t *key = table->TableInfo.key, *value = table->TableInfo.value;
int64_t padded_size = key->size;
- if ((padded_size % value->align) > 0)
- padded_size = padded_size + value->align - (padded_size % value->align);
+ if ((padded_size % value->align) > 0) padded_size = padded_size + value->align - (padded_size % value->align);
int64_t value_offset = padded_size;
padded_size += value->size;
- if ((padded_size % key->align) > 0)
- padded_size = padded_size + key->align - (padded_size % key->align);
+ if ((padded_size % key->align) > 0) padded_size = padded_size + key->align - (padded_size % key->align);
List_t entries = {
- .stride=padded_size,
- .length=n,
- .data=GC_MALLOC((size_t)(padded_size*n)),
+ .stride = padded_size,
+ .length = n,
+ .data = GC_MALLOC((size_t)(padded_size * n)),
};
for (int i = 0; i < n; i++) {
char *key_arg = args[i];
@@ -216,13 +197,11 @@ static Table_t parse_table(const TypeInfo_t *table, int n, char *args[])
char *value_arg = equals + 1;
*equals = '\0';
- bool success = parse_single_arg(key, key_arg, entries.data + entries.stride*i);
- if (!success)
- print_err("Couldn't parse table key: ", key_arg);
+ bool success = parse_single_arg(key, key_arg, entries.data + entries.stride * i);
+ if (!success) print_err("Couldn't parse table key: ", key_arg);
- success = parse_single_arg(value, value_arg, entries.data + entries.stride*i + value_offset);
- if (!success)
- print_err("Couldn't parse table value: ", value_arg);
+ success = parse_single_arg(value, value_arg, entries.data + entries.stride * i + value_offset);
+ if (!success) print_err("Couldn't parse table value: ", value_arg);
*equals = '=';
}
@@ -233,13 +212,14 @@ static Table_t parse_table(const TypeInfo_t *table, int n, char *args[])
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstack-protector"
#endif
-public void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help, const char *version, int spec_len, cli_arg_t spec[spec_len])
-{
+public
+void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help, const char *version, int spec_len,
+ cli_arg_t spec[spec_len]) {
bool populated_args[spec_len];
bool used_args[argc];
memset(populated_args, 0, sizeof(populated_args));
memset(used_args, 0, sizeof(used_args));
- for (int i = 1; i < argc; ) {
+ for (int i = 1; i < argc;) {
if (argv[i][0] == '-' && argv[i][1] == '-') {
if (argv[i][2] == '\0') { // "--" signals the rest of the arguments are literal
used_args[i] = true;
@@ -252,58 +232,54 @@ public void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help,
while (non_opt_type->tag == OptionalInfo)
non_opt_type = non_opt_type->OptionalInfo.type;
- if (non_opt_type == &Bool$info
- && strncmp(argv[i], "--no-", strlen("--no-")) == 0
+ if (non_opt_type == &Bool$info && strncmp(argv[i], "--no-", strlen("--no-")) == 0
&& strcmp(argv[i] + strlen("--no-"), spec[s].name) == 0) {
- *(OptionalBool_t*)spec[s].dest = false;
+ *(OptionalBool_t *)spec[s].dest = false;
populated_args[s] = true;
used_args[i] = true;
goto next_arg;
}
- if (strncmp(spec[s].name, argv[i] + 2, strlen(spec[s].name)) != 0)
- continue;
+ if (strncmp(spec[s].name, argv[i] + 2, strlen(spec[s].name)) != 0) continue;
- char after_name = argv[i][2+strlen(spec[s].name)];
+ char after_name = argv[i][2 + strlen(spec[s].name)];
if (after_name == '\0') { // --foo val
used_args[i] = true;
if (non_opt_type->tag == ListInfo) {
int num_args = 0;
while (i + 1 + num_args < argc) {
- if (argv[i+1+num_args][0] == '-')
- break;
- used_args[i+1+num_args] = true;
+ if (argv[i + 1 + num_args][0] == '-') break;
+ used_args[i + 1 + num_args] = true;
num_args += 1;
}
populated_args[s] = true;
- *(OptionalList_t*)spec[s].dest = parse_list(non_opt_type->ListInfo.item, num_args, &argv[i+1]);
+ *(OptionalList_t *)spec[s].dest =
+ parse_list(non_opt_type->ListInfo.item, num_args, &argv[i + 1]);
} else if (non_opt_type->tag == TableInfo) {
int num_args = 0;
while (i + 1 + num_args < argc) {
- if (argv[i+1+num_args][0] == '-' || !strchr(argv[i+1+num_args], '='))
- break;
- used_args[i+1+num_args] = true;
+ if (argv[i + 1 + num_args][0] == '-' || !strchr(argv[i + 1 + num_args], '=')) break;
+ used_args[i + 1 + num_args] = true;
num_args += 1;
}
populated_args[s] = true;
- *(OptionalTable_t*)spec[s].dest = parse_table(non_opt_type, num_args, &argv[i+1]);
+ *(OptionalTable_t *)spec[s].dest = parse_table(non_opt_type, num_args, &argv[i + 1]);
} else if (non_opt_type == &Bool$info) { // --flag
populated_args[s] = true;
- *(OptionalBool_t*)spec[s].dest = true;
+ *(OptionalBool_t *)spec[s].dest = true;
} else {
- if (i + 1 >= argc)
- print_err("Missing argument: ", argv[i], "\n", usage);
- used_args[i+1] = true;
- populated_args[s] = parse_single_arg(spec[s].type, argv[i+1], spec[s].dest);
+ if (i + 1 >= argc) print_err("Missing argument: ", argv[i], "\n", usage);
+ used_args[i + 1] = true;
+ populated_args[s] = parse_single_arg(spec[s].type, argv[i + 1], spec[s].dest);
if (!populated_args[s])
- print_err("Couldn't parse argument: ", argv[i], " ", argv[i+1], "\n", usage);
+ print_err("Couldn't parse argument: ", argv[i], " ", argv[i + 1], "\n", usage);
}
goto next_arg;
} else if (after_name == '=') { // --foo=val
used_args[i] = true;
- populated_args[s] = parse_single_arg(spec[s].type, 2 + argv[i] + strlen(spec[s].name) + 1, spec[s].dest);
- if (!populated_args[s])
- print_err("Couldn't parse argument: ", argv[i], "\n", usage);
+ populated_args[s] =
+ parse_single_arg(spec[s].type, 2 + argv[i] + strlen(spec[s].name) + 1, spec[s].dest);
+ if (!populated_args[s]) print_err("Couldn't parse argument: ", argv[i], "\n", usage);
goto next_arg;
} else {
continue;
@@ -324,8 +300,7 @@ public void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help,
for (char *f = argv[i] + 1; *f; f++) {
char flag[] = {'-', *f, 0};
for (int s = 0; s < spec_len; s++) {
- if (spec[s].name[0] != *f || strlen(spec[s].name) > 1)
- continue;
+ if (spec[s].name[0] != *f || strlen(spec[s].name) > 1) continue;
const TypeInfo_t *non_opt_type = spec[s].type;
while (non_opt_type->tag == OptionalInfo)
@@ -335,32 +310,31 @@ public void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help,
if (f[1]) print_err("No value provided for ", flag, "\n", usage);
int num_args = 0;
while (i + 1 + num_args < argc) {
- if (argv[i+1+num_args][0] == '-')
- break;
- used_args[i+1+num_args] = true;
+ if (argv[i + 1 + num_args][0] == '-') break;
+ used_args[i + 1 + num_args] = true;
num_args += 1;
}
populated_args[s] = true;
- *(OptionalList_t*)spec[s].dest = parse_list(non_opt_type->ListInfo.item, num_args, &argv[i+1]);
+ *(OptionalList_t *)spec[s].dest =
+ parse_list(non_opt_type->ListInfo.item, num_args, &argv[i + 1]);
} else if (non_opt_type->tag == TableInfo) {
int num_args = 0;
while (i + 1 + num_args < argc) {
- if (argv[i+1+num_args][0] == '-' || !strchr(argv[i+1+num_args], '='))
- break;
- used_args[i+1+num_args] = true;
+ if (argv[i + 1 + num_args][0] == '-' || !strchr(argv[i + 1 + num_args], '=')) break;
+ used_args[i + 1 + num_args] = true;
num_args += 1;
}
populated_args[s] = true;
- *(OptionalTable_t*)spec[s].dest = parse_table(non_opt_type, num_args, &argv[i+1]);
+ *(OptionalTable_t *)spec[s].dest = parse_table(non_opt_type, num_args, &argv[i + 1]);
} else if (non_opt_type == &Bool$info) { // -f
populated_args[s] = true;
- *(OptionalBool_t*)spec[s].dest = true;
+ *(OptionalBool_t *)spec[s].dest = true;
} else {
- if (f[1] || i+1 >= argc) print_err("No value provided for ", flag, "\n", usage);
- used_args[i+1] = true;
- populated_args[s] = parse_single_arg(spec[s].type, argv[i+1], spec[s].dest);
+ if (f[1] || i + 1 >= argc) print_err("No value provided for ", flag, "\n", usage);
+ used_args[i + 1] = true;
+ populated_args[s] = parse_single_arg(spec[s].type, argv[i + 1], spec[s].dest);
if (!populated_args[s])
- print_err("Couldn't parse argument: ", argv[i], " ", argv[i+1], "\n", usage);
+ print_err("Couldn't parse argument: ", argv[i], " ", argv[i + 1], "\n", usage);
}
goto next_flag;
}
@@ -370,7 +344,7 @@ public void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help,
exit(0);
}
print_err("Unrecognized flag: ", flag, "\n", usage);
- next_flag:;
+ next_flag:;
}
} else {
// Handle positional args later
@@ -378,7 +352,7 @@ public void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help,
continue;
}
- next_arg:
+ next_arg:
while (used_args[i] && i < argc)
i += 1;
}
@@ -393,10 +367,9 @@ public void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help,
if (used_args[i]) continue;
while (populated_args[s]) {
- next_non_bool_flag:
+ next_non_bool_flag:
++s;
- if (s >= spec_len)
- print_err("Extra argument: ", argv[i], "\n", usage);
+ if (s >= spec_len) print_err("Extra argument: ", argv[i], "\n", usage);
}
const TypeInfo_t *non_opt_type = spec[s].type;
@@ -404,45 +377,40 @@ public void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help,
non_opt_type = non_opt_type->OptionalInfo.type;
// You can't specify boolean flags positionally
- if (non_opt_type == &Bool$info)
- goto next_non_bool_flag;
+ if (non_opt_type == &Bool$info) goto next_non_bool_flag;
if (non_opt_type->tag == ListInfo) {
int num_args = 0;
while (i + num_args < argc) {
- if (!ignore_dashes && (argv[i+num_args][0] == '-' && !isdigit(argv[i+num_args][1])))
- break;
- used_args[i+num_args] = true;
+ if (!ignore_dashes && (argv[i + num_args][0] == '-' && !isdigit(argv[i + num_args][1]))) break;
+ used_args[i + num_args] = true;
num_args += 1;
}
populated_args[s] = true;
- *(OptionalList_t*)spec[s].dest = parse_list(non_opt_type->ListInfo.item, num_args, &argv[i]);
+ *(OptionalList_t *)spec[s].dest = parse_list(non_opt_type->ListInfo.item, num_args, &argv[i]);
} else if (non_opt_type->tag == TableInfo) {
int num_args = 0;
while (i + num_args < argc) {
- if ((argv[i+num_args][0] == '-' && !isdigit(argv[i+num_args][1])) || !strchr(argv[i+num_args], '='))
+ if ((argv[i + num_args][0] == '-' && !isdigit(argv[i + num_args][1]))
+ || !strchr(argv[i + num_args], '='))
break;
- used_args[i+num_args] = true;
+ used_args[i + num_args] = true;
num_args += 1;
}
populated_args[s] = true;
- *(OptionalTable_t*)spec[s].dest = parse_table(non_opt_type, num_args, &argv[i]);
+ *(OptionalTable_t *)spec[s].dest = parse_table(non_opt_type, num_args, &argv[i]);
} else {
populated_args[s] = parse_single_arg(spec[s].type, argv[i], spec[s].dest);
}
- if (!populated_args[s])
- print_err("Invalid value for ", spec[s].name, ": ", argv[i], "\n", usage);
+ if (!populated_args[s]) print_err("Invalid value for ", spec[s].name, ": ", argv[i], "\n", usage);
}
for (int s = 0; s < spec_len; s++) {
if (!populated_args[s] && spec[s].required) {
- if (spec[s].type->tag == ListInfo)
- *(OptionalList_t*)spec[s].dest = (List_t){};
- else if (spec[s].type->tag == TableInfo)
- *(OptionalTable_t*)spec[s].dest = (Table_t){};
- else
- print_err("The required argument '", spec[s].name, "' was not provided\n", usage);
+ if (spec[s].type->tag == ListInfo) *(OptionalList_t *)spec[s].dest = (List_t){};
+ else if (spec[s].type->tag == TableInfo) *(OptionalTable_t *)spec[s].dest = (Table_t){};
+ else print_err("The required argument '", spec[s].name, "' was not provided\n", usage);
}
}
}
@@ -450,24 +418,18 @@ public void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help,
#pragma GCC diagnostic pop
#endif
-public _Noreturn void fail_text(Text_t message)
-{
- fail(message);
-}
+public
+_Noreturn void fail_text(Text_t message) { fail(message); }
-public Text_t builtin_last_err()
-{
- return Text$from_str(strerror(errno));
-}
+public
+Text_t builtin_last_err() { return Text$from_str(strerror(errno)); }
static int _inspect_depth = 0;
static file_t *file = NULL;
-__attribute__((nonnull))
-public void start_inspect(const char *filename, int64_t start, int64_t end)
-{
- if (file == NULL || strcmp(file->filename, filename) != 0)
- file = load_file(filename);
+__attribute__((nonnull)) public
+void start_inspect(const char *filename, int64_t start, int64_t end) {
+ if (file == NULL || strcmp(file->filename, filename) != 0) file = load_file(filename);
if (file) {
size_t first_line_len = strcspn(file->text + start, "\r\n");
@@ -476,26 +438,25 @@ public void start_inspect(const char *filename, int64_t start, int64_t end)
int64_t line_num = get_line_number(file, file->text + start);
if (USE_COLOR) {
- print(repeated_char(' ', 3*_inspect_depth), "\x1b[33;1m>> \x1b[m",
- string_slice(file->text + start, first_line_len),
- " ", repeated_char(' ', MAX(0, 35-(int64_t)first_line_len-3*_inspect_depth)),
- "\x1b[32;2m[", file_base, ":", line_num, "]\x1b[m");
+ print(repeated_char(' ', 3 * _inspect_depth), "\x1b[33;1m>> \x1b[m",
+ string_slice(file->text + start, first_line_len), " ",
+ repeated_char(' ', MAX(0, 35 - (int64_t)first_line_len - 3 * _inspect_depth)), "\x1b[32;2m[",
+ file_base, ":", line_num, "]\x1b[m");
} else {
- print(repeated_char(' ', 3*_inspect_depth), ">> ",
- string_slice(file->text + start, first_line_len),
- " ", repeated_char(' ', MAX(0, 35-(int64_t)first_line_len-3*_inspect_depth)),
- "[", file_base, ":", line_num, "]");
+ print(repeated_char(' ', 3 * _inspect_depth), ">> ", string_slice(file->text + start, first_line_len),
+ " ", repeated_char(' ', MAX(0, 35 - (int64_t)first_line_len - 3 * _inspect_depth)), "[", file_base,
+ ":", line_num, "]");
}
// For multi-line expressions, dedent each and print it on a new line with ".. " in front:
if (end > start + (int64_t)first_line_len) {
const char *line_start = get_line(file, line_num);
int64_t indent_len = (int64_t)strspn(line_start, " \t");
- for (const char *line = file->text + start + first_line_len; line < file->text + end; line += strcspn(line, "\r\n")) {
+ for (const char *line = file->text + start + first_line_len; line < file->text + end;
+ line += strcspn(line, "\r\n")) {
line += strspn(line, "\r\n");
- if ((int64_t)strspn(line, " \t") >= indent_len)
- line += indent_len;
- print(repeated_char(' ', 3*_inspect_depth), USE_COLOR ? "\x1b[33m.. " : ".. ",
+ if ((int64_t)strspn(line, " \t") >= indent_len) line += indent_len;
+ print(repeated_char(' ', 3 * _inspect_depth), USE_COLOR ? "\x1b[33m.. " : ".. ",
string_slice(line, strcspn(line, "\r\n")));
}
}
@@ -503,23 +464,24 @@ public void start_inspect(const char *filename, int64_t start, int64_t end)
_inspect_depth += 1;
}
-public void end_inspect(const void *expr, const TypeInfo_t *type)
-{
+public
+void end_inspect(const void *expr, const TypeInfo_t *type) {
_inspect_depth -= 1;
if (type && type->metamethods.as_text) {
Text_t expr_text = generic_as_text(expr, USE_COLOR, type);
Text_t type_name = generic_as_text(NULL, false, type);
- for (int i = 0; i < 3*_inspect_depth; i++) fputc(' ', stdout);
- fprint(stdout, USE_COLOR ? "\x1b[33;1m=\x1b[0m " : "= ", expr_text, USE_COLOR ? " \x1b[2m: \x1b[36m" : " : ", type_name, USE_COLOR ? "\033[m" : "");
+ for (int i = 0; i < 3 * _inspect_depth; i++)
+ fputc(' ', stdout);
+ fprint(stdout, USE_COLOR ? "\x1b[33;1m=\x1b[0m " : "= ", expr_text, USE_COLOR ? " \x1b[2m: \x1b[36m" : " : ",
+ type_name, USE_COLOR ? "\033[m" : "");
}
}
-__attribute__((nonnull))
-public void test_value(const char *filename, int64_t start, int64_t end, const void *expr, const void *expected, const TypeInfo_t *type)
-{
- if (generic_equal(expr, expected, type))
- return;
+__attribute__((nonnull)) public
+void test_value(const char *filename, int64_t start, int64_t end, const void *expr, const void *expected,
+ const TypeInfo_t *type) {
+ if (generic_equal(expr, expected, type)) return;
print_stacktrace(stderr, 2);
fprint(stderr, "");
@@ -532,38 +494,42 @@ public void test_value(const char *filename, int64_t start, int64_t end, const v
Text_t expr_text = generic_as_text(expr, USE_COLOR, type);
Text_t expected_text = generic_as_text(expected, USE_COLOR, type);
if (USE_COLOR) {
- fprint(stderr,
- "\n\x1b[31;7m ==================== TEST FAILED ==================== \x1b[0;1m\n\n"
- "You expected: \x1b[m", expected_text, "\x1b[0m\n"
- "\x1b[1m But I got:\x1b[m ", expr_text, "\n");
+ fprint(stderr,
+ "\n\x1b[31;7m ==================== TEST FAILED ==================== \x1b[0;1m\n\n"
+ "You expected: \x1b[m",
+ expected_text,
+ "\x1b[0m\n"
+ "\x1b[1m But I got:\x1b[m ",
+ expr_text, "\n");
} else {
- fprint(stderr,
- "\n==================== TEST FAILED ====================\n\n"
- "You expected: ", expected_text, "\n"
- " But I got: ", expr_text, "\n");
+ fprint(stderr,
+ "\n==================== TEST FAILED ====================\n\n"
+ "You expected: ",
+ expected_text,
+ "\n"
+ " But I got: ",
+ expr_text, "\n");
}
fflush(stderr);
raise(SIGABRT);
}
-public void say(Text_t text, bool newline)
-{
+public
+void say(Text_t text, bool newline) {
Text$print(stdout, text);
- if (newline)
- fputc('\n', stdout);
+ if (newline) fputc('\n', stdout);
fflush(stdout);
}
-public _Noreturn void tomo_exit(Text_t text, int32_t status)
-{
- if (text.length > 0)
- print(text);
+public
+_Noreturn void tomo_exit(Text_t text, int32_t status) {
+ if (text.length > 0) print(text);
_exit(status);
}
-public OptionalText_t ask(Text_t prompt, bool bold, bool force_tty)
-{
+public
+OptionalText_t ask(Text_t prompt, bool bold, bool force_tty) {
OptionalText_t ret = NONE_TEXT;
FILE *out = stdout;
FILE *in = stdin;
@@ -597,8 +563,8 @@ public OptionalText_t ask(Text_t prompt, bool bold, bool force_tty)
goto cleanup;
}
- if (length > 0 && line[length-1] == '\n') {
- line[length-1] = '\0';
+ if (length > 0 && line[length - 1] == '\n') {
+ line[length - 1] = '\0';
--length;
}
@@ -607,14 +573,14 @@ public OptionalText_t ask(Text_t prompt, bool bold, bool force_tty)
ret = Text$from_strn(gc_input, (size_t)(length));
- cleanup:
+cleanup:
if (out && out != stdout) fclose(out);
if (in && in != stdin) fclose(in);
return ret;
}
-public bool pop_flag(char **argv, int *i, const char *flag, Text_t *result)
-{
+public
+bool pop_flag(char **argv, int *i, const char *flag, Text_t *result) {
if (argv[*i][0] != '-' || argv[*i][1] != '-') {
return false;
} else if (streq(argv[*i] + 2, flag)) {
@@ -637,23 +603,21 @@ public bool pop_flag(char **argv, int *i, const char *flag, Text_t *result)
}
}
-public void sleep_num(double seconds)
-{
+public
+void sleep_num(double seconds) {
struct timespec ts;
ts.tv_sec = (time_t)seconds;
ts.tv_nsec = (long)((seconds - (double)ts.tv_sec) * 1e9);
nanosleep(&ts, NULL);
}
-public OptionalText_t getenv_text(Text_t name)
-{
+public
+OptionalText_t getenv_text(Text_t name) {
const char *val = getenv(Text$as_c_string(name));
return val ? Text$from_str(val) : NONE_TEXT;
}
-public void setenv_text(Text_t name, Text_t value)
-{
- setenv(Text$as_c_string(name), Text$as_c_string(value), 1);
-}
+public
+void setenv_text(Text_t name, Text_t value) { setenv(Text$as_c_string(name), Text$as_c_string(value), 1); }
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/stdlib.h b/src/stdlib/stdlib.h
index 8ac35f72..c676beb1 100644
--- a/src/stdlib/stdlib.h
+++ b/src/stdlib/stdlib.h
@@ -23,66 +23,72 @@ typedef struct {
} cli_arg_t;
void tomo_init(void);
-void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help, const char *version, int spec_len, cli_arg_t spec[spec_len]);
-#define tomo_parse_args(argc, argv, usage, help, version, ...) \
- _tomo_parse_args(argc, argv, usage, help, version, sizeof((cli_arg_t[]){__VA_ARGS__})/sizeof(cli_arg_t), (cli_arg_t[]){__VA_ARGS__})
+void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help, const char *version, int spec_len,
+ cli_arg_t spec[spec_len]);
+#define tomo_parse_args(argc, argv, usage, help, version, ...) \
+ _tomo_parse_args(argc, argv, usage, help, version, sizeof((cli_arg_t[]){__VA_ARGS__}) / sizeof(cli_arg_t), \
+ (cli_arg_t[]){__VA_ARGS__})
-#define fail(...) ({ \
- fflush(stdout); \
- if (USE_COLOR) fputs("\x1b[31;7m ==================== ERROR ==================== \033[m\n\n", stderr); \
- else fputs("==================== ERROR ====================\n\n", stderr); \
- print_stacktrace(stderr, 1); \
- if (USE_COLOR) fputs("\n\x1b[31;1m", stderr); \
- else fputs("\n", stderr); \
- fprint_inline(stderr, "Error: ", __VA_ARGS__); \
- if (USE_COLOR) fputs("\x1b[m\n", stderr); \
- else fputs("\n", stderr); \
- fflush(stderr); \
- raise(SIGABRT); \
- _exit(1); \
-})
+#define fail(...) \
+ ({ \
+ fflush(stdout); \
+ if (USE_COLOR) fputs("\x1b[31;7m ==================== ERROR ==================== \033[m\n\n", stderr); \
+ else fputs("==================== ERROR ====================\n\n", stderr); \
+ print_stacktrace(stderr, 1); \
+ if (USE_COLOR) fputs("\n\x1b[31;1m", stderr); \
+ else fputs("\n", stderr); \
+ fprint_inline(stderr, "Error: ", __VA_ARGS__); \
+ if (USE_COLOR) fputs("\x1b[m\n", stderr); \
+ else fputs("\n", stderr); \
+ fflush(stderr); \
+ raise(SIGABRT); \
+ _exit(1); \
+ })
-#define fail_source(filename, start, end, ...) ({ \
- fflush(stdout); \
- if (USE_COLOR) fputs("\x1b[31;7m ==================== ERROR ==================== \n\n\x1b[0;1m", stderr); \
- else fputs("==================== ERROR ====================\n\n", stderr); \
- print_stacktrace(stderr, 0); \
- fputs("\n", stderr); \
- if (USE_COLOR) fputs("\x1b[31;1m", stderr); \
- fprint_inline(stderr, __VA_ARGS__); \
- file_t *_file = (filename) ? load_file(filename) : NULL; \
- if ((filename) && _file) { \
- fputs("\n", stderr); \
- highlight_error(_file, _file->text+(start), _file->text+(end), "\x1b[31;1m", 1, USE_COLOR); \
- } \
- if (USE_COLOR) fputs("\x1b[m", stderr); \
- fflush(stderr); \
- raise(SIGABRT); \
- _exit(1); \
-})
+#define fail_source(filename, start, end, ...) \
+ ({ \
+ fflush(stdout); \
+ if (USE_COLOR) fputs("\x1b[31;7m ==================== ERROR ==================== \n\n\x1b[0;1m", stderr); \
+ else fputs("==================== ERROR ====================\n\n", stderr); \
+ print_stacktrace(stderr, 0); \
+ fputs("\n", stderr); \
+ if (USE_COLOR) fputs("\x1b[31;1m", stderr); \
+ fprint_inline(stderr, __VA_ARGS__); \
+ file_t *_file = (filename) ? load_file(filename) : NULL; \
+ if ((filename) && _file) { \
+ fputs("\n", stderr); \
+ highlight_error(_file, _file->text + (start), _file->text + (end), "\x1b[31;1m", 1, USE_COLOR); \
+ } \
+ if (USE_COLOR) fputs("\x1b[m", stderr); \
+ fflush(stderr); \
+ raise(SIGABRT); \
+ _exit(1); \
+ })
_Noreturn void fail_text(Text_t message);
Text_t builtin_last_err();
-__attribute__((nonnull))
-void start_inspect(const char *filename, int64_t start, int64_t end);
+__attribute__((nonnull)) void start_inspect(const char *filename, int64_t start, int64_t end);
void end_inspect(const void *expr, const TypeInfo_t *type);
-#define inspect(type, expr, typeinfo, start, end) {\
- start_inspect(__SOURCE_FILE__, start, end); \
- type _expr = expr; \
- end_inspect(&_expr, typeinfo); \
-}
-#define inspect_void(expr, typeinfo, start, end) {\
- start_inspect(__SOURCE_FILE__, start, end); \
- expr; \
- end_inspect(NULL, typeinfo); \
-}
-__attribute__((nonnull))
-void test_value(const char *filename, int64_t start, int64_t end, const void *expr, const void *expected, const TypeInfo_t *type);
-#define test(type, expr, expected, typeinfo, start, end) {\
- type _expr = expr; \
- type _expected = expected; \
- test_value(__SOURCE_FILE__, start, end, &_expr, &_expected, typeinfo); \
-}
+#define inspect(type, expr, typeinfo, start, end) \
+ { \
+ start_inspect(__SOURCE_FILE__, start, end); \
+ type _expr = expr; \
+ end_inspect(&_expr, typeinfo); \
+ }
+#define inspect_void(expr, typeinfo, start, end) \
+ { \
+ start_inspect(__SOURCE_FILE__, start, end); \
+ expr; \
+ end_inspect(NULL, typeinfo); \
+ }
+__attribute__((nonnull)) void test_value(const char *filename, int64_t start, int64_t end, const void *expr,
+ const void *expected, const TypeInfo_t *type);
+#define test(type, expr, expected, typeinfo, start, end) \
+ { \
+ type _expr = expr; \
+ type _expected = expected; \
+ test_value(__SOURCE_FILE__, start, end, &_expr, &_expected, typeinfo); \
+ }
void say(Text_t text, bool newline);
Text_t ask(Text_t prompt, bool bold, bool force_tty);
diff --git a/src/stdlib/structs.c b/src/stdlib/structs.c
index 5d6b2319..d2300b74 100644
--- a/src/stdlib/structs.c
+++ b/src/stdlib/structs.c
@@ -13,13 +13,10 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstack-protector"
#endif
-PUREFUNC public uint64_t Struct$hash(const void *obj, const TypeInfo_t *type)
-{
- if (type->StructInfo.num_fields == 0)
- return 0;
+PUREFUNC public uint64_t Struct$hash(const void *obj, const TypeInfo_t *type) {
+ if (type->StructInfo.num_fields == 0) return 0;
- if (type->StructInfo.num_fields == 1)
- return generic_hash(obj, type->StructInfo.fields[0].type);
+ if (type->StructInfo.num_fields == 1) return generic_hash(obj, type->StructInfo.fields[0].type);
uint64_t field_hashes[type->StructInfo.num_fields];
ptrdiff_t byte_offset = 0;
@@ -27,7 +24,7 @@ PUREFUNC public uint64_t Struct$hash(const void *obj, const TypeInfo_t *type)
for (int i = 0; i < type->StructInfo.num_fields; i++) {
NamedType_t field = type->StructInfo.fields[i];
if (field.type == &Bool$info) {
- bool b = ((*(char*)(obj + byte_offset)) >> bit_offset) & 0x1;
+ bool b = ((*(char *)(obj + byte_offset)) >> bit_offset) & 0x1;
field_hashes[i] = (uint32_t)b;
bit_offset += 1;
if (bit_offset >= 8) {
@@ -45,34 +42,29 @@ PUREFUNC public uint64_t Struct$hash(const void *obj, const TypeInfo_t *type)
byte_offset += field.type->size;
}
}
- return siphash24((void*)field_hashes, sizeof(field_hashes));
+ return siphash24((void *)field_hashes, sizeof(field_hashes));
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
-PUREFUNC public uint64_t PackedData$hash(const void *obj, const TypeInfo_t *type)
-{
- if (type->StructInfo.num_fields == 0)
- return 0;
+PUREFUNC public uint64_t PackedData$hash(const void *obj, const TypeInfo_t *type) {
+ if (type->StructInfo.num_fields == 0) return 0;
return siphash24(obj, (size_t)type->size);
}
-PUREFUNC public int32_t Struct$compare(const void *x, const void *y, const TypeInfo_t *type)
-{
- if (x == y)
- return 0;
+PUREFUNC public int32_t Struct$compare(const void *x, const void *y, const TypeInfo_t *type) {
+ if (x == y) return 0;
ptrdiff_t byte_offset = 0;
ptrdiff_t bit_offset = 0;
for (int i = 0; i < type->StructInfo.num_fields; i++) {
NamedType_t field = type->StructInfo.fields[i];
if (field.type == &Bool$info) {
- bool bx = ((*(char*)(x + byte_offset)) >> bit_offset) & 0x1;
- bool by = ((*(char*)(y + byte_offset)) >> bit_offset) & 0x1;
- if (bx != by)
- return (int32_t)bx - (int32_t)by;
+ bool bx = ((*(char *)(x + byte_offset)) >> bit_offset) & 0x1;
+ bool by = ((*(char *)(y + byte_offset)) >> bit_offset) & 0x1;
+ if (bx != by) return (int32_t)bx - (int32_t)by;
bit_offset += 1;
if (bit_offset >= 8) {
byte_offset += 1;
@@ -86,28 +78,24 @@ PUREFUNC public int32_t Struct$compare(const void *x, const void *y, const TypeI
if (field.type->align && byte_offset % field.type->align > 0)
byte_offset += field.type->align - (byte_offset % field.type->align);
int32_t cmp = generic_compare(x + byte_offset, y + byte_offset, field.type);
- if (cmp != 0)
- return cmp;
+ if (cmp != 0) return cmp;
byte_offset += field.type->size;
}
}
return 0;
}
-PUREFUNC public bool Struct$equal(const void *x, const void *y, const TypeInfo_t *type)
-{
- if (x == y)
- return true;
+PUREFUNC public bool Struct$equal(const void *x, const void *y, const TypeInfo_t *type) {
+ if (x == y) return true;
ptrdiff_t byte_offset = 0;
ptrdiff_t bit_offset = 0;
for (int i = 0; i < type->StructInfo.num_fields; i++) {
NamedType_t field = type->StructInfo.fields[i];
if (field.type == &Bool$info) {
- bool bx = ((*(char*)(x + byte_offset)) >> bit_offset) & 0x1;
- bool by = ((*(char*)(y + byte_offset)) >> bit_offset) & 0x1;
- if (bx != by)
- return false;
+ bool bx = ((*(char *)(x + byte_offset)) >> bit_offset) & 0x1;
+ bool by = ((*(char *)(y + byte_offset)) >> bit_offset) & 0x1;
+ if (bx != by) return false;
bit_offset += 1;
if (bit_offset >= 8) {
byte_offset += 1;
@@ -120,22 +108,19 @@ PUREFUNC public bool Struct$equal(const void *x, const void *y, const TypeInfo_t
}
if (field.type->align && byte_offset % field.type->align > 0)
byte_offset += field.type->align - (byte_offset % field.type->align);
- if (!generic_equal(x + byte_offset, y + byte_offset, field.type))
- return false;
+ if (!generic_equal(x + byte_offset, y + byte_offset, field.type)) return false;
byte_offset += field.type->size;
}
}
return true;
}
-PUREFUNC public bool PackedData$equal(const void *x, const void *y, const TypeInfo_t *type)
-{
+PUREFUNC public bool PackedData$equal(const void *x, const void *y, const TypeInfo_t *type) {
if (x == y) return true;
return (memcmp(x, y, (size_t)type->size) == 0);
}
-PUREFUNC public Text_t Struct$as_text(const void *obj, bool colorize, const TypeInfo_t *type)
-{
+PUREFUNC public Text_t Struct$as_text(const void *obj, bool colorize, const TypeInfo_t *type) {
if (!obj) return Text$from_str(type->StructInfo.name);
Text_t name = Text$from_str(type->StructInfo.name);
@@ -148,15 +133,14 @@ PUREFUNC public Text_t Struct$as_text(const void *obj, bool colorize, const Type
ptrdiff_t bit_offset = 0;
for (int i = 0; i < type->StructInfo.num_fields; i++) {
NamedType_t field = type->StructInfo.fields[i];
- if (i > 0)
- text = Text$concat(text, Text(", "));
+ if (i > 0) text = Text$concat(text, Text(", "));
- if (type->StructInfo.num_fields > 1)
- text = Text$concat(text, Text$from_str(field.name), Text("="));
+ if (type->StructInfo.num_fields > 1) text = Text$concat(text, Text$from_str(field.name), Text("="));
if (field.type == &Bool$info) {
- bool b = ((*(char*)(obj + byte_offset)) >> bit_offset) & 0x1;
- text = Text$concat(text, Text$from_str(colorize ? (b ? "\x1b[35myes\x1b[m" : "\x1b[35mno\x1b[m") : (b ? "yes" : "no")));
+ bool b = ((*(char *)(obj + byte_offset)) >> bit_offset) & 0x1;
+ text = Text$concat(
+ text, Text$from_str(colorize ? (b ? "\x1b[35myes\x1b[m" : "\x1b[35mno\x1b[m") : (b ? "yes" : "no")));
bit_offset += 1;
if (bit_offset >= 8) {
byte_offset += 1;
@@ -176,19 +160,16 @@ PUREFUNC public Text_t Struct$as_text(const void *obj, bool colorize, const Type
return Text$concat(text, Text(")"));
}
-PUREFUNC public bool Struct$is_none(const void *obj, const TypeInfo_t *type)
-{
- return *(bool*)(obj + type->size);
-}
+PUREFUNC public bool Struct$is_none(const void *obj, const TypeInfo_t *type) { return *(bool *)(obj + type->size); }
-public void Struct$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type)
-{
+public
+void Struct$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
ptrdiff_t byte_offset = 0;
ptrdiff_t bit_offset = 0;
for (int i = 0; i < type->StructInfo.num_fields; i++) {
NamedType_t field = type->StructInfo.fields[i];
if (field.type == &Bool$info) {
- bool b = ((*(char*)(obj + byte_offset)) >> bit_offset) & 0x1;
+ bool b = ((*(char *)(obj + byte_offset)) >> bit_offset) & 0x1;
fputc((int)b, out);
bit_offset += 1;
if (bit_offset >= 8) {
@@ -208,15 +189,15 @@ public void Struct$serialize(const void *obj, FILE *out, Table_t *pointers, cons
}
}
-public void Struct$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type)
-{
+public
+void Struct$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type) {
ptrdiff_t byte_offset = 0;
ptrdiff_t bit_offset = 0;
for (int i = 0; i < type->StructInfo.num_fields; i++) {
NamedType_t field = type->StructInfo.fields[i];
if (field.type == &Bool$info) {
bool b = (bool)fgetc(in);
- *(char*)(outval + byte_offset) |= (b << bit_offset);
+ *(char *)(outval + byte_offset) |= (b << bit_offset);
bit_offset += 1;
if (bit_offset >= 8) {
byte_offset += 1;
diff --git a/src/stdlib/structs.h b/src/stdlib/structs.h
index c9c6c40a..03c051ec 100644
--- a/src/stdlib/structs.h
+++ b/src/stdlib/structs.h
@@ -17,24 +17,26 @@ PUREFUNC bool Struct$is_none(const void *obj, const TypeInfo_t *type);
void Struct$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type);
void Struct$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type);
-#define Struct$metamethods { \
- .hash=Struct$hash, \
- .compare=Struct$compare, \
- .equal=Struct$equal, \
- .as_text=Struct$as_text, \
- .is_none=Struct$is_none, \
- .serialize=Struct$serialize, \
- .deserialize=Struct$deserialize, \
-}
+#define Struct$metamethods \
+ { \
+ .hash = Struct$hash, \
+ .compare = Struct$compare, \
+ .equal = Struct$equal, \
+ .as_text = Struct$as_text, \
+ .is_none = Struct$is_none, \
+ .serialize = Struct$serialize, \
+ .deserialize = Struct$deserialize, \
+ }
-#define PackedData$metamethods { \
- .hash=PackedData$hash, \
- .compare=Struct$compare, \
- .equal=PackedData$equal, \
- .as_text=Struct$as_text, \
- .is_none=Struct$is_none, \
- .serialize=Struct$serialize, \
- .deserialize=Struct$deserialize, \
-}
+#define PackedData$metamethods \
+ { \
+ .hash = PackedData$hash, \
+ .compare = Struct$compare, \
+ .equal = PackedData$equal, \
+ .as_text = Struct$as_text, \
+ .is_none = Struct$is_none, \
+ .serialize = Struct$serialize, \
+ .deserialize = Struct$deserialize, \
+ }
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/tables.c b/src/stdlib/tables.c
index 63f8eb09..781da415 100644
--- a/src/stdlib/tables.c
+++ b/src/stdlib/tables.c
@@ -41,29 +41,29 @@
#define EQUAL_KEYS(x, y) (generic_equal((x), (y), type->TableInfo.key))
#define END_OF_CHAIN UINT32_MAX
-#define GET_ENTRY(t, i) ((t).entries.data + (t).entries.stride*(i))
+#define GET_ENTRY(t, i) ((t).entries.data + (t).entries.stride * (i))
static TypeInfo_t MemoryPointer = {
- .size=sizeof(void*),
- .align=__alignof__(void*),
- .tag=PointerInfo,
- .PointerInfo={
- .sigil="@",
- .pointed=&Memory$info,
- },
- .metamethods=Pointer$metamethods,
+ .size = sizeof(void *),
+ .align = __alignof__(void *),
+ .tag = PointerInfo,
+ .PointerInfo =
+ {
+ .sigil = "@",
+ .pointed = &Memory$info,
+ },
+ .metamethods = Pointer$metamethods,
};
const TypeInfo_t CStrToVoidStarTable = {
- .size=sizeof(Table_t),
- .align=__alignof__(Table_t),
- .tag=TableInfo,
- .TableInfo={.key=&CString$info, .value=&MemoryPointer},
- .metamethods=Table$metamethods,
+ .size = sizeof(Table_t),
+ .align = __alignof__(Table_t),
+ .tag = TableInfo,
+ .TableInfo = {.key = &CString$info, .value = &MemoryPointer},
+ .metamethods = Table$metamethods,
};
-PUREFUNC static INLINE size_t entry_size(const TypeInfo_t *info)
-{
+PUREFUNC static INLINE size_t entry_size(const TypeInfo_t *info) {
size_t size = (size_t)info->TableInfo.key->size;
if (info->TableInfo.value->align > 1 && size % (size_t)info->TableInfo.value->align)
size += (size_t)info->TableInfo.value->align - (size % (size_t)info->TableInfo.value->align); // padding
@@ -73,31 +73,27 @@ PUREFUNC static INLINE size_t entry_size(const TypeInfo_t *info)
return size;
}
-PUREFUNC static INLINE size_t value_offset(const TypeInfo_t *info)
-{
+PUREFUNC static INLINE size_t value_offset(const TypeInfo_t *info) {
size_t offset = (size_t)info->TableInfo.key->size;
if ((size_t)info->TableInfo.value->align > 1 && offset % (size_t)info->TableInfo.value->align)
offset += (size_t)info->TableInfo.value->align - (offset % (size_t)info->TableInfo.value->align); // padding
return offset;
}
-static INLINE void hshow(const Table_t *t)
-{
+static INLINE void hshow(const Table_t *t) {
hdebug("{");
for (uint32_t i = 0; t->bucket_info && i < t->bucket_info->count; i++) {
if (i > 0) hdebug(" ");
if (t->bucket_info->buckets[i].occupied)
- hdebug("[", i, "]=", (uint32_t)t->bucket_info->buckets[i].index, "(", t->bucket_info->buckets[i].next_bucket, ")");
- else
- hdebug("[", i, "]=_");
+ hdebug("[", i, "]=", (uint32_t)t->bucket_info->buckets[i].index, "(",
+ t->bucket_info->buckets[i].next_bucket, ")");
+ else hdebug("[", i, "]=_");
}
hdebug("}\n");
}
-static void maybe_copy_on_write(Table_t *t, const TypeInfo_t *type)
-{
- if (t->entries.data_refcount != 0)
- List$compact(&t->entries, (int64_t)entry_size(type));
+static void maybe_copy_on_write(Table_t *t, const TypeInfo_t *type) {
+ if (t->entries.data_refcount != 0) List$compact(&t->entries, (int64_t)entry_size(type));
if (t->bucket_info && t->bucket_info->data_refcount != 0) {
size_t size = sizeof(bucket_info_t) + sizeof(bucket_t[t->bucket_info->count]);
@@ -107,8 +103,7 @@ static void maybe_copy_on_write(Table_t *t, const TypeInfo_t *type)
}
// Return address of value or NULL
-PUREFUNC public void *Table$get_raw(Table_t t, const void *key, const TypeInfo_t *type)
-{
+PUREFUNC public void *Table$get_raw(Table_t t, const void *key, const TypeInfo_t *type) {
assert(type->tag == TableInfo);
if (!key || !t.bucket_info) return NULL;
@@ -123,14 +118,12 @@ PUREFUNC public void *Table$get_raw(Table_t t, const void *key, const TypeInfo_t
hdebug("Found key!\n");
return entry + value_offset(type);
}
- if (buckets[i].next_bucket == END_OF_CHAIN)
- break;
+ if (buckets[i].next_bucket == END_OF_CHAIN) break;
}
return NULL;
}
-PUREFUNC public void *Table$get(Table_t t, const void *key, const TypeInfo_t *type)
-{
+PUREFUNC public void *Table$get(Table_t t, const void *key, const TypeInfo_t *type) {
assert(type->tag == TableInfo);
for (const Table_t *iter = &t; iter; iter = iter->fallback) {
void *ret = Table$get_raw(*iter, key, type);
@@ -139,8 +132,7 @@ PUREFUNC public void *Table$get(Table_t t, const void *key, const TypeInfo_t *ty
return NULL;
}
-static void Table$set_bucket(Table_t *t, const void *entry, int32_t index, const TypeInfo_t *type)
-{
+static void Table$set_bucket(Table_t *t, const void *entry, int32_t index, const TypeInfo_t *type) {
assert(t->bucket_info);
hshow(t);
const void *key = entry;
@@ -182,15 +174,14 @@ static void Table$set_bucket(Table_t *t, const void *entry, int32_t index, const
bucket->next_bucket = END_OF_CHAIN;
} else { // Collided with the start of a chain, put the new entry in chain position #2
hdebug("Hit start of a chain\n");
- buckets[t->bucket_info->last_free] = (bucket_t){
- .occupied = 1, .index=index, .next_bucket=bucket->next_bucket};
+ buckets[t->bucket_info->last_free] =
+ (bucket_t){.occupied = 1, .index = index, .next_bucket = bucket->next_bucket};
bucket->next_bucket = t->bucket_info->last_free;
}
hshow(t);
}
-static void hashmap_resize_buckets(Table_t *t, uint32_t new_capacity, const TypeInfo_t *type)
-{
+static void hashmap_resize_buckets(Table_t *t, uint32_t new_capacity, const TypeInfo_t *type) {
if (unlikely(new_capacity > TABLE_MAX_BUCKETS))
fail("Table has exceeded the maximum table size (2^31) and cannot grow further!");
hdebug("About to resize from ", t->bucket_info ? (int32_t)t->bucket_info->count : 0, " to ", new_capacity, "\n");
@@ -199,7 +190,7 @@ static void hashmap_resize_buckets(Table_t *t, uint32_t new_capacity, const Type
t->bucket_info = GC_MALLOC_ATOMIC(alloc_size);
memset(t->bucket_info->buckets, 0, sizeof(bucket_t[new_capacity]));
t->bucket_info->count = new_capacity;
- t->bucket_info->last_free = new_capacity-1;
+ t->bucket_info->last_free = new_capacity - 1;
// Rehash:
for (int64_t i = 0; i < Table$length(*t); i++) {
hdebug("Rehashing ", i, "\n");
@@ -215,16 +206,15 @@ static void hashmap_resize_buckets(Table_t *t, uint32_t new_capacity, const Type
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstack-protector"
#endif
-public void *Table$reserve(Table_t *t, const void *key, const void *value, const TypeInfo_t *type)
-{
+public
+void *Table$reserve(Table_t *t, const void *key, const void *value, const TypeInfo_t *type) {
assert(type->tag == TableInfo);
if (!t || !key) return NULL;
hshow(t);
t->hash = 0;
- int64_t key_size = type->TableInfo.key->size,
- value_size = type->TableInfo.value->size;
+ int64_t key_size = type->TableInfo.key->size, value_size = type->TableInfo.value->size;
if (!t->bucket_info || t->bucket_info->count == 0) {
hashmap_resize_buckets(t, 8, type);
} else {
@@ -236,8 +226,7 @@ public void *Table$reserve(Table_t *t, const void *key, const void *value, const
maybe_copy_on_write(t, type);
value_home = t->entries.data + offset;
- if (value && value_size > 0)
- memcpy(value_home, value, (size_t)value_size);
+ if (value && value_size > 0) memcpy(value_home, value, (size_t)value_size);
return value_home;
}
@@ -247,9 +236,8 @@ public void *Table$reserve(Table_t *t, const void *key, const void *value, const
// Resize buckets if necessary
if (t->entries.length >= (int64_t)t->bucket_info->count) {
// Current resize policy: +50% at a time:
- uint32_t newsize = MAX(8, (uint32_t)(3*t->bucket_info->count)/2);
- if (unlikely(newsize > TABLE_MAX_BUCKETS))
- newsize = TABLE_MAX_BUCKETS;
+ uint32_t newsize = MAX(8, (uint32_t)(3 * t->bucket_info->count) / 2);
+ if (unlikely(newsize > TABLE_MAX_BUCKETS)) newsize = TABLE_MAX_BUCKETS;
hashmap_resize_buckets(t, newsize, type);
}
@@ -265,13 +253,11 @@ public void *Table$reserve(Table_t *t, const void *key, const void *value, const
char buf[entry_size(type)];
memset(buf, 0, sizeof(buf));
memcpy(buf, key, (size_t)key_size);
- if (value && value_size > 0)
- memcpy(buf + value_offset(type), value, (size_t)value_size);
- else if (value_size > 0)
- memset(buf + value_offset(type), 0, (size_t)value_size);
+ if (value && value_size > 0) memcpy(buf + value_offset(type), value, (size_t)value_size);
+ else if (value_size > 0) memset(buf + value_offset(type), 0, (size_t)value_size);
List$insert(&t->entries, buf, I(0), (int64_t)entry_size(type));
- int64_t entry_index = t->entries.length-1;
+ int64_t entry_index = t->entries.length - 1;
void *entry = GET_ENTRY(*t, entry_index);
Table$set_bucket(t, entry, entry_index, type);
return entry + value_offset(type);
@@ -280,14 +266,14 @@ public void *Table$reserve(Table_t *t, const void *key, const void *value, const
#pragma GCC diagnostic pop
#endif
-public void Table$set(Table_t *t, const void *key, const void *value, const TypeInfo_t *type)
-{
+public
+void Table$set(Table_t *t, const void *key, const void *value, const TypeInfo_t *type) {
assert(type->tag == TableInfo);
(void)Table$reserve(t, key, value, type);
}
-public void Table$remove(Table_t *t, const void *key, const TypeInfo_t *type)
-{
+public
+void Table$remove(Table_t *t, const void *key, const TypeInfo_t *type) {
assert(type->tag == TableInfo);
if (!t || Table$length(*t) == 0) return;
@@ -295,8 +281,7 @@ public void Table$remove(Table_t *t, const void *key, const TypeInfo_t *type)
maybe_copy_on_write(t, type);
// If unspecified, pop the last key:
- if (!key)
- key = GET_ENTRY(*t, t->entries.length-1);
+ if (!key) key = GET_ENTRY(*t, t->entries.length - 1);
// Steps: look up the bucket for the removed key
// If missing, then return immediately
@@ -322,13 +307,12 @@ public void Table$remove(Table_t *t, const void *key, const TypeInfo_t *type)
hdebug("Found key to delete in bucket ", i, "\n");
goto found_it;
}
- if (t->bucket_info->buckets[i].next_bucket == END_OF_CHAIN)
- return;
+ if (t->bucket_info->buckets[i].next_bucket == END_OF_CHAIN) return;
prev = &t->bucket_info->buckets[i];
}
return;
- found_it:;
+found_it:;
assert(bucket->occupied);
t->hash = 0;
@@ -337,7 +321,7 @@ public void Table$remove(Table_t *t, const void *key, const TypeInfo_t *type)
// swap the other entry into the last position and then remove the last
// entry. This disturbs the ordering of the table, but keeps removal O(1)
// instead of O(N)
- int64_t last_entry = t->entries.length-1;
+ int64_t last_entry = t->entries.length - 1;
if (bucket->index != last_entry) {
hdebug("Removing key/value from the middle of the entries list\n");
@@ -374,70 +358,58 @@ public void Table$remove(Table_t *t, const void *key, const TypeInfo_t *type)
}
t->bucket_info->buckets[bucket_to_clear] = (bucket_t){0};
- if (bucket_to_clear > t->bucket_info->last_free)
- t->bucket_info->last_free = bucket_to_clear;
+ if (bucket_to_clear > t->bucket_info->last_free) t->bucket_info->last_free = bucket_to_clear;
hshow(t);
}
-CONSTFUNC public void *Table$entry(Table_t t, int64_t n)
-{
- if (n < 1 || n > Table$length(t))
- return NULL;
- return GET_ENTRY(t, n-1);
+CONSTFUNC public void *Table$entry(Table_t t, int64_t n) {
+ if (n < 1 || n > Table$length(t)) return NULL;
+ return GET_ENTRY(t, n - 1);
}
-public void Table$clear(Table_t *t)
-{
- memset(t, 0, sizeof(Table_t));
-}
+public
+void Table$clear(Table_t *t) { memset(t, 0, sizeof(Table_t)); }
-public Table_t Table$sorted(Table_t t, const TypeInfo_t *type)
-{
- Closure_t cmp = (Closure_t){.fn=generic_compare, .userdata=(void*)type->TableInfo.key};
+public
+Table_t Table$sorted(Table_t t, const TypeInfo_t *type) {
+ Closure_t cmp = (Closure_t){.fn = generic_compare, .userdata = (void *)type->TableInfo.key};
List_t entries = List$sorted(t.entries, cmp, (int64_t)entry_size(type));
return Table$from_entries(entries, type);
}
-PUREFUNC public bool Table$equal(const void *vx, const void *vy, const TypeInfo_t *type)
-{
+PUREFUNC public bool Table$equal(const void *vx, const void *vy, const TypeInfo_t *type) {
if (vx == vy) return true;
- Table_t *x = (Table_t*)vx, *y = (Table_t*)vy;
+ Table_t *x = (Table_t *)vx, *y = (Table_t *)vy;
- if (x->hash && y->hash && x->hash != y->hash)
- return false;
+ if (x->hash && y->hash && x->hash != y->hash) return false;
assert(type->tag == TableInfo);
- if (x->entries.length != y->entries.length)
- return false;
-
- if ((x->fallback != NULL) != (y->fallback != NULL))
- return false;
+ if (x->entries.length != y->entries.length) return false;
+
+ if ((x->fallback != NULL) != (y->fallback != NULL)) return false;
const TypeInfo_t *value_type = type->TableInfo.value;
size_t offset = value_offset(type);
for (int64_t i = 0; i < x->entries.length; i++) {
- void *x_key = x->entries.data + i*x->entries.stride;
+ void *x_key = x->entries.data + i * x->entries.stride;
void *y_value = Table$get_raw(*y, x_key, type);
if (!y_value) return false;
void *x_value = x_key + offset;
- if (!generic_equal(y_value, x_value, value_type))
- return false;
+ if (!generic_equal(y_value, x_value, value_type)) return false;
}
return true;
}
-PUREFUNC public int32_t Table$compare(const void *vx, const void *vy, const TypeInfo_t *type)
-{
+PUREFUNC public int32_t Table$compare(const void *vx, const void *vy, const TypeInfo_t *type) {
if (vx == vy) return 0;
- Table_t *x = (Table_t*)vx, *y = (Table_t*)vy;
+ Table_t *x = (Table_t *)vx, *y = (Table_t *)vy;
assert(type->tag == TableInfo);
__typeof(type->TableInfo) table = type->TableInfo;
// Sort empty tables before non-empty tables:
- if (x->entries.length == 0 || y->entries.length == 0)
- return ((x->entries.length > 0) - (y->entries.length > 0));
+ if (x->entries.length == 0 || y->entries.length == 0) return ((x->entries.length > 0) - (y->entries.length > 0));
// Table comparison rules:
// - If two tables have different keys, then compare as if comparing a
@@ -446,22 +418,20 @@ PUREFUNC public int32_t Table$compare(const void *vx, const void *vy, const Type
// - Otherwise, compare as if comparing lists of values for the sorted key
// lists:
// `[x[k] for k in x.keys.sorted()] <> [y[k] for k in y.keys.sorted()]`
- //
+ //
// We can do this in _linear_ time if we find the smallest `k` such that
// `x[k] != y[k]`, as well as the largest key in `x` and `y`.
void *mismatched_key = NULL, *max_x_key = NULL;
for (int64_t i = 0; i < x->entries.length; i++) {
void *key = x->entries.data + x->entries.stride * i;
- if (max_x_key == NULL || generic_compare(key, max_x_key, table.key) > 0)
- max_x_key = key;
+ if (max_x_key == NULL || generic_compare(key, max_x_key, table.key) > 0) max_x_key = key;
void *x_value = key + value_offset(type);
void *y_value = Table$get_raw(*y, key, type);
if (!y_value || (table.value->size > 0 && !generic_equal(x_value, y_value, table.value))) {
- if (mismatched_key == NULL || generic_compare(key, mismatched_key, table.key) < 0)
- mismatched_key = key;
+ if (mismatched_key == NULL || generic_compare(key, mismatched_key, table.key) < 0) mismatched_key = key;
}
}
@@ -470,14 +440,12 @@ PUREFUNC public int32_t Table$compare(const void *vx, const void *vy, const Type
void *max_y_key = NULL;
for (int64_t i = 0; i < y->entries.length; i++) {
void *key = y->entries.data + y->entries.stride * i;
- if (max_y_key == NULL || generic_compare(key, max_y_key, table.key) > 0)
- max_y_key = key;
+ if (max_y_key == NULL || generic_compare(key, max_y_key, table.key) > 0) max_y_key = key;
void *y_value = key + value_offset(type);
void *x_value = Table$get_raw(*x, key, type);
if (!x_value || !generic_equal(x_value, y_value, table.value)) {
- if (mismatched_key == NULL || generic_compare(key, mismatched_key, table.key) < 0)
- mismatched_key = key;
+ if (mismatched_key == NULL || generic_compare(key, mismatched_key, table.key) < 0) mismatched_key = key;
}
}
@@ -529,12 +497,10 @@ PUREFUNC public int32_t Table$compare(const void *vx, const void *vy, const Type
return 0;
}
-PUREFUNC public uint64_t Table$hash(const void *obj, const TypeInfo_t *type)
-{
+PUREFUNC public uint64_t Table$hash(const void *obj, const TypeInfo_t *type) {
assert(type->tag == TableInfo);
- Table_t *t = (Table_t*)obj;
- if (t->hash != 0)
- return t->hash;
+ Table_t *t = (Table_t *)obj;
+ if (t->hash != 0) return t->hash;
// Table hashes are computed as:
// hash(t.length, (xor: t.keys), (xor: t.values), t.fallback)
@@ -544,12 +510,12 @@ PUREFUNC public uint64_t Table$hash(const void *obj, const TypeInfo_t *type)
size_t offset = value_offset(type);
if (table.value->size > 0) {
for (int64_t i = 0; i < t->entries.length; i++) {
- keys_hash ^= generic_hash(t->entries.data + i*t->entries.stride, table.key);
- values_hash ^= generic_hash(t->entries.data + i*t->entries.stride + offset, table.value);
+ keys_hash ^= generic_hash(t->entries.data + i * t->entries.stride, table.key);
+ values_hash ^= generic_hash(t->entries.data + i * t->entries.stride + offset, table.value);
}
} else {
for (int64_t i = 0; i < t->entries.length; i++)
- keys_hash ^= generic_hash(t->entries.data + i*t->entries.stride, table.key);
+ keys_hash ^= generic_hash(t->entries.data + i * t->entries.stride, table.key);
}
volatile struct {
@@ -561,41 +527,31 @@ PUREFUNC public uint64_t Table$hash(const void *obj, const TypeInfo_t *type)
values_hash,
t->fallback ? Table$hash(t->fallback, type) : 0,
};
- t->hash = siphash24((void*)&components, sizeof(components));
- if unlikely (t->hash == 0)
- t->hash = 1234567;
+ t->hash = siphash24((void *)&components, sizeof(components));
+ if unlikely (t->hash == 0) t->hash = 1234567;
return t->hash;
}
-public Text_t Table$as_text(const void *obj, bool colorize, const TypeInfo_t *type)
-{
- Table_t *t = (Table_t*)obj;
+public
+Text_t Table$as_text(const void *obj, bool colorize, const TypeInfo_t *type) {
+ Table_t *t = (Table_t *)obj;
assert(type->tag == TableInfo);
__typeof(type->TableInfo) table = type->TableInfo;
if (!t) {
- if (table.value != &Void$info)
- return Text$concat(
- Text("{"),
- generic_as_text(NULL, false, table.key),
- Text("="),
- generic_as_text(NULL, false, table.value),
- Text("}"));
- else
- return Text$concat(
- Text("|"),
- generic_as_text(NULL, false, table.key),
- Text("|"));
+ if (table.value != &Void$info)
+ return Text$concat(Text("{"), generic_as_text(NULL, false, table.key), Text("="),
+ generic_as_text(NULL, false, table.value), Text("}"));
+ else return Text$concat(Text("|"), generic_as_text(NULL, false, table.key), Text("|"));
}
int64_t val_off = (int64_t)value_offset(type);
Text_t text = table.value == &Void$info ? Text("|") : Text("{");
for (int64_t i = 0, length = Table$length(*t); i < length; i++) {
- if (i > 0)
- text = Text$concat(text, Text(", "));
+ if (i > 0) text = Text$concat(text, Text(", "));
void *entry = GET_ENTRY(*t, i);
text = Text$concat(text, generic_as_text(entry, colorize, table.key));
- if (table.value != &Void$info)
+ if (table.value != &Void$info)
text = Text$concat(text, Text("="), generic_as_text(entry + val_off, colorize, table.value));
}
@@ -607,11 +563,10 @@ public Text_t Table$as_text(const void *obj, bool colorize, const TypeInfo_t *ty
return text;
}
-public Table_t Table$from_entries(List_t entries, const TypeInfo_t *type)
-{
+public
+Table_t Table$from_entries(List_t entries, const TypeInfo_t *type) {
assert(type->tag == TableInfo);
- if (entries.length == 0)
- return (Table_t){};
+ if (entries.length == 0) return (Table_t){};
Table_t t = {};
int64_t length = entries.length + entries.length / 4;
@@ -619,19 +574,19 @@ public Table_t Table$from_entries(List_t entries, const TypeInfo_t *type)
t.bucket_info = GC_MALLOC_ATOMIC(alloc_size);
memset(t.bucket_info->buckets, 0, sizeof(bucket_t[length]));
t.bucket_info->count = length;
- t.bucket_info->last_free = length-1;
+ t.bucket_info->last_free = length - 1;
size_t offset = value_offset(type);
for (int64_t i = 0; i < entries.length; i++) {
- void *key = entries.data + i*entries.stride;
+ void *key = entries.data + i * entries.stride;
Table$set(&t, key, key + offset, type);
}
return t;
}
// Overlap is "set intersection" in formal terms
-public Table_t Table$overlap(Table_t a, Table_t b, const TypeInfo_t *type)
-{
+public
+Table_t Table$overlap(Table_t a, Table_t b, const TypeInfo_t *type) {
// Return a table such that t[k]==a[k] for all k such that a.has(k), b.has(k), and a[k]==b[k]
Table_t result = {};
const size_t offset = value_offset(type);
@@ -648,9 +603,10 @@ public Table_t Table$overlap(Table_t a, Table_t b, const TypeInfo_t *type)
}
// With is "set union" in formal terms
-public Table_t Table$with(Table_t a, Table_t b, const TypeInfo_t *type)
-{
- // return a table such that t[k]==b[k] for all k such that b.has(k), and t[k]==a[k] for all k such that a.has(k) and not b.has(k)
+public
+Table_t Table$with(Table_t a, Table_t b, const TypeInfo_t *type) {
+ // return a table such that t[k]==b[k] for all k such that b.has(k), and t[k]==a[k] for all k such that a.has(k) and
+ // not b.has(k)
Table_t result = {};
const size_t offset = value_offset(type);
for (Table_t *t = &a; t; t = t->fallback) {
@@ -669,31 +625,29 @@ public Table_t Table$with(Table_t a, Table_t b, const TypeInfo_t *type)
}
// Xor is "disjunctive union" or "symmetric difference" in formal terms
-public Table_t Table$xor(Table_t a, Table_t b, const TypeInfo_t *type)
-{
+public
+Table_t Table$xor(Table_t a, Table_t b, const TypeInfo_t *type) {
// return a table with elements in `a` or `b`, but not both
Table_t result = {};
const size_t offset = value_offset(type);
for (Table_t *t = &a; t; t = t->fallback) {
for (int64_t i = 0; i < Table$length(*t); i++) {
void *key = GET_ENTRY(*t, i);
- if (Table$get(b, key, type) == NULL)
- Table$set(&result, key, key + offset, type);
+ if (Table$get(b, key, type) == NULL) Table$set(&result, key, key + offset, type);
}
}
for (Table_t *t = &b; t; t = t->fallback) {
for (int64_t i = 0; i < Table$length(*t); i++) {
void *key = GET_ENTRY(*t, i);
- if (Table$get(a, key, type) == NULL)
- Table$set(&result, key, key + offset, type);
+ if (Table$get(a, key, type) == NULL) Table$set(&result, key, key + offset, type);
}
}
return result;
}
// Without is "set difference" in formal terms
-public Table_t Table$without(Table_t a, Table_t b, const TypeInfo_t *type)
-{
+public
+Table_t Table$without(Table_t a, Table_t b, const TypeInfo_t *type) {
// Return a table such that t[k]==a[k] for all k such that not b.has(k) or b[k] != a[k]
Table_t result = {};
const size_t offset = value_offset(type);
@@ -709,8 +663,8 @@ public Table_t Table$without(Table_t a, Table_t b, const TypeInfo_t *type)
return result;
}
-public Table_t Table$with_fallback(Table_t t, OptionalTable_t fallback)
-{
+public
+Table_t Table$with_fallback(Table_t t, OptionalTable_t fallback) {
if (fallback.entries.length <= 0) {
t.fallback = NULL;
return t;
@@ -722,10 +676,8 @@ public Table_t Table$with_fallback(Table_t t, OptionalTable_t fallback)
}
}
-PUREFUNC public bool Table$is_subset_of(Table_t a, Table_t b, bool strict, const TypeInfo_t *type)
-{
- if (a.entries.length > b.entries.length || (strict && a.entries.length == b.entries.length))
- return false;
+PUREFUNC public bool Table$is_subset_of(Table_t a, Table_t b, bool strict, const TypeInfo_t *type) {
+ if (a.entries.length > b.entries.length || (strict && a.entries.length == b.entries.length)) return false;
for (int64_t i = 0; i < Table$length(a); i++) {
void *found = Table$get_raw(b, GET_ENTRY(a, i), type);
@@ -734,73 +686,61 @@ PUREFUNC public bool Table$is_subset_of(Table_t a, Table_t b, bool strict, const
return true;
}
-PUREFUNC public bool Table$is_superset_of(Table_t a, Table_t b, bool strict, const TypeInfo_t *type)
-{
+PUREFUNC public bool Table$is_superset_of(Table_t a, Table_t b, bool strict, const TypeInfo_t *type) {
return Table$is_subset_of(b, a, strict, type);
}
-PUREFUNC public void *Table$str_get(Table_t t, const char *key)
-{
+PUREFUNC public void *Table$str_get(Table_t t, const char *key) {
void **ret = Table$get(t, &key, &CStrToVoidStarTable);
return ret ? *ret : NULL;
}
-PUREFUNC public void *Table$str_get_raw(Table_t t, const char *key)
-{
+PUREFUNC public void *Table$str_get_raw(Table_t t, const char *key) {
void **ret = Table$get_raw(t, &key, &CStrToVoidStarTable);
return ret ? *ret : NULL;
}
-public void *Table$str_reserve(Table_t *t, const char *key, const void *value)
-{
+public
+void *Table$str_reserve(Table_t *t, const char *key, const void *value) {
return Table$reserve(t, &key, &value, &CStrToVoidStarTable);
}
-public void Table$str_set(Table_t *t, const char *key, const void *value)
-{
- Table$set(t, &key, &value, &CStrToVoidStarTable);
-}
+public
+void Table$str_set(Table_t *t, const char *key, const void *value) { Table$set(t, &key, &value, &CStrToVoidStarTable); }
-public void Table$str_remove(Table_t *t, const char *key)
-{
- return Table$remove(t, &key, &CStrToVoidStarTable);
-}
+public
+void Table$str_remove(Table_t *t, const char *key) { return Table$remove(t, &key, &CStrToVoidStarTable); }
-CONSTFUNC public void *Table$str_entry(Table_t t, int64_t n)
-{
- return Table$entry(t, n);
-}
+CONSTFUNC public void *Table$str_entry(Table_t t, int64_t n) { return Table$entry(t, n); }
-PUREFUNC public bool Table$is_none(const void *obj, const TypeInfo_t *info)
-{
+PUREFUNC public bool Table$is_none(const void *obj, const TypeInfo_t *info) {
(void)info;
- return ((Table_t*)obj)->entries.length < 0;
+ return ((Table_t *)obj)->entries.length < 0;
}
-public void Table$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type)
-{
- Table_t *t = (Table_t*)obj;
+public
+void Table$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
+ Table_t *t = (Table_t *)obj;
int64_t len = t->entries.length;
Int64$serialize(&len, out, pointers, &Int64$info);
size_t offset = value_offset(type);
for (int64_t i = 0; i < len; i++) {
- _serialize(t->entries.data + i*t->entries.stride, out, pointers, type->TableInfo.key);
+ _serialize(t->entries.data + i * t->entries.stride, out, pointers, type->TableInfo.key);
if (type->TableInfo.value->size > 0)
- _serialize(t->entries.data + i*t->entries.stride + offset, out, pointers, type->TableInfo.value);
+ _serialize(t->entries.data + i * t->entries.stride + offset, out, pointers, type->TableInfo.value);
}
assert(fputc(t->fallback != NULL ? 1 : 0, out) != EOF);
- if (t->fallback)
- Table$serialize(t->fallback, out, pointers, type);
+ if (t->fallback) Table$serialize(t->fallback, out, pointers, type);
}
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstack-protector"
#endif
-public void Table$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type)
-{
+public
+void Table$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type) {
int64_t len;
Int64$deserialize(in, &len, pointers, &Int$info);
@@ -809,8 +749,7 @@ public void Table$deserialize(FILE *in, void *outval, List_t *pointers, const Ty
char key[type->TableInfo.key->size];
_deserialize(in, key, pointers, type->TableInfo.key);
char value[type->TableInfo.value->size];
- if (type->TableInfo.value->size > 0)
- _deserialize(in, value, pointers, type->TableInfo.value);
+ if (type->TableInfo.value->size > 0) _deserialize(in, value, pointers, type->TableInfo.value);
Table$set(&t, key, value, type);
}
@@ -819,7 +758,7 @@ public void Table$deserialize(FILE *in, void *outval, List_t *pointers, const Ty
Table$deserialize(in, t.fallback, pointers, type);
}
- *(Table_t*)outval = t;
+ *(Table_t *)outval = t;
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
diff --git a/src/stdlib/tables.h b/src/stdlib/tables.h
index f80c16c3..65f35060 100644
--- a/src/stdlib/tables.h
+++ b/src/stdlib/tables.h
@@ -2,59 +2,94 @@
// Hash table datastructure with methods and type information
-#include <stdint.h>
#include <stdbool.h>
+#include <stdint.h>
#include <string.h>
-#include "lists.h"
#include "datatypes.h"
+#include "lists.h"
#include "types.h"
#include "util.h"
-#define Table(key_t, val_t, key_info, value_info, fb, N, ...) ({ \
- struct { key_t k; val_t v; } ents[N] = {__VA_ARGS__}; \
- Table_t table = Table$from_entries((List_t){ \
- .data=memcpy(GC_MALLOC(sizeof(ents)), ents, sizeof(ents)), \
- .length=sizeof(ents)/sizeof(ents[0]), \
- .stride=(void*)&ents[1] - (void*)&ents[0], \
- }, Table$info(key_info, value_info)); \
- table.fallback = fb; \
- table; })
-#define Set(item_t, item_info, N, ...) ({ \
- item_t ents[N] = {__VA_ARGS__}; \
- Table_t set = Table$from_entries((List_t){ \
- .data=memcpy(GC_MALLOC(sizeof(ents)), ents, sizeof(ents)), \
- .length=sizeof(ents)/sizeof(ents[0]), \
- .stride=(void*)&ents[1] - (void*)&ents[0], \
- }, Set$info(item_info)); \
- set; })
+#define Table(key_t, val_t, key_info, value_info, fb, N, ...) \
+ ({ \
+ struct { \
+ key_t k; \
+ val_t v; \
+ } ents[N] = {__VA_ARGS__}; \
+ Table_t table = Table$from_entries( \
+ (List_t){ \
+ .data = memcpy(GC_MALLOC(sizeof(ents)), ents, sizeof(ents)), \
+ .length = sizeof(ents) / sizeof(ents[0]), \
+ .stride = (void *)&ents[1] - (void *)&ents[0], \
+ }, \
+ Table$info(key_info, value_info)); \
+ table.fallback = fb; \
+ table; \
+ })
+#define Set(item_t, item_info, N, ...) \
+ ({ \
+ item_t ents[N] = {__VA_ARGS__}; \
+ Table_t set = Table$from_entries( \
+ (List_t){ \
+ .data = memcpy(GC_MALLOC(sizeof(ents)), ents, sizeof(ents)), \
+ .length = sizeof(ents) / sizeof(ents[0]), \
+ .stride = (void *)&ents[1] - (void *)&ents[0], \
+ }, \
+ Set$info(item_info)); \
+ set; \
+ })
Table_t Table$from_entries(List_t entries, const TypeInfo_t *type);
void *Table$get(Table_t t, const void *key, const TypeInfo_t *type);
-#define Table$get_optional(table_expr, key_t, val_t, key_expr, nonnull_var, nonnull_expr, null_expr, info_expr) ({ \
- const Table_t t = table_expr; const key_t k = key_expr; \
- val_t *nonnull_var = Table$get(t, &k, info_expr); \
- nonnull_var ? nonnull_expr : null_expr; })
-#define Table$get_or_setdefault(table_expr, key_t, val_t, key_expr, default_expr, info_expr) ({ \
- Table_t *t = table_expr; const key_t k = key_expr; \
- if (t->entries.data_refcount > 0) List$compact(&t->entries, sizeof(struct {key_t k; val_t v;})); \
- val_t *v = Table$get(*t, &k, info_expr); \
- v ? v : (val_t*)Table$reserve(t, &k, (val_t[1]){default_expr}, info_expr); })
-#define Table$get_or_default(table_expr, key_t, val_t, key_expr, default_expr, info_expr) ({ \
- const Table_t t = table_expr; const key_t k = key_expr; \
- val_t *v = Table$get(t, &k, info_expr); \
- v ? *v : default_expr; })
-#define Table$has_value(table_expr, key_expr, info_expr) ({ \
- const Table_t t = table_expr; __typeof(key_expr) k = key_expr; \
- (Table$get(t, &k, info_expr) != NULL); })
+#define Table$get_optional(table_expr, key_t, val_t, key_expr, nonnull_var, nonnull_expr, null_expr, info_expr) \
+ ({ \
+ const Table_t t = table_expr; \
+ const key_t k = key_expr; \
+ val_t *nonnull_var = Table$get(t, &k, info_expr); \
+ nonnull_var ? nonnull_expr : null_expr; \
+ })
+#define Table$get_or_setdefault(table_expr, key_t, val_t, key_expr, default_expr, info_expr) \
+ ({ \
+ Table_t *t = table_expr; \
+ const key_t k = key_expr; \
+ if (t->entries.data_refcount > 0) \
+ List$compact(&t->entries, sizeof(struct { \
+ key_t k; \
+ val_t v; \
+ })); \
+ val_t *v = Table$get(*t, &k, info_expr); \
+ v ? v : (val_t *)Table$reserve(t, &k, (val_t[1]){default_expr}, info_expr); \
+ })
+#define Table$get_or_default(table_expr, key_t, val_t, key_expr, default_expr, info_expr) \
+ ({ \
+ const Table_t t = table_expr; \
+ const key_t k = key_expr; \
+ val_t *v = Table$get(t, &k, info_expr); \
+ v ? *v : default_expr; \
+ })
+#define Table$has_value(table_expr, key_expr, info_expr) \
+ ({ \
+ const Table_t t = table_expr; \
+ __typeof(key_expr) k = key_expr; \
+ (Table$get(t, &k, info_expr) != NULL); \
+ })
PUREFUNC void *Table$get_raw(Table_t t, const void *key, const TypeInfo_t *type);
CONSTFUNC void *Table$entry(Table_t t, int64_t n);
void *Table$reserve(Table_t *t, const void *key, const void *value, const TypeInfo_t *type);
void Table$set(Table_t *t, const void *key, const void *value, const TypeInfo_t *type);
-#define Table$set_value(t, key_expr, value_expr, type) ({ __typeof(key_expr) k = key_expr; __typeof(value_expr) v = value_expr; \
- Table$set(t, &k, &v, type); })
+#define Table$set_value(t, key_expr, value_expr, type) \
+ ({ \
+ __typeof(key_expr) k = key_expr; \
+ __typeof(value_expr) v = value_expr; \
+ Table$set(t, &k, &v, type); \
+ })
void Table$remove(Table_t *t, const void *key, const TypeInfo_t *type);
-#define Table$remove_value(t, key_expr, type) ({ __typeof(key_expr) k = key_expr; Table$remove(t, &k, type); })
+#define Table$remove_value(t, key_expr, type) \
+ ({ \
+ __typeof(key_expr) k = key_expr; \
+ Table$remove(t, &k, type); \
+ })
Table_t Table$overlap(Table_t a, Table_t b, const TypeInfo_t *type);
Table_t Table$with(Table_t a, Table_t b, const TypeInfo_t *type);
@@ -67,13 +102,22 @@ PUREFUNC bool Table$is_superset_of(Table_t a, Table_t b, bool strict, const Type
void Table$clear(Table_t *t);
Table_t Table$sorted(Table_t t, const TypeInfo_t *type);
void Table$mark_copy_on_write(Table_t *t);
-#define TABLE_INCREF(t) ({ LIST_INCREF((t).entries); if ((t).bucket_info) (t).bucket_info->data_refcount += ((t).bucket_info->data_refcount < TABLE_MAX_DATA_REFCOUNT); })
-#define TABLE_COPY(t) ({ TABLE_INCREF(t); t; })
+#define TABLE_INCREF(t) \
+ ({ \
+ LIST_INCREF((t).entries); \
+ if ((t).bucket_info) \
+ (t).bucket_info->data_refcount += ((t).bucket_info->data_refcount < TABLE_MAX_DATA_REFCOUNT); \
+ })
+#define TABLE_COPY(t) \
+ ({ \
+ TABLE_INCREF(t); \
+ t; \
+ })
PUREFUNC int32_t Table$compare(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC bool Table$equal(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC uint64_t Table$hash(const void *t, const TypeInfo_t *type);
Text_t Table$as_text(const void *t, bool colorize, const TypeInfo_t *type);
-PUREFUNC bool Table$is_none(const void *obj, const TypeInfo_t*);
+PUREFUNC bool Table$is_none(const void *obj, const TypeInfo_t *);
CONSTFUNC void *Table$str_entry(Table_t t, int64_t n);
PUREFUNC void *Table$str_get(Table_t t, const char *key);
@@ -88,19 +132,30 @@ void Table$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_
extern const TypeInfo_t CStrToVoidStarTable;
-#define Table$metamethods { \
- .as_text=Table$as_text, \
- .compare=Table$compare, \
- .equal=Table$equal, \
- .hash=Table$hash, \
- .is_none=Table$is_none, \
- .serialize=Table$serialize, \
- .deserialize=Table$deserialize, \
-}
+#define Table$metamethods \
+ { \
+ .as_text = Table$as_text, \
+ .compare = Table$compare, \
+ .equal = Table$equal, \
+ .hash = Table$hash, \
+ .is_none = Table$is_none, \
+ .serialize = Table$serialize, \
+ .deserialize = Table$deserialize, \
+ }
-#define Table$info(key_expr, value_expr) &((TypeInfo_t){.size=sizeof(Table_t), .align=__alignof__(Table_t), \
- .tag=TableInfo, .TableInfo.key=key_expr, .TableInfo.value=value_expr, .metamethods=Table$metamethods})
-#define Set$info(item_info) &((TypeInfo_t){.size=sizeof(Table_t), .align=__alignof__(Table_t), \
- .tag=TableInfo, .TableInfo.key=item_info, .TableInfo.value=&Void$info, .metamethods=Table$metamethods})
+#define Table$info(key_expr, value_expr) \
+ &((TypeInfo_t){.size = sizeof(Table_t), \
+ .align = __alignof__(Table_t), \
+ .tag = TableInfo, \
+ .TableInfo.key = key_expr, \
+ .TableInfo.value = value_expr, \
+ .metamethods = Table$metamethods})
+#define Set$info(item_info) \
+ &((TypeInfo_t){.size = sizeof(Table_t), \
+ .align = __alignof__(Table_t), \
+ .tag = TableInfo, \
+ .TableInfo.key = item_info, \
+ .TableInfo.value = &Void$info, \
+ .metamethods = Table$metamethods})
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
diff --git a/src/stdlib/text.c b/src/stdlib/text.c
index d9793eb8..aad3fd76 100644
--- a/src/stdlib/text.c
+++ b/src/stdlib/text.c
@@ -116,8 +116,8 @@
#include "text.h"
// Use inline version of the siphash code for performance:
-#include "siphash.h"
#include "siphash-internals.h"
+#include "siphash.h"
typedef struct {
ucs4_t main_codepoint;
@@ -133,9 +133,9 @@ static synthetic_grapheme_t *synthetic_graphemes = NULL;
static int32_t synthetic_grapheme_capacity = 0;
static int32_t num_synthetic_graphemes = 0;
-#define NUM_GRAPHEME_CODEPOINTS(id) (synthetic_graphemes[-(id)-1].utf32_cluster[0])
-#define GRAPHEME_CODEPOINTS(id) (&synthetic_graphemes[-(id)-1].utf32_cluster[1])
-#define GRAPHEME_UTF8(id) (synthetic_graphemes[-(id)-1].utf8)
+#define NUM_GRAPHEME_CODEPOINTS(id) (synthetic_graphemes[-(id) - 1].utf32_cluster[0])
+#define GRAPHEME_CODEPOINTS(id) (&synthetic_graphemes[-(id) - 1].utf32_cluster[1])
+#define GRAPHEME_UTF8(id) (synthetic_graphemes[-(id) - 1].utf8)
// Somewhat arbitrarily chosen, if two short literal ASCII or grapheme chunks
// are concatenated below this length threshold, we just merge them into a
@@ -145,16 +145,17 @@ static int32_t num_synthetic_graphemes = 0;
static Text_t simple_concatenation(Text_t a, Text_t b);
-public Text_t EMPTY_TEXT = {
- .length=0,
- .tag=TEXT_ASCII,
- .ascii=0,
+public
+Text_t EMPTY_TEXT = {
+ .length = 0,
+ .tag = TEXT_ASCII,
+ .ascii = 0,
};
PUREFUNC static bool graphemes_equal(const void *va, const void *vb, const TypeInfo_t *info) {
(void)info;
- ucs4_t *a = *(ucs4_t**)va;
- ucs4_t *b = *(ucs4_t**)vb;
+ ucs4_t *a = *(ucs4_t **)va;
+ ucs4_t *b = *(ucs4_t **)vb;
if (a[0] != b[0]) return false;
for (int i = 0; i < (int)a[0]; i++)
if (a[i] != b[i]) return false;
@@ -163,37 +164,37 @@ PUREFUNC static bool graphemes_equal(const void *va, const void *vb, const TypeI
PUREFUNC static uint64_t grapheme_hash(const void *g, const TypeInfo_t *info) {
(void)info;
- ucs4_t *cluster = *(ucs4_t**)g;
- return siphash24((void*)&cluster[1], sizeof(ucs4_t[cluster[0]]));
+ ucs4_t *cluster = *(ucs4_t **)g;
+ return siphash24((void *)&cluster[1], sizeof(ucs4_t[cluster[0]]));
}
static const TypeInfo_t GraphemeClusterInfo = {
- .size=sizeof(ucs4_t*),
- .align=__alignof__(ucs4_t*),
- .metamethods={
- .equal=graphemes_equal,
- .hash=grapheme_hash,
- },
+ .size = sizeof(ucs4_t *),
+ .align = __alignof__(ucs4_t *),
+ .metamethods =
+ {
+ .equal = graphemes_equal,
+ .hash = grapheme_hash,
+ },
};
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstack-protector"
#endif
-public int32_t get_synthetic_grapheme(const ucs4_t *codepoints, int64_t utf32_len)
-{
- if (utf32_len == 1)
- return (int32_t)*codepoints;
+public
+int32_t get_synthetic_grapheme(const ucs4_t *codepoints, int64_t utf32_len) {
+ if (utf32_len == 1) return (int32_t)*codepoints;
- ucs4_t length_prefixed[1+utf32_len];
+ ucs4_t length_prefixed[1 + utf32_len];
length_prefixed[0] = (ucs4_t)utf32_len;
for (int i = 0; i < utf32_len; i++)
- length_prefixed[i+1] = codepoints[i];
+ length_prefixed[i + 1] = codepoints[i];
ucs4_t *ptr = &length_prefixed[0];
// Optimization for common case of one frequently used synthetic grapheme:
static int32_t last_grapheme = 0;
- if (last_grapheme != 0 && graphemes_equal(&ptr, &synthetic_graphemes[-last_grapheme-1].utf32_cluster, NULL))
+ if (last_grapheme != 0 && graphemes_equal(&ptr, &synthetic_graphemes[-last_grapheme - 1].utf32_cluster, NULL))
return last_grapheme;
TypeInfo_t GraphemeIDLookupTableInfo = *Table$info(&GraphemeClusterInfo, &Int32$info);
@@ -209,12 +210,12 @@ public int32_t get_synthetic_grapheme(const ucs4_t *codepoints, int64_t utf32_le
synthetic_graphemes = new;
}
- int32_t grapheme_id = -(num_synthetic_graphemes+1);
+ int32_t grapheme_id = -(num_synthetic_graphemes + 1);
num_synthetic_graphemes += 1;
// Get UTF8 representation:
uint8_t u8_buf[64];
- size_t u8_len = sizeof(u8_buf)/sizeof(u8_buf[0]);
+ size_t u8_len = sizeof(u8_buf) / sizeof(u8_buf[0]);
uint8_t *u8 = u32_to_u8(codepoints, (size_t)utf32_len, u8_buf, &u8_len);
if (u8 == NULL) fail("Invalid graphemes encountered!");
@@ -223,11 +224,10 @@ public int32_t get_synthetic_grapheme(const ucs4_t *codepoints, int64_t utf32_le
// area with good cache locality:
static void *arena = NULL, *arena_end = NULL;
// Eat up any space needed to make arena 32-bit aligned:
- if ((size_t)arena % __alignof__(ucs4_t) != 0)
- arena += __alignof__(ucs4_t) - ((size_t)arena % __alignof__(ucs4_t));
+ if ((size_t)arena % __alignof__(ucs4_t) != 0) arena += __alignof__(ucs4_t) - ((size_t)arena % __alignof__(ucs4_t));
// If we have filled up this arena, allocate a new one:
- size_t needed_memory = sizeof(ucs4_t[1+utf32_len]) + sizeof(uint8_t[u8_len + 1]);
+ size_t needed_memory = sizeof(ucs4_t[1 + utf32_len]) + sizeof(uint8_t[u8_len + 1]);
if (arena + needed_memory > arena_end) {
// Do reasonably big chunks at a time, so most synthetic codepoints are
// nearby each other in memory and cache locality is good. This is a
@@ -239,28 +239,27 @@ public int32_t get_synthetic_grapheme(const ucs4_t *codepoints, int64_t utf32_le
// Copy length-prefixed UTF32 codepoints into the arena and store where they live:
ucs4_t *codepoint_copy = arena;
- memcpy(codepoint_copy, length_prefixed, sizeof(ucs4_t[1+utf32_len]));
- synthetic_graphemes[-grapheme_id-1].utf32_cluster = codepoint_copy;
- arena += sizeof(ucs4_t[1+utf32_len]);
+ memcpy(codepoint_copy, length_prefixed, sizeof(ucs4_t[1 + utf32_len]));
+ synthetic_graphemes[-grapheme_id - 1].utf32_cluster = codepoint_copy;
+ arena += sizeof(ucs4_t[1 + utf32_len]);
// Copy UTF8 bytes into the arena and store where they live:
uint8_t *utf8_final = arena;
memcpy(utf8_final, u8, sizeof(uint8_t[u8_len]));
utf8_final[u8_len] = '\0'; // Add a terminating NUL byte
- synthetic_graphemes[-grapheme_id-1].utf8 = utf8_final;
+ synthetic_graphemes[-grapheme_id - 1].utf8 = utf8_final;
arena += sizeof(uint8_t[u8_len + 1]);
// Sickos at the unicode consortium decreed that you can have grapheme clusters
// that begin with *prefix* modifiers, so we gotta check for that case:
- synthetic_graphemes[-grapheme_id-1].main_codepoint = length_prefixed[1];
+ synthetic_graphemes[-grapheme_id - 1].main_codepoint = length_prefixed[1];
for (ucs4_t i = 0; i < utf32_len; i++) {
#if _LIBUNISTRING_VERSION >= 0x010200
-// libuinstring version 1.2.0 introduced uc_is_property_prepended_concatenation_mark()
-// It's not critical, but it's technically more correct to have this check:
- if (unlikely(uc_is_property_prepended_concatenation_mark(length_prefixed[1+i])))
- continue;
+ // libuinstring version 1.2.0 introduced uc_is_property_prepended_concatenation_mark()
+ // It's not critical, but it's technically more correct to have this check:
+ if (unlikely(uc_is_property_prepended_concatenation_mark(length_prefixed[1 + i]))) continue;
#endif
- synthetic_graphemes[-grapheme_id-1].main_codepoint = length_prefixed[1+i];
+ synthetic_graphemes[-grapheme_id - 1].main_codepoint = length_prefixed[1 + i];
break;
}
@@ -276,8 +275,8 @@ public int32_t get_synthetic_grapheme(const ucs4_t *codepoints, int64_t utf32_le
#pragma GCC diagnostic pop
#endif
-public int Text$print(FILE *stream, Text_t t)
-{
+public
+int Text$print(FILE *stream, Text_t t) {
if (t.length == 0) return 0;
switch (t.tag) {
@@ -290,14 +289,14 @@ public int Text$print(FILE *stream, Text_t t)
if (grapheme >= 0) {
uint8_t buf[8];
size_t len = sizeof(buf);
- uint8_t *u8 = u32_to_u8((ucs4_t*)&grapheme, 1, buf, &len);
+ uint8_t *u8 = u32_to_u8((ucs4_t *)&grapheme, 1, buf, &len);
if (u8 == NULL) fail("Invalid grapheme encountered: ", grapheme);
written += (int)fwrite(u8, sizeof(char), len, stream);
if (u8 != buf) free(u8);
} else {
const uint8_t *u8 = GRAPHEME_UTF8(grapheme);
assert(u8);
- written += (int)fwrite(u8, sizeof(uint8_t), strlen((char*)u8), stream);
+ written += (int)fwrite(u8, sizeof(uint8_t), strlen((char *)u8), stream);
}
}
return written;
@@ -309,14 +308,14 @@ public int Text$print(FILE *stream, Text_t t)
if (grapheme >= 0) {
uint8_t buf[8];
size_t len = sizeof(buf);
- uint8_t *u8 = u32_to_u8((ucs4_t*)&grapheme, 1, buf, &len);
+ uint8_t *u8 = u32_to_u8((ucs4_t *)&grapheme, 1, buf, &len);
if (u8 == NULL) fail("Invalid grapheme encountered: ", grapheme);
written += (int)fwrite(u8, sizeof(char), len, stream);
if (u8 != buf) free(u8);
} else {
const uint8_t *u8 = GRAPHEME_UTF8(grapheme);
assert(u8);
- written += (int)fwrite(u8, sizeof(uint8_t), strlen((char*)u8), stream);
+ written += (int)fwrite(u8, sizeof(uint8_t), strlen((char *)u8), stream);
}
}
return written;
@@ -332,16 +331,16 @@ public int Text$print(FILE *stream, Text_t t)
static const int64_t min_len_for_depth[MAX_TEXT_DEPTH] = {
// Fibonacci numbers (skipping first two)
- 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946,
- 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578,
- 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296,
- 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976, 7778742049,
+ 1, 2, 3, 5, 8, 13, 21, 34, 55, 89,
+ 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946,
+ 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269,
+ 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141,
+ 267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976, 7778742049,
};
#define IS_BALANCED_TEXT(t) ((t).length >= min_len_for_depth[(t).depth])
-static void insert_balanced_recursive(Text_t balanced_texts[MAX_TEXT_DEPTH], Text_t text)
-{
+static void insert_balanced_recursive(Text_t balanced_texts[MAX_TEXT_DEPTH], Text_t text) {
if (text.tag == TEXT_CONCAT && (!IS_BALANCED_TEXT(text) || text.depth >= MAX_TEXT_DEPTH)) {
insert_balanced_recursive(balanced_texts, *text.left);
insert_balanced_recursive(balanced_texts, *text.right);
@@ -370,8 +369,7 @@ static void insert_balanced_recursive(Text_t balanced_texts[MAX_TEXT_DEPTH], Tex
balanced_texts[i] = accumulator;
}
-static Text_t rebalanced(Text_t a, Text_t b)
-{
+static Text_t rebalanced(Text_t a, Text_t b) {
Text_t balanced_texts[MAX_TEXT_DEPTH];
memset(balanced_texts, 0, sizeof(balanced_texts));
insert_balanced_recursive(balanced_texts, a);
@@ -379,14 +377,12 @@ static Text_t rebalanced(Text_t a, Text_t b)
Text_t ret = EMPTY_TEXT;
for (int i = 0; ret.length < a.length + b.length; i++) {
- if (balanced_texts[i].length)
- ret = simple_concatenation(balanced_texts[i], ret);
+ if (balanced_texts[i].length) ret = simple_concatenation(balanced_texts[i], ret);
}
return ret;
}
-Text_t simple_concatenation(Text_t a, Text_t b)
-{
+Text_t simple_concatenation(Text_t a, Text_t b) {
if (a.length == 0) return b;
if (b.length == 0) return a;
@@ -395,53 +391,53 @@ Text_t simple_concatenation(Text_t a, Text_t b)
// every concatenation to yield a balanced text, since many concatenations
// are ephemeral (e.g. doing a loop repeatedly concatenating without using
// the intermediary values).
- if (new_depth >= MAX_TEXT_DEPTH)
- return rebalanced(a, b);
+ if (new_depth >= MAX_TEXT_DEPTH) return rebalanced(a, b);
Text_t *children = GC_MALLOC(sizeof(Text_t[2]));
children[0] = a;
children[1] = b;
return (Text_t){
- .tag=TEXT_CONCAT,
- .length=a.length + b.length,
- .depth=new_depth,
- .left=&children[0],
- .right=&children[1],
+ .tag = TEXT_CONCAT,
+ .length = a.length + b.length,
+ .depth = new_depth,
+ .left = &children[0],
+ .right = &children[1],
};
}
-static Text_t concat2_assuming_safe(Text_t a, Text_t b)
-{
+static Text_t concat2_assuming_safe(Text_t a, Text_t b) {
if (a.length == 0) return b;
if (b.length == 0) return a;
if (a.tag == TEXT_ASCII && b.tag == TEXT_ASCII && (size_t)(a.length + b.length) <= SHORT_ASCII_LENGTH) {
struct Text_s ret = {
- .tag=TEXT_ASCII,
- .length=a.length + b.length,
+ .tag = TEXT_ASCII,
+ .length = a.length + b.length,
};
ret.ascii = GC_MALLOC_ATOMIC(sizeof(char[ret.length]));
- memcpy((char*)ret.ascii, a.ascii, sizeof(char[a.length]));
- memcpy((char*)&ret.ascii[a.length], b.ascii, sizeof(char[b.length]));
+ memcpy((char *)ret.ascii, a.ascii, sizeof(char[a.length]));
+ memcpy((char *)&ret.ascii[a.length], b.ascii, sizeof(char[b.length]));
return ret;
- } else if (a.tag == TEXT_GRAPHEMES && b.tag == TEXT_GRAPHEMES && (size_t)(a.length + b.length) <= SHORT_GRAPHEMES_LENGTH) {
+ } else if (a.tag == TEXT_GRAPHEMES && b.tag == TEXT_GRAPHEMES
+ && (size_t)(a.length + b.length) <= SHORT_GRAPHEMES_LENGTH) {
struct Text_s ret = {
- .tag=TEXT_GRAPHEMES,
- .length=a.length + b.length,
+ .tag = TEXT_GRAPHEMES,
+ .length = a.length + b.length,
};
ret.graphemes = GC_MALLOC_ATOMIC(sizeof(int32_t[ret.length]));
- memcpy((int32_t*)ret.graphemes, a.graphemes, sizeof(int32_t[a.length]));
- memcpy((int32_t*)&ret.graphemes[a.length], b.graphemes, sizeof(int32_t[b.length]));
+ memcpy((int32_t *)ret.graphemes, a.graphemes, sizeof(int32_t[a.length]));
+ memcpy((int32_t *)&ret.graphemes[a.length], b.graphemes, sizeof(int32_t[b.length]));
return ret;
- } else if (a.tag != TEXT_CONCAT && b.tag != TEXT_CONCAT && (size_t)(a.length + b.length) <= SHORT_GRAPHEMES_LENGTH) {
+ } else if (a.tag != TEXT_CONCAT && b.tag != TEXT_CONCAT
+ && (size_t)(a.length + b.length) <= SHORT_GRAPHEMES_LENGTH) {
// Turn a small bit of ASCII into graphemes if it helps make things smaller
// Text structs come with an extra 8 bytes, so allocate enough to hold the text
struct Text_s ret = {
- .tag=TEXT_GRAPHEMES,
- .length=a.length + b.length,
+ .tag = TEXT_GRAPHEMES,
+ .length = a.length + b.length,
};
ret.graphemes = GC_MALLOC_ATOMIC(sizeof(int32_t[ret.length]));
- int32_t *dest = (int32_t*)ret.graphemes;
+ int32_t *dest = (int32_t *)ret.graphemes;
if (a.tag == TEXT_GRAPHEMES) {
memcpy(dest, a.graphemes, sizeof(int32_t[a.length]));
dest += a.length;
@@ -474,12 +470,11 @@ static Text_t concat2_assuming_safe(Text_t a, Text_t b)
return simple_concatenation(a, b);
}
-static Text_t concat2(Text_t a, Text_t b)
-{
+static Text_t concat2(Text_t a, Text_t b) {
if (a.length == 0) return b;
if (b.length == 0) return a;
- int32_t last_a = Text$get_grapheme(a, a.length-1);
+ int32_t last_a = Text$get_grapheme(a, a.length - 1);
int32_t first_b = Text$get_grapheme(b, 0);
// Magic number, we know that no codepoints below here trigger instability:
@@ -509,60 +504,51 @@ static Text_t concat2(Text_t a, Text_t b)
// Do a normalization run for these two codepoints and see if it looks different.
// Normalization should not exceed 3x in the input length (but if it does, it will be
// handled gracefully)
- ucs4_t norm_buf[3*len];
- size_t norm_length = sizeof(norm_buf)/sizeof(norm_buf[0]);
+ ucs4_t norm_buf[3 * len];
+ size_t norm_length = sizeof(norm_buf) / sizeof(norm_buf[0]);
ucs4_t *normalized = u32_normalize(UNINORM_NFC, codepoints, len, norm_buf, &norm_length);
bool stable = (norm_length == len && memcmp(codepoints, normalized, sizeof(codepoints)) == 0);
if (stable) {
const void *second_grapheme = u32_grapheme_next(normalized, &normalized[norm_length]);
- if (second_grapheme == &normalized[norm_length])
- stable = false;
+ if (second_grapheme == &normalized[norm_length]) stable = false;
}
if likely (stable) {
- if (normalized != norm_buf)
- free(normalized);
+ if (normalized != norm_buf) free(normalized);
return concat2_assuming_safe(a, b);
}
- Text_t glue = Text$from_codepoints((List_t){.data=norm_buf, .length=(int64_t)norm_length, .stride=sizeof(int32_t)});
+ Text_t glue =
+ Text$from_codepoints((List_t){.data = norm_buf, .length = (int64_t)norm_length, .stride = sizeof(int32_t)});
- if (normalized != norm_buf)
- free(normalized);
+ if (normalized != norm_buf) free(normalized);
- if (a.length == 1 && b.length == 1)
- return glue;
- else if (a.length == 1)
- return concat2_assuming_safe(glue, Text$slice(b, I(2), I(b.length)));
- else if (b.length == 1)
- return concat2_assuming_safe(Text$slice(a, I(1), I(a.length-1)), glue);
+ if (a.length == 1 && b.length == 1) return glue;
+ else if (a.length == 1) return concat2_assuming_safe(glue, Text$slice(b, I(2), I(b.length)));
+ else if (b.length == 1) return concat2_assuming_safe(Text$slice(a, I(1), I(a.length - 1)), glue);
else
- return concat2_assuming_safe(
- concat2_assuming_safe(Text$slice(a, I(1), I(a.length-1)), glue),
- Text$slice(b, I(2), I(b.length)));
+ return concat2_assuming_safe(concat2_assuming_safe(Text$slice(a, I(1), I(a.length - 1)), glue),
+ Text$slice(b, I(2), I(b.length)));
}
-public Text_t Text$_concat(int n, Text_t items[n])
-{
+public
+Text_t Text$_concat(int n, Text_t items[n]) {
if (n == 0) return EMPTY_TEXT;
Text_t ret = items[0];
for (int i = 1; i < n; i++) {
- if (items[i].length > 0)
- ret = concat2(ret, items[i]);
+ if (items[i].length > 0) ret = concat2(ret, items[i]);
}
return ret;
}
-public Text_t Text$repeat(Text_t text, Int_t count)
-{
- if (text.length == 0 || Int$is_negative(count))
- return EMPTY_TEXT;
+public
+Text_t Text$repeat(Text_t text, Int_t count) {
+ if (text.length == 0 || Int$is_negative(count)) return EMPTY_TEXT;
Int_t result_len = Int$times(count, I(text.length));
- if (Int$compare_value(result_len, I(1l<<40)) > 0)
- fail("Text repeating would produce too big of an result!");
+ if (Int$compare_value(result_len, I(1l << 40)) > 0) fail("Text repeating would produce too big of an result!");
int64_t count64 = Int64$from_int(count, false);
Text_t ret = text;
@@ -571,19 +557,17 @@ public Text_t Text$repeat(Text_t text, Int_t count)
return ret;
}
-public Int_t Text$width(Text_t text, Text_t language)
-{
- int width = u8_strwidth((const uint8_t*)Text$as_c_string(text), Text$as_c_string(language));
+public
+Int_t Text$width(Text_t text, Text_t language) {
+ int width = u8_strwidth((const uint8_t *)Text$as_c_string(text), Text$as_c_string(language));
return Int$from_int32(width);
}
-static Text_t Text$repeat_to_width(Text_t to_repeat, int64_t target_width, Text_t language)
-{
- if (target_width <= 0)
- return EMPTY_TEXT;
+static Text_t Text$repeat_to_width(Text_t to_repeat, int64_t target_width, Text_t language) {
+ if (target_width <= 0) return EMPTY_TEXT;
const char *lang_str = Text$as_c_string(language);
- int64_t width = (int64_t)u8_strwidth((const uint8_t*)Text$as_c_string(to_repeat), lang_str);
+ int64_t width = (int64_t)u8_strwidth((const uint8_t *)Text$as_c_string(to_repeat), lang_str);
Text_t repeated = EMPTY_TEXT;
int64_t repeated_width = 0;
while (repeated_width + width <= target_width) {
@@ -593,8 +577,8 @@ static Text_t Text$repeat_to_width(Text_t to_repeat, int64_t target_width, Text_
if (repeated_width < target_width) {
for (int64_t i = 0; repeated_width < target_width && i < to_repeat.length; i++) {
- Text_t c = Text$slice(to_repeat, I_small(i+1), I_small(i+1));
- int64_t w = (int64_t)u8_strwidth((const uint8_t*)Text$as_c_string(c), lang_str);
+ Text_t c = Text$slice(to_repeat, I_small(i + 1), I_small(i + 1));
+ int64_t w = (int64_t)u8_strwidth((const uint8_t *)Text$as_c_string(c), lang_str);
if (repeated_width + w > target_width) {
repeated = concat2(repeated, Text$repeat(Text(" "), I(target_width - repeated_width)));
repeated_width = target_width;
@@ -608,35 +592,33 @@ static Text_t Text$repeat_to_width(Text_t to_repeat, int64_t target_width, Text_
return repeated;
}
-public Text_t Text$left_pad(Text_t text, Int_t width, Text_t padding, Text_t language)
-{
- if (padding.length == 0)
- fail("Cannot pad with an empty text!");
+public
+Text_t Text$left_pad(Text_t text, Int_t width, Text_t padding, Text_t language) {
+ if (padding.length == 0) fail("Cannot pad with an empty text!");
int64_t needed = Int64$from_int(width, false) - Int64$from_int(Text$width(text, language), false);
return concat2(Text$repeat_to_width(padding, needed, language), text);
}
-public Text_t Text$right_pad(Text_t text, Int_t width, Text_t padding, Text_t language)
-{
- if (padding.length == 0)
- fail("Cannot pad with an empty text!");
+public
+Text_t Text$right_pad(Text_t text, Int_t width, Text_t padding, Text_t language) {
+ if (padding.length == 0) fail("Cannot pad with an empty text!");
int64_t needed = Int64$from_int(width, false) - Int64$from_int(Text$width(text, language), false);
return concat2(text, Text$repeat_to_width(padding, needed, language));
}
-public Text_t Text$middle_pad(Text_t text, Int_t width, Text_t padding, Text_t language)
-{
- if (padding.length == 0)
- fail("Cannot pad with an empty text!");
+public
+Text_t Text$middle_pad(Text_t text, Int_t width, Text_t padding, Text_t language) {
+ if (padding.length == 0) fail("Cannot pad with an empty text!");
int64_t needed = Int64$from_int(width, false) - Int64$from_int(Text$width(text, language), false);
- return Texts(Text$repeat_to_width(padding, needed/2, language), text, Text$repeat_to_width(padding, (needed+1)/2, language));
+ return Texts(Text$repeat_to_width(padding, needed / 2, language), text,
+ Text$repeat_to_width(padding, (needed + 1) / 2, language));
}
-public Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int)
-{
+public
+Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int) {
int64_t first = Int64$from_int(first_int, false);
int64_t last = Int64$from_int(last_int, false);
if (first == 0) fail("Invalid index: 0");
@@ -647,11 +629,9 @@ public Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int)
if (last > text.length) last = text.length;
- if (first > text.length || last < first)
- return EMPTY_TEXT;
+ if (first > text.length || last < first) return EMPTY_TEXT;
- if (first == 1 && last == text.length)
- return text;
+ if (first == 1 && last == text.length) return text;
while (text.tag == TEXT_CONCAT) {
if (last < text.left->length) {
@@ -662,31 +642,31 @@ public Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int)
text = *text.right;
} else {
return concat2_assuming_safe(Text$slice(*text.left, I(first), I(text.length)),
- Text$slice(*text.right, I(1), I(last-text.left->length)));
+ Text$slice(*text.right, I(1), I(last - text.left->length)));
}
}
switch (text.tag) {
case TEXT_ASCII: {
return (Text_t){
- .tag=TEXT_ASCII,
- .length=last - first + 1,
- .ascii=text.ascii + (first-1),
+ .tag = TEXT_ASCII,
+ .length = last - first + 1,
+ .ascii = text.ascii + (first - 1),
};
}
case TEXT_GRAPHEMES: {
return (Text_t){
- .tag=TEXT_GRAPHEMES,
- .length=last - first + 1,
- .graphemes=text.graphemes + (first-1),
+ .tag = TEXT_GRAPHEMES,
+ .length = last - first + 1,
+ .graphemes = text.graphemes + (first - 1),
};
}
case TEXT_BLOB: {
Text_t ret = (Text_t){
- .tag=TEXT_BLOB,
- .length=last - first + 1,
- .blob.map=text.blob.map,
- .blob.bytes=text.blob.bytes + (first-1),
+ .tag = TEXT_BLOB,
+ .length = last - first + 1,
+ .blob.map = text.blob.map,
+ .blob.bytes = text.blob.bytes + (first - 1),
};
return ret;
}
@@ -695,48 +675,44 @@ public Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int)
return EMPTY_TEXT;
}
-public Text_t Text$from(Text_t text, Int_t first)
-{
- return Text$slice(text, first, I_small(-1));
-}
+public
+Text_t Text$from(Text_t text, Int_t first) { return Text$slice(text, first, I_small(-1)); }
-public Text_t Text$to(Text_t text, Int_t last)
-{
- return Text$slice(text, I_small(1), last);
-}
+public
+Text_t Text$to(Text_t text, Int_t last) { return Text$slice(text, I_small(1), last); }
-public Text_t Text$reversed(Text_t text)
-{
+public
+Text_t Text$reversed(Text_t text) {
switch (text.tag) {
case TEXT_ASCII: {
struct Text_s ret = {
- .tag=TEXT_ASCII,
- .length=text.length,
+ .tag = TEXT_ASCII,
+ .length = text.length,
};
ret.ascii = GC_MALLOC_ATOMIC(sizeof(char[ret.length]));
for (int64_t i = 0; i < text.length; i++)
- ((char*)ret.ascii)[text.length-1-i] = text.ascii[i];
+ ((char *)ret.ascii)[text.length - 1 - i] = text.ascii[i];
return ret;
}
case TEXT_GRAPHEMES: {
struct Text_s ret = {
- .tag=TEXT_GRAPHEMES,
- .length=text.length,
+ .tag = TEXT_GRAPHEMES,
+ .length = text.length,
};
ret.graphemes = GC_MALLOC_ATOMIC(sizeof(int32_t[ret.length]));
for (int64_t i = 0; i < text.length; i++)
- ((int32_t*)ret.graphemes)[text.length-1-i] = text.graphemes[i];
+ ((int32_t *)ret.graphemes)[text.length - 1 - i] = text.graphemes[i];
return ret;
}
case TEXT_BLOB: {
struct Text_s ret = {
- .tag=TEXT_BLOB,
- .length=text.length,
- .blob.map=text.blob.map,
+ .tag = TEXT_BLOB,
+ .length = text.length,
+ .blob.map = text.blob.map,
};
ret.blob.bytes = GC_MALLOC_ATOMIC(sizeof(uint8_t[ret.length]));
for (int64_t i = 0; i < text.length; i++)
- ((uint8_t*)ret.blob.bytes)[text.length-1-i] = text.graphemes[i];
+ ((uint8_t *)ret.blob.bytes)[text.length - 1 - i] = text.graphemes[i];
return ret;
}
case TEXT_CONCAT: {
@@ -747,32 +723,30 @@ public Text_t Text$reversed(Text_t text)
return EMPTY_TEXT;
}
-public PUREFUNC Text_t Text$cluster(Text_t text, Int_t index)
-{
- return Text$slice(text, index, index);
-}
+public
+PUREFUNC Text_t Text$cluster(Text_t text, Int_t index) { return Text$slice(text, index, index); }
-static Text_t Text$from_components(List_t graphemes, Table_t unique_clusters)
-{
- size_t blob_size = (
- sizeof(int32_t[unique_clusters.entries.length])
- + sizeof(uint8_t[graphemes.length]));
+static Text_t Text$from_components(List_t graphemes, Table_t unique_clusters) {
+ size_t blob_size = (sizeof(int32_t[unique_clusters.entries.length]) + sizeof(uint8_t[graphemes.length]));
// If blob optimization will save at least 200 bytes:
if (unique_clusters.entries.length <= 256 && blob_size + 200 < sizeof(int32_t[graphemes.length])) {
Text_t ret = {
- .tag=TEXT_BLOB,
- .length=graphemes.length,
- .depth=0,
+ .tag = TEXT_BLOB,
+ .length = graphemes.length,
+ .depth = 0,
};
void *blob = GC_MALLOC_ATOMIC(blob_size);
int32_t *map = blob;
uint8_t *bytes = blob + sizeof(int32_t[unique_clusters.entries.length]);
for (int64_t i = 0; i < unique_clusters.entries.length; i++) {
- struct { int32_t g; uint8_t b; } *entry = unique_clusters.entries.data + i*unique_clusters.entries.stride;
+ struct {
+ int32_t g;
+ uint8_t b;
+ } *entry = unique_clusters.entries.data + i * unique_clusters.entries.stride;
map[entry->b] = entry->g;
}
for (int64_t i = 0; i < graphemes.length; i++) {
- int32_t g = *(int32_t*)(graphemes.data + i*graphemes.stride);
+ int32_t g = *(int32_t *)(graphemes.data + i * graphemes.stride);
uint8_t *byte = Table$get(unique_clusters, &g, Table$info(&Int32$info, &Byte$info));
assert(byte);
bytes[i] = *byte;
@@ -782,15 +756,15 @@ static Text_t Text$from_components(List_t graphemes, Table_t unique_clusters)
return ret;
} else {
return (Text_t){
- .tag=TEXT_GRAPHEMES,
- .length=graphemes.length,
- .graphemes=graphemes.data,
+ .tag = TEXT_GRAPHEMES,
+ .length = graphemes.length,
+ .graphemes = graphemes.data,
};
}
}
-public OptionalText_t Text$from_strn(const char *str, size_t len)
-{
+public
+OptionalText_t Text$from_strn(const char *str, size_t len) {
int64_t ascii_span = 0;
for (size_t i = 0; i < len && isascii(str[i]); i++)
ascii_span++;
@@ -799,52 +773,48 @@ public OptionalText_t Text$from_strn(const char *str, size_t len)
char *copy = GC_MALLOC_ATOMIC(len);
memcpy(copy, str, len);
return (Text_t){
- .tag=TEXT_ASCII,
- .length=ascii_span,
- .ascii=copy,
+ .tag = TEXT_ASCII,
+ .length = ascii_span,
+ .ascii = copy,
};
}
- if (u8_check((uint8_t*)str, len) != NULL)
- return NONE_TEXT;
+ if (u8_check((uint8_t *)str, len) != NULL) return NONE_TEXT;
List_t graphemes = {};
Table_t unique_clusters = {};
- const uint8_t *pos = (const uint8_t*)str;
- const uint8_t *end = (const uint8_t*)&str[len];
+ const uint8_t *pos = (const uint8_t *)str;
+ const uint8_t *end = (const uint8_t *)&str[len];
// Iterate over grapheme clusters
- for (const uint8_t *next; (next=u8_grapheme_next(pos, end)); pos = next) {
+ for (const uint8_t *next; (next = u8_grapheme_next(pos, end)); pos = next) {
uint32_t buf[256];
- size_t u32_len = sizeof(buf)/sizeof(buf[0]);
- uint32_t *u32s = u8_to_u32(pos, (size_t)(next-pos), buf, &u32_len);
+ size_t u32_len = sizeof(buf) / sizeof(buf[0]);
+ uint32_t *u32s = u8_to_u32(pos, (size_t)(next - pos), buf, &u32_len);
uint32_t buf2[256];
- size_t u32_normlen = sizeof(buf2)/sizeof(buf2[0]);
+ size_t u32_normlen = sizeof(buf2) / sizeof(buf2[0]);
uint32_t *u32s_normalized = u32_normalize(UNINORM_NFC, u32s, u32_len, buf2, &u32_normlen);
int32_t g = get_synthetic_grapheme(u32s_normalized, (int64_t)u32_normlen);
List$insert(&graphemes, &g, I(0), sizeof(int32_t));
- Table$get_or_setdefault(&unique_clusters, int32_t, uint8_t, g, (uint8_t)unique_clusters.entries.length, Table$info(&Int32$info, &Byte$info));
+ Table$get_or_setdefault(&unique_clusters, int32_t, uint8_t, g, (uint8_t)unique_clusters.entries.length,
+ Table$info(&Int32$info, &Byte$info));
if (u32s != buf) free(u32s);
if (u32s_normalized != buf2) free(u32s_normalized);
if (unique_clusters.entries.length >= 256) {
- return concat2_assuming_safe(
- Text$from_components(graphemes, unique_clusters),
- Text$from_strn((const char*)next, (size_t)(end-next)));
+ return concat2_assuming_safe(Text$from_components(graphemes, unique_clusters),
+ Text$from_strn((const char *)next, (size_t)(end - next)));
}
}
return Text$from_components(graphemes, unique_clusters);
}
-public OptionalText_t Text$from_str(const char *str)
-{
- return str ? Text$from_strn(str, strlen(str)) : Text("");
-}
+public
+OptionalText_t Text$from_str(const char *str) { return str ? Text$from_strn(str, strlen(str)) : Text(""); }
-static void u8_buf_append(Text_t text, char **buf, int64_t *capacity, int64_t *i)
-{
+static void u8_buf_append(Text_t text, char **buf, int64_t *capacity, int64_t *i) {
switch (text.tag) {
case TEXT_ASCII: {
if (*i + text.length > (int64_t)*capacity) {
@@ -863,7 +833,7 @@ static void u8_buf_append(Text_t text, char **buf, int64_t *capacity, int64_t *i
if (graphemes[g] >= 0) {
uint8_t u8_buf[64];
size_t u8_len = sizeof(u8_buf);
- uint8_t *u8 = u32_to_u8((ucs4_t*)&graphemes[g], 1, u8_buf, &u8_len);
+ uint8_t *u8 = u32_to_u8((ucs4_t *)&graphemes[g], 1, u8_buf, &u8_len);
if (u8 == NULL) fail("Invalid grapheme encountered: ", graphemes[g]);
if (*i + (int64_t)u8_len > (int64_t)*capacity) {
@@ -894,7 +864,7 @@ static void u8_buf_append(Text_t text, char **buf, int64_t *capacity, int64_t *i
if (grapheme >= 0) {
uint8_t u8_buf[64];
size_t u8_len = sizeof(u8_buf);
- uint8_t *u8 = u32_to_u8((ucs4_t*)&grapheme, 1, u8_buf, &u8_len);
+ uint8_t *u8 = u32_to_u8((ucs4_t *)&grapheme, 1, u8_buf, &u8_len);
if (u8 == NULL) fail("Invalid grapheme encountered: ", grapheme);
if (*i + (int64_t)u8_len > (int64_t)*capacity) {
@@ -928,8 +898,8 @@ static void u8_buf_append(Text_t text, char **buf, int64_t *capacity, int64_t *i
}
}
-public char *Text$as_c_string(Text_t text)
-{
+public
+char *Text$as_c_string(Text_t text) {
int64_t capacity = text.length + 1;
char *buf = GC_MALLOC_ATOMIC((size_t)capacity);
int64_t i = 0;
@@ -943,10 +913,9 @@ public char *Text$as_c_string(Text_t text)
return buf;
}
-PUREFUNC public uint64_t Text$hash(const void *obj, const TypeInfo_t *info)
-{
+PUREFUNC public uint64_t Text$hash(const void *obj, const TypeInfo_t *info) {
(void)info;
- Text_t text = *(Text_t*)obj;
+ Text_t text = *(Text_t *)obj;
siphash sh;
siphashinit(&sh, sizeof(int32_t[text.length]));
@@ -959,40 +928,41 @@ PUREFUNC public uint64_t Text$hash(const void *obj, const TypeInfo_t *info)
const char *bytes = text.ascii;
for (int64_t i = 0; i + 1 < text.length; i += 2) {
tmp.chunks[0] = (int32_t)bytes[i];
- tmp.chunks[1] = (int32_t)bytes[i+1];
+ tmp.chunks[1] = (int32_t)bytes[i + 1];
siphashadd64bits(&sh, tmp.whole);
}
- int32_t last = text.length & 0x1 ? (int32_t)bytes[text.length-1] : 0; // Odd number of graphemes
+ int32_t last = text.length & 0x1 ? (int32_t)bytes[text.length - 1] : 0; // Odd number of graphemes
return siphashfinish_last_part(&sh, (uint64_t)last);
}
case TEXT_GRAPHEMES: {
const int32_t *graphemes = text.graphemes;
for (int64_t i = 0; i + 1 < text.length; i += 2) {
tmp.chunks[0] = graphemes[i];
- tmp.chunks[1] = graphemes[i+1];
+ tmp.chunks[1] = graphemes[i + 1];
siphashadd64bits(&sh, tmp.whole);
}
- int32_t last = text.length & 0x1 ? graphemes[text.length-1] : 0; // Odd number of graphemes
+ int32_t last = text.length & 0x1 ? graphemes[text.length - 1] : 0; // Odd number of graphemes
return siphashfinish_last_part(&sh, (uint64_t)last);
}
case TEXT_BLOB: {
for (int64_t i = 0; i + 1 < text.length; i += 2) {
tmp.chunks[0] = text.blob.map[text.blob.bytes[i]];
- tmp.chunks[1] = text.blob.map[text.blob.bytes[i+1]];
+ tmp.chunks[1] = text.blob.map[text.blob.bytes[i + 1]];
siphashadd64bits(&sh, tmp.whole);
}
- int32_t last = text.length & 0x1 ? text.blob.map[text.blob.bytes[text.length-1]] : 0; // Odd number of graphemes
+ int32_t last =
+ text.length & 0x1 ? text.blob.map[text.blob.bytes[text.length - 1]] : 0; // Odd number of graphemes
return siphashfinish_last_part(&sh, (uint64_t)last);
}
case TEXT_CONCAT: {
TextIter_t state = NEW_TEXT_ITER_STATE(text);
for (int64_t i = 0; i + 1 < text.length; i += 2) {
tmp.chunks[0] = Text$get_grapheme_fast(&state, i);
- tmp.chunks[1] = Text$get_grapheme_fast(&state, i+1);
+ tmp.chunks[1] = Text$get_grapheme_fast(&state, i + 1);
siphashadd64bits(&sh, tmp.whole);
}
- int32_t last = (text.length & 0x1) ? Text$get_grapheme_fast(&state, text.length-1) : 0;
+ int32_t last = (text.length & 0x1) ? Text$get_grapheme_fast(&state, text.length - 1) : 0;
return siphashfinish_last_part(&sh, (uint64_t)last);
}
default: errx(1, "Invalid text");
@@ -1000,8 +970,8 @@ PUREFUNC public uint64_t Text$hash(const void *obj, const TypeInfo_t *info)
return 0;
}
-public int32_t Text$get_grapheme_fast(TextIter_t *state, int64_t index)
-{
+public
+int32_t Text$get_grapheme_fast(TextIter_t *state, int64_t index) {
if (index < 0) return 0;
if (index >= state->stack[0].text.length) return 0;
@@ -1051,18 +1021,17 @@ public int32_t Text$get_grapheme_fast(TextIter_t *state, int64_t index)
return 0;
}
-public uint32_t Text$get_main_grapheme_fast(TextIter_t *state, int64_t index)
-{
+public
+uint32_t Text$get_main_grapheme_fast(TextIter_t *state, int64_t index) {
int32_t g = Text$get_grapheme_fast(state, index);
return (g) >= 0 ? (ucs4_t)(g) : synthetic_graphemes[-(g)-1].main_codepoint;
}
-PUREFUNC public int32_t Text$compare(const void *va, const void *vb, const TypeInfo_t *info)
-{
+PUREFUNC public int32_t Text$compare(const void *va, const void *vb, const TypeInfo_t *info) {
(void)info;
if (va == vb) return 0;
- const Text_t a = *(const Text_t*)va;
- const Text_t b = *(const Text_t*)vb;
+ const Text_t a = *(const Text_t *)va;
+ const Text_t b = *(const Text_t *)vb;
// TODO: make this smarter and more efficient
int64_t len = MAX(a.length, b.length);
@@ -1073,31 +1042,21 @@ PUREFUNC public int32_t Text$compare(const void *va, const void *vb, const TypeI
if (ai == bi) continue;
int32_t cmp;
if (ai > 0 && bi > 0) {
- cmp = u32_cmp((ucs4_t*)&ai, (ucs4_t*)&bi, 1);
+ cmp = u32_cmp((ucs4_t *)&ai, (ucs4_t *)&bi, 1);
} else if (ai > 0) {
- cmp = u32_cmp2(
- (ucs4_t*)&ai, 1,
- GRAPHEME_CODEPOINTS(bi),
- NUM_GRAPHEME_CODEPOINTS(bi));
+ cmp = u32_cmp2((ucs4_t *)&ai, 1, GRAPHEME_CODEPOINTS(bi), NUM_GRAPHEME_CODEPOINTS(bi));
} else if (bi > 0) {
- cmp = u32_cmp2(
- GRAPHEME_CODEPOINTS(ai),
- NUM_GRAPHEME_CODEPOINTS(ai),
- (ucs4_t*)&bi, 1);
+ cmp = u32_cmp2(GRAPHEME_CODEPOINTS(ai), NUM_GRAPHEME_CODEPOINTS(ai), (ucs4_t *)&bi, 1);
} else {
- cmp = u32_cmp2(
- GRAPHEME_CODEPOINTS(ai),
- NUM_GRAPHEME_CODEPOINTS(ai),
- GRAPHEME_CODEPOINTS(bi),
- NUM_GRAPHEME_CODEPOINTS(bi));
+ cmp = u32_cmp2(GRAPHEME_CODEPOINTS(ai), NUM_GRAPHEME_CODEPOINTS(ai), GRAPHEME_CODEPOINTS(bi),
+ NUM_GRAPHEME_CODEPOINTS(bi));
}
if (cmp != 0) return cmp;
}
return 0;
}
-bool _matches(TextIter_t *text_state, TextIter_t *target_state, int64_t pos)
-{
+bool _matches(TextIter_t *text_state, TextIter_t *target_state, int64_t pos) {
for (int64_t i = 0; i < target_state->stack[0].text.length; i++) {
int32_t text_i = Text$get_grapheme_fast(text_state, pos + i);
int32_t prefix_i = Text$get_grapheme_fast(target_state, i);
@@ -1106,10 +1065,8 @@ bool _matches(TextIter_t *text_state, TextIter_t *target_state, int64_t pos)
return true;
}
-PUREFUNC public bool Text$starts_with(Text_t text, Text_t prefix, Text_t *remainder)
-{
- if (text.length < prefix.length)
- return false;
+PUREFUNC public bool Text$starts_with(Text_t text, Text_t prefix, Text_t *remainder) {
+ if (text.length < prefix.length) return false;
TextIter_t text_state = NEW_TEXT_ITER_STATE(text), prefix_state = NEW_TEXT_ITER_STATE(prefix);
if (_matches(&text_state, &prefix_state, 0)) {
if (remainder) *remainder = Text$from(text, Int$from_int64(prefix.length + 1));
@@ -1120,10 +1077,8 @@ PUREFUNC public bool Text$starts_with(Text_t text, Text_t prefix, Text_t *remain
}
}
-PUREFUNC public bool Text$ends_with(Text_t text, Text_t suffix, Text_t *remainder)
-{
- if (text.length < suffix.length)
- return false;
+PUREFUNC public bool Text$ends_with(Text_t text, Text_t suffix, Text_t *remainder) {
+ if (text.length < suffix.length) return false;
TextIter_t text_state = NEW_TEXT_ITER_STATE(text), suffix_state = NEW_TEXT_ITER_STATE(suffix);
if (_matches(&text_state, &suffix_state, text.length - suffix.length)) {
if (remainder) *remainder = Text$to(text, Int$from_int64(text.length - suffix.length));
@@ -1134,18 +1089,17 @@ PUREFUNC public bool Text$ends_with(Text_t text, Text_t suffix, Text_t *remainde
}
}
-public Text_t Text$without_prefix(Text_t text, Text_t prefix)
-{
+public
+Text_t Text$without_prefix(Text_t text, Text_t prefix) {
return Text$starts_with(text, prefix, NULL) ? Text$slice(text, I(prefix.length + 1), I(text.length)) : text;
}
-public Text_t Text$without_suffix(Text_t text, Text_t suffix)
-{
+public
+Text_t Text$without_suffix(Text_t text, Text_t suffix) {
return Text$ends_with(text, suffix, NULL) ? Text$slice(text, I(1), I(text.length - suffix.length)) : text;
}
-static bool _has_grapheme(TextIter_t *text, int32_t g)
-{
+static bool _has_grapheme(TextIter_t *text, int32_t g) {
for (int64_t t = 0; t < text->stack[0].text.length; t++) {
if (g == Text$get_grapheme_fast(text, t)) {
return true;
@@ -1154,8 +1108,8 @@ static bool _has_grapheme(TextIter_t *text, int32_t g)
return false;
}
-public Text_t Text$trim(Text_t text, Text_t to_trim, bool left, bool right)
-{
+public
+Text_t Text$trim(Text_t text, Text_t to_trim, bool left, bool right) {
int64_t first = 0;
TextIter_t text_state = NEW_TEXT_ITER_STATE(text), trim_state = NEW_TEXT_ITER_STATE(to_trim);
if (left) {
@@ -1163,28 +1117,29 @@ public Text_t Text$trim(Text_t text, Text_t to_trim, bool left, bool right)
first += 1;
}
}
- int64_t last = text.length-1;
+ int64_t last = text.length - 1;
if (right) {
while (last >= first && _has_grapheme(&trim_state, Text$get_grapheme_fast(&text_state, last))) {
last -= 1;
}
}
- return (first != 0 || last != text.length-1) ? Text$slice(text, I(first+1), I(last+1)) : text;
+ return (first != 0 || last != text.length - 1) ? Text$slice(text, I(first + 1), I(last + 1)) : text;
}
-public Text_t Text$translate(Text_t text, Table_t translations)
-{
+public
+Text_t Text$translate(Text_t text, Table_t translations) {
TextIter_t text_state = NEW_TEXT_ITER_STATE(text);
Text_t result = EMPTY_TEXT;
int64_t span_start = 0;
List_t replacement_list = translations.entries;
- for (int64_t i = 0; i < text.length; ) {
+ for (int64_t i = 0; i < text.length;) {
for (int64_t r = 0; r < replacement_list.length; r++) {
- struct { Text_t target, replacement; } *entry = replacement_list.data + r*replacement_list.stride;
+ struct {
+ Text_t target, replacement;
+ } *entry = replacement_list.data + r * replacement_list.stride;
TextIter_t target_state = NEW_TEXT_ITER_STATE(entry->target);
if (_matches(&text_state, &target_state, i)) {
- if (i > span_start)
- result = concat2(result, Text$slice(text, I(span_start+1), I(i)));
+ if (i > span_start) result = concat2(result, Text$slice(text, I(span_start + 1), I(i)));
result = concat2(result, entry->replacement);
i += entry->target.length;
@@ -1193,22 +1148,21 @@ public Text_t Text$translate(Text_t text, Table_t translations)
}
}
i += 1;
- found_match: continue;
+ found_match:
+ continue;
}
- if (span_start < text.length)
- result = concat2(result, Text$slice(text, I(span_start+1), I(text.length)));
+ if (span_start < text.length) result = concat2(result, Text$slice(text, I(span_start + 1), I(text.length)));
return result;
}
-public Text_t Text$replace(Text_t text, Text_t target, Text_t replacement)
-{
+public
+Text_t Text$replace(Text_t text, Text_t target, Text_t replacement) {
TextIter_t text_state = NEW_TEXT_ITER_STATE(text), target_state = NEW_TEXT_ITER_STATE(target);
Text_t result = EMPTY_TEXT;
int64_t span_start = 0;
- for (int64_t i = 0; i < text.length; ) {
+ for (int64_t i = 0; i < text.length;) {
if (_matches(&text_state, &target_state, i)) {
- if (i > span_start)
- result = concat2(result, Text$slice(text, I(span_start+1), I(i)));
+ if (i > span_start) result = concat2(result, Text$slice(text, I(span_start + 1), I(i)));
result = concat2(result, replacement);
i += target.length;
@@ -1217,34 +1171,31 @@ public Text_t Text$replace(Text_t text, Text_t target, Text_t replacement)
i += 1;
}
}
- if (span_start < text.length)
- result = concat2(result, Text$slice(text, I(span_start+1), I(text.length)));
+ if (span_start < text.length) result = concat2(result, Text$slice(text, I(span_start + 1), I(text.length)));
return result;
}
-public PUREFUNC bool Text$has(Text_t text, Text_t target)
-{
+public
+PUREFUNC bool Text$has(Text_t text, Text_t target) {
TextIter_t text_state = NEW_TEXT_ITER_STATE(text), target_state = NEW_TEXT_ITER_STATE(target);
for (int64_t i = 0; i < text.length; i++) {
- if (_matches(&text_state, &target_state, i))
- return true;
+ if (_matches(&text_state, &target_state, i)) return true;
}
return false;
}
-public List_t Text$split(Text_t text, Text_t delimiters)
-{
- if (delimiters.length == 0)
- return Text$clusters(text);
+public
+List_t Text$split(Text_t text, Text_t delimiters) {
+ if (delimiters.length == 0) return Text$clusters(text);
TextIter_t text_state = NEW_TEXT_ITER_STATE(text), delim_state = NEW_TEXT_ITER_STATE(delimiters);
List_t splits = {};
- for (int64_t i = 0; i < text.length; ) {
+ for (int64_t i = 0; i < text.length;) {
int64_t span_len = 0;
while (i + span_len < text.length && !_matches(&text_state, &delim_state, i + span_len)) {
span_len += 1;
}
- Text_t slice = Text$slice(text, I(i+1), I(i+span_len));
+ Text_t slice = Text$slice(text, I(i + 1), I(i + span_len));
List$insert(&splits, &slice, I(0), sizeof(slice));
i += span_len + delimiters.length;
if (i == text.length) {
@@ -1255,20 +1206,20 @@ public List_t Text$split(Text_t text, Text_t delimiters)
return splits;
}
-public List_t Text$split_any(Text_t text, Text_t delimiters)
-{
- if (delimiters.length == 0)
- return List(text);
+public
+List_t Text$split_any(Text_t text, Text_t delimiters) {
+ if (delimiters.length == 0) return List(text);
TextIter_t text_state = NEW_TEXT_ITER_STATE(text), delim_state = NEW_TEXT_ITER_STATE(delimiters);
List_t splits = {};
- for (int64_t i = 0; i < text.length; ) {
+ for (int64_t i = 0; i < text.length;) {
int64_t span_len = 0;
- while (i + span_len < text.length && !_has_grapheme(&delim_state, Text$get_grapheme_fast(&text_state, i + span_len))) {
+ while (i + span_len < text.length
+ && !_has_grapheme(&delim_state, Text$get_grapheme_fast(&text_state, i + span_len))) {
span_len += 1;
}
bool trailing_delim = i + span_len < text.length;
- Text_t slice = Text$slice(text, I(i+1), I(i+span_len));
+ Text_t slice = Text$slice(text, I(i + 1), I(i + span_len));
List$insert(&splits, &slice, I(0), sizeof(slice));
i += span_len + 1;
while (i < text.length && _has_grapheme(&delim_state, Text$get_grapheme_fast(&text_state, i))) {
@@ -1288,8 +1239,7 @@ typedef struct {
Text_t delimiter;
} split_iter_state_t;
-static OptionalText_t next_split(split_iter_state_t *state)
-{
+static OptionalText_t next_split(split_iter_state_t *state) {
Text_t text = state->state.stack[0].text;
if (state->i >= text.length) {
if (state->delimiter.length > 0 && state->i == text.length) { // special case
@@ -1310,21 +1260,20 @@ static OptionalText_t next_split(split_iter_state_t *state)
while (i + span_len < text.length && !_matches(&state->state, &delim_state, i + span_len)) {
span_len += 1;
}
- Text_t slice = Text$slice(text, I(i+1), I(i+span_len));
+ Text_t slice = Text$slice(text, I(i + 1), I(i + span_len));
state->i = i + span_len + state->delimiter.length;
return slice;
}
-public Closure_t Text$by_split(Text_t text, Text_t delimiter)
-{
+public
+Closure_t Text$by_split(Text_t text, Text_t delimiter) {
return (Closure_t){
- .fn=(void*)next_split,
- .userdata=new(split_iter_state_t, .state=NEW_TEXT_ITER_STATE(text), .i=0, .delimiter=delimiter),
+ .fn = (void *)next_split,
+ .userdata = new (split_iter_state_t, .state = NEW_TEXT_ITER_STATE(text), .i = 0, .delimiter = delimiter),
};
}
-static OptionalText_t next_split_any(split_iter_state_t *state)
-{
+static OptionalText_t next_split_any(split_iter_state_t *state) {
Text_t text = state->state.stack[0].text;
if (state->i >= text.length) {
if (state->delimiter.length > 0 && state->i == text.length) { // special case
@@ -1335,7 +1284,7 @@ static OptionalText_t next_split_any(split_iter_state_t *state)
}
if (state->delimiter.length == 0) { // special case
- Text_t ret = Text$cluster(text, I(state->i+1));
+ Text_t ret = Text$cluster(text, I(state->i + 1));
state->i += 1;
return ret;
}
@@ -1343,10 +1292,11 @@ static OptionalText_t next_split_any(split_iter_state_t *state)
TextIter_t delim_state = NEW_TEXT_ITER_STATE(state->delimiter);
int64_t i = state->i;
int64_t span_len = 0;
- while (i + span_len < text.length && !_has_grapheme(&delim_state, Text$get_grapheme_fast(&state->state, i + span_len))) {
+ while (i + span_len < text.length
+ && !_has_grapheme(&delim_state, Text$get_grapheme_fast(&state->state, i + span_len))) {
span_len += 1;
}
- Text_t slice = Text$slice(text, I(i+1), I(i+span_len));
+ Text_t slice = Text$slice(text, I(i + 1), I(i + span_len));
i += span_len + 1;
while (i < text.length && _has_grapheme(&delim_state, Text$get_grapheme_fast(&state->state, i))) {
i += 1;
@@ -1355,18 +1305,16 @@ static OptionalText_t next_split_any(split_iter_state_t *state)
return slice;
}
-public Closure_t Text$by_split_any(Text_t text, Text_t delimiters)
-{
+public
+Closure_t Text$by_split_any(Text_t text, Text_t delimiters) {
return (Closure_t){
- .fn=(void*)next_split_any,
- .userdata=new(split_iter_state_t, .state=NEW_TEXT_ITER_STATE(text), .i=0, .delimiter=delimiters),
+ .fn = (void *)next_split_any,
+ .userdata = new (split_iter_state_t, .state = NEW_TEXT_ITER_STATE(text), .i = 0, .delimiter = delimiters),
};
}
-PUREFUNC public bool Text$equal_values(Text_t a, Text_t b)
-{
- if (a.length != b.length)
- return false;
+PUREFUNC public bool Text$equal_values(Text_t a, Text_t b) {
+ if (a.length != b.length) return false;
int64_t len = a.length;
TextIter_t a_state = NEW_TEXT_ITER_STATE(a), b_state = NEW_TEXT_ITER_STATE(b);
// TODO: make this smarter and more efficient
@@ -1378,17 +1326,14 @@ PUREFUNC public bool Text$equal_values(Text_t a, Text_t b)
return true;
}
-PUREFUNC public bool Text$equal(const void *a, const void *b, const TypeInfo_t *info)
-{
+PUREFUNC public bool Text$equal(const void *a, const void *b, const TypeInfo_t *info) {
(void)info;
if (a == b) return true;
- return Text$equal_values(*(Text_t*)a, *(Text_t*)b);
+ return Text$equal_values(*(Text_t *)a, *(Text_t *)b);
}
-PUREFUNC public bool Text$equal_ignoring_case(Text_t a, Text_t b, Text_t language)
-{
- if (a.length != b.length)
- return false;
+PUREFUNC public bool Text$equal_ignoring_case(Text_t a, Text_t b, Text_t language) {
+ if (a.length != b.length) return false;
int64_t len = a.length;
TextIter_t a_state = NEW_TEXT_ITER_STATE(a), b_state = NEW_TEXT_ITER_STATE(b);
const char *uc_language = Text$as_c_string(language);
@@ -1396,76 +1341,79 @@ PUREFUNC public bool Text$equal_ignoring_case(Text_t a, Text_t b, Text_t languag
int32_t ai = Text$get_grapheme_fast(&a_state, i);
int32_t bi = Text$get_grapheme_fast(&b_state, i);
if (ai != bi) {
- const ucs4_t *a_codepoints = ai >= 0 ? (ucs4_t*)&ai : GRAPHEME_CODEPOINTS(ai);
+ const ucs4_t *a_codepoints = ai >= 0 ? (ucs4_t *)&ai : GRAPHEME_CODEPOINTS(ai);
int64_t a_len = ai >= 0 ? 1 : NUM_GRAPHEME_CODEPOINTS(ai);
- const ucs4_t *b_codepoints = bi >= 0 ? (ucs4_t*)&bi : GRAPHEME_CODEPOINTS(bi);
+ const ucs4_t *b_codepoints = bi >= 0 ? (ucs4_t *)&bi : GRAPHEME_CODEPOINTS(bi);
int64_t b_len = bi >= 0 ? 1 : NUM_GRAPHEME_CODEPOINTS(bi);
int cmp = 0;
(void)u32_casecmp(a_codepoints, (size_t)a_len, b_codepoints, (size_t)b_len, uc_language, UNINORM_NFC, &cmp);
- if (cmp != 0)
- return false;
+ if (cmp != 0) return false;
}
}
return true;
}
-public Text_t Text$upper(Text_t text, Text_t language)
-{
+public
+Text_t Text$upper(Text_t text, Text_t language) {
if (text.length == 0) return text;
List_t codepoints = Text$utf32_codepoints(text);
const char *uc_language = Text$as_c_string(language);
size_t out_len = 0;
ucs4_t *upper = u32_toupper(codepoints.data, (size_t)codepoints.length, uc_language, UNINORM_NFC, NULL, &out_len);
- Text_t ret = Text$from_codepoints((List_t){.data=upper, .length=(int64_t)out_len, .stride=sizeof(int32_t)});
+ Text_t ret = Text$from_codepoints((List_t){.data = upper, .length = (int64_t)out_len, .stride = sizeof(int32_t)});
return ret;
}
-public Text_t Text$lower(Text_t text, Text_t language)
-{
+public
+Text_t Text$lower(Text_t text, Text_t language) {
if (text.length == 0) return text;
List_t codepoints = Text$utf32_codepoints(text);
const char *uc_language = Text$as_c_string(language);
size_t out_len = 0;
ucs4_t *lower = u32_tolower(codepoints.data, (size_t)codepoints.length, uc_language, UNINORM_NFC, NULL, &out_len);
- Text_t ret = Text$from_codepoints((List_t){.data=lower, .length=(int64_t)out_len, .stride=sizeof(int32_t)});
+ Text_t ret = Text$from_codepoints((List_t){.data = lower, .length = (int64_t)out_len, .stride = sizeof(int32_t)});
return ret;
}
-public Text_t Text$title(Text_t text, Text_t language)
-{
+public
+Text_t Text$title(Text_t text, Text_t language) {
if (text.length == 0) return text;
List_t codepoints = Text$utf32_codepoints(text);
const char *uc_language = Text$as_c_string(language);
size_t out_len = 0;
ucs4_t *title = u32_totitle(codepoints.data, (size_t)codepoints.length, uc_language, UNINORM_NFC, NULL, &out_len);
- Text_t ret = Text$from_codepoints((List_t){.data=title, .length=(int64_t)out_len, .stride=sizeof(int32_t)});
+ Text_t ret = Text$from_codepoints((List_t){.data = title, .length = (int64_t)out_len, .stride = sizeof(int32_t)});
return ret;
}
-public Text_t Text$quoted(Text_t text, bool colorize, Text_t quotation_mark)
-{
- if (quotation_mark.length != 1)
- fail("Invalid quote text: ", quotation_mark, " (must have length == 1)");
+public
+Text_t Text$quoted(Text_t text, bool colorize, Text_t quotation_mark) {
+ if (quotation_mark.length != 1) fail("Invalid quote text: ", quotation_mark, " (must have length == 1)");
Text_t ret = colorize ? Text("\x1b[35m") : EMPTY_TEXT;
- if (!Text$equal_values(quotation_mark, Text("\"")) && !Text$equal_values(quotation_mark, Text("'")) && !Text$equal_values(quotation_mark, Text("`")))
+ if (!Text$equal_values(quotation_mark, Text("\"")) && !Text$equal_values(quotation_mark, Text("'"))
+ && !Text$equal_values(quotation_mark, Text("`")))
ret = concat2_assuming_safe(ret, Text("$"));
ret = concat2_assuming_safe(ret, quotation_mark);
int32_t quote_char = Text$get_grapheme(quotation_mark, 0);
-#define flush_unquoted() ({ \
- if (unquoted_span > 0) { \
- ret = concat2_assuming_safe(ret, Text$slice(text, I(i-unquoted_span+1), I(i))); \
- unquoted_span = 0; \
- } })
-#define add_escaped(str) ({ \
- flush_unquoted(); \
- if (colorize) ret = concat2_assuming_safe(ret, Text("\x1b[34;1m")); \
- ret = concat2_assuming_safe(ret, Text("\\" str)); \
- if (colorize) ret = concat2_assuming_safe(ret, Text("\x1b[0;35m")); })
+#define flush_unquoted() \
+ ({ \
+ if (unquoted_span > 0) { \
+ ret = concat2_assuming_safe(ret, Text$slice(text, I(i - unquoted_span + 1), I(i))); \
+ unquoted_span = 0; \
+ } \
+ })
+#define add_escaped(str) \
+ ({ \
+ flush_unquoted(); \
+ if (colorize) ret = concat2_assuming_safe(ret, Text("\x1b[34;1m")); \
+ ret = concat2_assuming_safe(ret, Text("\\" str)); \
+ if (colorize) ret = concat2_assuming_safe(ret, Text("\x1b[0;35m")); \
+ })
TextIter_t state = NEW_TEXT_ITER_STATE(text);
int64_t unquoted_span = 0;
int64_t i = 0;
@@ -1488,8 +1436,10 @@ public Text_t Text$quoted(Text_t text, bool colorize, Text_t quotation_mark)
add_escaped("$");
break;
}
- case '\x00' ... '\x06': case '\x0E' ... '\x1A':
- case '\x1C' ... '\x1F': case '\x7F' ... '\x7F': {
+ case '\x00' ... '\x06':
+ case '\x0E' ... '\x1A':
+ case '\x1C' ... '\x1F':
+ case '\x7F' ... '\x7F': {
flush_unquoted();
if (colorize) ret = concat2_assuming_safe(ret, Text("\x1b[34;1m"));
ret = concat2_assuming_safe(ret, Text("\\x"));
@@ -1499,8 +1449,7 @@ public Text_t Text$quoted(Text_t text, bool colorize, Text_t quotation_mark)
'\0',
};
ret = concat2_assuming_safe(ret, Text$from_strn(tmp, 2));
- if (colorize)
- ret = concat2_assuming_safe(ret, Text("\x1b[0;35m"));
+ if (colorize) ret = concat2_assuming_safe(ret, Text("\x1b[0;35m"));
break;
}
default: {
@@ -1522,21 +1471,19 @@ public Text_t Text$quoted(Text_t text, bool colorize, Text_t quotation_mark)
#undef flush_unquoted
ret = concat2_assuming_safe(ret, quotation_mark);
- if (colorize)
- ret = concat2_assuming_safe(ret, Text("\x1b[m"));
+ if (colorize) ret = concat2_assuming_safe(ret, Text("\x1b[m"));
return ret;
}
-public Text_t Text$as_text(const void *vtext, bool colorize, const TypeInfo_t *info)
-{
+public
+Text_t Text$as_text(const void *vtext, bool colorize, const TypeInfo_t *info) {
(void)info;
if (!vtext) return info && info->TextInfo.lang ? Text$from_str(info->TextInfo.lang) : Text("Text");
- Text_t text = *(Text_t*)vtext;
+ Text_t text = *(Text_t *)vtext;
// Figure out the best quotation mark to use:
- bool has_double_quote = false, has_backtick = false,
- has_single_quote = false, needs_escapes = false;
+ bool has_double_quote = false, has_backtick = false, has_single_quote = false, needs_escapes = false;
TextIter_t state = NEW_TEXT_ITER_STATE(text);
for (int64_t i = 0; i < text.length; i++) {
int32_t g = Text$get_grapheme_fast(&state, i);
@@ -1554,39 +1501,33 @@ public Text_t Text$as_text(const void *vtext, bool colorize, const TypeInfo_t *i
// needing to escape them by using single quotes, but only if we don't have
// single quotes or need to escape anything else (because single quotes
// don't have interpolation):
- if (has_double_quote && !has_single_quote)
- quote = Text("'");
+ if (has_double_quote && !has_single_quote) quote = Text("'");
// If there is a double quote, but no backtick, we can save a bit of
// escaping by using backtick instead of double quote:
- else if (has_double_quote && has_single_quote && !has_backtick && !needs_escapes)
- quote = Text("`");
+ else if (has_double_quote && has_single_quote && !has_backtick && !needs_escapes) quote = Text("`");
// Otherwise fall back to double quotes as the default quoting style:
- else
- quote = Text("\"");
+ else quote = Text("\"");
Text_t as_text = Text$quoted(text, colorize, quote);
if (info && info->TextInfo.lang && info != &Text$info)
- as_text = Text$concat(
- colorize ? Text("\x1b[1m$") : Text("$"),
- Text$from_str(info->TextInfo.lang),
- colorize ? Text("\x1b[0m") : Text(""),
- as_text);
+ as_text = Text$concat(colorize ? Text("\x1b[1m$") : Text("$"), Text$from_str(info->TextInfo.lang),
+ colorize ? Text("\x1b[0m") : Text(""), as_text);
return as_text;
}
-public Text_t Text$join(Text_t glue, List_t pieces)
-{
+public
+Text_t Text$join(Text_t glue, List_t pieces) {
if (pieces.length == 0) return EMPTY_TEXT;
- Text_t result = *(Text_t*)pieces.data;
+ Text_t result = *(Text_t *)pieces.data;
for (int64_t i = 1; i < pieces.length; i++) {
- result = Text$concat(result, glue, *(Text_t*)(pieces.data + i*pieces.stride));
+ result = Text$concat(result, glue, *(Text_t *)(pieces.data + i * pieces.stride));
}
return result;
}
-public List_t Text$clusters(Text_t text)
-{
+public
+List_t Text$clusters(Text_t text) {
List_t clusters = {};
for (int64_t i = 1; i <= text.length; i++) {
Text_t cluster = Text$slice(text, I(i), I(i));
@@ -1595,9 +1536,9 @@ public List_t Text$clusters(Text_t text)
return clusters;
}
-public List_t Text$utf32_codepoints(Text_t text)
-{
- List_t codepoints = {.atomic=1};
+public
+List_t Text$utf32_codepoints(Text_t text) {
+ List_t codepoints = {.atomic = 1};
TextIter_t state = NEW_TEXT_ITER_STATE(text);
for (int64_t i = 0; i < text.length; i++) {
int32_t grapheme = Text$get_grapheme_fast(&state, i);
@@ -1613,24 +1554,23 @@ public List_t Text$utf32_codepoints(Text_t text)
return codepoints;
}
-public List_t Text$utf8_bytes(Text_t text)
-{
+public
+List_t Text$utf8_bytes(Text_t text) {
const char *str = Text$as_c_string(text);
- return (List_t){.length=(int64_t)strlen(str), .stride=1, .atomic=1, .data=(void*)str};
+ return (List_t){.length = (int64_t)strlen(str), .stride = 1, .atomic = 1, .data = (void *)str};
}
-static INLINE const char *codepoint_name(ucs4_t c)
-{
+static INLINE const char *codepoint_name(ucs4_t c) {
char *name = GC_MALLOC_ATOMIC(UNINAME_MAX);
char *found_name = unicode_character_name(c, name);
if (found_name) return found_name;
const uc_block_t *block = uc_block(c);
assert(block);
- return String(block->name, "-", hex(c, .no_prefix=true, .uppercase=true));
+ return String(block->name, "-", hex(c, .no_prefix = true, .uppercase = true));
}
-public List_t Text$codepoint_names(Text_t text)
-{
+public
+List_t Text$codepoint_names(Text_t text) {
List_t names = {};
TextIter_t state = NEW_TEXT_ITER_STATE(text);
for (int64_t i = 0; i < text.length; i++) {
@@ -1650,81 +1590,78 @@ public List_t Text$codepoint_names(Text_t text)
return names;
}
-public Text_t Text$from_codepoints(List_t codepoints)
-{
- if (codepoints.stride != sizeof(uint32_t))
- List$compact(&codepoints, sizeof(uint32_t));
+public
+Text_t Text$from_codepoints(List_t codepoints) {
+ if (codepoints.stride != sizeof(uint32_t)) List$compact(&codepoints, sizeof(uint32_t));
List_t graphemes = {};
Table_t unique_clusters = {};
- const uint32_t *pos = (const uint32_t*)codepoints.data;
- const uint32_t *end = (const uint32_t*)&pos[codepoints.length];
+ const uint32_t *pos = (const uint32_t *)codepoints.data;
+ const uint32_t *end = (const uint32_t *)&pos[codepoints.length];
// Iterate over grapheme clusters
- for (const uint32_t *next; (next=u32_grapheme_next(pos, end)); pos = next) {
+ for (const uint32_t *next; (next = u32_grapheme_next(pos, end)); pos = next) {
// Buffer for normalized cluster:
uint32_t buf[256];
- size_t u32_normlen = sizeof(buf)/sizeof(buf[0]);
- uint32_t *u32s_normalized = u32_normalize(UNINORM_NFC, pos, (size_t)(next-pos), buf, &u32_normlen);
+ size_t u32_normlen = sizeof(buf) / sizeof(buf[0]);
+ uint32_t *u32s_normalized = u32_normalize(UNINORM_NFC, pos, (size_t)(next - pos), buf, &u32_normlen);
int32_t g = get_synthetic_grapheme(u32s_normalized, (int64_t)u32_normlen);
List$insert(&graphemes, &g, I(0), sizeof(int32_t));
- Table$get_or_setdefault(
- &unique_clusters, int32_t, uint8_t, g, (uint8_t)unique_clusters.entries.length,
- Table$info(&Int32$info, &Byte$info));
+ Table$get_or_setdefault(&unique_clusters, int32_t, uint8_t, g, (uint8_t)unique_clusters.entries.length,
+ Table$info(&Int32$info, &Byte$info));
if (u32s_normalized != buf) free(u32s_normalized);
if (unique_clusters.entries.length == 256) {
List_t remaining_codepoints = {
- .length=(int64_t)(end-next),
- .data=(void*)next,
- .stride=sizeof(int32_t),
+ .length = (int64_t)(end - next),
+ .data = (void *)next,
+ .stride = sizeof(int32_t),
};
- return concat2_assuming_safe(Text$from_components(graphemes, unique_clusters), Text$from_codepoints(remaining_codepoints));
+ return concat2_assuming_safe(Text$from_components(graphemes, unique_clusters),
+ Text$from_codepoints(remaining_codepoints));
}
}
return Text$from_components(graphemes, unique_clusters);
}
-public OptionalText_t Text$from_codepoint_names(List_t codepoint_names)
-{
+public
+OptionalText_t Text$from_codepoint_names(List_t codepoint_names) {
List_t codepoints = {};
for (int64_t i = 0; i < codepoint_names.length; i++) {
- Text_t *name = ((Text_t*)(codepoint_names.data + i*codepoint_names.stride));
+ Text_t *name = ((Text_t *)(codepoint_names.data + i * codepoint_names.stride));
const char *name_str = Text$as_c_string(*name);
ucs4_t codepoint = unicode_name_character(name_str);
- if (codepoint == UNINAME_INVALID)
- return NONE_TEXT;
+ if (codepoint == UNINAME_INVALID) return NONE_TEXT;
List$insert(&codepoints, &codepoint, I_small(0), sizeof(ucs4_t));
}
return Text$from_codepoints(codepoints);
}
-public OptionalText_t Text$from_bytes(List_t bytes)
-{
- if (bytes.stride != sizeof(int8_t))
- List$compact(&bytes, sizeof(int8_t));
+public
+OptionalText_t Text$from_bytes(List_t bytes) {
+ if (bytes.stride != sizeof(int8_t)) List$compact(&bytes, sizeof(int8_t));
return Text$from_strn(bytes.data, (size_t)bytes.length);
}
-public List_t Text$lines(Text_t text)
-{
+public
+List_t Text$lines(Text_t text) {
List_t lines = {};
TextIter_t state = NEW_TEXT_ITER_STATE(text);
for (int64_t i = 0, line_start = 0; i < text.length; i++) {
int32_t grapheme = Text$get_grapheme_fast(&state, i);
if (grapheme == '\r' && Text$get_grapheme_fast(&state, i + 1) == '\n') { // CRLF
- Text_t line = Text$slice(text, I(line_start+1), I(i));
+ Text_t line = Text$slice(text, I(line_start + 1), I(i));
List$insert(&lines, &line, I_small(0), sizeof(Text_t));
i += 1; // skip one extra for CR
line_start = i + 1;
} else if (grapheme == '\n') { // newline
- Text_t line = Text$slice(text, I(line_start+1), I(i));
+ Text_t line = Text$slice(text, I(line_start + 1), I(i));
List$insert(&lines, &line, I_small(0), sizeof(Text_t));
line_start = i + 1;
- } else if (i == text.length-1 && line_start != i) { // last line
- Text_t line = Text$slice(text, I(line_start+1), I(i+1));
+ } else if (i == text.length - 1 && line_start != i) { // last line
+ Text_t line = Text$slice(text, I(line_start + 1), I(i + 1));
List$insert(&lines, &line, I_small(0), sizeof(Text_t));
}
}
@@ -1736,21 +1673,20 @@ typedef struct {
int64_t i;
} line_iter_state_t;
-static OptionalText_t next_line(line_iter_state_t *state)
-{
+static OptionalText_t next_line(line_iter_state_t *state) {
Text_t text = state->state.stack[0].text;
for (int64_t i = state->i; i < text.length; i++) {
int32_t grapheme = Text$get_grapheme_fast(&state->state, i);
if (grapheme == '\r' && Text$get_grapheme_fast(&state->state, i + 1) == '\n') { // CRLF
- Text_t line = Text$slice(text, I(state->i+1), I(i));
+ Text_t line = Text$slice(text, I(state->i + 1), I(i));
state->i = i + 2; // skip one extra for CR
return line;
} else if (grapheme == '\n') { // newline
- Text_t line = Text$slice(text, I(state->i+1), I(i));
+ Text_t line = Text$slice(text, I(state->i + 1), I(i));
state->i = i + 1;
return line;
- } else if (i == text.length-1 && state->i != i) { // last line
- Text_t line = Text$slice(text, I(state->i+1), I(i+1));
+ } else if (i == text.length - 1 && state->i != i) { // last line
+ Text_t line = Text$slice(text, I(state->i + 1), I(i + 1));
state->i = i + 1;
return line;
}
@@ -1758,81 +1694,75 @@ static OptionalText_t next_line(line_iter_state_t *state)
return NONE_TEXT;
}
-public Closure_t Text$by_line(Text_t text)
-{
+public
+Closure_t Text$by_line(Text_t text) {
return (Closure_t){
- .fn=(void*)next_line,
- .userdata=new(line_iter_state_t, .state=NEW_TEXT_ITER_STATE(text), .i=0),
+ .fn = (void *)next_line,
+ .userdata = new (line_iter_state_t, .state = NEW_TEXT_ITER_STATE(text), .i = 0),
};
}
-PUREFUNC public bool Text$is_none(const void *t, const TypeInfo_t *info)
-{
+PUREFUNC public bool Text$is_none(const void *t, const TypeInfo_t *info) {
(void)info;
- return ((Text_t*)t)->length < 0;
+ return ((Text_t *)t)->length < 0;
}
-public Int_t Text$memory_size(Text_t text)
-{
+public
+Int_t Text$memory_size(Text_t text) {
switch (text.tag) {
- case TEXT_ASCII:
- return Int$from_int64((int64_t)sizeof(Text_t) + (int64_t)sizeof(char[text.length]));
- case TEXT_GRAPHEMES:
- return Int$from_int64((int64_t)sizeof(Text_t) + (int64_t)sizeof(int32_t[text.length]));
+ case TEXT_ASCII: return Int$from_int64((int64_t)sizeof(Text_t) + (int64_t)sizeof(char[text.length]));
+ case TEXT_GRAPHEMES: return Int$from_int64((int64_t)sizeof(Text_t) + (int64_t)sizeof(int32_t[text.length]));
case TEXT_BLOB:
- return Int$from_int64((int64_t)sizeof(Text_t) + (int64_t)((void*)text.blob.bytes - (void*)text.blob.map) + (int64_t)sizeof(uint8_t[text.length]));
+ return Int$from_int64((int64_t)sizeof(Text_t) + (int64_t)((void *)text.blob.bytes - (void *)text.blob.map)
+ + (int64_t)sizeof(uint8_t[text.length]));
case TEXT_CONCAT:
- return Int$plus(
- Int$from_int64((int64_t)sizeof(Text_t)),
- Int$plus(Text$memory_size(*text.left), Text$memory_size(*text.right)));
+ return Int$plus(Int$from_int64((int64_t)sizeof(Text_t)),
+ Int$plus(Text$memory_size(*text.left), Text$memory_size(*text.right)));
default: errx(1, "Invalid text tag: %d", text.tag);
}
}
-public Text_t Text$layout(Text_t text)
-{
+public
+Text_t Text$layout(Text_t text) {
switch (text.tag) {
- case TEXT_ASCII:
- return Texts(Text("ASCII("), Int64$as_text((int64_t[1]){text.length}, false, NULL), Text(")"));
+ case TEXT_ASCII: return Texts(Text("ASCII("), Int64$as_text((int64_t[1]){text.length}, false, NULL), Text(")"));
case TEXT_GRAPHEMES:
return Texts(Text("Graphemes("), Int64$as_text((int64_t[1]){text.length}, false, NULL), Text(")"));
- case TEXT_BLOB:
- return Texts(Text("Blob("), Int64$as_text((int64_t[1]){text.length}, false, NULL), Text(")"));
+ case TEXT_BLOB: return Texts(Text("Blob("), Int64$as_text((int64_t[1]){text.length}, false, NULL), Text(")"));
case TEXT_CONCAT:
return Texts(Text("Concat("), Text$layout(*text.left), Text(", "), Text$layout(*text.right), Text(")"));
default: errx(1, "Invalid text tag: %d", text.tag);
}
}
-public void Text$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *info)
-{
+public
+void Text$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *info) {
(void)info;
- const char *str = Text$as_c_string(*(Text_t*)obj);
+ const char *str = Text$as_c_string(*(Text_t *)obj);
int64_t len = (int64_t)strlen(str);
Int64$serialize(&len, out, pointers, &Int64$info);
fwrite(str, sizeof(char), (size_t)len, out);
}
-public void Text$deserialize(FILE *in, void *out, List_t *pointers, const TypeInfo_t *info)
-{
+public
+void Text$deserialize(FILE *in, void *out, List_t *pointers, const TypeInfo_t *info) {
(void)info;
int64_t len = 0;
Int64$deserialize(in, &len, pointers, &Int64$info);
- if (len < 0)
- fail("Cannot deserialize text with a negative length!");
- char *buf = GC_MALLOC_ATOMIC((size_t)len+1);
- if (fread(buf, sizeof(char), (size_t)len, in) != (size_t)len)
- fail("Not enough data in stream to deserialize");
- buf[len+1] = '\0';
- *(Text_t*)out = Text$from_strn(buf, (size_t)len);
-}
-
-public const TypeInfo_t Text$info = {
- .size=sizeof(Text_t),
- .align=__alignof__(Text_t),
- .tag=TextInfo,
- .TextInfo={.lang="Text"},
- .metamethods=Text$metamethods,
+ if (len < 0) fail("Cannot deserialize text with a negative length!");
+ char *buf = GC_MALLOC_ATOMIC((size_t)len + 1);
+ if (fread(buf, sizeof(char), (size_t)len, in) != (size_t)len) fail("Not enough data in stream to deserialize");
+ buf[len + 1] = '\0';
+ *(Text_t *)out = Text$from_strn(buf, (size_t)len);
+}
+
+public
+const TypeInfo_t Text$info = {
+ .size = sizeof(Text_t),
+ .align = __alignof__(Text_t),
+ .tag = TextInfo,
+ .TextInfo = {.lang = "Text"},
+ .metamethods = Text$metamethods,
};
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/text.h b/src/stdlib/text.h
index cb3f1b90..6bedcb60 100644
--- a/src/stdlib/text.h
+++ b/src/stdlib/text.h
@@ -21,22 +21,20 @@ typedef struct {
int64_t stack_index;
} TextIter_t;
-#define NEW_TEXT_ITER_STATE(t) (TextIter_t){.stack={{t, 0}}, .stack_index=0}
+#define NEW_TEXT_ITER_STATE(t) (TextIter_t){.stack = {{t, 0}}, .stack_index = 0}
-#define Text(str) ((Text_t){.length=sizeof(str)-1, .tag=TEXT_ASCII, .ascii="" str})
+#define Text(str) ((Text_t){.length = sizeof(str) - 1, .tag = TEXT_ASCII, .ascii = "" str})
static inline Text_t Text_from_str_literal(const char *str) {
- return (Text_t){.length=strlen(str), .tag=TEXT_ASCII, .ascii=str};
+ return (Text_t){.length = strlen(str), .tag = TEXT_ASCII, .ascii = str};
}
-static inline Text_t Text_from_text(Text_t t) {
- return t;
-}
+static inline Text_t Text_from_text(Text_t t) { return t; }
-#define convert_to_text(x) _Generic(x, Text_t: Text_from_text, char*: Text$from_str, const char*: Text$from_str)(x)
+#define convert_to_text(x) _Generic(x, Text_t: Text_from_text, char *: Text$from_str, const char *: Text$from_str)(x)
Text_t Text$_concat(int n, Text_t items[n]);
-#define Text$concat(...) Text$_concat(sizeof((Text_t[]){__VA_ARGS__})/sizeof(Text_t), (Text_t[]){__VA_ARGS__})
+#define Text$concat(...) Text$_concat(sizeof((Text_t[]){__VA_ARGS__}) / sizeof(Text_t), (Text_t[]){__VA_ARGS__})
#define Texts(...) Text$concat(MAP_LIST(convert_to_text, __VA_ARGS__))
// int Text$print(FILE *stream, Text_t t);
Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int);
@@ -46,12 +44,12 @@ Text_t Text$reversed(Text_t text);
Text_t Text$cluster(Text_t text, Int_t index_int);
OptionalText_t Text$from_str(const char *str);
OptionalText_t Text$from_strn(const char *str, size_t len);
-PUREFUNC uint64_t Text$hash(const void *text, const TypeInfo_t*);
-PUREFUNC int32_t Text$compare(const void *va, const void *vb, const TypeInfo_t*);
-PUREFUNC bool Text$equal(const void *a, const void *b, const TypeInfo_t*);
+PUREFUNC uint64_t Text$hash(const void *text, const TypeInfo_t *);
+PUREFUNC int32_t Text$compare(const void *va, const void *vb, const TypeInfo_t *);
+PUREFUNC bool Text$equal(const void *a, const void *b, const TypeInfo_t *);
PUREFUNC bool Text$equal_values(Text_t a, Text_t b);
PUREFUNC bool Text$equal_ignoring_case(Text_t a, Text_t b, Text_t language);
-PUREFUNC bool Text$is_none(const void *t, const TypeInfo_t*);
+PUREFUNC bool Text$is_none(const void *t, const TypeInfo_t *);
Text_t Text$upper(Text_t text, Text_t language);
Text_t Text$lower(Text_t text, Text_t language);
Text_t Text$title(Text_t text, Text_t language);
@@ -92,8 +90,7 @@ Text_t Text$layout(Text_t text);
void Text$serialize(const void *obj, FILE *out, Table_t *, const TypeInfo_t *);
void Text$deserialize(FILE *in, void *out, List_t *, const TypeInfo_t *);
-MACROLIKE int32_t Text$get_grapheme(Text_t text, int64_t index)
-{
+MACROLIKE int32_t Text$get_grapheme(Text_t text, int64_t index) {
TextIter_t state = NEW_TEXT_ITER_STATE(text);
return Text$get_grapheme_fast(&state, index);
}
@@ -101,14 +98,15 @@ MACROLIKE int32_t Text$get_grapheme(Text_t text, int64_t index)
extern const TypeInfo_t Text$info;
extern Text_t EMPTY_TEXT;
-#define Text$metamethods { \
- .as_text=Text$as_text, \
- .hash=Text$hash, \
- .compare=Text$compare, \
- .equal=Text$equal, \
- .is_none=Text$is_none, \
- .serialize=Text$serialize, \
- .deserialize=Text$deserialize, \
-}
+#define Text$metamethods \
+ { \
+ .as_text = Text$as_text, \
+ .hash = Text$hash, \
+ .compare = Text$compare, \
+ .equal = Text$equal, \
+ .is_none = Text$is_none, \
+ .serialize = Text$serialize, \
+ .deserialize = Text$deserialize, \
+ }
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/types.c b/src/stdlib/types.c
index 0f17cb21..e64195fe 100644
--- a/src/stdlib/types.c
+++ b/src/stdlib/types.c
@@ -3,24 +3,21 @@
#include <gc.h>
#include <sys/param.h>
-#include "util.h"
#include "text.h"
#include "types.h"
+#include "util.h"
-public Text_t Type$as_text(const void *typeinfo, bool colorize, const TypeInfo_t *type)
-{
+public
+Text_t Type$as_text(const void *typeinfo, bool colorize, const TypeInfo_t *type) {
if (!typeinfo) return Text("Type");
- if (colorize)
- return Text$concat(
- Text("\x1b[36;1m"),
- Text$from_str(type->TypeInfoInfo.type_str),
- Text("\x1b[m"));
- else
- return Text$from_str(type->TypeInfoInfo.type_str);
+ if (colorize) return Text$concat(Text("\x1b[36;1m"), Text$from_str(type->TypeInfoInfo.type_str), Text("\x1b[m"));
+ else return Text$from_str(type->TypeInfoInfo.type_str);
}
-public const TypeInfo_t Void$info = {.size=0, .align=0, .tag=StructInfo};
-public const TypeInfo_t Abort$info = {.size=0, .align=0, .tag=StructInfo};
+public
+const TypeInfo_t Void$info = {.size = 0, .align = 0, .tag = StructInfo};
+public
+const TypeInfo_t Abort$info = {.size = 0, .align = 0, .tag = StructInfo};
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/types.h b/src/stdlib/types.h
index 60f1fcfd..a6509183 100644
--- a/src/stdlib/types.h
+++ b/src/stdlib/types.h
@@ -10,13 +10,13 @@
typedef struct TypeInfo_s TypeInfo_t;
-typedef void (*serialize_fn_t)(const void*, FILE*, Table_t*, const TypeInfo_t*);
-typedef void (*deserialize_fn_t)(FILE*, void*, List_t*, const TypeInfo_t*);
-typedef bool (*is_none_fn_t)(const void*, const TypeInfo_t*);
-typedef uint64_t (*hash_fn_t)(const void*, const TypeInfo_t*);
-typedef int32_t (*compare_fn_t)(const void*, const void*, const TypeInfo_t*);
-typedef bool (*equal_fn_t)(const void*, const void*, const TypeInfo_t*);
-typedef Text_t (*as_text_fn_t)(const void*, bool, const TypeInfo_t*);
+typedef void (*serialize_fn_t)(const void *, FILE *, Table_t *, const TypeInfo_t *);
+typedef void (*deserialize_fn_t)(FILE *, void *, List_t *, const TypeInfo_t *);
+typedef bool (*is_none_fn_t)(const void *, const TypeInfo_t *);
+typedef uint64_t (*hash_fn_t)(const void *, const TypeInfo_t *);
+typedef int32_t (*compare_fn_t)(const void *, const void *, const TypeInfo_t *);
+typedef bool (*equal_fn_t)(const void *, const void *, const TypeInfo_t *);
+typedef Text_t (*as_text_fn_t)(const void *, bool, const TypeInfo_t *);
typedef struct {
hash_fn_t hash;
@@ -36,11 +36,22 @@ typedef struct {
struct TypeInfo_s {
int64_t size, align;
metamethods_t metamethods;
- struct { // Anonymous tagged union for convenience
- enum { OpaqueInfo, StructInfo, EnumInfo, PointerInfo, TextInfo, ListInfo, TableInfo, FunctionInfo,
- OptionalInfo, TypeInfoInfo } tag;
+ struct { // Anonymous tagged union for convenience
+ enum {
+ OpaqueInfo,
+ StructInfo,
+ EnumInfo,
+ PointerInfo,
+ TextInfo,
+ ListInfo,
+ TableInfo,
+ FunctionInfo,
+ OptionalInfo,
+ TypeInfoInfo
+ } tag;
union {
- struct {} OpaqueInfo;
+ struct {
+ } OpaqueInfo;
struct {
const char *sigil;
const TypeInfo_t *pointed;
@@ -72,7 +83,7 @@ struct TypeInfo_s {
const char *name;
NamedType_t *fields;
int num_fields;
- bool is_secret:1, is_opaque:1;
+ bool is_secret : 1, is_opaque : 1;
} StructInfo;
};
};
@@ -84,18 +95,22 @@ extern const TypeInfo_t Abort$info;
Text_t Type$as_text(const void *typeinfo, bool colorize, const TypeInfo_t *type);
-#define Type$info(typestr) &((TypeInfo_t){.size=sizeof(TypeInfo_t), .align=__alignof__(TypeInfo_t), \
- .tag=TypeInfoInfo, .TypeInfoInfo.type_str=typestr, \
- .metamethods={.serialize=cannot_serialize, .deserialize=cannot_deserialize, .as_text=Type$as_text}})
+#define Type$info(typestr) \
+ &((TypeInfo_t){ \
+ .size = sizeof(TypeInfo_t), \
+ .align = __alignof__(TypeInfo_t), \
+ .tag = TypeInfoInfo, \
+ .TypeInfoInfo.type_str = typestr, \
+ .metamethods = {.serialize = cannot_serialize, .deserialize = cannot_deserialize, .as_text = Type$as_text}})
-#define DEFINE_OPTIONAL_TYPE(t, unpadded_size, name) \
- typedef struct { \
- union { \
- t value; \
- struct { \
- char _padding[unpadded_size]; \
- Bool_t is_none; \
- }; \
- }; \
+#define DEFINE_OPTIONAL_TYPE(t, unpadded_size, name) \
+ typedef struct { \
+ union { \
+ t value; \
+ struct { \
+ char _padding[unpadded_size]; \
+ Bool_t is_none; \
+ }; \
+ }; \
} name
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/util.h b/src/stdlib/util.h
index 3b00e6e9..819cecd9 100644
--- a/src/stdlib/util.h
+++ b/src/stdlib/util.h
@@ -3,38 +3,56 @@
// Built-in utility functions
#include <assert.h>
+#include <err.h>
#include <gc.h>
#include <stdbool.h>
#include <string.h>
-#include <err.h>
#define streq(a, b) (((a) == NULL && (b) == NULL) || (((a) == NULL) == ((b) == NULL) && strcmp(a, b) == 0))
#define starts_with(line, prefix) (strncmp(line, prefix, strlen(prefix)) == 0)
-#define ends_with(line, suffix) (strlen(line) >= strlen(suffix) && strcmp(line + strlen(line) - strlen(suffix), suffix) == 0)
-#define new(t, ...) ((t*)memcpy(GC_MALLOC(sizeof(t)), &(t){__VA_ARGS__}, sizeof(t)))
-#define heap(x) (__typeof(x)*)memcpy(GC_MALLOC(sizeof(x)), (__typeof(x)[1]){x}, sizeof(x))
-#define stack(x) (__typeof(x)*)((__typeof(x)[1]){x})
-#define check_initialized(var, init_var, name) *({ if (!init_var) fail("The variable " name " is being accessed before it has been initialized!"); \
- &var; })
+#define ends_with(line, suffix) \
+ (strlen(line) >= strlen(suffix) && strcmp(line + strlen(line) - strlen(suffix), suffix) == 0)
+#define new(t, ...) ((t *)memcpy(GC_MALLOC(sizeof(t)), &(t){__VA_ARGS__}, sizeof(t)))
+#define heap(x) (__typeof(x) *)memcpy(GC_MALLOC(sizeof(x)), (__typeof(x)[1]){x}, sizeof(x))
+#define stack(x) (__typeof(x) *)((__typeof(x)[1]){x})
+#define check_initialized(var, init_var, name) \
+ *({ \
+ if (!init_var) fail("The variable " name " is being accessed before it has been initialized!"); \
+ &var; \
+ })
-#define IF_DECLARE(decl, expr, block) if (({ decl; expr ? ({ block; 1; }) : 0; })) {}
+#define IF_DECLARE(decl, expr, block) \
+ if (({ \
+ decl; \
+ expr ? ({ \
+ block; \
+ 1; \
+ }) \
+ : 0; \
+ })) { \
+ }
-#define WHEN(type, subj, var, body) { type var = subj; switch (var.$tag) body }
+#define WHEN(type, subj, var, body) \
+ { \
+ type var = subj; \
+ switch (var.$tag) \
+ body \
+ }
#ifndef public
-#define public __attribute__ ((visibility ("default")))
+#define public __attribute__((visibility("default")))
#endif
#ifndef PUREFUNC
-#define PUREFUNC __attribute__ ((pure))
+#define PUREFUNC __attribute__((pure))
#endif
#ifndef CONSTFUNC
-#define CONSTFUNC __attribute__ ((const))
+#define CONSTFUNC __attribute__((const))
#endif
#ifndef INLINE
-#define INLINE inline __attribute__ ((always_inline))
+#define INLINE inline __attribute__((always_inline))
#endif
#ifndef likely