code / tomo

Lines41.3K C23.7K Markdown9.7K YAML5.0K Tomo2.3K
7 others 763
Python231 Shell230 make212 INI47 Text21 SVG16 Lua6
(100 lines)
1 // Metamethods are methods that all types share for hashing, equality, comparison, and textifying
3 #include <stdint.h>
4 #include <string.h>
6 #include "lists.h"
7 #include "metamethods.h"
8 #include "siphash.h"
9 #include "tables.h"
10 #include "types.h"
11 #include "util.h"
13 PUREFUNC public uint64_t generic_hash(const void *obj, const TypeInfo_t *type) {
14 if (type->metamethods.hash) return type->metamethods.hash(obj, type);
16 return siphash24((void *)obj, (size_t)(type->size));
19 PUREFUNC public int32_t generic_compare(const void *x, const void *y, const TypeInfo_t *type) {
20 if (x == y) return 0;
22 if (type->metamethods.compare) return type->metamethods.compare(x, y, type);
24 return (int32_t)memcmp((void *)x, (void *)y, (size_t)(type->size));
27 PUREFUNC public bool generic_equal(const void *x, const void *y, const TypeInfo_t *type) {
28 if (x == y) return true;
30 if (type->metamethods.equal) return type->metamethods.equal(x, y, type);
32 return (generic_compare(x, y, type) == 0);
35 public
36 Text_t generic_as_text(const void *obj, bool colorize, const TypeInfo_t *type) {
37 if (!type->metamethods.as_text) fail("No text metamethod provided for type!");
39 return type->metamethods.as_text(obj, colorize, type);
42 public
43 void _serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
44 if (type->metamethods.serialize) return type->metamethods.serialize(obj, out, pointers, type);
46 fwrite(obj, (size_t)type->size, 1, out);
49 public
50 List_t generic_serialize(const void *x, const TypeInfo_t *type) {
51 char *buf = NULL;
52 size_t size = 0;
53 FILE *stream = open_memstream(&buf, &size);
54 Table_t pointers = EMPTY_TABLE;
55 _serialize(x, stream, &pointers, type);
56 fclose(stream);
57 List_t bytes = {
58 .data = GC_MALLOC_ATOMIC(size),
59 .length = (uint64_t)size,
60 .stride = 1,
61 .atomic = 1,
62 };
63 memcpy(bytes.data, buf, size);
64 free(buf);
65 return bytes;
68 public
69 void _deserialize(FILE *input, void *outval, List_t *pointers, const TypeInfo_t *type) {
70 if (type->metamethods.deserialize) {
71 type->metamethods.deserialize(input, outval, pointers, type);
72 return;
75 if (fread(outval, (size_t)type->size, 1, input) != 1) fail("Not enough data in stream to deserialize");
78 public
79 void generic_deserialize(List_t bytes, void *outval, const TypeInfo_t *type) {
80 if (bytes.stride != 1) List$compact(&bytes, 1);
82 FILE *input = fmemopen(bytes.data, (size_t)bytes.length, "r");
83 List_t pointers = EMPTY_LIST;
84 _deserialize(input, outval, &pointers, type);
85 fclose(input);
88 __attribute__((noreturn)) public
89 void cannot_serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
90 (void)obj, (void)out, (void)pointers;
91 Text_t typestr = generic_as_text(NULL, false, type);
92 fail("Values of type ", typestr, " cannot be serialized or deserialized!");
95 __attribute__((noreturn)) public
96 void cannot_deserialize(FILE *in, void *obj, List_t *pointers, const TypeInfo_t *type) {
97 (void)obj, (void)in, (void)pointers;
98 Text_t typestr = generic_as_text(NULL, false, type);
99 fail("Values of type ", typestr, " cannot be serialized or deserialized!");