static struct value * read_value(struct _field *f, struct atom * a, uint8_t *buffer) { struct value * v; switch (f->type) { case PTYPE_DOUBLE: v = malloc(SIZE_VAR); v->v.var->real = read_double(a); break; case PTYPE_FLOAT: v = malloc(SIZE_VAR); v->v.var->real = (double) read_float(a); break; case PTYPE_ENUM: v = malloc(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_FIXED32: case PTYPE_FIXED64: case PTYPE_SFIXED32: case PTYPE_SFIXED64: case PTYPE_BOOL: v = malloc(SIZE_VAR); v->v.var->integer = a->v.i; break; case PTYPE_SINT32: v = malloc(SIZE_VAR); v->v.var->integer = a->v.i; varint_dezigzag32(&(v->v.var->integer)); break; case PTYPE_SINT64: v = malloc(SIZE_VAR); v->v.var->integer = a->v.i; varint_dezigzag64(&(v->v.var->integer)); break; case PTYPE_STRING: v = read_string(a,f,buffer); break; case PTYPE_BYTES: v = malloc(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: v = malloc(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); break; default: return NULL; } v->type = f; return v; }
static void push_value_array(pbc_array array, struct _field *f, struct atom * a, uint8_t *buffer) { pbc_var v; switch (f->type) { case PTYPE_DOUBLE: v->real = read_double(a); break; case PTYPE_FLOAT: v->real = (double) read_float(a); break; case PTYPE_ENUM: v->e.id = a->v.i.low; v->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_FIXED32: case PTYPE_FIXED64: case PTYPE_SFIXED32: case PTYPE_SFIXED64: case PTYPE_BOOL: v->integer = a->v.i; break; case PTYPE_SINT32: v->integer = a->v.i; varint_dezigzag32(&(v->integer)); break; case PTYPE_SINT64: v->integer = a->v.i; varint_dezigzag64(&(v->integer)); break; case PTYPE_STRING: read_string_var(v,a,f,buffer); break; case PTYPE_BYTES: v->s.str = (const char *)(buffer + a->v.s.start); v->s.len = a->v.s.end - a->v.s.start; break; case PTYPE_MESSAGE: { struct pbc_rmessage message; _pbc_rmessage_new(&message, f->type_name.m , buffer + a->v.s.start , a->v.s.end - a->v.s.start); if (message.msg == NULL) return; v->p[0] = message.msg; v->p[1] = message.index; break; } default: return; } _pbcA_push(array,v); }
static void _pbc_rmessage_new(struct pbc_rmessage * ret , struct _message * type , void *buffer, int size) { pbc_ctx _ctx; if (_pbcC_open(_ctx,buffer,size) <=0) { memset(ret , 0, sizeof(*ret)); return; } struct context * ctx = (struct context *)_ctx; ret->msg = type; ret->index = _pbcM_sp_new(); int i; for (i=0;i<ctx->number;i++) { int id = ctx->a[i].id; 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 = malloc(SIZE_ARRAY); v->type = f; _pbcA_open(v->v.array); *vv = v; } else { v= *vv; } if (f->label == LABEL_PACKED) { push_value_packed(v->v.array , f , &(ctx->a[i]), buffer); } else { push_value_array(v->v.array , f, &(ctx->a[i]), buffer); } } else { struct value * v = read_value(f, &(ctx->a[i]), buffer); if (v) { _pbcM_sp_insert(ret->index, f->name, v); } } } } _pbcC_close(_ctx); }
static void push_value_packed(pbc_array array, struct _field *f, struct atom * aa, uint8_t *buffer) { int n = _pbcP_unpack_packed((uint8_t *)buffer + aa->v.s.start, aa->v.s.end - aa->v.s.start, f->type , array); if (n<=0) { // todo : error return; } if (f->type == PTYPE_ENUM) { int i; for (i=0;i<n;i++) { union _pbc_var * v = _pbcA_index_p(array, i); int id = v->integer.low; v->e.id = id; v->e.name = _pbcM_ip_query(f->type_name.e->id , id); } } }
static void set_field_one(struct pbc_env *p, struct _field *f) { const char * type_name = f->type_name.n; if (f->type == PTYPE_MESSAGE) { f->type_name.m = _pbcM_sp_query(p->msgs, type_name); // printf("MESSAGE: %s %p\n",type_name, f->type_name.m); } else if (f->type == PTYPE_ENUM) { f->type_name.e = _pbcM_sp_query(p->enums, type_name); // printf("ENUM: %s %p ",type_name, f->type_name.e); const char * str = f->default_v->s.str; if (str) { f->default_v->e.id = _pbcM_si_query(f->type_name.e->name, str); f->default_v->e.name = _pbcM_ip_query(f->type_name.e->id, f->default_v->e.id); // printf("[%s %d]\n",str,f->default_v->e.id); } else { memcpy(f->default_v, f->type_name.e->default_v, sizeof(pbc_var)); // printf("(%s %d)\n",f->default_v->e.name,f->default_v->e.id); } } }
static void set_field_one(struct pbc_env *p, struct _field *f) { const char * type_name = f->type_name.n; if (f->type == PTYPE_MESSAGE) { f->type_name.m = (struct _message *)_pbcM_sp_query(p->msgs, type_name); // printf("MESSAGE: %s %p\n",type_name, f->type_name.m); } else if (f->type == PTYPE_ENUM) { f->type_name.e = (struct _enum *)_pbcM_sp_query(p->enums, type_name); // printf("ENUM: %s %p ",type_name, f->type_name.e); const char * str = f->default_v->s.str; if (str && str[0]) { int err = _pbcM_si_query(f->type_name.e->name, str , &(f->default_v->e.id)); if (err < 0) goto _default; f->default_v->e.name = (const char *)_pbcM_ip_query(f->type_name.e->id, f->default_v->e.id); // printf("[%s %d]\n",str,f->default_v->e.id); } else { _default: memcpy(f->default_v, f->type_name.e->default_v, sizeof(pbc_var)); // printf("(%s %d)\n",f->default_v->e.name,f->default_v->e.id); } } }
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); }