├── .gitattributes ├── README.md └── slua_unreal ├── Public └── luaprotobuf │ ├── lpb.h │ └── pb.h └── Private ├── LuaProtobufWrap.h ├── LuaProtobufWrap.cpp └── luaprotobuf ├── pb.cpp └── lpb.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # slua-unreal-pb 2 | 3 | sluaunreal 4 | https://github.com/Tencent/sluaunreal 5 | 6 | lua-protobuf 7 | https://github.com/starwing/lua-protobuf 8 | 9 | 集成lua-protobuf到sluaunreal中 10 | 11 | 1 复制slua_unreal到sluaunreal的插件目录中 12 | 13 | 2 在LuaState的init函数中的LuaSocket::init(L)代码前添加代码LuaProtobuf::init(L) 14 | -------------------------------------------------------------------------------- /slua_unreal/Public/luaprotobuf/lpb.h: -------------------------------------------------------------------------------- 1 | #ifndef lpb_h 2 | #define lpb_h 3 | 4 | #include "lua/lua.h" 5 | 6 | #ifndef LUALIB_API 7 | # define LUALIB_API extern 8 | #endif 9 | 10 | namespace NS_SLUA { 11 | 12 | LUALIB_API int luaopen_pb_conv(lua_State *L); 13 | LUALIB_API int luaopen_pb_buffer(lua_State *L); 14 | LUALIB_API int luaopen_pb_slice(lua_State *L); 15 | LUALIB_API int luaopen_pb(lua_State *L); 16 | 17 | } // end NS_SLUA 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /slua_unreal/Private/LuaProtobufWrap.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making sluaunreal available. 2 | 3 | // Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved. 4 | // Licensed under the BSD 3-Clause License (the "License"); 5 | // you may not use this file except in compliance with the License. You may obtain a copy of the License at 6 | 7 | // https://opensource.org/licenses/BSD-3-Clause 8 | 9 | // Unless required by applicable law or agreed to in writing, 10 | // software distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and limitations under the License. 13 | 14 | #pragma once 15 | 16 | #include "lua/lua.hpp" 17 | 18 | namespace NS_SLUA { 19 | namespace LuaProtobuf { 20 | void init(lua_State *L); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /slua_unreal/Private/LuaProtobufWrap.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making sluaunreal available. 2 | 3 | // Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved. 4 | // Licensed under the BSD 3-Clause License (the "License"); 5 | // you may not use this file except in compliance with the License. You may obtain a copy of the License at 6 | 7 | // https://opensource.org/licenses/BSD-3-Clause 8 | 9 | // Unless required by applicable law or agreed to in writing, 10 | // software distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and limitations under the License. 13 | 14 | #include "LuaProtobufWrap.h" 15 | #include "luaprotobuf/lpb.h" 16 | 17 | namespace NS_SLUA { 18 | 19 | namespace LuaProtobuf { 20 | 21 | void init(lua_State *L) { 22 | 23 | luaL_requiref(L, "pb", luaopen_pb, 0); 24 | luaL_requiref(L, "pb.slice", luaopen_pb_slice, 0); 25 | luaL_requiref(L, "pb.buffer", luaopen_pb_buffer, 0); 26 | luaL_requiref(L, "pb.conv", luaopen_pb_conv, 0); 27 | 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /slua_unreal/Public/luaprotobuf/pb.h: -------------------------------------------------------------------------------- 1 | #ifndef PB_H 2 | #define PB_H 3 | 4 | #include 5 | #include 6 | 7 | #ifndef PB_API 8 | # define PB_API extern 9 | #endif 10 | 11 | #if defined(_MSC_VER) || defined(__UNIXOS2__) || defined(__SOL64__) 12 | typedef unsigned char uint8_t; 13 | typedef signed char int8_t; 14 | typedef unsigned short uint16_t; 15 | typedef signed short int16_t; 16 | typedef unsigned int uint32_t; 17 | typedef signed int int32_t; 18 | typedef unsigned long long uint64_t; 19 | typedef signed long long int64_t; 20 | #define INT64_MIN LLONG_MIN 21 | #define INT64_MAX LLONG_MAX 22 | 23 | #elif defined(__SCO__) || defined(__USLC__) || defined(__MINGW32__) 24 | # include 25 | #else 26 | # include 27 | # if (defined(__sun__) || defined(__digital__)) 28 | # if defined(__STDC__) && (defined(__arch64__) || defined(_LP64)) 29 | typedef unsigned long int uint64_t; 30 | typedef signed long int int64_t; 31 | # else 32 | typedef unsigned long long uint64_t; 33 | typedef signed long long int64_t; 34 | # endif /* LP64 */ 35 | # endif /* __sun__ || __digital__ */ 36 | #endif 37 | 38 | #define PB_MAX_SIZET ((size_t)~0 - 100) 39 | #define PB_MIN_STRTABLE_SIZE 16 40 | #define PB_MIN_HASHTABLE_SIZE 8 41 | #define PB_HASHLIMIT 5 42 | 43 | namespace NS_SLUA { 44 | 45 | /* types */ 46 | 47 | #define PB_WIRETYPES(X) /* X(name, index) */\ 48 | X(VARINT, "varint", 0) X(64BIT, "64bit", 1) X(BYTES, "bytes", 2) \ 49 | X(GSTART, "gstart", 3) X(GEND, "gend", 4) X(32BIT, "32bit", 5) \ 50 | 51 | #define PB_TYPES(X) /* X(name, type, index) */\ 52 | X(double, double, 1) X(float, float, 2) \ 53 | X(int64, int64_t, 3) X(uint64, uint64_t, 4) \ 54 | X(int32, int32_t, 5) X(fixed64, uint64_t, 6) \ 55 | X(fixed32, uint32_t, 7) X(bool, int, 8) \ 56 | X(string, pb_Slice, 9) X(group, pb_Slice, 10) \ 57 | X(message, pb_Slice, 11) X(bytes, pb_Slice, 12) \ 58 | X(uint32, uint32_t, 13) X(enum, int32_t, 14) \ 59 | X(sfixed32, int32_t, 15) X(sfixed64, int64_t, 16) \ 60 | X(sint32, int32_t, 17) X(sint64, int64_t, 18) \ 61 | 62 | typedef enum pb_WireType { 63 | #define X(name, s, index) PB_T##name, 64 | PB_WIRETYPES(X) 65 | #undef X 66 | PB_TWIRECOUNT 67 | } pb_WireType; 68 | 69 | typedef enum pb_FieldType { 70 | #define X(name, type, index) PB_T##name = index, 71 | PB_TYPES(X) 72 | #undef X 73 | PB_TYPECOUNT 74 | } pb_FieldType; 75 | 76 | 77 | /* conversions */ 78 | 79 | PB_API uint64_t pb_expandsig(uint32_t v); 80 | PB_API uint32_t pb_encode_sint32(int32_t v); 81 | PB_API int32_t pb_decode_sint32(uint32_t v); 82 | PB_API uint64_t pb_encode_sint64(int64_t v); 83 | PB_API int64_t pb_decode_sint64(uint64_t v); 84 | PB_API uint32_t pb_encode_float(float v); 85 | PB_API float pb_decode_float(uint32_t v); 86 | PB_API uint64_t pb_encode_double(double v); 87 | PB_API double pb_decode_double(uint64_t v); 88 | 89 | 90 | /* decode */ 91 | 92 | typedef struct pb_Slice { const char *p, *end; } pb_Slice; 93 | #define pb_gettype(v) ((v) & 7) 94 | #define pb_gettag(v) ((v) >> 3) 95 | #define pb_pair(tag, type) ((tag) << 3 | ((type) & 7)) 96 | 97 | PB_API pb_Slice pb_slice(const char *p); 98 | PB_API pb_Slice pb_lslice(const char *p, size_t len); 99 | PB_API size_t pb_len(pb_Slice s); 100 | 101 | PB_API size_t pb_readvarint32(pb_Slice *s, uint32_t *pv); 102 | PB_API size_t pb_readvarint64(pb_Slice *s, uint64_t *pv); 103 | PB_API size_t pb_readfixed32(pb_Slice *s, uint32_t *pv); 104 | PB_API size_t pb_readfixed64(pb_Slice *s, uint64_t *pv); 105 | 106 | PB_API size_t pb_readslice(pb_Slice *s, size_t len, pb_Slice *pv); 107 | PB_API size_t pb_readbytes(pb_Slice *s, pb_Slice *pv); 108 | PB_API size_t pb_readgroup(pb_Slice *s, uint32_t tag, pb_Slice *pv); 109 | 110 | PB_API size_t pb_skipvarint(pb_Slice *s); 111 | PB_API size_t pb_skipbytes(pb_Slice *s); 112 | PB_API size_t pb_skipslice(pb_Slice *s, size_t len); 113 | PB_API size_t pb_skipvalue(pb_Slice *s, uint32_t tag); 114 | 115 | PB_API const char *pb_wtypename(int wiretype, const char *def); 116 | PB_API const char *pb_typename(int type, const char *def); 117 | 118 | PB_API int pb_typebyname(const char *name, int def); 119 | PB_API int pb_wtypebyname(const char *name, int def); 120 | PB_API int pb_wtypebytype(int type); 121 | 122 | 123 | /* encode */ 124 | 125 | #define PB_BUFFERSIZE (1024) 126 | 127 | typedef struct pb_Buffer { 128 | size_t size; 129 | size_t capacity; 130 | char *buff; 131 | char init_buff[PB_BUFFERSIZE]; 132 | } pb_Buffer; 133 | 134 | #define pb_buffer(b) ((b)->buff) 135 | #define pb_bufflen(b) ((b)->size) 136 | #define pb_addsize(b, sz) ((void)((b)->size += (sz))) 137 | #define pb_addchar(b, ch) \ 138 | ((void)((b)->size < (b)->capacity || pb_prepbuffsize((b), 1)), \ 139 | ((b)->buff[(b)->size++] = (ch))) 140 | 141 | PB_API void pb_initbuffer(pb_Buffer *b); 142 | PB_API void pb_resetbuffer(pb_Buffer *b); 143 | PB_API size_t pb_resizebuffer(pb_Buffer *b, size_t len); 144 | PB_API void *pb_prepbuffsize(pb_Buffer *b, size_t len); 145 | 146 | PB_API pb_Slice pb_result(pb_Buffer *b); 147 | 148 | PB_API size_t pb_addvarint32(pb_Buffer *b, uint32_t v); 149 | PB_API size_t pb_addvarint64(pb_Buffer *b, uint64_t v); 150 | PB_API size_t pb_addfixed32(pb_Buffer *b, uint32_t v); 151 | PB_API size_t pb_addfixed64(pb_Buffer *b, uint64_t v); 152 | 153 | PB_API size_t pb_addslice(pb_Buffer *b, pb_Slice s); 154 | PB_API size_t pb_addbytes(pb_Buffer *b, pb_Slice s); 155 | PB_API size_t pb_addlength(pb_Buffer *b, size_t len); 156 | 157 | 158 | /* type info database state and name table */ 159 | 160 | typedef struct pb_State pb_State; 161 | typedef struct pb_Name pb_Name; 162 | 163 | PB_API void pb_init(pb_State *S); 164 | PB_API void pb_free(pb_State *S); 165 | 166 | PB_API pb_Name *pb_newname(pb_State *S, pb_Slice s); 167 | PB_API void pb_delname(pb_State *S, pb_Name *name); 168 | PB_API pb_Name *pb_name(pb_State *S, const char *name); 169 | 170 | PB_API pb_Name *pb_usename(pb_Name *name); 171 | 172 | 173 | /* type info */ 174 | 175 | typedef struct pb_Type pb_Type; 176 | typedef struct pb_Field pb_Field; 177 | 178 | #define PB_OK 0 179 | #define PB_ERROR 1 180 | #define PB_ENOMEM 2 181 | 182 | PB_API int pb_load(pb_State *S, pb_Slice *s); 183 | 184 | PB_API pb_Type *pb_newtype(pb_State *S, pb_Name *tname); 185 | PB_API void pb_deltype(pb_State *S, pb_Type *t); 186 | PB_API pb_Field *pb_newfield(pb_State *S, pb_Type *t, pb_Name *fname, int32_t number); 187 | PB_API void pb_delfield(pb_State *S, pb_Type *t, pb_Field *f); 188 | 189 | PB_API pb_Type *pb_type(pb_State *S, pb_Name *tname); 190 | PB_API pb_Field *pb_fname(pb_Type *t, pb_Name *tname); 191 | PB_API pb_Field *pb_field(pb_Type *t, int32_t number); 192 | 193 | PB_API pb_Name *pb_oneofname(pb_Type *t, int oneof_index); 194 | 195 | PB_API int pb_nexttype(pb_State *S, pb_Type **ptype); 196 | PB_API int pb_nextfield(pb_Type *t, pb_Field **pfield); 197 | 198 | 199 | /* util: memory pool */ 200 | 201 | #define PB_POOLSIZE 4096 202 | 203 | typedef struct pb_Pool { 204 | void *pages; 205 | void *freed; 206 | size_t obj_size; 207 | } pb_Pool; 208 | 209 | PB_API void pb_initpool(pb_Pool *pool, size_t obj_size); 210 | PB_API void pb_freepool(pb_Pool *pool); 211 | 212 | PB_API void *pb_poolalloc(pb_Pool *pool); 213 | PB_API void pb_poolfree(pb_Pool *pool, void *obj); 214 | 215 | /* util: hash table */ 216 | 217 | typedef struct pb_Table pb_Table; 218 | typedef struct pb_Entry pb_Entry; 219 | typedef ptrdiff_t pb_Key; 220 | 221 | PB_API void pb_inittable(pb_Table *t, size_t entrysize); 222 | PB_API void pb_freetable(pb_Table *t); 223 | 224 | PB_API size_t pb_resizetable(pb_Table *t, size_t size); 225 | 226 | PB_API pb_Entry *pb_gettable(pb_Table *t, pb_Key key); 227 | PB_API pb_Entry *pb_settable(pb_Table *t, pb_Key key); 228 | PB_API int pb_nextentry(pb_Table *t, pb_Entry **pentry); 229 | 230 | struct pb_Table { 231 | size_t size; 232 | size_t lastfree; 233 | unsigned entry_size : sizeof(unsigned)*CHAR_BIT - 1; 234 | unsigned has_zero : 1; 235 | pb_Entry *hash; 236 | }; 237 | 238 | struct pb_Entry { 239 | ptrdiff_t next; 240 | pb_Key key; 241 | }; 242 | 243 | 244 | /* fields */ 245 | 246 | typedef struct pb_NameEntry { 247 | struct pb_NameEntry *next; 248 | unsigned hash : 32; 249 | unsigned length : 16; 250 | unsigned refcount : 16; 251 | } pb_NameEntry; 252 | 253 | typedef struct pb_NameTable { 254 | size_t size; 255 | size_t count; 256 | pb_NameEntry **hash; 257 | } pb_NameTable; 258 | 259 | struct pb_State { 260 | pb_Table types; 261 | pb_NameTable nametable; 262 | pb_Pool typepool; 263 | pb_Pool fieldpool; 264 | }; 265 | 266 | struct pb_Field { 267 | pb_Name *name; 268 | pb_Type *type; 269 | pb_Name *default_value; 270 | int32_t number; 271 | unsigned oneof_idx : 24; 272 | unsigned type_id : 5; /* PB_T* enum */ 273 | unsigned repeated : 1; 274 | unsigned packed : 1; 275 | unsigned scalar : 1; 276 | }; 277 | 278 | struct pb_Type { 279 | pb_Name *name; 280 | const char *basename; 281 | pb_Table field_tags; 282 | pb_Table field_names; 283 | pb_Table oneof_index; 284 | unsigned field_count : 28; 285 | unsigned is_enum : 1; 286 | unsigned is_map : 1; 287 | unsigned is_proto3 : 1; 288 | unsigned is_dead : 1; 289 | }; 290 | 291 | } 292 | 293 | #endif /* PB_H */ 294 | -------------------------------------------------------------------------------- /slua_unreal/Private/luaprotobuf/pb.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "pb.h" 6 | 7 | // Disable warning "interaction between '_setjmp' and C++ object destruction is non-portable" 8 | #ifdef _MSC_VER 9 | #pragma warning(push) 10 | #pragma warning(disable:4611) 11 | #pragma warning(disable:4706) 12 | #endif 13 | 14 | namespace NS_SLUA { 15 | 16 | /* conversions */ 17 | 18 | PB_API uint32_t pb_encode_sint32(int32_t value) 19 | { 20 | return ((uint32_t)value << 1) ^ -(value < 0); 21 | } 22 | 23 | PB_API int32_t pb_decode_sint32(uint32_t value) 24 | { 25 | return (value >> 1) ^ -(int32_t)(value & 1); 26 | } 27 | 28 | PB_API uint64_t pb_encode_sint64(int64_t value) 29 | { 30 | return ((uint64_t)value << 1) ^ -(value < 0); 31 | } 32 | 33 | PB_API int64_t pb_decode_sint64(uint64_t value) 34 | { 35 | return (value >> 1) ^ -(int64_t)(value & 1); 36 | } 37 | 38 | PB_API uint64_t pb_expandsig(uint32_t value) 39 | { 40 | uint64_t m = (uint64_t)1U << 31; return (value ^ m) - m; 41 | } 42 | 43 | PB_API uint32_t pb_encode_float(float value) 44 | { 45 | union { uint32_t u32; float f; } u; u.f = value; return u.u32; 46 | } 47 | 48 | PB_API float pb_decode_float(uint32_t value) 49 | { 50 | union { uint32_t u32; float f; } u; u.u32 = value; return u.f; 51 | } 52 | 53 | PB_API uint64_t pb_encode_double(double value) 54 | { 55 | union { uint64_t u64; double d; } u; u.d = value; return u.u64; 56 | } 57 | 58 | PB_API double pb_decode_double(uint64_t value) 59 | { 60 | union { uint64_t u64; double d; } u; u.u64 = value; return u.d; 61 | } 62 | 63 | 64 | /* decode */ 65 | 66 | PB_API pb_Slice pb_slice(const char *s) 67 | { 68 | return pb_lslice(s, strlen(s)); 69 | } 70 | 71 | PB_API pb_Slice pb_lslice(const char *s, size_t len) 72 | { 73 | pb_Slice slice; slice.p = s; slice.end = s + len; return slice; 74 | } 75 | 76 | PB_API size_t pb_len(pb_Slice s) 77 | { 78 | return s.end - s.p; 79 | } 80 | 81 | static size_t pb_readvarint_slow(pb_Slice *s, uint64_t *pv) { 82 | const char *p = s->p; 83 | uint64_t n = 0; 84 | int i = 0; 85 | while (s->p < s->end && i < 10) { 86 | int b = *s->p++; 87 | n |= ((uint64_t)b & 0x7F) << (7 * i++); 88 | if ((b & 0x80) == 0) { 89 | *pv = n; 90 | return i; 91 | } 92 | } 93 | s->p = p; 94 | return 0; 95 | } 96 | 97 | static size_t pb_readvarint32_fallback(pb_Slice *s, uint32_t *pv) { 98 | const uint8_t *p = (const uint8_t*)s->p, *o = p; 99 | uint32_t b, n; 100 | for (;;) { 101 | n = *p++ - 0x80, n += (b = *p++) << 7; if (!(b & 0x80)) break; 102 | n -= 0x80 << 7, n += (b = *p++) << 14; if (!(b & 0x80)) break; 103 | n -= 0x80 << 14, n += (b = *p++) << 21; if (!(b & 0x80)) break; 104 | n -= 0x80 << 21, n += (b = *p++) << 28; if (!(b & 0x80)) break; 105 | /* n -= 0x80 << 28; */ 106 | if (!(*p++ & 0x80)) break; 107 | if (!(*p++ & 0x80)) break; 108 | if (!(*p++ & 0x80)) break; 109 | if (!(*p++ & 0x80)) break; 110 | if (!(*p++ & 0x80)) break; 111 | return 0; 112 | } 113 | *pv = n; 114 | s->p = (const char*)p; 115 | return p - o; 116 | } 117 | 118 | static size_t pb_readvarint64_fallback(pb_Slice *s, uint64_t *pv) { 119 | const uint8_t *p = (const uint8_t*)s->p, *o = p; 120 | uint32_t b, n1, n2 = 0, n3 = 0; 121 | for (;;) { 122 | n1 = *p++ - 0x80, n1 += (b = *p++) << 7; if (!(b & 0x80)) break; 123 | n1 -= 0x80 << 7, n1 += (b = *p++) << 14; if (!(b & 0x80)) break; 124 | n1 -= 0x80 << 14, n1 += (b = *p++) << 21; if (!(b & 0x80)) break; 125 | n1 -= 0x80 << 21, n2 += (b = *p++); if (!(b & 0x80)) break; 126 | n2 -= 0x80, n2 += (b = *p++) << 7; if (!(b & 0x80)) break; 127 | n2 -= 0x80 << 7, n2 += (b = *p++) << 14; if (!(b & 0x80)) break; 128 | n2 -= 0x80 << 14, n2 += (b = *p++) << 21; if (!(b & 0x80)) break; 129 | n2 -= 0x80 << 21, n3 += (b = *p++); if (!(b & 0x80)) break; 130 | n3 -= 0x80, n3 += (b = *p++) << 7; if (!(b & 0x80)) break; 131 | return 0; 132 | } 133 | *pv = n1 | ((uint64_t)n2 << 28) | ((uint64_t)n3 << 56); 134 | s->p = (const char*)p; 135 | return p - o; 136 | } 137 | 138 | PB_API size_t pb_readvarint32(pb_Slice *s, uint32_t *pv) { 139 | uint64_t u64; 140 | size_t ret; 141 | if (s->p >= s->end) return 0; 142 | if (!(*s->p & 0x80)) { *pv = *s->p++; return 1; } 143 | if (pb_len(*s) >= 10 || !(s->end[-1] & 0x80)) 144 | return pb_readvarint32_fallback(s, pv); 145 | if ((ret = pb_readvarint_slow(s, &u64)) != 0) 146 | *pv = (uint32_t)u64; 147 | return ret; 148 | } 149 | 150 | PB_API size_t pb_readvarint64(pb_Slice *s, uint64_t *pv) { 151 | if (s->p >= s->end) return 0; 152 | if (!(*s->p & 0x80)) { *pv = *s->p++; return 1; } 153 | if (pb_len(*s) >= 10 || !(s->end[-1] & 0x80)) 154 | return pb_readvarint64_fallback(s, pv); 155 | return pb_readvarint_slow(s, pv); 156 | } 157 | 158 | PB_API size_t pb_readfixed32(pb_Slice *s, uint32_t *pv) { 159 | int i; 160 | uint32_t n = 0; 161 | if (s->p + 4 > s->end) 162 | return 0; 163 | for (i = 3; i >= 0; --i) { 164 | n <<= 8; 165 | n |= s->p[i] & 0xFF; 166 | } 167 | s->p += 4; 168 | *pv = n; 169 | return 4; 170 | } 171 | 172 | PB_API size_t pb_readfixed64(pb_Slice *s, uint64_t *pv) { 173 | int i; 174 | uint64_t n = 0; 175 | if (s->p + 8 > s->end) 176 | return 0; 177 | for (i = 7; i >= 0; --i) { 178 | n <<= 8; 179 | n |= s->p[i] & 0xFF; 180 | } 181 | s->p += 8; 182 | *pv = n; 183 | return 8; 184 | } 185 | 186 | PB_API size_t pb_readslice(pb_Slice *s, size_t len, pb_Slice *pv) { 187 | if (pb_len(*s) < len) 188 | return 0; 189 | pv->p = s->p; 190 | pv->end = s->p + len; 191 | s->p = pv->end; 192 | return len; 193 | } 194 | 195 | PB_API size_t pb_readbytes(pb_Slice *s, pb_Slice *pv) { 196 | const char *p = s->p; 197 | uint64_t len; 198 | if (pb_readvarint64(s, &len) == 0 || pb_len(*s) < len) { 199 | s->p = p; 200 | return 0; 201 | } 202 | pv->p = s->p; 203 | pv->end = s->p + len; 204 | s->p = pv->end; 205 | return s->p - p; 206 | } 207 | 208 | PB_API size_t pb_readgroup(pb_Slice *s, uint32_t tag, pb_Slice *pv) { 209 | const char *p = s->p; 210 | uint32_t newtag = 0; 211 | size_t count; 212 | assert(pb_gettype(tag) == PB_TGSTART); 213 | while ((count = pb_readvarint32(s, &newtag)) != 0) { 214 | if (pb_gettype(newtag) == PB_TGEND) { 215 | if (pb_gettag(newtag) != pb_gettag(tag)) 216 | break; 217 | pv->p = p; 218 | pv->end = s->p - count; 219 | return s->p - p; 220 | } 221 | pb_skipvalue(s, newtag); 222 | } 223 | s->p = p; 224 | return 0; 225 | } 226 | 227 | PB_API size_t pb_skipvalue(pb_Slice *s, uint32_t tag) { 228 | const char *p = s->p; 229 | size_t ret = 0; 230 | pb_Slice data; 231 | switch (pb_gettype(tag)) { 232 | default: break; 233 | case PB_TVARINT: ret = pb_skipvarint(s); break; 234 | case PB_T64BIT: ret = pb_skipslice(s, 8); break; 235 | case PB_TBYTES: ret = pb_skipbytes(s); break; 236 | case PB_T32BIT: ret = pb_skipslice(s, 4); break; 237 | case PB_TGSTART: ret = pb_readgroup(s, tag, &data); break; 238 | } 239 | if (!ret) s->p = p; 240 | return ret; 241 | } 242 | 243 | PB_API size_t pb_skipvarint(pb_Slice *s) { 244 | const char *p = s->p, *op = p; 245 | while (p < s->end && (*p & 0x80) != 0) ++p; 246 | if (p >= s->end) return 0; 247 | s->p = ++p; 248 | return p - op; 249 | } 250 | 251 | PB_API size_t pb_skipbytes(pb_Slice *s) { 252 | const char *p = s->p; 253 | uint64_t var; 254 | if (!pb_readvarint64(s, &var)) return 0; 255 | if (pb_len(*s) < var) { 256 | s->p = p; 257 | return 0; 258 | } 259 | s->p += var; 260 | return s->p - p; 261 | } 262 | 263 | PB_API size_t pb_skipslice(pb_Slice *s, size_t len) { 264 | if (s->p + len > s->end) return 0; 265 | s->p += len; 266 | return len; 267 | } 268 | 269 | PB_API int pb_wtypebytype(int type) { 270 | switch (type) { 271 | case PB_Tdouble: return PB_T64BIT; 272 | case PB_Tfloat: return PB_T32BIT; 273 | case PB_Tint64: return PB_TVARINT; 274 | case PB_Tuint64: return PB_TVARINT; 275 | case PB_Tint32: return PB_TVARINT; 276 | case PB_Tfixed64: return PB_T64BIT; 277 | case PB_Tfixed32: return PB_T32BIT; 278 | case PB_Tbool: return PB_TVARINT; 279 | case PB_Tstring: return PB_TBYTES; 280 | case PB_Tmessage: return PB_TBYTES; 281 | case PB_Tbytes: return PB_TBYTES; 282 | case PB_Tuint32: return PB_TVARINT; 283 | case PB_Tenum: return PB_TVARINT; 284 | case PB_Tsfixed32: return PB_T32BIT; 285 | case PB_Tsfixed64: return PB_T64BIT; 286 | case PB_Tsint32: return PB_TVARINT; 287 | case PB_Tsint64: return PB_TVARINT; 288 | default: return PB_TWIRECOUNT; 289 | } 290 | } 291 | 292 | PB_API const char *pb_wtypename(int wiretype, const char *def) { 293 | switch (wiretype) { 294 | #define X(id, name, v) case v: return name; 295 | PB_WIRETYPES(X) 296 | #undef X 297 | default: return def ? def : ""; 298 | } 299 | } 300 | 301 | PB_API const char *pb_typename(int type, const char *def) { 302 | switch (type) { 303 | #define X(name, t, v) case v: return #name; 304 | PB_TYPES(X) 305 | #undef X 306 | default: return def ? def : ""; 307 | } 308 | } 309 | 310 | PB_API int pb_typebyname(const char *name, int def) { 311 | static struct entry { const char *name; int value; } names[] = { 312 | #define X(name, t, v) { #name, v }, 313 | PB_TYPES(X) 314 | #undef X 315 | { 316 | NULL, 0 317 | } 318 | }; 319 | struct entry *p; 320 | for (p = names; p->name != NULL; ++p) 321 | if (strcmp(p->name, name) == 0) 322 | return p->value; 323 | return def; 324 | } 325 | 326 | PB_API int pb_wtypebyname(const char *name, int def) { 327 | static struct entry { const char *name; int value; } names[] = { 328 | #define X(id, name, v) { name, v }, 329 | PB_WIRETYPES(X) 330 | #undef X 331 | { 332 | NULL, 0 333 | } 334 | }; 335 | struct entry *p; 336 | for (p = names; p->name != NULL; ++p) 337 | if (strcmp(p->name, name) == 0) 338 | return p->value; 339 | return def; 340 | } 341 | 342 | 343 | /* encode */ 344 | 345 | PB_API pb_Slice pb_result(pb_Buffer *b) 346 | { 347 | pb_Slice slice = pb_lslice(b->buff, b->size); return slice; 348 | } 349 | 350 | PB_API void pb_initbuffer(pb_Buffer *b) 351 | { 352 | b->buff = b->init_buff, b->capacity = PB_BUFFERSIZE, b->size = 0; 353 | } 354 | 355 | PB_API void pb_resetbuffer(pb_Buffer *b) 356 | { 357 | if (b->buff != b->init_buff) free(b->buff); pb_initbuffer(b); 358 | } 359 | 360 | static int pb_write32(char *buff, uint32_t n) { 361 | int p, c = 0; 362 | do { 363 | p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c; 364 | p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c; 365 | p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c; 366 | p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c; 367 | p = n; 368 | } while (0); 369 | return *buff++ = p, ++c; 370 | } 371 | 372 | static int pb_write64(char *buff, uint64_t n) { 373 | int p, c = 0; 374 | do { 375 | p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c; 376 | p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c; 377 | p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c; 378 | p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c; 379 | p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c; 380 | p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c; 381 | p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c; 382 | p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c; 383 | p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c; 384 | p = n & 0x7F; 385 | } while (0); 386 | return *buff++ = p, ++c; 387 | } 388 | 389 | PB_API size_t pb_resizebuffer(pb_Buffer *b, size_t len) { 390 | size_t newsize = PB_BUFFERSIZE; 391 | while (newsize < PB_MAX_SIZET / 2 && newsize < len) 392 | newsize += newsize >> 1; 393 | if (newsize > b->size) { 394 | char *buff = b->buff == b->init_buff ? NULL : b->buff; 395 | char *newbuff = (char*)realloc(buff, newsize); 396 | if (newbuff == NULL) return 0; 397 | if (b->buff == b->init_buff) memcpy(newbuff, b->buff, b->size); 398 | b->buff = newbuff; 399 | b->capacity = newsize; 400 | } 401 | return b->capacity; 402 | } 403 | 404 | PB_API void* pb_prepbuffsize(pb_Buffer *b, size_t len) { 405 | if (b->size + len > b->capacity) { 406 | size_t oldsize = b->size; 407 | if (pb_resizebuffer(b, oldsize + len) == 0) 408 | return NULL; 409 | } 410 | return &b->buff[b->size]; 411 | } 412 | 413 | PB_API size_t pb_addslice(pb_Buffer *b, pb_Slice s) { 414 | size_t len = pb_len(s); 415 | void *buff = pb_prepbuffsize(b, len); 416 | if (buff == NULL) return 0; 417 | memcpy(buff, s.p, len); 418 | pb_addsize(b, len); 419 | return len; 420 | } 421 | 422 | PB_API size_t pb_addlength(pb_Buffer *b, size_t len) { 423 | char buff[10], *s; 424 | size_t bl, ml; 425 | if ((bl = pb_bufflen(b)) < len) 426 | return 0; 427 | ml = pb_write64(buff, bl - len); 428 | if (pb_prepbuffsize(b, ml) == 0) return 0; 429 | s = b->buff + len; 430 | memmove(s + ml, s, bl - len); 431 | memcpy(s, buff, ml); 432 | pb_addsize(b, ml); 433 | return ml; 434 | } 435 | 436 | PB_API size_t pb_addbytes(pb_Buffer *b, pb_Slice s) { 437 | size_t ret, len = pb_len(s); 438 | if (pb_prepbuffsize(b, len + 5) == NULL) return 0; 439 | ret = pb_addvarint32(b, (uint32_t)len); 440 | return ret + pb_addslice(b, s); 441 | } 442 | 443 | PB_API size_t pb_addvarint32(pb_Buffer *b, uint32_t n) { 444 | char *buff = (char*)pb_prepbuffsize(b, 5); 445 | size_t l; 446 | if (buff == NULL) return 0; 447 | pb_addsize(b, l = pb_write32(buff, n)); 448 | return l; 449 | } 450 | 451 | PB_API size_t pb_addvarint64(pb_Buffer *b, uint64_t n) { 452 | char *buff = (char*)pb_prepbuffsize(b, 10); 453 | size_t l; 454 | if (buff == NULL) return 0; 455 | pb_addsize(b, l = pb_write64(buff, n)); 456 | return l; 457 | } 458 | 459 | PB_API size_t pb_addfixed32(pb_Buffer *b, uint32_t n) { 460 | char *ch = (char*)pb_prepbuffsize(b, 4); 461 | if (ch == NULL) return 0; 462 | *ch++ = n & 0xFF; n >>= 8; 463 | *ch++ = n & 0xFF; n >>= 8; 464 | *ch++ = n & 0xFF; n >>= 8; 465 | *ch = n & 0xFF; 466 | pb_addsize(b, 4); 467 | return 4; 468 | } 469 | 470 | PB_API size_t pb_addfixed64(pb_Buffer *b, uint64_t n) { 471 | char *ch = (char*)pb_prepbuffsize(b, 8); 472 | if (ch == NULL) return 0; 473 | *ch++ = n & 0xFF; n >>= 8; 474 | *ch++ = n & 0xFF; n >>= 8; 475 | *ch++ = n & 0xFF; n >>= 8; 476 | *ch++ = n & 0xFF; n >>= 8; 477 | *ch++ = n & 0xFF; n >>= 8; 478 | *ch++ = n & 0xFF; n >>= 8; 479 | *ch++ = n & 0xFF; n >>= 8; 480 | *ch = n & 0xFF; 481 | pb_addsize(b, 8); 482 | return 8; 483 | } 484 | 485 | 486 | /* memory pool */ 487 | 488 | PB_API void pb_initpool(pb_Pool *pool, size_t obj_size) { 489 | memset(pool, 0, sizeof(pb_Pool)); 490 | pool->obj_size = obj_size; 491 | assert(obj_size > sizeof(void*) && obj_size < PB_POOLSIZE / 4); 492 | } 493 | 494 | PB_API void pb_freepool(pb_Pool *pool) { 495 | void *page = pool->pages; 496 | while (page) { 497 | void *next = *(void**)((char*)page + PB_POOLSIZE - sizeof(void*)); 498 | free(page); 499 | page = next; 500 | } 501 | pb_initpool(pool, pool->obj_size); 502 | } 503 | 504 | PB_API void *pb_poolalloc(pb_Pool *pool) { 505 | void *obj = pool->freed; 506 | if (obj == NULL) { 507 | size_t objsize = pool->obj_size, offset; 508 | void *newpage = malloc(PB_POOLSIZE); 509 | if (newpage == NULL) return NULL; 510 | offset = ((PB_POOLSIZE - sizeof(void*)) / objsize - 1) * objsize; 511 | for (; offset > 0; offset -= objsize) { 512 | void **entry = (void**)((char*)newpage + offset); 513 | *entry = pool->freed, pool->freed = (void*)entry; 514 | } 515 | *(void**)((char*)newpage + PB_POOLSIZE - sizeof(void*)) = pool->pages; 516 | pool->pages = newpage; 517 | return newpage; 518 | } 519 | pool->freed = *(void**)obj; 520 | return obj; 521 | } 522 | 523 | PB_API void pb_poolfree(pb_Pool *pool, void *obj) 524 | { 525 | *(void**)obj = pool->freed, pool->freed = obj; 526 | } 527 | 528 | 529 | /* hash table */ 530 | 531 | #define pbT_offset(a, b) ((char*)(a) - (char*)(b)) 532 | #define pbT_index(a, b) ((pb_Entry*)((char*)(a) + (b))) 533 | 534 | PB_API void pb_inittable(pb_Table *t, size_t entrysize) 535 | { 536 | memset(t, 0, sizeof(pb_Table)), t->entry_size = (unsigned)entrysize; 537 | } 538 | 539 | PB_API void pb_freetable(pb_Table *t) 540 | { 541 | free(t->hash); pb_inittable(t, t->entry_size); 542 | } 543 | 544 | static pb_Entry *pbT_hash(pb_Table *t, pb_Key key) { 545 | size_t h = ((size_t)key * 2654435761U)&(t->size - 1); 546 | if (key && h == 0) h = 1; 547 | return pbT_index(t->hash, h*t->entry_size); 548 | } 549 | 550 | static pb_Entry *pbT_newkey(pb_Table *t, pb_Key key) { 551 | pb_Entry *mp, *othern, *next, *f = NULL; 552 | if (t->size == 0 && pb_resizetable(t, t->size * 2) == 0) return NULL; 553 | if (key == 0) { 554 | mp = t->hash; 555 | t->has_zero = 1; 556 | } 557 | else if ((mp = pbT_hash(t, key))->key != 0) { 558 | while (t->lastfree > t->entry_size) { 559 | pb_Entry *cur = pbT_index(t->hash, t->lastfree -= t->entry_size); 560 | if (cur->key == 0 && cur->next == 0) { f = cur; break; } 561 | } 562 | if (f == NULL) return pb_resizetable(t, t->size * 2) ? 563 | pbT_newkey(t, key) : NULL; 564 | if ((othern = pbT_hash(t, mp->key)) != mp) { 565 | while ((next = pbT_index(othern, othern->next)) != mp) 566 | othern = next; 567 | othern->next = pbT_offset(f, othern); 568 | memcpy(f, mp, t->entry_size); 569 | if (mp->next != 0) f->next += pbT_offset(mp, f), mp->next = 0; 570 | } 571 | else { 572 | if (mp->next != 0) f->next = pbT_offset(mp, f) + mp->next; 573 | else assert(f->next == 0); 574 | mp->next = pbT_offset(f, mp); 575 | mp = f; 576 | } 577 | } 578 | mp->key = key; 579 | if (t->entry_size != sizeof(pb_Entry)) 580 | memset(mp + 1, 0, t->entry_size - sizeof(pb_Entry)); 581 | return mp; 582 | } 583 | 584 | PB_API size_t pb_resizetable(pb_Table *t, size_t size) { 585 | pb_Table nt = *t; 586 | size_t i, rawsize = t->size*t->entry_size; 587 | size_t newsize = PB_MIN_HASHTABLE_SIZE; 588 | while (newsize < PB_MAX_SIZET / t->entry_size && newsize < size) 589 | newsize <<= 1; 590 | if (newsize < size) return 0; 591 | nt.size = newsize; 592 | nt.lastfree = nt.entry_size * newsize; 593 | nt.hash = (pb_Entry*)malloc(nt.lastfree); 594 | if (nt.hash == NULL) return 0; 595 | memset(nt.hash, 0, nt.lastfree); 596 | for (i = 0; i < rawsize; i += t->entry_size) { 597 | pb_Entry *olde = (pb_Entry*)((char*)t->hash + i); 598 | pb_Entry *newe = pbT_newkey(&nt, olde->key); 599 | if (nt.entry_size > sizeof(pb_Entry)) 600 | memcpy(newe + 1, olde + 1, nt.entry_size - sizeof(pb_Entry)); 601 | } 602 | free(t->hash); 603 | *t = nt; 604 | return newsize; 605 | } 606 | 607 | PB_API pb_Entry *pb_gettable(pb_Table *t, pb_Key key) { 608 | pb_Entry *entry; 609 | if (t == NULL || t->size == 0) 610 | return NULL; 611 | if (key == 0) 612 | return t->has_zero ? t->hash : NULL; 613 | for (entry = pbT_hash(t, key); 614 | entry->key != key; 615 | entry = pbT_index(entry, entry->next)) 616 | if (entry->next == 0) return NULL; 617 | return entry; 618 | } 619 | 620 | PB_API pb_Entry *pb_settable(pb_Table *t, pb_Key key) { 621 | pb_Entry *entry; 622 | if ((entry = pb_gettable(t, key)) != NULL) 623 | return entry; 624 | return pbT_newkey(t, key); 625 | } 626 | 627 | PB_API int pb_nextentry(pb_Table *t, pb_Entry **pentry) { 628 | size_t i = *pentry ? pbT_offset(*pentry, t->hash) : 0; 629 | size_t size = t->size*t->entry_size; 630 | if (*pentry == NULL && t->has_zero) { 631 | *pentry = t->hash; 632 | return 1; 633 | } 634 | while (i += t->entry_size, i < size) { 635 | pb_Entry *entry = pbT_index(t->hash, i); 636 | if (entry->key != 0) { 637 | *pentry = entry; 638 | return 1; 639 | } 640 | } 641 | *pentry = NULL; 642 | return 0; 643 | } 644 | 645 | 646 | /* name table */ 647 | 648 | static void pbN_init(pb_State *S) 649 | { 650 | memset(&S->nametable, 0, sizeof(pb_NameTable)); 651 | } 652 | 653 | static void pbN_free(pb_State *S) { 654 | pb_NameTable *nt = &S->nametable; 655 | size_t i; 656 | for (i = 0; i < nt->size; ++i) { 657 | pb_NameEntry *ne = nt->hash[i]; 658 | while (ne != NULL) { 659 | pb_NameEntry *next = ne->next; 660 | free(ne); 661 | ne = next; 662 | } 663 | } 664 | free(nt->hash); 665 | pbN_init(S); 666 | } 667 | 668 | static unsigned pbN_calchash(const char *s, size_t len) { 669 | unsigned h = (unsigned)len; 670 | size_t step = (len >> PB_HASHLIMIT) + 1; 671 | for (; len >= step; len -= step) 672 | h ^= ((h << 5) + (h >> 2) + (unsigned char)(s[len - 1])); 673 | return h; 674 | } 675 | 676 | static size_t pbN_resize(pb_State *S, size_t size) { 677 | pb_NameTable *nt = &S->nametable; 678 | pb_NameEntry **hash; 679 | size_t i, newsize = PB_MIN_STRTABLE_SIZE; 680 | while (newsize < PB_MAX_SIZET / sizeof(pb_NameEntry*) && newsize < size) 681 | newsize <<= 1; 682 | if (newsize < size) return 0; 683 | hash = (pb_NameEntry**)malloc(newsize * sizeof(pb_NameEntry*)); 684 | if (hash == NULL) return 0; 685 | memset(hash, 0, newsize * sizeof(pb_NameEntry*)); 686 | for (i = 0; i < nt->size; ++i) { 687 | pb_NameEntry *entry = nt->hash[i]; 688 | while (entry != NULL) { 689 | pb_NameEntry *next = entry->next; 690 | pb_NameEntry **newh = &hash[entry->hash & (newsize - 1)]; 691 | entry->next = *newh, *newh = entry; 692 | entry = next; 693 | } 694 | } 695 | free(nt->hash); 696 | nt->hash = hash; 697 | nt->size = newsize; 698 | return newsize; 699 | } 700 | 701 | static pb_NameEntry *pbN_newname(pb_State *S, const char *name, size_t len, unsigned hash) { 702 | pb_NameTable *nt = &S->nametable; 703 | pb_NameEntry **list, *newobj; 704 | if (nt->count >= nt->size && !pbN_resize(S, nt->size * 2)) return NULL; 705 | list = &nt->hash[hash & (nt->size - 1)]; 706 | newobj = (pb_NameEntry*)malloc(sizeof(pb_NameEntry) + len + 1); 707 | if (newobj == NULL) return NULL; 708 | newobj->next = *list; 709 | newobj->length = (unsigned)len; 710 | newobj->refcount = 1; 711 | newobj->hash = hash; 712 | memcpy(newobj + 1, name, len); 713 | ((char*)(newobj + 1))[len] = '\0'; 714 | *list = newobj; 715 | ++nt->count; 716 | return newobj; 717 | } 718 | 719 | static void pbN_delname(pb_State *S, pb_NameEntry *name) { 720 | pb_NameTable *nt = &S->nametable; 721 | pb_NameEntry **list = &nt->hash[name->hash & (nt->size - 1)]; 722 | while (*list != NULL) { 723 | if (*list != name) 724 | list = &(*list)->next; 725 | else { 726 | *list = (*list)->next; 727 | free(name); 728 | --nt->count; 729 | break; 730 | } 731 | } 732 | } 733 | 734 | static pb_NameEntry *pbN_getname(pb_State *S, const char *name, size_t len, unsigned hash) { 735 | pb_NameTable *nt = &S->nametable; 736 | if (nt->hash) { 737 | pb_NameEntry *entry = nt->hash[hash & (nt->size - 1)]; 738 | for (; entry != NULL; entry = entry->next) 739 | if (entry->hash == hash && entry->length == len 740 | && memcmp(name, entry + 1, len) == 0) 741 | return entry; 742 | } 743 | return NULL; 744 | } 745 | 746 | PB_API pb_Name *pb_newname(pb_State *S, pb_Slice s) { 747 | if (s.p != NULL) { 748 | size_t size = pb_len(s); 749 | const char *name = s.p; 750 | unsigned hash = pbN_calchash(name, size); 751 | pb_NameEntry *entry = pbN_getname(S, name, size, hash); 752 | if (entry) return pb_usename((pb_Name*)(entry + 1)); 753 | entry = pbN_newname(S, name, size, hash); 754 | return entry ? (pb_Name*)(entry + 1) : NULL; 755 | } 756 | return NULL; 757 | } 758 | 759 | PB_API pb_Name *pb_usename(pb_Name *name) { 760 | if (name != NULL) 761 | ++((pb_NameEntry*)name - 1)->refcount; 762 | return name; 763 | } 764 | 765 | PB_API void pb_delname(pb_State *S, pb_Name *name) { 766 | if (name != NULL) { 767 | pb_NameEntry *ne = (pb_NameEntry*)name - 1; 768 | if (ne->refcount <= 1) 769 | { 770 | pbN_delname(S, ne); return; 771 | } 772 | --ne->refcount; 773 | } 774 | } 775 | 776 | PB_API pb_Name *pb_name(pb_State *S, const char *name) { 777 | if (name != NULL) { 778 | size_t size = strlen(name); 779 | unsigned hash = pbN_calchash(name, size); 780 | pb_NameEntry *entry = pbN_getname(S, name, size, hash); 781 | return entry ? (pb_Name*)(entry + 1) : NULL; 782 | } 783 | return NULL; 784 | } 785 | 786 | 787 | /* state */ 788 | 789 | typedef struct pb_TypeEntry { pb_Entry entry; pb_Type *value; } pb_TypeEntry; 790 | typedef struct pb_FieldEntry { pb_Entry entry; pb_Field *value; } pb_FieldEntry; 791 | 792 | typedef struct pb_OneofEntry { 793 | pb_Entry entry; 794 | pb_Name *name; 795 | unsigned index; 796 | } pb_OneofEntry; 797 | 798 | PB_API void pb_init(pb_State *S) { 799 | memset(S, 0, sizeof(pb_State)); 800 | S->types.entry_size = sizeof(pb_TypeEntry); 801 | pb_initpool(&S->typepool, sizeof(pb_Type)); 802 | pb_initpool(&S->fieldpool, sizeof(pb_Field)); 803 | } 804 | 805 | PB_API void pb_free(pb_State *S) { 806 | if (S != NULL) { 807 | pb_TypeEntry *te = NULL; 808 | while (pb_nextentry(&S->types, (pb_Entry**)&te)) 809 | if (te->value != NULL) pb_deltype(S, te->value); 810 | pb_freetable(&S->types); 811 | pb_freepool(&S->typepool); 812 | pb_freepool(&S->fieldpool); 813 | pbN_free(S); 814 | } 815 | } 816 | 817 | PB_API pb_Type *pb_type(pb_State *S, pb_Name *tname) { 818 | pb_TypeEntry *te = NULL; 819 | if (S != NULL && tname != NULL) 820 | te = (pb_TypeEntry*)pb_gettable(&S->types, (pb_Key)tname); 821 | return te && !te->value->is_dead ? te->value : NULL; 822 | } 823 | 824 | PB_API pb_Field *pb_fname(pb_Type *t, pb_Name *name) { 825 | pb_FieldEntry *fe = NULL; 826 | if (t != NULL && name != NULL) 827 | fe = (pb_FieldEntry*)pb_gettable(&t->field_names, (pb_Key)name); 828 | return fe ? fe->value : NULL; 829 | } 830 | 831 | PB_API pb_Field *pb_field(pb_Type *t, int32_t number) { 832 | pb_FieldEntry *fe = NULL; 833 | if (t != NULL) fe = (pb_FieldEntry*)pb_gettable(&t->field_tags, number); 834 | return fe ? fe->value : NULL; 835 | } 836 | 837 | PB_API pb_Name *pb_oneofname(pb_Type *t, int idx) { 838 | pb_OneofEntry *oe = NULL; 839 | if (t != NULL) oe = (pb_OneofEntry*)pb_gettable(&t->oneof_index, idx); 840 | return oe ? oe->name : NULL; 841 | } 842 | 843 | PB_API int pb_nexttype(pb_State *S, pb_Type **ptype) { 844 | pb_TypeEntry *e = NULL; 845 | if (S != NULL) { 846 | if (*ptype != NULL) 847 | e = (pb_TypeEntry*)pb_gettable(&S->types, (pb_Key)(*ptype)->name); 848 | while (pb_nextentry(&S->types, (pb_Entry**)&e)) 849 | if ((*ptype = e->value) != NULL && !(*ptype)->is_dead) 850 | return 1; 851 | } 852 | *ptype = NULL; 853 | return 0; 854 | } 855 | 856 | PB_API int pb_nextfield(pb_Type *t, pb_Field **pfield) { 857 | pb_FieldEntry *e = NULL; 858 | if (t != NULL) { 859 | if (*pfield != NULL) 860 | e = (pb_FieldEntry*)pb_gettable(&t->field_tags, (*pfield)->number); 861 | while (pb_nextentry(&t->field_tags, (pb_Entry**)&e)) 862 | if ((*pfield = e->value) != NULL) 863 | return 1; 864 | } 865 | *pfield = NULL; 866 | return 0; 867 | } 868 | 869 | 870 | /* new type/field */ 871 | 872 | static const char *pbT_basename(const char *tname) { 873 | const char *end = tname + strlen(tname); 874 | while (tname < end && *--end != '.') 875 | ; 876 | return *end != '.' ? end : end + 1; 877 | } 878 | 879 | static void pbT_inittype(pb_Type *t) { 880 | memset(t, 0, sizeof(pb_Type)); 881 | pb_inittable(&t->field_names, sizeof(pb_FieldEntry)); 882 | pb_inittable(&t->field_tags, sizeof(pb_FieldEntry)); 883 | pb_inittable(&t->oneof_index, sizeof(pb_OneofEntry)); 884 | } 885 | 886 | static void pbT_freefield(pb_State *S, pb_Field *f) { 887 | pb_delname(S, f->default_value); 888 | pb_delname(S, f->name); 889 | pb_poolfree(&S->fieldpool, f); 890 | } 891 | 892 | PB_API pb_Type *pb_newtype(pb_State *S, pb_Name *tname) { 893 | if (tname != NULL) { 894 | pb_TypeEntry *te = (pb_TypeEntry*)pb_settable( 895 | &S->types, (pb_Key)tname); 896 | pb_Type *t; 897 | if (te == NULL) return NULL; 898 | if ((t = te->value) != NULL) { 899 | t->is_dead = 0; 900 | return t; 901 | } 902 | if (!(t = (pb_Type*)pb_poolalloc(&S->typepool))) return NULL; 903 | pbT_inittype(t); 904 | t->name = tname; 905 | t->basename = pbT_basename((const char*)tname); 906 | return te->value = t; 907 | } 908 | return NULL; 909 | } 910 | 911 | PB_API void pb_deltype(pb_State *S, pb_Type *t) { 912 | if (S && t) { 913 | pb_FieldEntry *nf = NULL; 914 | pb_OneofEntry *ne = NULL; 915 | while (pb_nextentry(&t->field_names, (pb_Entry**)&nf)) { 916 | if (nf->value != NULL) { 917 | pb_FieldEntry *of = (pb_FieldEntry*)pb_gettable( 918 | &t->field_tags, nf->value->number); 919 | if (of && of->value == nf->value) 920 | of->entry.key = 0, of->value = NULL; 921 | pbT_freefield(S, nf->value); 922 | } 923 | } 924 | while (pb_nextentry(&t->field_tags, (pb_Entry**)&nf)) 925 | if (nf->value != NULL) pbT_freefield(S, nf->value); 926 | while (pb_nextentry(&t->oneof_index, (pb_Entry**)&ne)) 927 | pb_delname(S, ne->name); 928 | pb_freetable(&t->field_tags); 929 | pb_freetable(&t->field_names); 930 | pb_freetable(&t->oneof_index); 931 | t->field_count = 0; 932 | t->is_dead = 1; 933 | /*pb_delname(S, t->name); */ 934 | /*pb_poolfree(&S->typepool, t); */ 935 | } 936 | } 937 | 938 | PB_API pb_Field *pb_newfield(pb_State *S, pb_Type *t, pb_Name *fname, int32_t number) { 939 | if (fname != NULL) { 940 | pb_FieldEntry *nf = (pb_FieldEntry*)pb_settable( 941 | &t->field_names, (pb_Key)fname); 942 | pb_FieldEntry *tf = (pb_FieldEntry*)pb_settable( 943 | &t->field_tags, number); 944 | pb_Field *f; 945 | if (nf == NULL || tf == NULL) return NULL; 946 | if ((f = nf->value) != NULL && tf->value == f) { 947 | pb_delname(S, f->default_value); 948 | f->default_value = NULL; 949 | return f; 950 | } 951 | if (!(f = (pb_Field*)pb_poolalloc(&S->fieldpool))) return NULL; 952 | memset(f, 0, sizeof(pb_Field)); 953 | f->name = fname; 954 | f->type = t; 955 | f->number = number; 956 | if (nf->value && pb_field(t, nf->value->number) != nf->value) 957 | pbT_freefield(S, nf->value), --t->field_count; 958 | if (tf->value && pb_fname(t, tf->value->name) != tf->value) 959 | pbT_freefield(S, tf->value), --t->field_count; 960 | ++t->field_count; 961 | return nf->value = tf->value = f; 962 | } 963 | return NULL; 964 | } 965 | 966 | PB_API void pb_delfield(pb_State *S, pb_Type *t, pb_Field *f) { 967 | if (S && t && f) { 968 | pb_FieldEntry *nf = (pb_FieldEntry*)pb_gettable(&t->field_names, 969 | (pb_Key)f->name); 970 | pb_FieldEntry *tf = (pb_FieldEntry*)pb_gettable(&t->field_tags, 971 | (pb_Key)f->number); 972 | int count = 0; 973 | if (nf && nf->value == f) nf->entry.key = 0, nf->value = NULL, ++count; 974 | if (tf && tf->value == f) tf->entry.key = 0, tf->value = NULL, ++count; 975 | if (count) pbT_freefield(S, f), --t->field_count; 976 | } 977 | } 978 | 979 | 980 | /* .pb proto loader */ 981 | 982 | #include 983 | 984 | typedef struct pb_Loader pb_Loader; 985 | typedef struct pbL_FieldInfo pbL_FieldInfo; 986 | typedef struct pbL_EnumValueInfo pbL_EnumValueInfo; 987 | typedef struct pbL_EnumInfo pbL_EnumInfo; 988 | typedef struct pbL_TypeInfo pbL_TypeInfo; 989 | typedef struct pbL_FileInfo pbL_FileInfo; 990 | 991 | #define pbL_rawh(A) ((size_t*)(A) - 2) 992 | #define pbL_size(A) ((A) ? pbL_rawh(A)[0] : 0) 993 | #define pbL_count(A) ((A) ? pbL_rawh(A)[1] : 0) 994 | #define pbL_add(A) (pbL_grow(L, (void**)&(A), sizeof(*(A))), &(A)[pbL_rawh(A)[1]++]) 995 | #define pbL_delete(A) ((A) ? (void)free(pbL_rawh(A)) : (void)0) 996 | 997 | struct pb_Loader { 998 | jmp_buf jbuf; 999 | pb_Slice s; 1000 | pb_Buffer b; 1001 | int is_proto3; 1002 | }; 1003 | 1004 | /* parsers */ 1005 | 1006 | struct pbL_EnumValueInfo { 1007 | pb_Slice name; 1008 | int32_t number; 1009 | }; 1010 | 1011 | struct pbL_EnumInfo { 1012 | pb_Slice name; 1013 | pbL_EnumValueInfo *value; 1014 | }; 1015 | 1016 | struct pbL_FieldInfo { 1017 | pb_Slice name; 1018 | pb_Slice type_name; 1019 | pb_Slice extendee; 1020 | pb_Slice default_value; 1021 | int32_t number; 1022 | int32_t label; 1023 | int32_t type; 1024 | int32_t oneof_index; 1025 | int32_t packed; 1026 | }; 1027 | 1028 | struct pbL_TypeInfo { 1029 | pb_Slice name; 1030 | int32_t is_map; 1031 | pbL_FieldInfo *field; 1032 | pbL_FieldInfo *extension; 1033 | pbL_EnumInfo *enum_type; 1034 | pbL_TypeInfo *nested_type; 1035 | pb_Slice *oneof_decl; 1036 | }; 1037 | 1038 | struct pbL_FileInfo { 1039 | pb_Slice package; 1040 | pb_Slice syntax; 1041 | pbL_EnumInfo *enum_type; 1042 | pbL_TypeInfo *message_type; 1043 | pbL_FieldInfo *extension; 1044 | }; 1045 | 1046 | static void pbL_readbytes(pb_Loader *L, pb_Slice *pv) 1047 | { 1048 | if (pb_readbytes(&L->s, pv) == 0) longjmp(L->jbuf, 1); 1049 | } 1050 | 1051 | static void pbL_beginmsg(pb_Loader *L, pb_Slice *pv) 1052 | { 1053 | pb_Slice v; pbL_readbytes(L, &v); *pv = L->s, L->s = v; 1054 | } 1055 | 1056 | static void pbL_endmsg(pb_Loader *L, pb_Slice *pv) 1057 | { 1058 | L->s = *pv; 1059 | } 1060 | 1061 | static void pbL_readint32(pb_Loader *L, int32_t *pv) { 1062 | uint32_t v; 1063 | if (pb_readvarint32(&L->s, &v) == 0) 1064 | longjmp(L->jbuf, 1); 1065 | *pv = (int32_t)v; 1066 | } 1067 | 1068 | static void pbL_grow(pb_Loader *L, void **pp, size_t obj_size) { 1069 | enum { SIZE, COUNT, FIELDS }; 1070 | size_t *h = *pp ? pbL_rawh(*pp) : NULL; 1071 | if (h == NULL || h[SIZE] <= h[COUNT]) { 1072 | size_t used = (h ? h[COUNT] : 0); 1073 | size_t size = (h ? h[SIZE] : 2), newsize = size + (size >> 1); 1074 | size_t *nh = (size_t*)realloc(h, sizeof(size_t)*FIELDS + newsize * obj_size); 1075 | if (nh == NULL || newsize < size) longjmp(L->jbuf, PB_ENOMEM); 1076 | nh[SIZE] = newsize; 1077 | nh[COUNT] = used; 1078 | *pp = nh + FIELDS; 1079 | memset((char*)*pp + used * obj_size, 0, (newsize - used)*obj_size); 1080 | } 1081 | } 1082 | 1083 | static void pbL_FieldOptions(pb_Loader *L, pbL_FieldInfo *info) { 1084 | pb_Slice s; 1085 | uint32_t tag; 1086 | pbL_beginmsg(L, &s); 1087 | while (pb_readvarint32(&L->s, &tag)) { 1088 | switch (tag) { 1089 | case pb_pair(2, PB_TVARINT): /* bool packed */ 1090 | pbL_readint32(L, &info->packed); break; 1091 | default: pb_skipvalue(&L->s, tag); 1092 | } 1093 | } 1094 | pbL_endmsg(L, &s); 1095 | } 1096 | 1097 | static void pbL_FieldDescriptorProto(pb_Loader *L, pbL_FieldInfo *info) { 1098 | pb_Slice s; 1099 | uint32_t tag; 1100 | pbL_beginmsg(L, &s); 1101 | info->packed = -1; 1102 | while (pb_readvarint32(&L->s, &tag)) { 1103 | switch (tag) { 1104 | case pb_pair(1, PB_TBYTES): /* string name */ 1105 | pbL_readbytes(L, &info->name); break; 1106 | case pb_pair(3, PB_TVARINT): /* int32 number */ 1107 | pbL_readint32(L, &info->number); break; 1108 | case pb_pair(4, PB_TVARINT): /* Label label */ 1109 | pbL_readint32(L, &info->label); break; 1110 | case pb_pair(5, PB_TVARINT): /* Type type */ 1111 | pbL_readint32(L, &info->type); break; 1112 | case pb_pair(6, PB_TBYTES): /* string type_name */ 1113 | pbL_readbytes(L, &info->type_name); break; 1114 | case pb_pair(2, PB_TBYTES): /* string extendee */ 1115 | pbL_readbytes(L, &info->extendee); break; 1116 | case pb_pair(7, PB_TBYTES): /* string default_value */ 1117 | pbL_readbytes(L, &info->default_value); break; 1118 | case pb_pair(8, PB_TBYTES): /* FieldOptions options */ 1119 | pbL_FieldOptions(L, info); break; 1120 | case pb_pair(9, PB_TVARINT): /* int32 oneof_index */ 1121 | pbL_readint32(L, &info->oneof_index); 1122 | ++info->oneof_index; break; 1123 | default: pb_skipvalue(&L->s, tag); 1124 | } 1125 | } 1126 | pbL_endmsg(L, &s); 1127 | } 1128 | 1129 | static void pbL_EnumValueDescriptorProto(pb_Loader *L, pbL_EnumValueInfo *info) { 1130 | pb_Slice s; 1131 | uint32_t tag; 1132 | pbL_beginmsg(L, &s); 1133 | while (pb_readvarint32(&L->s, &tag)) { 1134 | switch (tag) { 1135 | case pb_pair(1, PB_TBYTES): /* string name */ 1136 | pbL_readbytes(L, &info->name); break; 1137 | case pb_pair(2, PB_TVARINT): /* int32 number */ 1138 | pbL_readint32(L, &info->number); break; 1139 | default: pb_skipvalue(&L->s, tag); 1140 | } 1141 | } 1142 | pbL_endmsg(L, &s); 1143 | } 1144 | 1145 | static void pbL_EnumDescriptorProto(pb_Loader *L, pbL_EnumInfo *info) { 1146 | pb_Slice s; 1147 | uint32_t tag; 1148 | pbL_beginmsg(L, &s); 1149 | while (pb_readvarint32(&L->s, &tag)) { 1150 | switch (tag) { 1151 | case pb_pair(1, PB_TBYTES): /* string name */ 1152 | pbL_readbytes(L, &info->name); break; 1153 | case pb_pair(2, PB_TBYTES): /* EnumValueDescriptorProto value */ 1154 | pbL_EnumValueDescriptorProto(L, pbL_add(info->value)); break; 1155 | default: pb_skipvalue(&L->s, tag); 1156 | } 1157 | } 1158 | pbL_endmsg(L, &s); 1159 | } 1160 | 1161 | static void pbL_MessageOptions(pb_Loader *L, pbL_TypeInfo *info) { 1162 | pb_Slice s; 1163 | uint32_t tag; 1164 | pbL_beginmsg(L, &s); 1165 | while (pb_readvarint32(&L->s, &tag)) { 1166 | switch (tag) { 1167 | case pb_pair(7, PB_TVARINT): /* bool map_entry */ 1168 | pbL_readint32(L, &info->is_map); break; 1169 | default: pb_skipvalue(&L->s, tag); 1170 | } 1171 | } 1172 | pbL_endmsg(L, &s); 1173 | } 1174 | 1175 | static void pbL_OneofDescriptorProto(pb_Loader *L, pbL_TypeInfo *info) { 1176 | pb_Slice s; 1177 | uint32_t tag; 1178 | pbL_beginmsg(L, &s); 1179 | while (pb_readvarint32(&L->s, &tag)) { 1180 | switch (tag) { 1181 | case pb_pair(1, PB_TBYTES): /* string name */ 1182 | pbL_readbytes(L, pbL_add(info->oneof_decl)); break; 1183 | default: pb_skipvalue(&L->s, tag); 1184 | } 1185 | } 1186 | pbL_endmsg(L, &s); 1187 | } 1188 | 1189 | static void pbL_DescriptorProto(pb_Loader *L, pbL_TypeInfo *info) { 1190 | pb_Slice s; 1191 | uint32_t tag; 1192 | pbL_beginmsg(L, &s); 1193 | while (pb_readvarint32(&L->s, &tag)) { 1194 | switch (tag) { 1195 | case pb_pair(1, PB_TBYTES): /* string name */ 1196 | pbL_readbytes(L, &info->name); break; 1197 | case pb_pair(2, PB_TBYTES): /* FieldDescriptorProto field */ 1198 | pbL_FieldDescriptorProto(L, pbL_add(info->field)); break; 1199 | case pb_pair(6, PB_TBYTES): /* FieldDescriptorProto extension */ 1200 | pbL_FieldDescriptorProto(L, pbL_add(info->extension)); break; 1201 | case pb_pair(3, PB_TBYTES): /* DescriptorProto nested_type */ 1202 | pbL_DescriptorProto(L, pbL_add(info->nested_type)); break; 1203 | case pb_pair(4, PB_TBYTES): /* EnumDescriptorProto enum_type */ 1204 | pbL_EnumDescriptorProto(L, pbL_add(info->enum_type)); break; 1205 | case pb_pair(8, PB_TBYTES): /* OneofDescriptorProto oneof_decl */ 1206 | pbL_OneofDescriptorProto(L, info); break; 1207 | case pb_pair(7, PB_TBYTES): /* MessageOptions options */ 1208 | pbL_MessageOptions(L, info); break; 1209 | default: pb_skipvalue(&L->s, tag); 1210 | } 1211 | } 1212 | pbL_endmsg(L, &s); 1213 | } 1214 | 1215 | static void pbL_FileDescriptorProto(pb_Loader *L, pbL_FileInfo *info) { 1216 | pb_Slice s; 1217 | uint32_t tag; 1218 | pbL_beginmsg(L, &s); 1219 | while (pb_readvarint32(&L->s, &tag)) { 1220 | switch (tag) { 1221 | case pb_pair(2, PB_TBYTES): /* string package */ 1222 | pbL_readbytes(L, &info->package); break; 1223 | case pb_pair(4, PB_TBYTES): /* DescriptorProto message_type */ 1224 | pbL_DescriptorProto(L, pbL_add(info->message_type)); break; 1225 | case pb_pair(5, PB_TBYTES): /* EnumDescriptorProto enum_type */ 1226 | pbL_EnumDescriptorProto(L, pbL_add(info->enum_type)); break; 1227 | case pb_pair(7, PB_TBYTES): /* FieldDescriptorProto extension */ 1228 | pbL_FieldDescriptorProto(L, pbL_add(info->extension)); break; 1229 | case pb_pair(12, PB_TBYTES): /* string syntax */ 1230 | pbL_readbytes(L, &info->syntax); break; 1231 | default: pb_skipvalue(&L->s, tag); 1232 | } 1233 | } 1234 | pbL_endmsg(L, &s); 1235 | } 1236 | 1237 | static void pbL_FileDescriptorSet(pb_Loader *L, pbL_FileInfo **pinfo) { 1238 | uint32_t tag; 1239 | while (pb_readvarint32(&L->s, &tag)) { 1240 | switch (tag) { 1241 | case pb_pair(1, PB_TBYTES): /* FileDescriptorProto file */ 1242 | pbL_FileDescriptorProto(L, pbL_add(pinfo[0])); break; 1243 | default: pb_skipvalue(&L->s, tag); 1244 | } 1245 | } 1246 | } 1247 | 1248 | /* loader */ 1249 | 1250 | static void pbL_delTypeInfo(pbL_TypeInfo *info) { 1251 | size_t i, count; 1252 | for (i = 0, count = pbL_count(info->nested_type); i < count; ++i) 1253 | pbL_delTypeInfo(&info->nested_type[i]); 1254 | for (i = 0, count = pbL_count(info->enum_type); i < count; ++i) 1255 | pbL_delete(info->enum_type[i].value); 1256 | pbL_delete(info->nested_type); 1257 | pbL_delete(info->enum_type); 1258 | pbL_delete(info->field); 1259 | pbL_delete(info->extension); 1260 | } 1261 | 1262 | static void pbL_delFileInfo(pbL_FileInfo *files) { 1263 | size_t i, count, j, jcount; 1264 | for (i = 0, count = pbL_count(files); i < count; ++i) { 1265 | for (j = 0, jcount = pbL_count(files[i].message_type); j < jcount; ++j) 1266 | pbL_delTypeInfo(&files[i].message_type[j]); 1267 | for (j = 0, jcount = pbL_count(files[i].enum_type); j < jcount; ++j) 1268 | pbL_delete(files[i].enum_type[j].value); 1269 | pbL_delete(files[i].message_type); 1270 | pbL_delete(files[i].enum_type); 1271 | pbL_delete(files[i].extension); 1272 | } 1273 | pbL_delete(files); 1274 | } 1275 | 1276 | static pb_Slice pbL_prefixname(pb_Buffer *b, pb_Slice s, size_t *ps) { 1277 | *ps = b->size; 1278 | pb_addchar(b, '.'); 1279 | pb_addslice(b, s); 1280 | return pb_result(b); 1281 | } 1282 | 1283 | static void pbL_loadEnum(pb_State *S, pbL_EnumInfo *info, pb_Loader *L) { 1284 | size_t i, count, curr; 1285 | pb_Type *t = pb_newtype(S, pb_newname(S, 1286 | pbL_prefixname(&L->b, info->name, &curr))); 1287 | t->is_enum = 1; 1288 | for (i = 0, count = pbL_count(info->value); i < count; ++i) { 1289 | pbL_EnumValueInfo *ev = &info->value[i]; 1290 | pb_newfield(S, t, pb_newname(S, ev->name), ev->number); 1291 | } 1292 | L->b.size = curr; 1293 | } 1294 | 1295 | static void pbL_loadField(pb_State *S, pbL_FieldInfo *info, pb_Loader *L, pb_Type *t) { 1296 | pb_Type *ft = pb_newtype(S, pb_newname(S, info->type_name)); 1297 | pb_Field *f; 1298 | if (!ft && (info->type == PB_Tmessage || info->type == PB_Tenum)) 1299 | return; 1300 | if (t == NULL && !(t = pb_newtype(S, pb_newname(S, info->extendee)))) 1301 | return; 1302 | if (!(f = pb_newfield(S, t, pb_newname(S, info->name), info->number))) 1303 | return; 1304 | f->default_value = pb_newname(S, info->default_value); 1305 | f->type = ft; 1306 | f->oneof_idx = info->oneof_index; 1307 | f->type_id = info->type; 1308 | f->repeated = info->label == 3; /* repeated */ 1309 | f->packed = info->packed >= 0 ? info->packed : L->is_proto3 && f->repeated; 1310 | if (f->type_id >= 9 && f->type_id <= 12) f->packed = 0; 1311 | f->scalar = (f->type == NULL); 1312 | } 1313 | 1314 | static void pbL_loadType(pb_State *S, pbL_TypeInfo *info, pb_Loader *L) { 1315 | size_t i, count, curr; 1316 | pb_Type *t = pb_newtype(S, pb_newname(S, 1317 | pbL_prefixname(&L->b, info->name, &curr))); 1318 | t->is_map = info->is_map; 1319 | t->is_proto3 = L->is_proto3; 1320 | for (i = 0, count = pbL_count(info->oneof_decl); i < count; ++i) { 1321 | pb_OneofEntry *e = (pb_OneofEntry*)pb_settable(&t->oneof_index, i + 1); 1322 | e->name = pb_newname(S, info->oneof_decl[i]); 1323 | e->index = (int)i + 1; 1324 | } 1325 | for (i = 0, count = pbL_count(info->field); i < count; ++i) 1326 | pbL_loadField(S, &info->field[i], L, t); 1327 | for (i = 0, count = pbL_count(info->extension); i < count; ++i) 1328 | pbL_loadField(S, &info->extension[i], L, NULL); 1329 | for (i = 0, count = pbL_count(info->enum_type); i < count; ++i) 1330 | pbL_loadEnum(S, &info->enum_type[i], L); 1331 | for (i = 0, count = pbL_count(info->nested_type); i < count; ++i) 1332 | pbL_loadType(S, &info->nested_type[i], L); 1333 | L->b.size = curr; 1334 | } 1335 | 1336 | static void pbL_loadFile(pb_State *S, pbL_FileInfo *info, pb_Loader *L) { 1337 | size_t i, count, j, jcount, curr = 0; 1338 | for (i = 0, count = pbL_count(info); i < count; ++i) { 1339 | if (info[i].package.p) pbL_prefixname(&L->b, info[i].package, &curr); 1340 | if (pb_newname(S, info[i].syntax) == pb_newname(S, pb_slice("proto3"))) 1341 | L->is_proto3 = 1; 1342 | for (j = 0, jcount = pbL_count(info[i].enum_type); j < jcount; ++j) 1343 | pbL_loadEnum(S, &info[i].enum_type[j], L); 1344 | for (j = 0, jcount = pbL_count(info[i].message_type); j < jcount; ++j) 1345 | pbL_loadType(S, &info[i].message_type[j], L); 1346 | for (j = 0, jcount = pbL_count(info[i].extension); j < jcount; ++j) 1347 | pbL_loadField(S, &info[i].extension[j], L, NULL); 1348 | L->b.size = curr; 1349 | } 1350 | } 1351 | 1352 | PB_API int pb_load(pb_State *S, pb_Slice *s) { 1353 | volatile int ret = PB_ERROR; 1354 | pbL_FileInfo *files = NULL; 1355 | pb_Loader L; 1356 | if (!setjmp(L.jbuf)) { 1357 | L.s = *s; 1358 | L.is_proto3 = 0; 1359 | pb_initbuffer(&L.b); 1360 | pbL_FileDescriptorSet(&L, &files); 1361 | pbL_loadFile(S, files, &L); 1362 | ret = PB_OK; 1363 | } 1364 | pbL_delFileInfo(files); 1365 | pb_resetbuffer(&L.b); 1366 | s->p = L.s.p; 1367 | return ret; 1368 | } 1369 | 1370 | } 1371 | 1372 | // Renable warning "interaction between '_setjmp' and C++ object destruction is non-portable" 1373 | #ifdef _MSC_VER 1374 | #pragma warning(pop) 1375 | #endif -------------------------------------------------------------------------------- /slua_unreal/Private/luaprotobuf/lpb.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "lua/lua.h" 4 | #include "lua/lauxlib.h" 5 | #include "pb.h" 6 | #include "lpb.h" 7 | 8 | // Disable warning "interaction between '_setjmp' and C++ object destruction is non-portable" 9 | #ifdef _MSC_VER 10 | #pragma warning(push) 11 | #pragma warning(disable:4611) 12 | #pragma warning(disable:4706) 13 | #endif 14 | 15 | namespace NS_SLUA { 16 | 17 | /* Lua util routines */ 18 | 19 | #define PB_STATE "pb.State" 20 | #define PB_BUFFER "pb.Buffer" 21 | #define PB_SLICE "pb.Slice" 22 | 23 | #define check_buffer(L,idx) ((pb_Buffer*)luaL_checkudata(L,idx,PB_BUFFER)) 24 | #define test_buffer(L,idx) ((pb_Buffer*)luaL_testudata(L,idx,PB_BUFFER)) 25 | #define check_slice(L,idx) ((lpb_SliceEx*)luaL_checkudata(L,idx,PB_SLICE)) 26 | #define test_slice(L,idx) ((lpb_SliceEx*)luaL_testudata(L,idx,PB_SLICE)) 27 | #define return_self(L) { lua_settop(L, 1); return 1; } 28 | 29 | #if LUA_VERSION_NUM < 502 30 | #include 31 | 32 | # define LUA_OK 0 33 | # define lua_rawlen lua_objlen 34 | # define luaL_setfuncs(L,l,n) (assert(n==0), luaL_register(L,NULL,l)) 35 | # define luaL_setmetatable(L, name) \ 36 | (luaL_getmetatable((L), (name)), lua_setmetatable(L, -2)) 37 | 38 | static int relindex(int idx, int offset) 39 | { 40 | return idx < 0 && idx > LUA_REGISTRYINDEX ? idx - offset : idx; 41 | } 42 | 43 | static void lua_rawgetp(lua_State *L, int idx, const void *p) { 44 | lua_pushlightuserdata(L, (void*)p); 45 | lua_rawget(L, relindex(idx, 1)); 46 | } 47 | 48 | static void lua_rawsetp(lua_State *L, int idx, const void *p) { 49 | lua_pushlightuserdata(L, (void*)p); 50 | lua_insert(L, -2); 51 | lua_rawset(L, relindex(idx, 1)); 52 | } 53 | 54 | #ifndef luaL_newlib /* not LuaJIT 2.1 */ 55 | #define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l)) 56 | 57 | static lua_Integer lua_tointegerx(lua_State *L, int idx, int *isint) { 58 | lua_Integer i = lua_tointeger(L, idx); 59 | if (isint) *isint = (i != 0 || lua_type(L, idx) == LUA_TNUMBER); 60 | return i; 61 | } 62 | 63 | static lua_Number lua_tonumberx(lua_State *L, int idx, int *isnum) { 64 | lua_Number i = lua_tonumber(L, idx); 65 | if (isnum) *isnum = (i != 0 || lua_type(L, idx) == LUA_TNUMBER); 66 | return i; 67 | } 68 | 69 | static void *luaL_testudata(lua_State *L, int idx, const char *type) { 70 | void *p = lua_touserdata(L, idx); 71 | if (p != NULL && lua_getmetatable(L, idx)) { 72 | lua_getfield(L, LUA_REGISTRYINDEX, type); 73 | if (!lua_rawequal(L, -2, -1)) 74 | p = NULL; 75 | lua_pop(L, 2); 76 | return p; 77 | } 78 | return NULL; 79 | } 80 | 81 | #endif 82 | 83 | #ifdef LUAI_BITSINT /* not LuaJIT */ 84 | #include 85 | 86 | static int luaL_fileresult(lua_State *L, int stat, const char *fname) { 87 | int en = errno; 88 | if (stat) { lua_pushboolean(L, 1); return 1; } 89 | lua_pushnil(L); 90 | lua_pushfstring(L, "%s: %s", fname, strerror(en)); 91 | /*if (fname) lua_pushfstring(L, "%s: %s", fname, strerror(en)); 92 | else lua_pushstring(L, strerror(en));*//* NOT USED */ 93 | lua_pushinteger(L, en); 94 | return 3; 95 | } 96 | 97 | #endif /* not LuaJIT */ 98 | 99 | #endif 100 | 101 | #if LUA_VERSION_NUM >= 503 102 | # define lua53_getfield lua_getfield 103 | # define lua53_rawgeti lua_rawgeti 104 | # define lua53_rawgetp lua_rawgetp 105 | #else /* not Lua 5.3 */ 106 | static int lua53_getfield(lua_State *L, int idx, const char *field) 107 | { 108 | lua_getfield(L, idx, field); return lua_type(L, -1); 109 | } 110 | static int lua53_rawgeti(lua_State *L, int idx, lua_Integer i) 111 | { 112 | lua_rawgeti(L, idx, i); return lua_type(L, -1); 113 | } 114 | static int lua53_rawgetp(lua_State *L, int idx, const void *p) 115 | { 116 | lua_rawgetp(L, idx, p); return lua_type(L, -1); 117 | } 118 | #endif 119 | 120 | 121 | /* protobuf global state */ 122 | 123 | #define default_state(L) ((pb_State*)default_lstate(L)) 124 | 125 | static const char state_name[] = PB_STATE; 126 | 127 | enum lpb_Int64Mode { LPB_NUMBER, LPB_STRING, LPB_HEXSTRING }; 128 | enum lpb_DefMode { LPB_DEFDEF, LPB_COPYDEF, LPB_METADEF, LPB_NODEF }; 129 | 130 | typedef struct lpb_State { 131 | pb_State base; 132 | pb_Buffer buffer; 133 | int defs_index; 134 | int hooks_index; 135 | unsigned use_hooks : 1; /* lpb_Int64Mode */ 136 | unsigned enum_as_value : 1; 137 | unsigned default_mode : 2; /* lpb_DefMode */ 138 | unsigned int64_mode : 2; /* lpb_Int64Mode */ 139 | } lpb_State; 140 | 141 | static int lpb_reftable(lua_State *L, int ref) { 142 | if (ref != LUA_NOREF) { 143 | lua_rawgeti(L, LUA_REGISTRYINDEX, ref); 144 | return ref; 145 | } 146 | else { 147 | lua_newtable(L); 148 | lua_pushvalue(L, -1); 149 | return luaL_ref(L, LUA_REGISTRYINDEX); 150 | } 151 | } 152 | 153 | static void lpb_pushdeftable(lua_State *L, lpb_State *LS) 154 | { 155 | LS->defs_index = lpb_reftable(L, LS->defs_index); 156 | } 157 | 158 | static void lpb_pushhooktable(lua_State *L, lpb_State *LS) 159 | { 160 | LS->hooks_index = lpb_reftable(L, LS->hooks_index); 161 | } 162 | 163 | static int Lpb_delete(lua_State *L) { 164 | lpb_State *LS = (lpb_State*)luaL_testudata(L, 1, PB_STATE); 165 | if (LS != NULL) { 166 | pb_free(&LS->base); 167 | pb_resetbuffer(&LS->buffer); 168 | luaL_unref(L, LUA_REGISTRYINDEX, LS->defs_index); 169 | luaL_unref(L, LUA_REGISTRYINDEX, LS->hooks_index); 170 | } 171 | return 0; 172 | } 173 | 174 | static lpb_State *default_lstate(lua_State *L) { 175 | lpb_State *LS; 176 | if (lua53_rawgetp(L, LUA_REGISTRYINDEX, state_name) == LUA_TUSERDATA) { 177 | LS = (lpb_State*)lua_touserdata(L, -1); 178 | lua_pop(L, 1); 179 | } 180 | else { 181 | lua_pop(L, 1); 182 | LS = (lpb_State*)lua_newuserdata(L, sizeof(lpb_State)); 183 | memset(LS, 0, sizeof(lpb_State)); 184 | LS->defs_index = LUA_NOREF; 185 | LS->hooks_index = LUA_NOREF; 186 | pb_init(&LS->base); 187 | pb_initbuffer(&LS->buffer); 188 | luaL_setmetatable(L, PB_STATE); 189 | lua_rawsetp(L, LUA_REGISTRYINDEX, state_name); 190 | } 191 | return LS; 192 | } 193 | 194 | static int Lpb_state(lua_State *L) { 195 | int top = lua_gettop(L); 196 | default_lstate(L); 197 | lua_rawgetp(L, LUA_REGISTRYINDEX, state_name); 198 | if (top != 0) { 199 | if (lua_isnil(L, 1)) 200 | lua_pushnil(L); 201 | else { 202 | luaL_checkudata(L, 1, PB_STATE); 203 | lua_pushvalue(L, 1); 204 | } 205 | lua_rawsetp(L, LUA_REGISTRYINDEX, state_name); 206 | } 207 | return 1; 208 | } 209 | 210 | 211 | /* protobuf util routines */ 212 | 213 | typedef struct lpb_SliceEx { 214 | pb_Slice base; 215 | const char *head; 216 | } lpb_SliceEx; 217 | 218 | static int lpb_offset(lpb_SliceEx *s) { return (int)(s->base.p - s->head) + 1; } 219 | 220 | static lpb_SliceEx lpb_initext(pb_Slice s) 221 | { 222 | lpb_SliceEx ext; ext.base = s, ext.head = s.p; return ext; 223 | } 224 | 225 | static void lpb_addlength(lua_State *L, pb_Buffer *b, size_t len) 226 | { 227 | if (pb_addlength(b, len) == 0) luaL_error(L, "encode bytes fail"); 228 | } 229 | 230 | static int typeerror(lua_State *L, int idx, const char *type) { 231 | lua_pushfstring(L, "%s expected, got %s", type, luaL_typename(L, idx)); 232 | return luaL_argerror(L, idx, lua_tostring(L, -1)); 233 | } 234 | 235 | static lua_Integer posrelat(lua_Integer pos, size_t len) { 236 | if (pos >= 0) return pos; 237 | else if (0u - (size_t)pos > len) return 0; 238 | else return (lua_Integer)len + pos + 1; 239 | } 240 | 241 | static lua_Integer rangerelat(lua_State *L, int idx, lua_Integer r[2], size_t len) { 242 | r[0] = posrelat(luaL_optinteger(L, idx, 1), len); 243 | r[1] = posrelat(luaL_optinteger(L, idx + 1, len), len); 244 | if (r[0] < 1) r[0] = 1; 245 | if (r[1] > (lua_Integer)len) r[1] = len; 246 | return r[0] <= r[1] ? r[1] - r[0] + 1 : 0; 247 | } 248 | 249 | static int argcheck(lua_State *L, int cond, int idx, const char *fmt, ...) { 250 | if (!cond) { 251 | va_list l; 252 | va_start(l, fmt); 253 | lua_pushvfstring(L, fmt, l); 254 | va_end(l); 255 | return luaL_argerror(L, idx, lua_tostring(L, -1)); 256 | } 257 | return 1; 258 | } 259 | 260 | static pb_Slice lpb_toslice(lua_State *L, int idx) { 261 | int type = lua_type(L, idx); 262 | pb_Slice ret = { NULL, NULL }; 263 | if (type == LUA_TSTRING) { 264 | size_t len; 265 | const char *s = lua_tolstring(L, idx, &len); 266 | ret = pb_lslice(s, len); 267 | } 268 | else if (type == LUA_TUSERDATA) { 269 | pb_Buffer *buffer; 270 | lpb_SliceEx *s; 271 | if ((buffer = test_buffer(L, idx)) != NULL) 272 | ret = pb_result(buffer); 273 | else if ((s = test_slice(L, idx)) != NULL) 274 | ret = s->base; 275 | } 276 | return ret; 277 | } 278 | 279 | static pb_Slice lpb_checkslice(lua_State *L, int idx) { 280 | pb_Slice ret = lpb_toslice(L, idx); 281 | if (ret.p == NULL) typeerror(L, idx, "string/buffer/slice"); 282 | return ret; 283 | } 284 | 285 | static void lpb_readbytes(lua_State *L, lpb_SliceEx *s, lpb_SliceEx *pv) { 286 | uint64_t len = 0; 287 | if (pb_readvarint64(&s->base, &len) == 0 || len > PB_MAX_SIZET) 288 | luaL_error(L, "invalid bytes length: %d (at offset %d)", 289 | (int)len, lpb_offset(s)); 290 | if (pb_readslice(&s->base, (size_t)len, &pv->base) == 0 && len != 0) 291 | luaL_error(L, "un-finished bytes (len %d at offset %d)", 292 | (int)len, lpb_offset(s)); 293 | pv->head = s->head; 294 | } 295 | 296 | static int lpb_hexchar(char ch) { 297 | switch (ch) { 298 | case '0': return 0; 299 | case '1': return 1; case '2': return 2; case '3': return 3; 300 | case '4': return 4; case '5': return 5; case '6': return 6; 301 | case '7': return 7; case '8': return 8; case '9': return 9; 302 | case 'a': case 'A': return 10; case 'b': case 'B': return 11; 303 | case 'c': case 'C': return 12; case 'd': case 'D': return 13; 304 | case 'e': case 'E': return 14; case 'f': case 'F': return 15; 305 | } 306 | return -1; 307 | } 308 | 309 | static uint64_t lpb_tointegerx(lua_State *L, int idx, int *isint) { 310 | int neg = 0; 311 | const char *s, *os; 312 | #if LUA_VERSION_NUM >= 503 313 | uint64_t v = (uint64_t)lua_tointegerx(L, idx, isint); 314 | if (*isint) return v; 315 | #else 316 | uint64_t v = 0; 317 | lua_Number nv = lua_tonumberx(L, idx, isint); 318 | if (*isint) { 319 | if (nv < (lua_Number)INT64_MIN || nv >(lua_Number)INT64_MAX) 320 | luaL_error(L, "number has no integer representation"); 321 | return (uint64_t)(int64_t)nv; 322 | } 323 | #endif 324 | if ((os = s = lua_tostring(L, idx)) == NULL) return 0; 325 | while (*s == '#' || *s == '+' || *s == '-') 326 | neg = (*s == '-') ^ neg, ++s; 327 | if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { 328 | for (s += 2; *s != '\0'; ++s) { 329 | int n = lpb_hexchar(*s); 330 | if (n < 0) break; 331 | v = v << 4 | n; 332 | } 333 | } 334 | else { 335 | for (; *s != '\0'; ++s) { 336 | int n = lpb_hexchar(*s); 337 | if (n < 0 || n > 10) break; 338 | v = v * 10 + n; 339 | } 340 | } 341 | if (*s != '\0') luaL_error(L, "integer format error: '%s'", os); 342 | *isint = 1; 343 | return neg ? ~v + 1 : v; 344 | } 345 | 346 | static uint64_t lpb_checkinteger(lua_State *L, int idx) { 347 | int isint; 348 | uint64_t v = lpb_tointegerx(L, idx, &isint); 349 | if (!isint) typeerror(L, idx, "number/string"); 350 | return v; 351 | } 352 | 353 | static void lpb_pushinteger(lua_State *L, int64_t n, int mode) { 354 | if (mode != LPB_NUMBER && (n < INT_MIN || n > INT_MAX)) { 355 | char buff[32], *p = buff + sizeof(buff) - 1; 356 | int neg = n < 0; 357 | uint64_t un = neg ? ~(uint64_t)n + 1 : (uint64_t)n; 358 | if (mode == LPB_STRING) { 359 | for (*p = '\0'; un > 0; un /= 10) 360 | *--p = "0123456789"[un % 10]; 361 | } 362 | else if (mode == LPB_HEXSTRING) { 363 | for (*p = '\0'; un > 0; un >>= 4) 364 | *--p = "0123456789ABCDEF"[un & 0xF]; 365 | *--p = 'x', *--p = '0'; 366 | } 367 | if (neg) *--p = '-'; 368 | *--p = '#'; 369 | lua_pushstring(L, p); 370 | } 371 | else if (LUA_VERSION_NUM >= 503 && sizeof(lua_Integer) >= 8) 372 | lua_pushinteger(L, (lua_Integer)n); 373 | else 374 | lua_pushnumber(L, (lua_Number)n); 375 | } 376 | 377 | typedef union lpb_Value { 378 | lpb_SliceEx s[1]; 379 | uint32_t u32; 380 | uint64_t u64; 381 | lua_Integer lint; 382 | lua_Number lnum; 383 | } lpb_Value; 384 | 385 | static int lpb_addtype(lua_State *L, pb_Buffer *b, int idx, int type, size_t *plen) { 386 | int ret = 0, expected = LUA_TNUMBER; 387 | lpb_Value v; 388 | size_t len = 0; 389 | switch (type) { 390 | case PB_Tbool: 391 | len = pb_addvarint32(b, ret = lua_toboolean(L, idx)); 392 | if (ret) len = 0; 393 | ret = 1; 394 | break; 395 | case PB_Tdouble: 396 | v.lnum = lua_tonumberx(L, idx, &ret); 397 | if (ret) len = pb_addfixed64(b, pb_encode_double((double)v.lnum)); 398 | if (v.lnum != 0.0) len = 0; 399 | break; 400 | case PB_Tfloat: 401 | v.lnum = lua_tonumberx(L, idx, &ret); 402 | if (ret) len = pb_addfixed32(b, pb_encode_float((float)v.lnum)); 403 | if (v.lnum != 0.0) len = 0; 404 | break; 405 | case PB_Tfixed32: 406 | v.u64 = lpb_tointegerx(L, idx, &ret); 407 | if (ret) len = pb_addfixed32(b, v.u32); 408 | if (v.u64 != 0) len = 0; 409 | break; 410 | case PB_Tsfixed32: 411 | v.u64 = lpb_tointegerx(L, idx, &ret); 412 | if (ret) len = pb_addfixed32(b, v.u32); 413 | if (v.u64 != 0) len = 0; 414 | break; 415 | case PB_Tint32: 416 | v.u64 = lpb_tointegerx(L, idx, &ret); 417 | if (ret) len = pb_addvarint64(b, pb_expandsig((uint32_t)v.u64)); 418 | if (v.u64 != 0) len = 0; 419 | break; 420 | case PB_Tuint32: 421 | v.u64 = lpb_tointegerx(L, idx, &ret); 422 | if (ret) len = pb_addvarint32(b, v.u32); 423 | if (v.u64 != 0) len = 0; 424 | break; 425 | case PB_Tsint32: 426 | v.u64 = lpb_tointegerx(L, idx, &ret); 427 | if (ret) len = pb_addvarint32(b, pb_encode_sint32(v.u32)); 428 | if (v.u64 != 0) len = 0; 429 | break; 430 | case PB_Tfixed64: 431 | v.u64 = lpb_tointegerx(L, idx, &ret); 432 | if (ret) len = pb_addfixed64(b, v.u64); 433 | if (v.u64 != 0) len = 0; 434 | break; 435 | case PB_Tsfixed64: 436 | v.u64 = lpb_tointegerx(L, idx, &ret); 437 | if (ret) len = pb_addfixed64(b, v.u64); 438 | if (v.u64 != 0) len = 0; 439 | break; 440 | case PB_Tint64: case PB_Tuint64: 441 | v.u64 = lpb_tointegerx(L, idx, &ret); 442 | if (ret) len = pb_addvarint64(b, v.u64); 443 | if (v.u64 != 0) len = 0; 444 | break; 445 | case PB_Tsint64: 446 | v.u64 = lpb_tointegerx(L, idx, &ret); 447 | if (ret) len = pb_addvarint64(b, pb_encode_sint64(v.u64)); 448 | if (v.u64 != 0) len = 0; 449 | break; 450 | case PB_Tbytes: case PB_Tstring: 451 | v.s->base = lpb_toslice(L, idx); 452 | if ((ret = (v.s->base.p != NULL))) len = pb_addbytes(b, v.s->base); 453 | if (pb_len(v.s->base) != 0) len = 0; 454 | expected = LUA_TSTRING; 455 | break; 456 | default: 457 | lua_pushfstring(L, "unknown type %s", pb_typename(type, "")); 458 | if (idx > 0) argcheck(L, 0, idx, lua_tostring(L, -1)); 459 | lua_error(L); 460 | } 461 | if (plen) *plen = len; 462 | return ret ? 0 : expected; 463 | } 464 | 465 | static void lpb_readtype(lua_State *L, lpb_State *LS, int type, lpb_SliceEx *s) { 466 | lpb_Value v; 467 | switch (type) { 468 | #define pushinteger(n) lpb_pushinteger((L), (n), LS->int64_mode) 469 | case PB_Tbool: case PB_Tenum: 470 | case PB_Tint32: case PB_Tuint32: case PB_Tsint32: 471 | case PB_Tint64: case PB_Tuint64: case PB_Tsint64: 472 | if (pb_readvarint64(&s->base, &v.u64) == 0) 473 | luaL_error(L, "invalid varint value at offset %d", lpb_offset(s)); 474 | switch (type) { 475 | case PB_Tbool: lua_pushboolean(L, v.u64 != 0); break; 476 | /*case PB_Tenum: pushinteger(v.u64); break; [> NOT REACHED <]*/ 477 | case PB_Tint32: pushinteger((int32_t)v.u64); break; 478 | case PB_Tuint32: pushinteger((uint32_t)v.u64); break; 479 | case PB_Tsint32: pushinteger(pb_decode_sint32((uint32_t)v.u64)); break; 480 | case PB_Tint64: pushinteger((int64_t)v.u64); break; 481 | case PB_Tuint64: pushinteger((uint64_t)v.u64); break; 482 | case PB_Tsint64: pushinteger(pb_decode_sint64(v.u64)); break; 483 | } 484 | break; 485 | case PB_Tfloat: 486 | case PB_Tfixed32: 487 | case PB_Tsfixed32: 488 | if (pb_readfixed32(&s->base, &v.u32) == 0) 489 | luaL_error(L, "invalid fixed32 value at offset %d", lpb_offset(s)); 490 | switch (type) { 491 | case PB_Tfloat: lua_pushnumber(L, pb_decode_float(v.u32)); break; 492 | case PB_Tfixed32: pushinteger(v.u32); break; 493 | case PB_Tsfixed32: pushinteger((int32_t)v.u32); break; 494 | } 495 | break; 496 | case PB_Tdouble: 497 | case PB_Tfixed64: 498 | case PB_Tsfixed64: 499 | if (pb_readfixed64(&s->base, &v.u64) == 0) 500 | luaL_error(L, "invalid fixed64 value at offset %d", lpb_offset(s)); 501 | switch (type) { 502 | case PB_Tdouble: lua_pushnumber(L, pb_decode_double(v.u64)); break; 503 | case PB_Tfixed64: pushinteger(v.u64); break; 504 | case PB_Tsfixed64: pushinteger((int64_t)v.u64); break; 505 | } 506 | break; 507 | case PB_Tbytes: 508 | case PB_Tstring: 509 | case PB_Tmessage: 510 | lpb_readbytes(L, s, v.s); 511 | lua_pushlstring(L, v.s->base.p, pb_len(v.s->base)); 512 | break; 513 | default: 514 | luaL_error(L, "unknown type %s (%d)", pb_typename(type, NULL), type); 515 | } 516 | } 517 | 518 | 519 | /* io routines */ 520 | 521 | #ifdef _WIN32 522 | # include 523 | # include 524 | #else 525 | # define setmode(a,b) ((void)0) 526 | #endif 527 | 528 | static int io_read(lua_State *L) { 529 | FILE *fp = (FILE*)lua_touserdata(L, 1); 530 | size_t nr; 531 | luaL_Buffer b; 532 | luaL_buffinit(L, &b); 533 | do { /* read file in chunks of LUAL_BUFFERSIZE bytes */ 534 | char *p = luaL_prepbuffer(&b); 535 | nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, fp); 536 | luaL_addsize(&b, nr); 537 | } while (nr == LUAL_BUFFERSIZE); 538 | luaL_pushresult(&b); /* close buffer */ 539 | return 1; 540 | } 541 | 542 | static int io_write(lua_State *L, FILE *f, int idx) { 543 | int nargs = lua_gettop(L) - idx + 1; 544 | int status = 1; 545 | for (; nargs--; idx++) { 546 | pb_Slice s = lpb_checkslice(L, idx); 547 | size_t l = pb_len(s); 548 | status = status && (fwrite(s.p, sizeof(char), l, f) == l); 549 | } 550 | return status ? 1 : luaL_fileresult(L, 0, NULL); 551 | } 552 | 553 | static int Lio_read(lua_State *L) { 554 | const char *fname = luaL_optstring(L, 1, NULL); 555 | FILE *fp = stdin; 556 | int ret; 557 | if (fname == NULL) 558 | (void)setmode(fileno(stdin), O_BINARY); 559 | else if ((fp = fopen(fname, "rb")) == NULL) 560 | return luaL_fileresult(L, 0, fname); 561 | lua_pushcfunction(L, io_read); 562 | lua_pushlightuserdata(L, fp); 563 | ret = lua_pcall(L, 1, 1, 0); 564 | if (fp != stdin) fclose(fp); 565 | else (void)setmode(fileno(stdin), O_TEXT); 566 | if (ret != LUA_OK) { lua_pushnil(L); lua_insert(L, -2); return 2; } 567 | return 1; 568 | } 569 | 570 | static int Lio_write(lua_State *L) { 571 | int res; 572 | (void)setmode(fileno(stdout), O_BINARY); 573 | res = io_write(L, stdout, 1); 574 | fflush(stdout); 575 | (void)setmode(fileno(stdout), O_TEXT); 576 | return res; 577 | } 578 | 579 | static int Lio_dump(lua_State *L) { 580 | int res; 581 | const char *fname = luaL_checkstring(L, 1); 582 | FILE *fp = fopen(fname, "wb"); 583 | if (fp == NULL) return luaL_fileresult(L, 0, fname); 584 | res = io_write(L, fp, 2); 585 | fclose(fp); 586 | return res; 587 | } 588 | 589 | LUALIB_API int luaopen_pb_io(lua_State *L) { 590 | luaL_Reg libs[] = { 591 | #define ENTRY(name) { #name, Lio_##name } 592 | ENTRY(read), 593 | ENTRY(write), 594 | ENTRY(dump), 595 | #undef ENTRY 596 | { NULL, NULL } 597 | }; 598 | luaL_newlib(L, libs); 599 | return 1; 600 | } 601 | 602 | 603 | /* protobuf integer conversion */ 604 | 605 | static int Lconv_encode_int32(lua_State *L) { 606 | unsigned mode = default_lstate(L)->int64_mode; 607 | uint64_t v = pb_expandsig((int32_t)lpb_checkinteger(L, 1)); 608 | lpb_pushinteger(L, v, mode); 609 | return 1; 610 | } 611 | 612 | static int Lconv_encode_uint32(lua_State *L) { 613 | unsigned mode = default_lstate(L)->int64_mode; 614 | lpb_pushinteger(L, (uint32_t)lpb_checkinteger(L, 1), mode); 615 | return 1; 616 | } 617 | 618 | static int Lconv_encode_sint32(lua_State *L) { 619 | unsigned mode = default_lstate(L)->int64_mode; 620 | lpb_pushinteger(L, pb_encode_sint32((int32_t)lpb_checkinteger(L, 1)), mode); 621 | return 1; 622 | } 623 | 624 | static int Lconv_decode_sint32(lua_State *L) { 625 | unsigned mode = default_lstate(L)->int64_mode; 626 | lpb_pushinteger(L, pb_decode_sint32((uint32_t)lpb_checkinteger(L, 1)), mode); 627 | return 1; 628 | } 629 | 630 | static int Lconv_encode_sint64(lua_State *L) { 631 | unsigned mode = default_lstate(L)->int64_mode; 632 | lpb_pushinteger(L, pb_encode_sint64(lpb_checkinteger(L, 1)), mode); 633 | return 1; 634 | } 635 | 636 | static int Lconv_decode_sint64(lua_State *L) { 637 | unsigned mode = default_lstate(L)->int64_mode; 638 | lpb_pushinteger(L, pb_decode_sint64(lpb_checkinteger(L, 1)), mode); 639 | return 1; 640 | } 641 | 642 | static int Lconv_encode_float(lua_State *L) { 643 | unsigned mode = default_lstate(L)->int64_mode; 644 | lpb_pushinteger(L, pb_encode_float((float)luaL_checknumber(L, 1)), mode); 645 | return 1; 646 | } 647 | 648 | static int Lconv_decode_float(lua_State *L) { 649 | lua_pushnumber(L, pb_decode_float((uint32_t)lpb_checkinteger(L, 1))); 650 | return 1; 651 | } 652 | 653 | static int Lconv_encode_double(lua_State *L) { 654 | unsigned mode = default_lstate(L)->int64_mode; 655 | lpb_pushinteger(L, pb_encode_double(luaL_checknumber(L, 1)), mode); 656 | return 1; 657 | } 658 | 659 | static int Lconv_decode_double(lua_State *L) { 660 | lua_pushnumber(L, pb_decode_double(lpb_checkinteger(L, 1))); 661 | return 1; 662 | } 663 | 664 | LUALIB_API int luaopen_pb_conv(lua_State *L) { 665 | luaL_Reg libs[] = { 666 | { "decode_uint32", Lconv_encode_uint32 }, 667 | { "decode_int32", Lconv_encode_int32 }, 668 | #define ENTRY(name) { #name, Lconv_##name } 669 | ENTRY(encode_int32), 670 | ENTRY(encode_uint32), 671 | ENTRY(encode_sint32), 672 | ENTRY(encode_sint64), 673 | ENTRY(decode_sint32), 674 | ENTRY(decode_sint64), 675 | ENTRY(decode_float), 676 | ENTRY(decode_double), 677 | ENTRY(encode_float), 678 | ENTRY(encode_double), 679 | #undef ENTRY 680 | { NULL, NULL } 681 | }; 682 | luaL_newlib(L, libs); 683 | return 1; 684 | } 685 | 686 | 687 | /* protobuf encode routine */ 688 | 689 | static int lpb_typefmt(const char *fmt) { 690 | switch (*fmt) { 691 | case 'b': return PB_Tbool; 692 | case 'f': return PB_Tfloat; 693 | case 'F': return PB_Tdouble; 694 | case 'i': return PB_Tint32; 695 | case 'j': return PB_Tsint32; 696 | case 'u': return PB_Tuint32; 697 | case 'x': return PB_Tfixed32; 698 | case 'y': return PB_Tsfixed32; 699 | case 'I': return PB_Tint64; 700 | case 'J': return PB_Tsint64; 701 | case 'U': return PB_Tuint64; 702 | case 'X': return PB_Tfixed64; 703 | case 'Y': return PB_Tsfixed64; 704 | } 705 | return -1; 706 | } 707 | 708 | static int lpb_packfmt(lua_State *L, int idx, pb_Buffer *b, const char **pfmt, int level) { 709 | const char *fmt = *pfmt; 710 | int type, ltype; 711 | size_t len; 712 | argcheck(L, level <= 100, 1, "format level overflow"); 713 | for (; *fmt != '\0'; ++fmt) { 714 | switch (*fmt) { 715 | case 'v': pb_addvarint64(b, (uint64_t)lpb_checkinteger(L, idx++)); break; 716 | case 'd': pb_addfixed32(b, (uint32_t)lpb_checkinteger(L, idx++)); break; 717 | case 'q': pb_addfixed64(b, (uint64_t)lpb_checkinteger(L, idx++)); break; 718 | case 'c': pb_addslice(b, lpb_checkslice(L, idx++)); break; 719 | case 's': pb_addbytes(b, lpb_checkslice(L, idx++)); break; 720 | case '#': lpb_addlength(L, b, (size_t)lpb_checkinteger(L, idx++)); break; 721 | case '(': 722 | len = pb_bufflen(b); 723 | ++fmt; 724 | idx = lpb_packfmt(L, idx, b, &fmt, level + 1); 725 | lpb_addlength(L, b, len); 726 | break; 727 | case ')': 728 | if (level == 0) luaL_argerror(L, 1, "unexpected ')' in format"); 729 | *pfmt = fmt; 730 | return idx; 731 | case '\0': 732 | default: 733 | argcheck(L, (type = lpb_typefmt(fmt)) >= 0, 734 | 1, "invalid formater: '%c'", *fmt); 735 | ltype = lpb_addtype(L, b, idx, type, NULL); 736 | argcheck(L, ltype == 0, idx, "%s expected for type '%s', got %s", 737 | lua_typename(L, ltype), pb_typename(type, ""), 738 | luaL_typename(L, idx)); 739 | ++idx; 740 | } 741 | } 742 | if (level != 0) luaL_argerror(L, 2, "unmatch '(' in format"); 743 | *pfmt = fmt; 744 | return idx; 745 | } 746 | 747 | static int Lpb_tohex(lua_State *L) { 748 | pb_Slice s = lpb_checkslice(L, 1); 749 | const char *hexa = "0123456789ABCDEF"; 750 | char hex[4] = "XX "; 751 | lua_Integer r[2] = { 1, -1 }; 752 | luaL_Buffer lb; 753 | rangerelat(L, 2, r, pb_len(s)); 754 | luaL_buffinit(L, &lb); 755 | for (; r[0] <= r[1]; ++r[0]) { 756 | unsigned int ch = s.p[r[0] - 1]; 757 | hex[0] = hexa[(ch >> 4) & 0xF]; 758 | hex[1] = hexa[(ch) & 0xF]; 759 | if (r[0] == r[1]) hex[2] = '\0'; 760 | luaL_addstring(&lb, hex); 761 | } 762 | luaL_pushresult(&lb); 763 | return 1; 764 | } 765 | 766 | static int Lpb_result(lua_State *L) { 767 | pb_Slice s = lpb_checkslice(L, 1); 768 | lua_Integer r[2] = { 1, -1 }, range = rangerelat(L, 2, r, pb_len(s)); 769 | lua_pushlstring(L, s.p + r[0] - 1, (size_t)range); 770 | return 1; 771 | } 772 | 773 | static int Lbuf_new(lua_State *L) { 774 | int i, top = lua_gettop(L); 775 | pb_Buffer *buf = (pb_Buffer*)lua_newuserdata(L, sizeof(pb_Buffer)); 776 | pb_initbuffer(buf); 777 | luaL_setmetatable(L, PB_BUFFER); 778 | for (i = 1; i <= top; ++i) 779 | pb_addslice(buf, lpb_checkslice(L, i)); 780 | return 1; 781 | } 782 | 783 | static int Lbuf_libcall(lua_State *L) { 784 | int i, top = lua_gettop(L); 785 | pb_Buffer *buf = (pb_Buffer*)lua_newuserdata(L, sizeof(pb_Buffer)); 786 | pb_initbuffer(buf); 787 | luaL_setmetatable(L, PB_BUFFER); 788 | for (i = 2; i <= top; ++i) 789 | pb_addslice(buf, lpb_checkslice(L, i)); 790 | return 1; 791 | } 792 | 793 | static int Lbuf_tostring(lua_State *L) { 794 | pb_Buffer *buf = check_buffer(L, 1); 795 | lua_pushfstring(L, "pb.Buffer: %p", buf); 796 | return 1; 797 | } 798 | 799 | static int Lbuf_reset(lua_State *L) { 800 | pb_Buffer *buf = check_buffer(L, 1); 801 | int i, top = lua_gettop(L); 802 | pb_resetbuffer(buf); 803 | for (i = 2; i <= top; ++i) 804 | pb_addslice(buf, lpb_checkslice(L, i)); 805 | return_self(L); 806 | } 807 | 808 | static int Lbuf_len(lua_State *L) { 809 | pb_Buffer *buf = check_buffer(L, 1); 810 | lua_pushinteger(L, (lua_Integer)buf->size); 811 | return 1; 812 | } 813 | 814 | static int Lbuf_pack(lua_State *L) { 815 | pb_Buffer b, *pb = test_buffer(L, 1); 816 | int idx = 1 + (pb != NULL); 817 | const char *fmt = luaL_checkstring(L, idx++); 818 | if (pb == NULL) pb_initbuffer(pb = &b); 819 | lpb_packfmt(L, idx, pb, &fmt, 0); 820 | if (pb != &b) 821 | lua_settop(L, 1); 822 | else { 823 | pb_Slice ret = pb_result(pb); 824 | lua_pushlstring(L, ret.p, pb_len(ret)); 825 | pb_resetbuffer(pb); 826 | } 827 | return 1; 828 | } 829 | 830 | LUALIB_API int luaopen_pb_buffer(lua_State *L) { 831 | luaL_Reg libs[] = { 832 | { "__tostring", Lbuf_tostring }, 833 | { "__len", Lbuf_len }, 834 | { "__gc", Lbuf_reset }, 835 | { "delete", Lbuf_reset }, 836 | { "tohex", Lpb_tohex }, 837 | { "result", Lpb_result }, 838 | #define ENTRY(name) { #name, Lbuf_##name } 839 | ENTRY(new), 840 | ENTRY(reset), 841 | ENTRY(pack), 842 | #undef ENTRY 843 | { NULL, NULL } 844 | }; 845 | if (luaL_newmetatable(L, PB_BUFFER)) { 846 | luaL_setfuncs(L, libs, 0); 847 | lua_pushvalue(L, -1); 848 | lua_setfield(L, -2, "__index"); 849 | lua_createtable(L, 0, 1); 850 | lua_pushcfunction(L, Lbuf_libcall); 851 | lua_setfield(L, -2, "__call"); 852 | lua_setmetatable(L, -2); 853 | } 854 | return 1; 855 | } 856 | 857 | 858 | /* protobuf decode routine */ 859 | 860 | #define LPB_INITSTACKLEN 2 861 | 862 | typedef struct lpb_Slice { 863 | lpb_SliceEx curr; 864 | lpb_SliceEx *buff; 865 | size_t used; 866 | size_t size; 867 | lpb_SliceEx init_buff[LPB_INITSTACKLEN]; 868 | } lpb_Slice; 869 | 870 | static void lpb_resetslice(lua_State *L, lpb_Slice *s, size_t size) { 871 | if (size == sizeof(lpb_Slice)) { 872 | if (s->buff != s->init_buff) 873 | free(s->buff); 874 | memset(s, 0, sizeof(lpb_Slice)); 875 | s->buff = s->init_buff; 876 | s->size = LPB_INITSTACKLEN; 877 | } 878 | lua_pushnil(L); 879 | lua_rawsetp(L, LUA_REGISTRYINDEX, s); 880 | } 881 | 882 | static lpb_SliceEx lpb_checkview(lua_State *L, int idx, lpb_SliceEx *ps) { 883 | pb_Slice src = lpb_checkslice(L, idx); 884 | lua_Integer r[2] = { 1, -1 }, range = rangerelat(L, idx + 1, r, pb_len(src)); 885 | lpb_SliceEx ret; 886 | if (ps) ps->base = src, ps->head = src.p; 887 | ret.base.p = src.p + r[0] - 1; 888 | ret.base.end = ret.base.p + range; 889 | ret.head = src.p; 890 | return ret; 891 | } 892 | 893 | static void lpb_enterview(lua_State *L, lpb_Slice *s, lpb_SliceEx view) { 894 | if (s->used >= s->size) { 895 | size_t newsize = s->size * 2; 896 | lpb_SliceEx *oldp = s->buff != s->init_buff ? s->buff : NULL; 897 | lpb_SliceEx *newp = (lpb_SliceEx*)realloc(oldp, newsize * sizeof(lpb_SliceEx)); 898 | if (newp == NULL) { luaL_error(L, "out of memory"); return; } 899 | if (oldp == NULL) memcpy(newp, s->buff, s->used * sizeof(lpb_SliceEx)); 900 | s->buff = newp; 901 | s->size = newsize; 902 | } 903 | s->buff[s->used++] = s->curr; 904 | s->curr = view; 905 | } 906 | 907 | static void lpb_initslice(lua_State *L, int idx, lpb_Slice *s, size_t size) { 908 | if (size == sizeof(lpb_Slice)) { 909 | memset(s, 0, sizeof(lpb_Slice)); 910 | s->buff = s->init_buff; 911 | s->size = LPB_INITSTACKLEN; 912 | } 913 | if (!lua_isnoneornil(L, idx)) { 914 | lpb_SliceEx base, view = lpb_checkview(L, idx, &base); 915 | s->curr = base; 916 | if (size == sizeof(lpb_Slice)) lpb_enterview(L, s, view); 917 | lua_pushvalue(L, idx); 918 | lua_rawsetp(L, LUA_REGISTRYINDEX, s); 919 | } 920 | } 921 | 922 | static int lpb_unpackscalar(lua_State *L, int *pidx, int top, int fmt, lpb_SliceEx *s) { 923 | unsigned mode = default_lstate(L)->int64_mode; 924 | lpb_Value v; 925 | switch (fmt) { 926 | case 'v': 927 | if (pb_readvarint64(&s->base, &v.u64) == 0) 928 | luaL_error(L, "invalid varint value at offset %d", lpb_offset(s)); 929 | lpb_pushinteger(L, v.u64, mode); 930 | break; 931 | case 'd': 932 | if (pb_readfixed32(&s->base, &v.u32) == 0) 933 | luaL_error(L, "invalid fixed32 value at offset %d", lpb_offset(s)); 934 | lpb_pushinteger(L, v.u32, mode); 935 | break; 936 | case 'q': 937 | if (pb_readfixed64(&s->base, &v.u64) == 0) 938 | luaL_error(L, "invalid fixed64 value at offset %d", lpb_offset(s)); 939 | lpb_pushinteger(L, v.u64, mode); 940 | break; 941 | case 's': 942 | if (pb_readbytes(&s->base, &v.s->base) == 0) 943 | luaL_error(L, "invalid bytes value at offset %d", lpb_offset(s)); 944 | lua_pushlstring(L, v.s->base.p, pb_len(v.s->base)); 945 | break; 946 | case 'c': 947 | argcheck(L, *pidx <= top, 1, "format argument exceed"); 948 | v.lint = luaL_checkinteger(L, *pidx++); 949 | if (pb_readslice(&s->base, (size_t)v.lint, &v.s->base) == 0) 950 | luaL_error(L, "invalid sub string at offset %d", lpb_offset(s)); 951 | lua_pushlstring(L, v.s->base.p, pb_len(v.s->base)); 952 | break; 953 | default: 954 | return 0; 955 | } 956 | return 1; 957 | } 958 | 959 | static int lpb_unpackloc(lua_State *L, int *pidx, int top, int fmt, lpb_SliceEx *s, int *prets) { 960 | lua_Integer li; 961 | size_t len = s->base.end - s->head; 962 | switch (fmt) { 963 | case '@': 964 | lua_pushinteger(L, lpb_offset(s)); 965 | ++*prets; 966 | break; 967 | 968 | case '*': case '+': 969 | argcheck(L, *pidx <= top, 1, "format argument exceed"); 970 | if (fmt == '*') 971 | li = posrelat(luaL_checkinteger(L, *pidx++), len); 972 | else 973 | li = lpb_offset(s) + luaL_checkinteger(L, *pidx++); 974 | if (li == 0) li = 1; 975 | if (li > (lua_Integer)len) li = (lua_Integer)len + 1; 976 | s->base.p = s->head + li - 1; 977 | break; 978 | 979 | default: 980 | return 0; 981 | } 982 | return 1; 983 | } 984 | 985 | static int lpb_unpackfmt(lua_State *L, int idx, const char *fmt, lpb_SliceEx *s) { 986 | int rets = 0, top = lua_gettop(L), type; 987 | for (; *fmt != '\0'; ++fmt) { 988 | if (lpb_unpackloc(L, &idx, top, *fmt, s, &rets)) 989 | continue; 990 | if (s->base.p >= s->base.end) { lua_pushnil(L); return rets + 1; } 991 | luaL_checkstack(L, 1, "too many values"); 992 | if (!lpb_unpackscalar(L, &idx, top, *fmt, s)) { 993 | argcheck(L, (type = lpb_typefmt(fmt)) >= 0, 994 | 1, "invalid formater: '%c'", *fmt); 995 | lpb_readtype(L, default_lstate(L), type, s); 996 | } 997 | ++rets; 998 | } 999 | return rets; 1000 | } 1001 | 1002 | static lpb_Slice *check_lslice(lua_State *L, int idx) { 1003 | lpb_SliceEx *s = check_slice(L, idx); 1004 | argcheck(L, lua_rawlen(L, 1) == sizeof(lpb_Slice), 1005 | idx, "unsupport operation for raw mode slice"); 1006 | return (lpb_Slice*)s; 1007 | } 1008 | 1009 | static int Lslice_new(lua_State *L) { 1010 | lpb_Slice *s; 1011 | lua_settop(L, 3); 1012 | s = (lpb_Slice*)lua_newuserdata(L, sizeof(lpb_Slice)); 1013 | lpb_initslice(L, 1, s, sizeof(lpb_Slice)); 1014 | luaL_setmetatable(L, PB_SLICE); 1015 | return 1; 1016 | } 1017 | 1018 | static int Lslice_libcall(lua_State *L) { 1019 | lpb_Slice *s; 1020 | lua_settop(L, 4); 1021 | s = (lpb_Slice*)lua_newuserdata(L, sizeof(lpb_Slice)); 1022 | lpb_initslice(L, 2, s, sizeof(lpb_Slice)); 1023 | luaL_setmetatable(L, PB_SLICE); 1024 | return 1; 1025 | } 1026 | 1027 | static int Lslice_reset(lua_State *L) { 1028 | lpb_Slice *s = check_lslice(L, 1); 1029 | size_t size = lua_rawlen(L, 1); 1030 | lpb_resetslice(L, s, size); 1031 | if (!lua_isnoneornil(L, 2)) 1032 | lpb_initslice(L, 2, s, size); 1033 | return_self(L); 1034 | } 1035 | 1036 | static int Lslice_tostring(lua_State *L) { 1037 | lpb_SliceEx *s = check_slice(L, 1); 1038 | lua_pushfstring(L, "pb.Slice: %p%s", s, 1039 | lua_rawlen(L, 1) == sizeof(lpb_Slice) ? "" : " (raw)"); 1040 | return 1; 1041 | } 1042 | 1043 | static int Lslice_len(lua_State *L) { 1044 | lpb_SliceEx *s = check_slice(L, 1); 1045 | lua_pushinteger(L, (lua_Integer)pb_len(s->base)); 1046 | lua_pushinteger(L, (lua_Integer)lpb_offset(s)); 1047 | return 2; 1048 | } 1049 | 1050 | static int Lslice_unpack(lua_State *L) { 1051 | lpb_SliceEx view, *s = test_slice(L, 1); 1052 | const char *fmt = luaL_checkstring(L, 2); 1053 | if (s == NULL) view = lpb_initext(lpb_checkslice(L, 1)), s = &view; 1054 | return lpb_unpackfmt(L, 3, fmt, s); 1055 | } 1056 | 1057 | static int Lslice_level(lua_State *L) { 1058 | lpb_Slice *s = check_lslice(L, 1); 1059 | if (!lua_isnoneornil(L, 2)) { 1060 | lpb_SliceEx *se; 1061 | lua_Integer level = posrelat(luaL_checkinteger(L, 2), s->used); 1062 | if (level > (lua_Integer)s->used) 1063 | return 0; 1064 | else if (level == (lua_Integer)s->used) 1065 | se = &s->curr; 1066 | else 1067 | se = &s->buff[level]; 1068 | lua_pushinteger(L, (lua_Integer)(se->base.p - s->buff[0].head) + 1); 1069 | lua_pushinteger(L, (lua_Integer)(se->head - s->buff[0].head) + 1); 1070 | lua_pushinteger(L, (lua_Integer)(se->base.end - s->buff[0].head)); 1071 | return 3; 1072 | } 1073 | lua_pushinteger(L, s->used); 1074 | return 1; 1075 | } 1076 | 1077 | static int Lslice_enter(lua_State *L) { 1078 | lpb_Slice *s = check_lslice(L, 1); 1079 | lpb_SliceEx view; 1080 | if (lua_isnoneornil(L, 2)) { 1081 | argcheck(L, pb_readbytes(&s->curr.base, &view.base) != 0, 1082 | 1, "bytes wireformat expected at offset %d", lpb_offset(&s->curr)); 1083 | view.head = view.base.p; 1084 | lpb_enterview(L, s, view); 1085 | } 1086 | else { 1087 | lua_Integer r[] = { 1, -1 }; 1088 | lua_Integer range = rangerelat(L, 2, r, s->curr.base.end - s->curr.head); 1089 | view.base.p = s->curr.head + r[0] - 1; 1090 | view.base.end = view.base.p + range; 1091 | view.head = s->curr.head; 1092 | lpb_enterview(L, s, view); 1093 | } 1094 | return_self(L); 1095 | } 1096 | 1097 | static int Lslice_leave(lua_State *L) { 1098 | lpb_Slice *s = check_lslice(L, 1); 1099 | lua_Integer count = posrelat(luaL_optinteger(L, 2, 1), s->used); 1100 | if (count > (lua_Integer)s->used) 1101 | argcheck(L, 0, 2, "level (%d) exceed max level %d", 1102 | (int)count, (int)s->used); 1103 | else if (count == (lua_Integer)s->used) { 1104 | s->curr = s->buff[0]; 1105 | s->used = 1; 1106 | } 1107 | else { 1108 | s->used -= (size_t)count; 1109 | s->curr = s->buff[s->used]; 1110 | } 1111 | lua_settop(L, 1); 1112 | lua_pushinteger(L, s->used); 1113 | return 2; 1114 | } 1115 | 1116 | LUALIB_API int lpb_newslice(lua_State *L, const char *s, size_t len) { 1117 | lpb_SliceEx *S = (lpb_SliceEx*)lua_newuserdata(L, sizeof(lpb_SliceEx)); 1118 | *S = lpb_initext(pb_lslice(s, len)); 1119 | luaL_setmetatable(L, PB_SLICE); 1120 | return 1; 1121 | } 1122 | 1123 | LUALIB_API int luaopen_pb_slice(lua_State *L) { 1124 | luaL_Reg libs[] = { 1125 | { "__tostring", Lslice_tostring }, 1126 | { "__len", Lslice_len }, 1127 | { "__gc", Lslice_reset }, 1128 | { "delete", Lslice_reset }, 1129 | { "tohex", Lpb_tohex }, 1130 | { "result", Lpb_result }, 1131 | #define ENTRY(name) { #name, Lslice_##name } 1132 | ENTRY(new), 1133 | ENTRY(reset), 1134 | ENTRY(level), 1135 | ENTRY(enter), 1136 | ENTRY(leave), 1137 | ENTRY(unpack), 1138 | #undef ENTRY 1139 | { NULL, NULL } 1140 | }; 1141 | if (luaL_newmetatable(L, PB_SLICE)) { 1142 | luaL_setfuncs(L, libs, 0); 1143 | lua_pushvalue(L, -1); 1144 | lua_setfield(L, -2, "__index"); 1145 | lua_createtable(L, 0, 1); 1146 | lua_pushcfunction(L, Lslice_libcall); 1147 | lua_setfield(L, -2, "__call"); 1148 | lua_setmetatable(L, -2); 1149 | } 1150 | return 1; 1151 | } 1152 | 1153 | 1154 | /* high level typeinfo/encode/decode routines */ 1155 | 1156 | static pb_Type *lpb_type(pb_State *S, const char *name) { 1157 | pb_Type *t; 1158 | if (name == NULL || *name == '.') 1159 | t = pb_type(S, pb_name(S, name)); 1160 | else { 1161 | pb_Buffer b; 1162 | pb_initbuffer(&b); 1163 | pb_addchar(&b, '.'); 1164 | pb_addslice(&b, pb_slice(name)); 1165 | pb_addchar(&b, '\0'); 1166 | t = pb_type(S, pb_name(S, pb_buffer(&b))); 1167 | pb_resetbuffer(&b); 1168 | } 1169 | return t; 1170 | } 1171 | 1172 | static pb_Field *lpb_checkfield(lua_State *L, int idx, pb_Type *t) { 1173 | int isint, number = (int)lua_tointegerx(L, idx, &isint); 1174 | if (isint) return pb_field(t, number); 1175 | return pb_fname(t, pb_name(default_state(L), luaL_checkstring(L, idx))); 1176 | } 1177 | 1178 | static int Lpb_load(lua_State *L) { 1179 | pb_State *S = default_state(L); 1180 | lpb_SliceEx s = lpb_initext(lpb_checkslice(L, 1)); 1181 | lua_pushboolean(L, pb_load(S, &s.base) == PB_OK); 1182 | lua_pushinteger(L, lpb_offset(&s)); 1183 | return 2; 1184 | } 1185 | 1186 | static int Lpb_loadfile(lua_State *L) { 1187 | pb_State *S = default_state(L); 1188 | const char *filename = luaL_checkstring(L, 1); 1189 | size_t size; 1190 | pb_Buffer b; 1191 | lpb_SliceEx s; 1192 | int ret; 1193 | FILE *fp = fopen(filename, "rb"); 1194 | if (fp == NULL) 1195 | return luaL_fileresult(L, 0, filename); 1196 | pb_initbuffer(&b); 1197 | do { 1198 | void *d = pb_prepbuffsize(&b, BUFSIZ); 1199 | if (d == NULL) { fclose(fp); return luaL_error(L, "out of memory"); } 1200 | size = fread(d, 1, BUFSIZ, fp); 1201 | pb_addsize(&b, size); 1202 | } while (size == BUFSIZ); 1203 | fclose(fp); 1204 | s = lpb_initext(pb_result(&b)); 1205 | ret = pb_load(S, &s.base); 1206 | pb_resetbuffer(&b); 1207 | lua_pushboolean(L, ret == PB_OK); 1208 | lua_pushinteger(L, lpb_offset(&s)); 1209 | return 2; 1210 | } 1211 | 1212 | static int lpb_pushtype(lua_State *L, pb_Type *t) { 1213 | if (t == NULL) return 0; 1214 | lua_pushstring(L, (char*)t->name); 1215 | lua_pushstring(L, (char*)t->basename); 1216 | lua_pushstring(L, t->is_map ? "map" : t->is_enum ? "enum" : "message"); 1217 | return 3; 1218 | } 1219 | 1220 | static int lpb_pushfield(lua_State *L, pb_Type *t, pb_Field *f) { 1221 | if (f == NULL) return 0; 1222 | lua_pushstring(L, (char*)f->name); 1223 | lua_pushinteger(L, f->number); 1224 | lua_pushstring(L, f->type ? 1225 | (char*)f->type->name : 1226 | pb_typename(f->type_id, "")); 1227 | lua_pushstring(L, (char*)f->default_value); 1228 | lua_pushstring(L, f->repeated ? 1229 | (f->packed ? "packed" : "repeated") : 1230 | "optional"); 1231 | if (f->oneof_idx > 0) { 1232 | lua_pushstring(L, (const char*)pb_oneofname(t, f->oneof_idx)); 1233 | lua_pushinteger(L, f->oneof_idx - 1); 1234 | return 7; 1235 | } 1236 | return 5; 1237 | } 1238 | 1239 | static int Lpb_typesiter(lua_State *L) { 1240 | pb_State *S = default_state(L); 1241 | pb_Type *t = lpb_type(S, lua_tostring(L, 2)); 1242 | if ((t == NULL && !lua_isnoneornil(L, 2))) 1243 | return 0; 1244 | pb_nexttype(S, &t); 1245 | return lpb_pushtype(L, t); 1246 | } 1247 | 1248 | static int Lpb_types(lua_State *L) { 1249 | lua_pushcfunction(L, Lpb_typesiter); 1250 | lua_pushnil(L); 1251 | lua_pushnil(L); 1252 | return 3; 1253 | } 1254 | 1255 | static int Lpb_fieldsiter(lua_State *L) { 1256 | pb_State *S = default_state(L); 1257 | pb_Type *t = lpb_type(S, luaL_checkstring(L, 1)); 1258 | pb_Field *f = pb_fname(t, pb_name(S, lua_tostring(L, 2))); 1259 | if ((f == NULL && !lua_isnoneornil(L, 2)) || !pb_nextfield(t, &f)) 1260 | return 0; 1261 | return lpb_pushfield(L, t, f); 1262 | } 1263 | 1264 | static int Lpb_fields(lua_State *L) { 1265 | lua_pushcfunction(L, Lpb_fieldsiter); 1266 | lua_pushvalue(L, 1); 1267 | lua_pushnil(L); 1268 | return 3; 1269 | } 1270 | 1271 | static int Lpb_type(lua_State *L) { 1272 | pb_State *S = default_state(L); 1273 | pb_Type *t = lpb_type(S, luaL_checkstring(L, 1)); 1274 | if (t == NULL || t->is_dead) 1275 | return 0; 1276 | return lpb_pushtype(L, t); 1277 | } 1278 | 1279 | static int Lpb_field(lua_State *L) { 1280 | pb_State *S = default_state(L); 1281 | pb_Type *t = lpb_type(S, luaL_checkstring(L, 1)); 1282 | return lpb_pushfield(L, t, lpb_checkfield(L, 2, t)); 1283 | } 1284 | 1285 | static int Lpb_enum(lua_State *L) { 1286 | lpb_State *LS = default_lstate(L); 1287 | pb_Type *t = lpb_type(&LS->base, luaL_checkstring(L, 1)); 1288 | pb_Field *f = lpb_checkfield(L, 2, t); 1289 | if (f == NULL) return 0; 1290 | if (lua_type(L, 2) == LUA_TNUMBER) 1291 | lua_pushstring(L, (char*)f->name); 1292 | else 1293 | lpb_pushinteger(L, f->number, LS->int64_mode); 1294 | return 1; 1295 | } 1296 | 1297 | static int lpb_pushdefault(lua_State *L, lpb_State *LS, pb_Field *f, int is_proto3) { 1298 | pb_Type *type = f->type; 1299 | int ret = 0; 1300 | char *end; 1301 | if (f == NULL) return 0; 1302 | if (is_proto3 && f->repeated) { lua_newtable(L); return 1; } 1303 | switch (f->type_id) { 1304 | case PB_Tbytes: case PB_Tstring: 1305 | if (f->default_value) 1306 | ret = 1, lua_pushstring(L, (char*)f->default_value); 1307 | else if (is_proto3) 1308 | ret = 1, lua_pushliteral(L, ""); 1309 | break; 1310 | case PB_Tenum: 1311 | if ((f = pb_fname(type, f->default_value)) != NULL) { 1312 | if (LS->enum_as_value) 1313 | ret = 1, lpb_pushinteger(L, f->number, LS->int64_mode); 1314 | else 1315 | ret = 1, lua_pushstring(L, (char*)f->name); 1316 | } 1317 | else if (is_proto3) { 1318 | if ((f = pb_field(type, 0)) == NULL || LS->enum_as_value) 1319 | ret = 1, lua_pushinteger(L, 0); 1320 | else 1321 | ret = 1, lua_pushstring(L, (char*)f->name); 1322 | } 1323 | break; 1324 | case PB_Tmessage: 1325 | return 0; 1326 | case PB_Tbool: 1327 | if (f->default_value) { 1328 | if (f->default_value == pb_name(&LS->base, "true")) 1329 | ret = 1, lua_pushboolean(L, 1); 1330 | else if (f->default_value == pb_name(&LS->base, "false")) 1331 | ret = 1, lua_pushboolean(L, 0); 1332 | } 1333 | else if (is_proto3) ret = 1, lua_pushboolean(L, 0); 1334 | break; 1335 | case PB_Tdouble: case PB_Tfloat: 1336 | if (f->default_value) { 1337 | lua_Number ln = (lua_Number)strtod((char*)f->default_value, &end); 1338 | if ((char*)f->default_value == end) return 0; 1339 | ret = 1, lua_pushnumber(L, ln); 1340 | } 1341 | else if (is_proto3) ret = 1, lua_pushnumber(L, 0.0); 1342 | break; 1343 | 1344 | default: 1345 | if (f->default_value) { 1346 | lua_Integer li = (lua_Integer)strtol((char*)f->default_value, &end, 10); 1347 | if ((char*)f->default_value == end) return 0; 1348 | ret = 1, lpb_pushinteger(L, li, LS->int64_mode); 1349 | } 1350 | else if (is_proto3) ret = 1, lua_pushinteger(L, 0); 1351 | } 1352 | return ret; 1353 | } 1354 | 1355 | static void lpb_pushdefaults(lua_State *L, lpb_State *LS, pb_Type *t) { 1356 | lpb_pushdeftable(L, LS); 1357 | if (lua53_rawgetp(L, -1, t) != LUA_TTABLE) { 1358 | pb_Field *f = NULL; 1359 | lua_pop(L, 1); 1360 | lua_newtable(L); 1361 | while (pb_nextfield(t, &f)) { 1362 | if (!f->repeated && lpb_pushdefault(L, LS, f, t->is_proto3)) 1363 | lua_setfield(L, -2, (char*)f->name); 1364 | } 1365 | lua_pushvalue(L, -1); 1366 | lua_setfield(L, -2, "__index"); 1367 | lua_pushvalue(L, -1); 1368 | lua_rawsetp(L, -3, t); 1369 | } 1370 | lua_remove(L, -2); 1371 | } 1372 | 1373 | static void lpb_cleardefaults(lua_State *L, lpb_State *LS, pb_Type *t) { 1374 | lpb_pushdeftable(L, LS); 1375 | lua_pushnil(L); 1376 | lua_rawsetp(L, -2, t); 1377 | lua_pop(L, 1); 1378 | } 1379 | 1380 | static int Lpb_defaults(lua_State *L) { 1381 | lpb_State *LS = default_lstate(L); 1382 | pb_Type *t = lpb_type(&LS->base, luaL_checkstring(L, 1)); 1383 | int clear = lua_toboolean(L, 2); 1384 | if (t == NULL) luaL_argerror(L, 1, "type not found"); 1385 | lpb_pushdefaults(L, LS, t); 1386 | if (clear) lpb_cleardefaults(L, LS, t); 1387 | return 1; 1388 | } 1389 | 1390 | static int Lpb_hook(lua_State *L) { 1391 | lpb_State *LS = default_lstate(L); 1392 | pb_Type *t = lpb_type(&LS->base, luaL_checkstring(L, 1)); 1393 | int type = lua_type(L, 2); 1394 | if (t == NULL) luaL_argerror(L, 1, "type not found"); 1395 | if (type != LUA_TNONE && type != LUA_TNIL && type != LUA_TFUNCTION) 1396 | typeerror(L, 2, "function"); 1397 | lua_settop(L, 2); 1398 | lpb_pushhooktable(L, LS); 1399 | lua_rawgetp(L, 3, t); 1400 | if (type != LUA_TNONE) { 1401 | lua_pushvalue(L, 2); 1402 | lua_rawsetp(L, 3, t); 1403 | } 1404 | return 1; 1405 | } 1406 | 1407 | static int Lpb_clear(lua_State *L) { 1408 | lpb_State *LS = default_lstate(L); 1409 | pb_State *S = &LS->base; 1410 | pb_Type *t; 1411 | if (lua_isnoneornil(L, 1)) { 1412 | pb_free(S), pb_init(S); 1413 | luaL_unref(L, LUA_REGISTRYINDEX, LS->defs_index); 1414 | LS->defs_index = LUA_NOREF; 1415 | luaL_unref(L, LUA_REGISTRYINDEX, LS->hooks_index); 1416 | LS->hooks_index = LUA_NOREF; 1417 | return 0; 1418 | } 1419 | t = lpb_type(S, luaL_checkstring(L, 1)); 1420 | if (lua_isnoneornil(L, 2)) pb_deltype(S, t); 1421 | else pb_delfield(S, t, lpb_checkfield(L, 2, t)); 1422 | lpb_cleardefaults(L, LS, t); 1423 | return 0; 1424 | } 1425 | 1426 | 1427 | /* protobuf encode */ 1428 | 1429 | typedef struct lpb_Env { 1430 | lua_State *L; 1431 | lpb_State *LS; 1432 | pb_Buffer *b; 1433 | lpb_SliceEx *s; 1434 | } lpb_Env; 1435 | 1436 | static void lpb_encode(lpb_Env *e, pb_Type *t); 1437 | 1438 | static void lpb_checktable(lua_State *L, pb_Field *f) { 1439 | argcheck(L, lua_istable(L, -1), 1440 | 2, "table expected at field '%s', got %s", 1441 | (char*)f->name, luaL_typename(L, -1)); 1442 | } 1443 | 1444 | static void lpbE_enum(lpb_Env *e, pb_Field *f) { 1445 | lua_State *L = e->L; 1446 | pb_Buffer *b = e->b; 1447 | pb_Field *ev; 1448 | int type = lua_type(L, -1); 1449 | if (type == LUA_TNUMBER) 1450 | pb_addvarint64(b, (uint64_t)lua_tonumber(L, -1)); 1451 | else if ((ev = pb_fname(f->type, 1452 | pb_name(&e->LS->base, lua_tostring(L, -1)))) != NULL) 1453 | pb_addvarint32(b, ev->number); 1454 | else if (type != LUA_TSTRING) 1455 | argcheck(L, 0, 2, "number/string expected at field '%s', got %s", 1456 | (char*)f->name, luaL_typename(L, -1)); 1457 | else 1458 | argcheck(L, 0, 2, "can not encode unknown enum '%s' at field '%s'", 1459 | lua_tostring(L, -1), (char*)f->name); 1460 | } 1461 | 1462 | static void lpbE_field(lpb_Env *e, pb_Field *f, size_t *plen) { 1463 | lua_State *L = e->L; 1464 | pb_Buffer *b = e->b; 1465 | size_t len; 1466 | int ltype; 1467 | if (plen) *plen = 0; 1468 | switch (f->type_id) { 1469 | case PB_Tenum: 1470 | lpbE_enum(e, f); 1471 | break; 1472 | 1473 | case PB_Tmessage: 1474 | lpb_checktable(L, f); 1475 | len = pb_bufflen(b); 1476 | lpb_encode(e, f->type); 1477 | lpb_addlength(L, b, len); 1478 | break; 1479 | 1480 | default: 1481 | ltype = lpb_addtype(L, b, -1, f->type_id, plen); 1482 | argcheck(L, ltype == 0, 1483 | 2, "%s expected for field '%s', got %s", 1484 | lua_typename(L, ltype), 1485 | (char*)f->name, luaL_typename(L, -1)); 1486 | } 1487 | } 1488 | 1489 | static void lpbE_tagfield(lpb_Env *e, pb_Field *f, size_t *plen) { 1490 | size_t klen = pb_addvarint32(e->b, 1491 | pb_pair(f->number, pb_wtypebytype(f->type_id))); 1492 | lpbE_field(e, f, plen); 1493 | if (plen && *plen != 0) *plen += klen; 1494 | } 1495 | 1496 | static void lpbE_map(lpb_Env *e, pb_Field *f) { 1497 | lua_State *L = e->L; 1498 | pb_Field *kf = pb_field(f->type, 1); 1499 | pb_Field *vf = pb_field(f->type, 2); 1500 | if (kf == NULL || vf == NULL) return; 1501 | lpb_checktable(L, f); 1502 | lua_pushnil(L); 1503 | while (lua_next(L, -2)) { 1504 | size_t len, ignoredlen; 1505 | pb_addvarint32(e->b, pb_pair(f->number, PB_TBYTES)); 1506 | len = pb_bufflen(e->b); 1507 | lua_pushvalue(L, -2); 1508 | lpbE_tagfield(e, kf, &ignoredlen); 1509 | e->b->size -= ignoredlen; 1510 | lua_pop(L, 1); 1511 | lpbE_tagfield(e, vf, &ignoredlen); 1512 | e->b->size -= ignoredlen; 1513 | lua_pop(L, 1); 1514 | lpb_addlength(L, e->b, len); 1515 | } 1516 | } 1517 | 1518 | static void lpbE_repeated(lpb_Env *e, pb_Field *f) { 1519 | lua_State *L = e->L; 1520 | pb_Buffer *b = e->b; 1521 | int i; 1522 | lpb_checktable(L, f); 1523 | if (f->packed) { 1524 | size_t len; 1525 | pb_addvarint32(b, pb_pair(f->number, PB_TBYTES)); 1526 | len = pb_bufflen(b); 1527 | for (i = 1; lua53_rawgeti(L, -1, i) != LUA_TNIL; ++i) { 1528 | lpbE_field(e, f, NULL); 1529 | lua_pop(L, 1); 1530 | } 1531 | lpb_addlength(L, b, len); 1532 | } 1533 | else { 1534 | for (i = 1; lua53_rawgeti(L, -1, i) != LUA_TNIL; ++i) { 1535 | lpbE_tagfield(e, f, NULL); 1536 | lua_pop(L, 1); 1537 | } 1538 | } 1539 | lua_pop(L, 1); 1540 | } 1541 | 1542 | static void lpb_encode(lpb_Env *e, pb_Type *t) { 1543 | lua_State *L = e->L; 1544 | luaL_checkstack(L, 3, "message too many levels"); 1545 | lua_pushnil(L); 1546 | while (lua_next(L, -2)) { 1547 | if (lua_type(L, -2) == LUA_TSTRING) { 1548 | pb_Field *f = 1549 | pb_fname(t, pb_name(&e->LS->base, lua_tostring(L, -2))); 1550 | if (f == NULL) 1551 | /* skip */; 1552 | else if (f->type && f->type->is_map) 1553 | lpbE_map(e, f); 1554 | else if (f->repeated) 1555 | lpbE_repeated(e, f); 1556 | else if (!f->type || !f->type->is_dead) { 1557 | size_t ignoredlen; 1558 | lpbE_tagfield(e, f, &ignoredlen); 1559 | if (t->is_proto3 && !f->oneof_idx) 1560 | e->b->size -= ignoredlen; 1561 | } 1562 | } 1563 | lua_pop(L, 1); 1564 | } 1565 | } 1566 | 1567 | static int Lpb_encode(lua_State *L) { 1568 | lpb_State *LS = default_lstate(L); 1569 | pb_Type *t = lpb_type(&LS->base, luaL_checkstring(L, 1)); 1570 | lpb_Env e; 1571 | argcheck(L, t != NULL, 1, "type '%s' does not exists", lua_tostring(L, 1)); 1572 | luaL_checktype(L, 2, LUA_TTABLE); 1573 | e.L = L, e.LS = LS, e.b = test_buffer(L, 3); 1574 | if (e.b == NULL) pb_resetbuffer(e.b = &LS->buffer); 1575 | lua_pushvalue(L, 2); 1576 | lpb_encode(&e, t); 1577 | if (e.b != &LS->buffer) 1578 | lua_settop(L, 3); 1579 | else { 1580 | lua_pushlstring(L, e.b->buff, e.b->size); 1581 | pb_resetbuffer(e.b); 1582 | } 1583 | return 1; 1584 | } 1585 | 1586 | 1587 | /* protobuf decode */ 1588 | 1589 | #define lpb_withinput(e, ns, stmt) ((e)->s = (ns), (stmt), (e)->s = s) 1590 | 1591 | static int lpbD_message(lpb_Env *e, pb_Type *t); 1592 | 1593 | static void lpb_usehooks(lua_State *L, lpb_State *LS, pb_Type *t) { 1594 | lpb_pushhooktable(L, LS); 1595 | if (lua53_rawgetp(L, -1, t) != LUA_TNIL) { 1596 | lua_pushvalue(L, -3); 1597 | lua_call(L, 1, 1); 1598 | if (!lua_isnil(L, -1)) { 1599 | lua_pushvalue(L, -1); 1600 | lua_replace(L, -4); 1601 | } 1602 | } 1603 | lua_pop(L, 2); 1604 | } 1605 | 1606 | static void lpb_pushtypetable(lua_State *L, lpb_State *LS, pb_Type *t) { 1607 | pb_Field *f = NULL; 1608 | int mode = t ? LS->default_mode : LPB_NODEF; 1609 | lua_newtable(L); 1610 | switch (t && t->is_proto3 && mode == LPB_DEFDEF ? LPB_COPYDEF : mode) { 1611 | case LPB_COPYDEF: 1612 | while (pb_nextfield(t, &f)) 1613 | if (!f->oneof_idx && lpb_pushdefault(L, LS, f, t->is_proto3)) 1614 | lua_setfield(L, -2, (char*)f->name); 1615 | break; 1616 | case LPB_METADEF: 1617 | while (pb_nextfield(t, &f)) 1618 | if (f->repeated && lpb_pushdefault(L, LS, f, t->is_proto3)) 1619 | lua_setfield(L, -2, (char*)f->name); 1620 | lpb_pushdefaults(L, LS, t); 1621 | lua_setmetatable(L, -2); 1622 | break; 1623 | default: /* no default value */ 1624 | break; 1625 | } 1626 | } 1627 | 1628 | static void lpb_fetchtable(lpb_Env *e, pb_Field *f, pb_Type *t) { 1629 | lua_State *L = e->L; 1630 | if (lua53_getfield(L, -1, (char*)f->name) == LUA_TNIL) { 1631 | lua_pop(L, 1); 1632 | lpb_pushtypetable(L, e->LS, t); 1633 | lua_pushvalue(L, -1); 1634 | lua_setfield(L, -3, (char*)f->name); 1635 | } 1636 | } 1637 | 1638 | static int lpbD_mismatch(lua_State *L, pb_Field *f, lpb_SliceEx *s, uint32_t tag) { 1639 | return luaL_error(L, 1640 | "type mismatch for field '%s' at offset %d, " 1641 | "%s expected for type %s, got %s", 1642 | (char*)f->name, 1643 | lpb_offset(s), 1644 | pb_wtypename(pb_wtypebytype(f->type_id), NULL), 1645 | pb_typename(f->type_id, NULL), 1646 | pb_wtypename(pb_gettype(tag), NULL)); 1647 | } 1648 | 1649 | static void lpbD_field(lpb_Env *e, pb_Field *f, uint32_t tag) { 1650 | lua_State *L = e->L; 1651 | lpb_SliceEx sv, *s = e->s; 1652 | pb_Field *ev = NULL; 1653 | uint64_t u64; 1654 | 1655 | if (!f->packed && pb_wtypebytype(f->type_id) != (int)pb_gettype(tag)) 1656 | lpbD_mismatch(L, f, s, tag); 1657 | 1658 | switch (f->type_id) { 1659 | case PB_Tenum: 1660 | if (pb_readvarint64(&s->base, &u64) == 0) 1661 | luaL_error(L, "invalid varint value at offset %d", lpb_offset(s)); 1662 | if (!default_lstate(L)->enum_as_value) 1663 | ev = pb_field(f->type, (int32_t)u64); 1664 | if (ev) lua_pushstring(L, (char*)ev->name); 1665 | else lpb_pushinteger(L, (lua_Integer)u64, default_lstate(L)->int64_mode); 1666 | if (e->LS->use_hooks) lpb_usehooks(L, e->LS, f->type); 1667 | break; 1668 | 1669 | case PB_Tmessage: 1670 | lpb_readbytes(L, s, &sv); 1671 | if (f->type == NULL || f->type->is_dead) 1672 | lua_pushnil(L); 1673 | else { 1674 | lpb_pushtypetable(L, e->LS, f->type); 1675 | lpb_withinput(e, &sv, lpbD_message(e, f->type)); 1676 | } 1677 | break; 1678 | 1679 | default: 1680 | lpb_readtype(L, e->LS, f->type_id, s); 1681 | } 1682 | } 1683 | 1684 | static void lpbD_map(lpb_Env *e, pb_Field *f) { 1685 | lua_State *L = e->L; 1686 | lpb_SliceEx p, *s = e->s; 1687 | int mask = 0, top = lua_gettop(L) + 1; 1688 | uint32_t tag; 1689 | lpb_fetchtable(e, f, NULL); 1690 | lpb_readbytes(L, s, &p); 1691 | if (f->type == NULL) return; 1692 | lua_pushnil(L); 1693 | lua_pushnil(L); 1694 | while (pb_readvarint32(&p.base, &tag)) { 1695 | int n = pb_gettag(tag); 1696 | if (n == 1 || n == 2) { 1697 | mask |= n; 1698 | lpb_withinput(e, &p, lpbD_field(e, pb_field(f->type, n), tag)); 1699 | lua_replace(L, top + n); 1700 | } 1701 | } 1702 | if ((mask & 1) == 0 && lpb_pushdefault(L, e->LS, pb_field(f->type, 1), 1)) 1703 | lua_replace(L, top + 1), mask |= 1; 1704 | if ((mask & 2) == 0 && lpb_pushdefault(L, e->LS, pb_field(f->type, 2), 1)) 1705 | lua_replace(L, top + 2), mask |= 2; 1706 | if (mask == 3) lua_rawset(L, -3); 1707 | else lua_pop(L, 2); 1708 | lua_pop(L, 1); 1709 | } 1710 | 1711 | static void lpbD_repeated(lpb_Env *e, pb_Field *f, uint32_t tag) { 1712 | lua_State *L = e->L; 1713 | lpb_fetchtable(e, f, NULL); 1714 | if (f->packed && pb_gettype(tag) == PB_TBYTES) { 1715 | int len = (int)lua_rawlen(L, -1); 1716 | lpb_SliceEx p, *s = e->s; 1717 | lpb_readbytes(L, s, &p); 1718 | while (p.base.p < p.base.end) { 1719 | lpb_withinput(e, &p, lpbD_field(e, f, tag)); 1720 | lua_rawseti(L, -2, ++len); 1721 | } 1722 | } 1723 | else { 1724 | lpbD_field(e, f, tag); 1725 | lua_rawseti(L, -2, (lua_Integer)lua_rawlen(L, -2) + 1); 1726 | } 1727 | lua_pop(L, 1); 1728 | } 1729 | 1730 | static int lpbD_message(lpb_Env *e, pb_Type *t) { 1731 | lua_State *L = e->L; 1732 | lpb_SliceEx *s = e->s; 1733 | uint32_t tag; 1734 | while (pb_readvarint32(&s->base, &tag)) { 1735 | pb_Field *f = pb_field(t, pb_gettag(tag)); 1736 | if (f == NULL) 1737 | pb_skipvalue(&s->base, tag); 1738 | else if (f->type && f->type->is_map) 1739 | lpbD_map(e, f); 1740 | else if (f->repeated) 1741 | lpbD_repeated(e, f, tag); 1742 | else { 1743 | lua_pushstring(L, (char*)f->name); 1744 | lpbD_field(e, f, tag); 1745 | lua_rawset(L, -3); 1746 | } 1747 | } 1748 | if (e->LS->use_hooks) lpb_usehooks(L, e->LS, t); 1749 | return 1; 1750 | } 1751 | 1752 | static int lpb_decode(lua_State *L, lpb_SliceEx s, int start) { 1753 | lpb_State *LS = default_lstate(L); 1754 | pb_Type *t = lpb_type(&LS->base, luaL_checkstring(L, 1)); 1755 | lpb_Env e; 1756 | argcheck(L, t != NULL, 1, "type '%s' does not exists", lua_tostring(L, 1)); 1757 | lua_settop(L, start); 1758 | if (!lua_istable(L, start)) { 1759 | lua_pop(L, 1); 1760 | lpb_pushtypetable(L, LS, t); 1761 | } 1762 | e.L = L, e.LS = LS, e.s = &s; 1763 | return lpbD_message(&e, t); 1764 | } 1765 | 1766 | static int Lpb_decode(lua_State *L) { 1767 | return lpb_decode(L, lua_isnoneornil(L, 2) ? 1768 | lpb_initext(pb_lslice(NULL, 0)) : 1769 | lpb_initext(lpb_checkslice(L, 2)), 3); 1770 | } 1771 | 1772 | /* pb module interface */ 1773 | 1774 | static int Lpb_option(lua_State *L) { 1775 | #define OPTS(X) \ 1776 | X(0, enum_as_name, LS->enum_as_value = 0) \ 1777 | X(1, enum_as_value, LS->enum_as_value = 1) \ 1778 | X(2, int64_as_number, LS->int64_mode = LPB_NUMBER) \ 1779 | X(3, int64_as_string, LS->int64_mode = LPB_STRING) \ 1780 | X(4, int64_as_hexstring, LS->int64_mode = LPB_HEXSTRING) \ 1781 | X(5, auto_default_values, LS->default_mode = LPB_DEFDEF) \ 1782 | X(6, no_default_values, LS->default_mode = LPB_NODEF) \ 1783 | X(7, use_default_values, LS->default_mode = LPB_COPYDEF) \ 1784 | X(8, use_default_metatable, LS->default_mode = LPB_METADEF) \ 1785 | X(9, enable_hooks, LS->use_hooks = 1) \ 1786 | X(10, disable_hooks, LS->use_hooks = 0) \ 1787 | 1788 | static const char *opts[] = { 1789 | #define X(ID,NAME,CODE) #NAME, 1790 | OPTS(X) 1791 | #undef X 1792 | NULL 1793 | }; 1794 | lpb_State *LS = default_lstate(L); 1795 | switch (luaL_checkoption(L, 1, NULL, opts)) { 1796 | #define X(ID,NAME,CODE) case ID: CODE; break; 1797 | OPTS(X) 1798 | #undef X 1799 | } 1800 | return 0; 1801 | #undef OPTS 1802 | } 1803 | 1804 | LUALIB_API int luaopen_pb(lua_State *L) { 1805 | luaL_Reg libs[] = { 1806 | { "pack", Lbuf_pack }, 1807 | { "unpack", Lslice_unpack }, 1808 | #define ENTRY(name) { #name, Lpb_##name } 1809 | ENTRY(clear), 1810 | ENTRY(load), 1811 | ENTRY(loadfile), 1812 | ENTRY(encode), 1813 | ENTRY(decode), 1814 | ENTRY(types), 1815 | ENTRY(fields), 1816 | ENTRY(type), 1817 | ENTRY(field), 1818 | ENTRY(enum), 1819 | ENTRY(defaults), 1820 | ENTRY(hook), 1821 | ENTRY(tohex), 1822 | ENTRY(result), 1823 | ENTRY(option), 1824 | ENTRY(state), 1825 | #undef ENTRY 1826 | { NULL, NULL } 1827 | }; 1828 | luaL_Reg meta[] = { 1829 | { "__gc", Lpb_delete }, 1830 | { "setdefault", Lpb_state }, 1831 | { NULL, NULL } 1832 | }; 1833 | if (luaL_newmetatable(L, PB_STATE)) { 1834 | luaL_setfuncs(L, meta, 0); 1835 | lua_pushvalue(L, -1); 1836 | lua_setfield(L, -2, "__index"); 1837 | } 1838 | luaL_newlib(L, libs); 1839 | return 1; 1840 | } 1841 | 1842 | static int Lpb_decode_unsafe(lua_State *L) { 1843 | const char *data = (const char *)lua_touserdata(L, 2); 1844 | size_t size = (size_t)luaL_checkinteger(L, 3); 1845 | if (data == NULL) typeerror(L, 2, "userdata"); 1846 | return lpb_decode(L, lpb_initext(pb_lslice(data, size)), 4); 1847 | } 1848 | 1849 | LUALIB_API int luaopen_pb_unsafe(lua_State *L) { 1850 | luaL_Reg libs[] = { 1851 | { "decode", Lpb_decode_unsafe }, 1852 | { NULL, NULL } 1853 | }; 1854 | luaL_newlib(L, libs); 1855 | return 1; 1856 | } 1857 | 1858 | } 1859 | 1860 | // Renable warning "interaction between '_setjmp' and C++ object destruction is non-portable" 1861 | #ifdef _MSC_VER 1862 | #pragma warning(pop) 1863 | #endif --------------------------------------------------------------------------------