├── .gitignore ├── .travis.yml ├── Android.mk ├── Makefile ├── README.md ├── binding ├── lua │ ├── Makefile │ ├── README.md │ ├── build_ios.sh │ ├── parser.lua │ ├── pbc-lua.c │ ├── protobuf.lua │ ├── test.lua │ ├── test2.lua │ └── testparser.lua └── lua53 │ ├── Makefile │ ├── build_ios.sh │ ├── pbc-lua53.c │ ├── protobuf.lua │ └── test.lua ├── build_ios.sh ├── license.txt ├── pbc.h ├── pbc.sln ├── pbc.vcxproj ├── pbc.vcxproj.filters ├── pbc.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── pbc └── pbc-Prefix.pch ├── src ├── alloc.c ├── alloc.h ├── array.c ├── array.h ├── bootstrap.c ├── bootstrap.h ├── context.c ├── context.h ├── decode.c ├── descriptor.pbc.h ├── map.c ├── map.h ├── pattern.c ├── pattern.h ├── proto.c ├── proto.h ├── register.c ├── rmessage.c ├── stringpool.c ├── stringpool.h ├── varint.c ├── varint.h └── wmessage.c ├── test ├── addressbook.c ├── addressbook.proto ├── array.c ├── decode.c ├── descriptor.proto ├── float.c ├── float.proto ├── map.c ├── pattern.c ├── pbc.c ├── readfile.h ├── test.c ├── test.proto └── varint.c └── tool └── dump.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo 2 | *.sdf 3 | *.opensdf 4 | *.d 5 | *.o 6 | Debug 7 | Release 8 | build 9 | .DS_Store 10 | xcuserdata 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # ref: http://docs.travis-ci.com/user/build-configuration 2 | 3 | language: erlang 4 | 5 | env: 6 | global: 7 | - DEPS_BUILD_DIR=$TRAVIS_BUILD_DIR/deps 8 | - LJ_REPO="https://github.com/LuaJIT/LuaJIT.git" 9 | - INC_DIR=/usr/local/include 10 | matrix: 11 | - LUA=lua-5.1 LUA_TYPE=lua LUA_DIST=lua-5.1.5 LUA_BD=lua LUA_INC=$INC_DIR 12 | - LUA=lua-5.2 LUA_TYPE=lua LUA_DIST=lua-5.2.4 LUA_BD=lua LUA_INC=$INC_DIR 13 | - LUA=lua-5.3 LUA_TYPE=lua LUA_DIST=lua-5.3.2 LUA_BD=lua53 LUA_INC=$INC_DIR 14 | - LUA=luajit-2.0 LUA_TYPE=luajit LJ_BR=master LUA_BD=lua LUA_INC=$INC_DIR/$LUA 15 | - LUA=luajit-2.1 LUA_TYPE=luajit LJ_BR=v2.1 LUA_BD=lua LUA_INC=$INC_DIR/$LUA 16 | 17 | before_install: 18 | - mkdir -p $DEPS_BUILD_DIR 19 | - sudo apt-get update -qq 20 | - sudo apt-get install libprotobuf-dev protobuf-compiler 21 | - LUA_BIN=lua 22 | 23 | install: 24 | # install Lua/LuaJIT 25 | - cd $DEPS_BUILD_DIR 26 | - if [ "$LUA_TYPE" == "luajit" ]; then 27 | git clone -b $LJ_BR $LJ_REPO luajit2.git && cd luajit2.git && LJ_TAG=`git describe --abbre=0` && LUA_BIN="luajit-${LJ_TAG:1}" && sudo make install; 28 | fi 29 | - if [ "$LUA_TYPE" == "lua" ]; then 30 | wget "http://www.lua.org/ftp/$LUA_DIST.tar.gz" && tar xzf $LUA_DIST.tar.gz && cd $LUA_DIST && sudo make linux test install; 31 | fi 32 | # build lib 33 | - cd $TRAVIS_BUILD_DIR 34 | - make 35 | # build lib bindings 36 | - make -C binding/$LUA_BD LUADIR=$LUA_INC 37 | 38 | before_script: 39 | # back to home directory 40 | - cd $TRAVIS_BUILD_DIR 41 | # check executables 42 | - which $LUA_BIN 2>/dev/null && $LUA_BIN -v 43 | 44 | script: 45 | - cd $TRAVIS_BUILD_DIR/binding/$LUA_BD 46 | - $LUA_BIN test.lua 47 | 48 | notifications: 49 | email: 50 | on_success: change 51 | on_failure: always 52 | -------------------------------------------------------------------------------- /Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_MODULE := pbc 6 | 7 | LOCAL_MODULE_FILENAME := libpbc 8 | 9 | LOCAL_SRC_FILES := \ 10 | src/alloc.c \ 11 | src/array.c \ 12 | src/bootstrap.c \ 13 | src/context.c \ 14 | src/decode.c \ 15 | src/map.c \ 16 | src/pattern.c \ 17 | src/proto.c \ 18 | src/register.c \ 19 | src/rmessage.c \ 20 | src/stringpool.c \ 21 | src/varint.c \ 22 | src/wmessage.c \ 23 | 24 | 25 | 26 | LOCAL_C_INCLUDES+= src\ 27 | 28 | 29 | include $(BUILD_STATIC_LIBRARY) 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O2 -fPIC -Wall 3 | AR = ar rc 4 | 5 | BUILD = build 6 | 7 | .PHONY : all lib clean tool 8 | 9 | LIBSRCS = context.c varint.c array.c pattern.c register.c proto.c map.c alloc.c rmessage.c wmessage.c bootstrap.c stringpool.c decode.c 10 | LIBNAME = libpbc.a 11 | 12 | TESTSRCS = addressbook.c pattern.c pbc.c float.c map.c test.c decode.c 13 | PROTOSRCS = addressbook.proto descriptor.proto float.proto test.proto 14 | 15 | BUILD_O = $(BUILD)/o 16 | 17 | all : lib test 18 | 19 | lib : $(LIBNAME) 20 | 21 | clean : 22 | rm -rf $(BUILD) 23 | 24 | $(BUILD) : $(BUILD_O) 25 | 26 | $(BUILD_O) : 27 | mkdir -p $@ 28 | 29 | TOOL := $(BUILD)/dump 30 | 31 | tool : $(TOOL) 32 | 33 | $(TOOL) : | $(BUILD) 34 | $(TOOL) : $(LIBNAME) 35 | $(TOOL) : tool/dump.c 36 | cd $(BUILD) && $(CC) $(CFLAGS) -I.. -L. -o dump ../$< -lpbc 37 | 38 | LIB_O := 39 | 40 | define BUILD_temp 41 | TAR := $(BUILD_O)/$(notdir $(basename $(1))) 42 | LIB_O := $(LIB_O) $$(TAR).o 43 | $$(TAR).o : | $(BUILD_O) 44 | -include $$(TAR).d 45 | $$(TAR).o : src/$(1) 46 | $(CC) $(CFLAGS) -c -Isrc -I. -o $$@ -MMD $$< 47 | endef 48 | 49 | $(foreach s,$(LIBSRCS),$(eval $(call BUILD_temp,$(s)))) 50 | 51 | $(LIBNAME) : $(LIB_O) 52 | cd $(BUILD) && $(AR) $(LIBNAME) $(addprefix ../,$^) 53 | 54 | TEST := 55 | 56 | define TEST_temp 57 | TAR := $(BUILD)/$(notdir $(basename $(1))) 58 | TEST := $(TEST) $$(TAR) 59 | $$(TAR) : | $(BUILD) 60 | $$(TAR) : $(LIBNAME) 61 | $$(TAR) : test/$(1) 62 | cd $(BUILD) && $(CC) $(CFLAGS) -I.. -L. -o $$(notdir $$@) ../$$< -lpbc 63 | endef 64 | 65 | $(foreach s,$(TESTSRCS),$(eval $(call TEST_temp,$(s)))) 66 | 67 | test : $(TEST) proto 68 | 69 | PROTO := 70 | 71 | define PROTO_temp 72 | TAR := $(BUILD)/$(notdir $(basename $(1))) 73 | PROTO := $(PROTO) $$(TAR).pb 74 | $$(TAR).pb : | $(BUILD) 75 | $$(TAR).pb : test/$(1) 76 | protoc -o$$@ $$< 77 | endef 78 | 79 | $(foreach s,$(PROTOSRCS),$(eval $(call PROTO_temp,$(s)))) 80 | 81 | proto : $(PROTO) 82 | 83 | .PHONY : all lib test proto clean 84 | 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## PBC 2 | 3 | [![travis-ci status](https://travis-ci.org/cloudwu/pbc.svg?branch=master)](https://travis-ci.org/cloudwu/pbc) 4 | 5 | PBC is a google protocol buffers library for C without code generation. 6 | 7 | ## Quick Example 8 | 9 | package tutorial; 10 | 11 | message Person { 12 | required string name = 1; 13 | required int32 id = 2; // Unique ID number for this person. 14 | optional string email = 3; 15 | 16 | enum PhoneType { 17 | MOBILE = 0; 18 | HOME = 1; 19 | WORK = 2; 20 | } 21 | 22 | message PhoneNumber { 23 | required string number = 1; 24 | optional PhoneType type = 2 [default = HOME]; 25 | } 26 | 27 | repeated PhoneNumber phone = 4; 28 | } 29 | 30 | ```C 31 | struct pbc_rmessage * m = pbc_rmessage_new(env, "tutorial.Person", slice); 32 | printf("name = %s\n", pbc_rmessage_string(m , "name" , 0 , NULL)); 33 | printf("id = %d\n", pbc_rmessage_integer(m , "id" , 0 , NULL)); 34 | printf("email = %s\n", pbc_rmessage_string(m , "email" , 0 , NULL)); 35 | 36 | int phone_n = pbc_rmessage_size(m, "phone"); 37 | int i; 38 | 39 | for (i=0;i 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /pbc.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOBUF_C_H 2 | #define PROTOBUF_C_H 3 | 4 | #include 5 | #include 6 | 7 | #define PBC_ARRAY_CAP 64 8 | 9 | #define PBC_NOEXIST -1 10 | #define PBC_INT 1 11 | #define PBC_REAL 2 12 | #define PBC_BOOL 3 13 | #define PBC_ENUM 4 14 | #define PBC_STRING 5 15 | #define PBC_MESSAGE 6 16 | #define PBC_FIXED64 7 17 | #define PBC_FIXED32 8 18 | #define PBC_BYTES 9 19 | #define PBC_INT64 10 20 | #define PBC_UINT 11 21 | #define PBC_UNKNOWN 12 22 | #define PBC_REPEATED 128 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | typedef struct _pbc_array { char _data[PBC_ARRAY_CAP]; } pbc_array[1]; 29 | 30 | struct pbc_slice { 31 | void *buffer; 32 | int len; 33 | }; 34 | 35 | struct pbc_pattern; 36 | struct pbc_env; 37 | struct pbc_rmessage; 38 | struct pbc_wmessage; 39 | 40 | struct pbc_env * pbc_new(void); 41 | void pbc_delete(struct pbc_env *); 42 | int pbc_register(struct pbc_env *, struct pbc_slice * slice); 43 | int pbc_type(struct pbc_env *, const char * type_name , const char * key , const char ** type); 44 | const char * pbc_error(struct pbc_env *); 45 | 46 | // callback api 47 | union pbc_value { 48 | struct { 49 | uint32_t low; 50 | uint32_t hi; 51 | } i; 52 | double f; 53 | struct pbc_slice s; 54 | struct { 55 | int id; 56 | const char * name; 57 | } e; 58 | }; 59 | 60 | typedef void (*pbc_decoder)(void *ud, int type, const char * type_name, union pbc_value *v, int id, const char *key); 61 | int pbc_decode(struct pbc_env * env, const char * type_name , struct pbc_slice * slice, pbc_decoder f, void *ud); 62 | 63 | // message api 64 | 65 | struct pbc_rmessage * pbc_rmessage_new(struct pbc_env * env, const char * type_name , struct pbc_slice * slice); 66 | void pbc_rmessage_delete(struct pbc_rmessage *); 67 | 68 | uint32_t pbc_rmessage_integer(struct pbc_rmessage * , const char *key , int index, uint32_t *hi); 69 | double pbc_rmessage_real(struct pbc_rmessage * , const char *key , int index); 70 | const char * pbc_rmessage_string(struct pbc_rmessage * , const char *key , int index, int *sz); 71 | struct pbc_rmessage * pbc_rmessage_message(struct pbc_rmessage *, const char *key, int index); 72 | int pbc_rmessage_size(struct pbc_rmessage *, const char *key); 73 | int pbc_rmessage_next(struct pbc_rmessage *, const char **key); 74 | 75 | struct pbc_wmessage * pbc_wmessage_new(struct pbc_env * env, const char *type_name); 76 | void pbc_wmessage_delete(struct pbc_wmessage *); 77 | 78 | // for negative integer, pass -1 to hi 79 | int pbc_wmessage_integer(struct pbc_wmessage *, const char *key, uint32_t low, uint32_t hi); 80 | int pbc_wmessage_real(struct pbc_wmessage *, const char *key, double v); 81 | int pbc_wmessage_string(struct pbc_wmessage *, const char *key, const char * v, int len); 82 | struct pbc_wmessage * pbc_wmessage_message(struct pbc_wmessage *, const char *key); 83 | void * pbc_wmessage_buffer(struct pbc_wmessage *, struct pbc_slice * slice); 84 | 85 | // array api 86 | 87 | int pbc_array_size(pbc_array); 88 | uint32_t pbc_array_integer(pbc_array array, int index, uint32_t *hi); 89 | double pbc_array_real(pbc_array array, int index); 90 | struct pbc_slice * pbc_array_slice(pbc_array array, int index); 91 | 92 | void pbc_array_push_integer(pbc_array array, uint32_t low, uint32_t hi); 93 | void pbc_array_push_slice(pbc_array array, struct pbc_slice *); 94 | void pbc_array_push_real(pbc_array array, double v); 95 | 96 | struct pbc_pattern * pbc_pattern_new(struct pbc_env * , const char * message, const char *format, ...); 97 | void pbc_pattern_delete(struct pbc_pattern *); 98 | 99 | // return unused bytes , -1 for error 100 | int pbc_pattern_pack(struct pbc_pattern *, void *input, struct pbc_slice * s); 101 | 102 | // <0 for error 103 | int pbc_pattern_unpack(struct pbc_pattern *, struct pbc_slice * s , void * output); 104 | 105 | void pbc_pattern_set_default(struct pbc_pattern * , void *data); 106 | void pbc_pattern_close_arrays(struct pbc_pattern *, void *data); 107 | 108 | int pbc_enum_id(struct pbc_env *env, const char *enum_type, const char *enum_name); 109 | 110 | #ifdef __cplusplus 111 | } 112 | #endif 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /pbc.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pbc", "pbc.vcxproj", "{82356F33-956B-4931-9977-BD7994B1C761}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {82356F33-956B-4931-9977-BD7994B1C761}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {82356F33-956B-4931-9977-BD7994B1C761}.Debug|Win32.Build.0 = Debug|Win32 14 | {82356F33-956B-4931-9977-BD7994B1C761}.Release|Win32.ActiveCfg = Release|Win32 15 | {82356F33-956B-4931-9977-BD7994B1C761}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /pbc.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | {82356F33-956B-4931-9977-BD7994B1C761} 43 | Win32Proj 44 | ConsoleApplication1 45 | 46 | 47 | 48 | StaticLibrary 49 | true 50 | v110_xp 51 | Unicode 52 | 53 | 54 | StaticLibrary 55 | false 56 | v110_xp 57 | true 58 | Unicode 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | Level3 74 | Disabled 75 | WIN32;_LIB;_DEBUG;%(PreprocessorDefinitions) 76 | .;.\pbc;.\pbc\src 77 | true 78 | CompileAsCpp 79 | 4146;4273;4244;4018 80 | 81 | 82 | Windows 83 | true 84 | 85 | 86 | 87 | 88 | 89 | Level3 90 | MaxSpeed 91 | true 92 | true 93 | WIN32;_LIB;NDEBUG;%(PreprocessorDefinitions) 94 | .;.\pbc;.\pbc\src 95 | true 96 | CompileAsCpp 97 | 4146;4273;4244;4018 98 | 99 | 100 | Windows 101 | true 102 | true 103 | true 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /pbc.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {aa230bd6-7da2-4cfb-af39-52310e429716} 6 | 7 | 8 | 9 | 10 | src 11 | 12 | 13 | src 14 | 15 | 16 | src 17 | 18 | 19 | src 20 | 21 | 22 | src 23 | 24 | 25 | src 26 | 27 | 28 | src 29 | 30 | 31 | src 32 | 33 | 34 | src 35 | 36 | 37 | src 38 | 39 | 40 | 41 | 42 | 43 | src 44 | 45 | 46 | src 47 | 48 | 49 | src 50 | 51 | 52 | src 53 | 54 | 55 | src 56 | 57 | 58 | src 59 | 60 | 61 | src 62 | 63 | 64 | src 65 | 66 | 67 | src 68 | 69 | 70 | src 71 | 72 | 73 | src 74 | 75 | 76 | src 77 | 78 | 79 | src 80 | 81 | 82 | -------------------------------------------------------------------------------- /pbc.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /pbc/pbc-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'pbc' target in the 'pbc' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import "pbc.h" 8 | #endif 9 | -------------------------------------------------------------------------------- /src/alloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static int _g = 0; 5 | 6 | void * _pbcM_malloc(size_t sz) { 7 | ++ _g; 8 | return malloc(sz); 9 | } 10 | 11 | void _pbcM_free(void *p) { 12 | if (p) { 13 | -- _g; 14 | free(p); 15 | } 16 | } 17 | 18 | void* _pbcM_realloc(void *p, size_t sz) { 19 | return realloc(p,sz); 20 | } 21 | 22 | void _pbcM_memory() { 23 | printf("%d\n",_g); 24 | } 25 | 26 | struct heap_page { 27 | struct heap_page * next; 28 | }; 29 | 30 | struct heap { 31 | struct heap_page *current; 32 | int size; 33 | int used; 34 | }; 35 | 36 | struct heap * 37 | _pbcH_new(int pagesize) { 38 | int cap = 1024; 39 | while(cap < pagesize) { 40 | cap *= 2; 41 | } 42 | struct heap * h = (struct heap *)_pbcM_malloc(sizeof(struct heap)); 43 | h->current = (struct heap_page *)_pbcM_malloc(sizeof(struct heap_page) + cap); 44 | h->size = cap; 45 | h->used = 0; 46 | h->current->next = NULL; 47 | return h; 48 | } 49 | 50 | void 51 | _pbcH_delete(struct heap *h) { 52 | struct heap_page * p = h->current; 53 | struct heap_page * next = p->next; 54 | for(;;) { 55 | _pbcM_free(p); 56 | if (next == NULL) 57 | break; 58 | p = next; 59 | next = p->next; 60 | } 61 | _pbcM_free(h); 62 | } 63 | 64 | void* 65 | _pbcH_alloc(struct heap *h, int size) { 66 | size = (size + 3) & ~3; 67 | if (h->size - h->used < size) { 68 | struct heap_page * p; 69 | if (size < h->size) { 70 | p = (struct heap_page *)_pbcM_malloc(sizeof(struct heap_page) + h->size); 71 | } else { 72 | p = (struct heap_page *)_pbcM_malloc(sizeof(struct heap_page) + size); 73 | } 74 | p->next = h->current; 75 | h->current = p; 76 | h->used = size; 77 | return (p+1); 78 | } else { 79 | char * buffer = (char *)(h->current + 1); 80 | buffer += h->used; 81 | h->used += size; 82 | return buffer; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOBUF_C_ALLOC_H 2 | #define PROTOBUF_C_ALLOC_H 3 | 4 | #include 5 | #include 6 | 7 | void * _pbcM_malloc(size_t sz); 8 | void _pbcM_free(void *p); 9 | void * _pbcM_realloc(void *p, size_t sz); 10 | void _pbcM_memory(); 11 | 12 | struct heap; 13 | 14 | struct heap * _pbcH_new(int pagesize); 15 | void _pbcH_delete(struct heap *); 16 | void* _pbcH_alloc(struct heap *, int size); 17 | 18 | #define HMALLOC(size) ((h) ? _pbcH_alloc(h, size) : _pbcM_malloc(size)) 19 | 20 | #define malloc _pbcM_malloc 21 | #define free _pbcM_free 22 | #define realloc _pbcM_realloc 23 | #define memory _pbcM_memory 24 | 25 | #ifdef _WIN32 26 | 27 | #include 28 | 29 | #endif 30 | 31 | #ifdef _MSC_VER 32 | 33 | #define alloca _alloca 34 | 35 | #endif 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/array.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | #include "array.h" 3 | #include "alloc.h" 4 | 5 | #include 6 | #include 7 | 8 | struct array { 9 | int number; 10 | struct heap *heap; 11 | union _pbc_var * a; 12 | }; 13 | 14 | #define INNER_FIELD ((PBC_ARRAY_CAP - sizeof(struct array)) / sizeof(pbc_var)) 15 | 16 | void 17 | _pbcA_open(pbc_array _array) { 18 | struct array * a = (struct array *)_array; 19 | a->number = 0; 20 | a->heap = NULL; 21 | a->a = (union _pbc_var *)(a+1); 22 | } 23 | 24 | void 25 | _pbcA_open_heap(pbc_array _array, struct heap *h) { 26 | struct array * a = (struct array *)_array; 27 | a->number = 0; 28 | a->heap = h; 29 | a->a = (union _pbc_var *)(a+1); 30 | } 31 | 32 | void 33 | _pbcA_close(pbc_array _array) { 34 | struct array * a = (struct array *)_array; 35 | if (a->heap == NULL && a->a != NULL && (union _pbc_var *)(a+1) != a->a) { 36 | _pbcM_free(a->a); 37 | a->a = NULL; 38 | } 39 | } 40 | 41 | void 42 | _pbcA_push(pbc_array _array, pbc_var var) { 43 | struct array * a = (struct array *)_array; 44 | if (a->number == 0) { 45 | a->a = (union _pbc_var *)(a+1); 46 | } else if (a->number >= INNER_FIELD) { 47 | if (a->number == INNER_FIELD) { 48 | int cap = 1; 49 | while (cap <= a->number + 1) 50 | cap *= 2; 51 | struct heap * h = a->heap; 52 | union _pbc_var * outer = (union _pbc_var *)HMALLOC(cap * sizeof(union _pbc_var)); 53 | memcpy(outer , a->a , INNER_FIELD * sizeof(pbc_var)); 54 | a->a = outer; 55 | } else { 56 | int size=a->number; 57 | if (((size + 1) ^ size) > size) { 58 | struct heap * h = a->heap; 59 | if (h) { 60 | void * old = a->a; 61 | a->a = (union _pbc_var *)_pbcH_alloc(h, sizeof(union _pbc_var) * (size+1) * 2); 62 | memcpy(a->a, old, sizeof(union _pbc_var) * size); 63 | } else { 64 | a->a = (union _pbc_var *)_pbcM_realloc(a->a,sizeof(union _pbc_var) * (size+1) * 2); 65 | } 66 | } 67 | } 68 | } 69 | a->a[a->number] = *var; 70 | ++ a->number; 71 | } 72 | 73 | void 74 | _pbcA_index(pbc_array _array, int idx, pbc_var var) 75 | { 76 | struct array * a = (struct array *)_array; 77 | var[0] = a->a[idx]; 78 | } 79 | 80 | void * 81 | _pbcA_index_p(pbc_array _array, int idx) 82 | { 83 | struct array * a = (struct array *)_array; 84 | return &(a->a[idx]); 85 | } 86 | 87 | int 88 | pbc_array_size(pbc_array _array) { 89 | struct array * a = (struct array *)_array; 90 | return a->number; 91 | } 92 | 93 | uint32_t 94 | pbc_array_integer(pbc_array array, int index, uint32_t *hi) { 95 | pbc_var var; 96 | _pbcA_index(array , index , var); 97 | if (hi) { 98 | *hi = var->integer.hi; 99 | } 100 | return var->integer.low; 101 | } 102 | 103 | double 104 | pbc_array_real(pbc_array array, int index) { 105 | pbc_var var; 106 | _pbcA_index(array , index , var); 107 | return var->real; 108 | } 109 | 110 | struct pbc_slice * 111 | pbc_array_slice(pbc_array _array, int index) { 112 | struct array * a = (struct array *)_array; 113 | if (index <0 || index > a->number) { 114 | return NULL; 115 | } 116 | return (struct pbc_slice *) &(a->a[index]); 117 | } 118 | 119 | void 120 | pbc_array_push_integer(pbc_array array, uint32_t low, uint32_t hi) { 121 | pbc_var var; 122 | var->integer.low = low; 123 | var->integer.hi = hi; 124 | _pbcA_push(array,var); 125 | } 126 | 127 | void 128 | pbc_array_push_slice(pbc_array array, struct pbc_slice *s) { 129 | pbc_var var; 130 | var->m = *s; 131 | _pbcA_push(array,var); 132 | } 133 | 134 | void 135 | pbc_array_push_real(pbc_array array, double v) { 136 | pbc_var var; 137 | var->real = v; 138 | _pbcA_push(array,var); 139 | } 140 | -------------------------------------------------------------------------------- /src/array.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOBUF_C_ARRAY_H 2 | #define PROTOBUF_C_ARRAY_H 3 | 4 | #include "varint.h" 5 | #include "pbc.h" 6 | #include "alloc.h" 7 | 8 | typedef union _pbc_var { 9 | struct longlong integer; 10 | double real; 11 | struct { 12 | const char * str; 13 | int len; 14 | } s; 15 | struct { 16 | int id; 17 | const char * name; 18 | } e; 19 | struct pbc_slice m; 20 | void * p[2]; 21 | } pbc_var[1]; 22 | 23 | void _pbcA_open(pbc_array); 24 | void _pbcA_open_heap(pbc_array, struct heap *h); 25 | void _pbcA_close(pbc_array); 26 | 27 | void _pbcA_push(pbc_array, pbc_var var); 28 | void _pbcA_index(pbc_array , int idx, pbc_var var); 29 | void * _pbcA_index_p(pbc_array _array, int idx); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/bootstrap.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | #include "map.h" 3 | #include "context.h" 4 | #include "pattern.h" 5 | #include "proto.h" 6 | #include "alloc.h" 7 | #include "bootstrap.h" 8 | #include "stringpool.h" 9 | #include "array.h" 10 | #include "descriptor.pbc.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /* 18 | 19 | // Descriptor 20 | 21 | // google.protobuf.Descriptor.proto encoded in descriptor.pbc.h with proto pbc.file . 22 | 23 | package pbc; 24 | 25 | message field { 26 | optional string name = 1; 27 | optional int32 id = 2; 28 | optional int32 label = 3; // 0 optional 1 required 2 repeated 29 | optional int32 type = 4; // type_id 30 | optional string type_name = 5; 31 | optional int32 default_int = 6; 32 | optional string default_string = 7; 33 | optional double default_real = 8; 34 | } 35 | 36 | message file { 37 | optional string name = 1; 38 | repeated string dependency = 2; 39 | 40 | repeated string message_name = 3; 41 | repeated int32 message_size = 4; 42 | repeated field message_field = 5; 43 | 44 | repeated string enum_name = 6; 45 | repeated int32 enum_size = 7; 46 | repeated string enum_string = 8; 47 | repeated int32 enum_id = 9; 48 | } 49 | 50 | */ 51 | 52 | struct field_t { 53 | struct pbc_slice name; 54 | int32_t id; 55 | int32_t label; 56 | int32_t type; 57 | struct pbc_slice type_name; 58 | int32_t default_integer; 59 | struct pbc_slice default_string; 60 | double default_real; 61 | }; 62 | 63 | struct file_t { 64 | struct pbc_slice name; // string 65 | pbc_array dependency; // string 66 | pbc_array message_name; // string 67 | pbc_array message_size; // int32 68 | pbc_array message_field; // field_t 69 | pbc_array enum_name; // string 70 | pbc_array enum_size; // int32 71 | pbc_array enum_string; // string 72 | pbc_array enum_id; // int32 73 | }; 74 | 75 | static void 76 | set_enum_one(struct pbc_env *p, struct file_t *file, const char *name, int start, int sz) { 77 | struct map_kv *table = (struct map_kv *)malloc(sz * sizeof(struct map_kv)); 78 | int i; 79 | for (i=0;ienum_id, start+i, id); 83 | _pbcA_index(file->enum_string, start+i, string); 84 | table[i].id = (int)id->integer.low; 85 | table[i].pointer = (void *)string->s.str; 86 | } 87 | _pbcP_push_enum(p,name,table,sz); 88 | 89 | free(table); 90 | } 91 | 92 | static void 93 | set_enums(struct pbc_env *p, struct file_t *file) { 94 | int n = pbc_array_size(file->enum_size); 95 | int i; 96 | int start = 0; 97 | for (i=0;ienum_name,i,name); 100 | pbc_var var; 101 | _pbcA_index(file->enum_size,i,var); 102 | set_enum_one(p, file, name->s.str, start , (int)var->integer.low); 103 | start += var->integer.low; 104 | } 105 | } 106 | 107 | static void 108 | set_default(struct _field *f, struct field_t *input) { 109 | switch (f->type) { 110 | case PTYPE_DOUBLE: 111 | case PTYPE_FLOAT: 112 | f->default_v->real = input->default_real; 113 | break; 114 | case PTYPE_STRING: 115 | case PTYPE_ENUM: 116 | f->default_v->m = input->default_string; 117 | break; 118 | default: 119 | f->default_v->integer.low = input->default_integer; 120 | break; 121 | } 122 | } 123 | 124 | static void 125 | 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) { 126 | int i; 127 | for (i=0;imessage_field, start+i, _field); 130 | struct field_t field; 131 | 132 | int ret = pbc_pattern_unpack(FIELD_T, &_field->m, &field); 133 | if (ret != 0) { 134 | continue; 135 | } 136 | struct _field f; 137 | f.id = field.id; 138 | f.name = (const char *)field.name.buffer; 139 | f.type = field.type; 140 | f.label = field.label; 141 | f.type_name.n = (const char *)field.type_name.buffer; 142 | set_default(&f, &field); 143 | 144 | _pbcP_push_message(p,name, &f , queue); 145 | 146 | // don't need to close pattern since no array 147 | } 148 | _pbcP_init_message(p, name); 149 | } 150 | 151 | static void 152 | set_msgs(struct pbc_pattern * FIELD_T, struct pbc_env *p, struct file_t *file , pbc_array queue) { 153 | int n = pbc_array_size(file->message_size); 154 | int i; 155 | int start = 0; 156 | for (i=0;imessage_name,i,name); 159 | pbc_var sz; 160 | _pbcA_index(file->message_size,i,sz); 161 | set_msg_one(FIELD_T, p, file, name->s.str, start , (int)sz->integer.low , queue); 162 | start += sz->integer.low; 163 | } 164 | } 165 | 166 | static void 167 | set_field_one(struct pbc_env *p, struct _field *f) { 168 | const char * type_name = f->type_name.n; 169 | if (f->type == PTYPE_MESSAGE) { 170 | f->type_name.m = (struct _message *)_pbcM_sp_query(p->msgs, type_name); 171 | // printf("MESSAGE: %s %p\n",type_name, f->type_name.m); 172 | } else if (f->type == PTYPE_ENUM) { 173 | f->type_name.e = (struct _enum *)_pbcM_sp_query(p->enums, type_name); 174 | // printf("ENUM: %s %p ",type_name, f->type_name.e); 175 | const char * str = f->default_v->s.str; 176 | if (str && str[0]) { 177 | int err = _pbcM_si_query(f->type_name.e->name, str , &(f->default_v->e.id)); 178 | if (err < 0) 179 | goto _default; 180 | f->default_v->e.name = (const char *)_pbcM_ip_query(f->type_name.e->id, f->default_v->e.id); 181 | // printf("[%s %d]\n",str,f->default_v->e.id); 182 | } else { 183 | _default: 184 | memcpy(f->default_v, f->type_name.e->default_v, sizeof(pbc_var)); 185 | // printf("(%s %d)\n",f->default_v->e.name,f->default_v->e.id); 186 | } 187 | } 188 | } 189 | 190 | void 191 | _pbcB_register_fields(struct pbc_env *p, pbc_array queue) { 192 | int sz = pbc_array_size(queue); 193 | int i; 194 | for (i=0;im.buffer; 198 | set_field_one(p, f); 199 | } 200 | } 201 | 202 | static void 203 | _set_string(struct _pattern_field * f) { 204 | f->ptype = PTYPE_STRING; 205 | f->ctype = CTYPE_VAR; 206 | f->defv->s.str = ""; 207 | f->defv->s.len = 0; 208 | } 209 | 210 | static void 211 | _set_int32(struct _pattern_field * f) { 212 | f->ptype = PTYPE_INT32; 213 | f->ctype = CTYPE_INT32; 214 | } 215 | 216 | static void 217 | _set_double(struct _pattern_field * f) { 218 | f->ptype = PTYPE_DOUBLE; 219 | f->ctype = CTYPE_DOUBLE; 220 | } 221 | 222 | static void 223 | _set_message_array(struct _pattern_field *f) { 224 | f->ptype = PTYPE_MESSAGE; 225 | f->ctype = CTYPE_ARRAY; 226 | } 227 | 228 | static void 229 | _set_string_array(struct _pattern_field * f) { 230 | f->ptype = PTYPE_STRING; 231 | f->ctype = CTYPE_ARRAY; 232 | } 233 | 234 | static void 235 | _set_int32_array(struct _pattern_field * f) { 236 | f->ptype = PTYPE_INT32; 237 | f->ctype = CTYPE_ARRAY; 238 | } 239 | 240 | #define SET_PATTERN(pat , idx , pat_type, field_name , type) \ 241 | pat->f[idx].id = idx+1 ; \ 242 | pat->f[idx].offset = offsetof(struct pat_type, field_name); \ 243 | _set_##type(&pat->f[idx]); 244 | 245 | #define F(idx,field_name,type) SET_PATTERN(FIELD_T, idx, field_t ,field_name, type) 246 | #define D(idx,field_name,type) SET_PATTERN(FILE_T, idx, file_t ,field_name, type) 247 | 248 | static int 249 | register_internal(struct pbc_env * p, struct pbc_slice *slice) { 250 | struct pbc_pattern * FIELD_T = _pbcP_new(p,8); 251 | F(0,name,string); 252 | F(1,id,int32); 253 | F(2,label,int32); 254 | F(3,type,int32); 255 | F(4,type_name,string); 256 | F(5,default_integer,int32); 257 | F(6,default_string,string); 258 | F(7,default_real,double); 259 | 260 | struct pbc_pattern * FILE_T = _pbcP_new(p,10); 261 | 262 | D(0,name,string); 263 | D(1,dependency,string_array); 264 | D(2,message_name,string_array); 265 | D(3,message_size,int32_array); 266 | D(4,message_field,message_array); 267 | D(5,enum_name,string_array); 268 | D(6,enum_size,int32_array); 269 | D(7,enum_string,string_array); 270 | D(8,enum_id,int32_array); 271 | 272 | int ret = 0; 273 | 274 | struct file_t file; 275 | int r = pbc_pattern_unpack(FILE_T, slice, &file); 276 | if (r != 0) { 277 | ret = 1; 278 | goto _return; 279 | } 280 | 281 | _pbcM_sp_insert(p->files , (const char *)file.name.buffer, NULL); 282 | 283 | pbc_array queue; 284 | _pbcA_open(queue); 285 | 286 | set_enums(p, &file); 287 | set_msgs(FIELD_T, p, &file, queue); 288 | _pbcB_register_fields(p, queue); 289 | 290 | _pbcA_close(queue); 291 | pbc_pattern_close_arrays(FILE_T, &file); 292 | 293 | _return: 294 | free(FIELD_T); 295 | free(FILE_T); 296 | return ret; 297 | } 298 | 299 | void 300 | _pbcB_init(struct pbc_env * p) { 301 | struct pbc_slice slice = { pbc_descriptor,sizeof(pbc_descriptor) }; 302 | register_internal(p,&slice); 303 | } 304 | -------------------------------------------------------------------------------- /src/bootstrap.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOBUF_C_BOOTSTRAP_H 2 | #define PROTOBUF_C_BOOTSTRAP_H 3 | 4 | #include "proto.h" 5 | #include "pbc.h" 6 | 7 | void _pbcB_init(struct pbc_env *); 8 | void _pbcB_register_fields(struct pbc_env *, pbc_array queue); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/context.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | #include "alloc.h" 3 | #include "varint.h" 4 | #include "context.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #ifndef _MSC_VER 10 | #include 11 | #endif 12 | 13 | #define INNER_ATOM ((PBC_CONTEXT_CAP - sizeof(struct context)) / sizeof(struct atom)) 14 | 15 | static char * 16 | wiretype_decode(uint8_t *buffer, int cap , struct atom *a , int start) 17 | { 18 | uint8_t temp[10]; 19 | struct longlong r; 20 | int len; 21 | if (cap >= 10) { 22 | len = _pbcV_decode(buffer, &r); 23 | if (r.hi !=0) 24 | return NULL; 25 | } else { 26 | memcpy(temp, buffer , cap); 27 | len = _pbcV_decode(temp, &r); 28 | if (len > cap || r.hi !=0) 29 | return NULL; 30 | } 31 | 32 | int wiretype = r.low & 7; 33 | a->wire_id = r.low; 34 | buffer += len; 35 | start += len; 36 | cap -=len; 37 | 38 | switch (wiretype) { 39 | case WT_VARINT : 40 | if (cap >=10) { 41 | len = _pbcV_decode(buffer, &a->v.i); 42 | } else { 43 | memcpy(temp, buffer , cap); 44 | len = _pbcV_decode(temp, &a->v.i); 45 | if (cap < len) 46 | return NULL; 47 | } 48 | return (char *)buffer+len; 49 | case WT_BIT64 : 50 | if (cap < 8) 51 | return NULL; 52 | a->v.i.low = buffer[0] | 53 | buffer[1] << 8 | 54 | buffer[2] << 16 | 55 | buffer[3] << 24; 56 | a->v.i.hi = buffer[4] | 57 | buffer[5] << 8 | 58 | buffer[6] << 16 | 59 | buffer[7] << 24; 60 | return (char *)buffer + 8; 61 | case WT_LEND : 62 | if (cap >=10) { 63 | len = _pbcV_decode(buffer, &r); 64 | } else { 65 | memcpy(temp, buffer , cap); 66 | len = _pbcV_decode(temp, &r); 67 | } 68 | if (cap < len + r.low || r.hi !=0) 69 | return NULL; 70 | a->v.s.start = start + len; 71 | a->v.s.end = start + len + r.low; 72 | return (char *)buffer + len + r.low; 73 | case WT_BIT32 : 74 | if (cap < 4) 75 | return NULL; 76 | a->v.i.low = buffer[0] | 77 | buffer[1] << 8 | 78 | buffer[2] << 16 | 79 | buffer[3] << 24; 80 | a->v.i.hi = 0; 81 | return (char *)buffer + 4; 82 | default: 83 | return NULL; 84 | } 85 | } 86 | 87 | static inline int 88 | _decode_varint(uint8_t * buffer, int size , struct atom * a) { 89 | a->wire_id = WT_VARINT; 90 | if (size < 10) { 91 | uint8_t temp[10]; 92 | memcpy(temp,buffer,size); 93 | return _pbcV_decode(temp , &(a->v.i)); 94 | } else { 95 | return _pbcV_decode(buffer , &(a->v.i)); 96 | } 97 | } 98 | 99 | static int 100 | _open_packed_varint(struct context * ctx , uint8_t * buffer, int size) { 101 | struct atom * a = (struct atom *)(ctx + 1); 102 | 103 | int i; 104 | 105 | for (i=0;ia = a; 115 | } else { 116 | int cap = 64; 117 | ctx->a = (struct atom *)malloc(cap * sizeof(struct atom)); 118 | while (size > 0) { 119 | if (i >= cap) { 120 | cap = cap + 64; 121 | ctx->a = (struct atom *)realloc(ctx->a, cap * sizeof(struct atom)); 122 | continue; 123 | } 124 | int len = _decode_varint(buffer, size, &a[i]); 125 | buffer += len; 126 | size -= len; 127 | 128 | ++i; 129 | } 130 | memcpy(ctx->a, a , sizeof(struct atom) * INNER_ATOM); 131 | } 132 | ctx->number = i; 133 | 134 | return i; 135 | } 136 | 137 | int 138 | _pbcC_open_packed(pbc_ctx _ctx, int ptype, void *buffer, int size) { 139 | struct context * ctx = (struct context *)_ctx; 140 | ctx->buffer = (char *)buffer; 141 | ctx->size = size; 142 | ctx->number = 0; 143 | ctx->a = NULL; 144 | 145 | if (buffer == NULL || size == 0) { 146 | return 0; 147 | } 148 | 149 | int bits = 0; 150 | 151 | switch (ptype) { 152 | case PTYPE_INT64: 153 | case PTYPE_UINT64: 154 | case PTYPE_INT32: 155 | case PTYPE_BOOL: 156 | case PTYPE_UINT32: 157 | case PTYPE_ENUM: 158 | case PTYPE_SINT32: 159 | case PTYPE_SINT64: 160 | return _open_packed_varint(ctx , (uint8_t *)buffer, size); 161 | case PTYPE_DOUBLE: 162 | case PTYPE_FIXED64: 163 | case PTYPE_SFIXED64: 164 | ctx->number = size / 8; 165 | bits = 64; 166 | break; 167 | case PTYPE_FLOAT: 168 | case PTYPE_FIXED32: 169 | case PTYPE_SFIXED32: 170 | ctx->number = size / 4; 171 | bits = 32; 172 | break; 173 | default: 174 | return 0; 175 | } 176 | 177 | struct atom * a = (struct atom *)(ctx + 1); 178 | 179 | if (ctx->number > INNER_ATOM) { 180 | ctx->a = (struct atom *)malloc(ctx->number * sizeof(struct atom)); 181 | a = ctx->a; 182 | } else { 183 | ctx->a = a; 184 | } 185 | 186 | int i; 187 | if (bits == 64) { 188 | uint8_t * data = (uint8_t *)buffer; 189 | for (i=0;inumber;i++) { 190 | a[i].wire_id = WT_BIT64; 191 | a[i].v.i.low = data[0] | 192 | data[1] << 8 | 193 | data[2] << 16 | 194 | data[3] << 24; 195 | a[i].v.i.hi = data[4] | 196 | data[5] << 8 | 197 | data[6] << 16 | 198 | data[7] << 24; 199 | data += 8; 200 | } 201 | } else { 202 | uint8_t * data = (uint8_t *)buffer; 203 | for (i=0;inumber;i++) { 204 | a[i].wire_id = WT_BIT32; 205 | a[i].v.i.low = data[0] | 206 | data[1] << 8 | 207 | data[2] << 16 | 208 | data[3] << 24; 209 | a[i].v.i.hi = 0; 210 | data += 4; 211 | } 212 | } 213 | 214 | return ctx->number; 215 | } 216 | 217 | int 218 | _pbcC_open(pbc_ctx _ctx , void *buffer, int size) { 219 | struct context * ctx = (struct context *)_ctx; 220 | ctx->buffer = (char *)buffer; 221 | ctx->size = size; 222 | 223 | if (buffer == NULL || size == 0) { 224 | ctx->number = 0; 225 | ctx->a = NULL; 226 | return 0; 227 | } 228 | 229 | struct atom * a = (struct atom *)(ctx + 1); 230 | 231 | int i; 232 | int start = 0; 233 | 234 | ctx->a = a; 235 | 236 | for (i=0;i 0) { 248 | int cap = 64; 249 | ctx->a = (struct atom *)malloc(cap * sizeof(struct atom)); 250 | while (size > 0) { 251 | if (i >= cap) { 252 | cap = cap + 64; 253 | ctx->a = (struct atom *)realloc(ctx->a, cap * sizeof(struct atom)); 254 | continue; 255 | } 256 | char * next = wiretype_decode((uint8_t *)buffer, size , &ctx->a[i] , start); 257 | if (next == NULL) { 258 | return -i; 259 | } 260 | start += next - (char *)buffer; 261 | size -= next - (char *)buffer; 262 | buffer = next; 263 | ++i; 264 | } 265 | memcpy(ctx->a, a , sizeof(struct atom) * INNER_ATOM); 266 | } 267 | ctx->number = i; 268 | 269 | return i; 270 | } 271 | 272 | 273 | void 274 | _pbcC_close(pbc_ctx _ctx) { 275 | struct context * ctx = (struct context *)_ctx; 276 | if (ctx->a != NULL && (struct atom *)(ctx+1) != ctx->a) { 277 | free(ctx->a); 278 | ctx->a = NULL; 279 | } 280 | } 281 | -------------------------------------------------------------------------------- /src/context.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOBUF_C_CONTEXT_H 2 | #define PROTOBUF_C_CONTEXT_H 3 | 4 | #include 5 | 6 | #include "array.h" 7 | 8 | #define PBC_CONTEXT_CAP 256 9 | 10 | // wiretype 11 | 12 | #define WT_VARINT 0 13 | #define WT_BIT64 1 14 | #define WT_LEND 2 15 | #define WT_BIT32 5 16 | 17 | #define CTYPE_INT32 1 18 | #define CTYPE_INT64 2 19 | #define CTYPE_DOUBLE 3 20 | #define CTYPE_FLOAT 4 21 | #define CTYPE_POINTER 5 22 | #define CTYPE_BOOL 6 23 | #define CTYPE_INT8 7 24 | #define CTYPE_INT16 8 25 | #define CTYPE_ARRAY 9 26 | #define CTYPE_VAR 10 27 | #define CTYPE_PACKED 11 28 | 29 | #define PTYPE_DOUBLE 1 30 | #define PTYPE_FLOAT 2 31 | #define PTYPE_INT64 3 // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if negative values are likely. 32 | #define PTYPE_UINT64 4 33 | #define PTYPE_INT32 5 // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if negative values are likely. 34 | #define PTYPE_FIXED64 6 35 | #define PTYPE_FIXED32 7 36 | #define PTYPE_BOOL 8 37 | #define PTYPE_STRING 9 38 | #define PTYPE_GROUP 10 // Tag-delimited aggregate. 39 | #define PTYPE_MESSAGE 11 // Length-delimited aggregate. 40 | #define PTYPE_BYTES 12 41 | #define PTYPE_UINT32 13 42 | #define PTYPE_ENUM 14 43 | #define PTYPE_SFIXED32 15 44 | #define PTYPE_SFIXED64 16 45 | #define PTYPE_SINT32 17 // Uses ZigZag encoding. 46 | #define PTYPE_SINT64 18 // Uses ZigZag encoding. 47 | 48 | struct slice { 49 | int start; 50 | int end; 51 | }; 52 | 53 | struct atom { 54 | int wire_id; 55 | union { 56 | struct slice s; 57 | struct longlong i; 58 | } v; 59 | }; 60 | 61 | struct context { 62 | char * buffer; 63 | int size; 64 | int number; 65 | struct atom * a; 66 | }; 67 | 68 | typedef struct _pbc_ctx { char _data[PBC_CONTEXT_CAP]; } pbc_ctx[1]; 69 | 70 | int _pbcC_open(pbc_ctx , void *buffer, int size); // <=0 failed 71 | int _pbcC_open_packed(pbc_ctx _ctx, int ptype, void *buffer, int size); 72 | void _pbcC_close(pbc_ctx); 73 | 74 | static inline double 75 | read_double(struct atom * a) { 76 | union { 77 | uint64_t i; 78 | double d; 79 | } u; 80 | u.i = (uint64_t) a->v.i.low | (uint64_t) a->v.i.hi << 32; 81 | return u.d; 82 | } 83 | 84 | static inline float 85 | read_float(struct atom * a) { 86 | union { 87 | uint32_t i; 88 | float f; 89 | } u; 90 | u.i = a->v.i.low; 91 | return u.f; 92 | } 93 | 94 | static inline void 95 | double_encode(double v , uint8_t * buffer) { 96 | union { 97 | double v; 98 | uint64_t e; 99 | } u; 100 | u.v = v; 101 | buffer[0] = (uint8_t) (u.e & 0xff); 102 | buffer[1] = (uint8_t) (u.e >> 8 & 0xff); 103 | buffer[2] = (uint8_t) (u.e >> 16 & 0xff); 104 | buffer[3] = (uint8_t) (u.e >> 24 & 0xff); 105 | buffer[4] = (uint8_t) (u.e >> 32 & 0xff); 106 | buffer[5] = (uint8_t) (u.e >> 40 & 0xff); 107 | buffer[6] = (uint8_t) (u.e >> 48 & 0xff); 108 | buffer[7] = (uint8_t) (u.e >> 56 & 0xff); 109 | } 110 | 111 | static inline void 112 | float_encode(float v , uint8_t * buffer) { 113 | union { 114 | float v; 115 | uint32_t e; 116 | } u; 117 | u.v = v; 118 | buffer[0] = (uint8_t) (u.e & 0xff); 119 | buffer[1] = (uint8_t) (u.e >> 8 & 0xff); 120 | buffer[2] = (uint8_t) (u.e >> 16 & 0xff); 121 | buffer[3] = (uint8_t) (u.e >> 24 & 0xff); 122 | } 123 | 124 | #define CHECK_LEND(a,err) if ((a->wire_id & 7) != WT_LEND) return err; 125 | 126 | #if 0 127 | /* maybe we don't need check these wire type */ 128 | #define CHECK_VARINT(a,err) if ((a->wire_id & 7) != WT_VARINT) return err; 129 | #define CHECK_BIT32(a,err) if ((a->wire_id & 7) != WT_BIT32) return err; 130 | #define CHECK_BIT64(a,err) if ((a->wire_id & 7) != WT_BIT64) return err; 131 | 132 | #else 133 | 134 | #define CHECK_VARINT(a,err) 135 | #define CHECK_BIT32(a,err) 136 | #define CHECK_BIT64(a,err) 137 | 138 | #endif 139 | 140 | #endif 141 | -------------------------------------------------------------------------------- /src/decode.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | #include "alloc.h" 3 | #include "context.h" 4 | #include "proto.h" 5 | #include "varint.h" 6 | 7 | #include 8 | 9 | static const char * TYPENAME[] = { 10 | "invalid", // 0 11 | "integer", // 1 12 | "real", // 2 13 | "boolean", // 3 14 | "enum", // 4 15 | "string", // 5 16 | "message", // 6 17 | "fixed64", // 7 18 | "fixed32", // 8 19 | "bytes", // 9 20 | "int64", // 10 21 | "uint", // 11 22 | }; 23 | 24 | static int 25 | call_unknown(pbc_decoder f, void * ud, int id, struct atom *a, uint8_t * start) { 26 | union pbc_value v; 27 | switch (a->wire_id & 7) { 28 | case WT_VARINT: 29 | v.i.low = a->v.i.low; 30 | v.i.hi = a->v.i.hi; 31 | f(ud, PBC_INT, TYPENAME[PBC_INT], &v, id , NULL); 32 | break; 33 | case WT_BIT64: 34 | v.i.low = a->v.i.low; 35 | v.i.hi = a->v.i.hi; 36 | f(ud, PBC_FIXED64, TYPENAME[PBC_FIXED64], &v, id , NULL); 37 | break; 38 | case WT_LEND: 39 | v.s.buffer = (char*)start + a->v.s.start; 40 | v.s.len = a->v.s.end - a->v.s.start; 41 | f(ud, PBC_BYTES, TYPENAME[PBC_BYTES], &v, id , NULL); 42 | break; 43 | case WT_BIT32: 44 | v.i.low = a->v.i.low; 45 | v.i.hi = 0; 46 | f(ud, PBC_FIXED32, TYPENAME[PBC_FIXED32], &v, id , NULL); 47 | break; 48 | default: 49 | return 1; 50 | } 51 | return 0; 52 | } 53 | 54 | static int 55 | call_type(pbc_decoder pd, void * ud, struct _field *f, struct atom *a, uint8_t * start) { 56 | union pbc_value v; 57 | const char * type_name = NULL; 58 | int type = _pbcP_type(f, &type_name); 59 | assert(type != 0); 60 | if (type_name == NULL) { 61 | type_name = TYPENAME[type & ~PBC_REPEATED]; 62 | } 63 | switch (f->type) { 64 | case PTYPE_DOUBLE: 65 | CHECK_BIT64(a, -1); 66 | v.f = read_double(a); 67 | break; 68 | case PTYPE_FLOAT: 69 | CHECK_BIT32(a, -1); 70 | v.f = (double) read_float(a); 71 | break; 72 | case PTYPE_ENUM: 73 | CHECK_VARINT(a, -1); 74 | v.e.id = a->v.i.low; 75 | v.e.name = (const char *)_pbcM_ip_query(f->type_name.e->id , v.e.id); 76 | break; 77 | case PTYPE_INT64: 78 | case PTYPE_UINT64: 79 | CHECK_VARINT(a, -1); 80 | v.i.low = a->v.i.low; 81 | v.i.hi = a->v.i.hi; 82 | break; 83 | case PTYPE_FIXED64: 84 | case PTYPE_SFIXED64: 85 | CHECK_BIT64(a, -1); 86 | v.i.low = a->v.i.low; 87 | v.i.hi = a->v.i.hi; 88 | break; 89 | case PTYPE_INT32: 90 | case PTYPE_UINT32: 91 | case PTYPE_BOOL: 92 | CHECK_VARINT(a, -1); 93 | v.i.low = a->v.i.low; 94 | v.i.hi = 0; 95 | break; 96 | case PTYPE_FIXED32: 97 | case PTYPE_SFIXED32: 98 | CHECK_BIT32(a, -1); 99 | v.i.low = a->v.i.low; 100 | v.i.hi = 0; 101 | break; 102 | case PTYPE_SINT32: 103 | CHECK_VARINT(a, -1); 104 | v.i.low = a->v.i.low; 105 | v.i.hi = a->v.i.hi; 106 | _pbcV_dezigzag32((struct longlong *)&(v.i)); 107 | break; 108 | case PTYPE_SINT64: 109 | CHECK_VARINT(a, -1); 110 | v.i.low = a->v.i.low; 111 | v.i.hi = a->v.i.hi; 112 | _pbcV_dezigzag64((struct longlong *)&(v.i)); 113 | break; 114 | case PTYPE_STRING: 115 | case PTYPE_BYTES: 116 | case PTYPE_MESSAGE: 117 | CHECK_LEND(a, -1); 118 | v.s.buffer = start + a->v.s.start; 119 | v.s.len = a->v.s.end - a->v.s.start; 120 | break; 121 | default: 122 | assert(0); 123 | break; 124 | } 125 | pd(ud, type, type_name, &v, f->id, f->name); 126 | return 0; 127 | } 128 | 129 | static int 130 | call_array(pbc_decoder pd, void * ud, struct _field *f, uint8_t * buffer , int size) { 131 | union pbc_value v; 132 | const char * type_name = NULL; 133 | int type = _pbcP_type(f, &type_name); 134 | assert(type != 0); 135 | if (type_name == NULL) { 136 | type_name = TYPENAME[type & ~PBC_REPEATED]; 137 | } 138 | v.i.hi = 0; 139 | int i; 140 | switch(f->type) { 141 | case PTYPE_DOUBLE: 142 | if (size % 8 != 0) { 143 | return -1; 144 | } 145 | for (i=0;iid, f->name); 160 | } 161 | return size/8; 162 | case PTYPE_FLOAT: 163 | if (size % 4 != 0) 164 | return -1; 165 | for (i=0;iid, f->name); 176 | } 177 | return size/4; 178 | case PTYPE_FIXED32: 179 | case PTYPE_SFIXED32: 180 | if (size % 4 != 0) 181 | return -1; 182 | for (i=0;iid, f->name); 188 | } 189 | return size/4; 190 | case PTYPE_FIXED64: 191 | case PTYPE_SFIXED64: 192 | if (size % 8 != 0) 193 | return -1; 194 | for (i=0;iid, f->name); 204 | } 205 | return size/8; 206 | case PTYPE_INT64: 207 | case PTYPE_UINT64: 208 | case PTYPE_INT32: 209 | case PTYPE_UINT32: 210 | case PTYPE_BOOL: { 211 | int n = 0; 212 | while (size > 0) { 213 | int len; 214 | if (size >= 10) { 215 | len = _pbcV_decode(buffer, (struct longlong *)&(v.i)); 216 | } else { 217 | uint8_t temp[10]; 218 | memcpy(temp, buffer, size); 219 | len = _pbcV_decode(buffer, (struct longlong *)&(v.i)); 220 | if (len > size) 221 | return -1; 222 | } 223 | pd(ud, type , type_name, &v, f->id, f->name); 224 | buffer += len; 225 | size -= len; 226 | ++n; 227 | } 228 | return n; 229 | } 230 | case PTYPE_ENUM: { 231 | int n = 0; 232 | while (size > 0) { 233 | int len; 234 | if (size >= 10) { 235 | len = _pbcV_decode(buffer, (struct longlong *)&(v.i)); 236 | } else { 237 | uint8_t temp[10]; 238 | memcpy(temp, buffer, size); 239 | len = _pbcV_decode(buffer, (struct longlong *)&(v.i)); 240 | if (len > size) 241 | return -1; 242 | } 243 | v.e.id = v.i.low; 244 | v.e.name = (const char *)_pbcM_ip_query(f->type_name.e->id , v.i.low); 245 | pd(ud, type , type_name, &v, f->id, f->name); 246 | buffer += len; 247 | size -= len; 248 | ++n; 249 | } 250 | return n; 251 | } 252 | case PTYPE_SINT32: { 253 | int n = 0; 254 | while (size > 0) { 255 | int len; 256 | if (size >= 10) { 257 | len = _pbcV_decode(buffer, (struct longlong *)&(v.i)); 258 | _pbcV_dezigzag32((struct longlong *)&(v.i)); 259 | } else { 260 | uint8_t temp[10]; 261 | memcpy(temp, buffer, size); 262 | len = _pbcV_decode(buffer, (struct longlong *)&(v.i)); 263 | if (len > size) 264 | return -1; 265 | _pbcV_dezigzag32((struct longlong *)&(v.i)); 266 | } 267 | pd(ud, type , type_name, &v, f->id, f->name); 268 | buffer += len; 269 | size -= len; 270 | ++n; 271 | } 272 | return n; 273 | } 274 | case PTYPE_SINT64: { 275 | int n = 0; 276 | while (size > 0) { 277 | int len; 278 | if (size >= 10) { 279 | len = _pbcV_decode(buffer, (struct longlong *)&(v.i)); 280 | _pbcV_dezigzag64((struct longlong *)&(v.i)); 281 | } else { 282 | uint8_t temp[10]; 283 | memcpy(temp, buffer, size); 284 | len = _pbcV_decode(buffer, (struct longlong *)&(v.i)); 285 | if (len > size) 286 | return -1; 287 | _pbcV_dezigzag64((struct longlong *)&(v.i)); 288 | } 289 | pd(ud, type , type_name, &v, f->id, f->name); 290 | buffer += len; 291 | size -= len; 292 | ++n; 293 | } 294 | return n; 295 | } 296 | default: 297 | return -1; 298 | } 299 | } 300 | 301 | int 302 | pbc_decode(struct pbc_env * env, const char * type_name , struct pbc_slice * slice, pbc_decoder pd, void *ud) { 303 | struct _message * msg = _pbcP_get_message(env, type_name); 304 | if (msg == NULL) { 305 | env->lasterror = "Proto not found"; 306 | return -1; 307 | } 308 | if (slice->len == 0) { 309 | return 0; 310 | } 311 | pbc_ctx _ctx; 312 | int count = _pbcC_open(_ctx,slice->buffer,slice->len); 313 | if (count <= 0) { 314 | env->lasterror = "decode context error"; 315 | _pbcC_close(_ctx); 316 | return count - 1; 317 | } 318 | struct context * ctx = (struct context *)_ctx; 319 | uint8_t * start = (uint8_t *)slice->buffer; 320 | 321 | int i; 322 | for (i=0;inumber;i++) { 323 | int id = ctx->a[i].wire_id >> 3; 324 | struct _field * f = (struct _field *)_pbcM_ip_query(msg->id , id); 325 | if (f==NULL) { 326 | int err = call_unknown(pd,ud,id,&ctx->a[i],start); 327 | if (err) { 328 | _pbcC_close(_ctx); 329 | return -i-1; 330 | } 331 | } else if (f->label == LABEL_PACKED) { 332 | struct atom * a = &ctx->a[i]; 333 | int n = call_array(pd, ud, f , start + a->v.s.start , a->v.s.end - a->v.s.start); 334 | if (n < 0) { 335 | _pbcC_close(_ctx); 336 | return -i-1; 337 | } 338 | } else { 339 | if (call_type(pd,ud,f,&ctx->a[i],start) != 0) { 340 | _pbcC_close(_ctx); 341 | return -i-1; 342 | } 343 | } 344 | } 345 | 346 | _pbcC_close(_ctx); 347 | return ctx->number; 348 | } 349 | 350 | -------------------------------------------------------------------------------- /src/descriptor.pbc.h: -------------------------------------------------------------------------------- 1 | static unsigned char pbc_descriptor[] = { 2 | 72,1,72,2,72,3,72,4,72,5,72,6,72,7,72,8, 3 | 72,9,72,10,72,11,72,12,72,13,72,14,72,15,72,16, 4 | 72,17,72,18,72,1,72,2,72,3,72,1,72,2,72,3, 5 | 72,0,72,1,72,2,50,42,103,111,111,103,108,101,46,112, 6 | 114,111,116,111,98,117,102,46,70,105,101,108,100,68,101,115, 7 | 99,114,105,112,116,111,114,80,114,111,116,111,46,84,121,112, 8 | 101,0,50,43,103,111,111,103,108,101,46,112,114,111,116,111, 9 | 98,117,102,46,70,105,101,108,100,68,101,115,99,114,105,112, 10 | 116,111,114,80,114,111,116,111,46,76,97,98,101,108,0,50, 11 | 41,103,111,111,103,108,101,46,112,114,111,116,111,98,117,102, 12 | 46,70,105,108,101,79,112,116,105,111,110,115,46,79,112,116, 13 | 105,109,105,122,101,77,111,100,101,0,50,35,103,111,111,103, 14 | 108,101,46,112,114,111,116,111,98,117,102,46,70,105,101,108, 15 | 100,79,112,116,105,111,110,115,46,67,84,121,112,101,0,66, 16 | 12,84,89,80,69,95,68,79,85,66,76,69,0,66,11,84, 17 | 89,80,69,95,70,76,79,65,84,0,66,11,84,89,80,69, 18 | 95,73,78,84,54,52,0,66,12,84,89,80,69,95,85,73, 19 | 78,84,54,52,0,66,11,84,89,80,69,95,73,78,84,51, 20 | 50,0,66,13,84,89,80,69,95,70,73,88,69,68,54,52, 21 | 0,66,13,84,89,80,69,95,70,73,88,69,68,51,50,0, 22 | 66,10,84,89,80,69,95,66,79,79,76,0,66,12,84,89, 23 | 80,69,95,83,84,82,73,78,71,0,66,11,84,89,80,69, 24 | 95,71,82,79,85,80,0,66,13,84,89,80,69,95,77,69, 25 | 83,83,65,71,69,0,66,11,84,89,80,69,95,66,89,84, 26 | 69,83,0,66,12,84,89,80,69,95,85,73,78,84,51,50, 27 | 0,66,10,84,89,80,69,95,69,78,85,77,0,66,14,84, 28 | 89,80,69,95,83,70,73,88,69,68,51,50,0,66,14,84, 29 | 89,80,69,95,83,70,73,88,69,68,54,52,0,66,12,84, 30 | 89,80,69,95,83,73,78,84,51,50,0,66,12,84,89,80, 31 | 69,95,83,73,78,84,54,52,0,66,15,76,65,66,69,76, 32 | 95,79,80,84,73,79,78,65,76,0,66,15,76,65,66,69, 33 | 76,95,82,69,81,85,73,82,69,68,0,66,15,76,65,66, 34 | 69,76,95,82,69,80,69,65,84,69,68,0,66,6,83,80, 35 | 69,69,68,0,66,10,67,79,68,69,95,83,73,90,69,0, 36 | 66,13,76,73,84,69,95,82,85,78,84,73,77,69,0,66, 37 | 7,83,84,82,73,78,71,0,66,5,67,79,82,68,0,66, 38 | 13,83,84,82,73,78,71,95,80,73,69,67,69,0,56,18, 39 | 56,3,56,3,56,3,10,11,100,101,115,99,114,105,112,116, 40 | 111,114,0,32,1,32,9,32,7,32,2,32,8,32,3,32, 41 | 3,32,3,32,4,32,9,32,3,32,5,32,1,32,1,32, 42 | 1,32,1,32,7,32,2,32,1,32,2,42,51,24,2,16, 43 | 1,32,11,42,36,103,111,111,103,108,101,46,112,114,111,116, 44 | 111,98,117,102,46,70,105,108,101,68,101,115,99,114,105,112, 45 | 116,111,114,80,114,111,116,111,0,10,5,102,105,108,101,0, 46 | 42,13,32,9,24,0,10,5,110,97,109,101,0,16,1,42, 47 | 16,32,9,24,0,10,8,112,97,99,107,97,103,101,0,16, 48 | 2,42,19,32,9,24,2,10,11,100,101,112,101,110,100,101, 49 | 110,99,121,0,16,3,42,55,24,2,16,4,32,11,42,32, 50 | 103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46, 51 | 68,101,115,99,114,105,112,116,111,114,80,114,111,116,111,0, 52 | 10,13,109,101,115,115,97,103,101,95,116,121,112,101,0,42, 53 | 56,24,2,16,5,32,11,42,36,103,111,111,103,108,101,46, 54 | 112,114,111,116,111,98,117,102,46,69,110,117,109,68,101,115, 55 | 99,114,105,112,116,111,114,80,114,111,116,111,0,10,10,101, 56 | 110,117,109,95,116,121,112,101,0,42,57,24,2,16,6,32, 57 | 11,42,39,103,111,111,103,108,101,46,112,114,111,116,111,98, 58 | 117,102,46,83,101,114,118,105,99,101,68,101,115,99,114,105, 59 | 112,116,111,114,80,114,111,116,111,0,10,8,115,101,114,118, 60 | 105,99,101,0,42,57,24,2,16,7,32,11,42,37,103,111, 61 | 111,103,108,101,46,112,114,111,116,111,98,117,102,46,70,105, 62 | 101,108,100,68,101,115,99,114,105,112,116,111,114,80,114,111, 63 | 116,111,0,10,10,101,120,116,101,110,115,105,111,110,0,42, 64 | 46,24,0,16,8,32,11,42,28,103,111,111,103,108,101,46, 65 | 112,114,111,116,111,98,117,102,46,70,105,108,101,79,112,116, 66 | 105,111,110,115,0,10,8,111,112,116,105,111,110,115,0,42, 67 | 58,24,0,16,9,32,11,42,31,103,111,111,103,108,101,46, 68 | 112,114,111,116,111,98,117,102,46,83,111,117,114,99,101,67, 69 | 111,100,101,73,110,102,111,0,10,17,115,111,117,114,99,101, 70 | 95,99,111,100,101,95,105,110,102,111,0,42,13,32,9,24, 71 | 0,10,5,110,97,109,101,0,16,1,42,53,24,2,16,2, 72 | 32,11,42,37,103,111,111,103,108,101,46,112,114,111,116,111, 73 | 98,117,102,46,70,105,101,108,100,68,101,115,99,114,105,112, 74 | 116,111,114,80,114,111,116,111,0,10,6,102,105,101,108,100, 75 | 0,42,57,24,2,16,6,32,11,42,37,103,111,111,103,108, 76 | 101,46,112,114,111,116,111,98,117,102,46,70,105,101,108,100, 77 | 68,101,115,99,114,105,112,116,111,114,80,114,111,116,111,0, 78 | 10,10,101,120,116,101,110,115,105,111,110,0,42,54,24,2, 79 | 16,3,32,11,42,32,103,111,111,103,108,101,46,112,114,111, 80 | 116,111,98,117,102,46,68,101,115,99,114,105,112,116,111,114, 81 | 80,114,111,116,111,0,10,12,110,101,115,116,101,100,95,116, 82 | 121,112,101,0,42,56,24,2,16,4,32,11,42,36,103,111, 83 | 111,103,108,101,46,112,114,111,116,111,98,117,102,46,69,110, 84 | 117,109,68,101,115,99,114,105,112,116,111,114,80,114,111,116, 85 | 111,0,10,10,101,110,117,109,95,116,121,112,101,0,42,73, 86 | 24,2,16,5,32,11,42,47,103,111,111,103,108,101,46,112, 87 | 114,111,116,111,98,117,102,46,68,101,115,99,114,105,112,116, 88 | 111,114,80,114,111,116,111,46,69,120,116,101,110,115,105,111, 89 | 110,82,97,110,103,101,0,10,16,101,120,116,101,110,115,105, 90 | 111,110,95,114,97,110,103,101,0,42,49,24,0,16,7,32, 91 | 11,42,31,103,111,111,103,108,101,46,112,114,111,116,111,98, 92 | 117,102,46,77,101,115,115,97,103,101,79,112,116,105,111,110, 93 | 115,0,10,8,111,112,116,105,111,110,115,0,42,14,32,5, 94 | 24,0,10,6,115,116,97,114,116,0,16,1,42,12,32,5, 95 | 24,0,10,4,101,110,100,0,16,2,42,13,32,9,24,0, 96 | 10,5,110,97,109,101,0,16,1,42,15,32,5,24,0,10, 97 | 7,110,117,109,98,101,114,0,16,3,42,59,24,0,16,4, 98 | 32,14,42,43,103,111,111,103,108,101,46,112,114,111,116,111, 99 | 98,117,102,46,70,105,101,108,100,68,101,115,99,114,105,112, 100 | 116,111,114,80,114,111,116,111,46,76,97,98,101,108,0,10, 101 | 6,108,97,98,101,108,0,42,57,24,0,16,5,32,14,42, 102 | 42,103,111,111,103,108,101,46,112,114,111,116,111,98,117,102, 103 | 46,70,105,101,108,100,68,101,115,99,114,105,112,116,111,114, 104 | 80,114,111,116,111,46,84,121,112,101,0,10,5,116,121,112, 105 | 101,0,42,18,32,9,24,0,10,10,116,121,112,101,95,110, 106 | 97,109,101,0,16,6,42,17,32,9,24,0,10,9,101,120, 107 | 116,101,110,100,101,101,0,16,2,42,22,32,9,24,0,10, 108 | 14,100,101,102,97,117,108,116,95,118,97,108,117,101,0,16, 109 | 7,42,47,24,0,16,8,32,11,42,29,103,111,111,103,108, 110 | 101,46,112,114,111,116,111,98,117,102,46,70,105,101,108,100, 111 | 79,112,116,105,111,110,115,0,10,8,111,112,116,105,111,110, 112 | 115,0,42,13,32,9,24,0,10,5,110,97,109,101,0,16, 113 | 1,42,57,24,2,16,2,32,11,42,41,103,111,111,103,108, 114 | 101,46,112,114,111,116,111,98,117,102,46,69,110,117,109,86, 115 | 97,108,117,101,68,101,115,99,114,105,112,116,111,114,80,114, 116 | 111,116,111,0,10,6,118,97,108,117,101,0,42,46,24,0, 117 | 16,3,32,11,42,28,103,111,111,103,108,101,46,112,114,111, 118 | 116,111,98,117,102,46,69,110,117,109,79,112,116,105,111,110, 119 | 115,0,10,8,111,112,116,105,111,110,115,0,42,13,32,9, 120 | 24,0,10,5,110,97,109,101,0,16,1,42,15,32,5,24, 121 | 0,10,7,110,117,109,98,101,114,0,16,2,42,51,24,0, 122 | 16,3,32,11,42,33,103,111,111,103,108,101,46,112,114,111, 123 | 116,111,98,117,102,46,69,110,117,109,86,97,108,117,101,79, 124 | 112,116,105,111,110,115,0,10,8,111,112,116,105,111,110,115, 125 | 0,42,13,32,9,24,0,10,5,110,97,109,101,0,16,1, 126 | 42,55,24,2,16,2,32,11,42,38,103,111,111,103,108,101, 127 | 46,112,114,111,116,111,98,117,102,46,77,101,116,104,111,100, 128 | 68,101,115,99,114,105,112,116,111,114,80,114,111,116,111,0, 129 | 10,7,109,101,116,104,111,100,0,42,49,24,0,16,3,32, 130 | 11,42,31,103,111,111,103,108,101,46,112,114,111,116,111,98, 131 | 117,102,46,83,101,114,118,105,99,101,79,112,116,105,111,110, 132 | 115,0,10,8,111,112,116,105,111,110,115,0,42,13,32,9, 133 | 24,0,10,5,110,97,109,101,0,16,1,42,19,32,9,24, 134 | 0,10,11,105,110,112,117,116,95,116,121,112,101,0,16,2, 135 | 42,20,32,9,24,0,10,12,111,117,116,112,117,116,95,116, 136 | 121,112,101,0,16,3,42,48,24,0,16,4,32,11,42,30, 137 | 103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46, 138 | 77,101,116,104,111,100,79,112,116,105,111,110,115,0,10,8, 139 | 111,112,116,105,111,110,115,0,42,21,32,9,24,0,10,13, 140 | 106,97,118,97,95,112,97,99,107,97,103,101,0,16,1,42, 141 | 29,32,9,24,0,10,21,106,97,118,97,95,111,117,116,101, 142 | 114,95,99,108,97,115,115,110,97,109,101,0,16,8,42,30, 143 | 24,0,16,10,32,8,10,20,106,97,118,97,95,109,117,108, 144 | 116,105,112,108,101,95,102,105,108,101,115,0,48,0,42,40, 145 | 24,0,16,20,32,8,10,30,106,97,118,97,95,103,101,110, 146 | 101,114,97,116,101,95,101,113,117,97,108,115,95,97,110,100, 147 | 95,104,97,115,104,0,48,0,42,72,24,0,16,9,32,14, 148 | 42,41,103,111,111,103,108,101,46,112,114,111,116,111,98,117, 149 | 102,46,70,105,108,101,79,112,116,105,111,110,115,46,79,112, 150 | 116,105,109,105,122,101,77,111,100,101,0,10,13,111,112,116, 151 | 105,109,105,122,101,95,102,111,114,0,58,6,83,80,69,69, 152 | 68,0,42,30,24,0,16,16,32,8,10,20,99,99,95,103, 153 | 101,110,101,114,105,99,95,115,101,114,118,105,99,101,115,0, 154 | 48,0,42,32,24,0,16,17,32,8,10,22,106,97,118,97, 155 | 95,103,101,110,101,114,105,99,95,115,101,114,118,105,99,101, 156 | 115,0,48,0,42,30,24,0,16,18,32,8,10,20,112,121, 157 | 95,103,101,110,101,114,105,99,95,115,101,114,118,105,99,101, 158 | 115,0,48,0,42,68,24,2,16,231,7,32,11,42,36,103, 159 | 111,111,103,108,101,46,112,114,111,116,111,98,117,102,46,85, 160 | 110,105,110,116,101,114,112,114,101,116,101,100,79,112,116,105, 161 | 111,110,0,10,21,117,110,105,110,116,101,114,112,114,101,116, 162 | 101,100,95,111,112,116,105,111,110,0,42,34,24,0,16,1, 163 | 32,8,10,24,109,101,115,115,97,103,101,95,115,101,116,95, 164 | 119,105,114,101,95,102,111,114,109,97,116,0,48,0,42,42, 165 | 24,0,16,2,32,8,10,32,110,111,95,115,116,97,110,100, 166 | 97,114,100,95,100,101,115,99,114,105,112,116,111,114,95,97, 167 | 99,99,101,115,115,111,114,0,48,0,42,68,24,2,16,231, 168 | 7,32,11,42,36,103,111,111,103,108,101,46,112,114,111,116, 169 | 111,98,117,102,46,85,110,105,110,116,101,114,112,114,101,116, 170 | 101,100,79,112,116,105,111,110,0,10,21,117,110,105,110,116, 171 | 101,114,112,114,101,116,101,100,95,111,112,116,105,111,110,0, 172 | 42,60,24,0,16,1,32,14,42,35,103,111,111,103,108,101, 173 | 46,112,114,111,116,111,98,117,102,46,70,105,101,108,100,79, 174 | 112,116,105,111,110,115,46,67,84,121,112,101,0,10,6,99, 175 | 116,121,112,101,0,58,7,83,84,82,73,78,71,0,42,15, 176 | 32,8,24,0,10,7,112,97,99,107,101,100,0,16,2,42, 177 | 21,24,0,16,3,32,8,10,11,100,101,112,114,101,99,97, 178 | 116,101,100,0,48,0,42,29,32,9,24,0,10,21,101,120, 179 | 112,101,114,105,109,101,110,116,97,108,95,109,97,112,95,107, 180 | 101,121,0,16,9,42,68,24,2,16,231,7,32,11,42,36, 181 | 103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46, 182 | 85,110,105,110,116,101,114,112,114,101,116,101,100,79,112,116, 183 | 105,111,110,0,10,21,117,110,105,110,116,101,114,112,114,101, 184 | 116,101,100,95,111,112,116,105,111,110,0,42,68,24,2,16, 185 | 231,7,32,11,42,36,103,111,111,103,108,101,46,112,114,111, 186 | 116,111,98,117,102,46,85,110,105,110,116,101,114,112,114,101, 187 | 116,101,100,79,112,116,105,111,110,0,10,21,117,110,105,110, 188 | 116,101,114,112,114,101,116,101,100,95,111,112,116,105,111,110, 189 | 0,42,68,24,2,16,231,7,32,11,42,36,103,111,111,103, 190 | 108,101,46,112,114,111,116,111,98,117,102,46,85,110,105,110, 191 | 116,101,114,112,114,101,116,101,100,79,112,116,105,111,110,0, 192 | 10,21,117,110,105,110,116,101,114,112,114,101,116,101,100,95, 193 | 111,112,116,105,111,110,0,42,68,24,2,16,231,7,32,11, 194 | 42,36,103,111,111,103,108,101,46,112,114,111,116,111,98,117, 195 | 102,46,85,110,105,110,116,101,114,112,114,101,116,101,100,79, 196 | 112,116,105,111,110,0,10,21,117,110,105,110,116,101,114,112, 197 | 114,101,116,101,100,95,111,112,116,105,111,110,0,42,68,24, 198 | 2,16,231,7,32,11,42,36,103,111,111,103,108,101,46,112, 199 | 114,111,116,111,98,117,102,46,85,110,105,110,116,101,114,112, 200 | 114,101,116,101,100,79,112,116,105,111,110,0,10,21,117,110, 201 | 105,110,116,101,114,112,114,101,116,101,100,95,111,112,116,105, 202 | 111,110,0,42,60,24,2,16,2,32,11,42,45,103,111,111, 203 | 103,108,101,46,112,114,111,116,111,98,117,102,46,85,110,105, 204 | 110,116,101,114,112,114,101,116,101,100,79,112,116,105,111,110, 205 | 46,78,97,109,101,80,97,114,116,0,10,5,110,97,109,101, 206 | 0,42,25,32,9,24,0,10,17,105,100,101,110,116,105,102, 207 | 105,101,114,95,118,97,108,117,101,0,16,3,42,27,32,4, 208 | 24,0,10,19,112,111,115,105,116,105,118,101,95,105,110,116, 209 | 95,118,97,108,117,101,0,16,4,42,27,32,3,24,0,10, 210 | 19,110,101,103,97,116,105,118,101,95,105,110,116,95,118,97, 211 | 108,117,101,0,16,5,42,21,32,1,24,0,10,13,100,111, 212 | 117,98,108,101,95,118,97,108,117,101,0,16,6,42,21,32, 213 | 12,24,0,10,13,115,116,114,105,110,103,95,118,97,108,117, 214 | 101,0,16,7,42,24,32,9,24,0,10,16,97,103,103,114, 215 | 101,103,97,116,101,95,118,97,108,117,101,0,16,8,42,18, 216 | 32,9,24,1,10,10,110,97,109,101,95,112,97,114,116,0, 217 | 16,1,42,21,32,8,24,1,10,13,105,115,95,101,120,116, 218 | 101,110,115,105,111,110,0,16,2,42,59,24,2,16,1,32, 219 | 11,42,40,103,111,111,103,108,101,46,112,114,111,116,111,98, 220 | 117,102,46,83,111,117,114,99,101,67,111,100,101,73,110,102, 221 | 111,46,76,111,99,97,116,105,111,110,0,10,9,108,111,99, 222 | 97,116,105,111,110,0,42,13,32,5,24,2,10,5,112,97, 223 | 116,104,0,16,1,42,13,32,5,24,2,10,5,115,112,97, 224 | 110,0,16,2,26,34,103,111,111,103,108,101,46,112,114,111, 225 | 116,111,98,117,102,46,70,105,108,101,68,101,115,99,114,105, 226 | 112,116,111,114,83,101,116,0,26,36,103,111,111,103,108,101, 227 | 46,112,114,111,116,111,98,117,102,46,70,105,108,101,68,101, 228 | 115,99,114,105,112,116,111,114,80,114,111,116,111,0,26,32, 229 | 103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46, 230 | 68,101,115,99,114,105,112,116,111,114,80,114,111,116,111,0, 231 | 26,47,103,111,111,103,108,101,46,112,114,111,116,111,98,117, 232 | 102,46,68,101,115,99,114,105,112,116,111,114,80,114,111,116, 233 | 111,46,69,120,116,101,110,115,105,111,110,82,97,110,103,101, 234 | 0,26,37,103,111,111,103,108,101,46,112,114,111,116,111,98, 235 | 117,102,46,70,105,101,108,100,68,101,115,99,114,105,112,116, 236 | 111,114,80,114,111,116,111,0,26,36,103,111,111,103,108,101, 237 | 46,112,114,111,116,111,98,117,102,46,69,110,117,109,68,101, 238 | 115,99,114,105,112,116,111,114,80,114,111,116,111,0,26,41, 239 | 103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46, 240 | 69,110,117,109,86,97,108,117,101,68,101,115,99,114,105,112, 241 | 116,111,114,80,114,111,116,111,0,26,39,103,111,111,103,108, 242 | 101,46,112,114,111,116,111,98,117,102,46,83,101,114,118,105, 243 | 99,101,68,101,115,99,114,105,112,116,111,114,80,114,111,116, 244 | 111,0,26,38,103,111,111,103,108,101,46,112,114,111,116,111, 245 | 98,117,102,46,77,101,116,104,111,100,68,101,115,99,114,105, 246 | 112,116,111,114,80,114,111,116,111,0,26,28,103,111,111,103, 247 | 108,101,46,112,114,111,116,111,98,117,102,46,70,105,108,101, 248 | 79,112,116,105,111,110,115,0,26,31,103,111,111,103,108,101, 249 | 46,112,114,111,116,111,98,117,102,46,77,101,115,115,97,103, 250 | 101,79,112,116,105,111,110,115,0,26,29,103,111,111,103,108, 251 | 101,46,112,114,111,116,111,98,117,102,46,70,105,101,108,100, 252 | 79,112,116,105,111,110,115,0,26,28,103,111,111,103,108,101, 253 | 46,112,114,111,116,111,98,117,102,46,69,110,117,109,79,112, 254 | 116,105,111,110,115,0,26,33,103,111,111,103,108,101,46,112, 255 | 114,111,116,111,98,117,102,46,69,110,117,109,86,97,108,117, 256 | 101,79,112,116,105,111,110,115,0,26,31,103,111,111,103,108, 257 | 101,46,112,114,111,116,111,98,117,102,46,83,101,114,118,105, 258 | 99,101,79,112,116,105,111,110,115,0,26,30,103,111,111,103, 259 | 108,101,46,112,114,111,116,111,98,117,102,46,77,101,116,104, 260 | 111,100,79,112,116,105,111,110,115,0,26,36,103,111,111,103, 261 | 108,101,46,112,114,111,116,111,98,117,102,46,85,110,105,110, 262 | 116,101,114,112,114,101,116,101,100,79,112,116,105,111,110,0, 263 | 26,45,103,111,111,103,108,101,46,112,114,111,116,111,98,117, 264 | 102,46,85,110,105,110,116,101,114,112,114,101,116,101,100,79, 265 | 112,116,105,111,110,46,78,97,109,101,80,97,114,116,0,26, 266 | 31,103,111,111,103,108,101,46,112,114,111,116,111,98,117,102, 267 | 46,83,111,117,114,99,101,67,111,100,101,73,110,102,111,0, 268 | 26,40,103,111,111,103,108,101,46,112,114,111,116,111,98,117, 269 | 102,46,83,111,117,114,99,101,67,111,100,101,73,110,102,111, 270 | 46,76,111,99,97,116,105,111,110,0, 271 | }; -------------------------------------------------------------------------------- /src/map.c: -------------------------------------------------------------------------------- 1 | #include "map.h" 2 | #include "alloc.h" 3 | 4 | #include 5 | #include 6 | 7 | struct _pbcM_ip_slot { 8 | int id; 9 | void * pointer; 10 | int next; 11 | }; 12 | 13 | struct map_ip { 14 | size_t array_size; 15 | void ** array; 16 | size_t hash_size; 17 | struct _pbcM_ip_slot * slot; 18 | }; 19 | 20 | struct _pbcM_si_slot { 21 | const char *key; 22 | size_t hash; 23 | int id; 24 | int next; 25 | }; 26 | 27 | struct map_si { 28 | size_t size; 29 | struct _pbcM_si_slot slot[1]; 30 | }; 31 | 32 | static size_t 33 | calc_hash(const char *name) 34 | { 35 | size_t len = strlen(name); 36 | size_t h = len; 37 | size_t step = (len>>5)+1; 38 | size_t i; 39 | for (i=len; i>=step; i-=step) 40 | h = h ^ ((h<<5)+(h>>2)+(size_t)name[i-1]); 41 | return h; 42 | } 43 | 44 | struct map_si * 45 | _pbcM_si_new(struct map_kv * table, int size) 46 | { 47 | size_t sz = sizeof(struct map_si) + (size-1) * sizeof(struct _pbcM_si_slot); 48 | struct map_si * ret = (struct map_si *)malloc(sz); 49 | memset(ret,0,sz); 50 | 51 | ret->size = (size_t)size; 52 | 53 | int empty = 0; 54 | int i; 55 | 56 | for (i=0;islot[hash]; 60 | if (slot->key == NULL) { 61 | slot->key = (const char *)table[i].pointer; 62 | slot->id = table[i].id; 63 | slot->hash = hash_full; 64 | } else { 65 | while(ret->slot[empty].key != NULL) { 66 | ++empty; 67 | } 68 | struct _pbcM_si_slot * empty_slot = &ret->slot[empty]; 69 | empty_slot->next = slot->next; 70 | slot->next = empty + 1; 71 | empty_slot->id = table[i].id; 72 | empty_slot->key = (const char *)table[i].pointer; 73 | empty_slot->hash = hash_full; 74 | } 75 | } 76 | 77 | return ret; 78 | } 79 | 80 | void 81 | _pbcM_si_delete(struct map_si *map) 82 | { 83 | free(map); 84 | } 85 | 86 | int 87 | _pbcM_si_query(struct map_si *map, const char *key, int *result) 88 | { 89 | size_t hash_full = calc_hash(key); 90 | size_t hash = hash_full % map->size; 91 | 92 | struct _pbcM_si_slot * slot = &map->slot[hash]; 93 | if (slot->key == NULL) { 94 | return 1; 95 | } 96 | for (;;) { 97 | if (slot->hash == hash_full && strcmp(slot->key, key) == 0) { 98 | *result = slot->id; 99 | return 0; 100 | } 101 | if (slot->next == 0) { 102 | return 1; 103 | } 104 | slot = &map->slot[slot->next-1]; 105 | } 106 | } 107 | 108 | static struct map_ip * 109 | _pbcM_ip_new_hash(struct map_kv * table, int size) 110 | { 111 | struct map_ip * ret = (struct map_ip *)malloc(sizeof(struct map_ip)); 112 | ret->array = NULL; 113 | ret->array_size = 0; 114 | ret->hash_size = (size_t)size; 115 | ret->slot = (struct _pbcM_ip_slot *)malloc(sizeof(struct _pbcM_ip_slot) * size); 116 | memset(ret->slot,0,sizeof(struct _pbcM_ip_slot) * size); 117 | int empty = 0; 118 | int i; 119 | for (i=0;islot[hash]; 122 | if (slot->pointer == NULL) { 123 | slot->pointer = table[i].pointer; 124 | slot->id = table[i].id; 125 | } else { 126 | while(ret->slot[empty].pointer != NULL) { 127 | ++empty; 128 | } 129 | struct _pbcM_ip_slot * empty_slot = &ret->slot[empty]; 130 | empty_slot->next = slot->next; 131 | slot->next = empty + 1; 132 | empty_slot->id = table[i].id; 133 | empty_slot->pointer = table[i].pointer; 134 | } 135 | } 136 | return ret; 137 | } 138 | 139 | struct map_ip * 140 | _pbcM_ip_new(struct map_kv * table, int size) 141 | { 142 | int i; 143 | int max = table[0].id; 144 | if (max > size * 2 || max < 0) 145 | return _pbcM_ip_new_hash(table,size); 146 | for (i=1;i max) { 151 | max = table[i].id; 152 | if (max > size * 2) 153 | return _pbcM_ip_new_hash(table,size); 154 | } 155 | } 156 | struct map_ip * ret = (struct map_ip *)malloc(sizeof(struct map_ip)); 157 | ret->hash_size = size; 158 | ret->slot = NULL; 159 | ret->array_size = max + 1; 160 | ret->array = (void **)malloc((max+1) * sizeof(void *)); 161 | memset(ret->array,0,(max+1) * sizeof(void *)); 162 | for (i=0;iarray[table[i].id] = table[i].pointer; 164 | } 165 | return ret; 166 | } 167 | 168 | void 169 | _pbcM_ip_delete(struct map_ip * map) 170 | { 171 | if (map) { 172 | free(map->array); 173 | free(map->slot); 174 | free(map); 175 | } 176 | } 177 | 178 | static void 179 | _inject(struct map_kv * table, struct map_ip *map) 180 | { 181 | if (map->array) { 182 | int n = 0; 183 | int i; 184 | for (i=0;i<(int)map->array_size;i++) { 185 | if (map->array[i]) { 186 | table[n].id = i; 187 | table[n].pointer = map->array[i]; 188 | ++ n; 189 | } 190 | } 191 | } else { 192 | int i; 193 | for (i=0;i<(int)map->hash_size;i++) { 194 | table[i].id = map->slot[i].id; 195 | table[i].pointer = map->slot[i].pointer; 196 | } 197 | } 198 | } 199 | 200 | struct map_ip * 201 | _pbcM_ip_combine(struct map_ip *a, struct map_ip *b) 202 | { 203 | int sz = (int)(a->hash_size + b->hash_size); 204 | struct map_kv * table = (struct map_kv *)malloc(sz * sizeof(struct map_kv)); 205 | memset(table , 0 , sz * sizeof(struct map_kv)); 206 | _inject(table, a); 207 | _inject(table + a->hash_size, b); 208 | struct map_ip * r = _pbcM_ip_new(table, sz); 209 | free(table); 210 | return r; 211 | } 212 | 213 | void * 214 | _pbcM_ip_query(struct map_ip * map, int id) 215 | { 216 | if (map == NULL) 217 | return NULL; 218 | if (map->array) { 219 | if (id>=0 && id<(int)map->array_size) 220 | return map->array[id]; 221 | return NULL; 222 | } 223 | int hash = (unsigned)id % map->hash_size; 224 | struct _pbcM_ip_slot * slot = &map->slot[hash]; 225 | for (;;) { 226 | if (slot->id == id) { 227 | return slot->pointer; 228 | } 229 | if (slot->next == 0) { 230 | return NULL; 231 | } 232 | slot = &map->slot[slot->next-1]; 233 | } 234 | } 235 | 236 | struct _pbcM_sp_slot { 237 | const char *key; 238 | size_t hash; 239 | void *pointer; 240 | int next; 241 | }; 242 | 243 | struct map_sp { 244 | size_t cap; 245 | size_t size; 246 | struct heap *heap; 247 | struct _pbcM_sp_slot * slot; 248 | }; 249 | 250 | struct map_sp * 251 | _pbcM_sp_new(int max , struct heap *h) 252 | { 253 | struct map_sp * ret = (struct map_sp *)HMALLOC(sizeof(struct map_sp)); 254 | int cap = 1; 255 | while (cap < max) { 256 | cap *=2; 257 | } 258 | ret->cap = cap; 259 | ret->size = 0; 260 | ret->slot = (struct _pbcM_sp_slot *)HMALLOC(ret->cap * sizeof(struct _pbcM_sp_slot)); 261 | memset(ret->slot,0,sizeof(struct _pbcM_sp_slot) * ret->cap); 262 | ret->heap = h; 263 | return ret; 264 | } 265 | 266 | void 267 | _pbcM_sp_delete(struct map_sp *map) 268 | { 269 | if (map && map->heap == NULL) { 270 | _pbcM_free(map->slot); 271 | _pbcM_free(map); 272 | } 273 | } 274 | 275 | static void _pbcM_sp_rehash(struct map_sp *map); 276 | 277 | static void 278 | _pbcM_sp_insert_hash(struct map_sp *map, const char *key, size_t hash_full, void * value) 279 | { 280 | if (map->cap > map->size) { 281 | size_t hash = hash_full & (map->cap-1); 282 | struct _pbcM_sp_slot * slot = &map->slot[hash]; 283 | if (slot->key == NULL) { 284 | slot->key = key; 285 | slot->pointer = value; 286 | slot->hash = hash_full; 287 | } else { 288 | int empty = (hash + 1) & (map->cap-1); 289 | while(map->slot[empty].key != NULL) { 290 | empty = (empty + 1) & (map->cap-1); 291 | } 292 | struct _pbcM_sp_slot * empty_slot = &map->slot[empty]; 293 | empty_slot->next = slot->next; 294 | slot->next = empty + 1; 295 | empty_slot->pointer = value; 296 | empty_slot->key = key; 297 | empty_slot->hash = hash_full; 298 | } 299 | map->size++; 300 | return; 301 | } 302 | _pbcM_sp_rehash(map); 303 | _pbcM_sp_insert_hash(map, key, hash_full, value); 304 | } 305 | 306 | static void 307 | _pbcM_sp_rehash(struct map_sp *map) { 308 | struct heap * h = map->heap; 309 | struct _pbcM_sp_slot * old_slot = map->slot; 310 | size_t size = map->size; 311 | map->size = 0; 312 | map->cap *= 2; 313 | map->slot = (struct _pbcM_sp_slot *)HMALLOC(sizeof(struct _pbcM_sp_slot)*map->cap); 314 | memset(map->slot,0,sizeof(struct _pbcM_sp_slot)*map->cap); 315 | size_t i; 316 | for (i=0;icap-1); 328 | struct _pbcM_sp_slot * slot = &map->slot[hash]; 329 | if (slot->key == NULL) { 330 | if (map->cap <= map->size) 331 | goto _rehash; 332 | slot->key = key; 333 | slot->hash = hash_full; 334 | map->size++; 335 | return &(slot->pointer); 336 | } else { 337 | for (;;) { 338 | if (slot->hash == hash_full && strcmp(slot->key, key) == 0) 339 | return &(slot->pointer); 340 | if (slot->next == 0) { 341 | break; 342 | } 343 | slot = &map->slot[slot->next-1]; 344 | } 345 | if (map->cap <= map->size) 346 | goto _rehash; 347 | 348 | int empty = (hash + 1) & (map->cap-1); 349 | while(map->slot[empty].key != NULL) { 350 | empty = (empty + 1) & (map->cap-1); 351 | } 352 | struct _pbcM_sp_slot * empty_slot = &map->slot[empty]; 353 | empty_slot->next = slot->next; 354 | slot->next = empty + 1; 355 | empty_slot->key = key; 356 | empty_slot->hash = hash_full; 357 | 358 | map->size++; 359 | 360 | return &(empty_slot->pointer); 361 | } 362 | _rehash: 363 | _pbcM_sp_rehash(map); 364 | return _pbcM_sp_query_insert_hash(map, key, hash_full); 365 | } 366 | 367 | void 368 | _pbcM_sp_insert(struct map_sp *map, const char *key, void * value) 369 | { 370 | _pbcM_sp_insert_hash(map,key,calc_hash(key),value); 371 | } 372 | 373 | void ** 374 | _pbcM_sp_query_insert(struct map_sp *map, const char *key) 375 | { 376 | return _pbcM_sp_query_insert_hash(map,key,calc_hash(key)); 377 | } 378 | 379 | void * 380 | _pbcM_sp_query(struct map_sp *map, const char *key) 381 | { 382 | if (map == NULL) 383 | return NULL; 384 | size_t hash_full = calc_hash(key); 385 | size_t hash = hash_full & (map->cap -1); 386 | 387 | struct _pbcM_sp_slot * slot = &map->slot[hash]; 388 | if (slot->key == NULL) 389 | return NULL; 390 | for (;;) { 391 | if (slot->hash == hash_full && strcmp(slot->key, key) == 0) { 392 | return slot->pointer; 393 | } 394 | if (slot->next == 0) { 395 | return NULL; 396 | } 397 | slot = &map->slot[slot->next-1]; 398 | } 399 | } 400 | 401 | void 402 | _pbcM_sp_foreach(struct map_sp *map, void (*func)(void *p)) 403 | { 404 | size_t i; 405 | for (i=0;icap;i++) { 406 | if (map->slot[i].pointer) { 407 | func(map->slot[i].pointer); 408 | } 409 | } 410 | } 411 | 412 | void 413 | _pbcM_sp_foreach_ud(struct map_sp *map, void (*func)(void *p, void *ud), void *ud) 414 | { 415 | size_t i; 416 | for (i=0;icap;i++) { 417 | if (map->slot[i].pointer) { 418 | func(map->slot[i].pointer,ud); 419 | } 420 | } 421 | } 422 | 423 | static int 424 | _find_first(struct map_sp *map) 425 | { 426 | size_t i; 427 | for (i=0;icap;i++) { 428 | if (map->slot[i].pointer) { 429 | return i; 430 | } 431 | } 432 | return -1; 433 | } 434 | 435 | static int 436 | _find_next(struct map_sp *map, const char *key) 437 | { 438 | size_t hash_full = calc_hash(key); 439 | size_t hash = hash_full & (map->cap -1); 440 | 441 | struct _pbcM_sp_slot * slot = &map->slot[hash]; 442 | if (slot->key == NULL) 443 | return -1; 444 | for (;;) { 445 | if (slot->hash == hash_full && strcmp(slot->key, key) == 0) { 446 | int i = slot - map->slot + 1; 447 | while(icap) { 448 | if (map->slot[i].pointer) { 449 | return i; 450 | } 451 | ++i; 452 | } 453 | return -1; 454 | } 455 | if (slot->next == 0) { 456 | return -1; 457 | } 458 | slot = &map->slot[slot->next-1]; 459 | } 460 | } 461 | 462 | void * 463 | _pbcM_sp_next(struct map_sp *map, const char ** key) 464 | { 465 | if (map == NULL) { 466 | *key = NULL; 467 | return NULL; 468 | } 469 | int idx; 470 | if (*key == NULL) { 471 | idx = _find_first(map); 472 | } else { 473 | idx = _find_next(map, *key); 474 | } 475 | if (idx < 0) { 476 | *key = NULL; 477 | return NULL; 478 | } 479 | *key = map->slot[idx].key; 480 | return map->slot[idx].pointer; 481 | } 482 | 483 | 484 | 485 | -------------------------------------------------------------------------------- /src/map.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOBUF_C_MAP_H 2 | #define PROTOBUF_C_MAP_H 3 | 4 | #include "alloc.h" 5 | 6 | struct map_ip; 7 | struct map_si; 8 | struct map_sp; 9 | 10 | struct map_kv { 11 | int id; 12 | void *pointer; 13 | }; 14 | 15 | struct map_si * _pbcM_si_new(struct map_kv * table, int size); 16 | int _pbcM_si_query(struct map_si *map, const char *key, int *result); 17 | void _pbcM_si_delete(struct map_si *map); 18 | 19 | struct map_ip * _pbcM_ip_new(struct map_kv * table, int size); 20 | struct map_ip * _pbcM_ip_combine(struct map_ip * a, struct map_ip * b); 21 | void * _pbcM_ip_query(struct map_ip * map, int id); 22 | void _pbcM_ip_delete(struct map_ip *map); 23 | 24 | struct map_sp * _pbcM_sp_new(int max, struct heap *h); 25 | void _pbcM_sp_insert(struct map_sp *map, const char *key, void * value); 26 | void * _pbcM_sp_query(struct map_sp *map, const char *key); 27 | void ** _pbcM_sp_query_insert(struct map_sp *map, const char *key); 28 | void _pbcM_sp_delete(struct map_sp *map); 29 | void _pbcM_sp_foreach(struct map_sp *map, void (*func)(void *p)); 30 | void _pbcM_sp_foreach_ud(struct map_sp *map, void (*func)(void *p, void *ud), void *ud); 31 | void * _pbcM_sp_next(struct map_sp *map, const char ** key); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/pattern.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOBUF_C_PATTERN_H 2 | #define PROTOBUF_C_PATTERN_H 3 | 4 | #include "pbc.h" 5 | #include "context.h" 6 | #include "array.h" 7 | 8 | struct _pattern_field { 9 | int id; 10 | int offset; 11 | int ptype; 12 | int ctype; 13 | int label; 14 | pbc_var defv; 15 | }; 16 | 17 | struct pbc_pattern { 18 | struct pbc_env * env; 19 | int count; 20 | struct _pattern_field f[1]; 21 | }; 22 | 23 | struct pbc_pattern * _pbcP_new(struct pbc_env * env, int n); 24 | int _pbcP_unpack_packed(uint8_t *buffer, int size, int ptype, pbc_array array); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/proto.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | #include "proto.h" 3 | #include "pattern.h" 4 | #include "map.h" 5 | #include "alloc.h" 6 | #include "stringpool.h" 7 | #include "bootstrap.h" 8 | 9 | #include 10 | #include 11 | 12 | const char * 13 | pbc_error(struct pbc_env * p) { 14 | const char *err = p->lasterror; 15 | p->lasterror = ""; 16 | return err; 17 | } 18 | 19 | struct _message * 20 | _pbcP_get_message(struct pbc_env * p , const char *name) { 21 | return (struct _message *)_pbcM_sp_query(p->msgs, name); 22 | } 23 | 24 | struct pbc_env * 25 | pbc_new(void) { 26 | struct pbc_env * p = (struct pbc_env *)malloc(sizeof(*p)); 27 | p->files = _pbcM_sp_new(0 , NULL); 28 | p->enums = _pbcM_sp_new(0 , NULL); 29 | p->msgs = _pbcM_sp_new(0 , NULL); 30 | p->lasterror = ""; 31 | 32 | _pbcB_init(p); 33 | 34 | return p; 35 | } 36 | 37 | static void 38 | free_enum(void *p) { 39 | struct _enum * e = (struct _enum *)p; 40 | _pbcM_ip_delete(e->id); 41 | _pbcM_si_delete(e->name); 42 | 43 | free(p); 44 | } 45 | 46 | static void 47 | free_stringpool(void *p) { 48 | _pbcS_delete((struct _stringpool *)p); 49 | } 50 | 51 | static void 52 | free_msg(void *p) { 53 | struct _message * m = (struct _message *)p; 54 | if (m->id) 55 | _pbcM_ip_delete(m->id); 56 | free(m->def); 57 | _pbcM_sp_foreach(m->name, free); 58 | _pbcM_sp_delete(m->name); 59 | free(p); 60 | } 61 | 62 | void 63 | pbc_delete(struct pbc_env *p) { 64 | _pbcM_sp_foreach(p->enums, free_enum); 65 | _pbcM_sp_delete(p->enums); 66 | 67 | _pbcM_sp_foreach(p->msgs, free_msg); 68 | _pbcM_sp_delete(p->msgs); 69 | 70 | _pbcM_sp_foreach(p->files, free_stringpool); 71 | _pbcM_sp_delete(p->files); 72 | 73 | free(p); 74 | } 75 | 76 | struct _enum * 77 | _pbcP_push_enum(struct pbc_env * p, const char *name, struct map_kv *table, int sz) { 78 | void * check = _pbcM_sp_query(p->enums, name); 79 | if (check) 80 | return NULL; 81 | struct _enum * v = (struct _enum *)malloc(sizeof(*v)); 82 | v->key = name; 83 | v->id = _pbcM_ip_new(table,sz); 84 | v->name = _pbcM_si_new(table,sz); 85 | v->default_v->e.id = table[0].id; 86 | v->default_v->e.name = (const char *)table[0].pointer; 87 | 88 | _pbcM_sp_insert(p->enums, name , v); 89 | return v; 90 | } 91 | 92 | void 93 | _pbcP_push_message(struct pbc_env * p, const char *name, struct _field *f , pbc_array queue) { 94 | struct _message * m = (struct _message *)_pbcM_sp_query(p->msgs, name); 95 | if (m==NULL) { 96 | m = (struct _message *)malloc(sizeof(*m)); 97 | m->def = NULL; 98 | m->key = name; 99 | m->id = NULL; 100 | m->name = _pbcM_sp_new(0 , NULL); 101 | m->env = p; 102 | _pbcM_sp_insert(p->msgs, name, m); 103 | } 104 | struct _field * field = (struct _field *)malloc(sizeof(*field)); 105 | memcpy(field,f,sizeof(*f)); 106 | _pbcM_sp_insert(m->name, field->name, field); 107 | pbc_var atom; 108 | atom->m.buffer = field; 109 | if (f->type == PTYPE_MESSAGE || f->type == PTYPE_ENUM) { 110 | _pbcA_push(queue, atom); 111 | } 112 | } 113 | 114 | struct _iter { 115 | int count; 116 | struct map_kv * table; 117 | }; 118 | 119 | static void 120 | _count(void *p, void *ud) { 121 | struct _iter *iter = (struct _iter *)ud; 122 | iter->count ++; 123 | } 124 | 125 | static void 126 | _set_table(void *p, void *ud) { 127 | struct _field * field = (struct _field *)p; 128 | struct _iter *iter = (struct _iter *)ud; 129 | iter->table[iter->count].id = field->id; 130 | iter->table[iter->count].pointer = field; 131 | ++iter->count; 132 | } 133 | 134 | struct _message * 135 | _pbcP_init_message(struct pbc_env * p, const char *name) { 136 | struct _message * m = (struct _message *)_pbcM_sp_query(p->msgs, name); 137 | if (m == NULL) { 138 | m = (struct _message *)malloc(sizeof(*m)); 139 | m->def = NULL; 140 | m->key = name; 141 | m->id = NULL; 142 | m->name = _pbcM_sp_new(0 , NULL); 143 | m->env = p; 144 | _pbcM_sp_insert(p->msgs, name, m); 145 | 146 | return m; 147 | } 148 | if (m->id) { 149 | // extend message, delete old id map. 150 | _pbcM_ip_delete(m->id); 151 | } 152 | struct _iter iter = { 0, NULL }; 153 | _pbcM_sp_foreach_ud(m->name, _count, &iter); 154 | iter.table = (struct map_kv *)malloc(iter.count * sizeof(struct map_kv)); 155 | iter.count = 0; 156 | _pbcM_sp_foreach_ud(m->name, _set_table, &iter); 157 | 158 | m->id = _pbcM_ip_new(iter.table , iter.count); 159 | 160 | free(iter.table); 161 | 162 | return m; 163 | } 164 | 165 | int 166 | _pbcP_message_default(struct _message * m, const char * name, pbc_var defv) { 167 | struct _field * f= (struct _field *)_pbcM_sp_query(m->name, name); 168 | if (f==NULL) { 169 | // invalid key 170 | defv->p[0] = NULL; 171 | defv->p[1] = NULL; 172 | return -1; 173 | } 174 | *defv = *(f->default_v); 175 | return f->type; 176 | } 177 | 178 | int 179 | _pbcP_type(struct _field * field, const char ** type) { 180 | if (field == NULL) { 181 | return 0; 182 | } 183 | int ret = 0; 184 | switch (field->type) { 185 | case PTYPE_DOUBLE: 186 | case PTYPE_FLOAT: 187 | ret = PBC_REAL; 188 | break; 189 | case PTYPE_INT64: 190 | case PTYPE_SINT64: 191 | ret = PBC_INT64; 192 | break; 193 | case PTYPE_INT32: 194 | case PTYPE_SINT32: 195 | ret = PBC_INT; 196 | break; 197 | case PTYPE_UINT32: 198 | case PTYPE_UINT64: 199 | ret = PBC_UINT; 200 | break; 201 | case PTYPE_FIXED32: 202 | case PTYPE_SFIXED32: 203 | ret = PBC_FIXED32; 204 | break; 205 | case PTYPE_SFIXED64: 206 | case PTYPE_FIXED64: 207 | ret = PBC_FIXED64; 208 | break; 209 | case PTYPE_BOOL: 210 | ret = PBC_BOOL; 211 | break; 212 | case PTYPE_STRING: 213 | ret = PBC_STRING; 214 | break; 215 | case PTYPE_BYTES: 216 | ret = PBC_BYTES; 217 | break; 218 | case PTYPE_ENUM: 219 | ret = PBC_ENUM; 220 | if (type) { 221 | *type = field->type_name.e->key; 222 | } 223 | break; 224 | case PTYPE_MESSAGE: 225 | ret = PBC_MESSAGE; 226 | if (type) { 227 | *type = field->type_name.m->key; 228 | } 229 | break; 230 | default: 231 | return 0; 232 | } 233 | if (field->label == LABEL_REPEATED || 234 | field->label == LABEL_PACKED) { 235 | ret |= PBC_REPEATED; 236 | } 237 | 238 | return ret; 239 | } 240 | 241 | int 242 | pbc_type(struct pbc_env * p, const char * type_name , const char * key , const char ** type) { 243 | struct _message *m = _pbcP_get_message(p, type_name); 244 | if (m==NULL) { 245 | return 0; 246 | } 247 | if (key == NULL) { 248 | return PBC_NOEXIST; 249 | } 250 | struct _field * field = (struct _field *)_pbcM_sp_query(m->name, key); 251 | return _pbcP_type(field, type); 252 | } 253 | 254 | int 255 | pbc_enum_id(struct pbc_env *env, const char *enum_type, const char *enum_name) { 256 | struct _enum *enum_map = (struct _enum *)_pbcM_sp_query(env->enums, enum_type); 257 | if(!enum_map) { 258 | return -1; 259 | } 260 | int32_t enum_id = 0; 261 | int err = _pbcM_si_query(enum_map->name, enum_name, &enum_id); 262 | if(err) { 263 | return -1; 264 | } 265 | return enum_id; 266 | } 267 | -------------------------------------------------------------------------------- /src/proto.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOBUFC_PROTO_H 2 | #define PROTOBUFC_PROTO_H 3 | 4 | #include "pbc.h" 5 | #include "map.h" 6 | #include "array.h" 7 | #ifndef _MSC_VER 8 | #include 9 | #endif 10 | #include 11 | 12 | struct map_ip; 13 | struct map_si; 14 | struct map_sp; 15 | struct _message; 16 | struct _enum; 17 | 18 | #define LABEL_OPTIONAL 0 19 | #define LABEL_REQUIRED 1 20 | #define LABEL_REPEATED 2 21 | #define LABEL_PACKED 3 22 | 23 | struct _field { 24 | int id; 25 | const char *name; 26 | int type; 27 | int label; 28 | pbc_var default_v; 29 | union { 30 | const char * n; 31 | struct _message * m; 32 | struct _enum * e; 33 | } type_name; 34 | }; 35 | 36 | struct _message { 37 | const char * key; 38 | struct map_ip * id; // id -> _field 39 | struct map_sp * name; // string -> _field 40 | struct pbc_rmessage * def; // default message 41 | struct pbc_env * env; 42 | }; 43 | 44 | struct _enum { 45 | const char * key; 46 | struct map_ip * id; 47 | struct map_si * name; 48 | pbc_var default_v; 49 | }; 50 | 51 | struct pbc_env { 52 | struct map_sp * files; // string -> void * 53 | struct map_sp * enums; // string -> _enum 54 | struct map_sp * msgs; // string -> _message 55 | const char * lasterror; 56 | }; 57 | 58 | struct _message * _pbcP_init_message(struct pbc_env * p, const char *name); 59 | void _pbcP_push_message(struct pbc_env * p, const char *name, struct _field *f , pbc_array queue); 60 | struct _enum * _pbcP_push_enum(struct pbc_env * p, const char *name, struct map_kv *table, int sz ); 61 | int _pbcP_message_default(struct _message * m, const char * name, pbc_var defv); 62 | struct _message * _pbcP_get_message(struct pbc_env * p, const char *name); 63 | int _pbcP_type(struct _field * field, const char **type); 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /src/register.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | #include "proto.h" 3 | #include "alloc.h" 4 | #include "map.h" 5 | #include "bootstrap.h" 6 | #include "context.h" 7 | #include "stringpool.h" 8 | 9 | #include 10 | #include 11 | 12 | #ifdef _MSC_VER 13 | #define strtoll _strtoi64 14 | #endif 15 | 16 | static const char * 17 | _concat_name(struct _stringpool *p , const char *prefix , int prefix_sz , const char *name , int name_sz, int *sz) { 18 | if (prefix_sz == 0) { 19 | if (sz) { 20 | *sz = name_sz; 21 | } 22 | return _pbcS_build(p , name, name_sz); 23 | } 24 | char * temp = (char *)alloca(name_sz + prefix_sz + 2); 25 | memcpy(temp,prefix,prefix_sz); 26 | temp[prefix_sz] = '.'; 27 | memcpy(temp+prefix_sz+1,name,name_sz); 28 | temp[name_sz + prefix_sz + 1] = '\0'; 29 | if (sz) { 30 | *sz = name_sz + prefix_sz + 1; 31 | } 32 | const char * ret = _pbcS_build(p , temp, name_sz + prefix_sz + 1); 33 | return ret; 34 | } 35 | 36 | static void 37 | _register_enum(struct pbc_env *p, struct _stringpool *pool, struct pbc_rmessage * enum_type, const char *prefix, int prefix_sz) { 38 | int field_count = pbc_rmessage_size(enum_type, "value"); 39 | struct map_kv *table = (struct map_kv *)malloc(field_count * sizeof(struct map_kv)); 40 | int i; 41 | for (i=0;itype == PTYPE_STRING || f->type == PTYPE_BYTES) { 60 | f->default_v->s.str = ""; 61 | f->default_v->s.len = 0; 62 | } else { 63 | f->default_v->integer.low = 0; 64 | f->default_v->integer.hi = 0; 65 | } 66 | return; 67 | } 68 | 69 | switch (f->type) { 70 | case PTYPE_DOUBLE: 71 | case PTYPE_FLOAT: 72 | f->default_v->real = strtod(value,NULL); 73 | break; 74 | case PTYPE_STRING: 75 | f->default_v->s.str = _pbcS_build(pool, value , sz); 76 | f->default_v->s.len = sz; 77 | break; 78 | case PTYPE_ENUM: 79 | // enum default value will be converted to f->default_v->e in bootstrap.c : set_field_one() 80 | f->default_v->s.str = value; 81 | f->default_v->s.len = sz; 82 | break; 83 | case PTYPE_BOOL: 84 | if (strcmp(value,"true") == 0) { 85 | f->default_v->integer.low = 1; 86 | } else { 87 | f->default_v->integer.low = 0; 88 | } 89 | f->default_v->integer.hi = 0; 90 | break; 91 | case PTYPE_UINT64: 92 | case PTYPE_INT64: 93 | case PTYPE_SFIXED64: 94 | case PTYPE_SINT64: { 95 | long long v = strtoll(value, NULL, 10); 96 | f->default_v->integer.low = (long) v; 97 | f->default_v->integer.hi = (long)(v >> 32); 98 | break; 99 | } 100 | case PTYPE_INT32: 101 | case PTYPE_FIXED32: 102 | case PTYPE_SFIXED32: 103 | case PTYPE_SINT32: { 104 | int low = strtol(value, NULL, 10); 105 | f->default_v->integer.low = low; 106 | if (low < 0) { 107 | f->default_v->integer.hi = -1; 108 | } else { 109 | f->default_v->integer.hi = 0; 110 | } 111 | break; 112 | } 113 | case PTYPE_UINT32: 114 | f->default_v->integer.low = strtoul(value, NULL, 10); 115 | f->default_v->integer.hi = 0; 116 | break; 117 | case PTYPE_BYTES: 118 | case PTYPE_MESSAGE: 119 | // bytes and message types have no default value 120 | f->default_v->m.buffer = 0; 121 | f->default_v->m.len = 0; 122 | break; 123 | default: 124 | f->default_v->integer.low = 0; 125 | f->default_v->integer.hi = 0; 126 | break; 127 | } 128 | } 129 | 130 | static void 131 | _register_field(struct pbc_rmessage * field, struct _field * f, struct _stringpool *pool) { 132 | f->id = pbc_rmessage_integer(field, "number", 0 , 0); 133 | f->type = pbc_rmessage_integer(field, "type", 0 , 0); // enum 134 | f->label = pbc_rmessage_integer(field, "label", 0, 0) - 1; // LABEL_OPTIONAL = 0 135 | if (pbc_rmessage_size(field , "options") > 0) { 136 | struct pbc_rmessage * options = pbc_rmessage_message(field, "options" , 0); 137 | int packed = pbc_rmessage_integer(options , "packed" , 0 , NULL); 138 | if (packed) { 139 | f->label = LABEL_PACKED; 140 | } 141 | } 142 | f->type_name.n = pbc_rmessage_string(field, "type_name", 0 , NULL) +1; // abandon prefix '.' 143 | int vsz; 144 | const char * default_value = pbc_rmessage_string(field, "default_value", 0 , &vsz); 145 | _set_default(pool , f , f->type, default_value , vsz); 146 | } 147 | 148 | static void 149 | _register_extension(struct pbc_env *p, struct _stringpool *pool , const char * prefix, int prefix_sz, struct pbc_rmessage * msg, pbc_array queue) { 150 | int extension_count = pbc_rmessage_size(msg , "extension"); 151 | if (extension_count <= 0) 152 | return; 153 | int i; 154 | 155 | const char * last = NULL; 156 | 157 | for (i=0;ifiles, filename)) { 260 | return CHECK_FILE_EXIST; 261 | } 262 | int sz = pbc_rmessage_size(file, "dependency"); 263 | int i; 264 | for (i=0;ifiles, dname) == NULL) { 268 | return CHECK_FILE_DEPENDENCY; 269 | } 270 | } 271 | 272 | *fname = filename; 273 | 274 | return CHECK_FILE_OK; 275 | } 276 | 277 | static int 278 | _register_no_dependency(struct pbc_env * p,struct pbc_rmessage ** files , int n ) { 279 | int r = 0; 280 | int i; 281 | for (i=0;ifiles , filename, pool); 296 | _register(p,files[i],pool); 297 | files[i] = NULL; 298 | } 299 | break; 300 | } 301 | } 302 | return r; 303 | } 304 | 305 | int 306 | pbc_register(struct pbc_env * p, struct pbc_slice *slice) { 307 | struct pbc_rmessage * message = pbc_rmessage_new(p, "google.protobuf.FileDescriptorSet", slice); 308 | if (message == NULL) { 309 | p->lasterror = "register open google.protobuf.FileDescriptorSet fail"; 310 | return 1; 311 | } 312 | int n = pbc_rmessage_size(message, "file"); 313 | struct pbc_rmessage ** files = (struct pbc_rmessage **)alloca(n * sizeof(struct pbc_rmessage *)); 314 | int i; 315 | if (n == 0) { 316 | p->lasterror = "register empty"; 317 | goto _error; 318 | } 319 | for (i=0;ilasterror = "register open fail"; 323 | goto _error; 324 | } 325 | } 326 | 327 | int r = n; 328 | do { 329 | int rr = _register_no_dependency(p,files , n); 330 | if (rr == r) { 331 | p->lasterror = "register dependency error"; 332 | goto _error; 333 | } 334 | r = rr; 335 | } while (r>0); 336 | 337 | pbc_rmessage_delete(message); 338 | return 0; 339 | _error: 340 | pbc_rmessage_delete(message); 341 | return 1; 342 | } 343 | -------------------------------------------------------------------------------- /src/rmessage.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | #include "alloc.h" 3 | #include "map.h" 4 | #include "context.h" 5 | #include "proto.h" 6 | #include "pattern.h" 7 | #include "varint.h" 8 | 9 | #include 10 | #include 11 | 12 | struct pbc_rmessage { 13 | struct _message * msg; 14 | struct map_sp * index; // key -> struct value * 15 | struct heap * heap; 16 | }; 17 | 18 | union _var { 19 | pbc_var var; 20 | pbc_array array; 21 | struct pbc_rmessage message; 22 | } ; 23 | 24 | struct value { 25 | struct _field * type; 26 | union _var v; 27 | }; 28 | 29 | int 30 | pbc_rmessage_next(struct pbc_rmessage *m, const char **key) { 31 | struct value * v = (struct value *)_pbcM_sp_next(m->index, key); 32 | if (*key == NULL) { 33 | return 0; 34 | } 35 | return _pbcP_type(v->type, NULL); 36 | } 37 | 38 | #define SIZE_VAR (offsetof(struct value, v) + sizeof(pbc_var)) 39 | #define SIZE_ARRAY (offsetof(struct value, v) + sizeof(pbc_array)) 40 | #define SIZE_MESSAGE (offsetof(struct value, v) + sizeof(struct pbc_rmessage)) 41 | 42 | static struct value * 43 | read_string(struct heap *h, struct atom *a,struct _field *f, uint8_t *buffer) { 44 | const char * temp = (const char *) (buffer + a->v.s.start); 45 | int len = a->v.s.end - a->v.s.start; 46 | 47 | if (len > 0 && temp[len-1] == '\0') { 48 | struct value * v = (struct value *)_pbcH_alloc(h, SIZE_VAR); 49 | v->v.var->s.str = temp; 50 | v->v.var->s.len = len; 51 | return v; 52 | } else { 53 | struct value * v = (struct value *)_pbcH_alloc(h, SIZE_VAR + len + 1); 54 | memcpy(((char *)v) + SIZE_VAR , temp, len); 55 | *(((char *)v) + SIZE_VAR + len) = '\0'; 56 | v->v.var->s.str = ((char *)v) + SIZE_VAR; 57 | v->v.var->s.len = len; 58 | return v; 59 | } 60 | } 61 | 62 | static void 63 | read_string_var(struct heap *h, pbc_var var,struct atom *a,struct _field *f,uint8_t *buffer) { 64 | const char * temp = (const char *) (buffer + a->v.s.start); 65 | int len = a->v.s.end - a->v.s.start; 66 | if (len == 0) { 67 | var->s.str = ""; 68 | var->s.len = 0; 69 | } 70 | else if (temp[len-1] == '\0') { 71 | var->s.str = temp; 72 | var->s.len = len; 73 | } else { 74 | char * temp2 = (char *)_pbcH_alloc(h, len + 1); 75 | memcpy(temp2, temp, len); 76 | temp2[len]='\0'; 77 | var->s.str = temp2; 78 | var->s.len = -len; 79 | } 80 | } 81 | 82 | static void _pbc_rmessage_new(struct pbc_rmessage * ret , struct _message * type , void *buffer, int size, struct heap *h); 83 | 84 | static struct value * 85 | read_value(struct heap *h, struct _field *f, struct atom * a, uint8_t *buffer) { 86 | struct value * v; 87 | 88 | switch (f->type) { 89 | case PTYPE_DOUBLE: 90 | CHECK_BIT64(a,NULL); 91 | v = (struct value *)_pbcH_alloc(h, SIZE_VAR); 92 | v->v.var->real = read_double(a); 93 | break; 94 | case PTYPE_FLOAT: 95 | CHECK_BIT32(a,NULL); 96 | v = (struct value *)_pbcH_alloc(h, SIZE_VAR); 97 | v->v.var->real = (double) read_float(a); 98 | break; 99 | case PTYPE_ENUM: 100 | CHECK_VARINT(a,NULL); 101 | v = (struct value *)_pbcH_alloc(h, SIZE_VAR); 102 | v->v.var->e.id = a->v.i.low; 103 | v->v.var->e.name = (const char *)_pbcM_ip_query(f->type_name.e->id , a->v.i.low); 104 | break; 105 | case PTYPE_INT64: 106 | case PTYPE_UINT64: 107 | case PTYPE_INT32: 108 | case PTYPE_UINT32: 109 | case PTYPE_BOOL: 110 | CHECK_VARINT(a,NULL); 111 | v = (struct value *)_pbcH_alloc(h, SIZE_VAR); 112 | v->v.var->integer = a->v.i; 113 | break; 114 | case PTYPE_FIXED32: 115 | case PTYPE_SFIXED32: 116 | CHECK_BIT32(a,NULL); 117 | v = (struct value *)_pbcH_alloc(h, SIZE_VAR); 118 | v->v.var->integer = a->v.i; 119 | break; 120 | case PTYPE_FIXED64: 121 | case PTYPE_SFIXED64: 122 | CHECK_BIT64(a,NULL); 123 | v = (struct value *)_pbcH_alloc(h, SIZE_VAR); 124 | v->v.var->integer = a->v.i; 125 | break; 126 | case PTYPE_SINT32: 127 | CHECK_VARINT(a,NULL); 128 | v = (struct value *)_pbcH_alloc(h, SIZE_VAR); 129 | v->v.var->integer = a->v.i; 130 | _pbcV_dezigzag32(&(v->v.var->integer)); 131 | break; 132 | case PTYPE_SINT64: 133 | CHECK_VARINT(a,NULL); 134 | v = (struct value *)_pbcH_alloc(h, SIZE_VAR); 135 | v->v.var->integer = a->v.i; 136 | _pbcV_dezigzag64(&(v->v.var->integer)); 137 | break; 138 | case PTYPE_STRING: 139 | CHECK_LEND(a,NULL); 140 | v = read_string(h,a,f,buffer); 141 | break; 142 | case PTYPE_BYTES: 143 | CHECK_LEND(a,NULL); 144 | v = (struct value *)_pbcH_alloc(h, SIZE_VAR); 145 | v->v.var->s.str = (const char *)(buffer + a->v.s.start); 146 | v->v.var->s.len = a->v.s.end - a->v.s.start; 147 | break; 148 | case PTYPE_MESSAGE: 149 | CHECK_LEND(a,NULL); 150 | v = (struct value *)_pbcH_alloc(h, SIZE_MESSAGE); 151 | _pbc_rmessage_new(&(v->v.message), f->type_name.m , 152 | buffer + a->v.s.start , 153 | a->v.s.end - a->v.s.start,h); 154 | break; 155 | default: 156 | return NULL; 157 | } 158 | v->type = f; 159 | return v; 160 | } 161 | 162 | static void 163 | push_value_packed(struct _message * type, pbc_array array, struct _field *f, struct atom * aa, uint8_t *buffer) { 164 | int n = _pbcP_unpack_packed((uint8_t *)buffer + aa->v.s.start, aa->v.s.end - aa->v.s.start, 165 | f->type , array); 166 | if (n<=0) { 167 | // todo : error 168 | type->env->lasterror = "Unpack packed field error"; 169 | return; 170 | } 171 | if (f->type == PTYPE_ENUM) { 172 | int i; 173 | for (i=0;iinteger.low; 176 | v->e.id = id; 177 | v->e.name = (const char*)_pbcM_ip_query(f->type_name.e->id , id); 178 | } 179 | } 180 | } 181 | 182 | static void 183 | push_value_array(struct heap *h, pbc_array array, struct _field *f, struct atom * a, uint8_t *buffer) { 184 | pbc_var v; 185 | 186 | switch (f->type) { 187 | case PTYPE_DOUBLE: 188 | v->real = read_double(a); 189 | break; 190 | case PTYPE_FLOAT: 191 | v->real = (double) read_float(a); 192 | break; 193 | case PTYPE_ENUM: 194 | v->e.id = a->v.i.low; 195 | v->e.name = (const char *)_pbcM_ip_query(f->type_name.e->id , a->v.i.low); 196 | break; 197 | case PTYPE_INT64: 198 | case PTYPE_UINT64: 199 | case PTYPE_INT32: 200 | case PTYPE_UINT32: 201 | case PTYPE_FIXED32: 202 | case PTYPE_FIXED64: 203 | case PTYPE_SFIXED32: 204 | case PTYPE_SFIXED64: 205 | case PTYPE_BOOL: 206 | v->integer = a->v.i; 207 | break; 208 | case PTYPE_SINT32: 209 | v->integer = a->v.i; 210 | _pbcV_dezigzag32(&(v->integer)); 211 | break; 212 | case PTYPE_SINT64: 213 | v->integer = a->v.i; 214 | _pbcV_dezigzag64(&(v->integer)); 215 | break; 216 | case PTYPE_STRING: 217 | CHECK_LEND(a, ); 218 | read_string_var(h,v,a,f,buffer); 219 | break; 220 | case PTYPE_BYTES: 221 | CHECK_LEND(a, ); 222 | v->s.str = (const char *)(buffer + a->v.s.start); 223 | v->s.len = a->v.s.end - a->v.s.start; 224 | break; 225 | case PTYPE_MESSAGE: { 226 | CHECK_LEND(a, ); 227 | struct pbc_rmessage message; 228 | _pbc_rmessage_new(&message, f->type_name.m , 229 | buffer + a->v.s.start , 230 | a->v.s.end - a->v.s.start,h); 231 | if (message.msg == NULL) { 232 | return; 233 | } 234 | v->p[0] = message.msg; 235 | v->p[1] = message.index; 236 | break; 237 | } 238 | default: 239 | return; 240 | } 241 | 242 | _pbcA_push(array,v); 243 | } 244 | 245 | static void 246 | _pbc_rmessage_new(struct pbc_rmessage * ret , struct _message * type , void *buffer, int size , struct heap *h) { 247 | if (size == 0) { 248 | ret->msg = type; 249 | ret->index = _pbcM_sp_new(0 , h); 250 | ret->heap = h; 251 | return; 252 | } 253 | pbc_ctx _ctx; 254 | int count = _pbcC_open(_ctx,buffer,size); 255 | if (count <= 0) { 256 | type->env->lasterror = "rmessage decode context error"; 257 | memset(ret , 0, sizeof(*ret)); 258 | return; 259 | } 260 | struct context * ctx = (struct context *)_ctx; 261 | 262 | ret->msg = type; 263 | ret->index = _pbcM_sp_new(count, h); 264 | ret->heap = h; 265 | 266 | int i; 267 | 268 | for (i=0;inumber;i++) { 269 | int id = ctx->a[i].wire_id >> 3; 270 | struct _field * f = (struct _field *)_pbcM_ip_query(type->id , id); 271 | if (f) { 272 | if (f->label == LABEL_REPEATED || f->label == LABEL_PACKED) { 273 | struct value * v; 274 | void ** vv = _pbcM_sp_query_insert(ret->index, f->name); 275 | if (*vv == NULL) { 276 | v = (struct value *)_pbcH_alloc(h, SIZE_ARRAY); 277 | v->type = f; 278 | _pbcA_open_heap(v->v.array,ret->heap); 279 | *vv = v; 280 | } else { 281 | v= (struct value *)*vv; 282 | } 283 | if (f->label == LABEL_PACKED) { 284 | push_value_packed(type, v->v.array , f , &(ctx->a[i]), (uint8_t *)buffer); 285 | if (pbc_array_size(v->v.array) == 0) { 286 | type->env->lasterror = "rmessage decode packed data error"; 287 | *vv = NULL; 288 | } 289 | } else { 290 | push_value_array(h,v->v.array , f, &(ctx->a[i]), (uint8_t *)buffer); 291 | if (pbc_array_size(v->v.array) == 0) { 292 | type->env->lasterror = "rmessage decode repeated data error"; 293 | *vv = NULL; 294 | } 295 | } 296 | } else { 297 | struct value * v = read_value(h, f, &(ctx->a[i]), (uint8_t *)buffer); 298 | if (v) { 299 | _pbcM_sp_insert(ret->index, f->name, v); 300 | } else { 301 | type->env->lasterror = "rmessage decode data error"; 302 | } 303 | } 304 | } 305 | } 306 | 307 | _pbcC_close(_ctx); 308 | } 309 | 310 | struct pbc_rmessage * 311 | pbc_rmessage_new(struct pbc_env * env, const char * type_name , struct pbc_slice * slice) { 312 | struct _message * msg = _pbcP_get_message(env, type_name); 313 | if (msg == NULL) { 314 | env->lasterror = "Proto not found"; 315 | return NULL; 316 | } 317 | struct pbc_rmessage temp; 318 | struct heap * h = _pbcH_new(slice->len); 319 | _pbc_rmessage_new(&temp, msg , slice->buffer, slice->len , h); 320 | if (temp.msg == NULL) { 321 | _pbcH_delete(h); 322 | return NULL; 323 | } 324 | 325 | struct pbc_rmessage *m = (struct pbc_rmessage *)_pbcH_alloc(temp.heap, sizeof(*m)); 326 | *m = temp; 327 | return m; 328 | } 329 | 330 | void 331 | pbc_rmessage_delete(struct pbc_rmessage * m) { 332 | if (m) { 333 | _pbcH_delete(m->heap); 334 | } 335 | } 336 | 337 | const char * 338 | pbc_rmessage_string(struct pbc_rmessage * m , const char *key , int index, int *sz) { 339 | struct value * v = (struct value *)_pbcM_sp_query(m->index,key); 340 | int type = 0; 341 | pbc_var var; 342 | if (v == NULL) { 343 | type = _pbcP_message_default(m->msg, key, var); 344 | } else { 345 | if (v->type->label == LABEL_REPEATED || v->type->label == LABEL_PACKED) { 346 | _pbcA_index(v->v.array, index, var); 347 | } else { 348 | var[0] = v->v.var[0]; 349 | } 350 | type = v->type->type; 351 | } 352 | 353 | if (type == PTYPE_ENUM) { 354 | if (sz) { 355 | *sz = strlen(var->e.name); 356 | } 357 | return var->e.name; 358 | } 359 | 360 | if (sz) { 361 | int len = var->s.len; 362 | if (len<0) { 363 | len = - len; 364 | } 365 | *sz = len; 366 | } 367 | return var->s.str; 368 | } 369 | 370 | uint32_t 371 | pbc_rmessage_integer(struct pbc_rmessage *m , const char *key , int index, uint32_t *hi) { 372 | struct value * v = (struct value *)_pbcM_sp_query(m->index,key); 373 | pbc_var var; 374 | int type = 0; 375 | if (v == NULL) { 376 | type = _pbcP_message_default(m->msg, key, var); 377 | } else { 378 | if (v->type->label == LABEL_REPEATED || v->type->label == LABEL_PACKED) { 379 | _pbcA_index(v->v.array, index, var); 380 | } else { 381 | var[0] = v->v.var[0]; 382 | } 383 | type = v->type->type; 384 | } 385 | 386 | if (type == PTYPE_ENUM) { 387 | if (hi) { 388 | *hi = 0; 389 | } 390 | return var->e.id; 391 | } 392 | 393 | if (hi) { 394 | *hi = var->integer.hi; 395 | } 396 | return var->integer.low; 397 | } 398 | 399 | double 400 | pbc_rmessage_real(struct pbc_rmessage * m, const char *key , int index) { 401 | struct value * v = (struct value *)_pbcM_sp_query(m->index,key); 402 | pbc_var var; 403 | if (v == NULL) { 404 | _pbcP_message_default(m->msg, key, var); 405 | } else { 406 | if (v->type->label == LABEL_REPEATED || v->type->label == LABEL_PACKED) { 407 | _pbcA_index(v->v.array, index, var); 408 | } else { 409 | return v->v.var->real; 410 | } 411 | } 412 | return var->real; 413 | } 414 | 415 | 416 | struct pbc_rmessage * 417 | pbc_rmessage_message(struct pbc_rmessage * rm, const char *key, int index) { 418 | struct value * v = (struct value *)_pbcM_sp_query(rm->index,key); 419 | if (v == NULL) { 420 | struct _field * f = (struct _field *)_pbcM_sp_query(rm->msg->name, key); 421 | if (f == NULL) { 422 | rm->msg->env->lasterror = "Invalid key for sub-message"; 423 | // invalid key 424 | return NULL; 425 | } 426 | struct _message * m = f->type_name.m; 427 | 428 | if (m->def == NULL) { 429 | // m->def will be free at the end (pbc_delete). 430 | m->def = (struct pbc_rmessage *)malloc(sizeof(struct pbc_rmessage)); 431 | m->def->msg = m; 432 | m->def->index = NULL; 433 | } 434 | return m->def; 435 | } else { 436 | if (v->type->label == LABEL_REPEATED) { 437 | return (struct pbc_rmessage *)_pbcA_index_p(v->v.array,index); 438 | } else { 439 | return &(v->v.message); 440 | } 441 | } 442 | } 443 | 444 | int 445 | pbc_rmessage_size(struct pbc_rmessage *m, const char *key) { 446 | struct value * v = (struct value *)_pbcM_sp_query(m->index,key); 447 | if (v == NULL) { 448 | return 0; 449 | } 450 | if (v->type->label == LABEL_REPEATED || v->type->label == LABEL_PACKED) { 451 | return pbc_array_size(v->v.array); 452 | } else { 453 | return 1; 454 | } 455 | } -------------------------------------------------------------------------------- /src/stringpool.c: -------------------------------------------------------------------------------- 1 | #include "alloc.h" 2 | 3 | #include 4 | #include 5 | 6 | #define PAGE_SIZE 256 7 | 8 | struct _stringpool { 9 | char * buffer; 10 | size_t len; 11 | struct _stringpool *next; 12 | }; 13 | 14 | struct _stringpool * 15 | _pbcS_new(void) { 16 | struct _stringpool * ret = (struct _stringpool *)malloc(sizeof(struct _stringpool) + PAGE_SIZE); 17 | ret->buffer = (char *)(ret + 1); 18 | ret->len = 0; 19 | ret->next = NULL; 20 | return ret; 21 | } 22 | 23 | void 24 | _pbcS_delete(struct _stringpool *pool) { 25 | while(pool) { 26 | struct _stringpool *next = pool->next; 27 | free(pool); 28 | pool = next; 29 | } 30 | } 31 | 32 | const char * 33 | _pbcS_build(struct _stringpool *pool, const char * str , int sz) { 34 | size_t s = sz + 1; 35 | if (s < PAGE_SIZE - pool->len) { 36 | char * ret = pool->buffer + pool->len; 37 | memcpy(pool->buffer + pool->len, str, s); 38 | pool->len += s; 39 | return ret; 40 | } 41 | if (s > PAGE_SIZE) { 42 | struct _stringpool * next = (struct _stringpool *)malloc(sizeof(struct _stringpool) + s); 43 | next->buffer = (char *)(next + 1); 44 | memcpy(next->buffer, str, s); 45 | next->len = s; 46 | next->next = pool->next; 47 | pool->next = next; 48 | return next->buffer; 49 | } 50 | struct _stringpool *next = (struct _stringpool *)malloc(sizeof(struct _stringpool) + PAGE_SIZE); 51 | next->buffer = pool->buffer; 52 | next->next = pool->next; 53 | next->len = pool->len; 54 | 55 | pool->next = next; 56 | pool->buffer = (char *)(next + 1); 57 | memcpy(pool->buffer, str, s); 58 | pool->len = s; 59 | return pool->buffer; 60 | } 61 | -------------------------------------------------------------------------------- /src/stringpool.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOBUF_C_STRINGPOOL_H 2 | #define PROTOBUF_C_STRINGPOOL_H 3 | 4 | struct _stringpool; 5 | 6 | struct _stringpool * _pbcS_new(void); 7 | void _pbcS_delete(struct _stringpool *pool); 8 | const char * _pbcS_build(struct _stringpool *pool, const char * str , int sz); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/varint.c: -------------------------------------------------------------------------------- 1 | #include "varint.h" 2 | 3 | #include "pbc.h" 4 | 5 | #include 6 | 7 | inline int 8 | _pbcV_encode32(uint32_t number, uint8_t buffer[10]) 9 | { 10 | if (number < 0x80) { 11 | buffer[0] = (uint8_t) number ; 12 | return 1; 13 | } 14 | buffer[0] = (uint8_t) (number | 0x80 ); 15 | if (number < 0x4000) { 16 | buffer[1] = (uint8_t) (number >> 7 ); 17 | return 2; 18 | } 19 | buffer[1] = (uint8_t) ((number >> 7) | 0x80 ); 20 | if (number < 0x200000) { 21 | buffer[2] = (uint8_t) (number >> 14); 22 | return 3; 23 | } 24 | buffer[2] = (uint8_t) ((number >> 14) | 0x80 ); 25 | if (number < 0x10000000) { 26 | buffer[3] = (uint8_t) (number >> 21); 27 | return 4; 28 | } 29 | buffer[3] = (uint8_t) ((number >> 21) | 0x80 ); 30 | buffer[4] = (uint8_t) (number >> 28); 31 | return 5; 32 | } 33 | 34 | int 35 | _pbcV_encode(uint64_t number, uint8_t buffer[10]) 36 | { 37 | if ((number & 0xffffffff) == number) { 38 | return _pbcV_encode32((uint32_t)number , buffer); 39 | } 40 | int i = 0; 41 | do { 42 | buffer[i] = (uint8_t)(number | 0x80); 43 | number >>= 7; 44 | ++i; 45 | } while (number >= 0x80); 46 | buffer[i] = (uint8_t)number; 47 | return i+1; 48 | } 49 | 50 | int 51 | _pbcV_decode(uint8_t buffer[10], struct longlong *result) { 52 | if (!(buffer[0] & 0x80)) { 53 | result->low = buffer[0]; 54 | result->hi = 0; 55 | return 1; 56 | } 57 | uint32_t r = buffer[0] & 0x7f; 58 | int i; 59 | for (i=1;i<4;i++) { 60 | r |= ((buffer[i]&0x7f) << (7*i)); 61 | if (!(buffer[i] & 0x80)) { 62 | result->low = r; 63 | result->hi = 0; 64 | return i+1; 65 | } 66 | } 67 | uint64_t lr = 0; 68 | for (i=4;i<10;i++) { 69 | lr |= ((uint64_t)(buffer[i] & 0x7f) << (7*(i-4))); 70 | if (!(buffer[i] & 0x80)) { 71 | result->hi = (uint32_t)(lr >> 4); 72 | result->low = r | (((uint32_t)lr & 0xf) << 28); 73 | return i+1; 74 | } 75 | } 76 | 77 | result->low = 0; 78 | result->hi = 0; 79 | return 10; 80 | } 81 | 82 | int 83 | _pbcV_zigzag32(int32_t n, uint8_t buffer[10]) 84 | { 85 | n = (n << 1) ^ (n >> 31); 86 | return _pbcV_encode32(n,buffer); 87 | } 88 | 89 | int 90 | _pbcV_zigzag(int64_t n, uint8_t buffer[10]) 91 | { 92 | n = (n << 1) ^ (n >> 63); 93 | return _pbcV_encode(n,buffer); 94 | } 95 | 96 | void 97 | _pbcV_dezigzag64(struct longlong *r) 98 | { 99 | uint32_t low = r->low; 100 | r->low = ((low >> 1) | ((r->hi & 1) << 31)) ^ - (low & 1); 101 | r->hi = (r->hi >> 1) ^ - (low & 1); 102 | } 103 | 104 | void 105 | _pbcV_dezigzag32(struct longlong *r) 106 | { 107 | uint32_t low = r->low; 108 | r->low = (low >> 1) ^ - (low & 1); 109 | r->hi = -(low >> 31); 110 | } 111 | -------------------------------------------------------------------------------- /src/varint.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOBUF_C_VARINT_H 2 | #define PROTOBUF_C_VARINT_H 3 | 4 | #include 5 | 6 | struct longlong { 7 | uint32_t low; 8 | uint32_t hi; 9 | }; 10 | 11 | int _pbcV_encode32(uint32_t number, uint8_t buffer[10]); 12 | int _pbcV_encode(uint64_t number, uint8_t buffer[10]); 13 | int _pbcV_zigzag32(int32_t number, uint8_t buffer[10]); 14 | int _pbcV_zigzag(int64_t number, uint8_t buffer[10]); 15 | 16 | int _pbcV_decode(uint8_t buffer[10], struct longlong *result); 17 | void _pbcV_dezigzag64(struct longlong *r); 18 | void _pbcV_dezigzag32(struct longlong *r); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/wmessage.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | #include "context.h" 3 | #include "alloc.h" 4 | #include "varint.h" 5 | #include "map.h" 6 | #include "proto.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #ifndef _MSC_VER 13 | #include 14 | #endif 15 | 16 | #define WMESSAGE_SIZE 64 17 | 18 | struct pbc_wmessage { 19 | struct _message *type; 20 | uint8_t * buffer; 21 | uint8_t * ptr; 22 | uint8_t * endptr; 23 | pbc_array sub; 24 | struct map_sp *packed; 25 | struct heap * heap; 26 | }; 27 | 28 | struct _packed { 29 | int id; 30 | int ptype; 31 | pbc_array data; 32 | }; 33 | 34 | static struct pbc_wmessage * 35 | _wmessage_new(struct heap *h, struct _message *msg) { 36 | struct pbc_wmessage * m = (struct pbc_wmessage *)_pbcH_alloc(h, sizeof(*m)); 37 | m->type = msg; 38 | m->buffer = (uint8_t *)_pbcH_alloc(h, WMESSAGE_SIZE); 39 | m->ptr = m->buffer; 40 | m->endptr = m->buffer + WMESSAGE_SIZE; 41 | _pbcA_open_heap(m->sub, h); 42 | m->packed = NULL; 43 | m->heap = h; 44 | 45 | return m; 46 | } 47 | 48 | struct pbc_wmessage * 49 | pbc_wmessage_new(struct pbc_env * env, const char *type_name) { 50 | struct _message * msg = _pbcP_get_message(env, type_name); 51 | if (msg == NULL) 52 | return NULL; 53 | struct heap *h = _pbcH_new(0); 54 | return _wmessage_new(h, msg); 55 | } 56 | 57 | void 58 | pbc_wmessage_delete(struct pbc_wmessage *m) { 59 | if (m) { 60 | _pbcH_delete(m->heap); 61 | } 62 | } 63 | 64 | static void 65 | _expand_message(struct pbc_wmessage *m, int sz) { 66 | if (m->ptr + sz > m->endptr) { 67 | int cap = m->endptr - m->buffer; 68 | sz = m->ptr + sz - m->buffer; 69 | do { 70 | cap = cap * 2; 71 | } while ( sz > cap ) ; 72 | int old_size = m->ptr - m->buffer; 73 | uint8_t * buffer = (uint8_t *)_pbcH_alloc(m->heap, cap); 74 | memcpy(buffer, m->buffer, old_size); 75 | m->ptr = buffer + (m->ptr - m->buffer); 76 | m->endptr = buffer + cap; 77 | m->buffer = buffer; 78 | } 79 | } 80 | 81 | static struct _packed * 82 | _get_packed(struct pbc_wmessage *m , struct _field *f , const char *key) { 83 | if (m->packed == NULL) { 84 | m->packed = _pbcM_sp_new(4, m->heap); 85 | } 86 | void ** v = _pbcM_sp_query_insert(m->packed , key); 87 | if (*v == NULL) { 88 | *v = _pbcH_alloc(m->heap, sizeof(struct _packed)); 89 | struct _packed *p = (struct _packed *)*v; 90 | p->id = f->id; 91 | p->ptype = f->type; 92 | _pbcA_open_heap(p->data, m->heap); 93 | return p; 94 | } 95 | return (struct _packed *)*v; 96 | } 97 | 98 | static void 99 | _packed_integer(struct pbc_wmessage *m, struct _field *f, const char *key , uint32_t low, uint32_t hi) { 100 | struct _packed * packed = _get_packed(m,f,key); 101 | pbc_var var; 102 | var->integer.low = low; 103 | var->integer.hi = hi; 104 | _pbcA_push(packed->data , var); 105 | } 106 | 107 | static void 108 | _packed_real(struct pbc_wmessage *m, struct _field *f, const char *key , double v) { 109 | struct _packed * packed = _get_packed(m,f,key); 110 | pbc_var var; 111 | var->real = v; 112 | _pbcA_push(packed->data , var); 113 | } 114 | 115 | static inline void 116 | int64_encode(uint32_t low, uint32_t hi , uint8_t * buffer) { 117 | buffer[0] = (uint8_t)(low & 0xff); 118 | buffer[1] = (uint8_t)(low >> 8 & 0xff); 119 | buffer[2] = (uint8_t)(low >> 16 & 0xff); 120 | buffer[3] = (uint8_t)(low >> 24 & 0xff); 121 | buffer[4] = (uint8_t)(hi & 0xff); 122 | buffer[5] = (uint8_t)(hi >> 8 & 0xff); 123 | buffer[6] = (uint8_t)(hi >> 16 & 0xff); 124 | buffer[7] = (uint8_t)(hi >> 24 & 0xff); 125 | } 126 | 127 | static inline void 128 | int32_encode(uint32_t low, uint8_t * buffer) { 129 | buffer[0] = (uint8_t)(low & 0xff); 130 | buffer[1] = (uint8_t)(low >> 8 & 0xff); 131 | buffer[2] = (uint8_t)(low >> 16 & 0xff); 132 | buffer[3] = (uint8_t)(low >> 24 & 0xff); 133 | } 134 | 135 | int 136 | pbc_wmessage_integer(struct pbc_wmessage *m, const char *key, uint32_t low, uint32_t hi) { 137 | struct _field * f = (struct _field *)_pbcM_sp_query(m->type->name,key); 138 | if (f==NULL) { 139 | // todo : error 140 | m->type->env->lasterror = "wmessage_interger query key error"; 141 | return -1; 142 | } 143 | if (f->label == LABEL_PACKED) { 144 | _packed_integer(m , f, key , low, hi); 145 | return 0; 146 | } 147 | if (f->label == LABEL_OPTIONAL) { 148 | if (f->type == PTYPE_ENUM) { 149 | if (low == f->default_v->e.id) 150 | return 0; 151 | } else { 152 | if (low == f->default_v->integer.low && 153 | hi == f->default_v->integer.hi) { 154 | return 0; 155 | } 156 | } 157 | } 158 | int id = f->id << 3; 159 | 160 | _expand_message(m,20); 161 | switch (f->type) { 162 | case PTYPE_INT64: 163 | case PTYPE_UINT64: 164 | case PTYPE_INT32: 165 | id |= WT_VARINT; 166 | m->ptr += _pbcV_encode32(id, m->ptr); 167 | m->ptr += _pbcV_encode((uint64_t)low | (uint64_t)hi << 32 , m->ptr); 168 | break; 169 | case PTYPE_UINT32: 170 | case PTYPE_ENUM: 171 | case PTYPE_BOOL: 172 | id |= WT_VARINT; 173 | m->ptr += _pbcV_encode32(id, m->ptr); 174 | m->ptr += _pbcV_encode32(low, m->ptr); 175 | break; 176 | case PTYPE_FIXED64: 177 | case PTYPE_SFIXED64: 178 | id |= WT_BIT64; 179 | m->ptr += _pbcV_encode32(id, m->ptr); 180 | int64_encode(low,hi,m->ptr); 181 | m->ptr += 8; 182 | break; 183 | case PTYPE_FIXED32: 184 | case PTYPE_SFIXED32: 185 | id |= WT_BIT32; 186 | m->ptr += _pbcV_encode32(id, m->ptr); 187 | int32_encode(low,m->ptr); 188 | m->ptr += 4; 189 | break; 190 | case PTYPE_SINT32: 191 | id |= WT_VARINT; 192 | m->ptr += _pbcV_encode32(id, m->ptr); 193 | m->ptr += _pbcV_zigzag32(low, m->ptr); 194 | break; 195 | case PTYPE_SINT64: 196 | id |= WT_VARINT; 197 | m->ptr += _pbcV_encode32(id, m->ptr); 198 | m->ptr += _pbcV_zigzag((uint64_t)low | (uint64_t)hi << 32 , m->ptr); 199 | break; 200 | } 201 | 202 | return 0; 203 | } 204 | 205 | int 206 | pbc_wmessage_real(struct pbc_wmessage *m, const char *key, double v) { 207 | struct _field * f = (struct _field *)_pbcM_sp_query(m->type->name,key); 208 | if (f == NULL) { 209 | // todo : error 210 | m->type->env->lasterror = "wmessage_real query key error"; 211 | return -1; 212 | } 213 | if (f->label == LABEL_PACKED) { 214 | _packed_real(m , f, key , v); 215 | return 0; 216 | } 217 | 218 | if (f->label == LABEL_OPTIONAL) { 219 | if (v == f->default_v->real) 220 | return 0; 221 | } 222 | int id = f->id << 3; 223 | _expand_message(m,18); 224 | switch (f->type) { 225 | case PTYPE_FLOAT: { 226 | id |= WT_BIT32; 227 | m->ptr += _pbcV_encode32(id, m->ptr); 228 | float_encode(v , m->ptr); 229 | m->ptr += 4; 230 | break; 231 | } 232 | case PTYPE_DOUBLE: 233 | id |= WT_BIT64; 234 | m->ptr += _pbcV_encode32(id, m->ptr); 235 | double_encode(v , m->ptr); 236 | m->ptr += 8; 237 | break; 238 | } 239 | 240 | return 0; 241 | } 242 | 243 | int 244 | pbc_wmessage_string(struct pbc_wmessage *m, const char *key, const char * v, int len) { 245 | struct _field * f = (struct _field *)_pbcM_sp_query(m->type->name,key); 246 | if (f == NULL) { 247 | // todo : error 248 | m->type->env->lasterror = "wmessage_string query key error"; 249 | return -1; 250 | } 251 | 252 | bool varlen = false; 253 | 254 | if (len <=0) { 255 | varlen = true; 256 | // -1 for add '\0' 257 | len = strlen(v) - len; 258 | } 259 | if (f->label == LABEL_PACKED) { 260 | if (f->type == PTYPE_ENUM) { 261 | char * temp = (char *)alloca(len + 1); 262 | if (!varlen || v[len] != '\0') { 263 | memcpy(temp,v,len); 264 | temp[len]='\0'; 265 | v = temp; 266 | } 267 | int enum_id = 0; 268 | int err = _pbcM_si_query(f->type_name.e->name, v , &enum_id); 269 | if (err) { 270 | // todo : error , invalid enum 271 | m->type->env->lasterror = "wmessage_string packed invalid enum"; 272 | return -1; 273 | } 274 | _packed_integer(m , f, key , enum_id , 0); 275 | } 276 | return 0; 277 | } 278 | 279 | if (f->label == LABEL_OPTIONAL) { 280 | if (f->type == PTYPE_ENUM) { 281 | if (strncmp(v , f->default_v->e.name, len) == 0 && f->default_v->e.name[len] =='\0') { 282 | return 0; 283 | } 284 | } else if (f->type == PTYPE_STRING) { 285 | if (len == f->default_v->s.len && 286 | strcmp(v, f->default_v->s.str) == 0) { 287 | return 0; 288 | } 289 | } else if (f->type == PTYPE_BYTES) { 290 | if (len == 0) { 291 | return 0; 292 | } 293 | } 294 | } 295 | int id = f->id << 3; 296 | _expand_message(m,20); 297 | switch (f->type) { 298 | case PTYPE_ENUM : { 299 | char * temp = (char *)alloca(len+1); 300 | if (!varlen || v[len] != '\0') { 301 | memcpy(temp,v,len); 302 | temp[len]='\0'; 303 | v = temp; 304 | } 305 | int enum_id = 0; 306 | int err = _pbcM_si_query(f->type_name.e->name, v, &enum_id); 307 | if (err) { 308 | // todo : error , enum invalid 309 | m->type->env->lasterror = "wmessage_string invalid enum"; 310 | return -1; 311 | } 312 | id |= WT_VARINT; 313 | m->ptr += _pbcV_encode32(id, m->ptr); 314 | m->ptr += _pbcV_encode32(enum_id, m->ptr); 315 | break; 316 | } 317 | case PTYPE_STRING: 318 | case PTYPE_BYTES: 319 | id |= WT_LEND; 320 | m->ptr += _pbcV_encode32(id, m->ptr); 321 | m->ptr += _pbcV_encode32(len, m->ptr); 322 | _expand_message(m,len); 323 | memcpy(m->ptr , v , len); 324 | m->ptr += len; 325 | break; 326 | } 327 | 328 | return 0; 329 | } 330 | 331 | struct pbc_wmessage * 332 | pbc_wmessage_message(struct pbc_wmessage *m, const char *key) { 333 | struct _field * f = (struct _field *)_pbcM_sp_query(m->type->name,key); 334 | if (f == NULL) { 335 | // todo : error 336 | m->type->env->lasterror = "wmessage_message query key error"; 337 | return NULL; 338 | } 339 | pbc_var var; 340 | var->p[0] = _wmessage_new(m->heap, f->type_name.m); 341 | var->p[1] = f; 342 | _pbcA_push(m->sub , var); 343 | return (struct pbc_wmessage *)var->p[0]; 344 | } 345 | 346 | static void 347 | _pack_packed_64(struct _packed *p,struct pbc_wmessage *m) { 348 | int n = pbc_array_size(p->data); 349 | int len = n * 8; 350 | int i; 351 | pbc_var var; 352 | _expand_message(m,10 + len); 353 | m->ptr += _pbcV_encode32(len, m->ptr); 354 | switch (p->ptype) { 355 | case PTYPE_DOUBLE: 356 | for (i=0;idata, i, var); 358 | double_encode(var->real , m->ptr + i * 8); 359 | } 360 | break; 361 | default: 362 | for (i=0;idata, i, var); 364 | int64_encode(var->integer.low , var->integer.hi, m->ptr + i * 8); 365 | } 366 | break; 367 | } 368 | m->ptr += len; 369 | } 370 | 371 | static void 372 | _pack_packed_32(struct _packed *p,struct pbc_wmessage *m) { 373 | int n = pbc_array_size(p->data); 374 | int len = n * 4; 375 | int i; 376 | pbc_var var; 377 | _expand_message(m,10 + len); 378 | m->ptr += _pbcV_encode32(len, m->ptr); 379 | switch (p->ptype) { 380 | case PTYPE_FLOAT: 381 | for (i=0;idata, i, var); 383 | float_encode(var->real , m->ptr + i * 8); 384 | } 385 | break; 386 | default: 387 | for (i=0;idata, i, var); 389 | int32_encode(var->integer.low , m->ptr + i * 8); 390 | } 391 | break; 392 | } 393 | m->ptr += len; 394 | } 395 | 396 | static void 397 | _pack_packed_varint(struct _packed *p,struct pbc_wmessage *m) { 398 | int n = pbc_array_size(p->data); 399 | 400 | int offset = m->ptr - m->buffer; 401 | int len = n * 2; 402 | if (p->ptype == PTYPE_BOOL) { 403 | len = n; 404 | } 405 | int i; 406 | pbc_var var; 407 | _expand_message(m,10 + len); 408 | int len_len = _pbcV_encode32(len, m->ptr); 409 | m->ptr += len_len; 410 | 411 | switch (p->ptype) { 412 | case PTYPE_INT64: 413 | case PTYPE_UINT64: 414 | for (i=0;idata, i, var); 416 | _expand_message(m,10); 417 | m->ptr += _pbcV_encode((uint64_t)var->integer.low | (uint64_t)var->integer.hi << 32 , m->ptr); 418 | } 419 | break; 420 | case PTYPE_INT32: 421 | case PTYPE_BOOL: 422 | case PTYPE_UINT32: 423 | case PTYPE_ENUM: 424 | for (i=0;idata, i, var); 426 | _expand_message(m,10); 427 | m->ptr += _pbcV_encode32(var->integer.low , m->ptr); 428 | } 429 | break; 430 | case PTYPE_SINT32: 431 | for (i=0;idata, i, var); 433 | _expand_message(m,10); 434 | m->ptr += _pbcV_zigzag32(var->integer.low, m->ptr); 435 | } 436 | break; 437 | case PTYPE_SINT64: 438 | for (i=0;idata, i, var); 440 | _expand_message(m,10); 441 | m->ptr += _pbcV_zigzag((uint64_t)var->integer.low | (uint64_t)var->integer.hi << 32 , m->ptr); 442 | } 443 | break; 444 | default: 445 | // error 446 | memset(m->ptr , 0 , n); 447 | m->ptr += n; 448 | m->type->env->lasterror = "wmessage type error when pack packed"; 449 | break; 450 | } 451 | int end_offset = m->ptr - m->buffer; 452 | int end_len = end_offset - (offset + len_len); 453 | if (end_len != len) { 454 | uint8_t temp[10]; 455 | int end_len_len = _pbcV_encode32(end_len, temp); 456 | if (end_len_len != len_len) { 457 | _expand_message(m, end_len_len); 458 | memmove(m->buffer + offset + end_len_len , 459 | m->buffer + offset + len_len , 460 | end_len); 461 | m->ptr += end_len_len - len_len; 462 | } 463 | memcpy(m->buffer + offset , temp, end_len_len); 464 | } 465 | } 466 | 467 | static void 468 | _pack_packed(void *p, void *ud) { 469 | struct _packed *packed = (struct _packed *)p; 470 | struct pbc_wmessage * m = (struct pbc_wmessage *)ud; 471 | int id = packed->id << 3 | WT_LEND; 472 | _expand_message(m,10); 473 | m->ptr += _pbcV_encode32(id, m->ptr); 474 | switch(packed->ptype) { 475 | case PTYPE_DOUBLE: 476 | case PTYPE_FIXED64: 477 | case PTYPE_SFIXED64: 478 | _pack_packed_64(packed,m); 479 | break; 480 | case PTYPE_FLOAT: 481 | case PTYPE_FIXED32: 482 | case PTYPE_SFIXED32: 483 | _pack_packed_32(packed,m); 484 | break; 485 | default: 486 | _pack_packed_varint(packed,m); 487 | break; 488 | } 489 | } 490 | 491 | void * 492 | pbc_wmessage_buffer(struct pbc_wmessage *m, struct pbc_slice *slice) { 493 | if (m->packed) { 494 | _pbcM_sp_foreach_ud(m->packed , _pack_packed, m); 495 | } 496 | int i; 497 | int n = pbc_array_size(m->sub); 498 | for (i=0;isub, i , var); 501 | struct pbc_slice s; 502 | pbc_wmessage_buffer((struct pbc_wmessage *)var->p[0] , &s); 503 | if (s.buffer) { 504 | struct _field * f = (struct _field *)var->p[1]; 505 | int id = f->id << 3 | WT_LEND; 506 | _expand_message(m,20+s.len); 507 | m->ptr += _pbcV_encode32(id, m->ptr); 508 | m->ptr += _pbcV_encode32(s.len, m->ptr); 509 | memcpy(m->ptr, s.buffer, s.len); 510 | m->ptr += s.len; 511 | } 512 | } 513 | slice->buffer = m->buffer; 514 | slice->len = m->ptr - m->buffer; 515 | 516 | return m->buffer; 517 | } 518 | 519 | -------------------------------------------------------------------------------- /test/addressbook.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "readfile.h" 9 | 10 | static void 11 | dump(uint8_t *buffer, int sz) { 12 | int i , j; 13 | for (i=0;i=32 && c<127) { 19 | printf("%c",c); 20 | } else { 21 | printf("."); 22 | } 23 | } 24 | printf("\n"); 25 | } 26 | } 27 | 28 | printf("\n"); 29 | } 30 | 31 | static void 32 | test_rmessage(struct pbc_env *env, struct pbc_slice *slice) { 33 | struct pbc_rmessage * m = pbc_rmessage_new(env, "tutorial.Person", slice); 34 | if (m==NULL) { 35 | printf("Error : %s",pbc_error(env)); 36 | return; 37 | } 38 | printf("name = %s\n", pbc_rmessage_string(m , "name" , 0 , NULL)); 39 | printf("id = %d\n", pbc_rmessage_integer(m , "id" , 0 , NULL)); 40 | printf("email = %s\n", pbc_rmessage_string(m , "email" , 0 , NULL)); 41 | 42 | int phone_n = pbc_rmessage_size(m, "phone"); 43 | int i; 44 | const char * field_name; 45 | pbc_type(env, "tutorial.Person", "phone", &field_name); 46 | printf("phone type [%s]\n",field_name); 47 | 48 | for (i=0;i 6 | 7 | int 8 | main() 9 | { 10 | pbc_array array; 11 | pbc_var v; 12 | 13 | _pbcA_open(array); 14 | 15 | int i ; 16 | 17 | for (i=0;i<100;i++) { 18 | v->real = (double)i; 19 | printf("push %d\n",i); 20 | _pbcA_push(array, v); 21 | } 22 | 23 | int s = pbc_array_size(array); 24 | 25 | for (i=0;ireal); 28 | } 29 | 30 | _pbcA_close(array); 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /test/decode.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "readfile.h" 8 | 9 | static void 10 | decode_all(void *ud , int type, const char * typename , union pbc_value *v, int id, const char *key) { 11 | printf("%s : ", key ) ; 12 | switch(type & ~PBC_REPEATED) { 13 | case PBC_MESSAGE: 14 | printf("[%s] -> \n" , typename); 15 | pbc_decode(ud, typename, &(v->s), decode_all, ud); 16 | printf("---------\n"); 17 | break; 18 | case PBC_INT: 19 | printf("%d\n", (int)v->i.low); 20 | break; 21 | case PBC_REAL: 22 | printf("%lf\n", v->f); 23 | break; 24 | case PBC_BOOL: 25 | printf("<%s>\n", v->i.low ? "true" : "false"); 26 | break; 27 | case PBC_ENUM: 28 | printf("[%s:%d]\n", v->e.name , v->e.id); 29 | break; 30 | case PBC_STRING: { 31 | char buffer[v->s.len+1]; 32 | memcpy(buffer, v->s.buffer, v->s.len); 33 | buffer[v->s.len] = '\0'; 34 | printf("\"%s\"\n", buffer); 35 | break; 36 | } 37 | case PBC_BYTES: { 38 | int i; 39 | uint8_t *buffer = v->s.buffer; 40 | for (i=0;is.len;i++) { 41 | printf("%02X ",buffer[i]); 42 | } 43 | printf("\n"); 44 | break; 45 | } 46 | case PBC_INT64: { 47 | printf("0x%x%08x\n",v->i.hi, v->i.low); 48 | break; 49 | } 50 | case PBC_UINT: 51 | printf("%u\n",v->i.low); 52 | break; 53 | default: 54 | printf("!!! %d\n", type); 55 | break; 56 | } 57 | } 58 | 59 | void 60 | test_decode(struct pbc_env * env , const char * pb) 61 | { 62 | struct pbc_slice slice; 63 | read_file(pb, &slice); 64 | 65 | pbc_decode(env, "google.protobuf.FileDescriptorSet", &slice, decode_all , env); 66 | 67 | int ret = pbc_register(env, &slice); 68 | 69 | printf("Register %d\n",ret); 70 | 71 | free(slice.buffer); 72 | } 73 | 74 | int 75 | main(int argc, char *argv[]) 76 | { 77 | struct pbc_env * env = pbc_new(); 78 | 79 | test_decode(env,argv[1]); 80 | 81 | pbc_delete(env); 82 | 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /test/float.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "readfile.h" 9 | 10 | static void 11 | dump(uint8_t *buffer, int sz) { 12 | int i , j; 13 | for (i=0;i=32 && c<127) { 19 | printf("%c",c); 20 | } else { 21 | printf("."); 22 | } 23 | } 24 | printf("\n"); 25 | } 26 | } 27 | 28 | printf("\n"); 29 | } 30 | 31 | static void 32 | test_rmessage(struct pbc_env *env, struct pbc_slice *slice) { 33 | struct pbc_rmessage * m = pbc_rmessage_new(env, "real", slice); 34 | printf("f = %f\n", pbc_rmessage_real(m , "f" , 0 )); 35 | printf("d = %f\n", pbc_rmessage_real(m , "d" , 0 )); 36 | pbc_rmessage_delete(m); 37 | } 38 | 39 | static struct pbc_wmessage * 40 | test_wmessage(struct pbc_env * env) 41 | { 42 | struct pbc_wmessage * msg = pbc_wmessage_new(env, "real"); 43 | 44 | pbc_wmessage_real(msg, "f", 1.0); 45 | pbc_wmessage_real(msg, "d" , 4.0); 46 | 47 | return msg; 48 | } 49 | 50 | int 51 | main() 52 | { 53 | struct pbc_slice slice; 54 | read_file("float.pb", &slice); 55 | if (slice.buffer == NULL) 56 | return 1; 57 | struct pbc_env * env = pbc_new(); 58 | pbc_register(env, &slice); 59 | 60 | free(slice.buffer); 61 | 62 | struct pbc_wmessage *msg = test_wmessage(env); 63 | 64 | pbc_wmessage_buffer(msg, &slice); 65 | 66 | dump(slice.buffer, slice.len); 67 | 68 | test_rmessage(env, &slice); 69 | 70 | pbc_wmessage_delete(msg); 71 | pbc_delete(env); 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /test/float.proto: -------------------------------------------------------------------------------- 1 | message real { 2 | optional float f = 1; 3 | optional double d = 2; 4 | } 5 | -------------------------------------------------------------------------------- /test/map.c: -------------------------------------------------------------------------------- 1 | #include "src/map.h" 2 | 3 | #include 4 | #include 5 | 6 | int 7 | main() 8 | { 9 | struct map_kv kv[] = { 10 | {1,"alice"}, 11 | {3,"bob" }, 12 | {99,"carol"}, 13 | }; 14 | 15 | struct map_ip * map = _pbcM_ip_new(kv, sizeof(kv)/sizeof(kv[0])); 16 | struct map_si * map2 = _pbcM_si_new(kv, sizeof(kv)/sizeof(kv[0])); 17 | int i; 18 | 19 | for (i=0;i<100;i++) { 20 | void *p= _pbcM_ip_query(map,i); 21 | if (p) { 22 | int id = 0; 23 | _pbcM_si_query(map2,p,&id); 24 | printf("%d %s\n",id,(const char *)p); 25 | } 26 | } 27 | 28 | struct map_sp * map3 = _pbcM_sp_new(0, NULL); 29 | _pbcM_sp_insert(map3,"Alice","alice"); 30 | _pbcM_sp_insert(map3,"Bob","bob"); 31 | 32 | void ** r = _pbcM_sp_query_insert(map3, "Carol"); 33 | *r = "carol"; 34 | 35 | r = _pbcM_sp_query_insert(map3, "Alice"); 36 | *r = "not alice"; 37 | 38 | printf("%s\n",(const char *)_pbcM_sp_query(map3,"Alice")); 39 | printf("%s\n",(const char *)_pbcM_sp_query(map3,"Bob")); 40 | printf("%s\n",(const char *)_pbcM_sp_query(map3,"Carol")); 41 | 42 | const char * key = NULL; 43 | for (;;) { 44 | void * v = _pbcM_sp_next(map3, &key); 45 | if (key == NULL) 46 | break; 47 | printf("%s : %s\n", key, (const char *)v); 48 | } 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /test/pattern.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "readfile.h" 9 | 10 | static void 11 | dump(uint8_t *buffer, int sz) { 12 | int i , j; 13 | for (i=0;i=32 && c<127) { 19 | printf("%c",c); 20 | } else { 21 | printf("."); 22 | } 23 | } 24 | printf("\n"); 25 | } 26 | } 27 | 28 | printf("\n"); 29 | } 30 | 31 | static struct pbc_pattern *pat; 32 | static struct pbc_pattern *pat_phone; 33 | 34 | struct person_phone { 35 | struct pbc_slice number; 36 | int32_t type; 37 | }; 38 | 39 | struct person { 40 | struct pbc_slice name; 41 | int32_t id; 42 | struct pbc_slice email; 43 | pbc_array phone; 44 | pbc_array test; 45 | }; 46 | 47 | 48 | static void 49 | test_pattern_unpack(struct pbc_env *env, struct pbc_slice * slice) { 50 | struct person p; 51 | int r = pbc_pattern_unpack(pat, slice, &p); 52 | if (r>=0) { 53 | printf("name = %s\n",(const char *)p.name.buffer); 54 | printf("id = %d\n",p.id); 55 | printf("email = %s\n",(const char *)p.email.buffer); 56 | int n = pbc_array_size(p.phone); 57 | int i; 58 | for (i=0;ilen = 0; 102 | return slice->len; 103 | } 104 | 105 | pbc_array_push_slice(p.phone, &phone_slice); 106 | 107 | pbc_pattern_set_default(pat_phone, &phone); 108 | 109 | phone.number.buffer = (void *)"87654321"; 110 | phone.number.len = -1; 111 | 112 | char temp2[128]; 113 | struct pbc_slice phone_slice2 = { temp2, sizeof(temp2) }; 114 | 115 | unused = pbc_pattern_pack(pat_phone, &phone , &phone_slice2); 116 | 117 | if (unused < 0) { 118 | slice->len = 0; 119 | return slice->len; 120 | } 121 | 122 | pbc_array_push_slice(p.phone, &phone_slice2); 123 | 124 | int i; 125 | for (i=0;i<3;i++) { 126 | pbc_array_push_integer(p.test, -i*4,0); 127 | } 128 | 129 | int r = pbc_pattern_pack(pat, &p, slice); 130 | 131 | pbc_pattern_close_arrays(pat,&p); 132 | printf("pack into %d bytes\n", slice->len); 133 | 134 | return r; 135 | } 136 | 137 | int 138 | main() 139 | { 140 | struct pbc_slice slice; 141 | read_file("addressbook.pb", &slice); 142 | if (slice.buffer == NULL) 143 | return 1; 144 | struct pbc_env * env = pbc_new(); 145 | pbc_register(env, &slice); 146 | 147 | free(slice.buffer); 148 | 149 | pat = pbc_pattern_new(env, "tutorial.Person" , 150 | "name %s id %d email %s phone %a test %a", 151 | offsetof(struct person, name) , 152 | offsetof(struct person, id) , 153 | offsetof(struct person, email) , 154 | offsetof(struct person, phone) , 155 | offsetof(struct person, test)); 156 | 157 | pat_phone = pbc_pattern_new(env, "tutorial.Person.PhoneNumber", 158 | "number %s type %d", 159 | offsetof(struct person_phone, number), 160 | offsetof(struct person_phone, type)); 161 | 162 | 163 | char buffer[4096]; 164 | struct pbc_slice message = { buffer, sizeof(buffer) }; 165 | 166 | test_pattern_pack(env, &message); 167 | 168 | dump(message.buffer, message.len); 169 | 170 | test_pattern_unpack(env, &message); 171 | 172 | pbc_pattern_delete(pat); 173 | pbc_pattern_delete(pat_phone); 174 | 175 | pbc_delete(env); 176 | 177 | return 0; 178 | } 179 | -------------------------------------------------------------------------------- /test/pbc.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "readfile.h" 7 | 8 | void 9 | test_des(struct pbc_env * env , const char * pb) 10 | { 11 | struct pbc_slice slice; 12 | read_file(pb, &slice); 13 | 14 | struct pbc_rmessage * msg = pbc_rmessage_new(env, "google.protobuf.FileDescriptorSet", &slice); 15 | 16 | struct pbc_rmessage * file = pbc_rmessage_message(msg,"file",0); 17 | 18 | printf("name = %s\n",pbc_rmessage_string(file, "name", 0 , NULL)); 19 | printf("package = %s\n",pbc_rmessage_string(file, "package", 0 , NULL)); 20 | 21 | int sz = pbc_rmessage_size(file, "dependency"); 22 | printf("dependency[%d] =\n" , sz); 23 | int i; 24 | for (i=0;i 5 | #include 6 | 7 | static void 8 | read_file (const char *filename , struct pbc_slice *slice) { 9 | FILE *f = fopen(filename, "rb"); 10 | if (f == NULL) { 11 | slice->buffer = NULL; 12 | slice->len = 0; 13 | return; 14 | } 15 | fseek(f,0,SEEK_END); 16 | slice->len = ftell(f); 17 | fseek(f,0,SEEK_SET); 18 | slice->buffer = malloc(slice->len); 19 | if (fread(slice->buffer, 1 , slice->len , f) == 0) 20 | exit(1); 21 | fclose(f); 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /test/test.c: -------------------------------------------------------------------------------- 1 | #include "pbc.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define COUNT 1000000 8 | 9 | #include "readfile.h" 10 | 11 | static void 12 | test(struct pbc_env *env) { 13 | int i; 14 | for(i=0; i 2 | 3 | #include "varint.h" 4 | #include "pbc.h" 5 | 6 | static void 7 | dump(uint8_t buffer[10], int s) 8 | { 9 | int i; 10 | for (i=0;i 2 | #include 3 | #include 4 | #include 5 | 6 | #include "pbc.h" 7 | 8 | static void 9 | read_file(const char *filename , struct pbc_slice *slice) { 10 | FILE *f = fopen(filename, "rb"); 11 | if (f == NULL) { 12 | fprintf(stderr, "Can't open file %s\n", filename); 13 | exit(1); 14 | } 15 | fseek(f,0,SEEK_END); 16 | slice->len = ftell(f); 17 | fseek(f,0,SEEK_SET); 18 | slice->buffer = malloc(slice->len); 19 | fread(slice->buffer, 1 , slice->len , f); 20 | fclose(f); 21 | } 22 | 23 | static void 24 | dump_bytes(const char *data, size_t len) { 25 | size_t i; 26 | for (i = 0; i < len; i++) 27 | if (i == 0) 28 | fprintf(stdout, "%02x", 0xff & data[i]); 29 | else 30 | fprintf(stdout, " %02x", 0xff & data[i]); 31 | } 32 | 33 | static void dump_message(struct pbc_rmessage *m, int level); 34 | 35 | static void 36 | dump_value(struct pbc_rmessage *m, const char *key, int type, int idx, int level) { 37 | int i; 38 | for (i=0;i= data->len) { 140 | data->len *= 2; 141 | data->buffer = realloc(data->buffer, data->len); 142 | } 143 | ((uint8_t *)data->buffer)[idx] = (uint8_t)byte; 144 | } 145 | 146 | static void 147 | read_stdin(int mode, struct pbc_slice *data) { 148 | data->len = 128; 149 | data->buffer = malloc(data->len); 150 | int idx = 0; 151 | while(!feof(stdin)) { 152 | int byte; 153 | int r = scanf("%d" , &byte); 154 | if (r == 0) { 155 | break; 156 | } 157 | push_byte(byte, data, idx); 158 | ++idx; 159 | } 160 | data->len = idx; 161 | } 162 | 163 | static void 164 | usage(const char *argv0) { 165 | printf(" -h help.\n" 166 | " -p protobuf file\n" 167 | " -m \n" 168 | " -d \n" 169 | " -D input from stdin (DEC number)\n" 170 | ); 171 | } 172 | 173 | int 174 | main(int argc , char * argv[]) 175 | { 176 | int ch; 177 | const char * proto = NULL; 178 | const char * message = NULL; 179 | const char * datafile = NULL; 180 | int mode = 0; 181 | while ((ch = getopt(argc, argv, "hDp:m:d:")) != -1) { 182 | switch(ch) { 183 | case 'h': 184 | usage(argv[0]); 185 | return 0; 186 | case 'p': 187 | proto = optarg; 188 | break; 189 | case 'm': 190 | message = optarg; 191 | break; 192 | case 'd': 193 | datafile = optarg; 194 | break; 195 | case 'D': 196 | mode = 10; 197 | break; 198 | default: 199 | usage(argv[0]); 200 | return 1; 201 | } 202 | } 203 | 204 | if (proto == NULL || message == NULL) { 205 | usage(argv[0]); 206 | return 1; 207 | } 208 | 209 | struct pbc_slice data; 210 | 211 | if (datafile == NULL) { 212 | read_stdin(mode, &data); 213 | } else { 214 | read_file(datafile , &data); 215 | } 216 | 217 | dump(proto , message , &data); 218 | 219 | return 0; 220 | } 221 | 222 | --------------------------------------------------------------------------------