pbc4hs (empty) → 0.1.0.0
raw patch · 29 files changed
+6409/−0 lines, 29 filesdep +basedep +hsluasetup-changed
Dependencies added: base, hslua
Files
- LICENSE +2/−0
- Setup.hs +2/−0
- cbits/alloc.c +84/−0
- cbits/alloc.h +37/−0
- cbits/array.c +139/−0
- cbits/array.h +31/−0
- cbits/bootstrap.c +303/−0
- cbits/bootstrap.h +10/−0
- cbits/context.c +280/−0
- cbits/context.h +140/−0
- cbits/decode.c +349/−0
- cbits/descriptor.pbc.h +271/−0
- cbits/map.c +477/−0
- cbits/map.h +33/−0
- cbits/pattern.c +1130/−0
- cbits/pattern.h +26/−0
- cbits/pbc-lua.c +1098/−0
- cbits/pbc.h +104/−0
- cbits/proto.c +252/−0
- cbits/proto.h +65/−0
- cbits/register.c +342/−0
- cbits/rmessage.c +455/−0
- cbits/stringpool.c +60/−0
- cbits/stringpool.h +10/−0
- cbits/varint.c +110/−0
- cbits/varint.h +20/−0
- cbits/wmessage.c +516/−0
- pbc4hs.cabal +47/−0
- src/Scripting/Lua/Pbc.hs +16/−0
+ LICENSE view
@@ -0,0 +1,2 @@+Copyright (c) 2014, david feng+public domain
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ cbits/alloc.c view
@@ -0,0 +1,84 @@+#include <stdlib.h>+#include <stdio.h>++static int _g = 0;++void * _pbcM_malloc(size_t sz) {+ ++ _g;+ return malloc(sz);+}++void _pbcM_free(void *p) {+ if (p) {+ -- _g;+ free(p);+ }+}++void* _pbcM_realloc(void *p, size_t sz) {+ return realloc(p,sz);+}++void _pbcM_memory() {+ printf("%d\n",_g); +}++struct heap_page {+ struct heap_page * next;+};++struct heap {+ struct heap_page *current;+ int size;+ int used;+};++struct heap * +_pbcH_new(int pagesize) {+ int cap = 1024;+ while(cap < pagesize) {+ cap *= 2;+ }+ struct heap * h = (struct heap *)_pbcM_malloc(sizeof(struct heap));+ h->current = (struct heap_page *)_pbcM_malloc(sizeof(struct heap_page) + cap);+ h->size = cap;+ h->used = 0;+ h->current->next = NULL;+ return h;+}++void +_pbcH_delete(struct heap *h) {+ struct heap_page * p = h->current;+ struct heap_page * next = p->next;+ for(;;) {+ _pbcM_free(p);+ if (next == NULL)+ break;+ p = next;+ next = p->next;+ }+ _pbcM_free(h);+}++void* +_pbcH_alloc(struct heap *h, int size) {+ size = (size + 3) & ~3;+ if (h->size - h->used < size) {+ struct heap_page * p;+ if (size < h->size) {+ p = (struct heap_page *)_pbcM_malloc(sizeof(struct heap_page) + h->size);+ } else {+ p = (struct heap_page *)_pbcM_malloc(sizeof(struct heap_page) + size);+ }+ p->next = h->current;+ h->current = p;+ h->used = size;+ return (p+1);+ } else {+ char * buffer = (char *)(h->current + 1);+ buffer += h->used;+ h->used += size;+ return buffer;+ }+}
+ cbits/alloc.h view
@@ -0,0 +1,37 @@+#ifndef PROTOBUF_C_ALLOC_H+#define PROTOBUF_C_ALLOC_H++#include <stdlib.h>+#include <string.h>++void * _pbcM_malloc(size_t sz);+void _pbcM_free(void *p);+void * _pbcM_realloc(void *p, size_t sz);+void _pbcM_memory();++struct heap;++struct heap * _pbcH_new(int pagesize);+void _pbcH_delete(struct heap *);+void* _pbcH_alloc(struct heap *, int size);++#define HMALLOC(size) ((h) ? _pbcH_alloc(h, size) : _pbcM_malloc(size))++#define malloc _pbcM_malloc+#define free _pbcM_free+#define realloc _pbcM_realloc+#define memory _pbcM_memory++#ifdef _WIN32++#include <malloc.h>++#endif++#ifdef _MSC_VER++#define alloca _alloca++#endif++#endif
+ cbits/array.c view
@@ -0,0 +1,139 @@+#include "pbc.h"+#include "array.h"+#include "alloc.h"++#include <stdlib.h>+#include <string.h>++struct array {+ int number;+ struct heap *heap;+ union _pbc_var * a;+};++#define INNER_FIELD ((PBC_ARRAY_CAP - sizeof(struct array)) / sizeof(pbc_var))++void +_pbcA_open(pbc_array _array) {+ struct array * a = (struct array *)_array;+ a->number = 0;+ a->heap = NULL;+ a->a = (union _pbc_var *)(a+1);+}++void +_pbcA_open_heap(pbc_array _array, struct heap *h) {+ struct array * a = (struct array *)_array;+ a->number = 0;+ a->heap = h;+ a->a = (union _pbc_var *)(a+1);+}++void +_pbcA_close(pbc_array _array) {+ struct array * a = (struct array *)_array;+ if (a->heap == NULL && a->a != NULL && (union _pbc_var *)(a+1) != a->a) {+ _pbcM_free(a->a);+ a->a = NULL;+ }+}++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) {+ if (a->number == INNER_FIELD) {+ int cap = 1;+ while (cap <= a->number + 1) + cap *= 2;+ struct heap * h = a->heap;+ union _pbc_var * 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;+}++void +_pbcA_index(pbc_array _array, int idx, pbc_var var)+{+ struct array * a = (struct array *)_array;+ var[0] = a->a[idx];+}++void *+_pbcA_index_p(pbc_array _array, int idx)+{+ struct array * a = (struct array *)_array;+ return &(a->a[idx]);+}++int +pbc_array_size(pbc_array _array) {+ struct array * a = (struct array *)_array;+ return a->number;+}++uint32_t +pbc_array_integer(pbc_array array, int index, uint32_t *hi) {+ pbc_var var;+ _pbcA_index(array , index , var);+ if (hi) {+ *hi = var->integer.hi;+ }+ return var->integer.low;+}++double +pbc_array_real(pbc_array array, int index) {+ pbc_var var;+ _pbcA_index(array , index , var);+ return var->real;+}++struct pbc_slice *+pbc_array_slice(pbc_array _array, int index) {+ struct array * a = (struct array *)_array;+ if (index <0 || index > a->number) {+ return NULL;+ }+ return (struct pbc_slice *) &(a->a[index]);+}++void +pbc_array_push_integer(pbc_array array, uint32_t low, uint32_t hi) {+ pbc_var var;+ var->integer.low = low;+ var->integer.hi = hi;+ _pbcA_push(array,var);+}++void +pbc_array_push_slice(pbc_array array, struct pbc_slice *s) {+ pbc_var var;+ var->m = *s;+ _pbcA_push(array,var);+}++void +pbc_array_push_real(pbc_array array, double v) {+ pbc_var var;+ var->real = v;+ _pbcA_push(array,var);+}
+ cbits/array.h view
@@ -0,0 +1,31 @@+#ifndef PROTOBUF_C_ARRAY_H+#define PROTOBUF_C_ARRAY_H++#include "varint.h"+#include "pbc.h"+#include "alloc.h"++typedef union _pbc_var {+ struct longlong integer;+ double real;+ struct {+ const char * str;+ int len;+ } s;+ struct {+ int id;+ const char * name;+ } e;+ struct pbc_slice m;+ void * p[2];+} pbc_var[1];++void _pbcA_open(pbc_array);+void _pbcA_open_heap(pbc_array, struct heap *h);+void _pbcA_close(pbc_array);++void _pbcA_push(pbc_array, pbc_var var);+void _pbcA_index(pbc_array , int idx, pbc_var var);+void * _pbcA_index_p(pbc_array _array, int idx);++#endif
+ cbits/bootstrap.c view
@@ -0,0 +1,303 @@+#include "pbc.h"+#include "map.h"+#include "context.h"+#include "pattern.h"+#include "proto.h"+#include "alloc.h"+#include "bootstrap.h"+#include "stringpool.h"+#include "array.h"+#include "descriptor.pbc.h"++#include <stdlib.h>+#include <stddef.h>+#include <string.h>+#include <stdint.h>++/*++// Descriptor++// google.protobuf.Descriptor.proto encoded in descriptor.pbc.h with proto pbc.file .++package pbc;++message field {+ optional string name = 1;+ optional int32 id = 2;+ optional int32 label = 3; // 0 optional 1 required 2 repeated + optional int32 type = 4; // type_id+ optional string type_name = 5; + optional int32 default_int = 6; + optional string default_string = 7;+ optional double default_real = 8;+}++message file {+ optional string name = 1;+ repeated string dependency = 2;++ repeated string message_name = 3;+ repeated int32 message_size = 4;+ repeated field message_field = 5;++ repeated string enum_name = 6;+ repeated int32 enum_size = 7;+ repeated string enum_string = 8;+ repeated int32 enum_id = 9;+}++*/++struct field_t {+ struct pbc_slice name;+ int32_t id;+ int32_t label;+ int32_t type;+ struct pbc_slice type_name;+ int32_t default_integer;+ struct pbc_slice default_string;+ double default_real;+};++struct file_t {+ struct pbc_slice name; // string+ pbc_array dependency; // string+ pbc_array message_name; // string+ pbc_array message_size; // int32+ pbc_array message_field; // field_t+ pbc_array enum_name; // string+ pbc_array enum_size; // int32+ pbc_array enum_string; // string+ pbc_array enum_id; // int32+};++static void+set_enum_one(struct pbc_env *p, struct file_t *file, const char *name, int start, int sz) {+ struct map_kv *table = (struct map_kv *)malloc(sz * sizeof(struct map_kv));+ int i;+ for (i=0;i<sz;i++) {+ pbc_var id;+ pbc_var string;+ _pbcA_index(file->enum_id, start+i, id);+ _pbcA_index(file->enum_string, start+i, string);+ table[i].id = (int)id->integer.low;+ table[i].pointer = (void *)string->s.str;+ }+ _pbcP_push_enum(p,name,table,sz);++ free(table);+}++static void+set_enums(struct pbc_env *p, struct file_t *file) {+ int n = pbc_array_size(file->enum_size);+ int i;+ int start = 0;+ for (i=0;i<n;i++) {+ pbc_var name;+ _pbcA_index(file->enum_name,i,name);+ pbc_var var;+ _pbcA_index(file->enum_size,i,var);+ set_enum_one(p, file, name->s.str, start , (int)var->integer.low);+ start += var->integer.low;+ }+}++static void+set_default(struct _field *f, struct field_t *input) {+ switch (f->type) {+ case PTYPE_DOUBLE:+ case PTYPE_FLOAT:+ f->default_v->real = input->default_real;+ break;+ case PTYPE_STRING:+ case PTYPE_ENUM:+ f->default_v->m = input->default_string;+ break;+ default:+ f->default_v->integer.low = input->default_integer;+ break;+ }+}++static void+set_msg_one(struct pbc_pattern * FIELD_T, struct pbc_env *p, struct file_t *file, const char *name, int start, int sz , pbc_array queue) {+ int i;+ for (i=0;i<sz;i++) {+ pbc_var _field;+ _pbcA_index(file->message_field, start+i, _field);+ struct field_t field;++ int ret = pbc_pattern_unpack(FIELD_T, &_field->m, &field);+ if (ret != 0) {+ continue;+ }+ struct _field f;+ f.id = field.id;+ f.name = (const char *)field.name.buffer;+ f.type = field.type;+ f.label = field.label;+ f.type_name.n = (const char *)field.type_name.buffer;+ set_default(&f, &field);++ _pbcP_push_message(p,name, &f , queue);++ // don't need to close pattern since no array+ }+ _pbcP_init_message(p, name);+}++static void+set_msgs(struct pbc_pattern * FIELD_T, struct pbc_env *p, struct file_t *file , pbc_array queue) {+ int n = pbc_array_size(file->message_size);+ int i;+ int start = 0;+ for (i=0;i<n;i++) {+ pbc_var name;+ _pbcA_index(file->message_name,i,name);+ pbc_var sz;+ _pbcA_index(file->message_size,i,sz);+ set_msg_one(FIELD_T, p, file, name->s.str, start , (int)sz->integer.low , queue);+ start += sz->integer.low;+ }+}++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);+ }+ }+}++void+_pbcB_register_fields(struct pbc_env *p, pbc_array queue) {+ int sz = pbc_array_size(queue);+ int i;+ for (i=0;i<sz;i++) {+ pbc_var atom;+ _pbcA_index(queue,i,atom);+ struct _field * f = (struct _field *)atom->m.buffer;+ set_field_one(p, f);+ }+}++static void+_set_string(struct _pattern_field * f) {+ f->ptype = PTYPE_STRING;+ f->ctype = CTYPE_VAR;+ f->defv->s.str = "";+ f->defv->s.len = 0;+}++static void+_set_int32(struct _pattern_field * f) {+ f->ptype = PTYPE_INT32;+ f->ctype = CTYPE_INT32;+}++static void+_set_double(struct _pattern_field * f) {+ f->ptype = PTYPE_DOUBLE;+ f->ctype = CTYPE_DOUBLE;+}++static void+_set_message_array(struct _pattern_field *f) {+ f->ptype = PTYPE_MESSAGE;+ f->ctype = CTYPE_ARRAY;+}++static void+_set_string_array(struct _pattern_field * f) {+ f->ptype = PTYPE_STRING;+ f->ctype = CTYPE_ARRAY;+}++static void+_set_int32_array(struct _pattern_field * f) {+ f->ptype = PTYPE_INT32;+ f->ctype = CTYPE_ARRAY;+}++#define SET_PATTERN(pat , idx , pat_type, field_name , type) \+ pat->f[idx].id = idx+1 ; \+ pat->f[idx].offset = offsetof(struct pat_type, field_name); \+ _set_##type(&pat->f[idx]);++#define F(idx,field_name,type) SET_PATTERN(FIELD_T, idx, field_t ,field_name, type)+#define D(idx,field_name,type) SET_PATTERN(FILE_T, idx, file_t ,field_name, type)++static int+register_internal(struct pbc_env * p, struct pbc_slice *slice) {+ struct pbc_pattern * FIELD_T = _pbcP_new(p,8);+ F(0,name,string);+ F(1,id,int32);+ F(2,label,int32);+ F(3,type,int32);+ F(4,type_name,string);+ F(5,default_integer,int32);+ F(6,default_string,string);+ F(7,default_real,double);++ struct pbc_pattern * FILE_T = _pbcP_new(p,10);++ D(0,name,string);+ D(1,dependency,string_array);+ D(2,message_name,string_array);+ D(3,message_size,int32_array);+ D(4,message_field,message_array);+ D(5,enum_name,string_array);+ D(6,enum_size,int32_array);+ D(7,enum_string,string_array);+ D(8,enum_id,int32_array);++ int ret = 0;++ struct file_t file;+ int r = pbc_pattern_unpack(FILE_T, slice, &file);+ if (r != 0) {+ ret = 1;+ goto _return;+ }++ _pbcM_sp_insert(p->files , (const char *)file.name.buffer, NULL);++ pbc_array queue;+ _pbcA_open(queue);++ set_enums(p, &file);+ set_msgs(FIELD_T, p, &file, queue);+ _pbcB_register_fields(p, queue);++ _pbcA_close(queue);+ pbc_pattern_close_arrays(FILE_T, &file);++_return:+ free(FIELD_T);+ free(FILE_T);+ return ret;+}++void +_pbcB_init(struct pbc_env * p) {+ struct pbc_slice slice = { pbc_descriptor,sizeof(pbc_descriptor) };+ register_internal(p,&slice);+}
+ cbits/bootstrap.h view
@@ -0,0 +1,10 @@+#ifndef PROTOBUF_C_BOOTSTRAP_H+#define PROTOBUF_C_BOOTSTRAP_H++#include "proto.h"+#include "pbc.h"++void _pbcB_init(struct pbc_env *);+void _pbcB_register_fields(struct pbc_env *, pbc_array queue);++#endif
+ cbits/context.c view
@@ -0,0 +1,280 @@+#include "pbc.h"+#include "alloc.h"+#include "varint.h"+#include "context.h"++#include <stdlib.h>+#include <string.h>+#include <stdint.h>+#ifndef _MSC_VER+#include <stdbool.h>+#endif++#define INNER_ATOM ((PBC_CONTEXT_CAP - sizeof(struct context)) / sizeof(struct atom))++static char * +wiretype_decode(uint8_t *buffer, int cap , struct atom *a , int start)+{+ uint8_t temp[10];+ struct longlong r;+ int len;+ if (cap >= 10) {+ len = _pbcV_decode(buffer, &r);+ if (r.hi !=0)+ return NULL;+ } else {+ memcpy(temp, buffer , cap);+ len = _pbcV_decode(temp, &r);+ if (len > cap || r.hi !=0)+ return NULL;+ }++ int wiretype = r.low & 7;+ a->wire_id = r.low;+ buffer += len;+ start += len;+ cap -=len;+ + switch (wiretype) {+ case WT_VARINT :+ if (cap >=10) {+ len = _pbcV_decode(buffer, &a->v.i);+ } else {+ memcpy(temp, buffer , cap);+ len = _pbcV_decode(temp, &a->v.i);+ if (cap < len)+ return NULL;+ }+ return (char *)buffer+len;+ case WT_BIT64 :+ if (cap < 8)+ return NULL;+ a->v.i.low = buffer[0] |+ buffer[1] << 8 |+ buffer[2] << 16 |+ buffer[3] << 24;+ a->v.i.hi = buffer[4] |+ buffer[5] << 8 |+ buffer[6] << 16 |+ buffer[7] << 24;+ return (char *)buffer + 8;+ case WT_LEND :+ if (cap >=10) {+ len = _pbcV_decode(buffer, &r);+ } else {+ memcpy(temp, buffer , cap);+ len = _pbcV_decode(temp, &r);+ }+ if (cap < len + r.low || r.hi !=0)+ return NULL;+ a->v.s.start = start + len;+ a->v.s.end = start + len + r.low;+ return (char *)buffer + len + r.low;+ case WT_BIT32 :+ if (cap < 4)+ return NULL;+ a->v.i.low = buffer[0] |+ buffer[1] << 8 |+ buffer[2] << 16 |+ buffer[3] << 24;+ a->v.i.hi = 0;+ return (char *)buffer + 4;+ default:+ return NULL;+ }+}++static inline int+_decode_varint(uint8_t * buffer, int size , struct atom * a) {+ a->wire_id = WT_VARINT;+ if (size < 10) {+ uint8_t temp[10];+ memcpy(temp,buffer,size);+ return _pbcV_decode(temp , &(a->v.i));+ } else {+ return _pbcV_decode(buffer , &(a->v.i));+ }+}++static int+_open_packed_varint(struct context * ctx , uint8_t * buffer, int size) {+ struct atom * a = (struct atom *)(ctx + 1);++ int i;++ for (i=0;i<INNER_ATOM;i++) {+ if (size == 0)+ break;+ int len = _decode_varint(buffer, size, &a[i]);+ buffer += len;+ size -= len;+ }++ if (size == 0) {+ ctx->a = a;+ } else {+ int cap = 64;+ ctx->a = (struct atom *)malloc(cap * sizeof(struct atom));+ while (size > 0) {+ if (i >= cap) {+ cap = cap + 64;+ ctx->a = (struct atom *)realloc(ctx->a, cap * sizeof(struct atom));+ continue;+ }+ int len = _decode_varint(buffer, size, &a[i]);+ buffer += len;+ size -= len;++ ++i;+ }+ memcpy(ctx->a, a , sizeof(struct atom) * INNER_ATOM);+ }+ ctx->number = i;++ return i;+}++int +_pbcC_open_packed(pbc_ctx _ctx, int ptype, void *buffer, int size) {+ struct context * ctx = (struct context *)_ctx;+ ctx->buffer = (char *)buffer;+ ctx->size = size;+ ctx->number = 0;+ ctx->a = NULL;++ if (buffer == NULL || size == 0) {+ return 0;+ }++ int bits = 0;++ switch (ptype) {+ case PTYPE_INT64:+ case PTYPE_UINT64:+ case PTYPE_INT32:+ case PTYPE_BOOL:+ case PTYPE_UINT32:+ case PTYPE_ENUM:+ case PTYPE_SINT32:+ case PTYPE_SINT64:+ return _open_packed_varint(ctx , (uint8_t *)buffer, size);+ case PTYPE_DOUBLE:+ case PTYPE_FIXED64:+ case PTYPE_SFIXED64:+ ctx->number = size / 8;+ bits = 64;+ break;+ case PTYPE_FLOAT:+ case PTYPE_FIXED32:+ case PTYPE_SFIXED32:+ ctx->number = size / 4;+ bits = 32;+ break;+ default:+ return 0;+ }++ struct atom * a = (struct atom *)(ctx + 1);++ if (ctx->number > INNER_ATOM) {+ ctx->a = (struct atom *)malloc(ctx->number * sizeof(struct atom));+ a = ctx->a;+ } else {+ ctx->a = a;+ }++ int i;+ if (bits == 64) {+ uint8_t * data = (uint8_t *)buffer;+ for (i=0;i<ctx->number;i++) {+ a[i].wire_id = WT_BIT64;+ a[i].v.i.low = data[0] |+ data[1] << 8 |+ data[2] << 16 |+ data[3] << 24;+ a[i].v.i.hi = data[4] |+ data[5] << 8 |+ data[6] << 16 |+ data[7] << 24;+ data += 8;+ }+ } else {+ uint8_t * data = (uint8_t *)buffer;+ for (i=0;i<ctx->number;i++) {+ a[i].wire_id = WT_BIT32;+ a[i].v.i.low = data[0] |+ data[1] << 8 |+ data[2] << 16 |+ data[3] << 24;+ a[i].v.i.hi = 0;+ data += 4;+ }+ }++ return ctx->number;+}++int +_pbcC_open(pbc_ctx _ctx , void *buffer, int size) {+ struct context * ctx = (struct context *)_ctx;+ ctx->buffer = (char *)buffer;+ ctx->size = size;++ if (buffer == NULL || size == 0) {+ ctx->number = 0;+ ctx->a = NULL;+ return 0;+ }++ struct atom * a = (struct atom *)(ctx + 1);++ int i;+ int start = 0;++ ctx->a = a;++ for (i=0;i<INNER_ATOM;i++) {+ if (size == 0)+ break;+ char * next = wiretype_decode((uint8_t *)buffer, size , &a[i] , start);+ if (next == NULL)+ return -i;+ start += next - (char *)buffer;+ size -= next - (char *)buffer;+ buffer = next;+ }++ if (size > 0) {+ int cap = 64;+ ctx->a = (struct atom *)malloc(cap * sizeof(struct atom));+ while (size > 0) {+ if (i >= cap) {+ cap = cap + 64;+ ctx->a = (struct atom *)realloc(ctx->a, cap * sizeof(struct atom));+ continue;+ }+ char * next = wiretype_decode((uint8_t *)buffer, size , &ctx->a[i] , start);+ if (next == NULL) {+ return -i;+ }+ start += next - (char *)buffer;+ size -= next - (char *)buffer;+ buffer = next;+ ++i;+ }+ memcpy(ctx->a, a , sizeof(struct atom) * INNER_ATOM);+ }+ ctx->number = i;++ return i;+}+++void +_pbcC_close(pbc_ctx _ctx) {+ struct context * ctx = (struct context *)_ctx;+ if (ctx->a != NULL && (struct atom *)(ctx+1) != ctx->a) {+ free(ctx->a);+ ctx->a = NULL;+ }+}
+ cbits/context.h view
@@ -0,0 +1,140 @@+#ifndef PROTOBUF_C_CONTEXT_H+#define PROTOBUF_C_CONTEXT_H++#include <stdint.h>++#include "array.h"++#define PBC_CONTEXT_CAP 256++// wiretype++#define WT_VARINT 0+#define WT_BIT64 1+#define WT_LEND 2+#define WT_BIT32 5++#define CTYPE_INT32 1+#define CTYPE_INT64 2+#define CTYPE_DOUBLE 3+#define CTYPE_FLOAT 4+#define CTYPE_POINTER 5+#define CTYPE_BOOL 6+#define CTYPE_INT8 7+#define CTYPE_INT16 8+#define CTYPE_ARRAY 9+#define CTYPE_VAR 10+#define CTYPE_PACKED 11++#define PTYPE_DOUBLE 1+#define PTYPE_FLOAT 2+#define PTYPE_INT64 3 // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if negative values are likely.+#define PTYPE_UINT64 4+#define PTYPE_INT32 5 // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if negative values are likely.+#define PTYPE_FIXED64 6+#define PTYPE_FIXED32 7+#define PTYPE_BOOL 8+#define PTYPE_STRING 9+#define PTYPE_GROUP 10 // Tag-delimited aggregate.+#define PTYPE_MESSAGE 11 // Length-delimited aggregate.+#define PTYPE_BYTES 12+#define PTYPE_UINT32 13+#define PTYPE_ENUM 14+#define PTYPE_SFIXED32 15+#define PTYPE_SFIXED64 16+#define PTYPE_SINT32 17 // Uses ZigZag encoding.+#define PTYPE_SINT64 18 // Uses ZigZag encoding.++struct slice {+ int start;+ int end;+};++struct atom {+ int wire_id;+ union {+ struct slice s;+ struct longlong i;+ } v;+};++struct context {+ char * buffer;+ int size;+ int number;+ struct atom * a;+};++typedef struct _pbc_ctx { char _data[PBC_CONTEXT_CAP]; } pbc_ctx[1];++int _pbcC_open(pbc_ctx , void *buffer, int size); // <=0 failed+int _pbcC_open_packed(pbc_ctx _ctx, int ptype, void *buffer, int size);+void _pbcC_close(pbc_ctx);++static inline double+read_double(struct atom * a) {+ union {+ uint64_t i;+ double d;+ } u;+ u.i = (uint64_t) a->v.i.low | (uint64_t) a->v.i.hi << 32;+ return u.d;+}++static inline float+read_float(struct atom * a) {+ union {+ uint32_t i;+ float f;+ } u;+ u.i = a->v.i.low;+ return u.f;+}++static inline void+double_encode(double v , uint8_t * buffer) {+ union {+ double v;+ uint64_t e;+ } u;+ u.v = v;+ buffer[0] = (uint8_t) (u.e & 0xff);+ buffer[1] = (uint8_t) (u.e >> 8 & 0xff);+ buffer[2] = (uint8_t) (u.e >> 16 & 0xff);+ buffer[3] = (uint8_t) (u.e >> 24 & 0xff);+ buffer[4] = (uint8_t) (u.e >> 32 & 0xff);+ buffer[5] = (uint8_t) (u.e >> 40 & 0xff);+ buffer[6] = (uint8_t) (u.e >> 48 & 0xff);+ buffer[7] = (uint8_t) (u.e >> 56 & 0xff);+}++static inline void+float_encode(float v , uint8_t * buffer) {+ union {+ float v;+ uint32_t e;+ } u;+ u.v = v;+ buffer[0] = (uint8_t) (u.e & 0xff);+ buffer[1] = (uint8_t) (u.e >> 8 & 0xff);+ buffer[2] = (uint8_t) (u.e >> 16 & 0xff);+ buffer[3] = (uint8_t) (u.e >> 24 & 0xff);+}++#define CHECK_LEND(a,err) if ((a->wire_id & 7) != WT_LEND) return err;++#if 0+/* maybe we don't need check these wire type */+#define CHECK_VARINT(a,err) if ((a->wire_id & 7) != WT_VARINT) return err;+#define CHECK_BIT32(a,err) if ((a->wire_id & 7) != WT_BIT32) return err;+#define CHECK_BIT64(a,err) if ((a->wire_id & 7) != WT_BIT64) return err;++#else++#define CHECK_VARINT(a,err)+#define CHECK_BIT32(a,err)+#define CHECK_BIT64(a,err)++#endif++#endif
+ cbits/decode.c view
@@ -0,0 +1,349 @@+#include "pbc.h"+#include "alloc.h"+#include "context.h"+#include "proto.h"+#include "varint.h"++#include <assert.h>++static const char * TYPENAME[] = {+ "invalid", // 0+ "integer", // 1+ "real", // 2+ "boolean", // 3+ "enum", // 4+ "string", // 5+ "message", // 6+ "fixed64", // 7+ "fixed32", // 8+ "bytes", // 9+ "int64", // 10+ "uint", // 11+};++static int+call_unknown(pbc_decoder f, void * ud, int id, struct atom *a, uint8_t * start) {+ union pbc_value v;+ switch (a->wire_id & 7) {+ case WT_VARINT:+ v.i.low = a->v.i.low;+ v.i.hi = a->v.i.hi;+ f(ud, PBC_INT, TYPENAME[PBC_INT], &v, id , NULL);+ break;+ case WT_BIT64:+ v.i.low = a->v.i.low;+ v.i.hi = a->v.i.hi;+ f(ud, PBC_FIXED64, TYPENAME[PBC_FIXED64], &v, id , NULL);+ break;+ case WT_LEND:+ v.s.buffer = (char*)start + a->v.s.start;+ v.s.len = a->v.s.end - a->v.s.start;+ f(ud, PBC_BYTES, TYPENAME[PBC_BYTES], &v, id , NULL);+ break;+ case WT_BIT32:+ v.i.low = a->v.i.low;+ v.i.hi = 0;+ f(ud, PBC_FIXED32, TYPENAME[PBC_FIXED32], &v, id , NULL);+ break;+ default:+ return 1;+ }+ return 0;+}++static int+call_type(pbc_decoder pd, void * ud, struct _field *f, struct atom *a, uint8_t * start) {+ union pbc_value v;+ const char * type_name = NULL;+ int type = _pbcP_type(f, &type_name);+ assert(type != 0);+ if (type_name == NULL) {+ type_name = TYPENAME[type & ~PBC_REPEATED];+ }+ switch (f->type) {+ case PTYPE_DOUBLE:+ CHECK_BIT64(a, -1);+ v.f = read_double(a);+ break;+ case PTYPE_FLOAT:+ CHECK_BIT32(a, -1);+ v.f = (double) read_float(a);+ break;+ case PTYPE_ENUM:+ CHECK_VARINT(a, -1);+ v.e.id = a->v.i.low;+ v.e.name = (const char *)_pbcM_ip_query(f->type_name.e->id , v.e.id);+ break;+ case PTYPE_INT64:+ case PTYPE_UINT64:+ CHECK_VARINT(a, -1);+ v.i.low = a->v.i.low;+ v.i.hi = a->v.i.hi;+ break;+ case PTYPE_FIXED64:+ case PTYPE_SFIXED64:+ CHECK_BIT64(a, -1);+ v.i.low = a->v.i.low;+ v.i.hi = a->v.i.hi;+ break;+ case PTYPE_INT32:+ case PTYPE_UINT32:+ case PTYPE_BOOL:+ CHECK_VARINT(a, -1);+ v.i.low = a->v.i.low;+ v.i.hi = 0;+ break;+ case PTYPE_FIXED32:+ case PTYPE_SFIXED32:+ CHECK_BIT32(a, -1);+ v.i.low = a->v.i.low;+ v.i.hi = 0;+ break;+ case PTYPE_SINT32: + CHECK_VARINT(a, -1);+ v.i.low = a->v.i.low;+ v.i.hi = a->v.i.hi;+ _pbcV_dezigzag32((struct longlong *)&(v.i));+ break;+ case PTYPE_SINT64:+ CHECK_VARINT(a, -1);+ v.i.low = a->v.i.low;+ v.i.hi = a->v.i.hi;+ _pbcV_dezigzag64((struct longlong *)&(v.i));+ break;+ case PTYPE_STRING:+ case PTYPE_BYTES:+ case PTYPE_MESSAGE:+ CHECK_LEND(a, -1);+ v.s.buffer = start + a->v.s.start;+ v.s.len = a->v.s.end - a->v.s.start;+ break;+ default:+ assert(0);+ break;+ }+ pd(ud, type, type_name, &v, f->id, f->name);+ return 0;+}++static int+call_array(pbc_decoder pd, void * ud, struct _field *f, uint8_t * buffer , int size) {+ union pbc_value v;+ const char * type_name = NULL;+ int type = _pbcP_type(f, &type_name);+ assert(type != 0);+ if (type_name == NULL) {+ type_name = TYPENAME[type & ~PBC_REPEATED];+ }+ v.i.hi = 0;+ int i;+ switch(f->type) {+ case PTYPE_DOUBLE:+ if (size % 8 != 0) {+ return -1;+ }+ for (i=0;i<size;i+=8) {+ union {+ double d;+ uint64_t i64;+ } u;+ u.i64 = (uint64_t)buffer[i] |+ (uint64_t)buffer[i+1] << 8 |+ (uint64_t)buffer[i+2] << 16 |+ (uint64_t)buffer[i+3] << 24 |+ (uint64_t)buffer[i+4] << 32 |+ (uint64_t)buffer[i+5] << 40 |+ (uint64_t)buffer[i+6] << 48 |+ (uint64_t)buffer[i+7] << 56;+ v.f = u.d;+ pd(ud, type , type_name, &v, f->id, f->name);+ }+ return size/8;+ case PTYPE_FLOAT:+ if (size % 4 != 0)+ return -1;+ for (i=0;i<size;i+=4) {+ union {+ float f;+ uint32_t i32;+ } u;+ u.i32 = (uint32_t)buffer[i] |+ (uint32_t)buffer[i+1] << 8 |+ (uint32_t)buffer[i+2] << 16 |+ (uint32_t)buffer[i+3] << 24;+ v.f = (double)u.f;+ pd(ud, type , type_name, &v, f->id, f->name);+ }+ return size/4;+ case PTYPE_FIXED32:+ case PTYPE_SFIXED32:+ if (size % 4 != 0)+ return -1;+ for (i=0;i<size;i+=4) {+ v.i.low = (uint32_t)buffer[i] |+ (uint32_t)buffer[i+1] << 8 |+ (uint32_t)buffer[i+2] << 16 |+ (uint32_t)buffer[i+3] << 24;+ pd(ud, type , type_name, &v, f->id, f->name);+ }+ return size/4;+ case PTYPE_FIXED64:+ case PTYPE_SFIXED64:+ if (size % 8 != 0)+ return -1;+ for (i=0;i<size;i+=8) {+ v.i.low = (uint32_t)buffer[i] |+ (uint32_t)buffer[i+1] << 8 |+ (uint32_t)buffer[i+2] << 16 |+ (uint32_t)buffer[i+3] << 24;+ v.i.hi = (uint32_t)buffer[i+4] |+ (uint32_t)buffer[i+5] << 8 |+ (uint32_t)buffer[i+6] << 16 |+ (uint32_t)buffer[i+7] << 24;+ pd(ud, type , type_name, &v, f->id, f->name);+ }+ return size/8;+ case PTYPE_INT64:+ case PTYPE_UINT64:+ case PTYPE_INT32:+ case PTYPE_UINT32:+ case PTYPE_BOOL: {+ int n = 0;+ while (size > 0) {+ int len;+ if (size >= 10) {+ len = _pbcV_decode(buffer, (struct longlong *)&(v.i));+ } else {+ uint8_t temp[10];+ memcpy(temp, buffer, size);+ len = _pbcV_decode(buffer, (struct longlong *)&(v.i));+ if (len > size)+ return -1;+ }+ pd(ud, type , type_name, &v, f->id, f->name);+ buffer += len;+ size -= len;+ ++n;+ }+ return n;+ }+ case PTYPE_ENUM: {+ int n = 0;+ while (size > 0) {+ int len;+ if (size >= 10) {+ len = _pbcV_decode(buffer, (struct longlong *)&(v.i));+ } else {+ uint8_t temp[10];+ memcpy(temp, buffer, size);+ len = _pbcV_decode(buffer, (struct longlong *)&(v.i));+ if (len > size)+ return -1;+ }+ v.e.id = v.i.low;+ v.e.name = (const char *)_pbcM_ip_query(f->type_name.e->id , v.i.low);+ pd(ud, type , type_name, &v, f->id, f->name);+ buffer += len;+ size -= len;+ ++n;+ }+ return n;+ }+ case PTYPE_SINT32: {+ int n = 0;+ while (size > 0) {+ int len;+ if (size >= 10) {+ len = _pbcV_decode(buffer, (struct longlong *)&(v.i));+ _pbcV_dezigzag32((struct longlong *)&(v.i));+ } else {+ uint8_t temp[10];+ memcpy(temp, buffer, size);+ len = _pbcV_decode(buffer, (struct longlong *)&(v.i));+ if (len > size)+ return -1;+ _pbcV_dezigzag32((struct longlong *)&(v.i));+ }+ pd(ud, type , type_name, &v, f->id, f->name);+ buffer += len;+ size -= len;+ ++n;+ }+ return n;+ }+ case PTYPE_SINT64: {+ int n = 0;+ while (size > 0) {+ int len;+ if (size >= 10) {+ len = _pbcV_decode(buffer, (struct longlong *)&(v.i));+ _pbcV_dezigzag64((struct longlong *)&(v.i));+ } else {+ uint8_t temp[10];+ memcpy(temp, buffer, size);+ len = _pbcV_decode(buffer, (struct longlong *)&(v.i));+ if (len > size)+ return -1;+ _pbcV_dezigzag64((struct longlong *)&(v.i));+ }+ pd(ud, type , type_name, &v, f->id, f->name);+ buffer += len;+ size -= len;+ ++n;+ }+ return n;+ }+ default:+ return -1;+ }+}++int+pbc_decode(struct pbc_env * env, const char * type_name , struct pbc_slice * slice, pbc_decoder pd, void *ud) {+ struct _message * msg = _pbcP_get_message(env, type_name);+ if (msg == NULL) {+ env->lasterror = "Proto not found";+ return -1;+ }+ if (slice->len == 0) {+ return 0;+ }+ pbc_ctx _ctx;+ int count = _pbcC_open(_ctx,slice->buffer,slice->len);+ if (count <= 0) {+ env->lasterror = "decode context error";+ _pbcC_close(_ctx);+ return count - 1;+ }+ struct context * ctx = (struct context *)_ctx;+ uint8_t * start = (uint8_t *)slice->buffer;++ int i;+ for (i=0;i<ctx->number;i++) {+ int id = ctx->a[i].wire_id >> 3;+ struct _field * f = (struct _field *)_pbcM_ip_query(msg->id , id);+ if (f==NULL) {+ int err = call_unknown(pd,ud,id,&ctx->a[i],start);+ if (err) {+ _pbcC_close(_ctx);+ return -i-1;+ }+ } else if (f->label == LABEL_PACKED) {+ struct atom * a = &ctx->a[i];+ int n = call_array(pd, ud, f , start + a->v.s.start , a->v.s.end - a->v.s.start);+ if (n < 0) {+ _pbcC_close(_ctx);+ return -i-1;+ }+ } else {+ if (call_type(pd,ud,f,&ctx->a[i],start) != 0) {+ _pbcC_close(_ctx);+ return -i-1;+ }+ }+ }++ _pbcC_close(_ctx);+ return ctx->number;+}+
+ cbits/descriptor.pbc.h view
@@ -0,0 +1,271 @@+static unsigned char pbc_descriptor[] = {+72,1,72,2,72,3,72,4,72,5,72,6,72,7,72,8,+72,9,72,10,72,11,72,12,72,13,72,14,72,15,72,16,+72,17,72,18,72,1,72,2,72,3,72,1,72,2,72,3,+72,0,72,1,72,2,50,42,103,111,111,103,108,101,46,112,+114,111,116,111,98,117,102,46,70,105,101,108,100,68,101,115,+99,114,105,112,116,111,114,80,114,111,116,111,46,84,121,112,+101,0,50,43,103,111,111,103,108,101,46,112,114,111,116,111,+98,117,102,46,70,105,101,108,100,68,101,115,99,114,105,112,+116,111,114,80,114,111,116,111,46,76,97,98,101,108,0,50,+41,103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,+46,70,105,108,101,79,112,116,105,111,110,115,46,79,112,116,+105,109,105,122,101,77,111,100,101,0,50,35,103,111,111,103,+108,101,46,112,114,111,116,111,98,117,102,46,70,105,101,108,+100,79,112,116,105,111,110,115,46,67,84,121,112,101,0,66,+12,84,89,80,69,95,68,79,85,66,76,69,0,66,11,84,+89,80,69,95,70,76,79,65,84,0,66,11,84,89,80,69,+95,73,78,84,54,52,0,66,12,84,89,80,69,95,85,73,+78,84,54,52,0,66,11,84,89,80,69,95,73,78,84,51,+50,0,66,13,84,89,80,69,95,70,73,88,69,68,54,52,+0,66,13,84,89,80,69,95,70,73,88,69,68,51,50,0,+66,10,84,89,80,69,95,66,79,79,76,0,66,12,84,89,+80,69,95,83,84,82,73,78,71,0,66,11,84,89,80,69,+95,71,82,79,85,80,0,66,13,84,89,80,69,95,77,69,+83,83,65,71,69,0,66,11,84,89,80,69,95,66,89,84,+69,83,0,66,12,84,89,80,69,95,85,73,78,84,51,50,+0,66,10,84,89,80,69,95,69,78,85,77,0,66,14,84,+89,80,69,95,83,70,73,88,69,68,51,50,0,66,14,84,+89,80,69,95,83,70,73,88,69,68,54,52,0,66,12,84,+89,80,69,95,83,73,78,84,51,50,0,66,12,84,89,80,+69,95,83,73,78,84,54,52,0,66,15,76,65,66,69,76,+95,79,80,84,73,79,78,65,76,0,66,15,76,65,66,69,+76,95,82,69,81,85,73,82,69,68,0,66,15,76,65,66,+69,76,95,82,69,80,69,65,84,69,68,0,66,6,83,80,+69,69,68,0,66,10,67,79,68,69,95,83,73,90,69,0,+66,13,76,73,84,69,95,82,85,78,84,73,77,69,0,66,+7,83,84,82,73,78,71,0,66,5,67,79,82,68,0,66,+13,83,84,82,73,78,71,95,80,73,69,67,69,0,56,18,+56,3,56,3,56,3,10,11,100,101,115,99,114,105,112,116,+111,114,0,32,1,32,9,32,7,32,2,32,8,32,3,32,+3,32,3,32,4,32,9,32,3,32,5,32,1,32,1,32,+1,32,1,32,7,32,2,32,1,32,2,42,51,24,2,16,+1,32,11,42,36,103,111,111,103,108,101,46,112,114,111,116,+111,98,117,102,46,70,105,108,101,68,101,115,99,114,105,112,+116,111,114,80,114,111,116,111,0,10,5,102,105,108,101,0,+42,13,32,9,24,0,10,5,110,97,109,101,0,16,1,42,+16,32,9,24,0,10,8,112,97,99,107,97,103,101,0,16,+2,42,19,32,9,24,2,10,11,100,101,112,101,110,100,101,+110,99,121,0,16,3,42,55,24,2,16,4,32,11,42,32,+103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46,+68,101,115,99,114,105,112,116,111,114,80,114,111,116,111,0,+10,13,109,101,115,115,97,103,101,95,116,121,112,101,0,42,+56,24,2,16,5,32,11,42,36,103,111,111,103,108,101,46,+112,114,111,116,111,98,117,102,46,69,110,117,109,68,101,115,+99,114,105,112,116,111,114,80,114,111,116,111,0,10,10,101,+110,117,109,95,116,121,112,101,0,42,57,24,2,16,6,32,+11,42,39,103,111,111,103,108,101,46,112,114,111,116,111,98,+117,102,46,83,101,114,118,105,99,101,68,101,115,99,114,105,+112,116,111,114,80,114,111,116,111,0,10,8,115,101,114,118,+105,99,101,0,42,57,24,2,16,7,32,11,42,37,103,111,+111,103,108,101,46,112,114,111,116,111,98,117,102,46,70,105,+101,108,100,68,101,115,99,114,105,112,116,111,114,80,114,111,+116,111,0,10,10,101,120,116,101,110,115,105,111,110,0,42,+46,24,0,16,8,32,11,42,28,103,111,111,103,108,101,46,+112,114,111,116,111,98,117,102,46,70,105,108,101,79,112,116,+105,111,110,115,0,10,8,111,112,116,105,111,110,115,0,42,+58,24,0,16,9,32,11,42,31,103,111,111,103,108,101,46,+112,114,111,116,111,98,117,102,46,83,111,117,114,99,101,67,+111,100,101,73,110,102,111,0,10,17,115,111,117,114,99,101,+95,99,111,100,101,95,105,110,102,111,0,42,13,32,9,24,+0,10,5,110,97,109,101,0,16,1,42,53,24,2,16,2,+32,11,42,37,103,111,111,103,108,101,46,112,114,111,116,111,+98,117,102,46,70,105,101,108,100,68,101,115,99,114,105,112,+116,111,114,80,114,111,116,111,0,10,6,102,105,101,108,100,+0,42,57,24,2,16,6,32,11,42,37,103,111,111,103,108,+101,46,112,114,111,116,111,98,117,102,46,70,105,101,108,100,+68,101,115,99,114,105,112,116,111,114,80,114,111,116,111,0,+10,10,101,120,116,101,110,115,105,111,110,0,42,54,24,2,+16,3,32,11,42,32,103,111,111,103,108,101,46,112,114,111,+116,111,98,117,102,46,68,101,115,99,114,105,112,116,111,114,+80,114,111,116,111,0,10,12,110,101,115,116,101,100,95,116,+121,112,101,0,42,56,24,2,16,4,32,11,42,36,103,111,+111,103,108,101,46,112,114,111,116,111,98,117,102,46,69,110,+117,109,68,101,115,99,114,105,112,116,111,114,80,114,111,116,+111,0,10,10,101,110,117,109,95,116,121,112,101,0,42,73,+24,2,16,5,32,11,42,47,103,111,111,103,108,101,46,112,+114,111,116,111,98,117,102,46,68,101,115,99,114,105,112,116,+111,114,80,114,111,116,111,46,69,120,116,101,110,115,105,111,+110,82,97,110,103,101,0,10,16,101,120,116,101,110,115,105,+111,110,95,114,97,110,103,101,0,42,49,24,0,16,7,32,+11,42,31,103,111,111,103,108,101,46,112,114,111,116,111,98,+117,102,46,77,101,115,115,97,103,101,79,112,116,105,111,110,+115,0,10,8,111,112,116,105,111,110,115,0,42,14,32,5,+24,0,10,6,115,116,97,114,116,0,16,1,42,12,32,5,+24,0,10,4,101,110,100,0,16,2,42,13,32,9,24,0,+10,5,110,97,109,101,0,16,1,42,15,32,5,24,0,10,+7,110,117,109,98,101,114,0,16,3,42,59,24,0,16,4,+32,14,42,43,103,111,111,103,108,101,46,112,114,111,116,111,+98,117,102,46,70,105,101,108,100,68,101,115,99,114,105,112,+116,111,114,80,114,111,116,111,46,76,97,98,101,108,0,10,+6,108,97,98,101,108,0,42,57,24,0,16,5,32,14,42,+42,103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,+46,70,105,101,108,100,68,101,115,99,114,105,112,116,111,114,+80,114,111,116,111,46,84,121,112,101,0,10,5,116,121,112,+101,0,42,18,32,9,24,0,10,10,116,121,112,101,95,110,+97,109,101,0,16,6,42,17,32,9,24,0,10,9,101,120,+116,101,110,100,101,101,0,16,2,42,22,32,9,24,0,10,+14,100,101,102,97,117,108,116,95,118,97,108,117,101,0,16,+7,42,47,24,0,16,8,32,11,42,29,103,111,111,103,108,+101,46,112,114,111,116,111,98,117,102,46,70,105,101,108,100,+79,112,116,105,111,110,115,0,10,8,111,112,116,105,111,110,+115,0,42,13,32,9,24,0,10,5,110,97,109,101,0,16,+1,42,57,24,2,16,2,32,11,42,41,103,111,111,103,108,+101,46,112,114,111,116,111,98,117,102,46,69,110,117,109,86,+97,108,117,101,68,101,115,99,114,105,112,116,111,114,80,114,+111,116,111,0,10,6,118,97,108,117,101,0,42,46,24,0,+16,3,32,11,42,28,103,111,111,103,108,101,46,112,114,111,+116,111,98,117,102,46,69,110,117,109,79,112,116,105,111,110,+115,0,10,8,111,112,116,105,111,110,115,0,42,13,32,9,+24,0,10,5,110,97,109,101,0,16,1,42,15,32,5,24,+0,10,7,110,117,109,98,101,114,0,16,2,42,51,24,0,+16,3,32,11,42,33,103,111,111,103,108,101,46,112,114,111,+116,111,98,117,102,46,69,110,117,109,86,97,108,117,101,79,+112,116,105,111,110,115,0,10,8,111,112,116,105,111,110,115,+0,42,13,32,9,24,0,10,5,110,97,109,101,0,16,1,+42,55,24,2,16,2,32,11,42,38,103,111,111,103,108,101,+46,112,114,111,116,111,98,117,102,46,77,101,116,104,111,100,+68,101,115,99,114,105,112,116,111,114,80,114,111,116,111,0,+10,7,109,101,116,104,111,100,0,42,49,24,0,16,3,32,+11,42,31,103,111,111,103,108,101,46,112,114,111,116,111,98,+117,102,46,83,101,114,118,105,99,101,79,112,116,105,111,110,+115,0,10,8,111,112,116,105,111,110,115,0,42,13,32,9,+24,0,10,5,110,97,109,101,0,16,1,42,19,32,9,24,+0,10,11,105,110,112,117,116,95,116,121,112,101,0,16,2,+42,20,32,9,24,0,10,12,111,117,116,112,117,116,95,116,+121,112,101,0,16,3,42,48,24,0,16,4,32,11,42,30,+103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46,+77,101,116,104,111,100,79,112,116,105,111,110,115,0,10,8,+111,112,116,105,111,110,115,0,42,21,32,9,24,0,10,13,+106,97,118,97,95,112,97,99,107,97,103,101,0,16,1,42,+29,32,9,24,0,10,21,106,97,118,97,95,111,117,116,101,+114,95,99,108,97,115,115,110,97,109,101,0,16,8,42,30,+24,0,16,10,32,8,10,20,106,97,118,97,95,109,117,108,+116,105,112,108,101,95,102,105,108,101,115,0,48,0,42,40,+24,0,16,20,32,8,10,30,106,97,118,97,95,103,101,110,+101,114,97,116,101,95,101,113,117,97,108,115,95,97,110,100,+95,104,97,115,104,0,48,0,42,72,24,0,16,9,32,14,+42,41,103,111,111,103,108,101,46,112,114,111,116,111,98,117,+102,46,70,105,108,101,79,112,116,105,111,110,115,46,79,112,+116,105,109,105,122,101,77,111,100,101,0,10,13,111,112,116,+105,109,105,122,101,95,102,111,114,0,58,6,83,80,69,69,+68,0,42,30,24,0,16,16,32,8,10,20,99,99,95,103,+101,110,101,114,105,99,95,115,101,114,118,105,99,101,115,0,+48,0,42,32,24,0,16,17,32,8,10,22,106,97,118,97,+95,103,101,110,101,114,105,99,95,115,101,114,118,105,99,101,+115,0,48,0,42,30,24,0,16,18,32,8,10,20,112,121,+95,103,101,110,101,114,105,99,95,115,101,114,118,105,99,101,+115,0,48,0,42,68,24,2,16,231,7,32,11,42,36,103,+111,111,103,108,101,46,112,114,111,116,111,98,117,102,46,85,+110,105,110,116,101,114,112,114,101,116,101,100,79,112,116,105,+111,110,0,10,21,117,110,105,110,116,101,114,112,114,101,116,+101,100,95,111,112,116,105,111,110,0,42,34,24,0,16,1,+32,8,10,24,109,101,115,115,97,103,101,95,115,101,116,95,+119,105,114,101,95,102,111,114,109,97,116,0,48,0,42,42,+24,0,16,2,32,8,10,32,110,111,95,115,116,97,110,100,+97,114,100,95,100,101,115,99,114,105,112,116,111,114,95,97,+99,99,101,115,115,111,114,0,48,0,42,68,24,2,16,231,+7,32,11,42,36,103,111,111,103,108,101,46,112,114,111,116,+111,98,117,102,46,85,110,105,110,116,101,114,112,114,101,116,+101,100,79,112,116,105,111,110,0,10,21,117,110,105,110,116,+101,114,112,114,101,116,101,100,95,111,112,116,105,111,110,0,+42,60,24,0,16,1,32,14,42,35,103,111,111,103,108,101,+46,112,114,111,116,111,98,117,102,46,70,105,101,108,100,79,+112,116,105,111,110,115,46,67,84,121,112,101,0,10,6,99,+116,121,112,101,0,58,7,83,84,82,73,78,71,0,42,15,+32,8,24,0,10,7,112,97,99,107,101,100,0,16,2,42,+21,24,0,16,3,32,8,10,11,100,101,112,114,101,99,97,+116,101,100,0,48,0,42,29,32,9,24,0,10,21,101,120,+112,101,114,105,109,101,110,116,97,108,95,109,97,112,95,107,+101,121,0,16,9,42,68,24,2,16,231,7,32,11,42,36,+103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46,+85,110,105,110,116,101,114,112,114,101,116,101,100,79,112,116,+105,111,110,0,10,21,117,110,105,110,116,101,114,112,114,101,+116,101,100,95,111,112,116,105,111,110,0,42,68,24,2,16,+231,7,32,11,42,36,103,111,111,103,108,101,46,112,114,111,+116,111,98,117,102,46,85,110,105,110,116,101,114,112,114,101,+116,101,100,79,112,116,105,111,110,0,10,21,117,110,105,110,+116,101,114,112,114,101,116,101,100,95,111,112,116,105,111,110,+0,42,68,24,2,16,231,7,32,11,42,36,103,111,111,103,+108,101,46,112,114,111,116,111,98,117,102,46,85,110,105,110,+116,101,114,112,114,101,116,101,100,79,112,116,105,111,110,0,+10,21,117,110,105,110,116,101,114,112,114,101,116,101,100,95,+111,112,116,105,111,110,0,42,68,24,2,16,231,7,32,11,+42,36,103,111,111,103,108,101,46,112,114,111,116,111,98,117,+102,46,85,110,105,110,116,101,114,112,114,101,116,101,100,79,+112,116,105,111,110,0,10,21,117,110,105,110,116,101,114,112,+114,101,116,101,100,95,111,112,116,105,111,110,0,42,68,24,+2,16,231,7,32,11,42,36,103,111,111,103,108,101,46,112,+114,111,116,111,98,117,102,46,85,110,105,110,116,101,114,112,+114,101,116,101,100,79,112,116,105,111,110,0,10,21,117,110,+105,110,116,101,114,112,114,101,116,101,100,95,111,112,116,105,+111,110,0,42,60,24,2,16,2,32,11,42,45,103,111,111,+103,108,101,46,112,114,111,116,111,98,117,102,46,85,110,105,+110,116,101,114,112,114,101,116,101,100,79,112,116,105,111,110,+46,78,97,109,101,80,97,114,116,0,10,5,110,97,109,101,+0,42,25,32,9,24,0,10,17,105,100,101,110,116,105,102,+105,101,114,95,118,97,108,117,101,0,16,3,42,27,32,4,+24,0,10,19,112,111,115,105,116,105,118,101,95,105,110,116,+95,118,97,108,117,101,0,16,4,42,27,32,3,24,0,10,+19,110,101,103,97,116,105,118,101,95,105,110,116,95,118,97,+108,117,101,0,16,5,42,21,32,1,24,0,10,13,100,111,+117,98,108,101,95,118,97,108,117,101,0,16,6,42,21,32,+12,24,0,10,13,115,116,114,105,110,103,95,118,97,108,117,+101,0,16,7,42,24,32,9,24,0,10,16,97,103,103,114,+101,103,97,116,101,95,118,97,108,117,101,0,16,8,42,18,+32,9,24,1,10,10,110,97,109,101,95,112,97,114,116,0,+16,1,42,21,32,8,24,1,10,13,105,115,95,101,120,116,+101,110,115,105,111,110,0,16,2,42,59,24,2,16,1,32,+11,42,40,103,111,111,103,108,101,46,112,114,111,116,111,98,+117,102,46,83,111,117,114,99,101,67,111,100,101,73,110,102,+111,46,76,111,99,97,116,105,111,110,0,10,9,108,111,99,+97,116,105,111,110,0,42,13,32,5,24,2,10,5,112,97,+116,104,0,16,1,42,13,32,5,24,2,10,5,115,112,97,+110,0,16,2,26,34,103,111,111,103,108,101,46,112,114,111,+116,111,98,117,102,46,70,105,108,101,68,101,115,99,114,105,+112,116,111,114,83,101,116,0,26,36,103,111,111,103,108,101,+46,112,114,111,116,111,98,117,102,46,70,105,108,101,68,101,+115,99,114,105,112,116,111,114,80,114,111,116,111,0,26,32,+103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46,+68,101,115,99,114,105,112,116,111,114,80,114,111,116,111,0,+26,47,103,111,111,103,108,101,46,112,114,111,116,111,98,117,+102,46,68,101,115,99,114,105,112,116,111,114,80,114,111,116,+111,46,69,120,116,101,110,115,105,111,110,82,97,110,103,101,+0,26,37,103,111,111,103,108,101,46,112,114,111,116,111,98,+117,102,46,70,105,101,108,100,68,101,115,99,114,105,112,116,+111,114,80,114,111,116,111,0,26,36,103,111,111,103,108,101,+46,112,114,111,116,111,98,117,102,46,69,110,117,109,68,101,+115,99,114,105,112,116,111,114,80,114,111,116,111,0,26,41,+103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46,+69,110,117,109,86,97,108,117,101,68,101,115,99,114,105,112,+116,111,114,80,114,111,116,111,0,26,39,103,111,111,103,108,+101,46,112,114,111,116,111,98,117,102,46,83,101,114,118,105,+99,101,68,101,115,99,114,105,112,116,111,114,80,114,111,116,+111,0,26,38,103,111,111,103,108,101,46,112,114,111,116,111,+98,117,102,46,77,101,116,104,111,100,68,101,115,99,114,105,+112,116,111,114,80,114,111,116,111,0,26,28,103,111,111,103,+108,101,46,112,114,111,116,111,98,117,102,46,70,105,108,101,+79,112,116,105,111,110,115,0,26,31,103,111,111,103,108,101,+46,112,114,111,116,111,98,117,102,46,77,101,115,115,97,103,+101,79,112,116,105,111,110,115,0,26,29,103,111,111,103,108,+101,46,112,114,111,116,111,98,117,102,46,70,105,101,108,100,+79,112,116,105,111,110,115,0,26,28,103,111,111,103,108,101,+46,112,114,111,116,111,98,117,102,46,69,110,117,109,79,112,+116,105,111,110,115,0,26,33,103,111,111,103,108,101,46,112,+114,111,116,111,98,117,102,46,69,110,117,109,86,97,108,117,+101,79,112,116,105,111,110,115,0,26,31,103,111,111,103,108,+101,46,112,114,111,116,111,98,117,102,46,83,101,114,118,105,+99,101,79,112,116,105,111,110,115,0,26,30,103,111,111,103,+108,101,46,112,114,111,116,111,98,117,102,46,77,101,116,104,+111,100,79,112,116,105,111,110,115,0,26,36,103,111,111,103,+108,101,46,112,114,111,116,111,98,117,102,46,85,110,105,110,+116,101,114,112,114,101,116,101,100,79,112,116,105,111,110,0,+26,45,103,111,111,103,108,101,46,112,114,111,116,111,98,117,+102,46,85,110,105,110,116,101,114,112,114,101,116,101,100,79,+112,116,105,111,110,46,78,97,109,101,80,97,114,116,0,26,+31,103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,+46,83,111,117,114,99,101,67,111,100,101,73,110,102,111,0,+26,40,103,111,111,103,108,101,46,112,114,111,116,111,98,117,+102,46,83,111,117,114,99,101,67,111,100,101,73,110,102,111,+46,76,111,99,97,116,105,111,110,0,+};
+ cbits/map.c view
@@ -0,0 +1,477 @@+#include "map.h"+#include "alloc.h"++#include <stdlib.h>+#include <string.h>++struct _pbcM_ip_slot {+ int id;+ void * pointer;+ int next;+};++struct map_ip {+ size_t array_size;+ void ** array;+ size_t hash_size;+ struct _pbcM_ip_slot * slot;+};++struct _pbcM_si_slot {+ const char *key;+ size_t hash;+ int id;+ int next;+};++struct map_si {+ size_t size;+ struct _pbcM_si_slot slot[1];+};++static size_t+calc_hash(const char *name)+{+ size_t len = strlen(name);+ size_t h = len;+ size_t step = (len>>5)+1;+ size_t i;+ for (i=len; i>=step; i-=step)+ h = h ^ ((h<<5)+(h>>2)+(size_t)name[i-1]);+ return h;+}++struct map_si *+_pbcM_si_new(struct map_kv * table, int size)+{+ size_t sz = sizeof(struct map_si) + (size-1) * sizeof(struct _pbcM_si_slot);+ struct map_si * ret = (struct map_si *)malloc(sz);+ memset(ret,0,sz);++ ret->size = (size_t)size;++ int empty = 0;+ int i;++ for (i=0;i<size;i++) {+ size_t hash_full = calc_hash((const char *)table[i].pointer);+ size_t hash = hash_full % size;+ struct _pbcM_si_slot * slot = &ret->slot[hash];+ if (slot->key == NULL) {+ slot->key = (const char *)table[i].pointer;+ slot->id = table[i].id;+ slot->hash = hash_full;+ } else {+ while(ret->slot[empty].key != NULL) {+ ++empty;+ }+ struct _pbcM_si_slot * empty_slot = &ret->slot[empty];+ empty_slot->next = slot->next;+ slot->next = empty + 1;+ empty_slot->id = table[i].id;+ empty_slot->key = (const char *)table[i].pointer;+ empty_slot->hash = hash_full;+ }+ }++ return ret;+}++void +_pbcM_si_delete(struct map_si *map)+{+ free(map);+}++int+_pbcM_si_query(struct map_si *map, const char *key, int *result) +{+ size_t hash_full = calc_hash(key);+ size_t hash = hash_full % map->size;++ struct _pbcM_si_slot * slot = &map->slot[hash];+ for (;;) {+ if (slot->hash == hash_full && strcmp(slot->key, key) == 0) {+ *result = slot->id;+ return 0;+ }+ if (slot->next == 0) {+ return 1;+ }+ slot = &map->slot[slot->next-1];+ }+}++static struct map_ip *+_pbcM_ip_new_hash(struct map_kv * table, int size)+{+ struct map_ip * ret = (struct map_ip *)malloc(sizeof(struct map_ip));+ ret->array = NULL;+ ret->array_size = 0;+ ret->hash_size = (size_t)size;+ ret->slot = (struct _pbcM_ip_slot *)malloc(sizeof(struct _pbcM_ip_slot) * size);+ memset(ret->slot,0,sizeof(struct _pbcM_ip_slot) * size);+ int empty = 0;+ int i;+ for (i=0;i<size;i++) {+ int hash = ((unsigned)table[i].id) % size;+ struct _pbcM_ip_slot * slot = &ret->slot[hash];+ if (slot->pointer == NULL) {+ slot->pointer = table[i].pointer;+ slot->id = table[i].id;+ } else {+ while(ret->slot[empty].pointer != NULL) {+ ++empty;+ }+ struct _pbcM_ip_slot * empty_slot = &ret->slot[empty];+ empty_slot->next = slot->next;+ slot->next = empty + 1;+ empty_slot->id = table[i].id;+ empty_slot->pointer = table[i].pointer;+ }+ }+ return ret;+}++struct map_ip *+_pbcM_ip_new(struct map_kv * table, int size)+{+ int i;+ int max = table[0].id;+ if (max > size * 2 || max < 0)+ return _pbcM_ip_new_hash(table,size);+ for (i=1;i<size;i++) {+ if (table[i].id < 0) {+ return _pbcM_ip_new_hash(table,size);+ }+ if (table[i].id > max) {+ max = table[i].id;+ if (max > size * 2)+ return _pbcM_ip_new_hash(table,size);+ }+ }+ struct map_ip * ret = (struct map_ip *)malloc(sizeof(struct map_ip));+ ret->hash_size = size;+ ret->slot = NULL;+ ret->array_size = max + 1;+ ret->array = (void **)malloc((max+1) * sizeof(void *));+ memset(ret->array,0,(max+1) * sizeof(void *));+ for (i=0;i<size;i++) {+ ret->array[table[i].id] = table[i].pointer;+ }+ return ret;+}++void+_pbcM_ip_delete(struct map_ip * map)+{+ if (map) {+ free(map->array);+ free(map->slot);+ free(map);+ }+}++static void+_inject(struct map_kv * table, struct map_ip *map)+{+ if (map->array) {+ int n = 0;+ int i;+ for (i=0;i<(int)map->array_size;i++) {+ if (map->array[i]) {+ table[n].id = i;+ table[n].pointer = map->array[i];+ ++ n;+ }+ }+ } else {+ int i;+ for (i=0;i<(int)map->hash_size;i++) {+ table[i].id = map->slot[i].id;+ table[i].pointer = map->slot[i].pointer;+ }+ }+}++struct map_ip *+_pbcM_ip_combine(struct map_ip *a, struct map_ip *b)+{+ int sz = (int)(a->hash_size + b->hash_size);+ struct map_kv * table = (struct map_kv *)malloc(sz * sizeof(struct map_kv));+ memset(table , 0 , sz * sizeof(struct map_kv));+ _inject(table, a);+ _inject(table + a->hash_size, b);+ struct map_ip * r = _pbcM_ip_new(table, sz);+ free(table);+ return r;+}++void *+_pbcM_ip_query(struct map_ip * map, int id)+{+ if (map == NULL)+ return NULL;+ if (map->array) {+ if (id>=0 && id<(int)map->array_size)+ return map->array[id];+ return NULL;+ }+ int hash = (unsigned)id % map->hash_size;+ struct _pbcM_ip_slot * slot = &map->slot[hash];+ for (;;) {+ if (slot->id == id) {+ return slot->pointer;+ }+ if (slot->next == 0) {+ return NULL;+ }+ slot = &map->slot[slot->next-1];+ }+}++struct _pbcM_sp_slot {+ const char *key;+ size_t hash;+ void *pointer;+ int next;+};++struct map_sp {+ size_t cap;+ size_t size;+ struct heap *heap;+ struct _pbcM_sp_slot * slot;+};++struct map_sp *+_pbcM_sp_new(int max , struct heap *h)+{+ struct map_sp * ret = (struct map_sp *)HMALLOC(sizeof(struct map_sp));+ int cap = 1;+ while (cap < max) {+ cap *=2;+ }+ ret->cap = cap;+ ret->size = 0;+ ret->slot = (struct _pbcM_sp_slot *)HMALLOC(ret->cap * sizeof(struct _pbcM_sp_slot));+ memset(ret->slot,0,sizeof(struct _pbcM_sp_slot) * ret->cap);+ ret->heap = h;+ return ret;+}++void+_pbcM_sp_delete(struct map_sp *map)+{+ if (map && map->heap == NULL) {+ _pbcM_free(map->slot);+ _pbcM_free(map);+ }+}++static void _pbcM_sp_rehash(struct map_sp *map);++static void+_pbcM_sp_insert_hash(struct map_sp *map, const char *key, size_t hash_full, void * value)+{+ if (map->cap > map->size) {+ size_t hash = hash_full & (map->cap-1);+ struct _pbcM_sp_slot * slot = &map->slot[hash];+ if (slot->key == NULL) {+ slot->key = key;+ slot->pointer = value;+ slot->hash = hash_full;+ } else {+ int empty = (hash + 1) & (map->cap-1);+ while(map->slot[empty].key != NULL) {+ empty = (empty + 1) & (map->cap-1);+ }+ struct _pbcM_sp_slot * empty_slot = &map->slot[empty];+ empty_slot->next = slot->next;+ slot->next = empty + 1;+ empty_slot->pointer = value;+ empty_slot->key = key;+ empty_slot->hash = hash_full;+ }+ map->size++;+ return;+ }+ _pbcM_sp_rehash(map);+ _pbcM_sp_insert_hash(map, key, hash_full, value);+}++static void+_pbcM_sp_rehash(struct map_sp *map) {+ struct heap * h = map->heap;+ struct _pbcM_sp_slot * old_slot = map->slot;+ size_t size = map->size;+ map->size = 0;+ map->cap *= 2;+ map->slot = (struct _pbcM_sp_slot *)HMALLOC(sizeof(struct _pbcM_sp_slot)*map->cap);+ memset(map->slot,0,sizeof(struct _pbcM_sp_slot)*map->cap);+ size_t i;+ for (i=0;i<size;i++) {+ _pbcM_sp_insert_hash(map, old_slot[i].key, old_slot[i].hash, old_slot[i].pointer);+ }+ if (h == NULL) {+ _pbcM_free(old_slot);+ }+}++static void **+_pbcM_sp_query_insert_hash(struct map_sp *map, const char *key, size_t hash_full)+{+ size_t hash = hash_full & (map->cap-1);+ struct _pbcM_sp_slot * slot = &map->slot[hash];+ if (slot->key == NULL) {+ if (map->cap <= map->size) + goto _rehash;+ slot->key = key;+ slot->hash = hash_full;+ map->size++;+ return &(slot->pointer);+ } else {+ for (;;) {+ if (slot->hash == hash_full && strcmp(slot->key, key) == 0) + return &(slot->pointer);+ if (slot->next == 0) {+ break;+ }+ slot = &map->slot[slot->next-1];+ }+ if (map->cap <= map->size) + goto _rehash;++ int empty = (hash + 1) & (map->cap-1);+ while(map->slot[empty].key != NULL) {+ empty = (empty + 1) & (map->cap-1);+ }+ struct _pbcM_sp_slot * empty_slot = &map->slot[empty];+ empty_slot->next = slot->next;+ slot->next = empty + 1;+ empty_slot->key = key;+ empty_slot->hash = hash_full;++ map->size++;++ return &(empty_slot->pointer);+ }+_rehash:+ _pbcM_sp_rehash(map);+ return _pbcM_sp_query_insert_hash(map, key, hash_full);+}++void+_pbcM_sp_insert(struct map_sp *map, const char *key, void * value)+{+ _pbcM_sp_insert_hash(map,key,calc_hash(key),value);+}++void **+_pbcM_sp_query_insert(struct map_sp *map, const char *key)+{+ return _pbcM_sp_query_insert_hash(map,key,calc_hash(key));+}++void *+_pbcM_sp_query(struct map_sp *map, const char *key)+{+ if (map == NULL)+ return NULL;+ size_t hash_full = calc_hash(key);+ size_t hash = hash_full & (map->cap -1);++ struct _pbcM_sp_slot * slot = &map->slot[hash];+ for (;;) {+ if (slot->hash == hash_full && strcmp(slot->key, key) == 0) {+ return slot->pointer;+ }+ if (slot->next == 0) {+ return NULL;+ }+ slot = &map->slot[slot->next-1];+ }+}++void +_pbcM_sp_foreach(struct map_sp *map, void (*func)(void *p))+{+ size_t i;+ for (i=0;i<map->cap;i++) {+ if (map->slot[i].pointer) {+ func(map->slot[i].pointer);+ }+ }+}++void +_pbcM_sp_foreach_ud(struct map_sp *map, void (*func)(void *p, void *ud), void *ud)+{+ size_t i;+ for (i=0;i<map->cap;i++) {+ if (map->slot[i].pointer) {+ func(map->slot[i].pointer,ud);+ }+ }+}++static int+_find_first(struct map_sp *map)+{+ size_t i;+ for (i=0;i<map->cap;i++) {+ if (map->slot[i].pointer) {+ return i;+ }+ }+ return -1;+}++static int+_find_next(struct map_sp *map, const char *key)+{+ size_t hash_full = calc_hash(key);+ size_t hash = hash_full & (map->cap -1);++ struct _pbcM_sp_slot * slot = &map->slot[hash];+ for (;;) {+ if (slot->hash == hash_full && strcmp(slot->key, key) == 0) {+ int i = slot - map->slot + 1;+ while(i<map->cap) {+ if (map->slot[i].pointer) {+ return i;+ }+ ++i;+ }+ return -1;+ }+ if (slot->next == 0) {+ return -1;+ }+ slot = &map->slot[slot->next-1];+ }+}++void * +_pbcM_sp_next(struct map_sp *map, const char ** key)+{+ if (map == NULL) {+ *key = NULL;+ return NULL;+ }+ int idx;+ if (*key == NULL) {+ idx = _find_first(map);+ } else {+ idx = _find_next(map, *key);+ }+ if (idx < 0) {+ *key = NULL;+ return NULL;+ }+ *key = map->slot[idx].key;+ return map->slot[idx].pointer;+}+++
+ cbits/map.h view
@@ -0,0 +1,33 @@+#ifndef PROTOBUF_C_MAP_H+#define PROTOBUF_C_MAP_H++#include "alloc.h"++struct map_ip;+struct map_si;+struct map_sp;++struct map_kv {+ int id;+ void *pointer;+};++struct map_si * _pbcM_si_new(struct map_kv * table, int size);+int _pbcM_si_query(struct map_si *map, const char *key, int *result);+void _pbcM_si_delete(struct map_si *map);++struct map_ip * _pbcM_ip_new(struct map_kv * table, int size);+struct map_ip * _pbcM_ip_combine(struct map_ip * a, struct map_ip * b);+void * _pbcM_ip_query(struct map_ip * map, int id);+void _pbcM_ip_delete(struct map_ip *map);++struct map_sp * _pbcM_sp_new(int max, struct heap *h);+void _pbcM_sp_insert(struct map_sp *map, const char *key, void * value);+void * _pbcM_sp_query(struct map_sp *map, const char *key);+void ** _pbcM_sp_query_insert(struct map_sp *map, const char *key);+void _pbcM_sp_delete(struct map_sp *map);+void _pbcM_sp_foreach(struct map_sp *map, void (*func)(void *p));+void _pbcM_sp_foreach_ud(struct map_sp *map, void (*func)(void *p, void *ud), void *ud);+void * _pbcM_sp_next(struct map_sp *map, const char ** key);++#endif
+ cbits/pattern.c view
@@ -0,0 +1,1130 @@+#include "alloc.h"+#include "context.h"+#include "varint.h"+#include "pattern.h"+#include "array.h"+#include "proto.h"+#include "map.h"++#include <stdint.h>+#ifndef _MSC_VER+#include <stdbool.h>+#endif+#include <stdlib.h>+#include <stddef.h>+#include <string.h>+#include <stdarg.h>++static void+set_default_v(void * output, int ctype, pbc_var defv) {+ switch (ctype) {+ case CTYPE_INT32:+ *(uint32_t *)output = defv->integer.low;+ break;+ case CTYPE_INT64:+ *(uint64_t *)output = (uint64_t)defv->integer.low | (uint64_t)defv->integer.hi << 32;+ break;+ case CTYPE_DOUBLE:+ *(double *)output = defv->real;+ break;+ case CTYPE_FLOAT:+ *(float *)output = (float)defv->real;+ break;+ case CTYPE_BOOL:+ *(bool *)output = (defv->integer.low != 0);+ break;+ case CTYPE_INT8:+ *(uint8_t *)output = (uint8_t)defv->integer.low;+ break;+ case CTYPE_INT16:+ *(uint16_t *)output = (uint16_t)defv->integer.low;+ break;+ case CTYPE_VAR:+ *(union _pbc_var *)output = *defv;+ break;+ }+}++static void+_pattern_set_default(struct _pattern_field *field, char *output) {+ if (field->ctype == CTYPE_ARRAY || field->ctype == CTYPE_PACKED) {+ struct _pbc_array *array = (struct _pbc_array *)(output + field->offset);+ _pbcA_open(array);+ } else if (field->ptype == PTYPE_ENUM) {+ pbc_var defv;+ defv->integer.low = field->defv->e.id;+ defv->integer.hi = 0;+ set_default_v(output + field->offset, field->ctype, defv);+ }+ set_default_v(output + field->offset, field->ctype, field->defv);+}++void+pbc_pattern_set_default(struct pbc_pattern *pat, void *output) {+ int i;+ for (i=0;i<pat->count;i++) {+ _pattern_set_default(&pat->f[i], (char *)output);+ }+}++// pattern unpack++static struct _pattern_field *+bsearch_pattern(struct pbc_pattern *pat, int id)+{+ int begin = 0;+ int end = pat->count;+ while (begin < end) {+ int mid = (begin + end)/2;+ struct _pattern_field * f = &pat->f[mid];+ if (id == f->id) {+ return f;+ }+ if (id < f->id) {+ end = mid;+ } else {+ begin = mid + 1;+ }+ }+ return NULL;+}++static inline int+write_real(int ctype, double v, void *out) {+ switch(ctype) {+ case CTYPE_DOUBLE:+ *(double *)out = v;+ return 0;+ case CTYPE_FLOAT:+ *(float *)out = (float)v;+ return 0;+ case CTYPE_VAR:+ ((union _pbc_var *)out)->real = v;+ return 0;+ }+ return -1;+}++static inline int+write_longlong(int ctype, struct longlong *i, void *out) {+ switch(ctype) {+ case CTYPE_INT32:+ *(uint32_t *)out = i->low;+ return 0;+ case CTYPE_INT64:+ *(uint64_t *)out = (uint64_t)i->low | (uint64_t)i->hi << 32;+ return 0;+ case CTYPE_BOOL:+ *(bool *)out = (i->low !=0) ;+ return 0;+ case CTYPE_INT8:+ *(uint8_t *)out = (uint8_t)i->low;+ return 0;+ case CTYPE_INT16:+ *(uint8_t *)out = (uint16_t)i->low;+ return 0;+ case CTYPE_VAR:+ ((union _pbc_var *)out)->integer = *i;+ return 0;+ }+ return -1;+}++static inline int+write_integer(int ctype, struct atom *a, void *out) {+ return write_longlong(ctype, &(a->v.i), out);+}++static int unpack_array(int ptype, char *buffer, struct atom *, pbc_array _array);++int+_pbcP_unpack_packed(uint8_t *buffer, int size, int ptype, pbc_array array) {+ pbc_var var;+ var->integer.hi = 0;+ int i;+ switch(ptype) {+ case PTYPE_DOUBLE:+ if (size % 8 != 0)+ return -1;+ for (i=0;i<size;i+=8) {+ union {+ double d;+ uint64_t i64;+ } u;+ u.i64 = (uint64_t)buffer[i] |+ (uint64_t)buffer[i+1] << 8 |+ (uint64_t)buffer[i+2] << 16 |+ (uint64_t)buffer[i+3] << 24 |+ (uint64_t)buffer[i+4] << 32 |+ (uint64_t)buffer[i+5] << 40 |+ (uint64_t)buffer[i+6] << 48 |+ (uint64_t)buffer[i+7] << 56;+ var->real = u.d;+ _pbcA_push(array, var);+ }+ return size/8;+ case PTYPE_FLOAT:+ if (size % 4 != 0)+ return -1;+ for (i=0;i<size;i+=4) {+ union {+ float f;+ uint32_t i32;+ } u;+ u.i32 = (uint32_t)buffer[i] |+ (uint32_t)buffer[i+1] << 8 |+ (uint32_t)buffer[i+2] << 16 |+ (uint32_t)buffer[i+3] << 24;+ var->real = (double)u.f;+ _pbcA_push(array, var);+ }+ return size/4;+ case PTYPE_FIXED32:+ case PTYPE_SFIXED32:+ if (size % 4 != 0)+ return -1;+ for (i=0;i<size;i+=4) {+ var->integer.low = (uint32_t)buffer[i] |+ (uint32_t)buffer[i+1] << 8 |+ (uint32_t)buffer[i+2] << 16 |+ (uint32_t)buffer[i+3] << 24;+ _pbcA_push(array, var);+ }+ return size/4;+ case PTYPE_FIXED64:+ case PTYPE_SFIXED64:+ if (size % 8 != 0)+ return -1;+ for (i=0;i<size;i+=8) {+ var->integer.low = (uint32_t)buffer[i] |+ (uint32_t)buffer[i+1] << 8 |+ (uint32_t)buffer[i+2] << 16 |+ (uint32_t)buffer[i+3] << 24;+ var->integer.hi = (uint32_t)buffer[i+4] |+ (uint32_t)buffer[i+5] << 8 |+ (uint32_t)buffer[i+6] << 16 |+ (uint32_t)buffer[i+7] << 24;+ _pbcA_push(array, var);+ }+ return size/8;+ case PTYPE_INT64:+ case PTYPE_UINT64:+ case PTYPE_INT32:+ case PTYPE_UINT32:+ case PTYPE_ENUM: // enum must be integer type in pattern mode+ case PTYPE_BOOL: {+ int n = 0;+ while (size > 0) {+ int len;+ if (size >= 10) {+ len = _pbcV_decode(buffer, &(var->integer));+ } else {+ uint8_t temp[10];+ memcpy(temp, buffer, size);+ len = _pbcV_decode(buffer, &(var->integer));+ if (len > size)+ return -1;+ }+ _pbcA_push(array, var);+ buffer += len;+ size -= len;+ ++n;+ }+ return n;+ }+ case PTYPE_SINT32: {+ int n = 0;+ while (size > 0) {+ int len;+ if (size >= 10) {+ len = _pbcV_decode(buffer, &(var->integer));+ _pbcV_dezigzag32(&(var->integer));+ } else {+ uint8_t temp[10];+ memcpy(temp, buffer, size);+ len = _pbcV_decode(buffer, &(var->integer));+ if (len > size)+ return -1;+ _pbcV_dezigzag32(&(var->integer));+ }+ _pbcA_push(array, var);+ buffer += len;+ size -= len;+ ++n;+ }+ return n;+ }+ case PTYPE_SINT64: {+ int n = 0;+ while (size > 0) {+ int len;+ if (size >= 10) {+ len = _pbcV_decode(buffer, &(var->integer));+ _pbcV_dezigzag64(&(var->integer));+ } else {+ uint8_t temp[10];+ memcpy(temp, buffer, size);+ len = _pbcV_decode(buffer, &(var->integer));+ if (len > size)+ return -1;+ _pbcV_dezigzag64(&(var->integer));+ }+ _pbcA_push(array, var);+ buffer += len;+ size -= len;+ ++n;+ }+ return n;+ }+ }+ return -1;+}++static int+unpack_field(int ctype, int ptype, char * buffer, struct atom * a, void *out) {+ if (ctype == CTYPE_ARRAY) {+ return unpack_array(ptype, buffer, a , (struct _pbc_array *)out);+ }+ if (ctype == CTYPE_PACKED) {+ return _pbcP_unpack_packed((uint8_t *)buffer + a->v.s.start, a->v.s.end - a->v.s.start, ptype, (struct _pbc_array *)out);+ }+ switch(ptype) {+ case PTYPE_DOUBLE:+ CHECK_BIT64(a, -1);+ return write_real(ctype, read_double(a), out);+ case PTYPE_FLOAT:+ CHECK_BIT32(a, -1);+ return write_real(ctype, read_float(a), out);+ case PTYPE_INT64:+ case PTYPE_UINT64:+ case PTYPE_INT32:+ case PTYPE_UINT32:+ case PTYPE_ENUM: // enum must be integer type in pattern mode+ case PTYPE_BOOL:+ CHECK_VARINT(a, -1);+ return write_integer(ctype, a , out);+ case PTYPE_FIXED32:+ case PTYPE_SFIXED32:+ CHECK_BIT32(a, -1);+ return write_integer(ctype, a , out);+ case PTYPE_FIXED64:+ case PTYPE_SFIXED64:+ CHECK_BIT64(a, -1);+ return write_integer(ctype, a , out);+ case PTYPE_SINT32: {+ CHECK_VARINT(a, -1);+ struct longlong temp = a->v.i;+ _pbcV_dezigzag32(&temp);+ return write_longlong(ctype, &temp , out);+ }+ case PTYPE_SINT64: {+ CHECK_LEND(a, -1);+ struct longlong temp = a->v.i;+ _pbcV_dezigzag64(&temp);+ return write_longlong(ctype, &temp , out);+ }+ case PTYPE_MESSAGE: + CHECK_LEND(a, -1);+ ((union _pbc_var *)out)->m.buffer = buffer + a->v.s.start;+ ((union _pbc_var *)out)->m.len = a->v.s.end - a->v.s.start;+ return 0;+ case PTYPE_STRING:+ case PTYPE_BYTES:+ CHECK_LEND(a, -1);+ ((struct pbc_slice *)out)->buffer = buffer + a->v.s.start;+ ((struct pbc_slice *)out)->len = a->v.s.end - a->v.s.start;+ return 0;+ }+ return -1;+}++static int +unpack_array(int ptype, char *buffer, struct atom * a, pbc_array _array) {+ pbc_var var;+ int r = unpack_field(CTYPE_VAR, ptype, buffer, a , var);+ if (r !=0 )+ return r;+ _pbcA_push(_array , var);++ return 0;+}++void +pbc_pattern_close_arrays(struct pbc_pattern *pat, void * data) {+ int i;+ for (i=0;i<pat->count;i++) {+ if (pat->f[i].ctype == CTYPE_ARRAY || pat->f[i].ctype == CTYPE_PACKED) {+ void *array = (char *)data + pat->f[i].offset;+ _pbcA_close((struct _pbc_array *)array);+ }+ }+}++static inline int+_pack_wiretype(uint32_t wt, struct pbc_slice *s) {+ int len;+ if (s->len < 10) {+ uint8_t temp[10];+ len = _pbcV_encode32(wt, temp);+ if (len > s->len)+ return -1;+ memcpy(s->buffer, temp, len);+ } else {+ len = _pbcV_encode32(wt, (uint8_t *)s->buffer);+ }+ s->buffer = (char *)s->buffer + len;+ s->len -= len;+ return len;+}++static inline int+_pack_varint64(uint64_t i64, struct pbc_slice *s) {+ int len;+ if (s->len < 10) {+ uint8_t temp[10];+ len = _pbcV_encode(i64, temp);+ if (len > s->len)+ return -1;+ memcpy(s->buffer, temp, len);+ } else {+ len = _pbcV_encode(i64, (uint8_t *)s->buffer);+ }+ s->buffer = (char *)s->buffer + len;+ s->len -= len;+ return len;+}++static inline int+_pack_sint32(uint32_t v, struct pbc_slice *s) {+ int len;+ if (s->len < 10) {+ uint8_t temp[10];+ len = _pbcV_zigzag32(v, temp);+ if (len > s->len)+ return -1;+ memcpy(s->buffer, temp, len);+ } else {+ len = _pbcV_zigzag32(v, (uint8_t *)s->buffer);+ }+ s->buffer = (char *)s->buffer + len;+ s->len -= len;+ return len;+}++static inline int+_pack_sint64(uint64_t v, struct pbc_slice *s) {+ int len;+ if (s->len < 10) {+ uint8_t temp[10];+ len = _pbcV_zigzag(v, temp);+ if (len > s->len)+ return -1;+ memcpy(s->buffer, temp, len);+ } else {+ len = _pbcV_zigzag(v, (uint8_t *)s->buffer);+ }+ s->buffer = (char *)s->buffer + len;+ s->len -= len;+ return len;+}++static inline void+_fix32_encode(uint32_t v , uint8_t *buffer) {+ buffer[0] = (uint8_t) v;+ buffer[1] = (uint8_t) (v >> 8);+ buffer[2] = (uint8_t) (v >> 16);+ buffer[3] = (uint8_t) (v >> 24);+}++static inline void+_fix64_encode(struct longlong *v , uint8_t *buffer) {+ _fix32_encode(v->low , buffer);+ _fix32_encode(v->hi, buffer + 4);+}++static int+_pack_number(int ptype , int ctype , struct pbc_slice *s, void *input) {+ pbc_var var;+ if (ctype == CTYPE_VAR) {+ memcpy(var, input, sizeof(var));+ } else {+ switch (ctype) {+ case CTYPE_INT32:+ var->integer.low = *(uint32_t *)input;+ var->integer.hi = 0;+ break;+ case CTYPE_INT64: {+ uint64_t v = *(uint64_t *)input;+ var->integer.low = (uint32_t) (v & 0xffffffff);+ var->integer.hi = (uint32_t) (v >> 32);+ break;+ }+ case CTYPE_INT16:+ var->integer.low = *(uint16_t *)input;+ var->integer.hi = 0;+ break;+ case CTYPE_INT8:+ var->integer.low = *(uint8_t *)input;+ var->integer.hi = 0;+ break;+ case CTYPE_BOOL:+ var->integer.low = *(bool *)input;+ var->integer.hi = 0;+ break;+ case CTYPE_DOUBLE:+ var->real = *(double *)input;+ break;+ case CTYPE_FLOAT:+ var->real = *(float *)input;+ break;+ }+ }++ switch(ptype) {+ case PTYPE_FIXED64:+ case PTYPE_SFIXED64:+ if (s->len < 8)+ return -1;+ _fix64_encode(&(var->integer), (uint8_t *)s->buffer);+ s->buffer = (char *)s->buffer + 8;+ s->len -= 8;+ return 8;+ case PTYPE_DOUBLE:+ if (s->len < 8)+ return -1;+ double_encode(var->real , (uint8_t *)s->buffer);+ s->buffer = (char *)s->buffer + 8;+ s->len -= 8;+ return 8;+ case PTYPE_FLOAT:+ if (s->len < 4)+ return -1;+ float_encode((float)var->real , (uint8_t *)s->buffer);+ s->buffer = (char *)s->buffer + 4;+ s->len -= 4;+ return 4;+ case PTYPE_FIXED32:+ case PTYPE_SFIXED32:+ if (s->len < 4)+ return -1;+ _fix32_encode(var->integer.low, (uint8_t *)s->buffer);+ s->buffer = (char *)s->buffer + 4;+ s->len -= 4;+ return 4;+ case PTYPE_UINT64:+ case PTYPE_INT64:+ case PTYPE_INT32:+ return _pack_varint64((uint64_t)var->integer.low | (uint64_t)var->integer.hi << 32, s);+ case PTYPE_UINT32:+ case PTYPE_BOOL:+ case PTYPE_ENUM:+ return _pack_wiretype(var->integer.low , s);+ case PTYPE_SINT32: + return _pack_sint32(var->integer.low , s);+ case PTYPE_SINT64:+ return _pack_sint64((uint64_t)var->integer.low | (uint64_t)var->integer.hi << 32 , s);+ default:+ return -1;+ }+}++static int+_pack_field(struct _pattern_field *pf , int ctype, struct pbc_slice *s, void *input) {+ int wiretype;+ int ret = 0;+ int len;+ struct pbc_slice * input_slice;+ struct pbc_slice string_slice;++ switch(pf->ptype) {+ case PTYPE_FIXED64:+ case PTYPE_SFIXED64:+ case PTYPE_DOUBLE:+ wiretype = WT_BIT64;+ goto _number;+ case PTYPE_FIXED32:+ case PTYPE_SFIXED32:+ case PTYPE_FLOAT:+ wiretype = WT_BIT32;+ goto _number;+ case PTYPE_UINT64:+ case PTYPE_INT64:+ case PTYPE_INT32:+ case PTYPE_BOOL:+ case PTYPE_UINT32:+ case PTYPE_ENUM:+ case PTYPE_SINT32:+ case PTYPE_SINT64:+ wiretype = WT_VARINT;+ goto _number;+ case PTYPE_STRING:+ wiretype = WT_LEND;+ input_slice = (struct pbc_slice *)input;+ if (input_slice->len >= 0)+ goto _string;+ string_slice.buffer = input_slice->buffer;+ string_slice.len = strlen((const char *)string_slice.buffer) - input_slice->len;+ input_slice = &string_slice;+ + goto _string;+ case PTYPE_MESSAGE:+ case PTYPE_BYTES:+ wiretype = WT_LEND;+ goto _bytes;+ default:+ break;+ }++ return 0;+_bytes:+ input_slice = (struct pbc_slice *)input;+_string:+ len = _pack_wiretype(pf->id << 3 | WT_LEND , s);+ if (len < 0) {+ return len;+ }+ ret += len;+ len = _pack_wiretype(input_slice->len , s);+ if (len < 0) {+ return len;+ }+ ret += len;+ if (input_slice->len > s->len)+ return -1;+ memcpy(s->buffer , input_slice->buffer, input_slice->len);+ ret += input_slice->len;+ s->buffer = (char *)s->buffer + input_slice->len;+ s->len -= input_slice->len;++ return ret;+_number:+ len = _pack_wiretype(pf->id << 3 | wiretype , s);+ if (len < 0) {+ return len;+ }+ ret += len;+ len = _pack_number(pf->ptype, ctype , s, input);+ if (len < 0) {+ return len;+ }+ ret += len;++ return ret;+}++static int +_pack_repeated(struct _pattern_field *pf , struct pbc_slice *s, pbc_array array) {+ int n = pbc_array_size(array);+ int ret = 0;+ if (n>0) {+ int i;+ for (i=0;i<n;i++) {+ int len = _pack_field(pf , CTYPE_VAR , s , _pbcA_index_p(array , i));+ if (len < 0)+ return len;+ ret += len;+ }+ }+ return ret;+}++static int+_pack_packed_fixed(struct _pattern_field *pf , int width, struct pbc_slice *s, pbc_array array) {+ int len;+ int n = pbc_array_size(array);+ len = _pack_wiretype(n * width , s);+ if (len < 0) {+ return len;+ }+ if (s->len - len < n * width)+ return -1;+ int i;+ for (i=0;i<n;i++) {+ _pack_number(pf->ptype, CTYPE_VAR , s, _pbcA_index_p(array, i));+ }++ return len + n * width;+}++static int+_pack_packed_varint(struct _pattern_field *pf , struct pbc_slice *slice, pbc_array array) {+ struct pbc_slice s = * slice;+ int n = pbc_array_size(array);+ int estimate = n; + int estimate_len = _pack_wiretype(estimate , &s);+ if (estimate_len < 0) {+ return -1;+ }+ int i;+ int packed_len = 0;+ for (i=0;i<n;i++) {+ int len = _pack_number(pf->ptype, CTYPE_VAR , &s, _pbcA_index_p(array, i));+ if (len < 0)+ return -1;+ packed_len += len;+ }+ if (packed_len == estimate) {+ *slice = s;+ return packed_len + estimate_len;+ }+ uint8_t temp[10];+ struct pbc_slice header_slice = { temp , 10 };+ int header_len = _pack_wiretype(packed_len , &header_slice);+ if (header_len == estimate_len) {+ memcpy(slice->buffer , temp , header_len);+ *slice = s;+ return packed_len + estimate_len;+ }+ if (header_len + packed_len > slice->len)+ return -1;+ memmove((char *)slice->buffer + header_len , (char *)slice->buffer + estimate_len, packed_len);+ memcpy(slice->buffer , temp , header_len);+ slice->buffer = (char *)slice->buffer + packed_len + header_len;+ slice->len -= packed_len + header_len;+ return packed_len + header_len;+}++static int +_pack_packed(struct _pattern_field *pf , struct pbc_slice *s, pbc_array array) {+ int n = pbc_array_size(array);+ if (n == 0)+ return 0;++ int ret = 0;+ int len;+ len = _pack_wiretype(pf->id << 3 | WT_LEND , s);+ if (len < 0) {+ return len;+ }+ ret += len;++ switch (pf->ptype) {+ case PTYPE_FIXED64:+ case PTYPE_SFIXED64:+ case PTYPE_DOUBLE:+ len = _pack_packed_fixed(pf, 8, s , array);+ if (len < 0)+ return len;+ break;+ case PTYPE_FIXED32:+ case PTYPE_SFIXED32:+ case PTYPE_FLOAT:+ len = _pack_packed_fixed(pf, 4, s , array);+ if (len < 0)+ return len;+ break;+ case PTYPE_UINT64:+ case PTYPE_INT64:+ case PTYPE_INT32:+ case PTYPE_BOOL:+ case PTYPE_UINT32:+ case PTYPE_ENUM:+ case PTYPE_SINT32:+ case PTYPE_SINT64:+ len = _pack_packed_varint(pf, s, array);+ if (len < 0)+ return len;+ break;+ }+ ret += len;++ return ret;+}++static bool+_is_default(struct _pattern_field * pf, void * in) {+ switch (pf->ctype) {+ case CTYPE_INT64: {+ struct longlong * d64 = &pf->defv->integer;+ return ((uint64_t)d64->low | (uint64_t)d64->hi << 32) == *(uint64_t *)in;+ }+ case CTYPE_DOUBLE: + return pf->defv->real == *(double *)in;+ case CTYPE_FLOAT:+ return (float)(pf->defv->real) == *(float *)in;+ case CTYPE_INT32:+ return pf->defv->integer.low == *(uint32_t *)in;+ case CTYPE_INT16:+ return (uint16_t)(pf->defv->integer.low) == *(uint16_t *)in;+ case CTYPE_INT8:+ return (uint8_t)(pf->defv->integer.low) == *(uint8_t *)in;+ case CTYPE_BOOL:+ if (pf->defv->integer.low)+ return *(bool *)in == true;+ else+ return *(bool *)in == false;+ }+ if (pf->ptype == PTYPE_STRING) {+ struct pbc_slice *slice = (struct pbc_slice *)in;+ if (slice->buffer == NULL) {+ return pf->defv->s.str[0] == '\0';+ }+ int len = slice->len;+ if (len <= 0) {+ return strcmp(pf->defv->s.str, (const char *)slice->buffer) == 0;+ }+ return len == pf->defv->s.len && memcmp(pf->defv->s.str, slice->buffer, len)==0;+ }++ return false;+}++int +pbc_pattern_pack(struct pbc_pattern *pat, void *input, struct pbc_slice * s)+{+ struct pbc_slice slice = *s;+ int i;+ for (i=0;i<pat->count;i++) {+ struct _pattern_field * pf = &pat->f[i];+ void * in = (char *)input + pf->offset;+ int len = 0;+ switch(pf->label) {+ case LABEL_OPTIONAL:+ if (_is_default(pf , in)) {+ break;+ }+ case LABEL_REQUIRED:+ len = _pack_field(pf, pf->ctype, &slice, in);+ break;+ case LABEL_REPEATED:+ len = _pack_repeated(pf, &slice , (struct _pbc_array *)in);+ break;+ case LABEL_PACKED:+ len = _pack_packed(pf, &slice , (struct _pbc_array *)in);+ break;+ }+ if (len < 0) {+ return len;+ }+ }+ int len = (char *)slice.buffer - (char *)s->buffer;+ int ret = s->len - len;+ s->len = len;+ return ret;+}++int +pbc_pattern_unpack(struct pbc_pattern *pat, struct pbc_slice *s, void * output) {+ if (s->len == 0) {+ pbc_pattern_set_default(pat, output);+ return 0;+ }+ pbc_ctx _ctx;+ int r = _pbcC_open(_ctx, s->buffer, s->len);+ if (r <= 0) {+ pat->env->lasterror = "Pattern unpack open context error";+ _pbcC_close(_ctx);+ return r-1;+ }++ struct context * ctx = (struct context *)_ctx;+ bool * field = (bool *)alloca(pat->count * sizeof(bool));+ memset(field, 0, pat->count * sizeof(bool));++ int i;+ int fc = 0;++ for (i=0;i<ctx->number;i++) {+ struct _pattern_field * f = bsearch_pattern(pat, ctx->a[i].wire_id >> 3);+ if (f) {+ int index = f - pat->f;+ if (field[index] == false) {+ field[index] = true;+ ++fc;+ if ((f->ctype == CTYPE_ARRAY || f->ctype == CTYPE_PACKED)) {+ struct _pbc_array *array = (struct _pbc_array *)((char *)output + f->offset);+ _pbcA_open(array);+ }+ }+ char * out = (char *)output + f->offset;+ if (unpack_field(f->ctype , f->ptype , ctx->buffer , &ctx->a[i], out) < 0) {+ int j;+ for (j=0;j<pat->count;j++) {+ if (field[j] == true && (pat->f[j].ctype == CTYPE_ARRAY || pat->f[j].ctype == CTYPE_PACKED)) {+ void *array = (char *)output + pat->f[j].offset;+ _pbcA_close((struct _pbc_array *)array);+ }+ }+ _pbcC_close(_ctx);+ pat->env->lasterror = "Pattern unpack field error";+ return -i-1;+ }+ }+ }+ _pbcC_close(_ctx);+ if (fc != pat->count) {+ for (i=0;i<pat->count;i++) {+ if (field[i] == false) {+ _pattern_set_default(&pat->f[i], (char *)output);+ }+ }+ }+ return 0;+}++/* + format : key %type+ %f float+ %F double+ %d int32+ %D int64+ %b bool+ %h int16+ %c int8+ %s slice+ %a array+*/++static int+_ctype(const char * ctype) {+ if (ctype[0]!='%')+ return -1;+ switch (ctype[1]) {+ case 'f':+ return CTYPE_FLOAT;+ case 'F':+ return CTYPE_DOUBLE;+ case 'd':+ return CTYPE_INT32;+ case 'D':+ return CTYPE_INT64;+ case 'b':+ return CTYPE_BOOL;+ case 'h':+ return CTYPE_INT16;+ case 'c':+ return CTYPE_INT8;+ case 's':+ return CTYPE_VAR;+ case 'a':+ return CTYPE_ARRAY;+ default:+ return -1;+ }+}++static int+_ctype_size(const char *ctype) {+ switch (ctype[1]) {+ case 'f':+ return sizeof(float);+ case 'F':+ return sizeof(double);+ case 'd':+ return sizeof(int32_t);+ case 'D':+ return sizeof(int64_t);+ case 'b':+ return sizeof(bool);+ case 'h':+ return sizeof(int16_t);+ case 'c':+ return sizeof(int8_t);+ case 's':+ return sizeof(struct pbc_slice);+ case 'a':+ return sizeof(pbc_array);+ default:+ return 0;+ }+}++static const char *+_copy_string(const char *format , char ** temp) {+ char * output = *temp;+ while (*format == ' ' || *format == '\t' || *format == '\n' || *format == '\r') {+ ++format;+ }+ while (*format != '\0' &&+ *format != ' ' &&+ *format != '\t' &&+ *format != '\n' &&+ *format != '\r') {+ *output = *format;+ ++output;+ ++format;+ }+ *output = '\0';+ ++output;+ *temp = output;++ return format;+}++static int+_scan_pattern(const char * format , char * temp) {+ int n = 0;+ for(;;) {+ format = _copy_string(format , &temp);+ if (format[0] == '\0')+ return 0;+ ++n;+ format = _copy_string(format , &temp);+ if (format[0] == '\0')+ return n;+ } +}++static int +_comp_field(const void * a, const void * b) {+ const struct _pattern_field * fa = (const struct _pattern_field *)a;+ const struct _pattern_field * fb = (const struct _pattern_field *)b;++ return fa->id - fb->id;+}++struct pbc_pattern *+_pbcP_new(struct pbc_env * env, int n) {+ size_t sz = sizeof(struct pbc_pattern) + (sizeof(struct _pattern_field)) * (n-1);+ struct pbc_pattern * ret = (struct pbc_pattern *)malloc(sz);+ memset(ret, 0 , sz);+ ret->count = n;+ ret->env = env;+ return ret;+}++static int+_check_ctype(struct _field * field, struct _pattern_field *f) {+ if (field->label == LABEL_REPEATED) {+ return f->ctype != CTYPE_ARRAY;+ } + if (field->label == LABEL_PACKED) {+ return f->ctype != CTYPE_PACKED;+ }+ if (field->type == PTYPE_STRING || field->type == PTYPE_MESSAGE || field->type == PTYPE_BYTES) {+ return f->ctype != CTYPE_VAR;+ }+ if (field->type == PTYPE_FLOAT || field->type == PTYPE_DOUBLE) {+ return !(f->ctype == CTYPE_DOUBLE || f->ctype == CTYPE_FLOAT);+ }+ if (field->type == PTYPE_ENUM) {+ return !(f->ctype == CTYPE_INT8 || + f->ctype == CTYPE_INT8 || + f->ctype == CTYPE_INT16 ||+ f->ctype == CTYPE_INT32 ||+ f->ctype == CTYPE_INT64);+ }++ return f->ctype == CTYPE_VAR || f->ctype == CTYPE_ARRAY || f->ctype == CTYPE_PACKED ||+ f->ctype == CTYPE_DOUBLE || f->ctype == CTYPE_FLOAT;+}++struct pbc_pattern *+_pattern_new(struct _message *m, const char *format) {+ int len = strlen(format);+ char * temp = (char *)alloca(len+1);+ int n = _scan_pattern(format, temp);+ struct pbc_pattern * pat = _pbcP_new(m->env, n);+ int i;++ const char *ptr = temp;++ int offset = 0;++ for (i=0;i<n;i++) {+ struct _pattern_field * f = &(pat->f[i]);+ struct _field * field = (struct _field *)_pbcM_sp_query(m->name, ptr);+ if (field == NULL) {+ m->env->lasterror = "Pattern @new query none exist field";+ goto _error;+ }+ f->id = field->id;+ f->ptype = field->type;+ *f->defv = *field->default_v;+ f->offset = offset;+ f->label = field->label;+ ptr += strlen(ptr) + 1;+ f->ctype = _ctype(ptr);+ if (f->ctype < 0) {+ m->env->lasterror = "Pattern @new use an invalid ctype";+ goto _error;+ }+ + if (f->ctype == CTYPE_ARRAY && field->label == LABEL_PACKED) {+ f->ctype = CTYPE_PACKED;+ }+ if (_check_ctype(field, f)) {+ m->env->lasterror = "Pattern @new ctype check error";+ goto _error;+ }++ offset += _ctype_size(ptr);+ ptr += strlen(ptr) + 1;+ }++ pat->count = n;++ qsort(pat->f , n , sizeof(struct _pattern_field), _comp_field);+ return pat;+_error:+ free(pat);+ return NULL;+}++struct pbc_pattern * +pbc_pattern_new(struct pbc_env * env , const char * message, const char * format, ... ) {+ struct _message *m = _pbcP_get_message(env, message);+ if (m==NULL) {+ env->lasterror = "Pattern new can't find proto";+ return NULL;+ }+ if (format[0]=='@') {+ return _pattern_new(m , format+1);+ }++ int len = strlen(format);+ char * temp = (char *)alloca(len+1);+ int n = _scan_pattern(format, temp);+ struct pbc_pattern * pat = _pbcP_new(env, n);+ int i;+ va_list ap;+ va_start(ap , format);++ const char *ptr = temp;++ for (i=0;i<n;i++) {+ struct _pattern_field * f = &(pat->f[i]);+ struct _field * field = (struct _field *)_pbcM_sp_query(m->name, ptr);+ if (field == NULL) {+ env->lasterror = "Pattern new query none exist field";+ goto _error;+ }+ f->id = field->id;+ f->ptype = field->type;+ *f->defv = *field->default_v;+ f->offset = va_arg(ap, int);+ f->label = field->label;++ ptr += strlen(ptr) + 1;++ f->ctype = _ctype(ptr);+ if (f->ctype < 0) {+ env->lasterror = "Pattern new use an invalid ctype";+ goto _error;+ }+ if (f->ctype == CTYPE_ARRAY && field->label == LABEL_PACKED) {+ f->ctype = CTYPE_PACKED;+ }+ if (_check_ctype(field, f)) {+ env->lasterror = "Pattern new ctype check error";+ goto _error;+ }++ ptr += strlen(ptr) + 1;+ }++ va_end(ap);++ pat->count = n;++ qsort(pat->f , n , sizeof(struct _pattern_field), _comp_field);+ return pat;+_error:+ free(pat);+ return NULL;+}++void +pbc_pattern_delete(struct pbc_pattern * pat) {+ free(pat);+}
+ cbits/pattern.h view
@@ -0,0 +1,26 @@+#ifndef PROTOBUF_C_PATTERN_H+#define PROTOBUF_C_PATTERN_H++#include "pbc.h"+#include "context.h"+#include "array.h"++struct _pattern_field {+ int id;+ int offset;+ int ptype;+ int ctype;+ int label;+ pbc_var defv;+};++struct pbc_pattern {+ struct pbc_env * env;+ int count;+ struct _pattern_field f[1];+};++struct pbc_pattern * _pbcP_new(struct pbc_env * env, int n);+int _pbcP_unpack_packed(uint8_t *buffer, int size, int ptype, pbc_array array);++#endif
+ cbits/pbc-lua.c view
@@ -0,0 +1,1098 @@+#ifdef __cplusplus+extern "C" {+#endif+#include "lua.h"+#include "lualib.h"+#include "lauxlib.h"+#ifdef __cplusplus+}+#endif++#include <stdlib.h>++#ifndef _MSC_VER+#include <stdbool.h>+#else+#define alloca _alloca+#endif++#include <string.h>+#include <stdlib.h>+#include <stdint.h>++#include "pbc.h"++#if LUA_VERSION_NUM == 501++#define lua_rawlen lua_objlen+#define luaL_newlib(L ,reg) luaL_register(L,"protobuf.c",reg)+#define luaL_buffinit(L , _ ) +#define luaL_prepbuffsize( b , cap ) malloc(cap)+#define _Free(p) free(p)+#undef luaL_addsize+#define luaL_addsize(b , len) lua_pushlstring(L, temp , len) ; free(temp)+#define luaL_pushresult(b) +#define luaL_checkversion(L)++#else++#define _Free(p)++#endif++static inline void *+checkuserdata(lua_State *L, int index) {+ void * ud = lua_touserdata(L,index);+ if (ud == NULL) {+ luaL_error(L, "userdata %d is nil",index);+ }+ return ud;+}++static int+_env_new(lua_State *L) {+ struct pbc_env * env = pbc_new();+ lua_pushlightuserdata(L, env);+ return 1;+}++static int+_env_register(lua_State *L) {+ struct pbc_env * env = (struct pbc_env *)checkuserdata(L,1);+ size_t sz = 0;+ const char * buffer = luaL_checklstring(L, 2 , &sz);+ struct pbc_slice slice;+ slice.buffer = (void *)buffer;+ slice.len = (int)sz;+ int ret = pbc_register(env, &slice);++ if (ret) {+ return luaL_error(L, "register fail");+ }+ return 0;+}++static int+_rmessage_new(lua_State *L) {+ struct pbc_env * env = (struct pbc_env *)checkuserdata(L,1);+ const char * type_name = luaL_checkstring(L,2);+ struct pbc_slice slice;+ if (lua_isstring(L,3)) {+ size_t sz = 0;+ slice.buffer = (void *)lua_tolstring(L,3,&sz);+ slice.len = (int)sz;+ } else {+ slice.buffer = lua_touserdata(L,3);+ slice.len = luaL_checkinteger(L,4);+ }+ struct pbc_rmessage * m = pbc_rmessage_new(env, type_name, &slice);+ if (m==NULL)+ return 0;+ lua_pushlightuserdata(L,m);+ return 1;+}++static int+_rmessage_delete(lua_State *L) {+ struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);+ pbc_rmessage_delete(m);++ return 0;+}++static int+_rmessage_integer(lua_State *L) {+ struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ int index = luaL_checkinteger(L,3);+ int32_t v = (int32_t)pbc_rmessage_integer(m, key, index, NULL);++ lua_pushinteger(L,v);++ return 1;+}++static int+_rmessage_int32(lua_State *L) {+ struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ int index = luaL_checkinteger(L,3);+ uint32_t v = pbc_rmessage_integer(m, key, index, NULL);+ lua_pushlightuserdata(L,(void *)(intptr_t)v);++ return 1;+}+++static int+_rmessage_int64(lua_State *L) {+ struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ int index = luaL_checkinteger(L,3);+ uint32_t v[2];+ v[0] = pbc_rmessage_integer(m, key, index, &v[1]);++ lua_pushlstring(L,(const char *)v,sizeof(v));++ return 1;+}++static int+_rmessage_int52(lua_State *L) {+ struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ int index = luaL_checkinteger(L,3);+ uint32_t hi,low;+ low = pbc_rmessage_integer(m, key, index, &hi);+ int64_t v = (int64_t)((uint64_t)hi << 32 | (uint64_t)low);+ lua_pushnumber(L,(lua_Number)v);++ return 1;+}++static int+_rmessage_uint52(lua_State *L) {+ struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ int index = luaL_checkinteger(L,3);+ uint32_t hi,low;+ low = pbc_rmessage_integer(m, key, index, &hi);+ uint64_t v = (uint64_t)hi << 32 | (uint64_t)low;+ lua_pushnumber(L,(lua_Number)v);++ return 1;+}++static int +_rmessage_real(lua_State *L) {+ struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ int index = luaL_checkinteger(L,3);+ double v = pbc_rmessage_real(m, key, index);++ lua_pushnumber(L,v);++ return 1;+}++static int+_rmessage_string(lua_State *L) {+ struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ int index = lua_tointeger(L,3);+ int sz = 0;+ const char * v = pbc_rmessage_string(m,key,index,&sz);+ lua_pushlstring(L,v,sz);+ return 1;+}++static int+_rmessage_message(lua_State *L) {+ struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ int index = lua_tointeger(L,3);+ struct pbc_rmessage * v = pbc_rmessage_message(m,key,index);+ lua_pushlightuserdata(L,v);+ return 1;+}++static int+_rmessage_size(lua_State *L) {+ struct pbc_rmessage * m = (struct pbc_rmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);++ int sz = pbc_rmessage_size(m, key);++ lua_pushinteger(L, sz);++ return 1;+}++static int+_env_type(lua_State *L) {+ lua_settop(L,3);+ struct pbc_env * env = (struct pbc_env *)checkuserdata(L,1);+ const char * type_name = luaL_checkstring(L,2);+ if (lua_isnil(L,3)) {+ int ret = pbc_type(env, type_name, NULL, NULL);+ lua_pushboolean(L,ret);+ return 1;+ }+ const char * key = luaL_checkstring(L,3);+ const char * type = NULL;+ int ret = pbc_type(env, type_name, key, &type);+ lua_pushinteger(L,ret);+ if (type == NULL) {+ return 1;+ } {+ lua_pushstring(L, type);+ return 2;+ }+}++static int+_wmessage_new(lua_State *L) {+ struct pbc_env * env = (struct pbc_env *)checkuserdata(L,1);+ const char * type_name = luaL_checkstring(L,2);+ struct pbc_wmessage * ret = pbc_wmessage_new(env, type_name);+ lua_pushlightuserdata(L,ret);+ return 1;+}++static int+_wmessage_delete(lua_State *L) {+ struct pbc_wmessage * m = (struct pbc_wmessage *)lua_touserdata(L,1);+ pbc_wmessage_delete(m);++ return 0;+}+++static int+_wmessage_integer(lua_State *L) {+ struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ int number = luaL_checkinteger(L,3);+ uint32_t hi = 0;+ if (number < 0)+ hi = ~0;+ pbc_wmessage_integer(m, key, number, hi);++ return 0;+}++static int+_wmessage_real(lua_State *L) {+ struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ double number = luaL_checknumber(L,3);+ pbc_wmessage_real(m, key, number);++ return 0;+}++static int+_wmessage_string(lua_State *L) {+ struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ size_t len = 0;+ const char * v = luaL_checklstring(L,3,&len);+ int err = pbc_wmessage_string(m, key, v, (int)len);+ if (err) {+ return luaL_error(L, "Write string error : %s", v);+ }++ return 0;+}++static int+_wmessage_message(lua_State *L) {+ struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ struct pbc_wmessage * ret = pbc_wmessage_message(m, key);+ lua_pushlightuserdata(L, ret);++ return 1;+}++static int+_wmessage_int32(lua_State *L) {+ struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ if (!lua_islightuserdata(L,3)) {+ return luaL_error(L,"Need a lightuserdata for int32");+ }+ void *number = lua_touserdata(L,3);+ pbc_wmessage_integer(m, key, (uint32_t)(intptr_t)number , 0);+ return 0;+}++static int+_wmessage_int64(lua_State *L) {+ struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ switch (lua_type(L,3)) {+ case LUA_TSTRING : {+ size_t len = 0;+ const char * number = lua_tolstring(L,3,&len);+ if (len !=8 ) {+ return luaL_error(L,"Need an 8 length string for int64");+ }+ const uint32_t * v = (const uint32_t *) number;+ pbc_wmessage_integer(m, key, v[0] , v[1]);+ break;+ }+ case LUA_TLIGHTUSERDATA : {+ void * v = lua_touserdata(L,3);+ uint64_t v64 = (uintptr_t)v;+ pbc_wmessage_integer(m, key, (uint32_t)v64 , (uint32_t)(v64>>32));+ break;+ }+ default :+ return luaL_error(L, "Need an int64 type");+ }+ return 0;+}++static int+_wmessage_int52(lua_State *L) {+ struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ int64_t number = (int64_t)(luaL_checknumber(L,3));+ uint32_t hi = (uint32_t)(number >> 32);+ pbc_wmessage_integer(m, key, (uint32_t)number, hi);++ return 0;+}++static int+_wmessage_uint52(lua_State *L) {+ struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);+ const char * key = luaL_checkstring(L,2);+ lua_Number v = (luaL_checknumber(L,3));+ if (v < 0) {+ return luaL_error(L, "negative number : %f passed to unsigned field",v);+ }+ uint64_t number = (uint64_t)v;+ uint32_t hi = (uint32_t)(number >> 32);+ pbc_wmessage_integer(m, key, (uint32_t)number, hi);++ return 0;+}++static int+_wmessage_buffer(lua_State *L) {+ struct pbc_slice slice;+ struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);+ pbc_wmessage_buffer(m , &slice);+ lua_pushlightuserdata(L, slice.buffer);+ lua_pushinteger(L, slice.len);+ return 2;+}++static int+_wmessage_buffer_string(lua_State *L) {+ struct pbc_slice slice;+ struct pbc_wmessage * m = (struct pbc_wmessage *)checkuserdata(L,1);+ pbc_wmessage_buffer(m , &slice);+ lua_pushlstring(L, (const char *)slice.buffer, slice.len);+ return 1;+}++/*+ lightuserdata env+ */+static int+_last_error(lua_State *L) {+ struct pbc_env * env = (struct pbc_env *)checkuserdata(L, 1);+ const char * err = pbc_error(env);+ lua_pushstring(L,err);+ return 1;+}++/*+ lightuserdata env+ string message+ string format+ */+static int+_pattern_new(lua_State *L) {+ struct pbc_env * env = (struct pbc_env *)checkuserdata(L, 1);+ const char * message = luaL_checkstring(L,2);+ const char * format = luaL_checkstring(L,3);+ struct pbc_pattern * pat = pbc_pattern_new(env, message, format);+ if (pat == NULL) {+ return luaL_error(L, "create patten %s (%s) failed", message , format);+ }+ lua_pushlightuserdata(L,pat);++ return 1;+}++static int+_pattern_delete(lua_State *L) {+ struct pbc_pattern * pat = (struct pbc_pattern *)lua_touserdata(L,1);+ pbc_pattern_delete(pat);+ + return 0;+}++static void *+_push_value(lua_State *L, char * ptr, char type) {+ switch(type) {+ case 'u': {+ uint64_t v = *(uint64_t*)ptr;+ ptr += 8;+ lua_pushnumber(L,(lua_Number)v);+ break;+ }+ case 'i': {+ int32_t v = *(int32_t*)ptr;+ ptr += 4;+ lua_pushinteger(L,v);+ break;+ }+ case 'b': {+ int32_t v = *(int32_t*)ptr;+ ptr += 4;+ lua_pushboolean(L,v);+ break;+ }+ case 'p': {+ uint32_t v = *(uint32_t*)ptr;+ ptr += 4;+ lua_pushlightuserdata(L,(void *)(intptr_t)v);+ break;+ }+ case 'x': {+ lua_pushlstring(L,ptr,8);+ ptr += 8;+ break;+ }+ case 'd': {+ int64_t v = *(int64_t*)ptr;+ ptr += 8;+ lua_pushnumber(L,(lua_Number)v);+ break;+ }+ case 'r': {+ double v = *(double *)ptr;+ ptr += 8;+ lua_pushnumber(L,v);+ break;+ }+ case 's': {+ struct pbc_slice * slice = (struct pbc_slice *)ptr;+ lua_pushlstring(L,(const char *)slice->buffer, slice->len);+ ptr += sizeof(struct pbc_slice);+ break;+ }+ case 'm': {+ struct pbc_slice * slice = (struct pbc_slice *)ptr;+ lua_createtable(L,2,0);+ lua_pushlightuserdata(L, slice->buffer);+ lua_rawseti(L,-2,1);+ lua_pushinteger(L,slice->len);+ lua_rawseti(L,-2,2);+ ptr += sizeof(struct pbc_slice);+ break; + }+ }+ return ptr;+}++static void+_push_array(lua_State *L, pbc_array array, char type, int index) {+ switch (type) {+ case 'I': {+ int v = pbc_array_integer(array, index, NULL);+ lua_pushinteger(L, v);+ break;+ }+ case 'U': {+ uint32_t hi = 0;+ uint32_t low = pbc_array_integer(array, index, &hi);+ uint64_t v = (uint64_t)hi << 32 | (uint64_t)low;+ lua_pushnumber(L, (lua_Number)v);+ break;+ }+ case 'D': {+ uint32_t hi = 0;+ uint32_t low = pbc_array_integer(array, index, &hi);+ uint64_t v = (uint64_t)hi << 32 | (uint64_t)low;+ lua_pushnumber(L, (lua_Number)((int64_t)v));+ break;+ }+ case 'B': {+ int v = pbc_array_integer(array, index, NULL);+ lua_pushboolean(L, v);+ break;+ }+ case 'P': {+ uint32_t v = pbc_array_integer(array, index, NULL);+ lua_pushlightuserdata(L,(void *)(intptr_t)v);+ break;+ }+ case 'X': {+ uint32_t hi = 0;+ uint32_t low = pbc_array_integer(array, index, &hi);+ uint64_t v = (uint64_t)low | (uint64_t)hi << 32;+ lua_pushlstring(L, (char *)&v, 8);+ break;+ }+ case 'R': {+ double v = pbc_array_real(array, index);+ lua_pushnumber(L, v);+ break;+ }+ case 'S': {+ struct pbc_slice * slice = pbc_array_slice(array, index);+ lua_pushlstring(L, (const char *)slice->buffer,slice->len);+ break;+ }+ case 'M': {+ struct pbc_slice * slice = pbc_array_slice(array, index);+ lua_createtable(L,2,0);+ lua_pushlightuserdata(L,slice->buffer);+ lua_rawseti(L,-2,1);+ lua_pushinteger(L,slice->len);+ lua_rawseti(L,-2,2);+ break;+ }+ }+ lua_rawseti(L,-2,index+1);+}++/*+ lightuserdata pattern+ string format "ixrsmb"+ integer size+ lightuserdata buffer+ integer buffer_len+ */+static int+_pattern_unpack(lua_State *L) {+ struct pbc_pattern * pat = (struct pbc_pattern *)checkuserdata(L, 1);+ if (pat == NULL) {+ return luaL_error(L, "unpack pattern is NULL");+ }+ size_t format_sz = 0;+ const char * format = lua_tolstring(L,2,&format_sz);+ int size = lua_tointeger(L,3);+ struct pbc_slice slice;+ if (lua_isstring(L,4)) {+ size_t buffer_len = 0;+ const char *buffer = luaL_checklstring(L,4,&buffer_len);+ slice.buffer = (void *)buffer;+ slice.len = buffer_len;+ } else {+ if (!lua_isuserdata(L,4)) {+ return luaL_error(L, "Need a userdata");+ }+ slice.buffer = lua_touserdata(L,4);+ slice.len = luaL_checkinteger(L,5);+ }+ + char * temp = (char *)alloca(size);+ int ret = pbc_pattern_unpack(pat, &slice, temp);+ if (ret < 0) {+ return 0;+ }+ lua_checkstack(L, format_sz + 3);+ int i;+ char * ptr = temp;+ bool array = false;+ for (i=0;i<format_sz;i++) {+ char type = format[i];+ if (type >= 'a' && type <='z') {+ ptr = (char *)_push_value(L,ptr,type);+ } else {+ array = true;+ int n = pbc_array_size((struct _pbc_array *)ptr);+ lua_createtable(L,n,0);+ int j;+ for (j=0;j<n;j++) {+ _push_array(L,(struct _pbc_array *)ptr, type, j);+ }+ ptr += sizeof(pbc_array);+ }+ }+ if (array) {+ pbc_pattern_close_arrays(pat, temp);+ }+ return format_sz;+}++static char *+_get_value(lua_State *L, int index, char * ptr, char type) {+ switch(type) {+ case 'i': {+ int32_t v = luaL_checkinteger(L, index);+ memcpy(ptr, &v, 4);+ return ptr + 4;+ }+ case 'u': {+ uint64_t v = (uint64_t)luaL_checknumber(L, index);+ memcpy(ptr, &v, 8);+ return ptr + 8;+ }+ case 'd': {+ int64_t v = (int64_t)luaL_checknumber(L, index);+ memcpy(ptr, &v, 8);+ return ptr + 8;+ }+ case 'b': {+ int32_t v = lua_toboolean(L, index);+ memcpy(ptr, &v, 4);+ return ptr + 4;+ }+ case 'p': {+ void *p = lua_touserdata(L, index);+ uint32_t v = (uint32_t)(intptr_t)p;+ memcpy(ptr, &v , 4);+ return ptr + 4;+ }+ case 'x': {+ const char * i64 = luaL_checkstring(L, index);+ memcpy(ptr, i64, 8);+ return ptr + 8;+ }+ case 'r': {+ double v = luaL_checknumber(L, index);+ memcpy(ptr, &v, 8);+ return ptr + 8;+ }+ case 's': {+ size_t sz = 0;+ const char * str = luaL_checklstring(L, index, &sz);+ struct pbc_slice * slice = (struct pbc_slice *)ptr;+ slice->buffer = (void*)str;+ slice->len = sz;+ return ptr + sizeof(struct pbc_slice);+ }+ case 'm': {+ struct pbc_slice * slice = (struct pbc_slice *)ptr;+ if (lua_istable(L,index)) {+ lua_rawgeti(L,index,1);+ slice->buffer = lua_touserdata(L,-1);+ lua_rawgeti(L,index,2);+ slice->len = lua_tointeger(L,-1);+ lua_pop(L,2);+ } else {+ size_t sz = 0;+ const char * buffer = luaL_checklstring(L, index, &sz);+ slice->buffer = (void *)buffer;+ slice->len = sz;+ }+ return ptr + sizeof(struct pbc_slice);+ }+ default:+ luaL_error(L,"unknown format %c", type);+ return ptr;+ }+}++static void+_get_array_value(lua_State *L, pbc_array array, char type) {+ switch(type) {+ case 'I': {+ int32_t v = luaL_checkinteger(L, -1);+ uint32_t hi = 0;+ if (v<0) {+ hi = ~0;+ }+ pbc_array_push_integer(array, v, hi);+ break;+ }+ case 'U' : {+ uint64_t v = (uint64_t)luaL_checknumber(L, -1);+ pbc_array_push_integer(array, (uint32_t)v, (uint32_t)(v >> 32));+ break;+ }+ case 'D' : {+ int64_t v = (int64_t)luaL_checknumber(L, -1);+ pbc_array_push_integer(array, (uint32_t)v, (uint32_t)(v >> 32));+ break;+ }+ case 'B': {+ int32_t v = lua_toboolean(L, -1);+ pbc_array_push_integer(array, v ? 1: 0, 0);+ break;+ }+ case 'P': {+ void *p = lua_touserdata(L, -1);+ uint32_t v = (uint32_t)(intptr_t)p;+ pbc_array_push_integer(array, v, 0);+ break;+ }+ case 'X': {+ const char * i64 = luaL_checkstring(L, -1);+ uint64_t v = *(uint64_t *)i64;+ pbc_array_push_integer(array, (uint32_t)v, (uint32_t)(v >> 32));+ break;+ }+ case 'R': {+ double v = luaL_checknumber(L, -1);+ pbc_array_push_real(array, v);+ break;+ }+ case 'S': {+ size_t sz = 0;+ const char * str = luaL_checklstring(L, -1, &sz);+ struct pbc_slice slice;+ slice.buffer = (void*)str;+ slice.len = sz;+ pbc_array_push_slice(array, &slice);+ break;+ }+ case 'M': {+ struct pbc_slice slice;+ if (lua_istable(L,-1)) {+ lua_rawgeti(L,-1,1);+ slice.buffer = lua_touserdata(L,-1);+ lua_rawgeti(L,-2,2);+ slice.len = lua_tointeger(L,-1);+ lua_pop(L,2);+ } else {+ size_t sz = 0;+ const char * buffer = luaL_checklstring(L, -1, &sz);+ slice.buffer = (void *)buffer;+ slice.len = sz;+ }+ pbc_array_push_slice(array, &slice);+ break;+ }+ }+}++/*+ lightuserdata pattern+ string format "ixrsmbp"+ integer size+ */+static int+_pattern_pack(lua_State *L) {+ struct pbc_pattern * pat = (struct pbc_pattern *)checkuserdata(L,1);+ if (pat == NULL) {+ return luaL_error(L, "pack pattern is NULL");+ }+ size_t format_sz = 0;+ const char * format = lua_tolstring(L,2,&format_sz);+ int size = lua_tointeger(L,3);++ char * data = (char *)alloca(size);+// A trick , we don't need default value. zero buffer for array and message field.+// pbc_pattern_set_default(pat, data);+ memset(data, 0 , size);++ char * ptr = data;++ int i;++ for (i=0;i<format_sz;i++) {+ if (format[i] >= 'a' && format[i] <='z') {+ ptr = _get_value(L, 4+i, ptr, format[i]);+ } else {+ if (!lua_istable(L,4+i)) {+ luaL_error(L,"need table for array type");+ }+ int j;+ int n = lua_rawlen(L,4+i);+ for (j=0;j<n;j++) {+ lua_rawgeti(L,4+i,j+1);+ _get_array_value(L,(struct _pbc_array *)ptr,format[i]);+ lua_pop(L,1);+ }+ ptr += sizeof(pbc_array);+ }+ }++ luaL_Buffer b;+ luaL_buffinit(L, &b);++ int cap = 128;+ for (;;) {+ char * temp = (char *)luaL_prepbuffsize(&b , cap);++ struct pbc_slice slice;+ slice.buffer = temp;+ slice.len = cap;++ int ret = pbc_pattern_pack(pat, data, &slice);++ if (ret < 0) {+ cap = cap * 2;+ _Free(temp);+ continue;+ }++ luaL_addsize(&b , slice.len);+ break;+ }+ luaL_pushresult(&b);++ pbc_pattern_close_arrays(pat, data);+ return 1;+}++static int+_pattern_size(lua_State *L) {+ size_t sz =0;+ const char *format = luaL_checklstring(L,1,&sz);+ int i;+ int size = 0;+ for (i=0;i<sz;i++) {+ switch(format[i]) {+ case 'b': + case 'i':+ case 'p':+ size += 4;+ break;+ case 'r':+ case 'x': + case 'u':+ case 'd':+ size += 8;+ break;+ case 's':+ case 'm':+ size += sizeof(struct pbc_slice);+ break;+ default:+ size += sizeof(pbc_array);+ break;+ }+ }+ lua_pushinteger(L,size);+ return 1;+}++/*+ -3 table key+ -2 table id+ -1 value+ */+static void+new_array(lua_State *L, int id, const char *key) {+ lua_rawgeti(L, -2 , id);+ if (lua_isnil(L, -1)) {+ lua_pop(L,1);+ lua_newtable(L); // table.key table.id value array+ lua_pushvalue(L,-1);+ lua_pushvalue(L,-1); // table.key table.id value array array array+ lua_setfield(L, -6 , key);+ lua_rawseti(L, -4, id);+ }+}++static void+push_value(lua_State *L, int type, const char * type_name, union pbc_value *v) {+ switch(type) {+ case PBC_INT:+ lua_pushinteger(L, (int)v->i.low);+ break;+ case PBC_REAL:+ lua_pushnumber(L, v->f);+ break;+ case PBC_BOOL:+ lua_pushboolean(L, v->i.low);+ break;+ case PBC_ENUM:+ lua_pushstring(L, v->e.name);+ break;+ case PBC_BYTES:+ case PBC_STRING:+ lua_pushlstring(L, (const char *)v->s.buffer , v->s.len);+ break;+ case PBC_MESSAGE:+ lua_pushvalue(L, -3);+ lua_pushstring(L, type_name);+ lua_pushlstring(L, (const char *)v->s.buffer , v->s.len);+ lua_call(L, 2 , 1);+ break;+ case PBC_FIXED64:+ lua_pushlstring(L, (const char *)&(v->i), 8);+ break;+ case PBC_FIXED32:+ lua_pushlightuserdata(L,(void *)(intptr_t)v->i.low);+ break;+ case PBC_INT64: {+ uint64_t v64 = (uint64_t)(v->i.hi) << 32 | (uint64_t)(v->i.low);+ lua_pushnumber(L,(lua_Number)(int64_t)v64);+ break;+ }+ case PBC_UINT: {+ uint64_t v64 = (uint64_t)(v->i.hi) << 32 | (uint64_t)(v->i.low);+ lua_pushnumber(L,(lua_Number)v64);+ break;+ }+ default:+ luaL_error(L, "Unknown type %s", type_name);+ break;+ }+}++/*+ -3: function decode+ -2: table key+ -1: table id+ */+static void+decode_cb(void *ud, int type, const char * type_name, union pbc_value *v, int id, const char *key) {+ lua_State *L = (lua_State *)ud;+ if (key == NULL) {+ // undefined field+ return;+ }+ if (type & PBC_REPEATED) {+ push_value(L, type & ~PBC_REPEATED, type_name, v);+ new_array(L, id , key); // func.decode table.key table.id value array+ int n = lua_rawlen(L,-1);+ lua_insert(L, -2); // func.decode table.key table.id array value+ lua_rawseti(L, -2 , n+1); // func.decode table.key table.id array+ lua_pop(L,1);+ } else {+ push_value(L, type, type_name, v);+ lua_setfield(L, -3 , key);+ }+}++/*+ :1 lightuserdata env+ :2 function decode_message+ :3 table target+ :4 string type+ :5 string data+ :5 lightuserdata pointer+ :6 integer len++ table+ */+static int+_decode(lua_State *L) {+ struct pbc_env * env = (struct pbc_env *)checkuserdata(L,1);+ luaL_checktype(L, 2 , LUA_TFUNCTION);+ luaL_checktype(L, 3 , LUA_TTABLE);+ const char * type = luaL_checkstring(L,4);+ struct pbc_slice slice;+ if (lua_type(L,5) == LUA_TSTRING) {+ size_t len;+ slice.buffer = (void *)luaL_checklstring(L,5,&len);+ slice.len = (int)len;+ } else {+ slice.buffer = checkuserdata(L,5);+ slice.len = luaL_checkinteger(L,6);+ }+ lua_pushvalue(L, 2);+ lua_pushvalue(L, 3);+ lua_newtable(L);++ int n = pbc_decode(env, type, &slice, decode_cb, L);+ if (n<0) {+ lua_pushboolean(L,0);+ } else {+ lua_pushboolean(L,1);+ }+ return 1;+}++struct gcobj {+ struct pbc_env * env;+ int size_pat;+ int cap_pat;+ struct pbc_pattern ** pat;+ int size_msg;+ int cap_msg;+ struct pbc_rmessage ** msg;+};++static int+_clear_gcobj(lua_State *L) {+ struct gcobj * obj = (struct gcobj *)lua_touserdata(L,1);+ int i;+ for (i=0;i<obj->size_pat;i++) {+ pbc_pattern_delete(obj->pat[i]);+ }+ for (i=0;i<obj->size_msg;i++) {+ pbc_rmessage_delete(obj->msg[i]);+ }+ free(obj->pat);+ free(obj->msg);+ obj->pat = NULL;+ obj->msg = NULL;+ pbc_delete(obj->env);+ obj->env = NULL;++ return 0;+}++static int+_gc(lua_State *L) {+ struct gcobj * obj = (struct gcobj *)lua_newuserdata(L,sizeof(*obj));+ obj->env = (struct pbc_env *)lua_touserdata(L,1);+ obj->size_pat = 0;+ obj->cap_pat = 4;+ obj->size_msg = 0;+ obj->cap_msg = 4;+ obj->pat = (struct pbc_pattern **)malloc(obj->cap_pat * sizeof(struct pbc_pattern *));+ obj->msg = (struct pbc_rmessage **)malloc(obj->cap_msg * sizeof(struct pbc_rmessage *));++ lua_createtable(L,0,1);+ lua_pushcfunction(L, _clear_gcobj);+ lua_setfield(L,-2,"__gc");+ lua_setmetatable(L,-2);++ return 1;+}++static int+_add_pattern(lua_State *L) {+ struct gcobj * obj = (struct gcobj *)lua_touserdata(L,1);+ if (obj->size_pat >= obj->cap_pat) {+ obj->cap_pat *= 2;+ obj->pat = (struct pbc_pattern **)realloc(obj->pat, obj->cap_pat * sizeof(struct pbc_pattern *));+ }+ struct pbc_pattern * pat = (struct pbc_pattern *)lua_touserdata(L,2);+ obj->pat[obj->size_pat++] = pat;+ return 0;+}++static int+_add_rmessage(lua_State *L) {+ struct gcobj * obj = (struct gcobj *)lua_touserdata(L,1);+ if (obj->size_msg >= obj->cap_msg) {+ obj->cap_msg *= 2;+ obj->msg = (struct pbc_rmessage **)realloc(obj->msg, obj->cap_msg * sizeof(struct pbc_rmessage *));+ }+ struct pbc_rmessage * msg = (struct pbc_rmessage *)lua_touserdata(L,2);+ obj->msg[obj->size_msg++] = msg;+ return 0;+}++int+luaopen_protobuf_c(lua_State *L) {+ luaL_Reg reg[] = {+ {"_env_new" , _env_new },+ {"_env_register" , _env_register },+ {"_env_type", _env_type },+ {"_rmessage_new" , _rmessage_new },+ {"_rmessage_delete" , _rmessage_delete },+ {"_rmessage_integer" , _rmessage_integer },+ {"_rmessage_int32", _rmessage_int32 },+ {"_rmessage_int64", _rmessage_int64 },+ {"_rmessage_int52", _rmessage_int52 },+ {"_rmessage_uint52", _rmessage_uint52 },+ {"_rmessage_real" , _rmessage_real },+ {"_rmessage_string" , _rmessage_string },+ {"_rmessage_message" , _rmessage_message },+ {"_rmessage_size" , _rmessage_size },+ {"_wmessage_new", _wmessage_new },+ {"_wmessage_delete", _wmessage_delete },+ {"_wmessage_integer", _wmessage_integer },+ {"_wmessage_real", _wmessage_real },+ {"_wmessage_string", _wmessage_string },+ {"_wmessage_message", _wmessage_message },+ {"_wmessage_int32", _wmessage_int32 },+ {"_wmessage_int64", _wmessage_int64 },+ {"_wmessage_int52", _wmessage_int52 },+ {"_wmessage_uint52", _wmessage_uint52 },+ {"_wmessage_buffer", _wmessage_buffer },+ {"_wmessage_buffer_string", _wmessage_buffer_string },+ {"_pattern_new", _pattern_new },+ {"_pattern_delete", _pattern_delete },+ {"_pattern_size", _pattern_size },+ {"_pattern_unpack", _pattern_unpack },+ {"_pattern_pack", _pattern_pack },+ {"_last_error", _last_error },+ {"_decode", _decode },+ {"_gc", _gc },+ {"_add_pattern", _add_pattern },+ {"_add_rmessage", _add_rmessage },+ {NULL,NULL},+ };++ luaL_checkversion(L);+ luaL_newlib(L, reg);++ return 1;+}
+ cbits/pbc.h view
@@ -0,0 +1,104 @@+#ifndef PROTOBUF_C_H+#define PROTOBUF_C_H++#include <stdio.h>+#include <stdint.h>++#define PBC_ARRAY_CAP 64++#define PBC_NOEXIST -1+#define PBC_INT 1+#define PBC_REAL 2+#define PBC_BOOL 3+#define PBC_ENUM 4+#define PBC_STRING 5+#define PBC_MESSAGE 6+#define PBC_FIXED64 7+#define PBC_FIXED32 8+#define PBC_BYTES 9+#define PBC_INT64 10+#define PBC_UINT 11+#define PBC_UNKNOWN 12+#define PBC_REPEATED 128++typedef struct _pbc_array { char _data[PBC_ARRAY_CAP]; } pbc_array[1];++struct pbc_slice {+ void *buffer;+ int len;+};++struct pbc_pattern;+struct pbc_env;+struct pbc_rmessage;+struct pbc_wmessage;++struct pbc_env * pbc_new(void);+void pbc_delete(struct pbc_env *);+int pbc_register(struct pbc_env *, struct pbc_slice * slice);+int pbc_type(struct pbc_env *, const char * type_name , const char * key , const char ** type);+const char * pbc_error(struct pbc_env *);++// callback api+union pbc_value {+ struct {+ uint32_t low;+ uint32_t hi;+ } i;+ double f;+ struct pbc_slice s;+ struct {+ int id;+ const char * name;+ } e;+};++typedef void (*pbc_decoder)(void *ud, int type, const char * type_name, union pbc_value *v, int id, const char *key);+int pbc_decode(struct pbc_env * env, const char * type_name , struct pbc_slice * slice, pbc_decoder f, void *ud);++// message api++struct pbc_rmessage * pbc_rmessage_new(struct pbc_env * env, const char * type_name , struct pbc_slice * slice);+void pbc_rmessage_delete(struct pbc_rmessage *);++uint32_t pbc_rmessage_integer(struct pbc_rmessage * , const char *key , int index, uint32_t *hi);+double pbc_rmessage_real(struct pbc_rmessage * , const char *key , int index);+const char * pbc_rmessage_string(struct pbc_rmessage * , const char *key , int index, int *sz);+struct pbc_rmessage * pbc_rmessage_message(struct pbc_rmessage *, const char *key, int index);+int pbc_rmessage_size(struct pbc_rmessage *, const char *key);+int pbc_rmessage_next(struct pbc_rmessage *, const char **key);++struct pbc_wmessage * pbc_wmessage_new(struct pbc_env * env, const char *type_name);+void pbc_wmessage_delete(struct pbc_wmessage *);++// for negative integer, pass -1 to hi+int pbc_wmessage_integer(struct pbc_wmessage *, const char *key, uint32_t low, uint32_t hi);+int pbc_wmessage_real(struct pbc_wmessage *, const char *key, double v);+int pbc_wmessage_string(struct pbc_wmessage *, const char *key, const char * v, int len);+struct pbc_wmessage * pbc_wmessage_message(struct pbc_wmessage *, const char *key);+void * pbc_wmessage_buffer(struct pbc_wmessage *, struct pbc_slice * slice);++// array api ++int pbc_array_size(pbc_array);+uint32_t pbc_array_integer(pbc_array array, int index, uint32_t *hi);+double pbc_array_real(pbc_array array, int index);+struct pbc_slice * pbc_array_slice(pbc_array array, int index);++void pbc_array_push_integer(pbc_array array, uint32_t low, uint32_t hi);+void pbc_array_push_slice(pbc_array array, struct pbc_slice *);+void pbc_array_push_real(pbc_array array, double v);++struct pbc_pattern * pbc_pattern_new(struct pbc_env * , const char * message, const char *format, ...);+void pbc_pattern_delete(struct pbc_pattern *);++// return unused bytes , -1 for error+int pbc_pattern_pack(struct pbc_pattern *, void *input, struct pbc_slice * s);++// <0 for error+int pbc_pattern_unpack(struct pbc_pattern *, struct pbc_slice * s , void * output);++void pbc_pattern_set_default(struct pbc_pattern * , void *data);+void pbc_pattern_close_arrays(struct pbc_pattern *, void *data);++#endif
+ cbits/proto.c view
@@ -0,0 +1,252 @@+#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);+}
+ cbits/proto.h view
@@ -0,0 +1,65 @@+#ifndef PROTOBUFC_PROTO_H+#define PROTOBUFC_PROTO_H++#include "pbc.h"+#include "map.h"+#include "array.h"+#ifndef _MSC_VER+#include <stdbool.h>+#endif+#include <stddef.h>++struct map_ip;+struct map_si;+struct map_sp;+struct _message;+struct _enum;++#define LABEL_OPTIONAL 0+#define LABEL_REQUIRED 1+#define LABEL_REPEATED 2+#define LABEL_PACKED 3++struct _field {+ int id;+ const char *name;+ int type;+ int label;+ pbc_var default_v;+ union {+ const char * n;+ struct _message * m;+ struct _enum * e;+ } type_name;+};++struct _message {+ const char * key;+ struct map_ip * id; // id -> _field+ struct map_sp * name; // string -> _field+ struct pbc_rmessage * def; // default message+ struct pbc_env * env;+};++struct _enum {+ const char * key;+ struct map_ip * id;+ struct map_si * name;+ pbc_var default_v;+};++struct pbc_env {+ struct map_sp * files; // string -> void *+ struct map_sp * enums; // string -> _enum+ struct map_sp * msgs; // string -> _message+ const char * lasterror;+};++struct _message * _pbcP_init_message(struct pbc_env * p, const char *name);+void _pbcP_push_message(struct pbc_env * p, const char *name, struct _field *f , pbc_array queue);+struct _enum * _pbcP_push_enum(struct pbc_env * p, const char *name, struct map_kv *table, int sz );+int _pbcP_message_default(struct _message * m, const char * name, pbc_var defv);+struct _message * _pbcP_get_message(struct pbc_env * p, const char *name);+int _pbcP_type(struct _field * field, const char **type);++#endif
+ cbits/register.c view
@@ -0,0 +1,342 @@+#include "pbc.h"+#include "proto.h"+#include "alloc.h"+#include "map.h"+#include "bootstrap.h"+#include "context.h"+#include "stringpool.h"++#include <string.h>+#include <stdlib.h>++#ifdef _MSC_VER+#define strtoll _strtoi64+#endif++static const char *+_concat_name(struct _stringpool *p , const char *prefix , int prefix_sz , const char *name , int name_sz, int *sz) {+ if (prefix_sz == 0) {+ if (sz) {+ *sz = name_sz;+ }+ return _pbcS_build(p , name, name_sz);+ }+ char * temp = (char *)alloca(name_sz + prefix_sz + 2);+ memcpy(temp,prefix,prefix_sz);+ temp[prefix_sz] = '.';+ memcpy(temp+prefix_sz+1,name,name_sz);+ temp[name_sz + prefix_sz + 1] = '\0';+ if (sz) {+ *sz = name_sz + prefix_sz + 1;+ }+ const char * ret = _pbcS_build(p , temp, name_sz + prefix_sz + 1);+ return ret;+}++static void+_register_enum(struct pbc_env *p, struct _stringpool *pool, struct pbc_rmessage * enum_type, const char *prefix, int prefix_sz) {+ int field_count = pbc_rmessage_size(enum_type, "value");+ struct map_kv *table = (struct map_kv *)malloc(field_count * sizeof(struct map_kv));+ int i;+ for (i=0;i<field_count;i++) {+ struct pbc_rmessage * value = pbc_rmessage_message(enum_type, "value", i);+ int enum_name_sz;+ const char *enum_name = pbc_rmessage_string(value , "name" , 0 , &enum_name_sz);+ table[i].pointer = (void *)_pbcS_build(pool, enum_name , enum_name_sz);+ table[i].id = pbc_rmessage_integer(value , "number", 0 , 0);+ }+ int name_sz;+ const char * name = pbc_rmessage_string(enum_type, "name", 0 , &name_sz);+ const char *temp = _concat_name(pool, prefix , prefix_sz , name , name_sz, NULL);++ _pbcP_push_enum(p,temp,table,field_count);+ free(table);+}++static void+_set_default(struct _stringpool *pool, struct _field *f , int ptype, const char *value, int sz) {+ if (value == NULL || sz == 0) {+ if (f->type == PTYPE_STRING || f->type == PTYPE_BYTES) {+ f->default_v->s.str = "";+ f->default_v->s.len = 0;+ } else {+ f->default_v->integer.low = 0;+ f->default_v->integer.hi = 0;+ }+ return;+ }++ switch (f->type) {+ case PTYPE_DOUBLE:+ case PTYPE_FLOAT:+ f->default_v->real = strtod(value,NULL);+ break;+ case PTYPE_STRING:+ f->default_v->s.str = _pbcS_build(pool, value , sz);+ f->default_v->s.len = sz;+ break;+ case PTYPE_ENUM:+ // enum default value will be converted to f->default_v->e in bootstrap.c : set_field_one()+ f->default_v->s.str = value;+ f->default_v->s.len = sz;+ break;+ case PTYPE_BOOL:+ if (strcmp(value,"true") == 0) {+ f->default_v->integer.low = 1;+ } else {+ f->default_v->integer.low = 0;+ }+ f->default_v->integer.hi = 0;+ break;+ case PTYPE_UINT64:+ case PTYPE_INT64:+ case PTYPE_SFIXED64:+ case PTYPE_SINT64: {+ long long v = strtoll(value, NULL, 10);+ f->default_v->integer.low = (long) v;+ f->default_v->integer.hi = (long)(v >> 32);+ break;+ }+ case PTYPE_INT32:+ case PTYPE_FIXED32:+ case PTYPE_SFIXED32:+ case PTYPE_SINT32: {+ int low = strtol(value, NULL, 10);+ f->default_v->integer.low = low;+ if (low < 0) {+ f->default_v->integer.hi = -1;+ } else {+ f->default_v->integer.hi = 0;+ }+ break;+ }+ case PTYPE_UINT32:+ f->default_v->integer.low = strtoul(value, NULL, 10);+ f->default_v->integer.hi = 0;+ break;+ case PTYPE_BYTES:+ case PTYPE_MESSAGE:+ // bytes and message types have no default value+ f->default_v->m.buffer = 0;+ f->default_v->m.len = 0;+ break;+ default:+ f->default_v->integer.low = 0;+ f->default_v->integer.hi = 0;+ break;+ }+}++static void+_register_field(struct pbc_rmessage * field, struct _field * f, struct _stringpool *pool) {+ f->id = pbc_rmessage_integer(field, "number", 0 , 0);+ f->type = pbc_rmessage_integer(field, "type", 0 , 0); // enum+ f->label = pbc_rmessage_integer(field, "label", 0, 0) - 1; // LABEL_OPTIONAL = 0+ if (pbc_rmessage_size(field , "options") > 0) {+ struct pbc_rmessage * options = pbc_rmessage_message(field, "options" , 0);+ int packed = pbc_rmessage_integer(options , "packed" , 0 , NULL);+ if (packed) {+ f->label = LABEL_PACKED;+ }+ }+ f->type_name.n = pbc_rmessage_string(field, "type_name", 0 , NULL) +1; // abandon prefix '.' + int vsz;+ const char * default_value = pbc_rmessage_string(field, "default_value", 0 , &vsz);+ _set_default(pool , f , f->type, default_value , vsz);+}++static void+_register_extension(struct pbc_env *p, struct _stringpool *pool , const char * prefix, int prefix_sz, struct pbc_rmessage * msg, pbc_array queue) {+ int extension_count = pbc_rmessage_size(msg , "extension");+ if (extension_count <= 0) + return;+ int i;++ const char * last = NULL;++ for (i=0;i<extension_count;i++) {+ struct pbc_rmessage * extension = pbc_rmessage_message(msg, "extension", i);+ int field_name_sz = 0;+ struct _field f;+ const char * field_name = pbc_rmessage_string(extension , "name" , 0, &field_name_sz);+ f.name = _concat_name(pool, prefix, prefix_sz, field_name, field_name_sz, NULL);++ _register_field(extension, &f , pool);++ const char * extendee = pbc_rmessage_string(extension , "extendee" , 0, NULL);++ _pbcP_push_message(p, extendee + 1 , &f , queue);++ if (last == NULL) {+ last = extendee;+ } else if (strcmp(extendee,last) != 0) {+ _pbcP_init_message(p, last+1);+ last = extendee;+ } + }+ _pbcP_init_message(p, last+1);+}++static void+_register_message(struct pbc_env *p, struct _stringpool *pool, struct pbc_rmessage * message_type, const char *prefix, int prefix_sz, pbc_array queue) {+ int name_sz;+ const char * name = pbc_rmessage_string(message_type, "name", 0 , &name_sz);+ int sz = 0;+ const char *temp = _concat_name(pool, prefix , prefix_sz , name , name_sz, &sz);++ int field_count = pbc_rmessage_size(message_type, "field");+ int i;+ for (i=0;i<field_count;i++) {+ struct pbc_rmessage * field = pbc_rmessage_message(message_type, "field" , i);+ struct _field f;+ int field_name_sz;+ const char * field_name = pbc_rmessage_string(field, "name", 0 , &field_name_sz);+ f.name = _pbcS_build(pool,field_name,field_name_sz);++ _register_field(field, &f , pool);++ _pbcP_push_message(p, temp , &f , queue);+ }++ _pbcP_init_message(p, temp);++ _register_extension(p, pool, temp, sz,message_type, queue);++ // nested enum++ int enum_count = pbc_rmessage_size(message_type, "enum_type");++ for (i=0;i<enum_count;i++) {+ struct pbc_rmessage * enum_type = pbc_rmessage_message(message_type, "enum_type", i);+ _register_enum(p, pool, enum_type, temp, sz);+ }+ + // nested type+ int message_count = pbc_rmessage_size(message_type, "nested_type");+ for (i=0;i<message_count;i++) {+ struct pbc_rmessage * nested_type = pbc_rmessage_message(message_type, "nested_type", i);+ _register_message(p, pool, nested_type, temp, sz, queue);+ }+}++static void+_register(struct pbc_env *p, struct pbc_rmessage * file, struct _stringpool *pool) {+ int package_sz;+ const char *package = pbc_rmessage_string(file, "package", 0, &package_sz);++ pbc_array queue;+ _pbcA_open(queue);++ int enum_count = pbc_rmessage_size(file, "enum_type");+ int i;++ for (i=0;i<enum_count;i++) {+ struct pbc_rmessage * enum_type = pbc_rmessage_message(file, "enum_type", i);+ _register_enum(p, pool , enum_type, package, package_sz);+ }++ int message_count = pbc_rmessage_size(file, "message_type");+ for (i=0;i<message_count;i++) {+ struct pbc_rmessage * message_type = pbc_rmessage_message(file, "message_type", i);+ _register_message(p, pool, message_type, package, package_sz, queue);+ }++ _register_extension(p, pool, package, package_sz, file , queue);++ _pbcB_register_fields(p, queue);++ _pbcA_close(queue);+}++#define CHECK_FILE_OK 0+#define CHECK_FILE_EXIST 1+#define CHECK_FILE_DEPENDENCY 2++static int+_check_file_name(struct pbc_env * p , struct pbc_rmessage * file, const char ** fname) {+ const char * filename = pbc_rmessage_string(file, "name", 0, NULL);+// printf("reg :%s\n",filename);+ if (_pbcM_sp_query(p->files, filename)) {+ return CHECK_FILE_EXIST;+ }+ int sz = pbc_rmessage_size(file, "dependency"); + int i;+ for (i=0;i<sz;i++) {+ const char *dname = pbc_rmessage_string(file,"dependency",i,NULL);+// printf("dependency :%s\n",dname);+ if (_pbcM_sp_query(p->files, dname) == NULL) {+ return CHECK_FILE_DEPENDENCY;+ }+ }++ *fname = filename;++ return CHECK_FILE_OK;+}++static int+_register_no_dependency(struct pbc_env * p,struct pbc_rmessage ** files , int n ) {+ int r = 0;+ int i;+ for (i=0;i<n;i++) {+ if (files[i] == NULL)+ continue;+ const char *filename = NULL;+ int err = _check_file_name(p, files[i], &filename);+ switch(err) {+ case CHECK_FILE_EXIST:+ break;+ case CHECK_FILE_DEPENDENCY:+ ++r;+ break;+ case CHECK_FILE_OK: {+ struct _stringpool *pool = _pbcS_new();+ filename = _pbcS_build(pool, filename , strlen(filename));+ _pbcM_sp_insert(p->files , filename, pool);+ _register(p,files[i],pool);+ files[i] = NULL;+ }+ break;+ }+ }+ return r;+}++int+pbc_register(struct pbc_env * p, struct pbc_slice *slice) {+ struct pbc_rmessage * message = pbc_rmessage_new(p, "google.protobuf.FileDescriptorSet", slice);+ if (message == NULL) {+ p->lasterror = "register open google.protobuf.FileDescriptorSet fail";+ return 1;+ }+ int n = pbc_rmessage_size(message, "file");+ struct pbc_rmessage ** files = (struct pbc_rmessage **)alloca(n * sizeof(struct pbc_rmessage *));+ int i;+ if (n == 0) {+ p->lasterror = "register empty";+ goto _error;+ }+ for (i=0;i<n;i++) {+ files[i] = pbc_rmessage_message(message, "file", i);+ if (files[i] == NULL) {+ p->lasterror = "register open fail";+ goto _error;+ }+ }++ int r = n;+ do {+ int rr = _register_no_dependency(p,files , n);+ if (rr == r) {+ p->lasterror = "register dependency error";+ goto _error;+ }+ r = rr;+ } while (r>0);++ pbc_rmessage_delete(message);+ return 0;+_error:+ pbc_rmessage_delete(message);+ return 1;+}
+ cbits/rmessage.c view
@@ -0,0 +1,455 @@+#include "pbc.h"+#include "alloc.h"+#include "map.h"+#include "context.h"+#include "proto.h"+#include "pattern.h"+#include "varint.h"++#include <stddef.h>+#include <string.h>++struct pbc_rmessage {+ struct _message * msg;+ struct map_sp * index; // key -> struct value *+ struct heap * heap;+};++union _var {+ pbc_var var;+ pbc_array array;+ struct pbc_rmessage message;+} ;++struct value {+ struct _field * type;+ union _var v;+};++int +pbc_rmessage_next(struct pbc_rmessage *m, const char **key) {+ struct value * v = (struct value *)_pbcM_sp_next(m->index, key);+ if (*key == NULL) {+ return 0;+ }+ return _pbcP_type(v->type, NULL);+}++#define SIZE_VAR (offsetof(struct value, v) + sizeof(pbc_var))+#define SIZE_ARRAY (offsetof(struct value, v) + sizeof(pbc_array))+#define SIZE_MESSAGE (offsetof(struct value, v) + sizeof(struct pbc_rmessage))++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 = (struct value *)_pbcH_alloc(h, SIZE_VAR);+ v->v.var->s.str = temp;+ v->v.var->s.len = len;+ return v;+ } else {+ struct value * v = (struct value *)_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 = (char *)_pbcH_alloc(h, len + 1);+ memcpy(temp2, temp, len);+ temp2[len]='\0';+ var->s.str = temp2;+ var->s.len = -len;+ }+}++static void _pbc_rmessage_new(struct pbc_rmessage * ret , struct _message * type , void *buffer, int size, struct heap *h);++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 = (struct value *)_pbcH_alloc(h, SIZE_VAR);+ v->v.var->real = read_double(a);+ break;+ case PTYPE_FLOAT:+ CHECK_BIT32(a,NULL);+ v = (struct value *)_pbcH_alloc(h, SIZE_VAR);+ v->v.var->real = (double) read_float(a);+ break;+ case PTYPE_ENUM:+ CHECK_VARINT(a,NULL);+ v = (struct value *)_pbcH_alloc(h, SIZE_VAR);+ v->v.var->e.id = a->v.i.low;+ v->v.var->e.name = (const char *)_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 = (struct value *)_pbcH_alloc(h, SIZE_VAR);+ v->v.var->integer = a->v.i;+ break;+ case PTYPE_FIXED32:+ case PTYPE_SFIXED32:+ CHECK_BIT32(a,NULL);+ v = (struct value *)_pbcH_alloc(h, SIZE_VAR);+ v->v.var->integer = a->v.i;+ break;+ case PTYPE_FIXED64:+ case PTYPE_SFIXED64:+ CHECK_BIT64(a,NULL);+ v = (struct value *)_pbcH_alloc(h, SIZE_VAR);+ v->v.var->integer = a->v.i;+ break;+ case PTYPE_SINT32: + CHECK_VARINT(a,NULL);+ v = (struct value *)_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 = (struct value *)_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 = (struct value *)_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 = (struct value *)_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+push_value_packed(struct _message * type, 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+ type->env->lasterror = "Unpack packed field error";+ return;+ }+ if (f->type == PTYPE_ENUM) {+ int i;+ for (i=0;i<n;i++) {+ union _pbc_var * v = (union _pbc_var *)_pbcA_index_p(array, i);+ int id = v->integer.low;+ v->e.id = id;+ v->e.name = (const char*)_pbcM_ip_query(f->type_name.e->id , id);+ }+ }+}++static void+push_value_array(struct heap *h, 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 = (const char *)_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;+ _pbcV_dezigzag32(&(v->integer));+ break;+ case PTYPE_SINT64:+ v->integer = a->v.i;+ _pbcV_dezigzag64(&(v->integer));+ break;+ case PTYPE_STRING:+ CHECK_LEND(a, );+ read_string_var(h,v,a,f,buffer);+ break;+ case PTYPE_BYTES:+ CHECK_LEND(a, );+ 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: {+ CHECK_LEND(a, );+ 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,h);+ 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 , 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 = (struct _field *)_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 = (struct value *)_pbcH_alloc(h, SIZE_ARRAY);+ v->type = f;+ _pbcA_open_heap(v->v.array,ret->heap);+ *vv = v;+ } else {+ v= (struct value *)*vv;+ }+ if (f->label == LABEL_PACKED) {+ push_value_packed(type, v->v.array , f , &(ctx->a[i]), (uint8_t *)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]), (uint8_t *)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]), (uint8_t *)buffer);+ if (v) {+ _pbcM_sp_insert(ret->index, f->name, v);+ } else {+ type->env->lasterror = "rmessage decode data error";+ }+ }+ }+ }++ _pbcC_close(_ctx);+}++struct pbc_rmessage * +pbc_rmessage_new(struct pbc_env * env, const char * type_name , struct pbc_slice * slice) {+ struct _message * msg = _pbcP_get_message(env, type_name);+ if (msg == NULL) {+ env->lasterror = "Proto not found";+ return NULL;+ }+ struct pbc_rmessage temp;+ struct heap * h = _pbcH_new(slice->len);+ _pbc_rmessage_new(&temp, msg , slice->buffer, slice->len , h);+ if (temp.msg == NULL) {+ _pbcH_delete(h);+ return NULL;+ }++ struct pbc_rmessage *m = (struct pbc_rmessage *)_pbcH_alloc(temp.heap, sizeof(*m));+ *m = temp;+ return m;+}++void +pbc_rmessage_delete(struct pbc_rmessage * m) {+ if (m) {+ _pbcH_delete(m->heap);+ }+}++const char * +pbc_rmessage_string(struct pbc_rmessage * m , const char *key , int index, int *sz) {+ struct value * v = (struct value *)_pbcM_sp_query(m->index,key);+ int type = 0;+ pbc_var var;+ if (v == NULL) {+ type = _pbcP_message_default(m->msg, key, var);+ } else {+ if (v->type->label == LABEL_REPEATED || v->type->label == LABEL_PACKED) {+ _pbcA_index(v->v.array, index, var);+ } else {+ var[0] = v->v.var[0];+ }+ type = v->type->type;+ }++ if (type == PTYPE_ENUM) {+ if (sz) {+ *sz = strlen(var->e.name);+ }+ return var->e.name;+ }++ if (sz) {+ int len = var->s.len;+ if (len<0) {+ len = - len;+ }+ *sz = len;+ }+ return var->s.str;+}++uint32_t +pbc_rmessage_integer(struct pbc_rmessage *m , const char *key , int index, uint32_t *hi) {+ struct value * v = (struct value *)_pbcM_sp_query(m->index,key);+ pbc_var var;+ int type = 0;+ if (v == NULL) {+ type = _pbcP_message_default(m->msg, key, var);+ } else {+ if (v->type->label == LABEL_REPEATED || v->type->label == LABEL_PACKED) {+ _pbcA_index(v->v.array, index, var);+ } else {+ var[0] = v->v.var[0];+ }+ type = v->type->type;+ }++ if (type == PTYPE_ENUM) {+ if (hi) {+ *hi = 0;+ }+ return var->e.id;+ }++ if (hi) {+ *hi = var->integer.hi;+ }+ return var->integer.low;+}++double +pbc_rmessage_real(struct pbc_rmessage * m, const char *key , int index) {+ struct value * v = (struct value *)_pbcM_sp_query(m->index,key);+ pbc_var var;+ if (v == NULL) {+ _pbcP_message_default(m->msg, key, var);+ } else {+ if (v->type->label == LABEL_REPEATED || v->type->label == LABEL_PACKED) {+ _pbcA_index(v->v.array, index, var);+ } else {+ return v->v.var->real;+ }+ }+ return var->real;+}+++struct pbc_rmessage * +pbc_rmessage_message(struct pbc_rmessage * rm, const char *key, int index) {+ struct value * v = (struct value *)_pbcM_sp_query(rm->index,key);+ if (v == NULL) {+ struct _field * f = (struct _field *)_pbcM_sp_query(rm->msg->name, key);+ if (f == NULL) {+ rm->msg->env->lasterror = "Invalid key for sub-message";+ // invalid key+ return NULL;+ }+ struct _message * m = f->type_name.m;++ if (m->def == NULL) {+ // m->def will be free at the end (pbc_delete).+ m->def = (struct pbc_rmessage *)malloc(sizeof(struct pbc_rmessage));+ m->def->msg = m;+ m->def->index = NULL;+ }+ return m->def;+ } else {+ if (v->type->label == LABEL_REPEATED) {+ return (struct pbc_rmessage *)_pbcA_index_p(v->v.array,index);+ } else {+ return &(v->v.message);+ }+ }+}++int +pbc_rmessage_size(struct pbc_rmessage *m, const char *key) {+ struct value * v = (struct value *)_pbcM_sp_query(m->index,key);+ if (v == NULL) {+ return 0;+ }+ if (v->type->label == LABEL_REPEATED || v->type->label == LABEL_PACKED) {+ return pbc_array_size(v->v.array);+ } else {+ return 1;+ }+}
+ cbits/stringpool.c view
@@ -0,0 +1,60 @@+#include "alloc.h"++#include <stdlib.h>+#include <string.h>++#define PAGE_SIZE 256++struct _stringpool {+ char * buffer;+ size_t len;+ struct _stringpool *next;+};++struct _stringpool * +_pbcS_new(void) {+ struct _stringpool * ret = (struct _stringpool *)malloc(sizeof(struct _stringpool) + PAGE_SIZE);+ ret->buffer = (char *)(ret + 1);+ ret->len = 0;+ ret->next = NULL;+ return ret;+}++void +_pbcS_delete(struct _stringpool *pool) {+ while(pool) {+ struct _stringpool *next = pool->next;+ free(pool);+ pool = next;+ }+}++const char *+_pbcS_build(struct _stringpool *pool, const char * str , int sz) {+ size_t s = sz + 1;+ if (s < PAGE_SIZE - pool->len) {+ char * ret = pool->buffer + pool->len;+ memcpy(pool->buffer + pool->len, str, s);+ pool->len += s;+ return ret;+ }+ if (s > PAGE_SIZE) {+ struct _stringpool * next = (struct _stringpool *)malloc(sizeof(struct _stringpool) + s);+ next->buffer = (char *)(next + 1);+ memcpy(next->buffer, str, s);+ next->len = s;+ next->next = pool->next;+ pool->next = next;+ return next->buffer;+ }+ struct _stringpool *next = (struct _stringpool *)malloc(sizeof(struct _stringpool) + PAGE_SIZE);+ next->buffer = pool->buffer;+ next->next = pool->next;+ next->len = pool->len;++ pool->next = next;+ pool->buffer = (char *)(next + 1);+ memcpy(pool->buffer, str, s);+ pool->len = s;+ return pool->buffer;+}
+ cbits/stringpool.h view
@@ -0,0 +1,10 @@+#ifndef PROTOBUF_C_STRINGPOOL_H+#define PROTOBUF_C_STRINGPOOL_H++struct _stringpool;++struct _stringpool * _pbcS_new(void);+void _pbcS_delete(struct _stringpool *pool);+const char * _pbcS_build(struct _stringpool *pool, const char * str , int sz);++#endif
+ cbits/varint.c view
@@ -0,0 +1,110 @@+#include "varint.h"++#include "pbc.h"++#include <stdint.h>++inline int+_pbcV_encode32(uint32_t number, uint8_t buffer[10])+{+ if (number < 0x80) {+ buffer[0] = (uint8_t) number ; + return 1;+ }+ buffer[0] = (uint8_t) (number | 0x80 );+ if (number < 0x4000) {+ buffer[1] = (uint8_t) (number >> 7 );+ return 2;+ }+ buffer[1] = (uint8_t) ((number >> 7) | 0x80 );+ if (number < 0x200000) {+ buffer[2] = (uint8_t) (number >> 14);+ return 3;+ }+ buffer[2] = (uint8_t) ((number >> 14) | 0x80 );+ if (number < 0x10000000) {+ buffer[3] = (uint8_t) (number >> 21);+ return 4;+ }+ buffer[3] = (uint8_t) ((number >> 21) | 0x80 );+ buffer[4] = (uint8_t) (number >> 28);+ return 5;+}++int+_pbcV_encode(uint64_t number, uint8_t buffer[10]) +{+ if ((number & 0xffffffff) == number) {+ return _pbcV_encode32((uint32_t)number , buffer);+ }+ int i = 0;+ do {+ buffer[i] = (uint8_t)(number | 0x80);+ number >>= 7;+ ++i;+ } while (number >= 0x80);+ buffer[i] = (uint8_t)number;+ return i+1;+}++int+_pbcV_decode(uint8_t buffer[10], struct longlong *result) {+ if (!(buffer[0] & 0x80)) {+ result->low = buffer[0];+ result->hi = 0;+ return 1;+ }+ uint32_t r = buffer[0] & 0x7f;+ int i;+ for (i=1;i<4;i++) {+ r |= ((buffer[i]&0x7f) << (7*i));+ if (!(buffer[i] & 0x80)) {+ result->low = r;+ result->hi = 0;+ return i+1;+ }+ }+ uint64_t lr = 0;+ for (i=4;i<10;i++) {+ lr |= ((uint64_t)(buffer[i] & 0x7f) << (7*(i-4)));+ if (!(buffer[i] & 0x80)) {+ result->hi = (uint32_t)(lr >> 4);+ result->low = r | (((uint32_t)lr & 0xf) << 28);+ return i+1;+ }+ }++ result->low = 0;+ result->hi = 0;+ return 10;+}++int +_pbcV_zigzag32(int32_t n, uint8_t buffer[10])+{+ n = (n << 1) ^ (n >> 31);+ return _pbcV_encode32(n,buffer);+}++int +_pbcV_zigzag(int64_t n, uint8_t buffer[10])+{+ n = (n << 1) ^ (n >> 63);+ return _pbcV_encode(n,buffer);+}++void+_pbcV_dezigzag64(struct longlong *r)+{+ uint32_t low = r->low;+ r->low = ((low >> 1) | ((r->hi & 1) << 31)) ^ - (low & 1);+ r->hi = (r->hi >> 1) ^ - (low & 1);+}++void+_pbcV_dezigzag32(struct longlong *r)+{+ uint32_t low = r->low;+ r->low = (low >> 1) ^ - (low & 1);+ r->hi = -(low >> 31);+}
+ cbits/varint.h view
@@ -0,0 +1,20 @@+#ifndef PROTOBUF_C_VARINT_H+#define PROTOBUF_C_VARINT_H++#include <stdint.h>++struct longlong {+ uint32_t low;+ uint32_t hi;+};++int _pbcV_encode32(uint32_t number, uint8_t buffer[10]);+int _pbcV_encode(uint64_t number, uint8_t buffer[10]);+int _pbcV_zigzag32(int32_t number, uint8_t buffer[10]);+int _pbcV_zigzag(int64_t number, uint8_t buffer[10]);++int _pbcV_decode(uint8_t buffer[10], struct longlong *result);+void _pbcV_dezigzag64(struct longlong *r);+void _pbcV_dezigzag32(struct longlong *r);++#endif
+ cbits/wmessage.c view
@@ -0,0 +1,516 @@+#include "pbc.h"+#include "context.h"+#include "alloc.h"+#include "varint.h"+#include "map.h"+#include "proto.h"++#include <stdint.h>+#include <string.h>+#include <assert.h>++#ifndef _MSC_VER+#include <stdbool.h>+#endif++#define WMESSAGE_SIZE 64++struct pbc_wmessage {+ struct _message *type;+ uint8_t * buffer;+ uint8_t * ptr;+ uint8_t * endptr;+ pbc_array sub;+ struct map_sp *packed;+ struct heap * heap;+};++struct _packed {+ int id;+ int ptype;+ pbc_array data;+};++static struct pbc_wmessage *+_wmessage_new(struct heap *h, struct _message *msg) {+ struct pbc_wmessage * m = (struct pbc_wmessage *)_pbcH_alloc(h, sizeof(*m));+ m->type = msg;+ m->buffer = (uint8_t *)_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;+}++struct pbc_wmessage * +pbc_wmessage_new(struct pbc_env * env, const char *type_name) {+ struct _message * msg = _pbcP_get_message(env, type_name);+ if (msg == NULL)+ return NULL;+ struct heap *h = _pbcH_new(0);+ return _wmessage_new(h, msg);+}++void +pbc_wmessage_delete(struct pbc_wmessage *m) {+ if (m) {+ _pbcH_delete(m->heap);+ }+}++static void+_expand_message(struct pbc_wmessage *m, int sz) {+ if (m->ptr + sz > m->endptr) {+ int cap = m->endptr - m->buffer;+ sz = m->ptr + sz - m->buffer;+ do {+ cap = cap * 2;+ } while ( sz > cap ) ;+ int old_size = m->ptr - m->buffer;+ uint8_t * buffer = (uint8_t *)_pbcH_alloc(m->heap, cap);+ memcpy(buffer, m->buffer, old_size);+ m->ptr = buffer + (m->ptr - m->buffer);+ m->endptr = buffer + cap;+ m->buffer = buffer;+ }+}++static struct _packed *+_get_packed(struct pbc_wmessage *m , struct _field *f , const char *key) {+ if (m->packed == NULL) {+ m->packed = _pbcM_sp_new(4, m->heap);+ }+ void ** v = _pbcM_sp_query_insert(m->packed , key);+ if (*v == NULL) {+ *v = _pbcH_alloc(m->heap, sizeof(struct _packed));+ struct _packed *p = (struct _packed *)*v;+ p->id = f->id;+ p->ptype = f->type;+ _pbcA_open_heap(p->data, m->heap);+ return p;+ }+ return (struct _packed *)*v;+}++static void+_packed_integer(struct pbc_wmessage *m, struct _field *f, const char *key , uint32_t low, uint32_t hi) {+ struct _packed * packed = _get_packed(m,f,key);+ pbc_var var;+ var->integer.low = low;+ var->integer.hi = hi;+ _pbcA_push(packed->data , var);+}++static void+_packed_real(struct pbc_wmessage *m, struct _field *f, const char *key , double v) {+ struct _packed * packed = _get_packed(m,f,key);+ pbc_var var;+ var->real = v;+ _pbcA_push(packed->data , var);+}++static inline void+int64_encode(uint32_t low, uint32_t hi , uint8_t * buffer) {+ buffer[0] = (uint8_t)(low & 0xff);+ buffer[1] = (uint8_t)(low >> 8 & 0xff);+ buffer[2] = (uint8_t)(low >> 16 & 0xff);+ buffer[3] = (uint8_t)(low >> 24 & 0xff);+ buffer[4] = (uint8_t)(hi & 0xff);+ buffer[5] = (uint8_t)(hi >> 8 & 0xff);+ buffer[6] = (uint8_t)(hi >> 16 & 0xff);+ buffer[7] = (uint8_t)(hi >> 24 & 0xff);+}++static inline void+int32_encode(uint32_t low, uint8_t * buffer) {+ buffer[0] = (uint8_t)(low & 0xff);+ buffer[1] = (uint8_t)(low >> 8 & 0xff);+ buffer[2] = (uint8_t)(low >> 16 & 0xff);+ buffer[3] = (uint8_t)(low >> 24 & 0xff);+}++int +pbc_wmessage_integer(struct pbc_wmessage *m, const char *key, uint32_t low, uint32_t hi) {+ struct _field * f = (struct _field *)_pbcM_sp_query(m->type->name,key);+ if (f==NULL) {+ // todo : error+ m->type->env->lasterror = "wmessage_interger query key error";+ return -1;+ }+ if (f->label == LABEL_PACKED) {+ _packed_integer(m , f, key , low, hi);+ return 0; + }+ if (f->label == LABEL_OPTIONAL) {+ if (f->type == PTYPE_ENUM) {+ if (low == f->default_v->e.id)+ return 0;+ } else {+ if (low == f->default_v->integer.low &&+ hi == f->default_v->integer.hi) {+ return 0;+ }+ }+ }+ int id = f->id << 3;++ _expand_message(m,20);+ switch (f->type) {+ case PTYPE_INT64:+ case PTYPE_UINT64: + case PTYPE_INT32:+ id |= WT_VARINT;+ m->ptr += _pbcV_encode32(id, m->ptr);+ m->ptr += _pbcV_encode((uint64_t)low | (uint64_t)hi << 32 , m->ptr);+ break;+ case PTYPE_UINT32:+ case PTYPE_ENUM:+ case PTYPE_BOOL:+ id |= WT_VARINT;+ m->ptr += _pbcV_encode32(id, m->ptr);+ m->ptr += _pbcV_encode32(low, m->ptr);+ break;+ case PTYPE_FIXED64:+ case PTYPE_SFIXED64:+ id |= WT_BIT64;+ m->ptr += _pbcV_encode32(id, m->ptr);+ int64_encode(low,hi,m->ptr);+ m->ptr += 8;+ break;+ case PTYPE_FIXED32:+ case PTYPE_SFIXED32:+ id |= WT_BIT32;+ m->ptr += _pbcV_encode32(id, m->ptr);+ int32_encode(low,m->ptr);+ m->ptr += 4;+ break;+ case PTYPE_SINT32:+ id |= WT_VARINT;+ m->ptr += _pbcV_encode32(id, m->ptr);+ m->ptr += _pbcV_zigzag32(low, m->ptr);+ break;+ case PTYPE_SINT64:+ id |= WT_VARINT;+ m->ptr += _pbcV_encode32(id, m->ptr);+ m->ptr += _pbcV_zigzag((uint64_t)low | (uint64_t)hi << 32 , m->ptr);+ break;+ }++ return 0;+}++int+pbc_wmessage_real(struct pbc_wmessage *m, const char *key, double v) {+ struct _field * f = (struct _field *)_pbcM_sp_query(m->type->name,key);+ if (f == NULL) {+ // todo : error+ m->type->env->lasterror = "wmessage_real query key error";+ return -1;+ }+ if (f->label == LABEL_PACKED) {+ _packed_real(m , f, key , v);+ return 0; + }++ if (f->label == LABEL_OPTIONAL) {+ if (v == f->default_v->real)+ return 0;+ }+ int id = f->id << 3;+ _expand_message(m,18);+ switch (f->type) {+ case PTYPE_FLOAT: {+ id |= WT_BIT32;+ m->ptr += _pbcV_encode32(id, m->ptr);+ float_encode(v , m->ptr);+ m->ptr += 4;+ break;+ }+ case PTYPE_DOUBLE:+ id |= WT_BIT64;+ m->ptr += _pbcV_encode32(id, m->ptr);+ double_encode(v , m->ptr);+ m->ptr += 8;+ break;+ }++ return 0;+}++int+pbc_wmessage_string(struct pbc_wmessage *m, const char *key, const char * v, int len) {+ struct _field * f = (struct _field *)_pbcM_sp_query(m->type->name,key);+ if (f == NULL) {+ // todo : error+ m->type->env->lasterror = "wmessage_string query key error";+ return -1;+ }++ bool varlen = false;++ if (len <=0) {+ varlen = true;+ // -1 for add '\0'+ len = strlen(v) - len;+ }+ if (f->label == LABEL_PACKED) {+ if (f->type == PTYPE_ENUM) {+ char * temp = (char *)alloca(len + 1);+ if (!varlen || v[len] != '\0') {+ memcpy(temp,v,len);+ temp[len]='\0';+ v = temp;+ }+ int enum_id = 0;+ int err = _pbcM_si_query(f->type_name.e->name, v , &enum_id);+ if (err) {+ // todo : error , invalid enum+ m->type->env->lasterror = "wmessage_string packed invalid enum";+ free(temp);+ return -1;+ }+ _packed_integer(m , f, key , enum_id , 0);+ }+ return 0; + }++ if (f->label == LABEL_OPTIONAL) {+ if (f->type == PTYPE_ENUM) {+ if (strncmp(v , f->default_v->e.name, len) == 0 && f->default_v->e.name[len] =='\0') {+ return 0;+ }+ } else if (f->type == PTYPE_STRING) {+ if (len == f->default_v->s.len &&+ strcmp(v, f->default_v->s.str) == 0) {+ return 0;+ }+ }+ }+ int id = f->id << 3;+ _expand_message(m,20);+ switch (f->type) {+ case PTYPE_ENUM : {+ char * temp = (char *)malloc(len+1);+ if (!varlen || v[len] != '\0') {+ memcpy(temp,v,len);+ temp[len]='\0';+ v = temp;+ }+ int enum_id = 0;+ int err = _pbcM_si_query(f->type_name.e->name, v, &enum_id);+ if (err) {+ // todo : error , enum invalid+ m->type->env->lasterror = "wmessage_string invalid enum";+ free(temp);+ return -1;+ }+ id |= WT_VARINT;+ m->ptr += _pbcV_encode32(id, m->ptr);+ m->ptr += _pbcV_encode32(enum_id, m->ptr);+ break;+ }+ case PTYPE_STRING:+ case PTYPE_BYTES:+ id |= WT_LEND;+ m->ptr += _pbcV_encode32(id, m->ptr);+ m->ptr += _pbcV_encode32(len, m->ptr);+ _expand_message(m,len);+ memcpy(m->ptr , v , len);+ m->ptr += len;+ break;+ }++ return 0;+}++struct pbc_wmessage * +pbc_wmessage_message(struct pbc_wmessage *m, const char *key) {+ struct _field * f = (struct _field *)_pbcM_sp_query(m->type->name,key);+ if (f == NULL) {+ // todo : error+ m->type->env->lasterror = "wmessage_message query key error";+ return NULL;+ }+ pbc_var var;+ var->p[0] = _wmessage_new(m->heap, f->type_name.m);+ var->p[1] = f;+ _pbcA_push(m->sub , var);+ return (struct pbc_wmessage *)var->p[0];+}++static void+_pack_packed_64(struct _packed *p,struct pbc_wmessage *m) {+ int n = pbc_array_size(p->data);+ int len = n * 8;+ int i;+ pbc_var var;+ _expand_message(m,10 + len);+ m->ptr += _pbcV_encode32(len, m->ptr);+ switch (p->ptype) {+ case PTYPE_DOUBLE:+ for (i=0;i<n;i++) {+ _pbcA_index(p->data, i, var);+ double_encode(var->real , m->ptr + i * 8);+ }+ break;+ default:+ for (i=0;i<n;i++) {+ _pbcA_index(p->data, i, var);+ int64_encode(var->integer.low , var->integer.hi, m->ptr + i * 8);+ }+ break;+ }+ m->ptr += len;+}++static void+_pack_packed_32(struct _packed *p,struct pbc_wmessage *m) {+ int n = pbc_array_size(p->data);+ int len = n * 4;+ int i;+ pbc_var var;+ _expand_message(m,10 + len);+ m->ptr += _pbcV_encode32(len, m->ptr);+ switch (p->ptype) {+ case PTYPE_FLOAT:+ for (i=0;i<n;i++) {+ _pbcA_index(p->data, i, var);+ float_encode(var->real , m->ptr + i * 8);+ }+ break;+ default:+ for (i=0;i<n;i++) {+ _pbcA_index(p->data, i, var);+ int32_encode(var->integer.low , m->ptr + i * 8);+ }+ break;+ }+ m->ptr += len;+}++static void+_pack_packed_varint(struct _packed *p,struct pbc_wmessage *m) {+ int n = pbc_array_size(p->data);++ int offset = m->ptr - m->buffer;+ int len = n * 2;+ if (p->ptype == PTYPE_BOOL) {+ len = n;+ }+ int i;+ pbc_var var;+ _expand_message(m,10 + len);+ int len_len = _pbcV_encode32(len, m->ptr);+ m->ptr += len_len;++ switch (p->ptype) {+ case PTYPE_INT64:+ case PTYPE_UINT64:+ for (i=0;i<n;i++) {+ _pbcA_index(p->data, i, var);+ _expand_message(m,10);+ m->ptr += _pbcV_encode((uint64_t)var->integer.low | (uint64_t)var->integer.hi << 32 , m->ptr);+ }+ break;+ case PTYPE_INT32:+ case PTYPE_BOOL:+ case PTYPE_UINT32:+ case PTYPE_ENUM:+ for (i=0;i<n;i++) {+ _pbcA_index(p->data, i, var);+ _expand_message(m,10);+ m->ptr += _pbcV_encode32(var->integer.low , m->ptr);+ }+ break;+ case PTYPE_SINT32:+ for (i=0;i<n;i++) {+ _pbcA_index(p->data, i, var);+ _expand_message(m,10);+ m->ptr += _pbcV_zigzag32(var->integer.low, m->ptr);+ }+ break;+ case PTYPE_SINT64:+ for (i=0;i<n;i++) {+ _pbcA_index(p->data, i, var);+ _expand_message(m,10);+ m->ptr += _pbcV_zigzag((uint64_t)var->integer.low | (uint64_t)var->integer.hi << 32 , m->ptr);+ }+ break;+ default:+ // error+ memset(m->ptr , 0 , n);+ m->ptr += n;+ m->type->env->lasterror = "wmessage type error when pack packed";+ break;+ }+ int end_offset = m->ptr - m->buffer;+ int end_len = end_offset - (offset + len_len);+ if (end_len != len) {+ uint8_t temp[10];+ int end_len_len = _pbcV_encode32(end_len, temp);+ if (end_len_len != len_len) {+ _expand_message(m, end_len_len);+ memmove(m->buffer + offset + end_len_len , + m->buffer + offset + len_len , + end_len);+ m->ptr += end_len_len - len_len;+ }+ memcpy(m->buffer + offset , temp, end_len_len);+ }+}++static void+_pack_packed(void *p, void *ud) {+ struct _packed *packed = (struct _packed *)p;+ struct pbc_wmessage * m = (struct pbc_wmessage *)ud;+ int id = packed->id << 3 | WT_LEND;+ _expand_message(m,10);+ m->ptr += _pbcV_encode32(id, m->ptr);+ switch(packed->ptype) {+ case PTYPE_DOUBLE:+ case PTYPE_FIXED64:+ case PTYPE_SFIXED64:+ _pack_packed_64(packed,m);+ break;+ case PTYPE_FLOAT:+ case PTYPE_FIXED32:+ case PTYPE_SFIXED32:+ _pack_packed_32(packed,m);+ break;+ default:+ _pack_packed_varint(packed,m);+ break;+ }+}++void * +pbc_wmessage_buffer(struct pbc_wmessage *m, struct pbc_slice *slice) {+ if (m->packed) {+ _pbcM_sp_foreach_ud(m->packed , _pack_packed, m);+ }+ int i;+ int n = pbc_array_size(m->sub);+ for (i=0;i<n;i++) {+ pbc_var var;+ _pbcA_index(m->sub, i , var);+ struct pbc_slice s;+ pbc_wmessage_buffer((struct pbc_wmessage *)var->p[0] , &s);+ if (s.buffer) {+ struct _field * f = (struct _field *)var->p[1];+ int id = f->id << 3 | WT_LEND;+ _expand_message(m,20+s.len);+ m->ptr += _pbcV_encode32(id, m->ptr);+ m->ptr += _pbcV_encode32(s.len, m->ptr);+ memcpy(m->ptr, s.buffer, s.len);+ m->ptr += s.len;+ }+ }+ slice->buffer = m->buffer;+ slice->len = m->ptr - m->buffer;++ return m->buffer;+}+
+ pbc4hs.cabal view
@@ -0,0 +1,47 @@+name: pbc4hs+version: 0.1.0.0+synopsis: pbc for HsLua+description: pbc wrapper for HsLua+license: BSD3+license-file: LICENSE+author: david feng+maintainer: davidxifeng@gmail.com+category: System+build-type: Simple+cabal-version: >=1.10++extra-source-files: cbits/alloc.h+ cbits/array.h+ cbits/bootstrap.h+ cbits/context.h+ cbits/descriptor.pbc.h+ cbits/map.h+ cbits/pattern.h+ cbits/pbc.h+ cbits/proto.h+ cbits/stringpool.h+ cbits/varint.h++library+ exposed-modules: Scripting.Lua.Pbc+ other-extensions: ForeignFunctionInterface+ build-depends: base >=4.6 && <4.7, hslua >=0.3 && <0.4+ hs-source-dirs: src+ default-language: Haskell2010++ include-dirs: cbits+ c-sources: cbits/alloc.c+ cbits/array.c+ cbits/bootstrap.c+ cbits/context.c+ cbits/decode.c+ cbits/map.c+ cbits/pattern.c+ cbits/proto.c+ cbits/register.c+ cbits/rmessage.c+ cbits/stringpool.c+ cbits/varint.c+ cbits/wmessage.c+ cbits/pbc-lua.c+ cc-options: -Wall
+ src/Scripting/Lua/Pbc.hs view
@@ -0,0 +1,16 @@+{-# LANGUAGE ForeignFunctionInterface #-}++-- | pbc library wrapper, useful when sometimes require from dylib doesn't+-- work well+module Scripting.Lua.Pbc ( -- ** functions+ openPbc+ ) where++import Scripting.Lua++foreign import ccall "luaopen_protobuf_c" c_luaopen_pbc :: LuaState -> IO ()++-- | open pbc Lua library+openPbc :: LuaState -> IO ()+openPbc = c_luaopen_pbc+