diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-11-29 18:09:12 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-11-29 18:09:12 -0500 |
| commit | f66f8ad7119207b99f00ea2ea389550ee65db5b3 (patch) | |
| tree | 5b5a7c887b311e3de2f2cb293b1228598c5b9eb1 /stdlib/structs.c | |
| parent | 4b5e4cd1f21582f5e5fa682ab4e4bff252963468 (diff) | |
Add serialization and deserialization
Diffstat (limited to 'stdlib/structs.c')
| -rw-r--r-- | stdlib/structs.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/stdlib/structs.c b/stdlib/structs.c index c23e4b7b..624fe933 100644 --- a/stdlib/structs.c +++ b/stdlib/structs.c @@ -167,4 +167,58 @@ 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) +{ + 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; + fputc((int)b, out); + bit_offset += 1; + if (bit_offset >= 8) { + byte_offset += 1; + bit_offset = 0; + } + } else { + if (bit_offset > 0) { + byte_offset += 1; + bit_offset = 0; + } + if (field.type->align && byte_offset % field.type->align > 0) + byte_offset += field.type->align - (byte_offset % field.type->align); + _serialize(obj + byte_offset, out, pointers, field.type); + byte_offset += field.type->size; + } + } +} + +public void Struct$deserialize(FILE *in, void *outval, Array_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); + bit_offset += 1; + if (bit_offset >= 8) { + byte_offset += 1; + bit_offset = 0; + } + } else { + if (bit_offset > 0) { + byte_offset += 1; + bit_offset = 0; + } + if (field.type->align && byte_offset % field.type->align > 0) + byte_offset += field.type->align - (byte_offset % field.type->align); + _deserialize(in, outval + byte_offset, pointers, field.type); + byte_offset += field.type->size; + } + } +} + // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 |
