mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-24 20:23:06 +00:00
add some lua library
This commit is contained in:
14
lua-protobuf/Makefile
Normal file
14
lua-protobuf/Makefile
Normal 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
2
lua-protobuf/README
Normal file
@@ -0,0 +1,2 @@
|
||||
See https://github.com/cloudwu/pbc
|
||||
|
||||
39
lua-protobuf/addressbook.proto
Normal file
39
lua-protobuf/addressbook.proto
Normal 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
84
lua-protobuf/alloc.c
Normal 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
25
lua-protobuf/alloc.h
Normal 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
139
lua-protobuf/array.c
Normal 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
31
lua-protobuf/array.h
Normal 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
303
lua-protobuf/bootstrap.c
Normal 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
10
lua-protobuf/bootstrap.h
Normal 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
278
lua-protobuf/context.c
Normal 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
140
lua-protobuf/context.h
Normal 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
349
lua-protobuf/decode.c
Normal 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;
|
||||
}
|
||||
|
||||
271
lua-protobuf/descriptor.pbc.h
Normal file
271
lua-protobuf/descriptor.pbc.h
Normal 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
477
lua-protobuf/map.c
Normal 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
33
lua-protobuf/map.h
Normal 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
1131
lua-protobuf/pattern.c
Normal file
File diff suppressed because it is too large
Load Diff
26
lua-protobuf/pattern.h
Normal file
26
lua-protobuf/pattern.h
Normal 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
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
104
lua-protobuf/pbc.h
Normal 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
252
lua-protobuf/proto.c
Normal 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
64
lua-protobuf/proto.h
Normal 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
329
lua-protobuf/register.c
Normal 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
455
lua-protobuf/rmessage.c
Normal 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
60
lua-protobuf/stringpool.c
Normal 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
10
lua-protobuf/stringpool.h
Normal 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
30
lua-protobuf/test.lua
Normal 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
110
lua-protobuf/varint.c
Normal 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
20
lua-protobuf/varint.h
Normal 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
509
lua-protobuf/wmessage.c
Normal 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user