static struct pbc_wmessage * _wmessage_new(struct heap *h, struct _message *msg) { struct pbc_wmessage * m = _pbcH_alloc(h, sizeof(*m)); m->type = msg; m->buffer = _pbcH_alloc(h, WMESSAGE_SIZE); m->ptr = m->buffer; m->endptr = m->buffer + WMESSAGE_SIZE; _pbcA_open_heap(m->sub, h); m->packed = NULL; m->heap = h; return m; }
void _pbcA_push(pbc_array _array, pbc_var var) { struct array * a = (struct array *)_array; if (a->number == 0) { a->a = (union _pbc_var *)(a+1); } else if (a->number >= INNER_FIELD) { struct heap * h; union _pbc_var * outer; if (a->number == INNER_FIELD) { int cap = 1; while (cap <= a->number + 1) { cap *= 2;} h = a->heap; outer = (union _pbc_var *)HMALLOC(cap * sizeof(union _pbc_var)); memcpy(outer , a->a , INNER_FIELD * sizeof(pbc_var)); a->a = outer; } else { int size=a->number; if (((size + 1) ^ size) > size) { struct heap * h = a->heap; if (h) { void * old = a->a; a->a = (union _pbc_var *)_pbcH_alloc(h, sizeof(union _pbc_var) * (size+1) * 2); memcpy(a->a, old, sizeof(union _pbc_var) * size); } else { a->a=(union _pbc_var *)_pbcM_realloc(a->a,sizeof(union _pbc_var) * (size+1) * 2); } } } } a->a[a->number] = *var; ++ a->number; }
static struct value * read_string(struct heap *h, struct atom *a,struct _field *f, uint8_t *buffer) { const char * temp = (const char *) (buffer + a->v.s.start); int len = a->v.s.end - a->v.s.start; if (len > 0 && temp[len-1] == '\0') { struct value * v = _pbcH_alloc(h, SIZE_VAR); v->v.var->s.str = temp; v->v.var->s.len = len; return v; } else { struct value * v = _pbcH_alloc(h, SIZE_VAR + len + 1); memcpy(((char *)v) + SIZE_VAR , temp, len); *(((char *)v) + SIZE_VAR + len) = '\0'; v->v.var->s.str = ((char *)v) + SIZE_VAR; v->v.var->s.len = len; return v; } }
static void read_string_var(struct heap *h, pbc_var var,struct atom *a,struct _field *f,uint8_t *buffer) { const char * temp = (const char *) (buffer + a->v.s.start); int len = a->v.s.end - a->v.s.start; if (len == 0) { var->s.str = ""; var->s.len = 0; } else if (temp[len-1] == '\0') { var->s.str = temp; var->s.len = len; } else { char * temp2 = _pbcH_alloc(h, len + 1); memcpy(temp2, temp, len); temp2[len]='\0'; var->s.str = temp2; var->s.len = -len; } }
static struct value * read_value(struct heap *h, struct _field *f, struct atom * a, uint8_t *buffer) { struct value * v; switch (f->type) { case PTYPE_DOUBLE: CHECK_BIT64(a,NULL); v = _pbcH_alloc(h, SIZE_VAR); v->v.var->real = read_double(a); break; case PTYPE_FLOAT: CHECK_BIT32(a,NULL); v = _pbcH_alloc(h, SIZE_VAR); v->v.var->real = (double) read_float(a); break; case PTYPE_ENUM: CHECK_VARINT(a,NULL); v = _pbcH_alloc(h, SIZE_VAR); v->v.var->e.id = a->v.i.low; v->v.var->e.name = _pbcM_ip_query(f->type_name.e->id , a->v.i.low); break; case PTYPE_INT64: case PTYPE_UINT64: case PTYPE_INT32: case PTYPE_UINT32: case PTYPE_BOOL: CHECK_VARINT(a,NULL); v = _pbcH_alloc(h, SIZE_VAR); v->v.var->integer = a->v.i; break; case PTYPE_FIXED32: case PTYPE_SFIXED32: CHECK_BIT32(a,NULL); v = _pbcH_alloc(h, SIZE_VAR); v->v.var->integer = a->v.i; break; case PTYPE_FIXED64: case PTYPE_SFIXED64: CHECK_BIT64(a,NULL); v = _pbcH_alloc(h, SIZE_VAR); v->v.var->integer = a->v.i; break; case PTYPE_SINT32: CHECK_VARINT(a,NULL); v = _pbcH_alloc(h, SIZE_VAR); v->v.var->integer = a->v.i; _pbcV_dezigzag32(&(v->v.var->integer)); break; case PTYPE_SINT64: CHECK_VARINT(a,NULL); v = _pbcH_alloc(h, SIZE_VAR); v->v.var->integer = a->v.i; _pbcV_dezigzag64(&(v->v.var->integer)); break; case PTYPE_STRING: CHECK_LEND(a,NULL); v = read_string(h,a,f,buffer); break; case PTYPE_BYTES: CHECK_LEND(a,NULL); v = _pbcH_alloc(h, SIZE_VAR); v->v.var->s.str = (const char *)(buffer + a->v.s.start); v->v.var->s.len = a->v.s.end - a->v.s.start; break; case PTYPE_MESSAGE: CHECK_LEND(a,NULL); v = _pbcH_alloc(h, SIZE_MESSAGE); _pbc_rmessage_new(&(v->v.message), f->type_name.m , buffer + a->v.s.start , a->v.s.end - a->v.s.start,h); break; default: return NULL; } v->type = f; return v; }
static void _pbc_rmessage_new(struct pbc_rmessage * ret , struct _message * type , void *buffer, int size , struct heap *h) { if (size == 0) { ret->msg = type; ret->index = _pbcM_sp_new(0 , h); ret->heap = h; return; } pbc_ctx _ctx; int count = _pbcC_open(_ctx,buffer,size); if (count <= 0) { type->env->lasterror = "rmessage decode context error"; memset(ret , 0, sizeof(*ret)); return; } struct context * ctx = (struct context *)_ctx; ret->msg = type; ret->index = _pbcM_sp_new(count, h); ret->heap = h; int i; for (i=0;i<ctx->number;i++) { int id = ctx->a[i].wire_id >> 3; struct _field * f = _pbcM_ip_query(type->id , id); if (f) { if (f->label == LABEL_REPEATED || f->label == LABEL_PACKED) { struct value * v; void ** vv = _pbcM_sp_query_insert(ret->index, f->name); if (*vv == NULL) { v = _pbcH_alloc(h, SIZE_ARRAY); v->type = f; _pbcA_open_heap(v->v.array,ret->heap); *vv = v; } else { v= *vv; } if (f->label == LABEL_PACKED) { push_value_packed(type, v->v.array , f , &(ctx->a[i]), buffer); if (pbc_array_size(v->v.array) == 0) { type->env->lasterror = "rmessage decode packed data error"; *vv = NULL; } } else { push_value_array(h,v->v.array , f, &(ctx->a[i]), buffer); if (pbc_array_size(v->v.array) == 0) { type->env->lasterror = "rmessage decode repeated data error"; *vv = NULL; } } } else { struct value * v = read_value(h, f, &(ctx->a[i]), buffer); if (v) { _pbcM_sp_insert(ret->index, f->name, v); } else { type->env->lasterror = "rmessage decode data error"; } } } } _pbcC_close(_ctx); }