Skip to content

Commit

Permalink
#762 add option to JSON serializer to serialize entire tables
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed Feb 2, 2023
1 parent 31fa902 commit 76cfd3d
Show file tree
Hide file tree
Showing 11 changed files with 306 additions and 35 deletions.
3 changes: 1 addition & 2 deletions examples/cpp/reflection/ser_opaque_type/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ int main(int, char *[]) {

// Create dummy value & serialize it
OpaqueType v = {10, 20};
auto json = ecs.to_json(&v);
std::cout << json << std::endl;
std::cout << ecs.to_json(&v) << std::endl;

// Output:
// {"x":10, "y":20}
Expand Down
6 changes: 2 additions & 4 deletions examples/cpp/reflection/ser_std_string/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ struct StringComponent {
// Serializer function for std::string
int std_string_ser(const flecs::serializer *s, const std::string *data) {
const char *str = data->c_str();
s->value(flecs::String, &str); // Serializer-specific string serialization
return 0;
return s->value(flecs::String, &str); // Serializer-specific string serialization
}

int main(int, char *[]) {
Expand All @@ -32,8 +31,7 @@ int main(int, char *[]) {

// Create dummy value & serialize it
StringComponent v = {"foo", "bar"};
auto json = ecs.to_json(&v);
std::cout << json << std::endl;
std::cout << ecs.to_json(&v) << std::endl;

// Output:
// {"a": "foo", "b": "bar"}
Expand Down
6 changes: 2 additions & 4 deletions examples/cpp/reflection/ser_std_vector/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ struct VectorComponent {
// Serializer function for std::string
int std_string_ser(const flecs::serializer *s, const std::string *data) {
const char *str = data->c_str();
s->value(flecs::String, &str); // Serializer-specific string serialization
return 0;
return s->value(flecs::String, &str); // Serializer-specific string serialization
}

// Serializer function for std::vector
Expand Down Expand Up @@ -54,8 +53,7 @@ int main(int, char *[]) {

// Create dummy value & serialize it
VectorComponent v = {{1, 2, 3}, {"foo", "bar"}};
auto json = ecs.to_json(&v);
std::cout << json << std::endl;
std::cout << ecs.to_json(&v) << std::endl;

// Output:
// {"ints":[1, 2, 3], "strings":["foo", "bar"]}
Expand Down
113 changes: 103 additions & 10 deletions flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -27371,7 +27371,7 @@ void FlecsMetaImport(
{.name = "StructType"},
{.name = "ArrayType"},
{.name = "VectorType"},
{.name = "CustomType"}
{.name = "OpaqueType"}
}
});

Expand Down Expand Up @@ -27440,7 +27440,7 @@ void FlecsMetaImport(
ecs_struct_init(world, &(ecs_struct_desc_t){
.entity = ecs_id(EcsOpaque),
.members = {
{ .name = (char*)"type", .type = ecs_id(ecs_entity_t) },
{ .name = (char*)"as_type", .type = ecs_id(ecs_entity_t) },
{ .name = (char*)"serialize", .type = ecs_id(ecs_uptr_t) }
}
});
Expand Down Expand Up @@ -34738,7 +34738,29 @@ void flecs_json_serialize_iter_result_ids(

for (int i = 0; i < it->field_count; i ++) {
flecs_json_next(buf);
flecs_json_serialize_id(world, ecs_field_id(it, i + 1), buf);
flecs_json_serialize_id(world, ecs_field_id(it, i + 1), buf);
}

flecs_json_array_pop(buf);
}

static
void flecs_json_serialize_iter_result_table_type(
const ecs_world_t *world,
const ecs_iter_t *it,
ecs_strbuf_t *buf)
{
if (!it->table) {
return;
}

flecs_json_memberl(buf, "ids");
flecs_json_array_push(buf);

ecs_type_t *type = &it->table->type;
for (int i = 0; i < type->count; i ++) {
flecs_json_next(buf);
flecs_json_serialize_id(world, type->array[i], buf);
}

flecs_json_array_pop(buf);
Expand Down Expand Up @@ -35045,6 +35067,63 @@ void flecs_json_serialize_iter_result_values(
flecs_json_array_pop(buf);
}

static
void flecs_json_serialize_iter_result_columns(
const ecs_world_t *world,
const ecs_iter_t *it,
ecs_strbuf_t *buf)
{
ecs_table_t *table = it->table;
if (!table || !table->storage_table) {
return;
}

flecs_json_memberl(buf, "values");
flecs_json_array_push(buf);

ecs_type_t *type = &table->type;
int32_t *storage_map = table->storage_map;
ecs_assert(storage_map != NULL, ECS_INTERNAL_ERROR, NULL);

for (int i = 0; i < type->count; i ++) {
int32_t storage_column = -1;
if (storage_map) {
storage_column = storage_map[i];
}

ecs_strbuf_list_next(buf);

if (storage_column == -1) {
ecs_strbuf_appendch(buf, '0');
continue;
}

ecs_entity_t typeid = table->type_info[storage_column]->component;
if (!typeid) {
ecs_strbuf_appendch(buf, '0');
continue;
}

const EcsComponent *comp = ecs_get(world, typeid, EcsComponent);
if (!comp) {
ecs_strbuf_appendch(buf, '0');
continue;
}

const EcsMetaTypeSerialized *ser = ecs_get(
world, typeid, EcsMetaTypeSerialized);
if (!ser) {
ecs_strbuf_appendch(buf, '0');
continue;
}

void *ptr = ecs_vec_first(&table->data.columns[storage_column]);
array_to_json_buf_w_type_data(world, ptr, it->count, buf, comp, ser);
}

flecs_json_array_pop(buf);
}

static
void flecs_json_serialize_iter_result(
const ecs_world_t *world,
Expand All @@ -35057,12 +35136,16 @@ void flecs_json_serialize_iter_result(

/* Each result can be matched with different component ids. Add them to
* the result so clients know with which component an entity was matched */
if (!desc || desc->serialize_ids) {
flecs_json_serialize_iter_result_ids(world, it, buf);
if (desc && desc->serialize_table) {
flecs_json_serialize_iter_result_table_type(world, it, buf);
} else {
if (!desc || desc->serialize_ids) {
flecs_json_serialize_iter_result_ids(world, it, buf);
}
}

/* Include information on which entity the term is matched with */
if (!desc || desc->serialize_ids) {
if (!desc || (desc->serialize_sources && !desc->serialize_table)) {
flecs_json_serialize_iter_result_sources(world, it, buf);
}

Expand All @@ -35082,12 +35165,12 @@ void flecs_json_serialize_iter_result(
}

/* Include information on which terms are set, to support optional terms */
if (!desc || desc->serialize_is_set) {
if (!desc || (desc->serialize_is_set && !desc->serialize_table)) {
flecs_json_serialize_iter_result_is_set(it, buf);
}

/* Write entity ids for current result (for queries with This terms) */
if (!desc || desc->serialize_entities) {
if (!desc || desc->serialize_entities || desc->serialize_table) {
flecs_json_serialize_iter_result_entities(world, it, buf);
}

Expand All @@ -35107,8 +35190,12 @@ void flecs_json_serialize_iter_result(
}

/* Serialize component values */
if (!desc || desc->serialize_values) {
flecs_json_serialize_iter_result_values(world, it, buf);
if (desc && desc->serialize_table) {
flecs_json_serialize_iter_result_columns(world, it, buf);
} else {
if (!desc || desc->serialize_values) {
flecs_json_serialize_iter_result_values(world, it, buf);
}
}

flecs_json_object_pop(buf);
Expand Down Expand Up @@ -35147,6 +35234,12 @@ int ecs_iter_to_json_buf(
/* Use instancing for improved performance */
ECS_BIT_SET(it->flags, EcsIterIsInstanced);

/* If serializing entire table, don't bother letting the iterator populate
* data fields as we'll be iterating all columns. */
if (desc && desc->serialize_table) {
ECS_BIT_SET(it->flags, EcsIterIsFilter);
}

ecs_iter_next_action_t next = it->next;
while (next(it)) {
flecs_json_serialize_iter_result(world, it, buf, desc);
Expand Down
6 changes: 4 additions & 2 deletions flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11717,6 +11717,7 @@ typedef struct ecs_iter_to_json_desc_t {
bool serialize_colors; /**< Serialize doc color for entities */
bool measure_eval_duration; /**< Serialize evaluation duration */
bool serialize_type_info; /**< Serialize type information */
bool serialize_table; /**< Serialize entire table vs. matched components */
} ecs_iter_to_json_desc_t;

#define ECS_ITER_TO_JSON_INIT (ecs_iter_to_json_desc_t){\
Expand All @@ -11733,7 +11734,8 @@ typedef struct ecs_iter_to_json_desc_t {
.serialize_variable_ids = false, \
.serialize_colors = false, \
.measure_eval_duration = false, \
.serialize_type_info = false \
.serialize_type_info = false, \
.serialize_table = false \
}

/** Serialize iterator into JSON string.
Expand Down Expand Up @@ -23929,7 +23931,7 @@ inline flecs::entity id::second() const {
if (m_world) {
return flecs::entity(m_world, ecs_get_alive(m_world, e));
} else {
return flecs::entity(m_world, e);
return flecs::entity(e);
}
}

Expand Down
4 changes: 3 additions & 1 deletion include/flecs/addons/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ typedef struct ecs_iter_to_json_desc_t {
bool serialize_colors; /**< Serialize doc color for entities */
bool measure_eval_duration; /**< Serialize evaluation duration */
bool serialize_type_info; /**< Serialize type information */
bool serialize_table; /**< Serialize entire table vs. matched components */
} ecs_iter_to_json_desc_t;

#define ECS_ITER_TO_JSON_INIT (ecs_iter_to_json_desc_t){\
Expand All @@ -245,7 +246,8 @@ typedef struct ecs_iter_to_json_desc_t {
.serialize_variable_ids = false, \
.serialize_colors = false, \
.measure_eval_duration = false, \
.serialize_type_info = false \
.serialize_type_info = false, \
.serialize_table = false \
}

/** Serialize iterator into JSON string.
Expand Down
Loading

0 comments on commit 76cfd3d

Please sign in to comment.