DCCL v4
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__)
42 typedef unsigned char uint8_t;
43 typedef signed char int8_t;
44 typedef unsigned short uint16_t;
45 typedef signed short int16_t;
46 typedef unsigned int uint32_t;
47 typedef signed int int32_t;
48 typedef unsigned long long uint64_t;
49 typedef 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))
65 typedef unsigned long int uint64_t;
66 typedef signed long int int64_t;
67 # else
68 typedef unsigned long long uint64_t;
69 typedef signed long long int64_t;
70 # endif /* LP64 */
71 # endif /* __sun__ || __digital__ */
72 #endif
73 
74 #include <stddef.h>
75 #include <limits.h>
76 
77 PB_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 
97 typedef 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 
104 typedef 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 
115 PB_API uint64_t pb_expandsig (uint32_t v);
116 PB_API uint32_t pb_encode_sint32 ( int32_t v);
117 PB_API int32_t pb_decode_sint32 (uint32_t v);
118 PB_API uint64_t pb_encode_sint64 ( int64_t v);
119 PB_API int64_t pb_decode_sint64 (uint64_t v);
120 PB_API uint32_t pb_encode_float (float v);
121 PB_API float pb_decode_float (uint32_t v);
122 PB_API uint64_t pb_encode_double (double v);
123 PB_API double pb_decode_double (uint64_t v);
124 
125 
126 /* decode */
127 
128 typedef 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 
133 PB_API pb_Slice pb_slice (const char *p);
134 PB_API pb_Slice pb_lslice (const char *p, size_t len);
135 
136 PB_API size_t pb_pos (const pb_Slice s);
137 PB_API size_t pb_len (const pb_Slice s);
138 
139 PB_API size_t pb_readvarint32 (pb_Slice *s, uint32_t *pv);
140 PB_API size_t pb_readvarint64 (pb_Slice *s, uint64_t *pv);
141 PB_API size_t pb_readfixed32 (pb_Slice *s, uint32_t *pv);
142 PB_API size_t pb_readfixed64 (pb_Slice *s, uint64_t *pv);
143 
144 PB_API size_t pb_readslice (pb_Slice *s, size_t len, pb_Slice *pv);
145 PB_API size_t pb_readbytes (pb_Slice *s, pb_Slice *pv);
146 PB_API size_t pb_readgroup (pb_Slice *s, uint32_t tag, pb_Slice *pv);
147 
148 PB_API size_t pb_skipvarint (pb_Slice *s);
149 PB_API size_t pb_skipbytes (pb_Slice *s);
150 PB_API size_t pb_skipslice (pb_Slice *s, size_t len);
151 PB_API size_t pb_skipvalue (pb_Slice *s, uint32_t tag);
152 
153 PB_API const char *pb_wtypename (int wiretype, const char *def);
154 PB_API const char *pb_typename (int type, const char *def);
155 
156 PB_API int pb_typebyname (const char *name, int def);
157 PB_API int pb_wtypebyname (const char *name, int def);
158 PB_API int pb_wtypebytype (int type);
159 
160 
161 /* encode */
162 
163 #define PB_SSO_SIZE (sizeof(pb_HeapBuffer))
164 
165 typedef struct pb_HeapBuffer {
166  unsigned capacity;
167  char *buff;
168 } pb_HeapBuffer;
169 
170 typedef struct pb_Buffer {
171  unsigned size : sizeof(unsigned)*CHAR_BIT - 1;
172  unsigned heap : 1;
173  union {
174  char buff[PB_SSO_SIZE];
175  pb_HeapBuffer h;
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 
184 PB_API void pb_initbuffer (pb_Buffer *b);
185 PB_API void pb_resetbuffer (pb_Buffer *b);
186 PB_API char *pb_prepbuffsize (pb_Buffer *b, size_t len);
187 
188 PB_API pb_Slice pb_result (const pb_Buffer *b);
189 
190 PB_API size_t pb_addvarint32 (pb_Buffer *b, uint32_t v);
191 PB_API size_t pb_addvarint64 (pb_Buffer *b, uint64_t v);
192 PB_API size_t pb_addfixed32 (pb_Buffer *b, uint32_t v);
193 PB_API size_t pb_addfixed64 (pb_Buffer *b, uint64_t v);
194 
195 PB_API size_t pb_addslice (pb_Buffer *b, pb_Slice s);
196 PB_API size_t pb_addbytes (pb_Buffer *b, pb_Slice s);
197 PB_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 
202 typedef struct pb_State pb_State;
203 typedef struct pb_Name pb_Name;
204 typedef struct pb_Cache pb_Cache;
205 
206 PB_API void pb_init (pb_State *S);
207 PB_API void pb_free (pb_State *S);
208 
209 PB_API pb_Name *pb_newname (pb_State *S, pb_Slice s, pb_Cache *cache);
210 PB_API void pb_delname (pb_State *S, pb_Name *name);
211 PB_API pb_Name *pb_usename (pb_Name *name);
212 
213 PB_API const pb_Name *pb_name (const pb_State *S, pb_Slice s, pb_Cache *cache);
214 
215 
216 /* type info */
217 
218 typedef struct pb_Type pb_Type;
219 typedef struct pb_Field pb_Field;
220 
221 #define PB_OK 0
222 #define PB_ERROR 1
223 #define PB_ENOMEM 2
224 
225 PB_API int pb_load (pb_State *S, pb_Slice *s);
226 
227 PB_API pb_Type *pb_newtype (pb_State *S, pb_Name *tname);
228 PB_API void pb_deltype (pb_State *S, pb_Type *t);
229 PB_API pb_Field *pb_newfield (pb_State *S, pb_Type *t, pb_Name *fname, int32_t number);
230 PB_API void pb_delfield (pb_State *S, pb_Type *t, pb_Field *f);
231 
232 PB_API const pb_Type *pb_type (const pb_State *S, const pb_Name *tname);
233 PB_API const pb_Field *pb_fname (const pb_Type *t, const pb_Name *tname);
234 PB_API const pb_Field *pb_field (const pb_Type *t, int32_t number);
235 
236 PB_API const pb_Name *pb_oneofname (const pb_Type *t, int oneof_index);
237 
238 PB_API int pb_nexttype (const pb_State *S, const pb_Type **ptype);
239 PB_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 
246 typedef struct pb_Pool {
247  void *pages;
248  void *freed;
249  size_t obj_size;
250 } pb_Pool;
251 
252 PB_API void pb_initpool (pb_Pool *pool, size_t obj_size);
253 PB_API void pb_freepool (pb_Pool *pool);
254 
255 PB_API void *pb_poolalloc (pb_Pool *pool);
256 PB_API void pb_poolfree (pb_Pool *pool, void *obj);
257 
258 /* util: hash table */
259 
260 typedef struct pb_Table pb_Table;
261 typedef struct pb_Entry pb_Entry;
262 typedef ptrdiff_t pb_Key;
263 
264 PB_API void pb_inittable (pb_Table *t, size_t entrysize);
265 PB_API void pb_freetable (pb_Table *t);
266 
267 PB_API size_t pb_resizetable (pb_Table *t, size_t size);
268 
269 PB_API pb_Entry *pb_gettable (const pb_Table *t, pb_Key key);
270 PB_API pb_Entry *pb_settable (pb_Table *t, pb_Key key);
271 
272 PB_API int pb_nextentry (const pb_Table *t, const pb_Entry **pentry);
273 
274 struct 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 
282 struct pb_Entry {
283  ptrdiff_t next;
284  pb_Key key;
285 };
286 
287 
288 /* fields */
289 
290 #define PB_CACHE_SIZE (53)
291 
292 typedef struct pb_NameEntry {
293  struct pb_NameEntry *next;
294  unsigned hash : 32;
295  unsigned length : 16;
296  unsigned refcount : 16;
297 } pb_NameEntry;
298 
299 typedef struct pb_NameTable {
300  size_t size;
301  size_t count;
302  pb_NameEntry **hash;
303 } pb_NameTable;
304 
305 typedef struct pb_CacheSlot {
306  const char *name;
307  unsigned hash;
308 } pb_CacheSlot;
309 
310 struct pb_Cache {
311  pb_CacheSlot slots[PB_CACHE_SIZE][2];
312  unsigned hash;
313 };
314 
315 struct pb_State {
316  pb_NameTable nametable;
317  pb_Table types;
318  pb_Pool typepool;
319  pb_Pool fieldpool;
320 };
321 
322 struct 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 
335 struct 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 
352 PB_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 
370 PB_NS_BEGIN
371 
372 
373 /* conversions */
374 
375 PB_API uint32_t pb_encode_sint32(int32_t value)
376 { return ((uint32_t)value << 1) ^ -(value < 0); }
377 
378 PB_API int32_t pb_decode_sint32(uint32_t value)
379 { return (value >> 1) ^ -(int32_t)(value & 1); }
380 
381 PB_API uint64_t pb_encode_sint64(int64_t value)
382 { return ((uint64_t)value << 1) ^ -(value < 0); }
383 
384 PB_API int64_t pb_decode_sint64(uint64_t value)
385 { return (value >> 1) ^ -(int64_t)(value & 1); }
386 
387 PB_API uint64_t pb_expandsig(uint32_t value)
388 { uint64_t m = (uint64_t)1U << 31; return (value ^ m) - m; }
389 
390 PB_API uint32_t pb_encode_float(float value)
391 { union { uint32_t u32; float f; } u; u.f = value; return u.u32; }
392 
393 PB_API float pb_decode_float(uint32_t value)
394 { union { uint32_t u32; float f; } u; u.u32 = value; return u.f; }
395 
396 PB_API uint64_t pb_encode_double(double value)
397 { union { uint64_t u64; double d; } u; u.d = value; return u.u64; }
398 
399 PB_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 
405 PB_API pb_Slice pb_slice(const char *s)
406 { return s ? pb_lslice(s, strlen(s)) : pb_lslice(NULL, 0); }
407 
408 PB_API size_t pb_pos(const pb_Slice s) { return s.p - s.start; }
409 PB_API size_t pb_len(const pb_Slice s) { return s.end - s.p; }
410 
411 static 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 
427 static 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 
448 static 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 
468 PB_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 
475 PB_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 
487 PB_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 
495 PB_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 
509 PB_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 
523 PB_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 
533 PB_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 
547 PB_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 
567 PB_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 
583 PB_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 
591 PB_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 
603 PB_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 
609 PB_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 
632 PB_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 
641 PB_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 
650 PB_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 
664 PB_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 
681 PB_API pb_Slice pb_result(const pb_Buffer *b)
682 { pb_Slice slice = pb_lslice(pb_buffer(b), b->size); return slice; }
683 
684 PB_API void pb_initbuffer(pb_Buffer *b)
685 { memset(b, 0, sizeof(pb_Buffer)); }
686 
687 PB_API void pb_resetbuffer(pb_Buffer *b)
688 { if (pb_onheap(b)) free(b->u.h.buff); pb_initbuffer(b); }
689 
690 static 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 
702 static 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 
719 PB_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 
737 PB_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 
746 PB_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 
764 PB_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 
771 PB_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 
779 PB_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 
787 PB_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 
798 PB_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 
816 PB_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 
822 PB_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 
832 PB_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 
851 PB_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 
860 PB_API void pb_inittable(pb_Table *t, size_t entrysize)
861 { memset(t, 0, sizeof(pb_Table)), t->entry_size = (unsigned)entrysize; }
862 
863 PB_API void pb_freetable(pb_Table *t)
864 { free(t->hash); pb_inittable(t, t->entry_size); }
865 
866 static 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 
872 static 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 
903 PB_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 
926 PB_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 
939 PB_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 
946 PB_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 
967 static void pbN_init(pb_State *S)
968 { memset(&S->nametable, 0, sizeof(pb_NameTable)); }
969 
970 PB_API pb_Name *pb_usename(pb_Name *name)
971 { if (name != NULL) ++((pb_NameEntry*)name-1)->refcount; return name; }
972 
973 static 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 
988 static 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 
997 static 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 
1022 static 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 
1041 static 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 
1056 static 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 
1069 PB_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 
1077 PB_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 
1094 PB_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 
1119 typedef struct pb_TypeEntry { pb_Entry entry; pb_Type *value; } pb_TypeEntry;
1120 typedef struct pb_FieldEntry { pb_Entry entry; pb_Field *value; } pb_FieldEntry;
1121 
1122 typedef struct pb_OneofEntry {
1123  pb_Entry entry;
1124  pb_Name *name;
1125  unsigned index;
1126 } pb_OneofEntry;
1127 
1128 PB_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 
1135 PB_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 
1148 PB_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 
1155 PB_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 
1162 PB_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 
1169 static int comp_field(const void* a, const void* b) {
1170  return (*(const pb_Field**)a)->number - (*(const pb_Field**)b)->number;
1171 }
1172 
1173 PB_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 = 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 
1195 PB_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 
1201 PB_API int pb_nexttype(const pb_State *S, const pb_Type **ptype) {
1202  const pb_TypeEntry *e = NULL;
1203  if (S != NULL) {
1204  if (*ptype != NULL)
1205  e = (pb_TypeEntry*)pb_gettable(&S->types, (pb_Key)(*ptype)->name);
1206  while (pb_nextentry(&S->types, (const pb_Entry**)&e))
1207  if ((*ptype = e->value) != NULL && !(*ptype)->is_dead)
1208  return 1;
1209  }
1210  *ptype = NULL;
1211  return 0;
1212 }
1213 
1214 PB_API int pb_nextfield(const pb_Type *t, const pb_Field **pfield) {
1215  const pb_FieldEntry *e = NULL;
1216  if (t != NULL) {
1217  if (*pfield != NULL)
1218  e = (pb_FieldEntry*)pb_gettable(&t->field_tags, (*pfield)->number);
1219  while (pb_nextentry(&t->field_tags, (const pb_Entry**)&e))
1220  if ((*pfield = e->value) != NULL)
1221  return 1;
1222  }
1223  *pfield = NULL;
1224  return 0;
1225 }
1226 
1227 
1228 /* new type/field */
1229 
1230 static const char *pbT_basename(const char *tname) {
1231  const char *end = tname + strlen(tname);
1232  while (tname < end && *--end != '.')
1233  ;
1234  return *end != '.' ? end : end + 1;
1235 }
1236 
1237 static void pbT_inittype(pb_Type *t) {
1238  memset(t, 0, sizeof(pb_Type));
1239  pb_inittable(&t->field_names, sizeof(pb_FieldEntry));
1240  pb_inittable(&t->field_tags, sizeof(pb_FieldEntry));
1241  pb_inittable(&t->oneof_index, sizeof(pb_OneofEntry));
1242 }
1243 
1244 static void pbT_freefield(pb_State *S, pb_Field *f) {
1245  pb_delname(S, f->default_value);
1246  pb_delname(S, f->name);
1247  pb_poolfree(&S->fieldpool, f);
1248 }
1249 
1250 PB_API pb_Type *pb_newtype(pb_State *S, pb_Name *tname) {
1251  pb_TypeEntry *te;
1252  pb_Type *t;
1253  if (tname == NULL) return NULL;
1254  te = (pb_TypeEntry*)pb_settable(&S->types, (pb_Key)tname);
1255  if (te == NULL) return NULL;
1256  if ((t = te->value) != NULL) return t->is_dead = 0, t;
1257  if (!(t = (pb_Type*)pb_poolalloc(&S->typepool))) return NULL;
1258  pbT_inittype(t);
1259  t->name = tname;
1260  t->basename = pbT_basename((const char*)tname);
1261  return te->value = t;
1262 }
1263 
1264 PB_API void pb_delsort(pb_Type *t) {
1265  if (t->field_sort) {
1266  free(t->field_sort);
1267  t->field_sort = NULL;
1268  }
1269 }
1270 
1271 PB_API void pb_deltype(pb_State *S, pb_Type *t) {
1272  const pb_Entry *e = NULL;
1273  if (S == NULL || t == NULL) return;
1274  while (pb_nextentry(&t->field_names, &e)) {
1275  const pb_FieldEntry *nf = (const pb_FieldEntry*)e;
1276  if (nf->value != NULL) {
1277  pb_FieldEntry *of = (pb_FieldEntry*)pb_gettable(
1278  &t->field_tags, nf->value->number);
1279  if (of && of->value == nf->value)
1280  of->entry.key = 0, of->value = NULL;
1281  pbT_freefield(S, nf->value);
1282  }
1283  }
1284  while (pb_nextentry(&t->field_tags, &e)) {
1285  pb_FieldEntry *nf = (pb_FieldEntry*)e;
1286  if (nf->value != NULL) pbT_freefield(S, nf->value);
1287  }
1288  while (pb_nextentry(&t->oneof_index, &e)) {
1289  pb_OneofEntry *oe = (pb_OneofEntry*)e;
1290  pb_delname(S, oe->name);
1291  }
1292  pb_freetable(&t->field_tags);
1293  pb_freetable(&t->field_names);
1294  pb_freetable(&t->oneof_index);
1295  t->oneof_field = 0, t->field_count = 0;
1296  t->is_dead = 1;
1297  pb_delsort(t);
1298  /*pb_delname(S, t->name); */
1299  /*pb_poolfree(&S->typepool, t); */
1300 }
1301 
1302 PB_API pb_Field *pb_newfield(pb_State *S, pb_Type *t, pb_Name *fname, int32_t number) {
1303  pb_FieldEntry *nf, *tf;
1304  pb_Field *f;
1305  if (fname == NULL) return NULL;
1306  nf = (pb_FieldEntry*)pb_settable(&t->field_names, (pb_Key)fname);
1307  tf = (pb_FieldEntry*)pb_settable(&t->field_tags, number);
1308  if (nf == NULL || tf == NULL) return NULL;
1309  if ((f = nf->value) != NULL && tf->value == f) {
1310  pb_delname(S, f->default_value);
1311  f->default_value = NULL;
1312  return f;
1313  }
1314  if (!(f = (pb_Field*)pb_poolalloc(&S->fieldpool))) return NULL;
1315  memset(f, 0, sizeof(pb_Field));
1316  f->name = fname;
1317  f->type = t;
1318  f->number = number;
1319  if (nf->value && pb_field(t, nf->value->number) != nf->value)
1320  pbT_freefield(S, nf->value), --t->field_count;
1321  if (tf->value && pb_fname(t, tf->value->name) != tf->value)
1322  pbT_freefield(S, tf->value), --t->field_count;
1323  ++t->field_count;
1324  pb_delsort(t);
1325  return nf->value = tf->value = f;
1326 }
1327 
1328 PB_API void pb_delfield(pb_State *S, pb_Type *t, pb_Field *f) {
1329  pb_FieldEntry *nf, *tf;
1330  int count = 0;
1331  if (S == NULL || t == NULL || f == NULL) return;
1332  nf = (pb_FieldEntry*)pb_gettable(&t->field_names, (pb_Key)f->name);
1333  tf = (pb_FieldEntry*)pb_gettable(&t->field_tags, (pb_Key)f->number);
1334  if (nf && nf->value == f) nf->entry.key = 0, nf->value = NULL, ++count;
1335  if (tf && tf->value == f) tf->entry.key = 0, tf->value = NULL, ++count;
1336  if (count) {
1337  if (f->oneof_idx) --t->oneof_field;
1338  pbT_freefield(S, f), --t->field_count;
1339  }
1340  pb_delsort(t);
1341 }
1342 
1343 
1344 /* .pb proto loader */
1345 
1346 typedef struct pb_Loader pb_Loader;
1347 typedef struct pbL_FieldInfo pbL_FieldInfo;
1348 typedef struct pbL_EnumValueInfo pbL_EnumValueInfo;
1349 typedef struct pbL_EnumInfo pbL_EnumInfo;
1350 typedef struct pbL_TypeInfo pbL_TypeInfo;
1351 typedef struct pbL_FileInfo pbL_FileInfo;
1352 
1353 #define pbC(e) do { int r = (e); if (r != PB_OK) return r; } while (0)
1354 #define pbCM(e) do { if ((e) == NULL) return PB_ENOMEM; } while (0)
1355 #define pbCE(e) do { if ((e) == NULL) return PB_ERROR; } while (0)
1356 
1357 typedef struct pb_ArrayHeader {
1358  unsigned count;
1359  unsigned capacity;
1360 } pb_ArrayHeader;
1361 
1362 #define pbL_rawh(A) ((pb_ArrayHeader*)(A) - 1)
1363 #define pbL_delete(A) ((A) ? (void)free(pbL_rawh(A)) : (void)0)
1364 #define pbL_count(A) ((A) ? pbL_rawh(A)->count : 0)
1365 #define pbL_add(A) (pbL_grow((void**)&(A),sizeof(*(A)))==PB_OK ?\
1366  &(A)[pbL_rawh(A)->count++] : NULL)
1367 
1368 struct pb_Loader {
1369  pb_Slice s;
1370  pb_Buffer b;
1371  int is_proto3;
1372 };
1373 
1374 /* parsers */
1375 
1376 struct pbL_EnumValueInfo {
1377  pb_Slice name;
1378  int32_t number;
1379 };
1380 
1381 struct pbL_EnumInfo {
1382  pb_Slice name;
1383  pbL_EnumValueInfo *value;
1384 };
1385 
1386 struct pbL_FieldInfo {
1387  pb_Slice name;
1388  pb_Slice type_name;
1389  pb_Slice extendee;
1390  pb_Slice default_value;
1391  int32_t number;
1392  int32_t label;
1393  int32_t type;
1394  int32_t oneof_index;
1395  int32_t packed;
1396 };
1397 
1398 struct pbL_TypeInfo {
1399  pb_Slice name;
1400  int32_t is_map;
1401  pbL_FieldInfo *field;
1402  pbL_FieldInfo *extension;
1403  pbL_EnumInfo *enum_type;
1404  pbL_TypeInfo *nested_type;
1405  pb_Slice *oneof_decl;
1406 };
1407 
1408 struct pbL_FileInfo {
1409  pb_Slice package;
1410  pb_Slice syntax;
1411  pbL_EnumInfo *enum_type;
1412  pbL_TypeInfo *message_type;
1413  pbL_FieldInfo *extension;
1414 };
1415 
1416 static int pbL_readbytes(pb_Loader *L, pb_Slice *pv)
1417 { return pb_readbytes(&L->s, pv) == 0 ? PB_ERROR : PB_OK; }
1418 
1419 static int pbL_beginmsg(pb_Loader *L, pb_Slice *pv)
1420 { pb_Slice v; pbC(pbL_readbytes(L, &v)); *pv = L->s, L->s = v; return PB_OK; }
1421 
1422 static void pbL_endmsg(pb_Loader *L, pb_Slice *pv)
1423 { L->s = *pv; }
1424 
1425 static int pbL_grow(void **pp, size_t objs) {
1426  pb_ArrayHeader *nh, *h = *pp ? pbL_rawh(*pp) : NULL;
1427  if (h == NULL || h->capacity <= h->count) {
1428  size_t used = (h ? h->count : 0);
1429  size_t size = used + 4, nsize = size + (size >> 1);
1430  nh = nsize < size ? NULL :
1431  (pb_ArrayHeader*)realloc(h, sizeof(pb_ArrayHeader)+nsize*objs);
1432  if (nh == NULL) return PB_ENOMEM;
1433  nh->count = (unsigned)used;
1434  nh->capacity = (unsigned)nsize;
1435  *pp = nh + 1;
1436  memset((char*)*pp + used*objs, 0, (nsize - used)*objs);
1437  }
1438  return PB_OK;
1439 }
1440 
1441 static int pbL_readint32(pb_Loader *L, int32_t *pv) {
1442  uint32_t v;
1443  if (pb_readvarint32(&L->s, &v) == 0) return PB_ERROR;
1444  *pv = (int32_t)v;
1445  return PB_OK;
1446 }
1447 
1448 static int pbL_FieldOptions(pb_Loader *L, pbL_FieldInfo *info) {
1449  pb_Slice s;
1450  uint32_t tag;
1451  pbC(pbL_beginmsg(L, &s));
1452  while (pb_readvarint32(&L->s, &tag)) {
1453  switch (tag) {
1454  case pb_pair(2, PB_TVARINT): /* bool packed */
1455  pbC(pbL_readint32(L, &info->packed)); break;
1456  default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1457  }
1458  }
1459  pbL_endmsg(L, &s);
1460  return PB_OK;
1461 }
1462 
1463 static int pbL_FieldDescriptorProto(pb_Loader *L, pbL_FieldInfo *info) {
1464  pb_Slice s;
1465  uint32_t tag;
1466  pbCM(info); pbC(pbL_beginmsg(L, &s));
1467  info->packed = -1;
1468  while (pb_readvarint32(&L->s, &tag)) {
1469  switch (tag) {
1470  case pb_pair(1, PB_TBYTES): /* string name */
1471  pbC(pbL_readbytes(L, &info->name)); break;
1472  case pb_pair(3, PB_TVARINT): /* int32 number */
1473  pbC(pbL_readint32(L, &info->number)); break;
1474  case pb_pair(4, PB_TVARINT): /* Label label */
1475  pbC(pbL_readint32(L, &info->label)); break;
1476  case pb_pair(5, PB_TVARINT): /* Type type */
1477  pbC(pbL_readint32(L, &info->type)); break;
1478  case pb_pair(6, PB_TBYTES): /* string type_name */
1479  pbC(pbL_readbytes(L, &info->type_name)); break;
1480  case pb_pair(2, PB_TBYTES): /* string extendee */
1481  pbC(pbL_readbytes(L, &info->extendee)); break;
1482  case pb_pair(7, PB_TBYTES): /* string default_value */
1483  pbC(pbL_readbytes(L, &info->default_value)); break;
1484  case pb_pair(8, PB_TBYTES): /* FieldOptions options */
1485  pbC(pbL_FieldOptions(L, info)); break;
1486  case pb_pair(9, PB_TVARINT): /* int32 oneof_index */
1487  pbC(pbL_readint32(L, &info->oneof_index));
1488  ++info->oneof_index; break;
1489  default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1490  }
1491  }
1492  pbL_endmsg(L, &s);
1493  return PB_OK;
1494 }
1495 
1496 static int pbL_EnumValueDescriptorProto(pb_Loader *L, pbL_EnumValueInfo *info) {
1497  pb_Slice s;
1498  uint32_t tag;
1499  pbCM(info); pbC(pbL_beginmsg(L, &s));
1500  while (pb_readvarint32(&L->s, &tag)) {
1501  switch (tag) {
1502  case pb_pair(1, PB_TBYTES): /* string name */
1503  pbC(pbL_readbytes(L, &info->name)); break;
1504  case pb_pair(2, PB_TVARINT): /* int32 number */
1505  pbC(pbL_readint32(L, &info->number)); break;
1506  default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1507  }
1508  }
1509  pbL_endmsg(L, &s);
1510  return PB_OK;
1511 }
1512 
1513 static int pbL_EnumDescriptorProto(pb_Loader *L, pbL_EnumInfo *info) {
1514  pb_Slice s;
1515  uint32_t tag;
1516  pbCM(info); pbC(pbL_beginmsg(L, &s));
1517  while (pb_readvarint32(&L->s, &tag)) {
1518  switch (tag) {
1519  case pb_pair(1, PB_TBYTES): /* string name */
1520  pbC(pbL_readbytes(L, &info->name)); break;
1521  case pb_pair(2, PB_TBYTES): /* EnumValueDescriptorProto value */
1522  pbC(pbL_EnumValueDescriptorProto(L, pbL_add(info->value))); break;
1523  default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1524  }
1525  }
1526  pbL_endmsg(L, &s);
1527  return PB_OK;
1528 }
1529 
1530 static int pbL_MessageOptions(pb_Loader *L, pbL_TypeInfo *info) {
1531  pb_Slice s;
1532  uint32_t tag;
1533  pbCM(info); pbC(pbL_beginmsg(L, &s));
1534  while (pb_readvarint32(&L->s, &tag)) {
1535  switch (tag) {
1536  case pb_pair(7, PB_TVARINT): /* bool map_entry */
1537  pbC(pbL_readint32(L, &info->is_map)); break;
1538  default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1539  }
1540  }
1541  pbL_endmsg(L, &s);
1542  return PB_OK;
1543 }
1544 
1545 static int pbL_OneofDescriptorProto(pb_Loader *L, pbL_TypeInfo *info) {
1546  pb_Slice s;
1547  uint32_t tag;
1548  pbCM(info); pbC(pbL_beginmsg(L, &s));
1549  while (pb_readvarint32(&L->s, &tag)) {
1550  switch (tag) {
1551  case pb_pair(1, PB_TBYTES): /* string name */
1552  pbC(pbL_readbytes(L, pbL_add(info->oneof_decl))); break;
1553  default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1554  }
1555  }
1556  pbL_endmsg(L, &s);
1557  return PB_OK;
1558 }
1559 
1560 static int pbL_DescriptorProto(pb_Loader *L, pbL_TypeInfo *info) {
1561  pb_Slice s;
1562  uint32_t tag;
1563  pbCM(info); pbC(pbL_beginmsg(L, &s));
1564  while (pb_readvarint32(&L->s, &tag)) {
1565  switch (tag) {
1566  case pb_pair(1, PB_TBYTES): /* string name */
1567  pbC(pbL_readbytes(L, &info->name)); break;
1568  case pb_pair(2, PB_TBYTES): /* FieldDescriptorProto field */
1569  pbC(pbL_FieldDescriptorProto(L, pbL_add(info->field))); break;
1570  case pb_pair(6, PB_TBYTES): /* FieldDescriptorProto extension */
1571  pbC(pbL_FieldDescriptorProto(L, pbL_add(info->extension))); break;
1572  case pb_pair(3, PB_TBYTES): /* DescriptorProto nested_type */
1573  pbC(pbL_DescriptorProto(L, pbL_add(info->nested_type))); break;
1574  case pb_pair(4, PB_TBYTES): /* EnumDescriptorProto enum_type */
1575  pbC(pbL_EnumDescriptorProto(L, pbL_add(info->enum_type))); break;
1576  case pb_pair(8, PB_TBYTES): /* OneofDescriptorProto oneof_decl */
1577  pbC(pbL_OneofDescriptorProto(L, info)); break;
1578  case pb_pair(7, PB_TBYTES): /* MessageOptions options */
1579  pbC(pbL_MessageOptions(L, info)); break;
1580  default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1581  }
1582  }
1583  pbL_endmsg(L, &s);
1584  return PB_OK;
1585 }
1586 
1587 static int pbL_FileDescriptorProto(pb_Loader *L, pbL_FileInfo *info) {
1588  pb_Slice s;
1589  uint32_t tag;
1590  pbCM(info); pbC(pbL_beginmsg(L, &s));
1591  while (pb_readvarint32(&L->s, &tag)) {
1592  switch (tag) {
1593  case pb_pair(2, PB_TBYTES): /* string package */
1594  pbC(pbL_readbytes(L, &info->package)); break;
1595  case pb_pair(4, PB_TBYTES): /* DescriptorProto message_type */
1596  pbC(pbL_DescriptorProto(L, pbL_add(info->message_type))); break;
1597  case pb_pair(5, PB_TBYTES): /* EnumDescriptorProto enum_type */
1598  pbC(pbL_EnumDescriptorProto(L, pbL_add(info->enum_type))); break;
1599  case pb_pair(7, PB_TBYTES): /* FieldDescriptorProto extension */
1600  pbC(pbL_FieldDescriptorProto(L, pbL_add(info->extension))); break;
1601  case pb_pair(12, PB_TBYTES): /* string syntax */
1602  pbC(pbL_readbytes(L, &info->syntax)); break;
1603  default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1604  }
1605  }
1606  pbL_endmsg(L, &s);
1607  return PB_OK;
1608 }
1609 
1610 static int pbL_FileDescriptorSet(pb_Loader *L, pbL_FileInfo **pfiles) {
1611  uint32_t tag;
1612  while (pb_readvarint32(&L->s, &tag)) {
1613  switch (tag) {
1614  case pb_pair(1, PB_TBYTES): /* FileDescriptorProto file */
1615  pbC(pbL_FileDescriptorProto(L, pbL_add(*pfiles))); break;
1616  default: if (pb_skipvalue(&L->s, tag) == 0) return PB_ERROR;
1617  }
1618  }
1619  return PB_OK;
1620 }
1621 
1622 /* loader */
1623 
1624 static void pbL_delTypeInfo(pbL_TypeInfo *info) {
1625  size_t i, count;
1626  for (i = 0, count = pbL_count(info->nested_type); i < count; ++i)
1627  pbL_delTypeInfo(&info->nested_type[i]);
1628  for (i = 0, count = pbL_count(info->enum_type); i < count; ++i)
1629  pbL_delete(info->enum_type[i].value);
1630  pbL_delete(info->nested_type);
1631  pbL_delete(info->enum_type);
1632  pbL_delete(info->field);
1633  pbL_delete(info->extension);
1634  pbL_delete(info->oneof_decl);
1635 }
1636 
1637 static void pbL_delFileInfo(pbL_FileInfo *files) {
1638  size_t i, count, j, jcount;
1639  for (i = 0, count = pbL_count(files); i < count; ++i) {
1640  for (j = 0, jcount = pbL_count(files[i].message_type); j < jcount; ++j)
1641  pbL_delTypeInfo(&files[i].message_type[j]);
1642  for (j = 0, jcount = pbL_count(files[i].enum_type); j < jcount; ++j)
1643  pbL_delete(files[i].enum_type[j].value);
1644  pbL_delete(files[i].message_type);
1645  pbL_delete(files[i].enum_type);
1646  pbL_delete(files[i].extension);
1647  }
1648  pbL_delete(files);
1649 }
1650 
1651 static int pbL_prefixname(pb_State *S, pb_Slice s, size_t *ps, pb_Loader *L, pb_Name **out) {
1652  char *buff;
1653  *ps = pb_bufflen(&L->b);
1654  pbCM(buff = pb_prepbuffsize(&L->b, pb_len(s) + 1));
1655  *buff = '.'; pb_addsize(&L->b, 1);
1656  if (pb_addslice(&L->b, s) == 0) return PB_ENOMEM;
1657  if (out) *out = pb_newname(S, pb_result(&L->b), NULL);
1658  return PB_OK;
1659 }
1660 
1661 static int pbL_loadEnum(pb_State *S, pbL_EnumInfo *info, pb_Loader *L) {
1662  size_t i, count, curr;
1663  pb_Name *name;
1664  pb_Type *t;
1665  pbC(pbL_prefixname(S, info->name, &curr, L, &name));
1666  pbCM(t = pb_newtype(S, name));
1667  t->is_enum = 1;
1668  for (i = 0, count = pbL_count(info->value); i < count; ++i) {
1669  pbL_EnumValueInfo *ev = &info->value[i];
1670  pbCE(pb_newfield(S, t, pb_newname(S, ev->name, NULL), ev->number));
1671  }
1672  L->b.size = (unsigned)curr;
1673  return PB_OK;
1674 }
1675 
1676 static int pbL_loadField(pb_State *S, pbL_FieldInfo *info, pb_Loader *L, pb_Type *t) {
1677  pb_Type *ft = NULL;
1678  pb_Field *f;
1679  if (info->type == PB_Tmessage || info->type == PB_Tenum)
1680  pbCE(ft = pb_newtype(S, pb_newname(S, info->type_name, NULL)));
1681  if (t == NULL)
1682  pbCE(t = pb_newtype(S, pb_newname(S, info->extendee, NULL)));
1683  pbCE(f = pb_newfield(S, t, pb_newname(S, info->name, NULL), info->number));
1684  f->default_value = pb_newname(S, info->default_value, NULL);
1685  f->type = ft;
1686  if ((f->oneof_idx = info->oneof_index)) ++t->oneof_field;
1687  f->type_id = info->type;
1688  f->repeated = info->label == 3; /* repeated */
1689  f->packed = info->packed >= 0 ? info->packed : L->is_proto3 && f->repeated;
1690  if (f->type_id >= 9 && f->type_id <= 12) f->packed = 0;
1691  f->scalar = (f->type == NULL);
1692  return PB_OK;
1693 }
1694 
1695 static int pbL_loadType(pb_State *S, pbL_TypeInfo *info, pb_Loader *L) {
1696  size_t i, count, curr;
1697  pb_Name *name;
1698  pb_Type *t;
1699  pbC(pbL_prefixname(S, info->name, &curr, L, &name));
1700  pbCM(t = pb_newtype(S, name));
1701  t->is_map = info->is_map, t->is_proto3 = L->is_proto3;
1702  for (i = 0, count = pbL_count(info->oneof_decl); i < count; ++i) {
1703  pb_OneofEntry *e = (pb_OneofEntry*)pb_settable(&t->oneof_index, i+1);
1704  pbCM(e); pbCE(e->name = pb_newname(S, info->oneof_decl[i], NULL));
1705  e->index = (int)i+1;
1706  }
1707  for (i = 0, count = pbL_count(info->field); i < count; ++i)
1708  pbC(pbL_loadField(S, &info->field[i], L, t));
1709  for (i = 0, count = pbL_count(info->extension); i < count; ++i)
1710  pbC(pbL_loadField(S, &info->extension[i], L, NULL));
1711  for (i = 0, count = pbL_count(info->enum_type); i < count; ++i)
1712  pbC(pbL_loadEnum(S, &info->enum_type[i], L));
1713  for (i = 0, count = pbL_count(info->nested_type); i < count; ++i)
1714  pbC(pbL_loadType(S, &info->nested_type[i], L));
1715  t->oneof_count = pbL_count(info->oneof_decl);
1716  L->b.size = (unsigned)curr;
1717  return PB_OK;
1718 }
1719 
1720 static int pbL_loadFile(pb_State *S, pbL_FileInfo *info, pb_Loader *L) {
1721  size_t i, count, j, jcount, curr = 0;
1722  pb_Name *syntax;
1723  pbCM(syntax = pb_newname(S, pb_slice("proto3"), NULL));
1724  for (i = 0, count = pbL_count(info); i < count; ++i) {
1725  if (info[i].package.p)
1726  pbC(pbL_prefixname(S, info[i].package, &curr, L, NULL));
1727  L->is_proto3 = (pb_name(S, info[i].syntax, NULL) == syntax);
1728  for (j = 0, jcount = pbL_count(info[i].enum_type); j < jcount; ++j)
1729  pbC(pbL_loadEnum(S, &info[i].enum_type[j], L));
1730  for (j = 0, jcount = pbL_count(info[i].message_type); j < jcount; ++j)
1731  pbC(pbL_loadType(S, &info[i].message_type[j], L));
1732  for (j = 0, jcount = pbL_count(info[i].extension); j < jcount; ++j)
1733  pbC(pbL_loadField(S, &info[i].extension[j], L, NULL));
1734  L->b.size = (unsigned)curr;
1735  }
1736  return PB_OK;
1737 }
1738 
1739 PB_API int pb_load(pb_State *S, pb_Slice *s) {
1740  pbL_FileInfo *files = NULL;
1741  pb_Loader L;
1742  int r;
1743  pb_initbuffer(&L.b);
1744  L.s = *s;
1745  L.is_proto3 = 0;
1746  if ((r = pbL_FileDescriptorSet(&L, &files)) == PB_OK)
1747  r = pbL_loadFile(S, files, &L);
1748  pbL_delFileInfo(files);
1749  pb_resetbuffer(&L.b);
1750  s->p = L.s.p;
1751  return r;
1752 }
1753 
1754 
1755 PB_NS_END
1756 
1757 #endif /* PB_IMPLEMENTATION */
1758 
1759 /* cc: flags+='-shared -DPB_IMPLEMENTATION -xc' output='pb.so' */
1760 
pb_State
Definition: pb.h:315
pb_Cache
Definition: pb.h:310
pb_NameTable
Definition: pb.h:299
pb_HeapBuffer
Definition: pb.h:165
pb_Entry
Definition: pb.h:282
pb_CacheSlot
Definition: pb.h:305
pb_NameEntry
Definition: pb.h:292
pb_Slice
Definition: pb.h:128
pb_Table
Definition: pb.h:274
pb_Pool
Definition: pb.h:246
pb_Buffer
Definition: pb.h:170
pb_Type
Definition: pb.h:335
pb_Field
Definition: pb.h:322