Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Visitor pattern implementation for serialization #1456

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
3,354 changes: 2,139 additions & 1,215 deletions distr/flecs.c

Large diffs are not rendered by default.

144 changes: 144 additions & 0 deletions distr/flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@
// #define FLECS_C /**< C API convenience macros, always enabled */
#define FLECS_CPP /**< C++ API */
#define FLECS_MODULE /**< Module support */
#define FLECS_SERIALIZE /**< API for serializing/visiting entity-component graph */
#define FLECS_SCRIPT /**< ECS data definition format */
#define FLECS_STATS /**< Track runtime statistics */
#define FLECS_METRICS /**< Expose component data as statistics */
Expand Down Expand Up @@ -13350,6 +13351,10 @@ void FlecsAlertsImport(
#define FLECS_SCRIPT
#endif

#ifndef FLECS_SERIALIZE
#define FLECS_SERIALIZE
#endif

#ifndef FLECS_JSON_H
#define FLECS_JSON_H

Expand Down Expand Up @@ -13763,6 +13768,142 @@ int ecs_world_to_json_buf(

#endif

#ifdef FLECS_SERIALIZE
#ifdef FLECS_NO_SERIALIZE
#error "FLECS_NO_SERIALIZE failed: SERIALIZE is required by other addons"
#endif

/**
* @file addons/serialize.h
* @brief Visitor-api addon.
*
* Implements visitor pattern to allow parsing of flecs entity-component
* graphs.
*
* Used by the json parser addon to serialize to json.
*/

#ifdef FLECS_SERIALIZE

#ifndef FLECS_META
#define FLECS_META
#endif

#ifndef FLECS_SCRIPT
#define FLECS_SCRIPT
#endif

#ifndef FLECS_SERIALIZE_H
#define FLECS_SERIALIZE_H

/**
* @defgroup c_addons_serialize Serialize
* @ingroup c_addons
* Functions for user-defined serialization.
*
* @{
*/

#ifdef __cplusplus
extern "C" {
#endif

/** Visitor Seriailzation API
*/
typedef struct ecs_visitor_desc_t {
/** Here Be Visitor Functions
* If the visit has a return, it has some form of flow control.
*/

/** visit primitives */
void (*visit_char)(const char value, void* user_data);
void (*visit_u8)(const uint8_t value, void* user_data);
void (*visit_u16)(const uint16_t value, void* user_data);
void (*visit_u32)(const uint32_t value, void* user_data);
void (*visit_u64)(const uint64_t value, void* user_data);
void (*visit_i8)(const int8_t value, void* user_data);
void (*visit_i16)(const int16_t value, void* user_data);
void (*visit_i32)(const int32_t value, void* user_data);
void (*visit_i64)(const int64_t value, void* user_data);
void (*visit_f32)(const float value, void* user_data);
void (*visit_f64)(const double value, void* user_data);
void (*visit_bool)(const bool value, void* user_data);
void (*visit_byte)(const unsigned char value, void* user_data);
void (*visit_uptr)(const uintptr_t value, void* user_data);
void (*visit_iptr)(const intptr_t value, void* user_data);
void (*visit_string)(const char* value, void* user_data);
void (*visit_entity)(const ecs_world_t*, const ecs_entity_t value, void* user_data);
void (*visit_id)(const ecs_world_t*, const ecs_id_t value, void* user_data);

void (*visit_member)(const char* member_name, void* user_data);

void (*visit_enum)(int32_t value, const char* constant_name, void* user_data);
struct {
int (*enter)(uint32_t initial_value, void* user_data);
void (*value)(uint32_t value, const char* constant_name, void* user_data);
void (*exit)(uint32_t values_visited, void* user_data);
} visit_bitmask;
struct {
void (*enter)(size_t size, void* user_data);
void (*next_value)(size_t index, void* user_data);
void (*exit)(void* user_data);
} visit_array;
struct {
void (*enter)(void* user_data);
void (*next_value)(size_t index, void* user_data);
void (*exit)(void* user_data);
} visit_struct;

struct {
void (*enter)(void* user_data);
void (*exit)(void* user_data);
} visit_iter_result;

void* (*exit)(void* user_data);
void* (*error)(void* user_data);

/** User Data that is handed out to each visit.
* Ex: JSON serialization passes a string buffer
*/
void* user_data;

/** Used to indicate an error has occurred while visiting
*/
bool _error;
} ecs_visitor_desc_t;


int ecs_ser_ptr(
const ecs_world_t *world,
ecs_entity_t type,
const void *ptr,
ecs_visitor_desc_t *visitor_desc);

int ecs_ser_array(
const ecs_world_t *world,
ecs_entity_t type,
const void *ptr,
int32_t count,
ecs_visitor_desc_t *visitor_desc);

void* ecs_ser_entity(
const ecs_world_t *stage,
ecs_entity_t entity,
ecs_visitor_desc_t *visitor_desc,
const ecs_entity_to_json_desc_t *desc);

#ifdef __cplusplus
}
#endif

#endif

/** @} */

#endif

#endif

#ifdef FLECS_UNITS
#ifdef FLECS_NO_UNITS
#error "FLECS_NO_UNITS failed: UNITS is required by other addons"
Expand Down Expand Up @@ -14155,6 +14296,9 @@ void FlecsUnitsImport(
#define FLECS_DOC
#endif

#ifndef FLECS_SERIALIZE
#define FLECS_SERIALIZE
#endif

#ifndef FLECS_SCRIPT_H
#define FLECS_SCRIPT_H
Expand Down
1 change: 1 addition & 0 deletions include/flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@
// #define FLECS_C /**< C API convenience macros, always enabled */
#define FLECS_CPP /**< C++ API */
#define FLECS_MODULE /**< Module support */
#define FLECS_SERIALIZE /**< API for serializing/visiting entity-component graph */
#define FLECS_SCRIPT /**< ECS data definition format */
#define FLECS_STATS /**< Track runtime statistics */
#define FLECS_METRICS /**< Expose component data as statistics */
Expand Down
4 changes: 4 additions & 0 deletions include/flecs/addons/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
#define FLECS_SCRIPT
#endif

#ifndef FLECS_SERIALIZE
#define FLECS_SERIALIZE
#endif

#ifndef FLECS_JSON_H
#define FLECS_JSON_H

Expand Down
3 changes: 3 additions & 0 deletions include/flecs/addons/script.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#define FLECS_DOC
#endif

#ifndef FLECS_SERIALIZE
#define FLECS_SERIALIZE
#endif

#ifndef FLECS_SCRIPT_H
#define FLECS_SCRIPT_H
Expand Down
129 changes: 129 additions & 0 deletions include/flecs/addons/serialize.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@

/**
* @file addons/serialize.h
* @brief Visitor-api addon.
*
* Implements visitor pattern to allow parsing of flecs entity-component
* graphs.
*
* Used by the json parser addon to serialize to json.
*/

#ifdef FLECS_SERIALIZE

#ifndef FLECS_META
#define FLECS_META
#endif

#ifndef FLECS_SCRIPT
#define FLECS_SCRIPT
#endif

#ifndef FLECS_SERIALIZE_H
#define FLECS_SERIALIZE_H

/**
* @defgroup c_addons_serialize Serialize
* @ingroup c_addons
* Functions for user-defined serialization.
*
* @{
*/

#ifdef __cplusplus
extern "C" {
#endif

/** Visitor Seriailzation API
*/
typedef struct ecs_visitor_desc_t {
/** Here Be Visitor Functions
* If the visit has a return, it has some form of flow control.
*/

/** visit primitives */
void (*visit_char)(const char value, void* user_data);
void (*visit_u8)(const uint8_t value, void* user_data);
void (*visit_u16)(const uint16_t value, void* user_data);
void (*visit_u32)(const uint32_t value, void* user_data);
void (*visit_u64)(const uint64_t value, void* user_data);
void (*visit_i8)(const int8_t value, void* user_data);
void (*visit_i16)(const int16_t value, void* user_data);
void (*visit_i32)(const int32_t value, void* user_data);
void (*visit_i64)(const int64_t value, void* user_data);
void (*visit_f32)(const float value, void* user_data);
void (*visit_f64)(const double value, void* user_data);
void (*visit_bool)(const bool value, void* user_data);
void (*visit_byte)(const unsigned char value, void* user_data);
void (*visit_uptr)(const uintptr_t value, void* user_data);
void (*visit_iptr)(const intptr_t value, void* user_data);
void (*visit_string)(const char* value, void* user_data);
void (*visit_entity)(const ecs_world_t*, const ecs_entity_t value, void* user_data);
void (*visit_id)(const ecs_world_t*, const ecs_id_t value, void* user_data);

void (*visit_member)(const char* member_name, void* user_data);

void (*visit_enum)(int32_t value, const char* constant_name, void* user_data);
struct {
int (*enter)(uint32_t initial_value, void* user_data);
void (*value)(uint32_t value, const char* constant_name, void* user_data);
void (*exit)(uint32_t values_visited, void* user_data);
} visit_bitmask;
struct {
void (*enter)(size_t size, void* user_data);
void (*next_value)(size_t index, void* user_data);
void (*exit)(void* user_data);
} visit_array;
struct {
void (*enter)(void* user_data);
void (*next_value)(size_t index, void* user_data);
void (*exit)(void* user_data);
} visit_struct;

struct {
void (*enter)(void* user_data);
void (*exit)(void* user_data);
} visit_iter_result;

void* (*exit)(void* user_data);
void* (*error)(void* user_data);

/** User Data that is handed out to each visit.
* Ex: JSON serialization passes a string buffer
*/
void* user_data;

/** Used to indicate an error has occurred while visiting
*/
bool _error;
} ecs_visitor_desc_t;


int ecs_ser_ptr(
const ecs_world_t *world,
ecs_entity_t type,
const void *ptr,
ecs_visitor_desc_t *visitor_desc);

int ecs_ser_array(
const ecs_world_t *world,
ecs_entity_t type,
const void *ptr,
int32_t count,
ecs_visitor_desc_t *visitor_desc);

void* ecs_ser_entity(
const ecs_world_t *stage,
ecs_entity_t entity,
ecs_visitor_desc_t *visitor_desc,
const ecs_entity_to_json_desc_t *desc);

#ifdef __cplusplus
}
#endif

#endif

/** @} */

#endif
7 changes: 7 additions & 0 deletions include/flecs/private/addons.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@
#include "../addons/json.h"
#endif

#ifdef FLECS_SERIALIZE
#ifdef FLECS_NO_SERIALIZE
#error "FLECS_NO_SERIALIZE failed: SERIALIZE is required by other addons"
#endif
#include "../addons/serialize.h"
#endif

#ifdef FLECS_UNITS
#ifdef FLECS_NO_UNITS
#error "FLECS_NO_UNITS failed: UNITS is required by other addons"
Expand Down
4 changes: 4 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ flecs_src = files(
'src/addons/json/serialize_iter_result_table.c',
'src/addons/json/serialize_iter_result.c',
'src/addons/json/serialize_iter.c',
'src/addons/json/serialize_json.c',
'src/addons/json/serialize_query_info.c',
'src/addons/json/serialize_type_info.c',
'src/addons/json/serialize_value.c',
Expand Down Expand Up @@ -65,12 +66,15 @@ flecs_src = files(
'src/addons/script/query_parser.c',
'src/addons/script/script.c',
'src/addons/script/serialize.c',
'src/addons/script/serialize_expr.c',
'src/addons/script/serialize_value.c',
'src/addons/script/tokenizer.c',
'src/addons/script/vars.c',
'src/addons/script/visit_eval.c',
'src/addons/script/visit_free.c',
'src/addons/script/visit_to_str.c',
'src/addons/script/visit.c',
'src/addons/serialize/serialize.c',
'src/addons/system/system.c',
'src/addons/timer.c',
'src/addons/units.c',
Expand Down
6 changes: 0 additions & 6 deletions src/addons/json/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -694,10 +694,4 @@ void flecs_json_id_member(
}
}

ecs_primitive_kind_t flecs_json_op_to_primitive_kind(
ecs_meta_type_op_kind_t kind)
{
return kind - EcsOpPrimitive;
}

#endif
Loading
Loading