Compare commits

...

10 commits

Author SHA1 Message Date
Rongsong Shen
7484693df1 fix decode issue of structure with zero length list 2025-09-22 17:34:58 +08:00
Rongsong Shen
94af71fa0b fix pkg data 2025-09-05 15:58:36 +08:00
Rongsong Shen
a8a0da6ced fix pkgconfig data 2025-09-05 15:49:06 +08:00
Rongsong Shen
891355581d fix missed file for cmake install 2025-09-05 15:35:23 +08:00
Rongsong Shen
c1fe4d4a53 enhance list decode & provide pkgconfig data 2025-09-05 14:54:01 +08:00
Rongsong Shen
a86c5ab151 use capn_null than zero filled object for null object 2025-05-09 13:48:56 +08:00
Rongsong Shen
6c0fbc4bbd test with nest union 2025-05-08 09:42:09 +08:00
Rongsong Shen
dd65178724 fix issue of unused variable 2025-05-08 09:13:06 +08:00
Rongsong Shen
dd1fbd4043 auto generate memory free code for decode data 2025-05-07 18:04:13 +08:00
Rongsong Shen
40006c00d2 improve list encode/decode 2025-04-28 10:32:18 +08:00
7 changed files with 414 additions and 67 deletions

View file

@ -7,6 +7,8 @@ else()
endif() endif()
project(c-capnproto LANGUAGES ${languages}) project(c-capnproto LANGUAGES ${languages})
configure_file(c-capnproto.pc.in c-capnproto.pc @ONLY)
include(CTest) include(CTest)
# set(CMAKE_C_STANDARD 11) # set(CMAKE_C_STANDARD 11)
@ -161,6 +163,7 @@ endif()
option(C_CAPNPROTO_ENABLE_INSTALL "Add instructions for 'cmake --install' of CapnC_Runtime library and capnpc-c executable" ON) option(C_CAPNPROTO_ENABLE_INSTALL "Add instructions for 'cmake --install' of CapnC_Runtime library and capnpc-c executable" ON)
if(C_CAPNPROTO_ENABLE_INSTALL) if(C_CAPNPROTO_ENABLE_INSTALL)
set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib)
install(TARGETS CapnC_Runtime capnpc-c install(TARGETS CapnC_Runtime capnpc-c
EXPORT CapnC) EXPORT CapnC)
install(EXPORT CapnC install(EXPORT CapnC
@ -168,6 +171,8 @@ if(C_CAPNPROTO_ENABLE_INSTALL)
NAMESPACE CapnC:: NAMESPACE CapnC::
FILE CapnCConfig.cmake) FILE CapnCConfig.cmake)
install(FILES lib/capnp_c.h TYPE INCLUDE) install(FILES lib/capnp_c.h TYPE INCLUDE)
install(FILES build/c-capnproto.pc
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
endif() endif()
add_subdirectory(examples/book) add_subdirectory(examples/book)

View file

@ -1,12 +1,12 @@
prefix=@prefix@ prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@exec_prefix@ exec_prefix=${prefix}
libdir=@libdir@ libdir=${prefix}/lib
bindir=@bindir@ bindir=${prefix}/bin
includedir=@includedir@ includedir=${prefix}/include
codegen=${bindir}/capnpc-c codegen=${bindir}/capnpc-c
Name: c-capnproto Name: c-capnproto
Description: Cap'n Proto C bindings Description: Cap'n Proto C bindings
Version: @PACKAGE_VERSION@ Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lcapnp_c Libs: -L${libdir} -lCapnC_Runtime
Cflags: -I${includedir} Cflags: -I${includedir}

View file

@ -887,15 +887,25 @@ static void mk_simple_list_decoder(struct str *func, const char *tab,
str_add(func, tab, -1); str_add(func, tab, -1);
str_addf(func, "\tnc_ = s->%s.len;\n", svar); str_addf(func, "\tnc_ = s->%s.len;\n", svar);
str_add(func, tab, -1); str_add(func, tab, -1);
str_addf(func, "\td->%s = (char **)calloc(nc_, sizeof(char *));\n", dvar); str_addf(func, "\tif (nc_ == 0) {\n");
str_add(func, tab, -1); str_add(func, tab, -1);
str_addf(func, "\tfor(i_ = 0; i_ < nc_; i_ ++) {\n"); str_addf(func, "\t\td->%s = NULL;\n", dvar);
str_add(func, tab, -1);
str_addf(func, "\t}\n");
str_add(func, tab, -1);
str_addf(func, "\telse {\n");
str_add(func, tab, -1);
str_addf(func, "\t\td->%s = (char **)calloc(nc_, sizeof(char *));\n", dvar);
str_add(func, tab, -1);
str_addf(func, "\t\tfor(i_ = 0; i_ < nc_; i_ ++) {\n");
str_add(func, tab, -1); str_add(func, tab, -1);
str_addf(func, str_addf(func,
"\t\tcapn_text text_ = capn_get_text(s->%s, i_, capn_val0);\n", "\t\t\tcapn_text text_ = capn_get_text(s->%s, i_, capn_val0);\n",
svar); svar);
str_add(func, tab, -1); str_add(func, tab, -1);
str_addf(func, "\t\td->%s[i_] = strdup(text_.str);\n", dvar); str_addf(func, "\t\t\td->%s[i_] = strdup(text_.str);\n", dvar);
str_add(func, tab, -1);
str_addf(func, "\t\t}\n");
str_add(func, tab, -1); str_add(func, tab, -1);
str_addf(func, "\t}\n"); str_addf(func, "\t}\n");
} else { } else {
@ -903,14 +913,23 @@ static void mk_simple_list_decoder(struct str *func, const char *tab,
str_addf(func, "\tcapn_resolve(&(s->%s.p));\n", svar); str_addf(func, "\tcapn_resolve(&(s->%s.p));\n", svar);
str_add(func, tab, -1); str_add(func, tab, -1);
str_addf(func, "\tnc_ = s->%s.p.len;\n", svar); str_addf(func, "\tnc_ = s->%s.p.len;\n", svar);
str_add(func, tab, -1); str_add(func, tab, -1);
str_addf(func, "\td->%s = (%s *)calloc(nc_, sizeof(%s));\n", dvar, str_addf(func, "\tif (nc_ == 0) {\n");
str_add(func, tab, -1);
str_addf(func, "\t\td->%s = NULL;\n", dvar);
str_add(func, tab, -1);
str_addf(func, "\t}\n");
str_add(func, tab, -1);
str_addf(func, "\telse {\n");
str_add(func, tab, -1);
str_addf(func, "\t\td->%s = (%s *)calloc(nc_, sizeof(%s));\n", dvar,
list_type, list_type); list_type, list_type);
str_add(func, tab, -1); str_add(func, tab, -1);
str_addf(func, "\tfor(i_ = 0; i_ < nc_; i_ ++) {\n"); str_addf(func, "\t\tfor(i_ = 0; i_ < nc_; i_ ++) {\n");
str_add(func, tab, -1); str_add(func, tab, -1);
str_addf(func, "\t\td->%s[i_] = capn_%s(s->%s, i_);\n", dvar, getf, svar); str_addf(func, "\t\t\td->%s[i_] = capn_%s(s->%s, i_);\n", dvar, getf, svar);
str_add(func, tab, -1);
str_addf(func, "\t\t}\n");
str_add(func, tab, -1); str_add(func, tab, -1);
str_addf(func, "\t}\n"); str_addf(func, "\t}\n");
} }
@ -921,6 +940,33 @@ static void mk_simple_list_decoder(struct str *func, const char *tab,
str_addf(func, "}\n"); str_addf(func, "}\n");
} }
static void mk_simple_list_free(struct str *func, const char *tab,
const char *list_type, const char *getf,
const char *dvar, const char *cvar,
const char *svar) {
str_add(func, tab, -1);
str_addf(func, "if (1) {\n");
str_add(func, tab, -1);
str_addf(func, "\tint i_, nc_ = d->%s;\n", cvar);
str_add(func, tab, -1);
str_addf(func, "\tcapnp_use(i_);capnp_use(nc_);\n");
if (strcmp(list_type, "text") == 0) {
str_add(func, tab, -1);
str_addf(func, "\tfor(i_ = 0; i_ < nc_; i_ ++) {\n");
str_add(func, tab, -1);
str_addf(func, "\t\tif (d->%s[i_] == NULL) continue;\n", dvar);
str_add(func, tab, -1);
str_addf(func, "\t\tfree(d->%s[i_]);\n", dvar);
str_add(func, tab, -1);
str_addf(func, "\t}\n");
}
str_add(func, tab, -1);
str_addf(func, "\tfree(d->%s);\n", dvar);
str_add(func, tab, -1);
str_addf(func, "}\n");
}
static void gen_call_list_encoder(capnp_ctx_t *ctx, struct str *func, static void gen_call_list_encoder(capnp_ctx_t *ctx, struct str *func,
struct Type *type, const char *tab, struct Type *type, const char *tab,
const char *var, const char *countvar, const char *var, const char *countvar,
@ -1039,6 +1085,77 @@ static void gen_call_list_decoder(capnp_ctx_t *ctx, struct str *func,
} }
} }
static void gen_call_list_free(capnp_ctx_t *ctx, struct str *func,
struct Type *type, const char *tab,
const char *var, const char *countvar,
const char *var2) {
char *t = NULL;
struct node *n = NULL;
str_add(func, tab, -1);
switch (type->which) {
case Type__bool:
t = "uint8_t";
mk_simple_list_free(func, tab, t, "get1", var, countvar, var2);
break;
case Type_int8:
case Type_uint8:
if (type->which == Type_int8) {
t = "int8_t";
} else {
t = "uint8_t";
}
mk_simple_list_free(func, tab, t, "get8", var, countvar, var2);
break;
case Type_int16:
case Type_uint16:
if (type->which == Type_int16) {
t = "int16_t";
} else {
t = "uint16_t";
}
mk_simple_list_free(func, tab, t, "get16", var, countvar, var2);
break;
case Type_int32:
case Type_uint32:
case Type_float32:
if (type->which == Type_int32) {
t = "int32_t";
} else if (type->which == Type_uint32) {
t = "uint32_t";
} else {
t = "float";
}
mk_simple_list_free(func, tab, t, "get32", var, countvar, var2);
break;
case Type_int64:
case Type_uint64:
case Type_float64:
if (type->which == Type_int64) {
t = "int64_t";
} else if (type->which == Type_uint64) {
t = "uint64_t";
} else {
t = "double";
}
mk_simple_list_free(func, tab, t, "get64", var, countvar, var2);
break;
case Type_text:
mk_simple_list_free(func, tab, "text", NULL, var, countvar, var2);
break;
case Type__struct:
n = find_node(ctx, type->_struct.typeId);
if (n != NULL) {
char *dtypename = n->name.str;
str_addf(func, "free_%s_list(d->%s, d->%s);\n", dtypename, countvar, var);
}
break;
}
}
static void encode_member(capnp_ctx_t *ctx, struct str *func, struct field *f, static void encode_member(capnp_ctx_t *ctx, struct str *func, struct field *f,
const char *tab, const char *var, const char *var2) { const char *tab, const char *var, const char *var2) {
struct Type list_type; struct Type list_type;
@ -1214,6 +1331,93 @@ static void decode_member(capnp_ctx_t *ctx, struct str *func, struct field *f,
} }
} }
static void free_member(capnp_ctx_t *ctx, struct str *func, struct field *f,
const char *tab, const char *var, const char *var2) {
struct Type list_type;
struct node *n = NULL;
if (f->v.t.which == Type__void) {
return;
}
if (var2 == NULL) {
var2 = var;
}
switch (f->v.t.which) {
case Type__bool:
case Type_int8:
case Type_int16:
case Type_int32:
case Type_int64:
case Type_uint8:
case Type_uint16:
case Type_uint32:
case Type_uint64:
case Type_float32:
case Type_float64:
case Type__enum:
break;
case Type_text:
str_add(func, tab, -1);
str_addf(func, "if (d->%s != NULL) {\n", var2);
str_add(func, tab, -1);
str_addf(func, "\tfree(d->%s);\n", var2);
str_add(func, tab, -1);
str_addf(func, "}\n");
break;
case Type__struct:
n = find_node(ctx, f->v.t._struct.typeId);
if (n != NULL) {
str_add(func, tab, -1);
str_addf(func, "free_%s_ptr(&(d->%s));\n", n->name.str, var2);
}
break;
case Type__list:
read_Type(&list_type, f->v.t._list.elementType);
if (list_type.which != Type__void) {
char *name = NULL;
char *ncount = NULL;
char buf[256];
name = (char *)get_mapname(f->f.annotations);
if (name == NULL) {
var2 = var;
} else {
var2 = name;
}
ncount = (char *)get_maplistcount(f->f.annotations);
if (ncount != NULL) {
sprintf(buf, "%s", ncount);
} else {
char buf2[256];
char *p;
strcpy(buf2, var2);
p = strchr(buf2, '.');
if (p != NULL) {
*p = 0x0;
p++;
}
strcpy(buf, buf2);
if (p != NULL) {
strcat(buf, ".");
sprintf(&buf[strlen(buf)], "n_%s", p);
}
}
gen_call_list_free(ctx, func, &list_type, tab, var2, buf, var);
}
break;
default:
str_add(func, tab, -1);
str_addf(func, "\t /* %s %s */\n", var2, var);
break;
}
}
void mk_struct_list_encoder(capnp_ctx_t *ctx, struct node *n) { void mk_struct_list_encoder(capnp_ctx_t *ctx, struct node *n) {
if (n == NULL) { if (n == NULL) {
return; return;
@ -1231,14 +1435,14 @@ void mk_struct_list_encoder(capnp_ctx_t *ctx, struct node *n) {
str_addf(&(ctx->SRC), str_addf(&(ctx->SRC),
"void encode_%s_list(struct capn_segment *cs, %s_list *l,int " "void encode_%s_list(struct capn_segment *cs, %s_list *l,int "
"count,%s *s) {\n", "count,%s **s) {\n",
n->name.str, n->name.str, buf); n->name.str, n->name.str, buf);
str_addf(&(ctx->SRC), "\t%s_list lst;\n", n->name.str); str_addf(&(ctx->SRC), "\t%s_list lst;\n", n->name.str);
str_addf(&(ctx->SRC), "\tint i;\n"); str_addf(&(ctx->SRC), "\tint i;\n");
str_addf(&(ctx->SRC), "\tlst = new_%s_list(cs, count);\n", n->name.str); str_addf(&(ctx->SRC), "\tlst = new_%s_list(cs, count);\n", n->name.str);
str_addf(&(ctx->SRC), "\tfor(i = 0; i < count; i ++) {\n"); str_addf(&(ctx->SRC), "\tfor(i = 0; i < count; i ++) {\n");
str_addf(&(ctx->SRC), "\t\tstruct %s d;\n", n->name.str); str_addf(&(ctx->SRC), "\t\tstruct %s d;\n", n->name.str);
str_addf(&(ctx->SRC), "\t\tencode_%s(cs, &d, &(s[i]));\n", n->name.str); str_addf(&(ctx->SRC), "\t\tencode_%s(cs, &d, s[i]);\n", n->name.str);
str_addf(&(ctx->SRC), "\t\tset_%s(&d, lst, i);\n", n->name.str); str_addf(&(ctx->SRC), "\t\tset_%s(&d, lst, i);\n", n->name.str);
str_addf(&(ctx->SRC), "\t}\n"); str_addf(&(ctx->SRC), "\t}\n");
str_addf(&(ctx->SRC), "\t(*l) = lst;\n"); str_addf(&(ctx->SRC), "\t(*l) = lst;\n");
@ -1268,15 +1472,17 @@ void mk_struct_ptr_encoder(capnp_ctx_t *ctx, struct node *n) {
n->name.str, n->name.str, buf); n->name.str, n->name.str, buf);
str_addf(&(ctx->SRC), "\t%s_ptr ptr;\n", n->name.str); str_addf(&(ctx->SRC), "\t%s_ptr ptr;\n", n->name.str);
str_addf(&(ctx->SRC), "\tstruct %s d;\n", n->name.str); str_addf(&(ctx->SRC), "\tstruct %s d;\n", n->name.str);
str_addf(&(ctx->SRC), "\t%s zero_ = {0}; \n", buf);
str_addf(&(ctx->SRC), "\tptr = new_%s(cs);\n", n->name.str); str_addf(&(ctx->SRC), "\tptr = new_%s(cs);\n", n->name.str);
str_addf(&(ctx->SRC), "\tif (s == NULL) {\n"); str_addf(&(ctx->SRC), "\tif (s == NULL) {\n");
str_addf(&(ctx->SRC), "\t\ts = &zero_;\n"); str_addf(&(ctx->SRC), "\t\tptr.p = capn_null;\n");
str_addf(&(ctx->SRC), "\t}\n");
str_addf(&(ctx->SRC), "\telse{\n");
str_addf(&(ctx->SRC), "\t\tencode_%s(cs, &d, s);\n", n->name.str);
str_addf(&(ctx->SRC), "\t\twrite_%s(&d, ptr);\n", n->name.str);
str_addf(&(ctx->SRC), "\t}\n"); str_addf(&(ctx->SRC), "\t}\n");
str_addf(&(ctx->SRC), "\tencode_%s(cs, &d, s);\n", n->name.str);
str_addf(&(ctx->SRC), "\twrite_%s(&d, ptr);\n", n->name.str);
str_addf(&(ctx->SRC), "\t(*p) = ptr;\n"); str_addf(&(ctx->SRC), "\t(*p) = ptr;\n");
str_addf(&(ctx->SRC), "}\n"); str_addf(&(ctx->SRC), "}\n");
ctx->g_nullused = 1;
} }
void mk_struct_list_decoder(capnp_ctx_t *ctx, struct node *n) { void mk_struct_list_decoder(capnp_ctx_t *ctx, struct node *n) {
@ -1295,18 +1501,26 @@ void mk_struct_list_decoder(capnp_ctx_t *ctx, struct node *n) {
} }
str_addf(&(ctx->SRC), str_addf(&(ctx->SRC),
"void decode_%s_list(int *pcount, %s **d, %s_list list) {\n", "void decode_%s_list(int *pcount, %s ***d, %s_list list) {\n",
n->name.str, buf, n->name.str); n->name.str, buf, n->name.str);
str_addf(&(ctx->SRC), "\tint i;\n"); str_addf(&(ctx->SRC), "\tint i;\n");
str_addf(&(ctx->SRC), "\tint nc;\n"); str_addf(&(ctx->SRC), "\tint nc;\n");
str_addf(&(ctx->SRC), "\t%s *ptr;\n", buf); str_addf(&(ctx->SRC), "\t%s **ptr;\n", buf);
str_addf(&(ctx->SRC), "\tcapn_resolve(&(list.p));\n"); str_addf(&(ctx->SRC), "\tcapn_resolve(&(list.p));\n");
str_addf(&(ctx->SRC), "\tnc = list.p.len;\n"); str_addf(&(ctx->SRC), "\tnc = list.p.len;\n");
str_addf(&(ctx->SRC), "\tptr = (%s *)calloc(nc, sizeof(%s));\n", buf, buf); str_addf(&(ctx->SRC), "\tif (nc == 0) {\n");
str_addf(&(ctx->SRC), "\t\t(*d) = NULL;\n");
str_addf(&(ctx->SRC), "\t\t(*pcount) = 0;\n");
str_addf(&(ctx->SRC), "\t\treturn;\n");
str_addf(&(ctx->SRC), "\t}\n");
str_addf(&(ctx->SRC), "\tptr = (%s **)calloc(nc, sizeof(%s *));\n", buf,
buf);
str_addf(&(ctx->SRC), "\tfor(i = 0; i < nc; i ++) {\n"); str_addf(&(ctx->SRC), "\tfor(i = 0; i < nc; i ++) {\n");
str_addf(&(ctx->SRC), "\t\tstruct %s s;\n", n->name.str); str_addf(&(ctx->SRC), "\t\tstruct %s s;\n", n->name.str);
str_addf(&(ctx->SRC), "\t\tget_%s(&s, list, i);\n", n->name.str); str_addf(&(ctx->SRC), "\t\tget_%s(&s, list, i);\n", n->name.str);
str_addf(&(ctx->SRC), "\t\tdecode_%s(&(ptr[i]), &s);\n", n->name.str); str_addf(&(ctx->SRC), "\t\tptr[i] = (%s *)calloc(1, sizeof(%s));\n", buf,
buf);
str_addf(&(ctx->SRC), "\t\tdecode_%s(ptr[i], &s);\n", n->name.str);
str_addf(&(ctx->SRC), "\t}\n"); str_addf(&(ctx->SRC), "\t}\n");
str_addf(&(ctx->SRC), "\t(*d) = ptr;\n"); str_addf(&(ctx->SRC), "\t(*d) = ptr;\n");
str_addf(&(ctx->SRC), "\t(*pcount) = nc;\n"); str_addf(&(ctx->SRC), "\t(*pcount) = nc;\n");
@ -1335,10 +1549,71 @@ void mk_struct_ptr_decoder(capnp_ctx_t *ctx, struct node *n) {
"%s_ptr p) {\n", "%s_ptr p) {\n",
n->name.str, buf, n->name.str); n->name.str, buf, n->name.str);
str_addf(&(ctx->SRC), "\tstruct %s s;\n", n->name.str); str_addf(&(ctx->SRC), "\tstruct %s s;\n", n->name.str);
str_addf(&(ctx->SRC), "\tcapn_resolve(&(p.p));\n");
str_addf(&(ctx->SRC), "\tif (p.p.type == CAPN_NULL) {\n");
str_addf(&(ctx->SRC), "\t\t(*d) = NULL;\n");
str_addf(&(ctx->SRC), "\t\treturn;\n");
str_addf(&(ctx->SRC), "\t}\n");
str_addf(&(ctx->SRC), "\t*d = (%s *)calloc(1, sizeof(%s));\n", buf, buf); str_addf(&(ctx->SRC), "\t*d = (%s *)calloc(1, sizeof(%s));\n", buf, buf);
str_addf(&(ctx->SRC), "\tread_%s(&s, p);\n", n->name.str); str_addf(&(ctx->SRC), "\tread_%s(&s, p);\n", n->name.str);
str_addf(&(ctx->SRC), "\tdecode_%s(*d, &s);\n", n->name.str); str_addf(&(ctx->SRC), "\tdecode_%s(*d, &s);\n", n->name.str);
str_addf(&(ctx->SRC), "}\n"); str_addf(&(ctx->SRC), "}\n");
ctx->g_nullused = 1;
}
void mk_struct_list_free(capnp_ctx_t *ctx, struct node *n) {
if (n == NULL) {
return;
}
if (1) {
char *mapname = (char *)get_mapname(n->n.annotations);
char buf[256];
if (mapname == NULL) {
sprintf(buf, "struct %s_", n->name.str);
} else {
strcpy(buf, mapname);
}
str_addf(&(ctx->SRC), "void free_%s_list(int pcount, %s **d) {\n",
n->name.str, buf);
str_addf(&(ctx->SRC), "\tint i;\n");
str_addf(&(ctx->SRC), "\tint nc = pcount;\n");
str_addf(&(ctx->SRC), "\t%s **ptr = d;\n", buf);
str_addf(&(ctx->SRC), "\tif (ptr == NULL) return;\n");
str_addf(&(ctx->SRC), "\tfor(i = 0; i < nc; i ++) {\n");
str_addf(&(ctx->SRC), "\t\tif(ptr[i] == NULL) continue;\n");
str_addf(&(ctx->SRC), "\t\tfree_%s(ptr[i]);\n", n->name.str);
str_addf(&(ctx->SRC), "\t\tfree(ptr[i]);\n");
str_addf(&(ctx->SRC), "\t}\n");
str_addf(&(ctx->SRC), "\tfree(ptr);\n");
str_addf(&(ctx->SRC), "}\n");
}
}
void mk_struct_ptr_free(capnp_ctx_t *ctx, struct node *n) {
char *mapname;
char buf[256];
if (n == NULL) {
return;
}
mapname = (char *)get_mapname(n->n.annotations);
if (mapname == NULL) {
sprintf(buf, "struct %s_", n->name.str);
} else {
strcpy(buf, mapname);
}
str_addf(&(ctx->SRC), "void free_%s_ptr(%s **d){\n", n->name.str, buf);
str_addf(&(ctx->SRC), "\tif((*d) == NULL) return;\n");
str_addf(&(ctx->SRC), "\tfree_%s(*d);\n", n->name.str);
str_addf(&(ctx->SRC), "\tfree(*d);\n");
str_addf(&(ctx->SRC), "\t(*d) = NULL;\n");
str_addf(&(ctx->SRC), "}\n");
} }
struct strings { struct strings {
@ -1348,6 +1623,7 @@ struct strings {
struct str set; struct str set;
struct str encoder; struct str encoder;
struct str decoder; struct str decoder;
struct str freeup;
struct str enums; struct str enums;
struct str decl; struct str decl;
struct str var; struct str var;
@ -1514,6 +1790,8 @@ static void union_block(capnp_ctx_t *ctx, struct strings *s, struct field *f,
str_addf(&s->encoder, "%sbreak;\n", s->ftab.str); str_addf(&s->encoder, "%sbreak;\n", s->ftab.str);
decode_member(ctx, &s->decoder, f, s->ftab.str, var1, var2); decode_member(ctx, &s->decoder, f, s->ftab.str, var1, var2);
str_addf(&s->decoder, "%sbreak;\n", s->ftab.str); str_addf(&s->decoder, "%sbreak;\n", s->ftab.str);
free_member(ctx, &s->freeup, f, s->ftab.str, var1, var2);
str_addf(&s->freeup, "%sbreak;\n", s->ftab.str);
} }
str_setlen(&s->ftab, s->ftab.len - 1); str_setlen(&s->ftab, s->ftab.len - 1);
} }
@ -1546,6 +1824,8 @@ static void union_cases(capnp_ctx_t *ctx, struct strings *s, struct node *n,
field_name(f)); field_name(f));
str_addf(&s->decoder, "%scase %s_%s:\n", s->ftab.str, n->name.str, str_addf(&s->decoder, "%scase %s_%s:\n", s->ftab.str, n->name.str,
field_name(f)); field_name(f));
str_addf(&s->freeup, "%scase %s_%s:\n", s->ftab.str, n->name.str,
field_name(f));
} }
if (u) { if (u) {
@ -1571,11 +1851,13 @@ static void declare_slot(struct strings *s, struct field *f) {
static void define_group(capnp_ctx_t *ctx, struct strings *s, struct node *n, static void define_group(capnp_ctx_t *ctx, struct strings *s, struct node *n,
const char *group_name, bool enclose_unions, const char *group_name, bool enclose_unions,
const char *extattr, const char *extattr_space); const char *extattr, const char *extattr_space,
const char *uniontag);
static void do_union(capnp_ctx_t *ctx, struct strings *s, struct node *n, static void do_union(capnp_ctx_t *ctx, struct strings *s, struct node *n,
struct field *first_field, const char *union_name, struct field *first_field, const char *union_name,
const char *extattr, const char *extattr_space) { const char *extattr, const char *extattr_space,
const char *uniontag) {
int tagoff = 2 * n->n._struct.discriminantOffset; int tagoff = 2 * n->n._struct.discriminantOffset;
struct field *f; struct field *f;
static struct str tag = STR_INIT; static struct str tag = STR_INIT;
@ -1615,6 +1897,7 @@ static void do_union(capnp_ctx_t *ctx, struct strings *s, struct node *n,
str_addf(&s->encoder, "%sswitch (%s) {\n", s->ftab.str, var); str_addf(&s->encoder, "%sswitch (%s) {\n", s->ftab.str, var);
str_addf(&s->decoder, "%sswitch (%s) {\n", s->ftab.str, tag.str); str_addf(&s->decoder, "%sswitch (%s) {\n", s->ftab.str, tag.str);
str_addf(&s->freeup, "%sswitch (%s) {\n", s->ftab.str, uniontag);
} }
/* if we have a bunch of the same C type with zero defaults, we /* if we have a bunch of the same C type with zero defaults, we
@ -1658,12 +1941,13 @@ static void do_union(capnp_ctx_t *ctx, struct strings *s, struct node *n,
// own struct so that its members do not overwrite its own // own struct so that its members do not overwrite its own
// discriminant. // discriminant.
define_group(ctx, s, f->group, field_name(f), true, extattr, define_group(ctx, s, f->group, field_name(f), true, extattr,
extattr_space); extattr_space, uniontag);
str_addf(&s->get, "%sbreak;\n", s->ftab.str); str_addf(&s->get, "%sbreak;\n", s->ftab.str);
str_addf(&s->set, "%sbreak;\n", s->ftab.str); str_addf(&s->set, "%sbreak;\n", s->ftab.str);
if (ctx->g_codecgen) { if (ctx->g_codecgen) {
str_addf(&s->encoder, "%sbreak;\n", s->ftab.str); str_addf(&s->encoder, "%sbreak;\n", s->ftab.str);
str_addf(&s->decoder, "%sbreak;\n", s->ftab.str); str_addf(&s->decoder, "%sbreak;\n", s->ftab.str);
str_addf(&s->freeup, "%sbreak;\n", s->ftab.str);
} }
str_setlen(&s->ftab, s->ftab.len - 1); str_setlen(&s->ftab, s->ftab.len - 1);
break; break;
@ -1680,6 +1964,8 @@ static void do_union(capnp_ctx_t *ctx, struct strings *s, struct node *n,
field_name(f)); field_name(f));
str_addf(&s->decoder, "%scase %s_%s:\n", s->ftab.str, n->name.str, str_addf(&s->decoder, "%scase %s_%s:\n", s->ftab.str, n->name.str,
field_name(f)); field_name(f));
str_addf(&s->freeup, "%scase %s_%s:\n", s->ftab.str, n->name.str,
field_name(f));
} }
union_block( union_block(
ctx, s, f, ctx, s, f,
@ -1711,6 +1997,8 @@ static void do_union(capnp_ctx_t *ctx, struct strings *s, struct node *n,
s->ftab.str, s->ftab.str); s->ftab.str, s->ftab.str);
str_addf(&s->decoder, "%sdefault:\n%s\tbreak;\n%s}\n", s->ftab.str, str_addf(&s->decoder, "%sdefault:\n%s\tbreak;\n%s}\n", s->ftab.str,
s->ftab.str, s->ftab.str); s->ftab.str, s->ftab.str);
str_addf(&s->freeup, "%sdefault:\n%s\tbreak;\n%s}\n", s->ftab.str,
s->ftab.str, s->ftab.str);
} }
str_addf(&enums, "\n};\n"); str_addf(&enums, "\n};\n");
@ -1734,11 +2022,16 @@ static void define_field(capnp_ctx_t *ctx, struct strings *s, struct field *f,
get_mapname(f->f.annotations)); get_mapname(f->f.annotations));
decode_member(ctx, &s->decoder, f, s->ftab.str, field_name(f), decode_member(ctx, &s->decoder, f, s->ftab.str, field_name(f),
get_mapname(f->f.annotations)); get_mapname(f->f.annotations));
free_member(ctx, &s->freeup, f, s->ftab.str, field_name(f),
get_mapname(f->f.annotations));
} }
break; break;
case Field_group: case Field_group:
if (ctx->g_codecgen) { if (ctx->g_codecgen) {
char uniontagvar[256];
memset(uniontagvar, 0x0, sizeof(uniontagvar));
if (f->group != NULL) { if (f->group != NULL) {
int flen = capn_len(f->group->n._struct.fields); int flen = capn_len(f->group->n._struct.fields);
int ulen = f->group->n._struct.discriminantCount; int ulen = f->group->n._struct.discriminantCount;
@ -1758,12 +2051,16 @@ static void define_field(capnp_ctx_t *ctx, struct strings *s, struct field *f,
buf); buf);
str_addf(&s->decoder, "\td->%s = s->%s_which;\n", buf, str_addf(&s->decoder, "\td->%s = s->%s_which;\n", buf,
field_name(f)); field_name(f));
} sprintf(uniontagvar, "d->%s", buf);
} }
} }
} }
define_group(ctx, s, f->group, field_name(f), false, extattr, define_group(ctx, s, f->group, field_name(f), false, extattr,
extattr_space); extattr_space, uniontagvar);
} else {
define_group(ctx, s, f->group, field_name(f), false, extattr,
extattr_space, NULL);
}
break; break;
} }
} }
@ -1812,7 +2109,8 @@ static void define_encode_function(capnp_ctx_t *ctx, struct node *node,
const char *extattr_space) {} const char *extattr_space) {}
static void define_group(capnp_ctx_t *ctx, struct strings *s, struct node *n, static void define_group(capnp_ctx_t *ctx, struct strings *s, struct node *n,
const char *group_name, bool enclose_unions, const char *group_name, bool enclose_unions,
const char *extattr, const char *extattr_space) { const char *extattr, const char *extattr_space,
const char *uniontag) {
struct field *f; struct field *f;
int flen = capn_len(n->n._struct.fields); int flen = capn_len(n->n._struct.fields);
int ulen = n->n._struct.discriminantCount; int ulen = n->n._struct.discriminantCount;
@ -1877,7 +2175,7 @@ static void define_group(capnp_ctx_t *ctx, struct strings *s, struct node *n,
const bool keep_union_name = named_union && !enclose_unions; const bool keep_union_name = named_union && !enclose_unions;
do_union(ctx, s, n, f, keep_union_name ? group_name : NULL, extattr, do_union(ctx, s, n, f, keep_union_name ? group_name : NULL, extattr,
extattr_space); extattr_space, uniontag);
while (f < n->fields + flen && in_union(f)) while (f < n->fields + flen && in_union(f))
f++; f++;
@ -1914,6 +2212,7 @@ static void define_struct(capnp_ctx_t *ctx, struct node *n, const char *extattr,
str_reset(&s.set); str_reset(&s.set);
str_reset(&s.encoder); str_reset(&s.encoder);
str_reset(&s.decoder); str_reset(&s.decoder);
str_reset(&s.freeup);
str_reset(&s.enums); str_reset(&s.enums);
str_reset(&s.decl); str_reset(&s.decl);
str_reset(&s.var); str_reset(&s.var);
@ -1940,7 +2239,7 @@ static void define_struct(capnp_ctx_t *ctx, struct node *n, const char *extattr,
} }
} }
define_group(ctx, &s, n, NULL, false, extattr, extattr_space); define_group(ctx, &s, n, NULL, false, extattr, extattr_space, NULL);
str_add(&(ctx->HDR), s.enums.str, s.enums.len); str_add(&(ctx->HDR), s.enums.str, s.enums.len);
@ -2041,6 +2340,9 @@ static void define_struct(capnp_ctx_t *ctx, struct node *n, const char *extattr,
n->name.str, buf, n->name.str); n->name.str, buf, n->name.str);
str_addf(&(ctx->SRC), "%s\n", s.decoder.str); str_addf(&(ctx->SRC), "%s\n", s.decoder.str);
str_addf(&(ctx->SRC), "}\n"); str_addf(&(ctx->SRC), "}\n");
str_addf(&(ctx->SRC), "\nvoid free_%s(%s *d) {\n", n->name.str, buf);
str_addf(&(ctx->SRC), "%s\n", s.freeup.str);
str_addf(&(ctx->SRC), "}\n");
} }
str_add(&(ctx->SRC), s.pub_get.str, s.pub_get.len); str_add(&(ctx->SRC), s.pub_get.str, s.pub_get.len);
@ -2101,15 +2403,19 @@ static void mk_codec_declares(capnp_ctx_t *ctx, const char *n1,
"void encode_%s(struct capn_segment *,struct %s *, %s *);\n", n1, n1, "void encode_%s(struct capn_segment *,struct %s *, %s *);\n", n1, n1,
n2); n2);
str_addf(&(ctx->HDR), "void decode_%s(%s *, struct %s *);\n", n1, n2, n1); str_addf(&(ctx->HDR), "void decode_%s(%s *, struct %s *);\n", n1, n2, n1);
str_addf(&(ctx->HDR), str_addf(&(ctx->HDR), "void free_%s(%s *);\n", n1, n2);
"void encode_%s_list(struct capn_segment *,%s_list *, int, %s *);\n", str_addf(
n1, n1, n2); &(ctx->HDR),
str_addf(&(ctx->HDR), "void decode_%s_list(int *, %s **, %s_list);\n", n1, n2, "void encode_%s_list(struct capn_segment *,%s_list *, int, %s **);\n", n1,
n1); n1, n2);
str_addf(&(ctx->HDR), "void decode_%s_list(int *, %s ***, %s_list);\n", n1,
n2, n1);
str_addf(&(ctx->HDR), "void free_%s_list(int, %s **);\n", n1, n2);
str_addf(&(ctx->HDR), str_addf(&(ctx->HDR),
"void encode_%s_ptr(struct capn_segment*, %s_ptr *, %s *);\n", n1, "void encode_%s_ptr(struct capn_segment*, %s_ptr *, %s *);\n", n1,
n1, n2); n1, n2);
str_addf(&(ctx->HDR), "void decode_%s_ptr(%s **, %s_ptr);\n", n1, n2, n1); str_addf(&(ctx->HDR), "void decode_%s_ptr(%s **, %s_ptr);\n", n1, n2, n1);
str_addf(&(ctx->HDR), "void free_%s_ptr(%s **);\n", n1, n2);
} }
static void declare_codec(capnp_ctx_t *ctx, struct node *file_node) { static void declare_codec(capnp_ctx_t *ctx, struct node *file_node) {
struct node *n; struct node *n;
@ -2432,6 +2738,8 @@ int ctx_gen(capnp_ctx_t *ctx) {
mk_struct_ptr_encoder(ctx, n); mk_struct_ptr_encoder(ctx, n);
mk_struct_list_decoder(ctx, n); mk_struct_list_decoder(ctx, n);
mk_struct_ptr_decoder(ctx, n); mk_struct_ptr_decoder(ctx, n);
mk_struct_list_free(ctx, n);
mk_struct_ptr_free(ctx, n);
} }
} }

View file

@ -20,6 +20,13 @@ struct Nulldata $C.mapname("nulldata_t") {
null @0: UInt32 $C.mapname("null_"); null @0: UInt32 $C.mapname("null_");
} }
struct Buy $C.mapname("buy_t") {
from @0: Text;
u :union $C.mapname("u") $C.mapuniontag("with_recipe") {
norecipe @1: Void;
recipeAddr @2: Text $C.mapname("recipe_addr");
}
}
struct Book $C.mapname("book_t") { struct Book $C.mapname("book_t") {
title @0: Text; title @0: Text;
authors @1: List(Text) $C.mapname("authors") $C.maplistcount("n_authors"); authors @1: List(Text) $C.mapname("authors") $C.maplistcount("n_authors");
@ -29,7 +36,7 @@ struct Book $C.mapname("book_t") {
magic1 @2: List(UInt32) $C.mapname("magic_1") $C.maplistcount("n_magic1"); magic1 @2: List(UInt32) $C.mapname("magic_1") $C.maplistcount("n_magic1");
description @8: Text; description @8: Text;
acquire :union $C.mapuniontag("acquire_method") { acquire :union $C.mapuniontag("acquire_method") {
buy @3: Text; buy @3: Buy;
donation @4: Text; donation @4: Text;
} }
} }

View file

@ -20,12 +20,20 @@ typedef struct {
int null_; int null_;
} nulldata_t; } nulldata_t;
typedef struct {
char *from;
int with_recipe;
union {
char *recipe_addr;
} u;
} buy_t;
typedef struct { typedef struct {
char *title; char *title;
int n_authors; int n_authors;
char **authors; char **authors;
int n_chapters; int n_chapters;
chapter_t *chapters_; chapter_t **chapters_;
publish_t *publish; publish_t *publish;
nulldata_t *nulldata; nulldata_t *nulldata;
int n_magic1; int n_magic1;
@ -33,7 +41,7 @@ typedef struct {
char *description; char *description;
int acquire_method; int acquire_method;
union { union {
char *buy; buy_t *buy;
char *donation; char *donation;
} acquire; } acquire;
} book_t; } book_t;

View file

@ -20,7 +20,7 @@ int encode() {
uint32_t magic1[2] = { uint32_t magic1[2] = {
1101,1012 1101,1012
}; };
chapter_t chapters[3] = { chapter_t chapters_[3] = {
{.caption ="Chapter1", {.caption ="Chapter1",
.start =1, .start =1,
.end=99}, .end=99},
@ -31,10 +31,20 @@ int encode() {
.start = 151, .start = 151,
.end=199} .end=199}
}; };
chapter_t* chapters[3] = {
&chapters_[0], &chapters_[1], &chapters_[2]
};
publish_t publish = { publish_t publish = {
.isbn = 335677, .isbn = 335677,
.year =2001 .year =2001
}; };
buy_t buy = {
.from = "Xinghua Book store",
.with_recipe = Buy_u_recipeAddr,
.u = {
.recipe_addr = "Xinghua Street"
}
};
struct capn_segment *cs; struct capn_segment *cs;
struct Book b; struct Book b;
Book_ptr p; Book_ptr p;
@ -50,7 +60,7 @@ int encode() {
book.magic_1 = &magic1[0]; book.magic_1 = &magic1[0];
book.description = NULL; book.description = NULL;
book.acquire_method = Book_acquire_buy; book.acquire_method = Book_acquire_buy;
book.acquire.buy = "bought from Xinhua book store"; book.acquire.buy = &buy;
capn_init_malloc(&c); capn_init_malloc(&c);
cs = capn_root(&c).seg; cs = capn_root(&c).seg;
@ -87,10 +97,10 @@ int decode() {
printf("chapters(%d):\n", book->n_chapters); printf("chapters(%d):\n", book->n_chapters);
for(i = 0; i < book->n_chapters; i ++) { for(i = 0; i < book->n_chapters; i ++) {
printf("\tcaption: %s\n", book->chapters_[i].caption); printf("\tcaption: %s\n", book->chapters_[i]->caption);
printf("\tfrom %d to %d\n", printf("\tfrom %d to %d\n",
book->chapters_[i].start, book->chapters_[i]->start,
book->chapters_[i].end); book->chapters_[i]->end);
} }
printf("ISBN: %lu year: %u\n", printf("ISBN: %lu year: %u\n",
@ -103,12 +113,19 @@ int decode() {
} }
if (book->acquire_method == Book_acquire_buy) { if (book->acquire_method == Book_acquire_buy) {
printf("%s\n", book->acquire.buy); printf("buy from %s\n", book->acquire.buy->from);
if (book->acquire.buy->with_recipe == Buy_u_recipeAddr) {
printf("recipe address %s\n",
book->acquire.buy->u.recipe_addr);
}
} }
else { else {
printf("%s\n", book->acquire.donation); printf("%s\n", book->acquire.donation);
} }
free_Book_ptr(&book);
capn_free(&c);
return 0; return 0;
} }

View file

@ -49,6 +49,8 @@ target("book")
add_files("examples/book/*.c") add_files("examples/book/*.c")
add_includedirs("compiler","lib","examples/book") add_includedirs("compiler","lib","examples/book")
add_deps("CapnC_Runtime", "capnpc-c") add_deps("CapnC_Runtime", "capnpc-c")
add_cflags("-fsanitize=address")
add_ldflags("-fsanitize=address")
xpack("capnpc-c") xpack("capnpc-c")
set_formats("targz") set_formats("targz")