/** * create a serialized version of an mtree * * @param[in] oh handle of mtree node to detach from the mtree * @param[inout] sizeP pointer to size_t value to return length of serialized data * @returns pointer to newly malloced buffer of serialized tree data */ S *_m_serialize(M *m) { uint32_t s_size = SERIALIZED_HEADER_SIZE(m->levels); uint32_t levels_size = 0; size_t blob_size = 0; Mindex i; H h = {m,{0,0}}; // calculate level and blob sizes so we can allocate for(h.a.l=0; h.a.l<m->levels; h.a.l++) { L *l = GET_LEVEL(h); levels_size += SERIALIZED_LEVEL_SIZE(l); for(h.a.i=0;h.a.i < l->nodes;h.a.i++) { N *n = GET_NODE(h,l); blob_size+=n->size; } } size_t total_size = s_size+levels_size+blob_size; S *s = malloc(total_size); memset(s,0,total_size); s->magic = m->magic; s->total_size = total_size; s->levels = m->levels; s->blob_offset = s_size+levels_size; void *blob = s->blob_offset + (void *)s; levels_size = 0; blob_size = 0; for(h.a.l=0; h.a.l<m->levels; h.a.l++) { s->level_offsets[h.a.l] = levels_size; L *sl = (L *) (((void *)s) + s_size + levels_size); L *l = GET_LEVEL(h); levels_size += SERIALIZED_LEVEL_SIZE(l); sl->nodes = l->nodes; N *sn = sizeof(Mindex)+(void *)sl; for(h.a.i=0;h.a.i < l->nodes;h.a.i++) { N *n = GET_NODE(h,l); *sn = *n; // raise(SIGINT); if (n->flags & TFLAG_SURFACE_IS_RECEPTOR) { raise_error("can't serialize receptors"); } if (n->flags & TFLAG_SURFACE_IS_TREE && !(n->flags & TFLAG_SURFACE_IS_RECEPTOR)) { H sh = *(H *)n->surface; S *ss = _m_serialize(sh.m); *(size_t *)&sn->surface = blob_size; // orth tree size wasn't included in the original total size so // we have to realloc the buffer and increase the size // @todo, a better way to do this would have been to serialize the orthogonal // trees ahead of time in the size calculation loop so as not to have to // realloc here, instead we could just copy the tree in size_t new_total_size = s->total_size + ss->total_size; s = realloc(s,new_total_size); s->total_size = new_total_size; // reset pointers into the serialized block because of the realloc: // blob, sl and sn blob = s->blob_offset + (void *)s; sl = (L *) (((void *)s) + s_size + levels_size); sn = sizeof(Mindex)+(void *)sl + SERIALIZED_NODE_SIZE*h.a.i; memcpy(blob+blob_size,ss,ss->total_size); blob_size+=ss->total_size; free(ss); } else if (n->flags & TFLAG_ALLOCATED) { *(size_t *)&sn->surface = blob_size; memcpy(blob+blob_size,n->surface,n->size); blob_size+=n->size; } else { memcpy(&sn->surface,&n->surface,n->size); } sn = (N *) (SERIALIZED_NODE_SIZE + ((void*)sn)); } } return s; }
/** * create a serialized version of an mtree * * @param[in] oh handle of mtree node to detach from the mtree * @param[inout] sizeP pointer to size_t value to return length of serialized data * @returns pointer to newly malloced buffer of serialized tree data */ void * _m_serialize(M *m,size_t *sizeP) { uint32_t s_size = SERIALIZED_HEADER_SIZE(m->levels); uint32_t levels_size = 0; size_t blob_size = 0; Mlevel j; Mindex i; H h = {m,{0,0}}; // calculate level and blob sizes so we can allocate for(h.a.l=0; h.a.l<m->levels; h.a.l++) { L *l = GET_LEVEL(h); levels_size += SERIALIZED_LEVEL_SIZE(l); for(h.a.i=0;h.a.i < l->nodes;h.a.i++) { N *n = GET_NODE(h,l); blob_size+=n->size; } } S *s = malloc(*sizeP = s_size+levels_size+blob_size); memset(s,0,*sizeP); s->magic = m->magic; s->levels = m->levels; s->blob_offset = s_size+levels_size; void *blob = s->blob_offset + (void *)s; levels_size = 0; blob_size = 0; for(h.a.l=0; h.a.l<m->levels; h.a.l++) { s->level_offsets[h.a.l] = levels_size; L *sl = (L *) (((void *)s) + s_size + levels_size); L *l = GET_LEVEL(h); levels_size += SERIALIZED_LEVEL_SIZE(l); sl->nodes = l->nodes; N *sn = sizeof(Mindex)+(void *)sl; for(h.a.i=0;h.a.i < l->nodes;h.a.i++) { N *n = GET_NODE(h,l); *sn = *n; // raise(SIGINT); if (n->flags & TFLAG_ALLOCATED) { *(size_t *)&sn->surface = blob_size; memcpy(blob+blob_size,n->surface,n->size); blob_size+=n->size; } else { *((int *)&sn->surface) = *((int *)&n->surface); } sn = (N *) (SERIALIZED_NODE_SIZE + ((void*)sn)); } } return s; }