aboutsummaryrefslogtreecommitdiff
path: root/stdlib/optionals.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-11-29 18:09:12 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-11-29 18:09:12 -0500
commitf66f8ad7119207b99f00ea2ea389550ee65db5b3 (patch)
tree5b5a7c887b311e3de2f2cb293b1228598c5b9eb1 /stdlib/optionals.c
parent4b5e4cd1f21582f5e5fa682ab4e4bff252963468 (diff)
Add serialization and deserialization
Diffstat (limited to 'stdlib/optionals.c')
-rw-r--r--stdlib/optionals.c47
1 files changed, 40 insertions, 7 deletions
diff --git a/stdlib/optionals.c b/stdlib/optionals.c
index 810f6172..38cd4700 100644
--- a/stdlib/optionals.c
+++ b/stdlib/optionals.c
@@ -13,7 +13,7 @@
#include "threads.h"
#include "util.h"
-public PUREFUNC bool is_null(const void *obj, const TypeInfo_t *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);
@@ -23,14 +23,14 @@ public PUREFUNC bool is_null(const void *obj, const TypeInfo_t *non_optional_typ
PUREFUNC public uint64_t Optional$hash(const void *obj, const TypeInfo_t *type)
{
- return is_null(obj, type->OptionalInfo.type) ? 0 : generic_hash(obj, type->OptionalInfo.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)
{
if (x == y) return 0;
- bool x_is_null = is_null(x, type->OptionalInfo.type);
- bool y_is_null = is_null(y, type->OptionalInfo.type);
+ bool x_is_null = is_none(x, type->OptionalInfo.type);
+ bool y_is_null = is_none(y, type->OptionalInfo.type);
if (x_is_null && y_is_null) return 0;
else if (x_is_null != y_is_null) return (int32_t)y_is_null - (int32_t)x_is_null;
else return generic_compare(x, y, type->OptionalInfo.type);
@@ -40,8 +40,8 @@ PUREFUNC public bool Optional$equal(const void *x, const void *y, const TypeInfo
{
if (x == y) return true;
- bool x_is_null = is_null(x, type->OptionalInfo.type);
- bool y_is_null = is_null(y, type->OptionalInfo.type);
+ bool x_is_null = is_none(x, type->OptionalInfo.type);
+ bool y_is_null = is_none(y, type->OptionalInfo.type);
if (x_is_null && y_is_null) return true;
else if (x_is_null != y_is_null) return false;
else return generic_equal(x, y, type->OptionalInfo.type);
@@ -52,9 +52,42 @@ public Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo_t
if (!obj)
return Text$concat(generic_as_text(obj, colorize, type->OptionalInfo.type), Text("?"));
- if (is_null(obj, type->OptionalInfo.type))
+ 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)
+{
+ bool has_value = !is_none(obj, type->OptionalInfo.type);
+ fputc((int)has_value, out);
+ if (has_value)
+ _serialize(obj, out, pointers, type->OptionalInfo.type);
+}
+
+public void Optional$deserialize(FILE *in, void *outval, Array_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 = (Text_t){.length=-1};
+ else if (nonnull->tag == ArrayInfo)
+ *(Array_t*)outval = (Array_t){.length=-1};
+ else if (nonnull->tag == TableInfo)
+ *(Table_t*)outval = (Table_t){.entries={.length=-1}};
+ else if (nonnull == &Num$info)
+ *(double*)outval = NAN;
+ else if (nonnull == &Num32$info)
+ *(float*)outval = 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);
+ }
+}
+
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1