From 65c23b92181c4eaa82e1136e9b2e4fb11a77b035 Mon Sep 17 00:00:00 2001 From: James McKaskill Date: Sat, 11 May 2013 22:02:15 -0400 Subject: [PATCH] get recursive copy to work --- capn-test.cpp | 76 ++++++++++---- capn.c | 223 +++++++++++++++++----------------------- capn.h | 15 ++- compiler/schema.capnp.c | 17 +-- 4 files changed, 167 insertions(+), 164 deletions(-) diff --git a/capn-test.cpp b/capn-test.cpp index 491593d..a6e2419 100644 --- a/capn-test.cpp +++ b/capn-test.cpp @@ -72,10 +72,10 @@ static void setupStruct(struct capn *ctx) { ASSERT_EQ(CAPN_PTR_LIST, root.type); ASSERT_EQ(1, root.len); - struct capn_ptr ptr = capn_new_struct(root.seg, 16, 4); + struct capn_ptr ptr = capn_new_struct(root.seg, 16, 5); ASSERT_EQ(CAPN_STRUCT, ptr.type); EXPECT_EQ(16, ptr.datasz); - EXPECT_EQ(32, ptr.ptrsz); + EXPECT_EQ(40, ptr.ptrsz); EXPECT_EQ(0, capn_setp(root, 0, ptr)); EXPECT_EQ(0, capn_write64(ptr, 0, UINT64_C(0x1011121314151617))); @@ -106,6 +106,7 @@ static void setupStruct(struct capn *ctx) { capn_ptr list = capn_new_list(ptr.seg, 4, 4, 1); ASSERT_EQ(CAPN_LIST, list.type); + EXPECT_EQ(1, list.has_composite_tag); EXPECT_EQ(4, list.len); EXPECT_EQ(8, list.datasz); EXPECT_EQ(8, list.ptrsz); @@ -141,13 +142,20 @@ static void setupStruct(struct capn *ctx) { EXPECT_EQ(0, capn_set16(element, j, 500+j)); } } + + capn_ptr recurse = capn_new_struct(ptr.seg, 0, 1); + EXPECT_EQ(CAPN_STRUCT, recurse.type); + EXPECT_EQ(0, recurse.datasz); + EXPECT_EQ(8, recurse.ptrsz); + EXPECT_EQ(0, capn_setp(recurse, 0, recurse)); + EXPECT_EQ(0, capn_setp(ptr, 4, recurse)); } static void checkStruct(struct capn *ctx) { capn_ptr ptr = capn_get_root(ctx); EXPECT_EQ(CAPN_STRUCT, ptr.type); EXPECT_EQ(16, ptr.datasz); - EXPECT_EQ(32, ptr.ptrsz); + EXPECT_EQ(40, ptr.ptrsz); EXPECT_EQ(UINT64_C(0x1011121314151617), capn_read64(ptr, 0)); EXPECT_EQ(UINT32_C(0x20212223), capn_read32(ptr, 8)); EXPECT_EQ(0x3031, capn_read16(ptr, 12)); @@ -210,6 +218,17 @@ static void checkStruct(struct capn *ctx) { EXPECT_EQ(500+j, capn_get16(element, j)); } } + + capn_ptr recurse = capn_getp(ptr, 4); + EXPECT_EQ(CAPN_STRUCT, recurse.type); + EXPECT_EQ(0, recurse.datasz); + EXPECT_EQ(8, recurse.ptrsz); + capn_ptr recurse_mbr = capn_getp(recurse, 0); + EXPECT_EQ(CAPN_STRUCT, recurse_mbr.type); + EXPECT_EQ(0, recurse_mbr.datasz); + EXPECT_EQ(8, recurse_mbr.ptrsz); + EXPECT_EQ(recurse.seg, recurse_mbr.seg); + EXPECT_EQ(recurse.data, recurse_mbr.data); } TEST(WireFormat, StructRoundTrip_OneSegment) { @@ -218,7 +237,7 @@ TEST(WireFormat, StructRoundTrip_OneSegment) { // word count: // 1 root reference - // 6 root struct + // 7 root struct // 1 sub message // 2 3-element int32 list // 13 struct list @@ -230,10 +249,11 @@ TEST(WireFormat, StructRoundTrip_OneSegment) { // 11 list list // 5 references to sub-lists // 6 sub-lists (4x 1 word, 1x 2 words) + // 1 recurse // ----- - // 34 + // 36 ASSERT_EQ(1, ctx.capn.segnum); - EXPECT_EQ(34*8, ctx.capn.seglist->len); + EXPECT_EQ(36*8, ctx.capn.seglist->len); checkStruct(&ctx.capn); @@ -269,13 +289,13 @@ TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation) { setupStruct(&ctx.capn); - struct capn_segment *segments[15]; - getSegments(&ctx.capn, segments, 15); + struct capn_segment *segments[16]; + getSegments(&ctx.capn, segments, 16); // Check that each segment has the expected size. Recall that the first word of each segment will // actually be a reference to the first thing allocated within that segment. EXPECT_EQ( 8, segments[ 0]->len); // root ref - EXPECT_EQ(56, segments[ 1]->len); // root struct + EXPECT_EQ(64, segments[ 1]->len); // root struct EXPECT_EQ(16, segments[ 2]->len); // sub-struct EXPECT_EQ(24, segments[ 3]->len); // 3-element int32 list EXPECT_EQ(80, segments[ 4]->len); // struct list @@ -289,12 +309,13 @@ TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation) { EXPECT_EQ(16, segments[12]->len); // list list sublist 3 EXPECT_EQ(16, segments[13]->len); // list list sublist 4 EXPECT_EQ(24, segments[14]->len); // list list sublist 5 + EXPECT_EQ(16, segments[15]->len); // recurse struct checkStruct(&ctx.capn); struct capn ctx2; memset(&ctx2, 0, sizeof(ctx2)); - for (int i = 0; i < 15; i++) { + for (int i = 0; i < sizeof(segments)/sizeof(segments[0]); i++) { capn_append_segment(&ctx2, segments[i]); } @@ -309,13 +330,13 @@ TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation_NoTag) { setupStruct(&ctx.capn); g_AddTag = 1; - struct capn_segment *segments[29]; - getSegments(&ctx.capn, segments, 29); + struct capn_segment *segments[31]; + getSegments(&ctx.capn, segments, 31); // Check that each segment has the expected size. Note that we have plenty // of 16 byte double far ptrs. EXPECT_EQ( 8, segments[ 0]->len); // root ref - EXPECT_EQ(48, segments[ 1]->len); // root struct + EXPECT_EQ(56, segments[ 1]->len); // root struct EXPECT_EQ(16, segments[ 2]->len); // root struct ptr EXPECT_EQ( 8, segments[ 3]->len); // sub-struct EXPECT_EQ(16, segments[ 4]->len); // sub-struct ptr @@ -343,12 +364,14 @@ TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation_NoTag) { EXPECT_EQ(16, segments[26]->len); // list list sublist 4 ptr EXPECT_EQ(16, segments[27]->len); // list list sublist 5 EXPECT_EQ(16, segments[28]->len); // list list sublist 5 ptr + EXPECT_EQ( 8, segments[29]->len); // recurse struct + EXPECT_EQ(16, segments[30]->len); // recurse struct ptr checkStruct(&ctx.capn); struct capn ctx2; memset(&ctx2, 0, sizeof(ctx2)); - for (int i = 0; i < 29; i++) { + for (int i = 0; i < sizeof(segments)/sizeof(segments[0]); i++) { capn_append_segment(&ctx2, segments[i]); } @@ -387,24 +410,35 @@ TEST(WireFormat, StructRoundTrip_MultipleSegmentsWithMultipleAllocations) { // Check that each segment has the expected size. Recall that each object will be prefixed by an // extra word if its parent is in a different segment. - EXPECT_EQ(64, segments[0]->len); // root ref + struct + sub - EXPECT_EQ(56, segments[1]->len); // 3-element int32 list (+tag) + struct list substructs 1+2 (+tag) - EXPECT_EQ(80, segments[2]->len); // struct list (+tag) - EXPECT_EQ(64, segments[3]->len); // struct list substructs 3+4 (+tag) + list list sublist 1,2 (+tag) - EXPECT_EQ(64, segments[4]->len); // list list (+tag) + sublist 3,4 - EXPECT_EQ(24, segments[5]->len); // list list sublist 5 + EXPECT_EQ(64, segments[0]->len); // root ref + struct (48) + EXPECT_EQ(56, segments[1]->len); // sub (8+tag) + 3-element int32 list (16+tag) + struct list substructs 1 (8+tag) + EXPECT_EQ(80, segments[2]->len); // struct list (72+tag) + EXPECT_EQ(64, segments[3]->len); // struct list substructs 2+3+4 3*(8+tag) + list list sublist 3 (8+tag) + EXPECT_EQ(64, segments[4]->len); // list list (40+tag) + sublist 1,2 2*(8) + EXPECT_EQ(56, segments[5]->len); // list list sublist 4 (8+tag), 5 (16+tag) + recurse struct (8+tag) checkStruct(&ctx.capn); struct capn ctx2; memset(&ctx2, 0, sizeof(ctx2)); - for (int i = 0; i < 6; i++) { + for (int i = 0; i < sizeof(segments)/sizeof(segments[0]); i++) { capn_append_segment(&ctx2, segments[i]); } checkStruct(&ctx2); } +TEST(WireFormat, CopyStruct) { + Session ctx1, ctx2; + setupStruct(&ctx1.capn); + checkStruct(&ctx1.capn); + + capn_ptr root = capn_new_root(&ctx2.capn); + EXPECT_EQ(0, capn_setp(root, 0, capn_get_root(&ctx1.capn))); + + checkStruct(&ctx2.capn); +} + int main(int argc, char *argv[]) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/capn.c b/capn.c index 3ba75ce..e302c18 100644 --- a/capn.c +++ b/capn.c @@ -492,7 +492,7 @@ static void write_ptr_tag(char *d, capn_ptr p, int off) { #define NEED_TO_COPY 1 -static int write_ptr_no_copy(struct capn_segment *s, char *d, capn_ptr p) { +static int write_ptr(struct capn_segment *s, char *d, capn_ptr p) { /* note p.seg can be NULL if its a ptr to static data */ char *pdata = p.data; @@ -556,8 +556,7 @@ static int write_ptr_no_copy(struct capn_segment *s, char *d, capn_ptr p) { struct copy { struct capn_tree hdr; struct capn_ptr to, from; - char *fdata; - int fsize; + char *fbegin, *fend; }; static int data_size(const struct capn_ptr *p) { @@ -578,17 +577,16 @@ static int data_size(const struct capn_ptr *p) { static capn_ptr new_clone(struct capn_segment *s, capn_ptr p) { switch (p.type) { case CAPN_STRUCT: - return capn_new_struct(s, p.datasz, p.ptrsz); + return capn_new_struct(s, p.datasz, p.ptrsz/8); case CAPN_PTR_LIST: return capn_new_ptr_list(s, p.len); case CAPN_BIT_LIST: return capn_new_list1(s, p.len).p; case CAPN_LIST: - return capn_new_list(s, p.len, p.datasz, p.ptrsz); + return capn_new_list(s, p.len, p.datasz, p.ptrsz/8); default: return p; } - } static int is_ptr_equal(const struct capn_ptr *a, const struct capn_ptr *b) { @@ -600,45 +598,52 @@ static int is_ptr_equal(const struct capn_ptr *a, const struct capn_ptr *b) { && a->has_composite_tag == b->has_composite_tag; } -static int write_copy(struct capn_segment *seg, char *data, struct capn_ptr *t, struct capn_ptr *f, int *dep, int zeros) { +static int copy_ptr(struct capn_segment *seg, char *data, struct capn_ptr *t, struct capn_ptr *f, int *dep) { struct capn *c = seg->capn; - struct copy *cp = (struct copy*) c->copy; - int fsize = data_size(f); - char *fdata = f->data; + struct copy *cp = NULL; + struct capn_tree **xcp; + char *fbegin = f->data; + char *fend = fbegin + data_size(f); if (f->has_composite_tag) { - fsize += 8; - fdata -= 8; + fbegin -= 8; + } else if (f->is_list_member) { + fend = fbegin; } /* We always copy list members as it would otherwise be an - * overlapped pointer (the data is owned by the inclosing list). + * overlapped pointer (the data is owned by the enclosing list). * We do not bother with the overlapped lookup for zero sized * structures/lists as they never overlap. Nor do we add them to * the copy list as there is no data to be shared by multiple * pointers. */ - while (c && fsize) { - if (fdata + fsize <= cp->fdata) { - cp = (struct copy*) cp->hdr.link[0]; - } else if (cp->fdata + cp->fsize <= fdata) { - cp = (struct copy*) cp->hdr.link[1]; + xcp = &c->copy; + while (*xcp && fend > fbegin) { + cp = (struct copy*) *xcp; + if (fend <= cp->fbegin) { + xcp = &cp->hdr.link[0]; + } else if (cp->fend <= fbegin) { + xcp = &cp->hdr.link[1]; } else if (is_ptr_equal(f, &cp->from)) { /* we already have a copy so just point to that */ - return write_ptr_no_copy(seg, data, cp->from); + return write_ptr(seg, data, cp->to); } else { /* pointer to overlapped data */ return -1; } } - /* no copy - have to copy */ + /* no copy found - have to create a new copy */ *t = new_clone(seg, *f); + if (write_ptr(seg, data, *t)) + return -1; + /* add the copy to the copy tree so we can look for overlapping * source pointers and handle recursive structures */ - if (fsize && !f->is_list_member) { + if (fend > fbegin) { struct copy *n; struct capn_segment *cs = c->copylist; @@ -658,13 +663,13 @@ static int write_copy(struct capn_segment *seg, char *data, struct capn_ptr *t, n->from = *f; n->to = *t; - n->fdata = fdata; - n->fsize = fsize; + n->fbegin = fbegin; + n->fend = fend; + *xcp = &n->hdr; n->hdr.parent = &cp->hdr; - cp->hdr.link[cp->fdata < f->data] = &n->hdr; - seg->capn->copy = capn_tree_insert(seg->capn->copy, &n->hdr); + c->copy = capn_tree_insert(c->copy, &n->hdr); } /* minimize the number of types the main copy routine has to @@ -674,7 +679,7 @@ static int write_copy(struct capn_segment *seg, char *data, struct capn_ptr *t, switch (t->type) { case CAPN_STRUCT: if (t->datasz) { - memcpy(t->data, f->data, t->datasz - zeros); + memcpy(t->data, f->data, t->datasz); t->data += t->datasz; f->data += t->datasz; } @@ -714,87 +719,79 @@ static int write_copy(struct capn_segment *seg, char *data, struct capn_ptr *t, } } +void copy_list_member(capn_ptr* t, capn_ptr *f, int *dep) { + /* copy struct data */ + int sz = min(t->datasz, f->datasz); + memcpy(t->data, f->data, sz); + memset(t->data + sz, 0, t->datasz - sz); + t->data += t->datasz; + f->data += f->datasz; + + /* reset excess pointers */ + sz = min(t->ptrsz, f->ptrsz); + memset(t->data + sz, 0, t->ptrsz - sz); + + /* create a pointer list for the main loop to copy */ + if (t->ptrsz) { + t->type = CAPN_PTR_LIST; + t->len = t->ptrsz/8; + (*dep)++; + } +} + #define MAX_COPY_DEPTH 32 -int write_ptr(capn_ptr p, int off, struct capn_ptr tgt, int zeros) { +int capn_setp(capn_ptr p, int off, capn_ptr tgt) { struct capn_ptr to[MAX_COPY_DEPTH], from[MAX_COPY_DEPTH]; char *data; - int err, dep; + int err, dep = 0; switch (p.type) { case CAPN_LIST: - if (off < p.len && tgt.type == CAPN_STRUCT) { - struct capn_ptr *f, *t; - char *d; - int sz; - - /* copy struct data */ - d = p.data + off * (p.datasz + p.ptrsz); - sz = min(p.datasz, tgt.datasz); - memcpy(d, tgt.data, sz); - memset(d + sz, 0, p.datasz - sz); - - /* reset excess pointers */ - d += p.datasz; - sz = min(p.ptrsz, tgt.ptrsz); - memset(d + sz, 0, p.ptrsz - sz); - - /* create a pointer list for the main loop to copy */ - dep = 1; - - /* main copy loop doesn't need the other fields - * for ptr lists */ - f = &from[0]; - f->data = tgt.data + tgt.datasz; - f->seg = tgt.seg; - - t = &to[0]; - t->type = CAPN_PTR_LIST; - t->data = d; - t->len = sz/8; - t->seg = p.seg; - - goto copy_loop; - } else { + if (off >= p.len || tgt.type != CAPN_STRUCT) return -1; - } + + to[0] = p; + to[0].data += off * (p.datasz + p.ptrsz); + from[0] = tgt; + copy_list_member(to, from, &dep); + break; case CAPN_PTR_LIST: if (off >= p.len) return -1; data = p.data + off * 8; - break; + goto copy_ptr; case CAPN_STRUCT: off *= 8; if (off >= p.ptrsz) return -1; data = p.data + p.datasz + off; + goto copy_ptr; + + copy_ptr: + err = write_ptr(p.seg, data, tgt); + if (err != NEED_TO_COPY) + return err; + + /* Depth first copy the source whilst using a pointer stack to + * maintain the ptr to set and size left to copy at each level. + * We also maintain a rbtree (capn->copy) of the copies indexed + * by the source data. This way we can detect overlapped + * pointers in the source (and bail) and recursive structures + * (and point to the previous copy). + */ + + from[0] = tgt; + if (copy_ptr(p.seg, data, to, from, &dep)) + return -1; break; default: return -1; } - err = write_ptr_no_copy(p.seg, data, tgt); - if (err != NEED_TO_COPY) - return err; - - /* Depth first copy the source whilst using a pointer stack to - * maintain the ptr to set and size left to copy at each level. - * We also maintain a rbtree (capn->copy) of the copies indexed - * by the source data. This way we can detect overlapped - * pointers in the source (and bail) and recursive structures - * (and point to the previous copy). - */ - - dep = 0; - from[0] = tgt; - if (write_copy(p.seg, data, to, from, &dep, zeros)) - return -1; - -copy_loop: - while (dep) { struct capn_ptr *tc = &to[dep-1], *tn = &to[dep]; struct capn_ptr *fc = &from[dep-1], *fn = &from[dep]; @@ -810,16 +807,12 @@ copy_loop: switch (tc->type) { case CAPN_LIST: - *fn = *fc; - *tn = *tc; - fn->type = tn->type = CAPN_STRUCT; - fn->is_list_member = tn->is_list_member = 1; - fn->len = tn->len = 0; + *fn = capn_getp(*fc, 0); + *tn = capn_getp(*tc, 0); - if (write_copy(tc->seg, tc->data, tn, fn, &dep, 0)) - return -1; + copy_list_member(tn, fn, &dep); - fc->data += tc->datasz + tc->ptrsz; + fc->data += fc->datasz + fc->ptrsz; tc->data += tc->datasz + tc->ptrsz; tc->len--; break; @@ -828,7 +821,7 @@ copy_loop: default: *fn = read_ptr(fc->seg, fc->data); - if (write_copy(tc->seg, tc->data, tn, fn, &dep, 0)) + if (copy_ptr(tc->seg, tc->data, tn, fn, &dep)) return -1; fc->data += 8; @@ -841,10 +834,6 @@ copy_loop: return 0; } -int capn_setp(capn_ptr p, int off, capn_ptr tgt) { - return write_ptr(p, off, tgt, 0); -} - int capn_get1(capn_list1 l, int off) { return l.p.type == CAPN_BIT_LIST && off < l.p.len @@ -916,7 +905,7 @@ int capn_setv1(capn_list1 l, int off, const uint8_t *data, int sz) { #include "capn-list.inc" #undef SZ -/* pull out whether we add a tag or nor as a define so the unit test can +/* pull out whether we add a tag or not as a define so the unit test can * test double far pointers by not creating tags */ #ifndef ADD_TAG #define ADD_TAG 1 @@ -1048,9 +1037,9 @@ capn_ptr capn_new_string(struct capn_segment *seg, const char *str, int sz) { return p; } -capn_text capn_get_text(capn_ptr p, int off) { +capn_text capn_get_text(capn_ptr p, int off, capn_text def) { capn_ptr m = capn_getp(p, off); - capn_text ret = {CAPN_NULL}; + capn_text ret = def; if (m.type == CAPN_LIST && m.datasz == 1 && m.len && m.data[m.len - 1] == 0) { ret.seg = m.seg; ret.str = m.data; @@ -1059,42 +1048,24 @@ capn_text capn_get_text(capn_ptr p, int off) { return ret; } -capn_data capn_get_data(capn_ptr p, int off) { - capn_ptr m = capn_getp(p, off); - capn_data ret = {CAPN_NULL}; - if (m.type == CAPN_LIST && m.datasz == 1) { - ret.seg = m.seg; - ret.data = (uint8_t*) m.data; - ret.len = m.len; - } - return ret; -} - int capn_set_text(capn_ptr p, int off, capn_text tgt) { capn_ptr m = {CAPN_NULL}; - if (tgt.str) { + if (tgt.seg) { m.type = CAPN_LIST; m.seg = tgt.seg; m.data = (char*)tgt.str; - m.len = (tgt.len >= 0 ? tgt.len : strlen(tgt.str)) + 1; + m.len = tgt.len + 1; m.datasz = 1; + } else if (tgt.str) { + m = capn_new_string(p.seg, tgt.str, tgt.len); } - /* in the case that the size is specified we need to be careful - * that we don't read the extra byte as it may be not be null or - * may be in a different page and cause a segfault - */ - return write_ptr(p, off, m, 1); + return capn_setp(p, off, m); } -int capn_set_data(capn_ptr p, int off, capn_data tgt) { - capn_ptr m = {CAPN_NULL}; - if (tgt.data) { - m.type = CAPN_LIST; - m.seg = tgt.seg; - m.data = (char*)tgt.data; - m.len = tgt.len; - m.datasz = 1; +capn_data capn_get_data(capn_ptr p, int off) { + capn_data ret = {capn_getp(p, off)}; + if (ret.p.type != CAPN_LIST || ret.p.datasz != 1) { + memset(&ret, 0, sizeof(ret)); } - return write_ptr(p, off, m, 0); + return ret; } - diff --git a/capn.h b/capn.h index 0af17db..ba4d619 100644 --- a/capn.h +++ b/capn.h @@ -108,15 +108,9 @@ struct capn_text { struct capn_segment *seg; }; -struct capn_data { - int len; - const uint8_t *data; - struct capn_segment *seg; -}; - typedef struct capn_ptr capn_ptr; typedef struct capn_text capn_text; -typedef struct capn_data capn_data; +typedef struct {capn_ptr p;} capn_data; typedef struct {capn_ptr p;} capn_list1; typedef struct {capn_ptr p;} capn_list8; typedef struct {capn_ptr p;} capn_list16; @@ -137,10 +131,10 @@ capn_ptr capn_get_root(struct capn*); capn_ptr capn_getp(capn_ptr p, int off); int capn_setp(capn_ptr p, int off, capn_ptr tgt); -capn_text capn_get_text(capn_ptr p, int off); +capn_text capn_get_text(capn_ptr p, int off, capn_text def); capn_data capn_get_data(capn_ptr p, int off); int capn_set_text(capn_ptr p, int off, capn_text tgt); -int capn_set_data(capn_ptr p, int off, capn_data tgt); +CAPN_INLINE int capn_set_data(capn_ptr p, int off, capn_data tgt); /* capn_get_* functions get data from a list * The length of the list is given by p->size @@ -384,6 +378,9 @@ CAPN_INLINE capn_list64 capn_new_list64(struct capn_segment *seg, int sz) { capn_list64 p = {capn_new_list(seg, sz, 8, 0)}; return p; } +CAPN_INLINE int capn_set_data(capn_ptr p, int off, capn_data d) { + return capn_setp(p, off, d.p); +} #ifdef __cplusplus } diff --git a/compiler/schema.capnp.c b/compiler/schema.capnp.c index 13b04bf..2def151 100644 --- a/compiler/schema.capnp.c +++ b/compiler/schema.capnp.c @@ -1,5 +1,6 @@ #include "schema.capnp.h" /* AUTO GENERATED DO NOT EDIT*/ +static const capn_text g_nullstr = {0, ""}; Node_ptr new_Node(struct capn_segment *s) { Node_ptr p = {capn_new_struct(s, 24, 4)}; @@ -11,7 +12,7 @@ Node_list new_Node_list(struct capn_segment *s, int len) { } void read_Node(struct Node *s, Node_ptr p) { s->id = capn_read64(p.p, 0); - s->displayName = capn_get_text(p.p, 0); + s->displayName = capn_get_text(p.p, 0, g_nullstr); s->scopeId = capn_read64(p.p, 8); s->nestedNodes.p = capn_getp(p.p, 1); s->annotations.p = capn_getp(p.p, 2); @@ -67,7 +68,7 @@ Node_NestedNode_list new_Node_NestedNode_list(struct capn_segment *s, int len) { return p; } void read_Node_NestedNode(struct Node_NestedNode *s, Node_NestedNode_ptr p) { - s->name = capn_get_text(p.p, 0); + s->name = capn_get_text(p.p, 0, g_nullstr); s->id = capn_read64(p.p, 0); } int write_Node_NestedNode(const struct Node_NestedNode *s, Node_NestedNode_ptr p) { @@ -202,7 +203,7 @@ void read_Value(struct Value *s, Value_ptr p) { s->body.float64Value = capn_read_double(p.p, 8, 0.0); break; case Value_textValue: - s->body.textValue = capn_get_text(p.p, 0); + s->body.textValue = capn_get_text(p.p, 0, g_nullstr); break; case Value_dataValue: s->body.dataValue = capn_get_data(p.p, 0); @@ -329,7 +330,7 @@ FileNode_Import_list new_FileNode_Import_list(struct capn_segment *s, int len) { } void read_FileNode_Import(struct FileNode_Import *s, FileNode_Import_ptr p) { s->id = capn_read64(p.p, 0); - s->name = capn_get_text(p.p, 0); + s->name = capn_get_text(p.p, 0, g_nullstr); } int write_FileNode_Import(const struct FileNode_Import *s, FileNode_Import_ptr p) { int err = 0; @@ -386,7 +387,7 @@ StructNode_Member_list new_StructNode_Member_list(struct capn_segment *s, int le return p; } void read_StructNode_Member(struct StructNode_Member *s, StructNode_Member_ptr p) { - s->name = capn_get_text(p.p, 0); + s->name = capn_get_text(p.p, 0, g_nullstr); s->ordinal = capn_read16(p.p, 0); s->codeOrder = capn_read16(p.p, 2); s->annotations.p = capn_getp(p.p, 1); @@ -514,7 +515,7 @@ EnumNode_Enumerant_list new_EnumNode_Enumerant_list(struct capn_segment *s, int return p; } void read_EnumNode_Enumerant(struct EnumNode_Enumerant *s, EnumNode_Enumerant_ptr p) { - s->name = capn_get_text(p.p, 0); + s->name = capn_get_text(p.p, 0, g_nullstr); s->codeOrder = capn_read16(p.p, 0); s->annotations.p = capn_getp(p.p, 1); } @@ -568,7 +569,7 @@ InterfaceNode_Method_list new_InterfaceNode_Method_list(struct capn_segment *s, return p; } void read_InterfaceNode_Method(struct InterfaceNode_Method *s, InterfaceNode_Method_ptr p) { - s->name = capn_get_text(p.p, 0); + s->name = capn_get_text(p.p, 0, g_nullstr); s->codeOrder = capn_read16(p.p, 0); s->params.p = capn_getp(p.p, 1); s->requiredParamCount = capn_read16(p.p, 2); @@ -603,7 +604,7 @@ InterfaceNode_Method_Param_list new_InterfaceNode_Method_Param_list(struct capn_ return p; } void read_InterfaceNode_Method_Param(struct InterfaceNode_Method_Param *s, InterfaceNode_Method_Param_ptr p) { - s->name = capn_get_text(p.p, 0); + s->name = capn_get_text(p.p, 0, g_nullstr); s->type.p = capn_getp(p.p, 1); s->defaultValue.p = capn_getp(p.p, 2); s->annotations.p = capn_getp(p.p, 3);