blueloveTH 2 месяцев назад
Родитель
Сommit
cac6177656
2 измененных файлов с 151 добавлено и 0 удалено
  1. 55 0
      include/pocketpy/common/serialize.h
  2. 96 0
      src/common/serialize.c

+ 55 - 0
include/pocketpy/common/serialize.h

@@ -0,0 +1,55 @@
+#pragma once
+
+#include <stdint.h>
+
+#include "pocketpy/common/vector.h"
+#include "pocketpy/common/str.h"
+
+
+typedef struct c11_serializer {
+    c11_vector data;
+} c11_serializer;
+
+void c11_serializer__ctor(c11_serializer* self, int16_t magic, int8_t major_ver, int8_t minor_ver);
+void c11_serializer__dtor(c11_serializer* self);
+void c11_serializer__write_cstr(c11_serializer* self, const char*);
+void c11_serializer__write_bytes(c11_serializer* self, const void* data, int size);
+void* c11_serializer__submit(c11_serializer* self, int* size);
+
+typedef struct c11_deserializer {
+    char error_msg[64];
+    const uint8_t* data;
+    int size;
+    int index;
+    int8_t major_ver;
+    int8_t minor_ver;
+} c11_deserializer;
+
+void c11_deserializer__ctor(c11_deserializer* self, const void* data, int size);
+void c11_deserializer__dtor(c11_deserializer* self);
+bool c11_deserializer__check_header(c11_deserializer* self, int16_t magic, int8_t major_ver, int8_t minor_ver);
+const char* c11_deserializer__read_cstr(c11_deserializer* self);
+void* c11_deserializer__read_bytes(c11_deserializer* self, int size);
+
+
+#define DEF_ATOMIC_INLINE_RW(name, T) \
+    inline void c11_serializer__write_##name(c11_serializer* self, T value){ \
+        c11_serializer__write_bytes(self, &value, sizeof(T)); \
+    } \
+    inline T c11_deserializer__read_##name(c11_deserializer* self){ \
+        T* p = (T*)(self->data + self->index); \
+        self->index += sizeof(T); \
+        return *p; \
+    }
+
+
+DEF_ATOMIC_INLINE_RW(size, int)
+DEF_ATOMIC_INLINE_RW(i8, int8_t)
+DEF_ATOMIC_INLINE_RW(i16, int16_t)
+DEF_ATOMIC_INLINE_RW(i32, int32_t)
+DEF_ATOMIC_INLINE_RW(i64, int64_t)
+DEF_ATOMIC_INLINE_RW(f32, float)
+DEF_ATOMIC_INLINE_RW(f64, double)
+DEF_ATOMIC_INLINE_RW(type, py_Type)
+
+#undef DEF_ATOMIC_INLINE_RW

+ 96 - 0
src/common/serialize.c

@@ -0,0 +1,96 @@
+#include "pocketpy/common/serialize.h"
+
+// >>> ord('🥕')
+// 129365
+// >>> ord('🍋')
+// 127819
+
+static uint32_t c11__checksum_32bit(const void* data, int size){
+    const uint8_t* p = (const uint8_t*)data;
+    uint32_t res = 0;
+    for(int i = 0; i < size; i++){
+        res = res * 31 + p[i];
+    }
+    return res;
+}
+
+void c11_serializer__ctor(c11_serializer* self, int16_t magic, int8_t major_ver, int8_t minor_ver){
+    c11_vector__ctor(&self->data, 1);
+    c11_serializer__write_i16(self, magic);
+    c11_serializer__write_i8(self, major_ver);
+    c11_serializer__write_i8(self, minor_ver);
+}
+
+void c11_serializer__dtor(c11_serializer* self){
+    c11_vector__dtor(&self->data);
+}
+
+void c11_serializer__write_cstr(c11_serializer *self, const char* cstr) {
+    int len = (int)strlen(cstr);
+    c11_serializer__write_bytes(self, cstr, len + 1);
+}
+
+void c11_serializer__write_bytes(c11_serializer* self, const void* data, int size){
+    c11_vector__extend(uint8_t, &self->data, data, size);
+}
+
+void* c11_serializer__submit(c11_serializer* self, int* size){
+    uint32_t checksum = c11__checksum_32bit(self->data.data, self->data.length);
+    c11_serializer__write_bytes(self, &checksum, sizeof(uint32_t));
+    return c11_vector__submit(&self->data, size);
+}
+
+void c11_deserializer__ctor(c11_deserializer* self, const void* data, int size){
+    self->data = (const uint8_t*)data;
+    self->size = size;
+    self->index = 0;
+    self->error_msg[0] = '\0';
+}
+
+void c11_deserializer__dtor(c11_deserializer* self){
+    // nothing to do
+}
+
+bool c11_deserializer__error(c11_deserializer* self, const char* msg){
+    snprintf(self->error_msg, sizeof(self->error_msg), "%s", msg);
+    return false;
+}
+
+bool c11_deserializer__check_header(c11_deserializer* self, int16_t magic, int8_t major_ver, int8_t minor_ver){
+    if(self->size < 8){
+        return c11_deserializer__error(self, "bad header: size < 8");
+    }
+    // read 16bit magic
+    int16_t file_magic = c11_deserializer__read_i16(self);
+    if(file_magic != magic){
+        return c11_deserializer__error(self, "bad header: magic mismatch");
+    }
+    // read 16bit version
+    self->major_ver = c11_deserializer__read_i8(self);
+    self->minor_ver = c11_deserializer__read_i8(self);
+
+    // check checksum
+    uint32_t checksum;
+    memcpy(&checksum, self->data + self->size - 4, sizeof(uint32_t));
+    uint32_t actual_checksum = c11__checksum_32bit(self->data, self->size - 4);
+    if(checksum != actual_checksum){
+        return c11_deserializer__error(self, "bad header: checksum mismatch");
+    }
+    // check version
+    if(self->major_ver != major_ver || self->minor_ver > minor_ver){
+        return c11_deserializer__error(self, "bad header: version mismatch");
+    }
+    return true;
+}
+
+const char* c11_deserializer__read_cstr(c11_deserializer* self){
+    const char* p = (const char*)(self->data + self->index);
+    self->index += (strlen(p) + 1);
+    return p;
+}
+
+void* c11_deserializer__read_bytes(c11_deserializer* self, int size){
+    void* p = (void*)(self->data + self->index);
+    self->index += size;
+    return p;
+}