DCCL v4
Loading...
Searching...
No Matches
pb.h
1#ifndef pb_h
2#define pb_h
3
4#ifndef PB_NS_BEGIN
5# ifdef __cplusplus
6# define PB_NS_BEGIN extern "C" {
7# define PB_NS_END }
8# else
9# define PB_NS_BEGIN
10# define PB_NS_END
11# endif
12#endif /* PB_NS_BEGIN */
13
14#ifndef PB_STATIC
15# if __GNUC__
16# define PB_STATIC static __attribute((unused))
17# else
18# define PB_STATIC static
19# endif
20#endif
21
22#ifdef PB_STATIC_API
23# ifndef PB_IMPLEMENTATION
24# define PB_IMPLEMENTATION
25# endif
26# define PB_API PB_STATIC
27#endif
28
29#if !defined(PB_API) && defined(_WIN32)
30# ifdef PB_IMPLEMENTATION
31# define PB_API __declspec(dllexport)
32# else
33# define PB_API __declspec(dllimport)
34# endif
35#endif
36
37#ifndef PB_API
38# define PB_API extern
39#endif
40
41#if defined(_MSC_VER) || defined(__UNIXOS2__) || defined(__SOL64__)
42typedef unsigned char uint8_t;
43typedef signed char int8_t;
44typedef unsigned short uint16_t;
45typedef signed short int16_t;
46typedef unsigned int uint32_t;
47typedef signed int int32_t;
48typedef unsigned long long uint64_t;
49typedef signed long long int64_t;
50
51#ifndef INT64_MIN
52# define INT64_MIN LLONG_MIN
53#endif
54
55#ifndef INT64_MAX
56# define INT64_MAX LLONG_MAX
57#endif
58
59#elif defined(__SCO__) || defined(__USLC__) || defined(__MINGW32__)
60# include <stdint.h>
61#else
62# include <inttypes.h>
63# if (defined(__sun__) || defined(__digital__))
64# if defined(__STDC__) && (defined(__arch64__) || defined(_LP64))
65typedef unsigned long int uint64_t;
66typedef signed long int int64_t;
67# else
68typedef unsigned long long uint64_t;
69typedef signed long long int64_t;
70# endif /* LP64 */
71# endif /* __sun__ || __digital__ */
72#endif
73
74#include <stddef.h>
75#include <limits.h>
76
77PB_NS_BEGIN
78
79
80/* types */
81
82#define PB_WIRETYPES(X) /* X(id, name, fmt) */\
83 X(VARINT, "varint", 'v') X(64BIT, "64bit", 'q') X(BYTES, "bytes", 's') \
84 X(GSTART, "gstart", '!') X(GEND, "gend", '!') X(32BIT, "32bit", 'd') \
85
86#define PB_TYPES(X) /* X(name, type, fmt) */\
87 X(double, double, 'F') X(float, float, 'f') \
88 X(int64, int64_t, 'I') X(uint64, uint64_t, 'U') \
89 X(int32, int32_t, 'i') X(fixed64, uint64_t, 'X') \
90 X(fixed32, uint32_t, 'x') X(bool, int, 'b') \
91 X(string, pb_Slice, 't') X(group, pb_Slice, 'g') \
92 X(message, pb_Slice, 'S') X(bytes, pb_Slice, 's') \
93 X(uint32, uint32_t, 'u') X(enum, int32_t, 'v') \
94 X(sfixed32, int32_t, 'y') X(sfixed64, int64_t, 'Y') \
95 X(sint32, int32_t, 'j') X(sint64, int64_t, 'J') \
96
97typedef enum pb_WireType {
98#define X(id,name,fmt) PB_T##id,
99 PB_WIRETYPES(X)
100#undef X
101 PB_TWIRECOUNT
102} pb_WireType;
103
104typedef enum pb_FieldType {
105 PB_TNONE,
106#define X(name,type,fmt) PB_T##name,
107 PB_TYPES(X)
108#undef X
109 PB_TYPECOUNT
110} pb_FieldType;
111
112
113/* conversions */
114
115PB_API uint64_t pb_expandsig (uint32_t v);
116PB_API uint32_t pb_encode_sint32 ( int32_t v);
117PB_API int32_t pb_decode_sint32 (uint32_t v);
118PB_API uint64_t pb_encode_sint64 ( int64_t v);
119PB_API int64_t pb_decode_sint64 (uint64_t v);
120PB_API uint32_t pb_encode_float (float v);
121PB_API float pb_decode_float (uint32_t v);
122PB_API uint64_t pb_encode_double (double v);
123PB_API double pb_decode_double (uint64_t v);
124
125
126/* decode */
127
128typedef struct pb_Slice { const char *p, *start, *end; } pb_Slice;
129#define pb_gettype(v) ((v) & 7)
130#define pb_gettag(v) ((v) >> 3)
131#define pb_pair(tag,type) ((tag) << 3 | ((type) & 7))
132
133PB_API pb_Slice pb_slice (const char *p);
134PB_API pb_Slice pb_lslice (const char *p, size_t len);
135
136PB_API size_t pb_pos (const pb_Slice s);
137PB_API size_t pb_len (const pb_Slice s);
138
139PB_API size_t pb_readvarint32 (pb_Slice *s, uint32_t *pv);
140PB_API size_t pb_readvarint64 (pb_Slice *s, uint64_t *pv);
141PB_API size_t pb_readfixed32 (pb_Slice *s, uint32_t *pv);
142PB_API size_t pb_readfixed64 (pb_Slice *s, uint64_t *pv);
143
144PB_API size_t pb_readslice (pb_Slice *s, size_t len, pb_Slice *pv);
145PB_API size_t pb_readbytes (pb_Slice *s, pb_Slice *pv);
146PB_API size_t pb_readgroup (pb_Slice *s, uint32_t tag, pb_Slice *pv);
147
148PB_API size_t pb_skipvarint (pb_Slice *s);
149PB_API size_t pb_skipbytes (pb_Slice *s);
150PB_API size_t pb_skipslice (pb_Slice *s, size_t len);
151PB_API size_t pb_skipvalue (pb_Slice *s, uint32_t tag);
152
153PB_API const char *pb_wtypename (int wiretype, const char *def);
154PB_API const char *pb_typename (int type, const char *def);
155
156PB_API int pb_typebyname (const char *name, int def);
157PB_API int pb_wtypebyname (const char *name, int def);
158PB_API int pb_wtypebytype (int type);
159
160
161/* encode */
162
163#define PB_SSO_SIZE (sizeof(pb_HeapBuffer))
164
165typedef struct pb_HeapBuffer {
166 unsigned capacity;
167 char *buff;
169
170typedef struct pb_Buffer {
171 unsigned size : sizeof(unsigned)*CHAR_BIT - 1;
172 unsigned heap : 1;
173 union {
174 char buff[PB_SSO_SIZE];
176 } u;
177} pb_Buffer;
178
179#define pb_onheap(b) ((b)->heap)
180#define pb_bufflen(b) ((b)->size)
181#define pb_buffer(b) (pb_onheap(b) ? (b)->u.h.buff : (b)->u.buff)
182#define pb_addsize(b,sz) ((void)((b)->size += (unsigned)(sz)))
183
184PB_API void pb_initbuffer (pb_Buffer *b);
185PB_API void pb_resetbuffer (pb_Buffer *b);
186PB_API char *pb_prepbuffsize (pb_Buffer *b, size_t len);
187
188PB_API pb_Slice pb_result (const pb_Buffer *b);
189
190PB_API size_t pb_addvarint32 (pb_Buffer *b, uint32_t v);
191PB_API size_t pb_addvarint64 (pb_Buffer *b, uint64_t v);
192PB_API size_t pb_addfixed32 (pb_Buffer *b, uint32_t v);
193PB_API size_t pb_addfixed64 (pb_Buffer *b, uint64_t v);
194
195PB_API size_t pb_addslice (pb_Buffer *b, pb_Slice s);
196PB_API size_t pb_addbytes (pb_Buffer *b, pb_Slice s);
197PB_API size_t pb_addlength (pb_Buffer *b, size_t len, size_t prealloc);
198
199
200/* type info database state and name table */
201
202typedef struct pb_State pb_State;
203typedef struct pb_Name pb_Name;
204typedef struct pb_Cache pb_Cache;
205
206PB_API void pb_init (pb_State *S);
207PB_API void pb_free (pb_State *S);
208
209PB_API pb_Name *pb_newname (pb_State *S, pb_Slice s, pb_Cache *cache);
210PB_API void pb_delname (pb_State *S, pb_Name *name);
211PB_API pb_Name *pb_usename (pb_Name *name);
212
213PB_API const pb_Name *pb_name (const pb_State *S, pb_Slice s, pb_Cache *cache);
214
215
216/* type info */
217
218typedef struct pb_Type pb_Type;
219typedef struct pb_Field pb_Field;
220
221#define PB_OK 0
222#define PB_ERROR 1
223#define PB_ENOMEM 2
224
225PB_API int pb_load (pb_State *S, pb_Slice *s);
226
227PB_API pb_Type *pb_newtype (pb_State *S, pb_Name *tname);
228PB_API void pb_deltype (pb_State *S, pb_Type *t);
229PB_API pb_Field *pb_newfield (pb_State *S, pb_Type *t, pb_Name *fname, int32_t number);
230PB_API void pb_delfield (pb_State *S, pb_Type *t, pb_Field *f);
231
232PB_API const pb_Type *pb_type (const pb_State *S, const pb_Name *tname);
233PB_API const pb_Field *pb_fname (const pb_Type *t, const pb_Name *tname);
234PB_API const pb_Field *pb_field (const pb_Type *t, int32_t number);
235
236PB_API const pb_Name *pb_oneofname (const pb_Type *t, int oneof_index);
237
238PB_API int pb_nexttype (const pb_State *S, const pb_Type **ptype);
239PB_API int pb_nextfield (const pb_Type *t, const pb_Field **pfield);
240
241
242/* util: memory pool */
243
244#define PB_POOLSIZE 4096
245
246typedef struct pb_Pool {
247 void *pages;
248 void *freed;
249 size_t obj_size;
250} pb_Pool;
251
252PB_API void pb_initpool (pb_Pool *pool, size_t obj_size);
253PB_API void pb_freepool (pb_Pool *pool);
254
255PB_API void *pb_poolalloc (pb_Pool *pool);
256PB_API void pb_poolfree (pb_Pool *pool, void *obj);
257
258/* util: hash table */
259
260typedef struct pb_Table pb_Table;
261typedef struct pb_Entry pb_Entry;
262typedef ptrdiff_t pb_Key;
263
264PB_API void pb_inittable (pb_Table *t, size_t entrysize);
265PB_API void pb_freetable (pb_Table *t);
266
267PB_API size_t pb_resizetable (pb_Table *t, size_t size);
268
269PB_API pb_Entry *pb_gettable (const pb_Table *t, pb_Key key);
270PB_API pb_Entry *pb_settable (pb_Table *t, pb_Key key);
271
272PB_API int pb_nextentry (const pb_Table *t, const pb_Entry **pentry);
273
274struct pb_Table {
275 unsigned size;
276 unsigned lastfree;
277 unsigned entry_size : sizeof(unsigned)*CHAR_BIT - 1;
278 unsigned has_zero : 1;
279 pb_Entry *hash;
280};
281
282struct pb_Entry {
283 ptrdiff_t next;
284 pb_Key key;
285};
286
287
288/* fields */
289
290#define PB_CACHE_SIZE (53)
291
292typedef struct pb_NameEntry {
293 struct pb_NameEntry *next;
294 unsigned hash : 32;
295 unsigned length : 16;
296 unsigned refcount : 16;
298
299typedef struct pb_NameTable {
300 size_t size;
301 size_t count;
302 pb_NameEntry **hash;
304
305typedef struct pb_CacheSlot {
306 const char *name;
307 unsigned hash;
309
310struct pb_Cache {
311 pb_CacheSlot slots[PB_CACHE_SIZE][2];
312 unsigned hash;
313};
314
315struct pb_State {
316 pb_NameTable nametable;
317 pb_Table types;
318 pb_Pool typepool;
319 pb_Pool fieldpool;
320};
321
322struct pb_Field {
323 pb_Name *name;
324 pb_Type *type;
325 pb_Name *default_value;
326 int32_t number;
327 int32_t sort_index;
328 unsigned oneof_idx : 24;
329 unsigned type_id : 5; /* PB_T* enum */
330 unsigned repeated : 1;
331 unsigned packed : 1;
332 unsigned scalar : 1;
333};
334
335struct pb_Type {
336 pb_Name *name;
337 const char *basename;
338 pb_Field **field_sort;
339 pb_Table field_tags;
340 pb_Table field_names;
341 pb_Table oneof_index;
342 unsigned oneof_count; /* extra field count from oneof entries */
343 unsigned oneof_field; /* extra field in oneof declarations */
344 unsigned field_count : 28;
345 unsigned is_enum : 1;
346 unsigned is_map : 1;
347 unsigned is_proto3 : 1;
348 unsigned is_dead : 1;
349};
350
351
352PB_NS_END
353
354#endif /* pb_h */
355
356
357#if defined(PB_IMPLEMENTATION) && !defined(pb_implemented)
358#define pb_implemented
359
360#define PB_MAX_SIZET ((unsigned)~0 - 100)
361#define PB_MAX_HASHSIZE ((unsigned)~0 - 100)
362#define PB_MIN_STRTABLE_SIZE 16
363#define PB_MIN_HASHTABLE_SIZE 8
364#define PB_HASHLIMIT 5
365
366#include <assert.h>
367#include <stdlib.h>
368#include <string.h>
369
370PB_NS_BEGIN
371
372
373/* conversions */
374
375PB_API uint32_t pb_encode_sint32(int32_t value)
376{ return ((uint32_t)value << 1) ^ -(value < 0); }
377
378PB_API int32_t pb_decode_sint32(uint32_t value)
379{ return (value >> 1) ^ -(int32_t)(value & 1); }
380
381PB_API uint64_t pb_encode_sint64(int64_t value)
382{ return ((uint64_t)value << 1) ^ -(value < 0); }
383
384PB_API int64_t pb_decode_sint64(uint64_t value)
385{ return (value >> 1) ^ -(int64_t)(value & 1); }
386
387PB_API uint64_t pb_expandsig(uint32_t value)
388{ uint64_t m = (uint64_t)1U << 31; return (value ^ m) - m; }
389
390PB_API uint32_t pb_encode_float(float value)
391{ union { uint32_t u32; float f; } u; u.f = value; return u.u32; }
392
393PB_API float pb_decode_float(uint32_t value)
394{ union { uint32_t u32; float f; } u; u.u32 = value; return u.f; }
395
396PB_API uint64_t pb_encode_double(double value)
397{ union { uint64_t u64; double d; } u; u.d = value; return u.u64; }
398
399PB_API double pb_decode_double(uint64_t value)
400{ union { uint64_t u64; double d; } u; u.u64 = value; return u.d; }
401
402
403/* decode */
404
405PB_API pb_Slice pb_slice(const char *s)
406{ return s ? pb_lslice(s, strlen(s)) : pb_lslice(NULL, 0); }
407
408PB_API size_t pb_pos(const pb_Slice s) { return s.p - s.start; }
409PB_API size_t pb_len(const pb_Slice s) { return s.end - s.p; }
410
411static size_t pb_readvarint_slow(pb_Slice *s, uint64_t *pv) {
412 const char *p = s->p;
413 uint64_t n = 0;
414 int i = 0;
415 while (s->p < s->end && i < 10) {
416 int b = *s->p++;
417 n |= ((uint64_t)b & 0x7F) << (7*i++);
418 if ((b & 0x80) == 0) {
419 *pv = n;
420 return i;
421 }
422 }
423 s->p = p;
424 return 0;
425}
426
427static size_t pb_readvarint32_fallback(pb_Slice *s, uint32_t *pv) {
428 const uint8_t *p = (const uint8_t*)s->p, *o = p;
429 uint32_t b, n;
430 for (;;) {
431 n = *p++ - 0x80, n += (b = *p++) << 7; if (!(b & 0x80)) break;
432 n -= 0x80 << 7, n += (b = *p++) << 14; if (!(b & 0x80)) break;
433 n -= 0x80 << 14, n += (b = *p++) << 21; if (!(b & 0x80)) break;
434 n -= 0x80 << 21, n += (b = *p++) << 28; if (!(b & 0x80)) break;
435 /* n -= 0x80 << 28; */
436 if (!(*p++ & 0x80)) break;
437 if (!(*p++ & 0x80)) break;
438 if (!(*p++ & 0x80)) break;
439 if (!(*p++ & 0x80)) break;
440 if (!(*p++ & 0x80)) break;
441 return 0;
442 }
443 *pv = n;
444 s->p = (const char*)p;
445 return p - o;
446}
447
448static size_t pb_readvarint64_fallback(pb_Slice *s, uint64_t *pv) {
449 const uint8_t *p = (const uint8_t*)s->p, *o = p;
450 uint32_t b, n1, n2 = 0, n3 = 0;
451 for (;;) {
452 n1 = *p++ - 0x80, n1 += (b = *p++) << 7; if (!(b & 0x80)) break;
453 n1 -= 0x80 << 7, n1 += (b = *p++) << 14; if (!(b & 0x80)) break;
454 n1 -= 0x80 << 14, n1 += (b = *p++) << 21; if (!(b & 0x80)) break;
455 n1 -= 0x80 << 21, n2 += (b = *p++) ; if (!(b & 0x80)) break;
456 n2 -= 0x80 , n2 += (b = *p++) << 7; if (!(b & 0x80)) break;
457 n2 -= 0x80 << 7, n2 += (b = *p++) << 14; if (!(b & 0x80)) break;
458 n2 -= 0x80 << 14, n2 += (b = *p++) << 21; if (!(b & 0x80)) break;
459 n2 -= 0x80 << 21, n3 += (b = *p++) ; if (!(b & 0x80)) break;
460 n3 -= 0x80 , n3 += (b = *p++) << 7; if (!(b & 0x80)) break;
461 return 0;
462 }
463 *pv = n1 | ((uint64_t)n2 << 28) | ((uint64_t)n3 << 56);
464 s->p = (const char*)p;
465 return p - o;
466}
467
468PB_API pb_Slice pb_lslice(const char *s, size_t len) {
469 pb_Slice slice;
470 slice.start = slice.p = s;
471 slice.end = s + len;
472 return slice;
473}
474
475PB_API size_t pb_readvarint32(pb_Slice *s, uint32_t *pv) {
476 uint64_t u64;
477 size_t ret;
478 if (s->p >= s->end) return 0;
479 if (!(*s->p & 0x80)) return *pv = *s->p++, 1;
480 if (pb_len(*s) >= 10 || !(s->end[-1] & 0x80))
481 return pb_readvarint32_fallback(s, pv);
482 if ((ret = pb_readvarint_slow(s, &u64)) != 0)
483 *pv = (uint32_t)u64;
484 return ret;
485}
486
487PB_API size_t pb_readvarint64(pb_Slice *s, uint64_t *pv) {
488 if (s->p >= s->end) return 0;
489 if (!(*s->p & 0x80)) return *pv = *s->p++, 1;
490 if (pb_len(*s) >= 10 || !(s->end[-1] & 0x80))
491 return pb_readvarint64_fallback(s, pv);
492 return pb_readvarint_slow(s, pv);
493}
494
495PB_API size_t pb_readfixed32(pb_Slice *s, uint32_t *pv) {
496 int i;
497 uint32_t n = 0;
498 if (s->p + 4 > s->end)
499 return 0;
500 for (i = 3; i >= 0; --i) {
501 n <<= 8;
502 n |= s->p[i] & 0xFF;
503 }
504 s->p += 4;
505 *pv = n;
506 return 4;
507}
508
509PB_API size_t pb_readfixed64(pb_Slice *s, uint64_t *pv) {
510 int i;
511 uint64_t n = 0;
512 if (s->p + 8 > s->end)
513 return 0;
514 for (i = 7; i >= 0; --i) {
515 n <<= 8;
516 n |= s->p[i] & 0xFF;
517 }
518 s->p += 8;
519 *pv = n;
520 return 8;
521}
522
523PB_API size_t pb_readslice(pb_Slice *s, size_t len, pb_Slice *pv) {
524 if (pb_len(*s) < len)
525 return 0;
526 pv->start = s->start;
527 pv->p = s->p;
528 pv->end = s->p + len;
529 s->p = pv->end;
530 return len;
531}
532
533PB_API size_t pb_readbytes(pb_Slice *s, pb_Slice *pv) {
534 const char *p = s->p;
535 uint64_t len;
536 if (pb_readvarint64(s, &len) == 0 || pb_len(*s) < len) {
537 s->p = p;
538 return 0;
539 }
540 pv->start = s->start;
541 pv->p = s->p;
542 pv->end = s->p + len;
543 s->p = pv->end;
544 return s->p - p;
545}
546
547PB_API size_t pb_readgroup(pb_Slice *s, uint32_t tag, pb_Slice *pv) {
548 const char *p = s->p;
549 uint32_t newtag = 0;
550 size_t count;
551 assert(pb_gettype(tag) == PB_TGSTART);
552 while ((count = pb_readvarint32(s, &newtag)) != 0) {
553 if (pb_gettype(newtag) == PB_TGEND) {
554 if (pb_gettag(newtag) != pb_gettag(tag))
555 break;
556 pv->start = s->start;
557 pv->p = p;
558 pv->end = s->p - count;
559 return s->p - p;
560 }
561 if (pb_skipvalue(s, newtag) == 0) break;
562 }
563 s->p = p;
564 return 0;
565}
566
567PB_API size_t pb_skipvalue(pb_Slice *s, uint32_t tag) {
568 const char *p = s->p;
569 size_t ret = 0;
570 pb_Slice data;
571 switch (pb_gettype(tag)) {
572 default: break;
573 case PB_TVARINT: ret = pb_skipvarint(s); break;
574 case PB_T64BIT: ret = pb_skipslice(s, 8); break;
575 case PB_TBYTES: ret = pb_skipbytes(s); break;
576 case PB_T32BIT: ret = pb_skipslice(s, 4); break;
577 case PB_TGSTART: ret = pb_readgroup(s, tag, &data); break;
578 }
579 if (!ret) s->p = p;
580 return ret;
581}
582
583PB_API size_t pb_skipvarint(pb_Slice *s) {
584 const char *p = s->p, *op = p;
585 while (p < s->end && (*p & 0x80) != 0) ++p;
586 if (p >= s->end) return 0;
587 s->p = ++p;
588 return p - op;
589}
590
591PB_API size_t pb_skipbytes(pb_Slice *s) {
592 const char *p = s->p;
593 uint64_t var;
594 if (!pb_readvarint64(s, &var)) return 0;
595 if (pb_len(*s) < var) {
596 s->p = p;
597 return 0;
598 }
599 s->p += var;
600 return s->p - p;
601}
602
603PB_API size_t pb_skipslice(pb_Slice *s, size_t len) {
604 if (s->p + len > s->end) return 0;
605 s->p += len;
606 return len;
607}
608
609PB_API int pb_wtypebytype(int type) {
610 switch (type) {
611 case PB_Tdouble: return PB_T64BIT;
612 case PB_Tfloat: return PB_T32BIT;
613 case PB_Tint64: return PB_TVARINT;
614 case PB_Tuint64: return PB_TVARINT;
615 case PB_Tint32: return PB_TVARINT;
616 case PB_Tfixed64: return PB_T64BIT;
617 case PB_Tfixed32: return PB_T32BIT;
618 case PB_Tbool: return PB_TVARINT;
619 case PB_Tstring: return PB_TBYTES;
620 case PB_Tmessage: return PB_TBYTES;
621 case PB_Tbytes: return PB_TBYTES;
622 case PB_Tuint32: return PB_TVARINT;
623 case PB_Tenum: return PB_TVARINT;
624 case PB_Tsfixed32: return PB_T32BIT;
625 case PB_Tsfixed64: return PB_T64BIT;
626 case PB_Tsint32: return PB_TVARINT;
627 case PB_Tsint64: return PB_TVARINT;
628 default: return PB_TWIRECOUNT;
629 }
630}
631
632PB_API const char *pb_wtypename(int wiretype, const char *def) {
633 switch (wiretype) {
634#define X(id,name,fmt) case PB_T##id: return name;
635 PB_WIRETYPES(X)
636#undef X
637 default: return def ? def : "<unknown>";
638 }
639}
640
641PB_API const char *pb_typename(int type, const char *def) {
642 switch (type) {
643#define X(name,type,fmt) case PB_T##name: return #name;
644 PB_TYPES(X)
645#undef X
646 default: return def ? def : "<unknown>";
647 }
648}
649
650PB_API int pb_typebyname(const char *name, int def) {
651 static struct entry { const char *name; int value; } names[] = {
652#define X(name,type,fmt) { #name, PB_T##name },
653 PB_TYPES(X)
654#undef X
655 { NULL, 0 }
656 };
657 struct entry *p;
658 for (p = names; p->name != NULL; ++p)
659 if (strcmp(p->name, name) == 0)
660 return p->value;
661 return def;
662}
663
664PB_API int pb_wtypebyname(const char *name, int def) {
665 static struct entry { const char *name; int value; } names[] = {
666#define X(id,name,fmt) { name, PB_T##id },
667 PB_WIRETYPES(X)
668#undef X
669 { NULL, 0 }
670 };
671 struct entry *p;
672 for (p = names; p->name != NULL; ++p)
673 if (strcmp(p->name, name) == 0)
674 return p->value;
675 return def;
676}
677
678
679/* encode */
680
681PB_API pb_Slice pb_result(const pb_Buffer *b)
682{ pb_Slice slice = pb_lslice(pb_buffer(b), b->size); return slice; }
683
684PB_API void pb_initbuffer(pb_Buffer *b)
685{ memset(b, 0, sizeof(pb_Buffer)); }
686
687PB_API void pb_resetbuffer(pb_Buffer *b)
688{ if (pb_onheap(b)) free(b->u.h.buff); pb_initbuffer(b); }
689
690static int pb_write32(char *buff, uint32_t n) {
691 int p, c = 0;
692 do {
693 p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c;
694 p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c;
695 p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c;
696 p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c;
697 p = n;
698 } while (0);
699 return *buff++ = p, ++c;
700}
701
702static int pb_write64(char *buff, uint64_t n) {
703 int p, c = 0;
704 do {
705 p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c;
706 p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c;
707 p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c;
708 p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c;
709 p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c;
710 p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c;
711 p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c;
712 p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c;
713 p = n & 0x7F; if ((n >>= 7) == 0) break; *buff++ = p | 0x80, ++c;
714 p = n & 0x7F;
715 } while (0);
716 return *buff++ = p, ++c;
717}
718
719PB_API char *pb_prepbuffsize(pb_Buffer *b, size_t len) {
720 size_t capacity = pb_onheap(b) ? b->u.h.capacity : PB_SSO_SIZE;
721 if (b->size + len > capacity) {
722 char *newp, *oldp = pb_onheap(b) ? b->u.h.buff : NULL;
723 size_t expected = b->size + len;
724 size_t newsize = PB_SSO_SIZE;
725 while (newsize < PB_MAX_SIZET/2 && newsize < expected)
726 newsize += newsize >> 1;
727 if (newsize < expected) return NULL;
728 if ((newp = (char*)realloc(oldp, newsize)) == NULL) return NULL;
729 if (!pb_onheap(b)) memcpy(newp, pb_buffer(b), b->size);
730 b->heap = 1;
731 b->u.h.buff = newp;
732 b->u.h.capacity = (unsigned)newsize;
733 }
734 return &pb_buffer(b)[b->size];
735}
736
737PB_API size_t pb_addslice(pb_Buffer *b, pb_Slice s) {
738 size_t len = pb_len(s);
739 char *buff = pb_prepbuffsize(b, len);
740 if (buff == NULL) return 0;
741 memcpy(buff, s.p, len);
742 pb_addsize(b, len);
743 return len;
744}
745
746PB_API size_t pb_addlength(pb_Buffer *b, size_t len, size_t prealloc) {
747 char buff[10], *s;
748 size_t bl, ml, rl = 0;
749 if ((bl = pb_bufflen(b)) < len)
750 return 0;
751 ml = pb_write64(buff, bl - len);
752 s = pb_buffer(b) + len - prealloc;
753 assert(ml >= prealloc);
754 if (ml > prealloc) {
755 if (pb_prepbuffsize(b, (rl = ml - prealloc)) == NULL) return 0;
756 s = pb_buffer(b) + len - prealloc;
757 memmove(s+ml, s+prealloc, bl - len);
758 }
759 memcpy(s, buff, ml);
760 pb_addsize(b, rl);
761 return ml + (bl - len);
762}
763
764PB_API size_t pb_addbytes(pb_Buffer *b, pb_Slice s) {
765 size_t ret, len = pb_len(s);
766 if (pb_prepbuffsize(b, len+5) == NULL) return 0;
767 ret = pb_addvarint32(b, (uint32_t)len);
768 return ret + pb_addslice(b, s);
769}
770
771PB_API size_t pb_addvarint32(pb_Buffer *b, uint32_t n) {
772 char *buff = pb_prepbuffsize(b, 5);
773 size_t l;
774 if (buff == NULL) return 0;
775 pb_addsize(b, l = pb_write32(buff, n));
776 return l;
777}
778
779PB_API size_t pb_addvarint64(pb_Buffer *b, uint64_t n) {
780 char *buff = pb_prepbuffsize(b, 10);
781 size_t l;
782 if (buff == NULL) return 0;
783 pb_addsize(b, l = pb_write64(buff, n));
784 return l;
785}
786
787PB_API size_t pb_addfixed32(pb_Buffer *b, uint32_t n) {
788 char *ch = pb_prepbuffsize(b, 4);
789 if (ch == NULL) return 0;
790 *ch++ = n & 0xFF; n >>= 8;
791 *ch++ = n & 0xFF; n >>= 8;
792 *ch++ = n & 0xFF; n >>= 8;
793 *ch = n & 0xFF;
794 pb_addsize(b, 4);
795 return 4;
796}
797
798PB_API size_t pb_addfixed64(pb_Buffer *b, uint64_t n) {
799 char *ch = pb_prepbuffsize(b, 8);
800 if (ch == NULL) return 0;
801 *ch++ = n & 0xFF; n >>= 8;
802 *ch++ = n & 0xFF; n >>= 8;
803 *ch++ = n & 0xFF; n >>= 8;
804 *ch++ = n & 0xFF; n >>= 8;
805 *ch++ = n & 0xFF; n >>= 8;
806 *ch++ = n & 0xFF; n >>= 8;
807 *ch++ = n & 0xFF; n >>= 8;
808 *ch = n & 0xFF;
809 pb_addsize(b, 8);
810 return 8;
811}
812
813
814/* memory pool */
815
816PB_API void pb_initpool(pb_Pool *pool, size_t obj_size) {
817 memset(pool, 0, sizeof(pb_Pool));
818 pool->obj_size = obj_size;
819 assert(obj_size > sizeof(void*) && obj_size < PB_POOLSIZE/4);
820}
821
822PB_API void pb_freepool(pb_Pool *pool) {
823 void *page = pool->pages;
824 while (page) {
825 void *next = *(void**)((char*)page + PB_POOLSIZE - sizeof(void*));
826 free(page);
827 page = next;
828 }
829 pb_initpool(pool, pool->obj_size);
830}
831
832PB_API void *pb_poolalloc(pb_Pool *pool) {
833 void *obj = pool->freed;
834 if (obj == NULL) {
835 size_t objsize = pool->obj_size, offset;
836 void *newpage = malloc(PB_POOLSIZE);
837 if (newpage == NULL) return NULL;
838 offset = ((PB_POOLSIZE - sizeof(void*)) / objsize - 1) * objsize;
839 for (; offset > 0; offset -= objsize) {
840 void **entry = (void**)((char*)newpage + offset);
841 *entry = pool->freed, pool->freed = (void*)entry;
842 }
843 *(void**)((char*)newpage + PB_POOLSIZE - sizeof(void*)) = pool->pages;
844 pool->pages = newpage;
845 return newpage;
846 }
847 pool->freed = *(void**)obj;
848 return obj;
849}
850
851PB_API void pb_poolfree(pb_Pool *pool, void *obj)
852{ *(void**)obj = pool->freed, pool->freed = obj; }
853
854
855/* hash table */
856
857#define pbT_offset(a,b) ((char*)(a) - (char*)(b))
858#define pbT_index(a,b) ((pb_Entry*)((char*)(a) + (b)))
859
860PB_API void pb_inittable(pb_Table *t, size_t entrysize)
861{ memset(t, 0, sizeof(pb_Table)), t->entry_size = (unsigned)entrysize; }
862
863PB_API void pb_freetable(pb_Table *t)
864{ free(t->hash); pb_inittable(t, t->entry_size); }
865
866static pb_Entry *pbT_hash(const pb_Table *t, pb_Key key) {
867 size_t h = ((size_t)key*2654435761U)&(t->size-1);
868 if (key && h == 0) h = 1;
869 return pbT_index(t->hash, h*t->entry_size);
870}
871
872static pb_Entry *pbT_newkey(pb_Table *t, pb_Key key) {
873 pb_Entry *mp, *on, *next, *f = NULL;
874 if (t->size == 0 && pb_resizetable(t, (size_t)t->size*2) == 0) return NULL;
875 if (key == 0) {
876 mp = t->hash;
877 t->has_zero = 1;
878 } else if ((mp = pbT_hash(t, key))->key != 0) {
879 while (t->lastfree > t->entry_size) {
880 pb_Entry *cur = pbT_index(t->hash, t->lastfree -= t->entry_size);
881 if (cur->key == 0 && cur->next == 0) { f = cur; break; }
882 }
883 if (f == NULL) return pb_resizetable(t, (size_t)t->size*2u) ?
884 pbT_newkey(t, key) : NULL;
885 if ((on = pbT_hash(t, mp->key)) != mp) {
886 while ((next = pbT_index(on, on->next)) != mp) on = next;
887 on->next = pbT_offset(f, on);
888 memcpy(f, mp, t->entry_size);
889 if (mp->next != 0) f->next += pbT_offset(mp, f), mp->next = 0;
890 } else {
891 if (mp->next != 0) f->next = pbT_offset(mp, f) + mp->next;
892 else assert(f->next == 0);
893 mp->next = pbT_offset(f, mp);
894 mp = f;
895 }
896 }
897 mp->key = key;
898 if (t->entry_size != sizeof(pb_Entry))
899 memset(mp+1, 0, t->entry_size - sizeof(pb_Entry));
900 return mp;
901}
902
903PB_API size_t pb_resizetable(pb_Table *t, size_t size) {
904 pb_Table nt = *t;
905 unsigned i, rawsize = t->size*t->entry_size;
906 unsigned newsize = PB_MIN_HASHTABLE_SIZE;
907 while (newsize < PB_MAX_HASHSIZE/t->entry_size && newsize < size)
908 newsize <<= 1;
909 if (newsize < size) return 0;
910 nt.size = newsize;
911 nt.lastfree = nt.entry_size * newsize;
912 nt.hash = (pb_Entry*)malloc(nt.lastfree);
913 if (nt.hash == NULL) return 0;
914 memset(nt.hash, 0, nt.lastfree);
915 for (i = 0; i < rawsize; i += t->entry_size) {
916 pb_Entry *olde = (pb_Entry*)((char*)t->hash + i);
917 pb_Entry *newe = pbT_newkey(&nt, olde->key);
918 if (nt.entry_size > sizeof(pb_Entry))
919 memcpy(newe+1, olde+1, nt.entry_size - sizeof(pb_Entry));
920 }
921 free(t->hash);
922 *t = nt;
923 return newsize;
924}
925
926PB_API pb_Entry *pb_gettable(const pb_Table *t, pb_Key key) {
927 pb_Entry *entry;
928 if (t == NULL || t->size == 0)
929 return NULL;
930 if (key == 0)
931 return t->has_zero ? t->hash : NULL;
932 for (entry = pbT_hash(t, key);
933 entry->key != key;
934 entry = pbT_index(entry, entry->next))
935 if (entry->next == 0) return NULL;
936 return entry;
937}
938
939PB_API pb_Entry *pb_settable(pb_Table *t, pb_Key key) {
940 pb_Entry *entry;
941 if ((entry = pb_gettable(t, key)) != NULL)
942 return entry;
943 return pbT_newkey(t, key);
944}
945
946PB_API int pb_nextentry(const pb_Table *t, const pb_Entry **pentry) {
947 size_t i = *pentry ? pbT_offset(*pentry, t->hash) : 0;
948 size_t size = (size_t)t->size*t->entry_size;
949 if (*pentry == NULL && t->has_zero) {
950 *pentry = t->hash;
951 return 1;
952 }
953 while (i += t->entry_size, i < size) {
954 pb_Entry *entry = pbT_index(t->hash, i);
955 if (entry->key != 0) {
956 *pentry = entry;
957 return 1;
958 }
959 }
960 *pentry = NULL;
961 return 0;
962}
963
964
965/* name table */
966
967static void pbN_init(pb_State *S)
968{ memset(&S->nametable, 0, sizeof(pb_NameTable)); }
969
970PB_API pb_Name *pb_usename(pb_Name *name)
971{ if (name != NULL) ++((pb_NameEntry*)name-1)->refcount; return name; }
972
973static void pbN_free(pb_State *S) {
974 pb_NameTable *nt = &S->nametable;
975 size_t i;
976 for (i = 0; i < nt->size; ++i) {
977 pb_NameEntry *ne = nt->hash[i];
978 while (ne != NULL) {
979 pb_NameEntry *next = ne->next;
980 free(ne);
981 ne = next;
982 }
983 }
984 free(nt->hash);
985 pbN_init(S);
986}
987
988static unsigned pbN_calchash(pb_Slice s) {
989 size_t len = pb_len(s);
990 unsigned h = (unsigned)len;
991 size_t step = (len >> PB_HASHLIMIT) + 1;
992 for (; len >= step; len -= step)
993 h ^= ((h<<5) + (h>>2) + (unsigned char)(s.p[len - 1]));
994 return h;
995}
996
997static size_t pbN_resize(pb_State *S, size_t size) {
998 pb_NameTable *nt = &S->nametable;
999 pb_NameEntry **hash;
1000 size_t i, newsize = PB_MIN_STRTABLE_SIZE;
1001 while (newsize < PB_MAX_HASHSIZE/sizeof(pb_NameEntry*) && newsize < size)
1002 newsize <<= 1;
1003 if (newsize < size) return 0;
1004 hash = (pb_NameEntry**)malloc(newsize * sizeof(pb_NameEntry*));
1005 if (hash == NULL) return 0;
1006 memset(hash, 0, newsize * sizeof(pb_NameEntry*));
1007 for (i = 0; i < nt->size; ++i) {
1008 pb_NameEntry *entry = nt->hash[i];
1009 while (entry != NULL) {
1010 pb_NameEntry *next = entry->next;
1011 pb_NameEntry **newh = &hash[entry->hash & (newsize - 1)];
1012 entry->next = *newh, *newh = entry;
1013 entry = next;
1014 }
1015 }
1016 free(nt->hash);
1017 nt->hash = hash;
1018 nt->size = newsize;
1019 return newsize;
1020}
1021
1022static pb_NameEntry *pbN_newname(pb_State *S, pb_Slice s, unsigned hash) {
1023 pb_NameTable *nt = &S->nametable;
1024 pb_NameEntry **list, *newobj;
1025 size_t len = pb_len(s);
1026 if (nt->count >= nt->size && !pbN_resize(S, nt->size * 2)) return NULL;
1027 list = &nt->hash[hash & (nt->size - 1)];
1028 newobj = (pb_NameEntry*)malloc(sizeof(pb_NameEntry) + len + 1);
1029 if (newobj == NULL) return NULL;
1030 newobj->next = *list;
1031 newobj->length = (unsigned)len;
1032 newobj->refcount = 0;
1033 newobj->hash = hash;
1034 memcpy(newobj+1, s.p, len);
1035 ((char*)(newobj+1))[len] = '\0';
1036 *list = newobj;
1037 ++nt->count;
1038 return newobj;
1039}
1040
1041static void pbN_delname(pb_State *S, pb_NameEntry *name) {
1042 pb_NameTable *nt = &S->nametable;
1043 pb_NameEntry **list = &nt->hash[name->hash & (nt->size - 1)];
1044 while (*list != NULL) {
1045 if (*list != name)
1046 list = &(*list)->next;
1047 else {
1048 *list = (*list)->next;
1049 --nt->count;
1050 free(name);
1051 break;
1052 }
1053 }
1054}
1055
1056static pb_NameEntry *pbN_getname(const pb_State *S, pb_Slice s, unsigned hash) {
1057 const pb_NameTable *nt = &S->nametable;
1058 size_t len = pb_len(s);
1059 if (nt->hash) {
1060 pb_NameEntry *entry = nt->hash[hash & (nt->size - 1)];
1061 for (; entry != NULL; entry = entry->next)
1062 if (entry->hash == hash && entry->length == len
1063 && memcmp(s.p, entry + 1, len) == 0)
1064 return entry;
1065 }
1066 return NULL;
1067}
1068
1069PB_API void pb_delname(pb_State *S, pb_Name *name) {
1070 if (name != NULL) {
1071 pb_NameEntry *ne = (pb_NameEntry*)name - 1;
1072 if (ne->refcount <= 1) { pbN_delname(S, ne); return; }
1073 --ne->refcount;
1074 }
1075}
1076
1077PB_API pb_Name *pb_newname(pb_State *S, pb_Slice s, pb_Cache *cache) {
1078 pb_NameEntry *entry;
1079 if (s.p == NULL) return NULL;
1080 (void)cache;
1081 assert(cache == NULL);
1082 /* if (cache == NULL) */{
1083 unsigned hash = pbN_calchash(s);
1084 entry = pbN_getname(S, s, hash);
1085 if (entry == NULL) entry = pbN_newname(S, s, hash);
1086 }/* else {
1087 pb_Name *name = (pb_Name*)pb_name(S, s, cache);
1088 if (name) return pb_usename(name);
1089 entry = pbN_newname(S, s, cache->hash);
1090 }*/
1091 return entry ? pb_usename((pb_Name*)(entry + 1)) : NULL;
1092}
1093
1094PB_API const pb_Name *pb_name(const pb_State *S, pb_Slice s, pb_Cache *cache) {
1095 pb_NameEntry *entry = NULL;
1096 pb_CacheSlot *slot;
1097 if (S == NULL || s.p == NULL) return NULL;
1098 if (cache == NULL)
1099 entry = pbN_getname(S, s, pbN_calchash(s));
1100 else {
1101 slot = cache->slots[((uintptr_t)s.p*2654435761U)%PB_CACHE_SIZE];
1102 if (slot[0].name == s.p)
1103 entry = pbN_getname(S, s, cache->hash = slot[0].hash);
1104 else if (slot[1].name == s.p)
1105 entry = pbN_getname(S, s, cache->hash = (++slot)[0].hash);
1106 else
1107 slot[1] = slot[0], slot[0].name = s.p;
1108 if (entry == NULL) {
1109 cache->hash = slot[0].hash = pbN_calchash(s);
1110 entry = pbN_getname(S, s, slot[0].hash);
1111 }
1112 }
1113 return entry ? (pb_Name*)(entry + 1) : NULL;
1114}
1115
1116
1117/* state */
1118
1119typedef struct pb_TypeEntry { pb_Entry entry; pb_Type *value; } pb_TypeEntry;
1120typedef struct pb_FieldEntry { pb_Entry entry; pb_Field *value; } pb_FieldEntry;
1121
1122typedef struct pb_OneofEntry {
1123 pb_Entry entry;
1124 pb_Name *name;
1125 unsigned index;
1126} pb_OneofEntry;
1127
1128PB_API void pb_init(pb_State *S) {
1129 memset(S, 0, sizeof(pb_State));
1130 S->types.entry_size = sizeof(pb_TypeEntry);
1131 pb_initpool(&S->typepool, sizeof(pb_Type));
1132 pb_initpool(&S->fieldpool, sizeof(pb_Field));
1133}
1134
1135PB_API void pb_free(pb_State *S) {
1136 const pb_Entry *e = NULL;
1137 if (S == NULL) return;
1138 while (pb_nextentry(&S->types, &e)) {
1139 pb_TypeEntry *te = (pb_TypeEntry*)e;
1140 if (te->value != NULL) pb_deltype(S, te->value);
1141 }
1142 pb_freetable(&S->types);
1143 pb_freepool(&S->typepool);
1144 pb_freepool(&S->fieldpool);
1145 pbN_free(S);
1146}
1147
1148PB_API const pb_Type *pb_type(const pb_State *S, const pb_Name *tname) {
1149 pb_TypeEntry *te = NULL;
1150 if (S != NULL && tname != NULL)
1151 te = (pb_TypeEntry*)pb_gettable(&S->types, (pb_Key)tname);
1152 return te && !te->value->is_dead ? te->value : NULL;
1153}
1154
1155PB_API const pb_Field *pb_fname(const pb_Type *t, const pb_Name *name) {
1156 pb_FieldEntry *fe = NULL;
1157 if (t != NULL && name != NULL)
1158 fe = (pb_FieldEntry*)pb_gettable(&t->field_names, (pb_Key)name);
1159 return fe ? fe->value : NULL;
1160}
1161
1162PB_API const pb_Field *pb_field(const pb_Type *t, int32_t number) {
1163 pb_FieldEntry *fe = NULL;
1164 if (t != NULL) fe = (pb_FieldEntry*)pb_gettable(&t->field_tags, number);
1165 return fe ? fe->value : NULL;
1166}
1167
1168
1169static int comp_field(const void* a, const void* b) {
1170 return (*(const pb_Field**)a)->number - (*(const pb_Field**)b)->number;
1171}
1172
1173PB_API pb_Field** pb_sortfield(pb_Type* t) {
1174 if (!t->field_sort && t->field_count) {
1175 int index = 0;
1176 unsigned int i = 0;
1177 const pb_Field* f = NULL;
1178 pb_Field** list = (pb_Field**)malloc(sizeof(pb_Field*) * t->field_count);
1179
1180 assert(list);
1181 while (pb_nextfield(t, &f)) {
1182 list[index++] = (pb_Field*)f;
1183 }
1184
1185 qsort(list, index, sizeof(pb_Field*), comp_field);
1186 for (i = 0; i < t->field_count; i++) {
1187 list[i]->sort_index = i + 1;
1188 }
1189 t->field_sort = list;
1190 }
1191
1192 return t->field_sort;
1193}
1194
1195PB_API const pb_Name *pb_oneofname(const pb_Type *t, int idx) {
1196 pb_OneofEntry *oe = NULL;
1197 if (t != NULL) oe = (pb_OneofEntry*)pb_gettable(&t->oneof_index, idx);
1198 return oe ? oe->name : NULL;
1199}
1200
1201PB_API int pb_nexttype(const pb_State *S, const pb_Type **ptype) {
1202 if (S != NULL) {
1203 const pb_Entry *ent = NULL;
1204 if (*ptype != NULL) {
1205 const pb_TypeEntry *e = (const pb_TypeEntry*)
1206 pb_gettable(&S->types, (pb_Key)(*ptype)->name);
1207 ent = &e->entry;
1208 }
1209 while (pb_nextentry(&S->types, &ent)) {
1210 const pb_TypeEntry *e = (const pb_TypeEntry*)ent;
1211 if ((*ptype = e->value) != NULL && !(*ptype)->is_dead)
1212 return 1;
1213 }
1214 }
1215 *ptype = NULL;
1216 return 0;
1217}
1218
1219PB_API int pb_nextfield(const pb_Type *t, const pb_Field **pfield) {
1220 if (t != NULL) {
1221 const pb_Entry *ent = NULL;
1222 if (*pfield != NULL) {
1223 const pb_FieldEntry *e = (const pb_FieldEntry*)
1224 pb_gettable(&t->field_tags, (*pfield)->number);
1225 ent = &e->entry;
1226 }
1227 while (pb_nextentry(&t->field_tags, &ent)) {
1228 const pb_FieldEntry *e = (const pb_FieldEntry*)ent;
1229 if ((*pfield = e->value) != NULL)
1230 return 1;
1231 }
1232 }
1233 *pfield = NULL;
1234 return 0;
1235}
1236
1237
1238/* new type/field */
1239
1240static const char *pbT_basename(const char *tname) {
1241 const char *end = tname + strlen(tname);
1242 while (tname < end && *--end != '.')
1243 ;
1244 return *end != '.' ? end : end + 1;
1245}
1246
1247static void pbT_inittype(pb_Type *t) {
1248 memset(t, 0, sizeof(pb_Type));
1249 pb_inittable(&t->field_names, sizeof(pb_FieldEntry));
1250 pb_inittable(&t->field_tags, sizeof(pb_FieldEntry));
1251 pb_inittable(&t->oneof_index, sizeof(pb_OneofEntry));
1252}
1253
1254static void pbT_freefield(pb_State *S, pb_Field *f) {
1255 pb_delname(S, f->default_value);
1256 pb_delname(S, f->name);
1257 pb_poolfree(&S->fieldpool, f);
1258}
1259
1260PB_API pb_Type *pb_newtype(pb_State *S, pb_Name *tname) {
1261 pb_TypeEntry *te;
1262 pb_Type *t;
1263 if (tname == NULL) return NULL;
1264 te = (pb_TypeEntry*)pb_settable(&S->types, (pb_Key)tname);
1265 if (te == NULL) return NULL;
1266 if ((t = te->value) != NULL) return t->is_dead = 0, t;
1267 if (!(t = (pb_Type*)pb_poolalloc(&S->typepool))) return NULL;
1268 pbT_inittype(t);
1269 t->name = tname;
1270 t->basename = pbT_basename((const char*)tname);
1271 return te->value = t;
1272}
1273
1274PB_API void pb_delsort(pb_Type *t) {
1275 if (t->field_sort) {
1276 free(t->field_sort);
1277 t->field_sort = NULL;
1278 }
1279}
1280
1281PB_API void pb_deltype(pb_State *S, pb_Type *t) {
1282 const pb_Entry *e = NULL;
1283 if (S == NULL || t == NULL) return;
1284 while (pb_nextentry(&t->field_names, &e)) {
1285 const pb_FieldEntry *nf = (const pb_FieldEntry*)e;
1286 if (nf->value != NULL) {
1287 pb_FieldEntry *of = (pb_FieldEntry*)pb_gettable(
1288 &t->field_tags, nf->value->number);
1289 if (of && of->value == nf->value)
1290 of->entry.key = 0, of->value = NULL;
1291 pbT_freefield(S, nf->value);
1292 }
1293 }
1294 while (pb_nextentry(&t->field_tags, &e)) {
1295 pb_FieldEntry *nf = (pb_FieldEntry*)e;
1296 if (nf->value != NULL) pbT_freefield(S, nf->value);
1297 }
1298 while (pb_nextentry(&t->oneof_index, &e)) {
1299 pb_OneofEntry *oe = (pb_OneofEntry*)e;
1300 pb_delname(S, oe->name);
1301 }
1302 pb_freetable(&t->field_tags);
1303 pb_freetable(&t->field_names);
1304 pb_freetable(&t->oneof_index);
1305 t->oneof_field = 0, t->field_count = 0;
1306 t->is_dead = 1;
1307 pb_delsort(t);
1308 /*pb_delname(S, t->name); */
1309 /*pb_poolfree(&S->typepool, t); */
1310}
1311
1312PB_API pb_Field *pb_newfield(pb_State *S, pb_Type *t, pb_Name *fname, int32_t number) {
1313 pb_FieldEntry *nf, *tf;
1314 pb_Field *f;
1315 if (fname == NULL) return NULL;
1316 nf = (pb_FieldEntry*)pb_settable(&t->field_names, (pb_Key)fname);
1317 tf = (pb_FieldEntry*)pb_settable(&t->field_tags, number);
1318 if (nf == NULL || tf == NULL) return NULL;
1319 if ((f = nf->value) != NULL && tf->value == f) {
1320 pb_delname(S, f->default_value);
1321 f->default_value = NULL;
1322 return f;
1323 }
1324 if (!(f = (pb_Field*)pb_poolalloc(&S->fieldpool))) return NULL;
1325 memset(f, 0, sizeof(pb_Field));
1326 f->name = fname;
1327 f->type = t;
1328 f->number = number;
1329 if (nf->value && pb_field(t, nf->value->number) != nf->value)
1330 pbT_freefield(S, nf->value), --t->field_count;
1331 if (tf->value && pb_fname(t, tf->value->name) != tf->value)
1332 pbT_freefield(S, tf->value), --t->field_count;
1333 ++t->field_count;
1334 pb_delsort(t);
1335 return nf->value = tf->value = f;
1336}
1337
1338PB_API void pb_delfield(pb_State *S, pb_Type *t, pb_Field *f) {
1339 pb_FieldEntry *nf, *tf;
1340 int count = 0;
1341 if (S == NULL || t == NULL || f == NULL) return;
1342 nf = (pb_FieldEntry*)pb_gettable(&t->field_names, (pb_Key)f->name);
1343 tf = (pb_FieldEntry*)pb_gettable(&t->field_tags, (pb_Key)f->number);
1344 if (nf && nf->value == f) nf->entry.key = 0, nf->value = NULL, ++count;
1345 if (tf && tf->value == f) tf->entry.key = 0, tf->value = NULL, ++count;
1346 if (count) {
1347 if (f->oneof_idx) --t->oneof_field;
1348 pbT_freefield(S, f), --t->field_count;
1349 }
1350 pb_delsort(t);
1351}
1352
1353
1354/* .pb proto loader */
1355
1356typedef struct pb_Loader pb_Loader;
1357typedef struct pbL_FieldInfo pbL_FieldInfo;
1358typedef struct pbL_EnumValueInfo pbL_EnumValueInfo;
1359typedef struct pbL_EnumInfo pbL_EnumInfo;
1360typedef struct pbL_TypeInfo pbL_TypeInfo;
1361typedef struct pbL_FileInfo pbL_FileInfo;
1362
1363#define pbC(e) do { int r = (e); if (r != PB_OK) return r; } while (0)
1364#define pbCM(e) do { if ((e) == NULL) return PB_ENOMEM; } while (0)
1365#define pbCE(e) do { if ((e) == NULL) return PB_ERROR; } while (0)
1366
1367typedef struct pb_ArrayHeader {
1368 unsigned count;
1369 unsigned capacity;
1370} pb_ArrayHeader;
1371
1372#define pbL_rawh(A) ((pb_ArrayHeader*)(A) - 1)
1373#define pbL_delete(A) ((A) ? (void)free(pbL_rawh(A)) : (void)0)
1374#define pbL_count(A) ((A) ? pbL_rawh(A)->count : 0)
1375#define pbL_add(A) (pbL_grow((void*)&(A),sizeof(*(A)))==PB_OK ?\
1376 &(A)[pbL_rawh(A)->count++] : NULL)
1377
1378struct pb_Loader {
1379 pb_Slice s;
1380 pb_Buffer b;
1381 int is_proto3;
1382};
1383
1384/* parsers */
1385
1386struct pbL_EnumValueInfo {
1387 pb_Slice name;
1388 int32_t number;
1389};
1390
1391struct pbL_EnumInfo {
1392 pb_Slice name;
1393 pbL_EnumValueInfo *value;
1394};
1395
1396struct pbL_FieldInfo {
1397 pb_Slice name;
1398 pb_Slice type_name;
1399 pb_Slice extendee;
1400 pb_Slice default_value;
1401 int32_t number;
1402 int32_t label;
1403 int32_t type;
1404 int32_t oneof_index;
1405 int32_t packed;
1406};
1407
1408struct pbL_TypeInfo {
1409 pb_Slice name;
1410 int32_t is_map;
1411 pbL_FieldInfo *field;
1412 pbL_FieldInfo *extension;
1413 pbL_EnumInfo *enum_type;
1414 pbL_TypeInfo *nested_type;
1415 pb_Slice *oneof_decl;
1416};
1417
1418struct pbL_FileInfo {
1419 pb_Slice package;
1420 pb_Slice syntax;
1421 pbL_EnumInfo *enum_type;
1422 pbL_TypeInfo *message_type;
1423 pbL_FieldInfo *extension;
1424};
1425
1426static int pbL_readbytes(pb_Loader *L, pb_Slice *pv)
1427{ return pb_readbytes(&L->s, pv) == 0 ? PB_ERROR : PB_OK; }
1428
1429static int pbL_beginmsg(pb_Loader *L, pb_Slice *pv)
1430{ pb_Slice v; pbC(pbL_readbytes(L, &v)); *pv = L->s, L->s = v; return PB_OK; }
1431
1432static void pbL_endmsg(pb_Loader *L, pb_Slice *pv)
1433{ L->s = *pv; }
1434
1435static int pbL_grow(void *p, size_t objs) {
1436 union { void *p; void **pp; } up;
1437 pb_ArrayHeader *nh, *h = (up.p = p, *up.pp) ? pbL_rawh(*up.pp) : NULL;
1438 if (h == NULL || h->capacity <= h->count) {
1439 size_t used = (h ? h->count : 0);
1440 size_t size = used + 4, nsize = size + (size >> 1);
1441 nh = nsize < size ? NULL :
1442 (pb_ArrayHeader*)realloc(h, sizeof(pb_ArrayHeader)+nsize*objs);
1443 if (nh == NULL) return PB_ENOMEM;
1444 nh->count = (unsigned)used;
1445 nh->capacity = (unsigned)nsize;
1446 *up.pp = nh + 1;
1447 memset((char*)*up.pp + used*objs, 0, (nsize - used)*objs);
1448 }
1449 return PB_OK;
1450}
1451
1452static int pbL_readint32(pb_Loader *L, int32_t *pv) {
1453 uint32_t v;
1454 if (pb_readvarint32(&L->s, &v) == 0) return PB_ERROR;
1455 *pv = (int32_t)v;
1456 return PB_OK;
1457}
1458
1459static int pbL_FieldOptions(pb_Loader *L, pbL_FieldInfo *info) {
1460 pb_Slice s;
1461 uint32_t tag;
1462 pbC(pbL_beginmsg(L, &s));
1463 while (pb_readvarint32(&L->s, &tag)) {
1464 switch (tag) {
1465 case pb_pair(2, PB_TVARINT): /* bool packed */
1466 pbC(pbL_readint32(L, &info->packed)); break;
1467 default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1468 }
1469 }
1470 pbL_endmsg(L, &s);
1471 return PB_OK;
1472}
1473
1474static int pbL_FieldDescriptorProto(pb_Loader *L, pbL_FieldInfo *info) {
1475 pb_Slice s;
1476 uint32_t tag;
1477 pbCM(info); pbC(pbL_beginmsg(L, &s));
1478 info->packed = -1;
1479 while (pb_readvarint32(&L->s, &tag)) {
1480 switch (tag) {
1481 case pb_pair(1, PB_TBYTES): /* string name */
1482 pbC(pbL_readbytes(L, &info->name)); break;
1483 case pb_pair(3, PB_TVARINT): /* int32 number */
1484 pbC(pbL_readint32(L, &info->number)); break;
1485 case pb_pair(4, PB_TVARINT): /* Label label */
1486 pbC(pbL_readint32(L, &info->label)); break;
1487 case pb_pair(5, PB_TVARINT): /* Type type */
1488 pbC(pbL_readint32(L, &info->type)); break;
1489 case pb_pair(6, PB_TBYTES): /* string type_name */
1490 pbC(pbL_readbytes(L, &info->type_name)); break;
1491 case pb_pair(2, PB_TBYTES): /* string extendee */
1492 pbC(pbL_readbytes(L, &info->extendee)); break;
1493 case pb_pair(7, PB_TBYTES): /* string default_value */
1494 pbC(pbL_readbytes(L, &info->default_value)); break;
1495 case pb_pair(8, PB_TBYTES): /* FieldOptions options */
1496 pbC(pbL_FieldOptions(L, info)); break;
1497 case pb_pair(9, PB_TVARINT): /* int32 oneof_index */
1498 pbC(pbL_readint32(L, &info->oneof_index));
1499 ++info->oneof_index; break;
1500 default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1501 }
1502 }
1503 pbL_endmsg(L, &s);
1504 return PB_OK;
1505}
1506
1507static int pbL_EnumValueDescriptorProto(pb_Loader *L, pbL_EnumValueInfo *info) {
1508 pb_Slice s;
1509 uint32_t tag;
1510 pbCM(info); pbC(pbL_beginmsg(L, &s));
1511 while (pb_readvarint32(&L->s, &tag)) {
1512 switch (tag) {
1513 case pb_pair(1, PB_TBYTES): /* string name */
1514 pbC(pbL_readbytes(L, &info->name)); break;
1515 case pb_pair(2, PB_TVARINT): /* int32 number */
1516 pbC(pbL_readint32(L, &info->number)); break;
1517 default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1518 }
1519 }
1520 pbL_endmsg(L, &s);
1521 return PB_OK;
1522}
1523
1524static int pbL_EnumDescriptorProto(pb_Loader *L, pbL_EnumInfo *info) {
1525 pb_Slice s;
1526 uint32_t tag;
1527 pbCM(info); pbC(pbL_beginmsg(L, &s));
1528 while (pb_readvarint32(&L->s, &tag)) {
1529 switch (tag) {
1530 case pb_pair(1, PB_TBYTES): /* string name */
1531 pbC(pbL_readbytes(L, &info->name)); break;
1532 case pb_pair(2, PB_TBYTES): /* EnumValueDescriptorProto value */
1533 pbC(pbL_EnumValueDescriptorProto(L, pbL_add(info->value))); break;
1534 default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1535 }
1536 }
1537 pbL_endmsg(L, &s);
1538 return PB_OK;
1539}
1540
1541static int pbL_MessageOptions(pb_Loader *L, pbL_TypeInfo *info) {
1542 pb_Slice s;
1543 uint32_t tag;
1544 pbCM(info); pbC(pbL_beginmsg(L, &s));
1545 while (pb_readvarint32(&L->s, &tag)) {
1546 switch (tag) {
1547 case pb_pair(7, PB_TVARINT): /* bool map_entry */
1548 pbC(pbL_readint32(L, &info->is_map)); break;
1549 default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1550 }
1551 }
1552 pbL_endmsg(L, &s);
1553 return PB_OK;
1554}
1555
1556static int pbL_OneofDescriptorProto(pb_Loader *L, pbL_TypeInfo *info) {
1557 pb_Slice s;
1558 uint32_t tag;
1559 pbCM(info); pbC(pbL_beginmsg(L, &s));
1560 while (pb_readvarint32(&L->s, &tag)) {
1561 switch (tag) {
1562 case pb_pair(1, PB_TBYTES): /* string name */
1563 pbC(pbL_readbytes(L, pbL_add(info->oneof_decl))); break;
1564 default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1565 }
1566 }
1567 pbL_endmsg(L, &s);
1568 return PB_OK;
1569}
1570
1571static int pbL_DescriptorProto(pb_Loader *L, pbL_TypeInfo *info) {
1572 pb_Slice s;
1573 uint32_t tag;
1574 pbCM(info); pbC(pbL_beginmsg(L, &s));
1575 while (pb_readvarint32(&L->s, &tag)) {
1576 switch (tag) {
1577 case pb_pair(1, PB_TBYTES): /* string name */
1578 pbC(pbL_readbytes(L, &info->name)); break;
1579 case pb_pair(2, PB_TBYTES): /* FieldDescriptorProto field */
1580 pbC(pbL_FieldDescriptorProto(L, pbL_add(info->field))); break;
1581 case pb_pair(6, PB_TBYTES): /* FieldDescriptorProto extension */
1582 pbC(pbL_FieldDescriptorProto(L, pbL_add(info->extension))); break;
1583 case pb_pair(3, PB_TBYTES): /* DescriptorProto nested_type */
1584 pbC(pbL_DescriptorProto(L, pbL_add(info->nested_type))); break;
1585 case pb_pair(4, PB_TBYTES): /* EnumDescriptorProto enum_type */
1586 pbC(pbL_EnumDescriptorProto(L, pbL_add(info->enum_type))); break;
1587 case pb_pair(8, PB_TBYTES): /* OneofDescriptorProto oneof_decl */
1588 pbC(pbL_OneofDescriptorProto(L, info)); break;
1589 case pb_pair(7, PB_TBYTES): /* MessageOptions options */
1590 pbC(pbL_MessageOptions(L, info)); break;
1591 default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1592 }
1593 }
1594 pbL_endmsg(L, &s);
1595 return PB_OK;
1596}
1597
1598static int pbL_FileDescriptorProto(pb_Loader *L, pbL_FileInfo *info) {
1599 pb_Slice s;
1600 uint32_t tag;
1601 pbCM(info); pbC(pbL_beginmsg(L, &s));
1602 while (pb_readvarint32(&L->s, &tag)) {
1603 switch (tag) {
1604 case pb_pair(2, PB_TBYTES): /* string package */
1605 pbC(pbL_readbytes(L, &info->package)); break;
1606 case pb_pair(4, PB_TBYTES): /* DescriptorProto message_type */
1607 pbC(pbL_DescriptorProto(L, pbL_add(info->message_type))); break;
1608 case pb_pair(5, PB_TBYTES): /* EnumDescriptorProto enum_type */
1609 pbC(pbL_EnumDescriptorProto(L, pbL_add(info->enum_type))); break;
1610 case pb_pair(7, PB_TBYTES): /* FieldDescriptorProto extension */
1611 pbC(pbL_FieldDescriptorProto(L, pbL_add(info->extension))); break;
1612 case pb_pair(12, PB_TBYTES): /* string syntax */
1613 pbC(pbL_readbytes(L, &info->syntax)); break;
1614 default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1615 }
1616 }
1617 pbL_endmsg(L, &s);
1618 return PB_OK;
1619}
1620
1621static int pbL_FileDescriptorSet(pb_Loader *L, pbL_FileInfo **pfiles) {
1622 uint32_t tag;
1623 while (pb_readvarint32(&L->s, &tag)) {
1624 switch (tag) {
1625 case pb_pair(1, PB_TBYTES): /* FileDescriptorProto file */
1626 pbC(pbL_FileDescriptorProto(L, pbL_add(*pfiles))); break;
1627 default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1628 }
1629 }
1630 return PB_OK;
1631}
1632
1633/* loader */
1634
1635static void pbL_delTypeInfo(pbL_TypeInfo *info) {
1636 size_t i, count;
1637 for (i = 0, count = pbL_count(info->nested_type); i < count; ++i)
1638 pbL_delTypeInfo(&info->nested_type[i]);
1639 for (i = 0, count = pbL_count(info->enum_type); i < count; ++i)
1640 pbL_delete(info->enum_type[i].value);
1641 pbL_delete(info->nested_type);
1642 pbL_delete(info->enum_type);
1643 pbL_delete(info->field);
1644 pbL_delete(info->extension);
1645 pbL_delete(info->oneof_decl);
1646}
1647
1648static void pbL_delFileInfo(pbL_FileInfo *files) {
1649 size_t i, count, j, jcount;
1650 for (i = 0, count = pbL_count(files); i < count; ++i) {
1651 for (j = 0, jcount = pbL_count(files[i].message_type); j < jcount; ++j)
1652 pbL_delTypeInfo(&files[i].message_type[j]);
1653 for (j = 0, jcount = pbL_count(files[i].enum_type); j < jcount; ++j)
1654 pbL_delete(files[i].enum_type[j].value);
1655 pbL_delete(files[i].message_type);
1656 pbL_delete(files[i].enum_type);
1657 pbL_delete(files[i].extension);
1658 }
1659 pbL_delete(files);
1660}
1661
1662static int pbL_prefixname(pb_State *S, pb_Slice s, size_t *ps, pb_Loader *L, pb_Name **out) {
1663 char *buff;
1664 *ps = pb_bufflen(&L->b);
1665 pbCM(buff = pb_prepbuffsize(&L->b, pb_len(s) + 1));
1666 *buff = '.'; pb_addsize(&L->b, 1);
1667 if (pb_addslice(&L->b, s) == 0) return PB_ENOMEM;
1668 if (out) *out = pb_newname(S, pb_result(&L->b), NULL);
1669 return PB_OK;
1670}
1671
1672static int pbL_loadEnum(pb_State *S, pbL_EnumInfo *info, pb_Loader *L) {
1673 size_t i, count, curr;
1674 pb_Name *name;
1675 pb_Type *t;
1676 pbC(pbL_prefixname(S, info->name, &curr, L, &name));
1677 pbCM(t = pb_newtype(S, name));
1678 t->is_enum = 1;
1679 for (i = 0, count = pbL_count(info->value); i < count; ++i) {
1680 pbL_EnumValueInfo *ev = &info->value[i];
1681 pbCE(pb_newfield(S, t, pb_newname(S, ev->name, NULL), ev->number));
1682 }
1683 L->b.size = (unsigned)curr;
1684 return PB_OK;
1685}
1686
1687static int pbL_loadField(pb_State *S, pbL_FieldInfo *info, pb_Loader *L, pb_Type *t) {
1688 pb_Type *ft = NULL;
1689 pb_Field *f;
1690 if (info->type == PB_Tmessage || info->type == PB_Tenum)
1691 pbCE(ft = pb_newtype(S, pb_newname(S, info->type_name, NULL)));
1692 if (t == NULL)
1693 pbCE(t = pb_newtype(S, pb_newname(S, info->extendee, NULL)));
1694 pbCE(f = pb_newfield(S, t, pb_newname(S, info->name, NULL), info->number));
1695 f->default_value = pb_newname(S, info->default_value, NULL);
1696 f->type = ft;
1697 if ((f->oneof_idx = info->oneof_index)) ++t->oneof_field;
1698 f->type_id = info->type;
1699 f->repeated = info->label == 3; /* repeated */
1700 f->packed = info->packed >= 0 ? info->packed : L->is_proto3 && f->repeated;
1701 if (f->type_id >= 9 && f->type_id <= 12) f->packed = 0;
1702 f->scalar = (f->type == NULL);
1703 return PB_OK;
1704}
1705
1706static int pbL_loadType(pb_State *S, pbL_TypeInfo *info, pb_Loader *L) {
1707 size_t i, count, curr;
1708 pb_Name *name;
1709 pb_Type *t;
1710 pbC(pbL_prefixname(S, info->name, &curr, L, &name));
1711 pbCM(t = pb_newtype(S, name));
1712 t->is_map = info->is_map, t->is_proto3 = L->is_proto3;
1713 for (i = 0, count = pbL_count(info->oneof_decl); i < count; ++i) {
1714 pb_OneofEntry *e = (pb_OneofEntry*)pb_settable(&t->oneof_index, i+1);
1715 pbCM(e); pbCE(e->name = pb_newname(S, info->oneof_decl[i], NULL));
1716 e->index = (int)i+1;
1717 }
1718 for (i = 0, count = pbL_count(info->field); i < count; ++i)
1719 pbC(pbL_loadField(S, &info->field[i], L, t));
1720 for (i = 0, count = pbL_count(info->extension); i < count; ++i)
1721 pbC(pbL_loadField(S, &info->extension[i], L, NULL));
1722 for (i = 0, count = pbL_count(info->enum_type); i < count; ++i)
1723 pbC(pbL_loadEnum(S, &info->enum_type[i], L));
1724 for (i = 0, count = pbL_count(info->nested_type); i < count; ++i)
1725 pbC(pbL_loadType(S, &info->nested_type[i], L));
1726 t->oneof_count = pbL_count(info->oneof_decl);
1727 L->b.size = (unsigned)curr;
1728 return PB_OK;
1729}
1730
1731static int pbL_loadFile(pb_State *S, pbL_FileInfo *info, pb_Loader *L) {
1732 size_t i, count, j, jcount, curr = 0;
1733 pb_Name *syntax;
1734 pbCM(syntax = pb_newname(S, pb_slice("proto3"), NULL));
1735 for (i = 0, count = pbL_count(info); i < count; ++i) {
1736 if (info[i].package.p)
1737 pbC(pbL_prefixname(S, info[i].package, &curr, L, NULL));
1738 L->is_proto3 = (pb_name(S, info[i].syntax, NULL) == syntax);
1739 for (j = 0, jcount = pbL_count(info[i].enum_type); j < jcount; ++j)
1740 pbC(pbL_loadEnum(S, &info[i].enum_type[j], L));
1741 for (j = 0, jcount = pbL_count(info[i].message_type); j < jcount; ++j)
1742 pbC(pbL_loadType(S, &info[i].message_type[j], L));
1743 for (j = 0, jcount = pbL_count(info[i].extension); j < jcount; ++j)
1744 pbC(pbL_loadField(S, &info[i].extension[j], L, NULL));
1745 L->b.size = (unsigned)curr;
1746 }
1747 return PB_OK;
1748}
1749
1750PB_API int pb_load(pb_State *S, pb_Slice *s) {
1751 pbL_FileInfo *files = NULL;
1752 pb_Loader L;
1753 int r;
1754 pb_initbuffer(&L.b);
1755 L.s = *s;
1756 L.is_proto3 = 0;
1757 if ((r = pbL_FileDescriptorSet(&L, &files)) == PB_OK)
1758 r = pbL_loadFile(S, files, &L);
1759 pbL_delFileInfo(files);
1760 pb_resetbuffer(&L.b);
1761 s->p = L.s.p;
1762 return r;
1763}
1764
1765
1766PB_NS_END
1767
1768#endif /* PB_IMPLEMENTATION */
1769
1770/* cc: flags+='-shared -DPB_IMPLEMENTATION -xc' output='pb.so' */
1771
Definition pb.h:310
Definition pb.h:282
Definition pb.h:322
Definition pb.h:246
Definition pb.h:128
Definition pb.h:315
Definition pb.h:274
Definition pb.h:335