packages feed

pbc4hs (empty) → 0.1.0.0

raw patch · 29 files changed

+6409/−0 lines, 29 filesdep +basedep +hsluasetup-changed

Dependencies added: base, hslua

Files

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