pbc4hs-0.1.0.0: cbits/proto.c
#include "pbc.h"
#include "proto.h"
#include "pattern.h"
#include "map.h"
#include "alloc.h"
#include "stringpool.h"
#include "bootstrap.h"
#include <stdlib.h>
#include <string.h>
const char *
pbc_error(struct pbc_env * p) {
const char *err = p->lasterror;
p->lasterror = "";
return err;
}
struct _message *
_pbcP_get_message(struct pbc_env * p , const char *name) {
return (struct _message *)_pbcM_sp_query(p->msgs, name);
}
struct pbc_env *
pbc_new(void) {
struct pbc_env * p = (struct pbc_env *)malloc(sizeof(*p));
p->files = _pbcM_sp_new(0 , NULL);
p->enums = _pbcM_sp_new(0 , NULL);
p->msgs = _pbcM_sp_new(0 , NULL);
p->lasterror = "";
_pbcB_init(p);
return p;
}
static void
free_enum(void *p) {
struct _enum * e = (struct _enum *)p;
_pbcM_ip_delete(e->id);
_pbcM_si_delete(e->name);
free(p);
}
static void
free_stringpool(void *p) {
_pbcS_delete((struct _stringpool *)p);
}
static void
free_msg(void *p) {
struct _message * m = (struct _message *)p;
if (m->id)
_pbcM_ip_delete(m->id);
free(m->def);
_pbcM_sp_foreach(m->name, free);
_pbcM_sp_delete(m->name);
free(p);
}
void
pbc_delete(struct pbc_env *p) {
_pbcM_sp_foreach(p->enums, free_enum);
_pbcM_sp_delete(p->enums);
_pbcM_sp_foreach(p->msgs, free_msg);
_pbcM_sp_delete(p->msgs);
_pbcM_sp_foreach(p->files, free_stringpool);
_pbcM_sp_delete(p->files);
free(p);
}
struct _enum *
_pbcP_push_enum(struct pbc_env * p, const char *name, struct map_kv *table, int sz) {
void * check = _pbcM_sp_query(p->enums, name);
if (check)
return NULL;
struct _enum * v = (struct _enum *)malloc(sizeof(*v));
v->key = name;
v->id = _pbcM_ip_new(table,sz);
v->name = _pbcM_si_new(table,sz);
v->default_v->e.id = table[0].id;
v->default_v->e.name = (const char *)table[0].pointer;
_pbcM_sp_insert(p->enums, name , v);
return v;
}
void
_pbcP_push_message(struct pbc_env * p, const char *name, struct _field *f , pbc_array queue) {
struct _message * m = (struct _message *)_pbcM_sp_query(p->msgs, name);
if (m==NULL) {
m = (struct _message *)malloc(sizeof(*m));
m->def = NULL;
m->key = name;
m->id = NULL;
m->name = _pbcM_sp_new(0 , NULL);
m->env = p;
_pbcM_sp_insert(p->msgs, name, m);
}
struct _field * field = (struct _field *)malloc(sizeof(*field));
memcpy(field,f,sizeof(*f));
_pbcM_sp_insert(m->name, field->name, field);
pbc_var atom;
atom->m.buffer = field;
if (f->type == PTYPE_MESSAGE || f->type == PTYPE_ENUM) {
_pbcA_push(queue, atom);
}
}
struct _iter {
int count;
struct map_kv * table;
};
static void
_count(void *p, void *ud) {
struct _iter *iter = (struct _iter *)ud;
iter->count ++;
}
static void
_set_table(void *p, void *ud) {
struct _field * field = (struct _field *)p;
struct _iter *iter = (struct _iter *)ud;
iter->table[iter->count].id = field->id;
iter->table[iter->count].pointer = field;
++iter->count;
}
struct _message *
_pbcP_init_message(struct pbc_env * p, const char *name) {
struct _message * m = (struct _message *)_pbcM_sp_query(p->msgs, name);
if (m == NULL) {
m = (struct _message *)malloc(sizeof(*m));
m->def = NULL;
m->key = name;
m->id = NULL;
m->name = _pbcM_sp_new(0 , NULL);
m->env = p;
_pbcM_sp_insert(p->msgs, name, m);
return m;
}
if (m->id) {
// extend message, delete old id map.
_pbcM_ip_delete(m->id);
}
struct _iter iter = { 0, NULL };
_pbcM_sp_foreach_ud(m->name, _count, &iter);
iter.table = (struct map_kv *)malloc(iter.count * sizeof(struct map_kv));
iter.count = 0;
_pbcM_sp_foreach_ud(m->name, _set_table, &iter);
m->id = _pbcM_ip_new(iter.table , iter.count);
free(iter.table);
return m;
}
int
_pbcP_message_default(struct _message * m, const char * name, pbc_var defv) {
struct _field * f= (struct _field *)_pbcM_sp_query(m->name, name);
if (f==NULL) {
// invalid key
defv->p[0] = NULL;
defv->p[1] = NULL;
return -1;
}
*defv = *(f->default_v);
return f->type;
}
int
_pbcP_type(struct _field * field, const char ** type) {
if (field == NULL) {
return 0;
}
int ret = 0;
switch (field->type) {
case PTYPE_DOUBLE:
case PTYPE_FLOAT:
ret = PBC_REAL;
break;
case PTYPE_INT64:
case PTYPE_SINT64:
ret = PBC_INT64;
break;
case PTYPE_INT32:
case PTYPE_SINT32:
ret = PBC_INT;
break;
case PTYPE_UINT32:
case PTYPE_UINT64:
ret = PBC_UINT;
break;
case PTYPE_FIXED32:
case PTYPE_SFIXED32:
ret = PBC_FIXED32;
break;
case PTYPE_SFIXED64:
case PTYPE_FIXED64:
ret = PBC_FIXED64;
break;
case PTYPE_BOOL:
ret = PBC_BOOL;
break;
case PTYPE_STRING:
ret = PBC_STRING;
break;
case PTYPE_BYTES:
ret = PBC_BYTES;
break;
case PTYPE_ENUM:
ret = PBC_ENUM;
if (type) {
*type = field->type_name.e->key;
}
break;
case PTYPE_MESSAGE:
ret = PBC_MESSAGE;
if (type) {
*type = field->type_name.m->key;
}
break;
default:
return 0;
}
if (field->label == LABEL_REPEATED ||
field->label == LABEL_PACKED) {
ret |= PBC_REPEATED;
}
return ret;
}
int
pbc_type(struct pbc_env * p, const char * type_name , const char * key , const char ** type) {
struct _message *m = _pbcP_get_message(p, type_name);
if (m==NULL) {
return 0;
}
if (key == NULL) {
return PBC_NOEXIST;
}
struct _field * field = (struct _field *)_pbcM_sp_query(m->name, key);
return _pbcP_type(field, type);
}