add some lua library

This commit is contained in:
云风
2012-08-09 16:48:28 +08:00
parent d246152ca5
commit 4e50079706
47 changed files with 13562 additions and 0 deletions

14
lua-protobuf/Makefile Normal file
View File

@@ -0,0 +1,14 @@
.PHONY : all clean
all : protobuf.so addressbook.pb
LIBSRCS = context.c varint.c array.c pattern.c register.c proto.c map.c alloc.c rmessage.c wmessage.c bootstrap.c stringpool.c decode.c
protobuf.so : pbc-lua.c $(LIBSRCS)
gcc -O2 -Wall --shared -fPIC -o $@ $^
addressbook.pb : addressbook.proto
protoc -o$@ $<
clean :
rm protobuf.so addressbook.pb

2
lua-protobuf/README Normal file
View File

@@ -0,0 +1,2 @@
See https://github.com/cloudwu/pbc

View File

@@ -0,0 +1,39 @@
// See README.txt for information and build instructions.
package tutorial;
option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 id = 2; // Unique ID number for this person.
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
repeated int32 test = 5 [packed=true];
extensions 10 to max;
}
message Ext {
extend Person {
optional int32 test = 10;
}
}
// Our address book file is just one of these.
message AddressBook {
repeated Person person = 1;
}

84
lua-protobuf/alloc.c Normal file
View File

@@ -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 = _pbcM_malloc(sizeof(struct heap));
h->current = _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 = _pbcM_malloc(sizeof(struct heap_page) + h->size);
} else {
p = _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;
}
}

25
lua-protobuf/alloc.h Normal file
View File

@@ -0,0 +1,25 @@
#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
#endif

139
lua-protobuf/array.c Normal file
View File

@@ -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 = 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 = _pbcH_alloc(h, sizeof(union _pbc_var) * (size+1) * 2);
memcpy(a->a, old, sizeof(union _pbc_var) * size);
} else {
a->a=_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);
}

31
lua-protobuf/array.h Normal file
View File

@@ -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

303
lua-protobuf/bootstrap.c Normal file
View File

@@ -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 = 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 = field.name.buffer;
f.type = field.type;
f.label = field.label;
f.type_name.n = 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 = _pbcM_sp_query(p->msgs, type_name);
// printf("MESSAGE: %s %p\n",type_name, f->type_name.m);
} else if (f->type == PTYPE_ENUM) {
f->type_name.e = _pbcM_sp_query(p->enums, type_name);
// printf("ENUM: %s %p ",type_name, f->type_name.e);
const char * str = f->default_v->s.str;
if (str && 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 = _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 = 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 , 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);
}

10
lua-protobuf/bootstrap.h Normal file
View File

@@ -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

278
lua-protobuf/context.c Normal file
View File

@@ -0,0 +1,278 @@
#include "pbc.h"
#include "alloc.h"
#include "varint.h"
#include "context.h"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#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 = malloc(cap * sizeof(struct atom));
while (size > 0) {
if (i >= cap) {
cap = cap + 64;
ctx->a = 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 = 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 , 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 = malloc(ctx->number * sizeof(struct atom));
a = ctx->a;
} else {
ctx->a = a;
}
int i;
if (bits == 64) {
uint8_t * data = 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 = 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 = 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(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 = malloc(cap * sizeof(struct atom));
while (size > 0) {
if (i >= cap) {
cap = cap + 64;
ctx->a = realloc(ctx->a, cap * sizeof(struct atom));
continue;
}
char * next = wiretype_decode(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;
}
}

140
lua-protobuf/context.h Normal file
View File

@@ -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

349
lua-protobuf/decode.c Normal file
View File

@@ -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) {
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 * typename = NULL;
int type = _pbcP_type(f, &typename);
assert(type != 0);
if (typename == NULL) {
typename = 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 = _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, typename, &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 * typename = NULL;
int type = _pbcP_type(f, &typename);
assert(type != 0);
if (typename == NULL) {
typename = 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 , typename, &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 , typename, &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 , typename, &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 , typename, &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 , typename, &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 = _pbcM_ip_query(f->type_name.e->id , v.i.low);
pd(ud, type , typename, &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 , typename, &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 , typename, &v, f->id, f->name);
buffer += len;
size -= len;
++n;
}
return n;
}
default:
return -1;
}
}
int
pbc_decode(struct pbc_env * env, const char * typename , struct pbc_slice * slice, pbc_decoder pd, void *ud) {
struct _message * msg = _pbcP_get_message(env, typename);
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 = slice->buffer;
int i;
for (i=0;i<ctx->number;i++) {
int id = ctx->a[i].wire_id >> 3;
struct _field * f = _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;
}

View File

@@ -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,
};

477
lua-protobuf/map.c Normal file
View File

@@ -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(table[i].pointer);
size_t hash = hash_full % size;
struct _pbcM_si_slot * slot = &ret->slot[hash];
if (slot->key == NULL) {
slot->key = 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 = 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 = 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 = 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;
}

33
lua-protobuf/map.h Normal file
View File

@@ -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

1131
lua-protobuf/pattern.c Normal file

File diff suppressed because it is too large Load Diff

26
lua-protobuf/pattern.h Normal file
View File

@@ -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

1004
lua-protobuf/pbc-lua.c Normal file

File diff suppressed because it is too large Load Diff

104
lua-protobuf/pbc.h Normal file
View File

@@ -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 * typename , 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 * typename, union pbc_value *v, int id, const char *key);
int pbc_decode(struct pbc_env * env, const char * typename , struct pbc_slice * slice, pbc_decoder f, void *ud);
// message api
struct pbc_rmessage * pbc_rmessage_new(struct pbc_env * env, const char * typename , 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 *typename);
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

252
lua-protobuf/proto.c Normal file
View File

@@ -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 _pbcM_sp_query(p->msgs, name);
}
struct pbc_env *
pbc_new(void) {
struct pbc_env * p = 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 = p;
_pbcM_ip_delete(e->id);
_pbcM_si_delete(e->name);
free(p);
}
static void
free_stringpool(void *p) {
_pbcS_delete(p);
}
static void
free_msg(void *p) {
struct _message * m = 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 = 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 = 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 = _pbcM_sp_query(p->msgs, name);
if (m==NULL) {
m = 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 = 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 = ud;
iter->count ++;
}
static void
_set_table(void *p, void *ud) {
struct _field * field = p;
struct _iter *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 = _pbcM_sp_query(p->msgs, name);
if (m == NULL) {
m = 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 = 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= _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 * typename , const char * key , const char ** type) {
struct _message *m = _pbcP_get_message(p, typename);
if (m==NULL) {
return 0;
}
if (key == NULL) {
return PBC_NOEXIST;
}
struct _field * field = _pbcM_sp_query(m->name, key);
return _pbcP_type(field, type);
}

64
lua-protobuf/proto.h Normal file
View File

@@ -0,0 +1,64 @@
#ifndef PROTOBUFC_PROTO_H
#define PROTOBUFC_PROTO_H
#include "pbc.h"
#include "map.h"
#include "array.h"
#include <stdbool.h>
#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

329
lua-protobuf/register.c Normal file
View File

@@ -0,0 +1,329 @@
#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>
static const char *
_concat_name(struct _stringpool *p , const char *prefix , int prefix_sz , const char *name , int name_sz) {
if (prefix_sz == 0) {
return _pbcS_build(p , name, name_sz);
}
char temp[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';
return _pbcS_build(p , temp, name_sz + prefix_sz + 1);
}
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 = 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);
_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:
f->default_v->integer.low = strtol(value, NULL, 10);
if (f->default_v->integer.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);
_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);
const char *temp = _concat_name(pool, prefix , prefix_sz , name , name_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, prefix_sz + name_sz + 1,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, name_sz + prefix_sz + 1);
}
// 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, name_sz + prefix_sz + 1, 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[n];
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;
}

455
lua-protobuf/rmessage.c Normal file
View File

@@ -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 = _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 = _pbcH_alloc(h, SIZE_VAR);
v->v.var->s.str = temp;
v->v.var->s.len = len;
return v;
} else {
struct value * v = _pbcH_alloc(h, SIZE_VAR + len + 1);
memcpy(((char *)v) + SIZE_VAR , temp, len);
*(((char *)v) + SIZE_VAR + len) = '\0';
v->v.var->s.str = ((char *)v) + SIZE_VAR;
v->v.var->s.len = len;
return v;
}
}
static void
read_string_var(struct heap *h, pbc_var var,struct atom *a,struct _field *f,uint8_t *buffer) {
const char * temp = (const char *) (buffer + a->v.s.start);
int len = a->v.s.end - a->v.s.start;
if (len == 0) {
var->s.str = "";
var->s.len = 0;
}
else if (temp[len-1] == '\0') {
var->s.str = temp;
var->s.len = len;
} else {
char * temp2 = _pbcH_alloc(h, len + 1);
memcpy(temp2, temp, len);
temp2[len]='\0';
var->s.str = temp2;
var->s.len = -len;
}
}
static 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 = _pbcH_alloc(h, SIZE_VAR);
v->v.var->real = read_double(a);
break;
case PTYPE_FLOAT:
CHECK_BIT32(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->real = (double) read_float(a);
break;
case PTYPE_ENUM:
CHECK_VARINT(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->e.id = a->v.i.low;
v->v.var->e.name = _pbcM_ip_query(f->type_name.e->id , a->v.i.low);
break;
case PTYPE_INT64:
case PTYPE_UINT64:
case PTYPE_INT32:
case PTYPE_UINT32:
case PTYPE_BOOL:
CHECK_VARINT(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->integer = a->v.i;
break;
case PTYPE_FIXED32:
case PTYPE_SFIXED32:
CHECK_BIT32(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->integer = a->v.i;
break;
case PTYPE_FIXED64:
case PTYPE_SFIXED64:
CHECK_BIT64(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->integer = a->v.i;
break;
case PTYPE_SINT32:
CHECK_VARINT(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->integer = a->v.i;
_pbcV_dezigzag32(&(v->v.var->integer));
break;
case PTYPE_SINT64:
CHECK_VARINT(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->integer = a->v.i;
_pbcV_dezigzag64(&(v->v.var->integer));
break;
case PTYPE_STRING:
CHECK_LEND(a,NULL);
v = read_string(h,a,f,buffer);
break;
case PTYPE_BYTES:
CHECK_LEND(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->s.str = (const char *)(buffer + a->v.s.start);
v->v.var->s.len = a->v.s.end - a->v.s.start;
break;
case PTYPE_MESSAGE:
CHECK_LEND(a,NULL);
v = _pbcH_alloc(h, SIZE_MESSAGE);
_pbc_rmessage_new(&(v->v.message), f->type_name.m ,
buffer + a->v.s.start ,
a->v.s.end - a->v.s.start,h);
break;
default:
return NULL;
}
v->type = f;
return v;
}
static void
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 = _pbcA_index_p(array, i);
int id = v->integer.low;
v->e.id = id;
v->e.name = _pbcM_ip_query(f->type_name.e->id , id);
}
}
}
static void
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 = _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 = _pbcM_ip_query(type->id , id);
if (f) {
if (f->label == LABEL_REPEATED || f->label == LABEL_PACKED) {
struct value * v;
void ** vv = _pbcM_sp_query_insert(ret->index, f->name);
if (*vv == NULL) {
v = _pbcH_alloc(h, SIZE_ARRAY);
v->type = f;
_pbcA_open_heap(v->v.array,ret->heap);
*vv = v;
} else {
v= *vv;
}
if (f->label == LABEL_PACKED) {
push_value_packed(type, v->v.array , f , &(ctx->a[i]), buffer);
if (pbc_array_size(v->v.array) == 0) {
type->env->lasterror = "rmessage decode packed data error";
*vv = NULL;
}
} else {
push_value_array(h,v->v.array , f, &(ctx->a[i]), buffer);
if (pbc_array_size(v->v.array) == 0) {
type->env->lasterror = "rmessage decode repeated data error";
*vv = NULL;
}
}
} else {
struct value * v = read_value(h, f, &(ctx->a[i]), buffer);
if (v) {
_pbcM_sp_insert(ret->index, f->name, v);
} else {
type->env->lasterror = "rmessage decode data error";
}
}
}
}
_pbcC_close(_ctx);
}
struct pbc_rmessage *
pbc_rmessage_new(struct pbc_env * env, const char * typename , struct pbc_slice * slice) {
struct _message * msg = _pbcP_get_message(env, typename);
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 = _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 = _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 = _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 = _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 = _pbcM_sp_query(rm->index,key);
if (v == NULL) {
struct _field * f = _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 = malloc(sizeof(struct pbc_rmessage));
m->def->msg = m;
m->def->index = NULL;
}
return m->def;
} else {
if (v->type->label == LABEL_REPEATED) {
return _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 = _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;
}
}

60
lua-protobuf/stringpool.c Normal file
View File

@@ -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;
}

10
lua-protobuf/stringpool.h Normal file
View File

@@ -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

30
lua-protobuf/test.lua Normal file
View File

@@ -0,0 +1,30 @@
require "protobuf"
addr = io.open("addressbook.pb","rb")
buffer = addr:read "*a"
addr:close()
protobuf.register(buffer)
addressbook = {
name = "Alice",
id = 12345,
phone = {
{ number = "1301234567" },
{ number = "87654321", type = "WORK" },
}
}
code = protobuf.encode("tutorial.Person", addressbook)
decode = protobuf.decode("tutorial.Person" , code)
print(decode.name)
print(decode.id)
for _,v in ipairs(decode.phone) do
print("\t"..v.number, v.type)
end
phonebuf = protobuf.pack("tutorial.Person.PhoneNumber number","87654321")
buffer = protobuf.pack("tutorial.Person name id phone", "Alice", 123, { phonebuf })
print(protobuf.unpack("tutorial.Person name id phone", buffer))

110
lua-protobuf/varint.c Normal file
View File

@@ -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 |= ((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);
}

20
lua-protobuf/varint.h Normal file
View File

@@ -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

509
lua-protobuf/wmessage.c Normal file
View File

@@ -0,0 +1,509 @@
#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>
#include <stdbool.h>
#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 = _pbcH_alloc(h, sizeof(*m));
m->type = msg;
m->buffer = _pbcH_alloc(h, WMESSAGE_SIZE);
m->ptr = m->buffer;
m->endptr = m->buffer + WMESSAGE_SIZE;
_pbcA_open_heap(m->sub, h);
m->packed = NULL;
m->heap = h;
return m;
}
struct pbc_wmessage *
pbc_wmessage_new(struct pbc_env * env, const char *typename) {
struct _message * msg = _pbcP_get_message(env, typename);
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(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 = _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 = *v;
p->id = f->id;
p->ptype = f->type;
_pbcA_open_heap(p->data, m->heap);
return p;
}
return *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 = _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(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 = _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(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 = _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[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";
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(m,20);
switch (f->type) {
case PTYPE_ENUM : {
char temp[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";
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(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 = _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 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(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(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(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(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(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(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(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(m, end_len_len);
memmove(m->buffer + offset + end_len_len ,
m->buffer + offset + len_len ,
end_len);
}
memcpy(m->buffer + offset , temp, end_len_len);
}
}
static void
_pack_packed(void *p, void *ud) {
struct _packed *packed = p;
struct pbc_wmessage * m = ud;
int id = packed->id << 3 | WT_LEND;
_expand(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(var->p[0] , &s);
if (s.buffer) {
struct _field * f = var->p[1];
int id = f->id << 3 | WT_LEND;
_expand(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;
}