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 = (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 
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  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 
1219 PB_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 
1240 static 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 
1247 static 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 
1254 static 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 
1260 PB_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 
1274 PB_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 
1281 PB_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 
1312 PB_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 
1338 PB_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 
1356 typedef struct pb_Loader pb_Loader;
1357 typedef struct pbL_FieldInfo pbL_FieldInfo;
1358 typedef struct pbL_EnumValueInfo pbL_EnumValueInfo;
1359 typedef struct pbL_EnumInfo pbL_EnumInfo;
1360 typedef struct pbL_TypeInfo pbL_TypeInfo;
1361 typedef 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 
1367 typedef 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 
1378 struct pb_Loader {
1379  pb_Slice s;
1380  pb_Buffer b;
1381  int is_proto3;
1382 };
1383 
1384 /* parsers */
1385 
1386 struct pbL_EnumValueInfo {
1387  pb_Slice name;
1388  int32_t number;
1389 };
1390 
1391 struct pbL_EnumInfo {
1392  pb_Slice name;
1393  pbL_EnumValueInfo *value;
1394 };
1395 
1396 struct 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 
1408 struct 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 
1418 struct 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 
1426 static int pbL_readbytes(pb_Loader *L, pb_Slice *pv)
1427 { return pb_readbytes(&L->s, pv) == 0 ? PB_ERROR : PB_OK; }
1428 
1429 static 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 
1432 static void pbL_endmsg(pb_Loader *L, pb_Slice *pv)
1433 { L->s = *pv; }
1434 
1435 static 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 
1452 static 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 
1459 static 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 
1474 static 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 
1507 static 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 
1524 static 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 
1541 static 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 
1556 static 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 
1571 static 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 
1598 static 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 
1621 static 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 
1635 static 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 
1648 static 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 
1662 static 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 
1672 static 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 
1687 static 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 
1706 static 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 
1731 static 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 
1750 PB_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 
1766 PB_NS_END
1767 
1768 #endif /* PB_IMPLEMENTATION */
1769 
1770 /* cc: flags+='-shared -DPB_IMPLEMENTATION -xc' output='pb.so' */
1771 
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