6 # define PB_NS_BEGIN extern "C" {
16 # define PB_STATIC static __attribute((unused))
18 # define PB_STATIC static
23 # ifndef PB_IMPLEMENTATION
24 # define PB_IMPLEMENTATION
26 # define PB_API PB_STATIC
29 #if !defined(PB_API) && defined(_WIN32)
30 # ifdef PB_IMPLEMENTATION
31 # define PB_API __declspec(dllexport)
33 # define PB_API __declspec(dllimport)
38 # define PB_API extern
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;
52 # define INT64_MIN LLONG_MIN
56 # define INT64_MAX LLONG_MAX
59 #elif defined(__SCO__) || defined(__USLC__) || defined(__MINGW32__)
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;
68 typedef unsigned long long uint64_t;
69 typedef signed long long int64_t;
82 #define PB_WIRETYPES(X) \
83 X(VARINT, "varint", 'v') X(64BIT, "64bit", 'q') X(BYTES, "bytes", 's') \
84 X(GSTART, "gstart", '!') X(GEND, "gend", '!') X(32BIT, "32bit", 'd') \
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') \
97 typedef enum pb_WireType {
98 #define X(id,name,fmt) PB_T##id,
104 typedef enum pb_FieldType {
106 #define X(name,type,fmt) PB_T##name,
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);
129 #define pb_gettype(v) ((v) & 7)
130 #define pb_gettag(v) ((v) >> 3)
131 #define pb_pair(tag,type) ((tag) << 3 | ((type) & 7))
133 PB_API
pb_Slice pb_slice (
const char *p);
134 PB_API
pb_Slice pb_lslice (
const char *p,
size_t len);
136 PB_API
size_t pb_pos (
const pb_Slice s);
137 PB_API
size_t pb_len (
const pb_Slice s);
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);
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);
153 PB_API
const char *pb_wtypename (
int wiretype,
const char *def);
154 PB_API
const char *pb_typename (
int type,
const char *def);
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);
163 #define PB_SSO_SIZE (sizeof(pb_HeapBuffer))
171 unsigned size :
sizeof(unsigned)*CHAR_BIT - 1;
174 char buff[PB_SSO_SIZE];
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)))
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);
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);
197 PB_API
size_t pb_addlength (
pb_Buffer *b,
size_t len,
size_t prealloc);
203 typedef struct pb_Name pb_Name;
210 PB_API
void pb_delname (
pb_State *S, pb_Name *name);
211 PB_API pb_Name *pb_usename (pb_Name *name);
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);
236 PB_API
const pb_Name *pb_oneofname (
const pb_Type *t,
int oneof_index);
244 #define PB_POOLSIZE 4096
252 PB_API
void pb_initpool (
pb_Pool *pool,
size_t obj_size);
253 PB_API
void pb_freepool (
pb_Pool *pool);
255 PB_API
void *pb_poolalloc (
pb_Pool *pool);
256 PB_API
void pb_poolfree (
pb_Pool *pool,
void *obj);
262 typedef ptrdiff_t pb_Key;
264 PB_API
void pb_inittable (
pb_Table *t,
size_t entrysize);
265 PB_API
void pb_freetable (
pb_Table *t);
267 PB_API
size_t pb_resizetable (
pb_Table *t,
size_t size);
277 unsigned entry_size :
sizeof(unsigned)*CHAR_BIT - 1;
278 unsigned has_zero : 1;
290 #define PB_CACHE_SIZE (53)
295 unsigned length : 16;
296 unsigned refcount : 16;
325 pb_Name *default_value;
328 unsigned oneof_idx : 24;
329 unsigned type_id : 5;
330 unsigned repeated : 1;
337 const char *basename;
342 unsigned oneof_count;
343 unsigned oneof_field;
344 unsigned field_count : 28;
345 unsigned is_enum : 1;
347 unsigned is_proto3 : 1;
348 unsigned is_dead : 1;
357 #if defined(PB_IMPLEMENTATION) && !defined(pb_implemented)
358 #define pb_implemented
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
375 PB_API uint32_t pb_encode_sint32(int32_t value)
376 {
return ((uint32_t)value << 1) ^ -(value < 0); }
378 PB_API int32_t pb_decode_sint32(uint32_t value)
379 {
return (value >> 1) ^ -(int32_t)(value & 1); }
381 PB_API uint64_t pb_encode_sint64(int64_t value)
382 {
return ((uint64_t)value << 1) ^ -(value < 0); }
384 PB_API int64_t pb_decode_sint64(uint64_t value)
385 {
return (value >> 1) ^ -(int64_t)(value & 1); }
387 PB_API uint64_t pb_expandsig(uint32_t value)
388 { uint64_t m = (uint64_t)1U << 31;
return (value ^ m) - m; }
390 PB_API uint32_t pb_encode_float(
float value)
391 {
union { uint32_t u32;
float f; } u; u.f = value;
return u.u32; }
393 PB_API
float pb_decode_float(uint32_t value)
394 {
union { uint32_t u32;
float f; } u; u.u32 = value;
return u.f; }
396 PB_API uint64_t pb_encode_double(
double value)
397 {
union { uint64_t u64;
double d; } u; u.d = value;
return u.u64; }
399 PB_API
double pb_decode_double(uint64_t value)
400 {
union { uint64_t u64;
double d; } u; u.u64 = value;
return u.d; }
405 PB_API
pb_Slice pb_slice(
const char *s)
406 {
return s ? pb_lslice(s, strlen(s)) : pb_lslice(NULL, 0); }
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; }
411 static size_t pb_readvarint_slow(
pb_Slice *s, uint64_t *pv) {
412 const char *p = s->p;
415 while (s->p < s->end && i < 10) {
417 n |= ((uint64_t)b & 0x7F) << (7*i++);
418 if ((b & 0x80) == 0) {
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;
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;
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;
444 s->p = (
const char*)p;
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;
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;
463 *pv = n1 | ((uint64_t)n2 << 28) | ((uint64_t)n3 << 56);
464 s->p = (
const char*)p;
468 PB_API
pb_Slice pb_lslice(
const char *s,
size_t len) {
470 slice.start = slice.p = s;
475 PB_API
size_t pb_readvarint32(
pb_Slice *s, uint32_t *pv) {
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)
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);
495 PB_API
size_t pb_readfixed32(
pb_Slice *s, uint32_t *pv) {
498 if (s->p + 4 > s->end)
500 for (i = 3; i >= 0; --i) {
509 PB_API
size_t pb_readfixed64(
pb_Slice *s, uint64_t *pv) {
512 if (s->p + 8 > s->end)
514 for (i = 7; i >= 0; --i) {
524 if (pb_len(*s) < len)
526 pv->start = s->start;
528 pv->end = s->p + len;
534 const char *p = s->p;
536 if (pb_readvarint64(s, &len) == 0 || pb_len(*s) < len) {
540 pv->start = s->start;
542 pv->end = s->p + len;
548 const char *p = s->p;
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))
556 pv->start = s->start;
558 pv->end = s->p - count;
561 if (pb_skipvalue(s, newtag) == 0)
break;
567 PB_API
size_t pb_skipvalue(
pb_Slice *s, uint32_t tag) {
568 const char *p = s->p;
571 switch (pb_gettype(tag)) {
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;
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;
591 PB_API
size_t pb_skipbytes(
pb_Slice *s) {
592 const char *p = s->p;
594 if (!pb_readvarint64(s, &var))
return 0;
595 if (pb_len(*s) < var) {
603 PB_API
size_t pb_skipslice(
pb_Slice *s,
size_t len) {
604 if (s->p + len > s->end)
return 0;
609 PB_API
int pb_wtypebytype(
int 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;
632 PB_API
const char *pb_wtypename(
int wiretype,
const char *def) {
634 #define X(id,name,fmt) case PB_T##id: return name;
637 default:
return def ? def :
"<unknown>";
641 PB_API
const char *pb_typename(
int type,
const char *def) {
643 #define X(name,type,fmt) case PB_T##name: return #name;
646 default:
return def ? def :
"<unknown>";
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 },
658 for (p = names; p->name != NULL; ++p)
659 if (strcmp(p->name, name) == 0)
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 },
672 for (p = names; p->name != NULL; ++p)
673 if (strcmp(p->name, name) == 0)
682 {
pb_Slice slice = pb_lslice(pb_buffer(b), b->size);
return slice; }
688 {
if (pb_onheap(b)) free(b->u.h.buff); pb_initbuffer(b); }
690 static int pb_write32(
char *buff, uint32_t n) {
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;
699 return *buff++ = p, ++c;
702 static int pb_write64(
char *buff, uint64_t n) {
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;
716 return *buff++ = p, ++c;
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);
732 b->u.h.capacity = (unsigned)newsize;
734 return &pb_buffer(b)[b->size];
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);
746 PB_API
size_t pb_addlength(
pb_Buffer *b,
size_t len,
size_t prealloc) {
748 size_t bl, ml, rl = 0;
749 if ((bl = pb_bufflen(b)) < len)
751 ml = pb_write64(buff, bl - len);
752 s = pb_buffer(b) + len - prealloc;
753 assert(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);
761 return ml + (bl - len);
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);
771 PB_API
size_t pb_addvarint32(
pb_Buffer *b, uint32_t n) {
772 char *buff = pb_prepbuffsize(b, 5);
774 if (buff == NULL)
return 0;
775 pb_addsize(b, l = pb_write32(buff, n));
779 PB_API
size_t pb_addvarint64(
pb_Buffer *b, uint64_t n) {
780 char *buff = pb_prepbuffsize(b, 10);
782 if (buff == NULL)
return 0;
783 pb_addsize(b, l = pb_write64(buff, n));
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;
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;
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);
822 PB_API
void pb_freepool(
pb_Pool *pool) {
823 void *page = pool->pages;
825 void *next = *(
void**)((
char*)page + PB_POOLSIZE -
sizeof(
void*));
829 pb_initpool(pool, pool->obj_size);
832 PB_API
void *pb_poolalloc(
pb_Pool *pool) {
833 void *obj = pool->freed;
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;
843 *(
void**)((
char*)newpage + PB_POOLSIZE -
sizeof(
void*)) = pool->pages;
844 pool->pages = newpage;
847 pool->freed = *(
void**)obj;
851 PB_API
void pb_poolfree(
pb_Pool *pool,
void *obj)
852 { *(
void**)obj = pool->freed, pool->freed = obj; }
857 #define pbT_offset(a,b) ((char*)(a) - (char*)(b))
858 #define pbT_index(a,b) ((pb_Entry*)((char*)(a) + (b)))
860 PB_API
void pb_inittable(
pb_Table *t,
size_t entrysize)
861 { memset(t, 0,
sizeof(
pb_Table)), t->entry_size = (unsigned)entrysize; }
863 PB_API
void pb_freetable(
pb_Table *t)
864 { free(t->hash); pb_inittable(t, t->entry_size); }
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);
873 pb_Entry *mp, *on, *next, *f = NULL;
874 if (t->size == 0 && pb_resizetable(t, (
size_t)t->size*2) == 0)
return NULL;
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; }
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;
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);
898 if (t->entry_size !=
sizeof(
pb_Entry))
899 memset(mp+1, 0, t->entry_size -
sizeof(
pb_Entry));
903 PB_API
size_t pb_resizetable(
pb_Table *t,
size_t size) {
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)
909 if (newsize < size)
return 0;
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) {
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));
928 if (t == NULL || t->size == 0)
931 return t->has_zero ? t->hash : NULL;
932 for (entry = pbT_hash(t, key);
934 entry = pbT_index(entry, entry->next))
935 if (entry->next == 0)
return NULL;
941 if ((entry = pb_gettable(t, key)) != NULL)
943 return pbT_newkey(t, key);
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) {
953 while (i += t->entry_size, i < size) {
954 pb_Entry *entry = pbT_index(t->hash, i);
955 if (entry->key != 0) {
970 PB_API pb_Name *pb_usename(pb_Name *name)
971 {
if (name != NULL) ++((
pb_NameEntry*)name-1)->refcount;
return name; }
976 for (i = 0; i < nt->size; ++i) {
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]));
997 static size_t pbN_resize(
pb_State *S,
size_t size) {
1000 size_t i, newsize = PB_MIN_STRTABLE_SIZE;
1001 while (newsize < PB_MAX_HASHSIZE/
sizeof(
pb_NameEntry*) && newsize < size)
1003 if (newsize < size)
return 0;
1005 if (hash == NULL)
return 0;
1007 for (i = 0; i < nt->size; ++i) {
1009 while (entry != NULL) {
1011 pb_NameEntry **newh = &hash[entry->hash & (newsize - 1)];
1012 entry->next = *newh, *newh = entry;
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)];
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';
1043 pb_NameEntry **list = &nt->hash[name->hash & (nt->size - 1)];
1044 while (*list != NULL) {
1046 list = &(*list)->next;
1048 *list = (*list)->next;
1058 size_t len = pb_len(s);
1061 for (; entry != NULL; entry = entry->next)
1062 if (entry->hash == hash && entry->length == len
1063 && memcmp(s.p, entry + 1, len) == 0)
1069 PB_API
void pb_delname(
pb_State *S, pb_Name *name) {
1072 if (ne->refcount <= 1) { pbN_delname(S, ne);
return; }
1079 if (s.p == NULL)
return NULL;
1081 assert(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);
1091 return entry ? pb_usename((pb_Name*)(entry + 1)) : NULL;
1097 if (S == NULL || s.p == NULL)
return NULL;
1099 entry = pbN_getname(S, s, pbN_calchash(s));
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);
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);
1113 return entry ? (pb_Name*)(entry + 1) : NULL;
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;
1122 typedef struct pb_OneofEntry {
1130 S->types.entry_size =
sizeof(pb_TypeEntry);
1131 pb_initpool(&S->typepool,
sizeof(
pb_Type));
1132 pb_initpool(&S->fieldpool,
sizeof(
pb_Field));
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);
1142 pb_freetable(&S->types);
1143 pb_freepool(&S->typepool);
1144 pb_freepool(&S->fieldpool);
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;
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;
1163 pb_FieldEntry *fe = NULL;
1164 if (t != NULL) fe = (pb_FieldEntry*)pb_gettable(&t->field_tags, number);
1165 return fe ? fe->value : NULL;
1169 static int comp_field(
const void* a,
const void* b) {
1174 if (!t->field_sort && t->field_count) {
1181 while (pb_nextfield(t, &f)) {
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;
1189 t->field_sort = list;
1192 return t->field_sort;
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;
1204 if (*ptype != NULL) {
1205 const pb_TypeEntry *e = (
const pb_TypeEntry*)
1206 pb_gettable(&S->types, (pb_Key)(*ptype)->name);
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)
1222 if (*pfield != NULL) {
1223 const pb_FieldEntry *e = (
const pb_FieldEntry*)
1224 pb_gettable(&t->field_tags, (*pfield)->number);
1227 while (pb_nextentry(&t->field_tags, &ent)) {
1228 const pb_FieldEntry *e = (
const pb_FieldEntry*)ent;
1229 if ((*pfield = e->value) != NULL)
1240 static const char *pbT_basename(
const char *tname) {
1241 const char *end = tname + strlen(tname);
1242 while (tname < end && *--end !=
'.')
1244 return *end !=
'.' ? end : end + 1;
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));
1255 pb_delname(S, f->default_value);
1256 pb_delname(S, f->name);
1257 pb_poolfree(&S->fieldpool, f);
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;
1270 t->basename = pbT_basename((
const char*)tname);
1271 return te->value = t;
1274 PB_API
void pb_delsort(
pb_Type *t) {
1275 if (t->field_sort) {
1276 free(t->field_sort);
1277 t->field_sort = 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);
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);
1298 while (pb_nextentry(&t->oneof_index, &e)) {
1299 pb_OneofEntry *oe = (pb_OneofEntry*)e;
1300 pb_delname(S, oe->name);
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;
1313 pb_FieldEntry *nf, *tf;
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;
1324 if (!(f = (
pb_Field*)pb_poolalloc(&S->fieldpool)))
return NULL;
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;
1335 return nf->value = tf->value = f;
1339 pb_FieldEntry *nf, *tf;
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;
1347 if (f->oneof_idx) --t->oneof_field;
1348 pbT_freefield(S, f), --t->field_count;
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;
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)
1367 typedef struct pb_ArrayHeader {
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)
1386 struct pbL_EnumValueInfo {
1391 struct pbL_EnumInfo {
1393 pbL_EnumValueInfo *value;
1396 struct pbL_FieldInfo {
1404 int32_t oneof_index;
1408 struct pbL_TypeInfo {
1411 pbL_FieldInfo *field;
1412 pbL_FieldInfo *extension;
1413 pbL_EnumInfo *enum_type;
1414 pbL_TypeInfo *nested_type;
1418 struct pbL_FileInfo {
1421 pbL_EnumInfo *enum_type;
1422 pbL_TypeInfo *message_type;
1423 pbL_FieldInfo *extension;
1426 static int pbL_readbytes(pb_Loader *L,
pb_Slice *pv)
1427 {
return pb_readbytes(&L->s, pv) == 0 ? PB_ERROR : PB_OK; }
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; }
1432 static void pbL_endmsg(pb_Loader *L,
pb_Slice *pv)
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;
1447 memset((
char*)*up.pp + used*objs, 0, (nsize - used)*objs);
1452 static int pbL_readint32(pb_Loader *L, int32_t *pv) {
1454 if (pb_readvarint32(&L->s, &v) == 0)
return PB_ERROR;
1459 static int pbL_FieldOptions(pb_Loader *L, pbL_FieldInfo *info) {
1462 pbC(pbL_beginmsg(L, &s));
1463 while (pb_readvarint32(&L->s, &tag)) {
1465 case pb_pair(2, PB_TVARINT):
1466 pbC(pbL_readint32(L, &info->packed));
break;
1467 default:
if (pb_skipvalue(&L->s, tag) == 0)
return PB_ERROR;
1474 static int pbL_FieldDescriptorProto(pb_Loader *L, pbL_FieldInfo *info) {
1477 pbCM(info); pbC(pbL_beginmsg(L, &s));
1479 while (pb_readvarint32(&L->s, &tag)) {
1481 case pb_pair(1, PB_TBYTES):
1482 pbC(pbL_readbytes(L, &info->name));
break;
1483 case pb_pair(3, PB_TVARINT):
1484 pbC(pbL_readint32(L, &info->number));
break;
1485 case pb_pair(4, PB_TVARINT):
1486 pbC(pbL_readint32(L, &info->label));
break;
1487 case pb_pair(5, PB_TVARINT):
1488 pbC(pbL_readint32(L, &info->type));
break;
1489 case pb_pair(6, PB_TBYTES):
1490 pbC(pbL_readbytes(L, &info->type_name));
break;
1491 case pb_pair(2, PB_TBYTES):
1492 pbC(pbL_readbytes(L, &info->extendee));
break;
1493 case pb_pair(7, PB_TBYTES):
1494 pbC(pbL_readbytes(L, &info->default_value));
break;
1495 case pb_pair(8, PB_TBYTES):
1496 pbC(pbL_FieldOptions(L, info));
break;
1497 case pb_pair(9, PB_TVARINT):
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;
1507 static int pbL_EnumValueDescriptorProto(pb_Loader *L, pbL_EnumValueInfo *info) {
1510 pbCM(info); pbC(pbL_beginmsg(L, &s));
1511 while (pb_readvarint32(&L->s, &tag)) {
1513 case pb_pair(1, PB_TBYTES):
1514 pbC(pbL_readbytes(L, &info->name));
break;
1515 case pb_pair(2, PB_TVARINT):
1516 pbC(pbL_readint32(L, &info->number));
break;
1517 default:
if (pb_skipvalue(&L->s, tag) == 0)
return PB_ERROR;
1524 static int pbL_EnumDescriptorProto(pb_Loader *L, pbL_EnumInfo *info) {
1527 pbCM(info); pbC(pbL_beginmsg(L, &s));
1528 while (pb_readvarint32(&L->s, &tag)) {
1530 case pb_pair(1, PB_TBYTES):
1531 pbC(pbL_readbytes(L, &info->name));
break;
1532 case pb_pair(2, PB_TBYTES):
1533 pbC(pbL_EnumValueDescriptorProto(L, pbL_add(info->value)));
break;
1534 default:
if (pb_skipvalue(&L->s, tag) == 0)
return PB_ERROR;
1541 static int pbL_MessageOptions(pb_Loader *L, pbL_TypeInfo *info) {
1544 pbCM(info); pbC(pbL_beginmsg(L, &s));
1545 while (pb_readvarint32(&L->s, &tag)) {
1547 case pb_pair(7, PB_TVARINT):
1548 pbC(pbL_readint32(L, &info->is_map));
break;
1549 default:
if (pb_skipvalue(&L->s, tag) == 0)
return PB_ERROR;
1556 static int pbL_OneofDescriptorProto(pb_Loader *L, pbL_TypeInfo *info) {
1559 pbCM(info); pbC(pbL_beginmsg(L, &s));
1560 while (pb_readvarint32(&L->s, &tag)) {
1562 case pb_pair(1, PB_TBYTES):
1563 pbC(pbL_readbytes(L, pbL_add(info->oneof_decl)));
break;
1564 default:
if (pb_skipvalue(&L->s, tag) == 0)
return PB_ERROR;
1571 static int pbL_DescriptorProto(pb_Loader *L, pbL_TypeInfo *info) {
1574 pbCM(info); pbC(pbL_beginmsg(L, &s));
1575 while (pb_readvarint32(&L->s, &tag)) {
1577 case pb_pair(1, PB_TBYTES):
1578 pbC(pbL_readbytes(L, &info->name));
break;
1579 case pb_pair(2, PB_TBYTES):
1580 pbC(pbL_FieldDescriptorProto(L, pbL_add(info->field)));
break;
1581 case pb_pair(6, PB_TBYTES):
1582 pbC(pbL_FieldDescriptorProto(L, pbL_add(info->extension)));
break;
1583 case pb_pair(3, PB_TBYTES):
1584 pbC(pbL_DescriptorProto(L, pbL_add(info->nested_type)));
break;
1585 case pb_pair(4, PB_TBYTES):
1586 pbC(pbL_EnumDescriptorProto(L, pbL_add(info->enum_type)));
break;
1587 case pb_pair(8, PB_TBYTES):
1588 pbC(pbL_OneofDescriptorProto(L, info));
break;
1589 case pb_pair(7, PB_TBYTES):
1590 pbC(pbL_MessageOptions(L, info));
break;
1591 default:
if (pb_skipvalue(&L->s, tag) == 0)
return PB_ERROR;
1598 static int pbL_FileDescriptorProto(pb_Loader *L, pbL_FileInfo *info) {
1601 pbCM(info); pbC(pbL_beginmsg(L, &s));
1602 while (pb_readvarint32(&L->s, &tag)) {
1604 case pb_pair(2, PB_TBYTES):
1605 pbC(pbL_readbytes(L, &info->package));
break;
1606 case pb_pair(4, PB_TBYTES):
1607 pbC(pbL_DescriptorProto(L, pbL_add(info->message_type)));
break;
1608 case pb_pair(5, PB_TBYTES):
1609 pbC(pbL_EnumDescriptorProto(L, pbL_add(info->enum_type)));
break;
1610 case pb_pair(7, PB_TBYTES):
1611 pbC(pbL_FieldDescriptorProto(L, pbL_add(info->extension)));
break;
1612 case pb_pair(12, PB_TBYTES):
1613 pbC(pbL_readbytes(L, &info->syntax));
break;
1614 default:
if (pb_skipvalue(&L->s, tag) == 0)
return PB_ERROR;
1621 static int pbL_FileDescriptorSet(pb_Loader *L, pbL_FileInfo **pfiles) {
1623 while (pb_readvarint32(&L->s, &tag)) {
1625 case pb_pair(1, PB_TBYTES):
1626 pbC(pbL_FileDescriptorProto(L, pbL_add(*pfiles)));
break;
1627 default:
if (pb_skipvalue(&L->s, tag) == 0)
return PB_ERROR;
1635 static void pbL_delTypeInfo(pbL_TypeInfo *info) {
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);
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);
1662 static int pbL_prefixname(
pb_State *S,
pb_Slice s,
size_t *ps, pb_Loader *L, pb_Name **out) {
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);
1672 static int pbL_loadEnum(
pb_State *S, pbL_EnumInfo *info, pb_Loader *L) {
1673 size_t i, count, curr;
1676 pbC(pbL_prefixname(S, info->name, &curr, L, &name));
1677 pbCM(t = pb_newtype(S, name));
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));
1683 L->b.size = (unsigned)curr;
1687 static int pbL_loadField(
pb_State *S, pbL_FieldInfo *info, pb_Loader *L,
pb_Type *t) {
1690 if (info->type == PB_Tmessage || info->type == PB_Tenum)
1691 pbCE(ft = pb_newtype(S, pb_newname(S, info->type_name, 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);
1697 if ((f->oneof_idx = info->oneof_index)) ++t->oneof_field;
1698 f->type_id = info->type;
1699 f->repeated = info->label == 3;
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);
1706 static int pbL_loadType(
pb_State *S, pbL_TypeInfo *info, pb_Loader *L) {
1707 size_t i, count, curr;
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;
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;
1731 static int pbL_loadFile(
pb_State *S, pbL_FileInfo *info, pb_Loader *L) {
1732 size_t i, count, j, jcount, curr = 0;
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;
1751 pbL_FileInfo *files = NULL;
1754 pb_initbuffer(&L.b);
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);