get recursive copy to work
This commit is contained in:
parent
2ded64d310
commit
65c23b9218
4 changed files with 167 additions and 164 deletions
|
|
@ -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();
|
||||
|
|
|
|||
203
capn.c
203
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,69 +719,59 @@ 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;
|
||||
break;
|
||||
goto copy_ptr;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = write_ptr_no_copy(p.seg, data, tgt);
|
||||
copy_ptr:
|
||||
err = write_ptr(p.seg, data, tgt);
|
||||
if (err != NEED_TO_COPY)
|
||||
return err;
|
||||
|
||||
|
|
@ -788,12 +783,14 @@ int write_ptr(capn_ptr p, int off, struct capn_ptr tgt, int zeros) {
|
|||
* (and point to the previous copy).
|
||||
*/
|
||||
|
||||
dep = 0;
|
||||
from[0] = tgt;
|
||||
if (write_copy(p.seg, data, to, from, &dep, zeros))
|
||||
if (copy_ptr(p.seg, data, to, from, &dep))
|
||||
return -1;
|
||||
break;
|
||||
|
||||
copy_loop:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (dep) {
|
||||
struct capn_ptr *tc = &to[dep-1], *tn = &to[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;
|
||||
}
|
||||
|
||||
|
|
|
|||
15
capn.h
15
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue