Skip to content

Commit

Permalink
#608 support NaN and Inf values in serializers
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed Jan 22, 2022
1 parent 1d8e6c5 commit a540dcc
Show file tree
Hide file tree
Showing 14 changed files with 400 additions and 19 deletions.
42 changes: 36 additions & 6 deletions flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -11077,6 +11077,7 @@ void flecs_bitset_swap(
}

#include <stdio.h>
#include <math.h>

/**
* stm32tpl -- STM32 C++ Template Peripheral Library
Expand Down Expand Up @@ -11105,14 +11106,34 @@ static
int ecs_strbuf_ftoa(
ecs_strbuf_t *out,
double f,
int precision)
int precision,
char nan_delim)
{
char buf[64];
char * ptr = buf;
char * p1;
char c;
int64_t intPart;

if (isnan(f)) {
if (nan_delim) {
ecs_strbuf_appendch(out, nan_delim);
ecs_strbuf_appendstr(out, "nan");
return ecs_strbuf_appendch(out, nan_delim);
} else {
return ecs_strbuf_appendstr(out, "nan");
}
}
if (isinf(f)) {
if (nan_delim) {
ecs_strbuf_appendch(out, nan_delim);
ecs_strbuf_appendstr(out, "inf");
return ecs_strbuf_appendch(out, nan_delim);
} else {
return ecs_strbuf_appendstr(out, "inf");
}
}

if (precision > MAX_PRECISION) {
precision = MAX_PRECISION;
}
Expand Down Expand Up @@ -11469,10 +11490,11 @@ bool ecs_strbuf_appendch(

bool ecs_strbuf_appendflt(
ecs_strbuf_t *b,
double flt)
double flt,
char nan_delim)
{
ecs_assert(b != NULL, ECS_INVALID_PARAMETER, NULL);
return ecs_strbuf_ftoa(b, flt, 2);
return ecs_strbuf_ftoa(b, flt, 2, nan_delim);
}

bool ecs_strbuf_appendstr_zerocpy(
Expand Down Expand Up @@ -23089,10 +23111,10 @@ int expr_ser_primitive(
ecs_strbuf_append(str, "%lld", *(int64_t*)base);
break;
case EcsF32:
ecs_strbuf_appendflt(str, (double)*(float*)base);
ecs_strbuf_appendflt(str, (double)*(float*)base, 0);
break;
case EcsF64:
ecs_strbuf_appendflt(str, *(double*)base);
ecs_strbuf_appendflt(str, *(double*)base, 0);
break;
case EcsIPtr:
ecs_strbuf_append(str, "%i", *(intptr_t*)base);
Expand Down Expand Up @@ -25328,7 +25350,7 @@ void json_number(
ecs_strbuf_t *buf,
double value)
{
ecs_strbuf_appendflt(buf, value);
ecs_strbuf_appendflt(buf, value, '"');
}

void json_true(
Expand Down Expand Up @@ -25621,6 +25643,14 @@ int json_ser_type_op(
/* Should not be parsed as single op */
ecs_throw(ECS_INVALID_PARAMETER, NULL);
break;
case EcsOpF32:
ecs_strbuf_appendflt(str,
(ecs_f64_t)*(ecs_f32_t*)ECS_OFFSET(ptr, op->offset), '"');
break;
case EcsOpF64:
ecs_strbuf_appendflt(str,
*(ecs_f64_t*)ECS_OFFSET(ptr, op->offset), '"');
break;
case EcsOpEnum:
if (json_ser_enum(world, op, ECS_OFFSET(ptr, op->offset), str)) {
goto error;
Expand Down
3 changes: 2 additions & 1 deletion flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1710,7 +1710,8 @@ bool ecs_strbuf_appendch(
FLECS_API
bool ecs_strbuf_appendflt(
ecs_strbuf_t *buffer,
double v);
double v,
char nan_delim);

/* Append source buffer to destination buffer.
* Returns false when max is reached, true when there is still space */
Expand Down
3 changes: 2 additions & 1 deletion include/flecs/private/strbuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ bool ecs_strbuf_appendch(
FLECS_API
bool ecs_strbuf_appendflt(
ecs_strbuf_t *buffer,
double v);
double v,
char nan_delim);

/* Append source buffer to destination buffer.
* Returns false when max is reached, true when there is still space */
Expand Down
4 changes: 2 additions & 2 deletions src/addons/expr/serialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ int expr_ser_primitive(
ecs_strbuf_append(str, "%lld", *(int64_t*)base);
break;
case EcsF32:
ecs_strbuf_appendflt(str, (double)*(float*)base);
ecs_strbuf_appendflt(str, (double)*(float*)base, 0);
break;
case EcsF64:
ecs_strbuf_appendflt(str, *(double*)base);
ecs_strbuf_appendflt(str, *(double*)base, 0);
break;
case EcsIPtr:
ecs_strbuf_append(str, "%i", *(intptr_t*)base);
Expand Down
2 changes: 1 addition & 1 deletion src/addons/json/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void json_number(
ecs_strbuf_t *buf,
double value)
{
ecs_strbuf_appendflt(buf, value);
ecs_strbuf_appendflt(buf, value, '"');
}

void json_true(
Expand Down
8 changes: 8 additions & 0 deletions src/addons/json/serialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,14 @@ int json_ser_type_op(
/* Should not be parsed as single op */
ecs_throw(ECS_INVALID_PARAMETER, NULL);
break;
case EcsOpF32:
ecs_strbuf_appendflt(str,
(ecs_f64_t)*(ecs_f32_t*)ECS_OFFSET(ptr, op->offset), '"');
break;
case EcsOpF64:
ecs_strbuf_appendflt(str,
*(ecs_f64_t*)ECS_OFFSET(ptr, op->offset), '"');
break;
case EcsOpEnum:
if (json_ser_enum(world, op, ECS_OFFSET(ptr, op->offset), str)) {
goto error;
Expand Down
28 changes: 25 additions & 3 deletions src/datastructures/strbuf.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "../private_api.h"
#include <stdio.h>
#include <math.h>

/**
* stm32tpl -- STM32 C++ Template Peripheral Library
Expand Down Expand Up @@ -28,14 +29,34 @@ static
int ecs_strbuf_ftoa(
ecs_strbuf_t *out,
double f,
int precision)
int precision,
char nan_delim)
{
char buf[64];
char * ptr = buf;
char * p1;
char c;
int64_t intPart;

if (isnan(f)) {
if (nan_delim) {
ecs_strbuf_appendch(out, nan_delim);
ecs_strbuf_appendstr(out, "nan");
return ecs_strbuf_appendch(out, nan_delim);
} else {
return ecs_strbuf_appendstr(out, "nan");
}
}
if (isinf(f)) {
if (nan_delim) {
ecs_strbuf_appendch(out, nan_delim);
ecs_strbuf_appendstr(out, "inf");
return ecs_strbuf_appendch(out, nan_delim);
} else {
return ecs_strbuf_appendstr(out, "inf");
}
}

if (precision > MAX_PRECISION) {
precision = MAX_PRECISION;
}
Expand Down Expand Up @@ -392,10 +413,11 @@ bool ecs_strbuf_appendch(

bool ecs_strbuf_appendflt(
ecs_strbuf_t *b,
double flt)
double flt,
char nan_delim)
{
ecs_assert(b != NULL, ECS_INVALID_PARAMETER, NULL);
return ecs_strbuf_ftoa(b, flt, 2);
return ecs_strbuf_ftoa(b, flt, 2, nan_delim);
}

bool ecs_strbuf_appendstr_zerocpy(
Expand Down
6 changes: 5 additions & 1 deletion test/collections/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@
"append_511_chars",
"append_512_chars",
"append_513_chars",
"append_flt"
"append_flt",
"append_nan",
"append_inf",
"append_nan_delim",
"append_inf_delim"
]
}]
}
Expand Down
65 changes: 64 additions & 1 deletion test/collections/src/Strbuf.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <collections.h>
#include <math.h>

void Strbuf_setup() {
ecs_os_set_api_defaults();
Expand Down Expand Up @@ -234,10 +235,72 @@ void Strbuf_append_513_chars() {

void Strbuf_append_flt() {
ecs_strbuf_t b = ECS_STRBUF_INIT;
ecs_strbuf_appendflt(&b, 10.5);
ecs_strbuf_appendflt(&b, 10.5, 0);

char *str = ecs_strbuf_get(&b);
test_assert(str != NULL);
test_str(str, "10.50");
ecs_os_free(str);
}

void Strbuf_append_nan() {
ecs_strbuf_t b = ECS_STRBUF_INIT;
ecs_strbuf_appendflt(&b, NAN, 0);

char *str = ecs_strbuf_get(&b);
test_assert(str != NULL);
test_str(str, "nan");
ecs_os_free(str);
}

void Strbuf_append_inf() {
{
ecs_strbuf_t b = ECS_STRBUF_INIT;
ecs_strbuf_appendflt(&b, INFINITY, 0);

char *str = ecs_strbuf_get(&b);
test_assert(str != NULL);
test_str(str, "inf");
ecs_os_free(str);
}
{
ecs_strbuf_t b = ECS_STRBUF_INIT;
ecs_strbuf_appendflt(&b, -INFINITY, 0);

char *str = ecs_strbuf_get(&b);
test_assert(str != NULL);
test_str(str, "inf");
ecs_os_free(str);
}
}

void Strbuf_append_nan_delim() {
ecs_strbuf_t b = ECS_STRBUF_INIT;
ecs_strbuf_appendflt(&b, NAN, '"');

char *str = ecs_strbuf_get(&b);
test_assert(str != NULL);
test_str(str, "\"nan\"");
ecs_os_free(str);
}

void Strbuf_append_inf_delim() {
{
ecs_strbuf_t b = ECS_STRBUF_INIT;
ecs_strbuf_appendflt(&b, INFINITY, '"');

char *str = ecs_strbuf_get(&b);
test_assert(str != NULL);
test_str(str, "\"inf\"");
ecs_os_free(str);
}
{
ecs_strbuf_t b = ECS_STRBUF_INIT;
ecs_strbuf_appendflt(&b, -INFINITY, '"');

char *str = ecs_strbuf_get(&b);
test_assert(str != NULL);
test_str(str, "\"inf\"");
ecs_os_free(str);
}
}
22 changes: 21 additions & 1 deletion test/collections/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ void Strbuf_append_511_chars(void);
void Strbuf_append_512_chars(void);
void Strbuf_append_513_chars(void);
void Strbuf_append_flt(void);
void Strbuf_append_nan(void);
void Strbuf_append_inf(void);
void Strbuf_append_nan_delim(void);
void Strbuf_append_inf_delim(void);

bake_test_case Vector_testcases[] = {
{
Expand Down Expand Up @@ -489,6 +493,22 @@ bake_test_case Strbuf_testcases[] = {
{
"append_flt",
Strbuf_append_flt
},
{
"append_nan",
Strbuf_append_nan
},
{
"append_inf",
Strbuf_append_inf
},
{
"append_nan_delim",
Strbuf_append_nan_delim
},
{
"append_inf_delim",
Strbuf_append_inf_delim
}
};

Expand Down Expand Up @@ -518,7 +538,7 @@ static bake_test_suite suites[] = {
"Strbuf",
Strbuf_setup,
NULL,
19,
23,
Strbuf_testcases
}
};
Expand Down
8 changes: 8 additions & 0 deletions test/meta/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,10 @@
"entity",
"enum",
"bitmask",
"float_nan",
"float_inf",
"double_nan",
"double_inf",
"struct_enum",
"struct_bitmask",
"struct_i32",
Expand Down Expand Up @@ -436,6 +440,10 @@
"struct_string",
"struct_entity",
"struct_entity_after_float",
"struct_float_nan",
"struct_float_inf",
"struct_double_nan",
"struct_double_inf",
"struct_enum",
"struct_bitmask",
"struct_i32_i32",
Expand Down
Loading

0 comments on commit a540dcc

Please sign in to comment.