Supports empty array.

This commit is contained in:
falsycat 2020-12-31 00:00:00 +00:00
parent ec1b284979
commit a5b76c3f51
4 changed files with 84 additions and 25 deletions

View File

@ -12,5 +12,5 @@ X C transpiler for unpacking
X C transpiler for packing
X setup tests
X add bitmanip operators
handling of overflown or negative expression
X handling of overflown or negative expression
release 1.0.0

10
c/result.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
typedef enum biner_result_t {
BINER_RESULT_COMPLETED,
BINER_RESULT_CONTINUE,
BINER_RESULT_ERROR_THRESHOULD_,
BINER_RESULT_MEMORY_ERROR,
} biner_result_t;

View File

@ -10,8 +10,15 @@
#include <string.h>
#include "../c/pack.h"
#include "../c/result.h"
#include "../c/unpack.h"
#include "../c/zone.h"
static inline void* biner_malloc_(size_t sz, void* udata) {
(void) udata;
/* returning NULL can abort the unpacking */
return malloc(sz);
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
@ -67,10 +74,11 @@ int main(void) {
.sex = SEX_CAT,
.role = ROLE_STUDENT,
.property_count = 2,
.property_count = 3,
.properties = (strpair_t[]) {
{ .key = str_("like"), .value = str_("rat"), },
{ .key = str_("hate"), .value = str_("dog"), },
{ .key = str_("empty"), .value = str_(""), },
},
.student = {
@ -85,13 +93,18 @@ int main(void) {
user_t dst = {0};
size_t b = 0;
bool completed = false;
while (!completed) {
biner_result_t result = BINER_RESULT_CONTINUE;
while (result == BINER_RESULT_CONTINUE) {
uint8_t c;
completed = user_pack(&pack_ctx, &src, &c);
if (user_unpack(&unpack_ctx, &dst, c) != completed) {
result = user_pack(&pack_ctx, &src, &c);
if (result >= BINER_RESULT_ERROR_THRESHOULD_) {
fprintf(stderr, "unexpected error happened\n");
return EXIT_FAILURE;
}
if (user_unpack(&unpack_ctx, &dst, c) != result) {
fprintf(stderr, "fail at the %zu byte: ", b);
if (completed) {
if (result == BINER_RESULT_COMPLETED) {
fprintf(stderr, "pack function finsihed but unpack not\n");
} else {
fprintf(stderr, "unpack function finsihed but pack not\n");

View File

@ -290,6 +290,7 @@ static void print_struct_member_context_struct_(
fprintf(p->dst, "size_t count; ");
fprintf(p->dst, "size_t count_max; ");
fprintf(p->dst, "size_t byte; ");
fprintf(p->dst, "void* udata; ");
bool require_subctx = false;
const biner_tree_struct_member_t* itr = m;
@ -342,6 +343,8 @@ static void print_struct_member_pack_code_each_(
print_expr_(
info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr));
fprintf(info->p->dst, "; ");
fprintf(info->p->dst,
"if (ctx->count_max <= 0) { ++ctx->step; goto CONTINUE; } ");
fprintf(info->p->dst, "ctx->count = 0; ");
break;
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY:
@ -353,7 +356,7 @@ static void print_struct_member_pack_code_each_(
if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
fprintf(info->p->dst, "ctx->subctx.%s = (", name);
print_fixed_decl_name_(info->p, dname);
fprintf(info->p->dst, CONTEXT_SUFFIX_") {0}; ");
fprintf(info->p->dst, CONTEXT_SUFFIX_") { .udata = ctx->udata, }; ");
}
fprintf(info->p->dst, "body%zu: ", info->m->index);
@ -377,9 +380,11 @@ static void print_struct_member_pack_code_each_(
}
if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
fprintf(info->p->dst, "if (");
fprintf(info->p->dst, "result = ");
print_fixed_decl_name_(info->p, dname);
fprintf(info->p->dst, "_pack(&ctx->subctx.%s, &s->%s%s, c)) { ", name, name, suffix);
fprintf(info->p->dst, "_pack(&ctx->subctx.%s, &s->%s%s, c); ", name, name, suffix);
fprintf(info->p->dst,
"if (result != BINER_RESULT_COMPLETED) { return result; } else { ");
} else {
const char* func = struct_member_type_name_meta_map_[info->t->name].func;
fprintf(info->p->dst,
@ -409,11 +414,11 @@ static void print_struct_member_pack_code_each_(
if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
fprintf(info->p->dst, "ctx->subctx.%s = (", name);
print_fixed_decl_name_(info->p, dname);
fprintf(info->p->dst, CONTEXT_SUFFIX_") {0}; ");
fprintf(info->p->dst, CONTEXT_SUFFIX_") { .udata = ctx->udata, }; ");
}
fprintf(info->p->dst, "ctx->byte = 0; ");
}
fprintf(info->p->dst, "} return false; ");
fprintf(info->p->dst, "} return BINER_RESULT_CONTINUE; ");
if (info->m->condition != 0) {
fprintf(info->p->dst, "} ");
@ -445,8 +450,12 @@ static void print_struct_member_unpack_code_each_(
info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr));
fprintf(info->p->dst, "; ");
fprintf(info->p->dst,
"s->%s = malloc(sizeof(*s->%s)*ctx->count_max); ",
"if (ctx->count_max <= 0) { ++ctx->step; goto CONTINUE; } ");
fprintf(info->p->dst,
"s->%s = biner_malloc_(sizeof(*s->%s)*ctx->count_max, ctx->udata); ",
name, name);
fprintf(info->p->dst,
"if (s->%s == NULL) { return BINER_RESULT_MEMORY_ERROR; } ", name);
fprintf(info->p->dst, "ctx->count = 0; ");
break;
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY:
@ -458,7 +467,7 @@ static void print_struct_member_unpack_code_each_(
if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
fprintf(info->p->dst, "ctx->subctx.%s = (", name);
print_fixed_decl_name_(info->p, dname);
fprintf(info->p->dst, CONTEXT_SUFFIX_") {0}; ");
fprintf(info->p->dst, CONTEXT_SUFFIX_") { .udata = ctx->udata, }; ");
}
fprintf(info->p->dst, "body%zu: ", info->m->index);
@ -482,9 +491,11 @@ static void print_struct_member_unpack_code_each_(
}
if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
fprintf(info->p->dst, "if (");
fprintf(info->p->dst, "result = ");
print_fixed_decl_name_(info->p, dname);
fprintf(info->p->dst, "_unpack(&ctx->subctx.%s, &s->%s%s, c)) { ", name, name, suffix);
fprintf(info->p->dst, "_unpack(&ctx->subctx.%s, &s->%s%s, c); ", name, name, suffix);
fprintf(info->p->dst,
"if (result != BINER_RESULT_COMPLETED) { return result; } else { ");
} else {
const char* func = struct_member_type_name_meta_map_[info->t->name].func;
fprintf(info->p->dst,
@ -514,11 +525,11 @@ static void print_struct_member_unpack_code_each_(
if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
fprintf(info->p->dst, "ctx->subctx.%s = (", name);
print_fixed_decl_name_(info->p, dname);
fprintf(info->p->dst, CONTEXT_SUFFIX_") {0}; ");
fprintf(info->p->dst, CONTEXT_SUFFIX_") { .udata = ctx->udata, }; ");
}
fprintf(info->p->dst, "ctx->byte = 0; ");
}
fprintf(info->p->dst, "} return false; ");
fprintf(info->p->dst, "} return BINER_RESULT_CONTINUE; ");
if (info->m->condition != 0) {
fprintf(info->p->dst, "} ");
@ -536,20 +547,45 @@ static inline void print_struct_member_iteration_code_(
assert(m != NULL);
assert(f != NULL);
bool require_continue = false;
bool require_result_var = false;
const biner_tree_struct_member_t* itr = m;
while ((uintptr_t) itr != (uintptr_t) p->zone) {
const biner_tree_struct_member_type_t* t =
(const biner_tree_struct_member_type_t*) (p->zone+itr->type);
if (t->qualifier == BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY) {
require_continue = true;
}
if (t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
require_result_var = true;
}
itr = (const biner_tree_struct_member_t*) (p->zone+itr->prev);
}
fprintf(p->dst, "static const void* const steps_[] = { ");
for (size_t i = 0; i <= m->index; ++i) {
fprintf(p->dst, "&&init%zu, &&body%zu, ", i, i);
}
fprintf(p->dst, "}; ");
if (require_result_var) {
fprintf(p->dst, "biner_result_t result; ");
}
if (require_continue) {
fprintf(p->dst, "CONTINUE: ");
}
fprintf(p->dst,
"if (ctx->step >= sizeof(steps_)/sizeof(steps_[0])) return true; ");
"if (ctx->step >= sizeof(steps_)/sizeof(steps_[0]))"
" return BINER_RESULT_COMPLETED; ");
fprintf(p->dst, "goto *steps_[ctx->step]; ");
struct_member_each_(p, m, f, SIZE_MAX);
fprintf(p->dst, "NEXT: ");
fprintf(p->dst, "return ++ctx->step >= sizeof(steps_)/sizeof(steps_[0]); ");
fprintf(p->dst,
"return (++ctx->step >= sizeof(steps_)/sizeof(steps_[0]))?"
" BINER_RESULT_COMPLETED:"
" BINER_RESULT_CONTINUE; ");
}
static void print_decls_(
@ -597,7 +633,7 @@ static void print_decls_(
print_struct_member_context_struct_(p, body, CONTEXT_SUFFIX_);
print_typedef_footer_(p, name, CONTEXT_SUFFIX_);
print_func_header_(p, "bool", name, "_pack");
print_func_header_(p, "biner_result_t", name, "_pack");
print_fixed_decl_name_(p, name);
fprintf(p->dst, CONTEXT_SUFFIX_"* ctx, ");
fprintf(p->dst, "const ");
@ -608,7 +644,7 @@ static void print_decls_(
p, body, &print_struct_member_pack_code_each_);
fprintf(p->dst, "}\n");
print_func_header_(p, "bool", name, "_unpack");
print_func_header_(p, "biner_result_t", name, "_unpack");
print_fixed_decl_name_(p, name);
fprintf(p->dst, CONTEXT_SUFFIX_"* ctx, ");
print_fixed_decl_name_(p, name);