PageRenderTime 32ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/src/google/protobuf-c/protobuf-c.c

http://github.com/smtlaissezfaire/protobuf-c
C | 1934 lines | 1709 code | 105 blank | 120 comment | 342 complexity | bb1b3b5b2c3e4f741af1f58159530ac1 MD5 | raw file
Possible License(s): Apache-2.0
  1. /* --- protobuf-c.c: public protobuf c runtime implementation --- */
  2. /*
  3. * Copyright 2008, Dave Benson.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License
  8. * at http://www.apache.org/licenses/LICENSE-2.0 Unless
  9. * required by applicable law or agreed to in writing,
  10. * software distributed under the License is distributed on
  11. * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  12. * KIND, either express or implied. See the License for the
  13. * specific language governing permissions and limitations
  14. * under the License.
  15. */
  16. /* TODO: certain implementations use 32-bit math even for
  17. (uint64_size, uint64_pack, parse_uint64) */
  18. /* TODO: get_packed_size and pack seem to use type-prefixed names,
  19. whereas parse uses type-suffixed names. pick one and stick with it.
  20. Decision: go with type-suffixed, since the type (or its instance)
  21. is typically the object of the verb.
  22. NOTE: perhaps the "parse" methods should be reanemd to "unpack"
  23. at the same time.
  24. */
  25. #include <stdio.h> /* for occasional printf()s */
  26. #include <stdlib.h> /* for abort(), malloc() etc */
  27. #include <string.h> /* for strlen(), memcpy(), memmove() */
  28. #ifndef PRINT_UNPACK_ERRORS
  29. #define PRINT_UNPACK_ERRORS 1
  30. #endif
  31. #include "protobuf-c.h"
  32. #define MAX_UINT64_ENCODED_SIZE 10
  33. /* convenience macros */
  34. #define TMPALLOC(allocator, size) ((allocator)->tmp_alloc ((allocator)->allocator_data, (size)))
  35. #define FREE(allocator, ptr) \
  36. do { if ((ptr) != NULL) ((allocator)->free ((allocator)->allocator_data, (ptr))); } while(0)
  37. #define UNALIGNED_ALLOC(allocator, size) ALLOC (allocator, size) /* placeholder */
  38. #define STRUCT_MEMBER_P(struct_p, struct_offset) \
  39. ((void *) ((uint8_t*) (struct_p) + (struct_offset)))
  40. #define STRUCT_MEMBER(member_type, struct_p, struct_offset) \
  41. (*(member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset)))
  42. #define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \
  43. ((member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset)))
  44. #define TRUE 1
  45. #define FALSE 0
  46. static void
  47. alloc_failed_warning (unsigned size, const char *filename, unsigned line)
  48. {
  49. fprintf (stderr,
  50. "WARNING: out-of-memory allocating a block of size %u (%s:%u)\n",
  51. size, filename, line);
  52. }
  53. /* Try to allocate memory, running some special code if it fails. */
  54. #define DO_ALLOC(dst, allocator, size, fail_code) \
  55. { size_t da__allocation_size = (size); \
  56. if (da__allocation_size == 0) \
  57. dst = NULL; \
  58. else if ((dst=((allocator)->alloc ((allocator)->allocator_data, \
  59. da__allocation_size))) == NULL) \
  60. { \
  61. alloc_failed_warning (da__allocation_size, __FILE__, __LINE__); \
  62. fail_code; \
  63. } \
  64. }
  65. #define DO_UNALIGNED_ALLOC DO_ALLOC /* placeholder */
  66. #define ASSERT_IS_ENUM_DESCRIPTOR(desc) \
  67. assert((desc)->magic == PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC)
  68. #define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \
  69. assert((desc)->magic == PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC)
  70. #define ASSERT_IS_MESSAGE(message) \
  71. ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor)
  72. #define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \
  73. assert((desc)->magic == PROTOBUF_C_SERVICE_DESCRIPTOR_MAGIC)
  74. /* --- allocator --- */
  75. static void protobuf_c_out_of_memory_default (void)
  76. {
  77. fprintf (stderr, "Out Of Memory!!!\n");
  78. abort ();
  79. }
  80. void (*protobuf_c_out_of_memory) (void) = protobuf_c_out_of_memory_default;
  81. static void *system_alloc(void *allocator_data, size_t size)
  82. {
  83. void *rv;
  84. (void) allocator_data;
  85. if (size == 0)
  86. return NULL;
  87. rv = malloc (size);
  88. if (rv == NULL)
  89. protobuf_c_out_of_memory ();
  90. return rv;
  91. }
  92. static void system_free (void *allocator_data, void *data)
  93. {
  94. (void) allocator_data;
  95. if (data)
  96. free (data);
  97. }
  98. ProtobufCAllocator protobuf_c_default_allocator =
  99. {
  100. system_alloc,
  101. system_free,
  102. NULL,
  103. 8192,
  104. NULL
  105. };
  106. ProtobufCAllocator protobuf_c_system_allocator =
  107. {
  108. system_alloc,
  109. system_free,
  110. NULL,
  111. 8192,
  112. NULL
  113. };
  114. /* === buffer-simple === */
  115. void
  116. protobuf_c_buffer_simple_append (ProtobufCBuffer *buffer,
  117. size_t len,
  118. const uint8_t *data)
  119. {
  120. ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer;
  121. size_t new_len = simp->len + len;
  122. if (new_len > simp->alloced)
  123. {
  124. size_t new_alloced = simp->alloced * 2;
  125. uint8_t *new_data;
  126. while (new_alloced < new_len)
  127. new_alloced += new_alloced;
  128. DO_ALLOC (new_data, &protobuf_c_default_allocator, new_alloced, return);
  129. memcpy (new_data, simp->data, simp->len);
  130. if (simp->must_free_data)
  131. FREE (&protobuf_c_default_allocator, simp->data);
  132. else
  133. simp->must_free_data = 1;
  134. simp->data = new_data;
  135. simp->alloced = new_alloced;
  136. }
  137. memcpy (simp->data + simp->len, data, len);
  138. simp->len = new_len;
  139. }
  140. /* === get_packed_size() === */
  141. /* Return the number of bytes required to store the
  142. tag for the field (which includes 3 bits for
  143. the wire-type, and a single bit that denotes the end-of-tag. */
  144. static inline size_t
  145. get_tag_size (unsigned number)
  146. {
  147. if (number < (1<<4))
  148. return 1;
  149. else if (number < (1<<11))
  150. return 2;
  151. else if (number < (1<<18))
  152. return 3;
  153. else if (number < (1<<25))
  154. return 4;
  155. else
  156. return 5;
  157. }
  158. /* Return the number of bytes required to store
  159. a variable-length unsigned integer that fits in 32-bit uint
  160. in base-128 encoding. */
  161. static inline size_t
  162. uint32_size (uint32_t v)
  163. {
  164. if (v < (1<<7))
  165. return 1;
  166. else if (v < (1<<14))
  167. return 2;
  168. else if (v < (1<<21))
  169. return 3;
  170. else if (v < (1<<28))
  171. return 4;
  172. else
  173. return 5;
  174. }
  175. /* Return the number of bytes required to store
  176. a variable-length signed integer that fits in 32-bit int
  177. in base-128 encoding. */
  178. static inline size_t
  179. int32_size (int32_t v)
  180. {
  181. if (v < 0)
  182. return 10;
  183. else if (v < (1<<7))
  184. return 1;
  185. else if (v < (1<<14))
  186. return 2;
  187. else if (v < (1<<21))
  188. return 3;
  189. else if (v < (1<<28))
  190. return 4;
  191. else
  192. return 5;
  193. }
  194. /* return the zigzag-encoded 32-bit unsigned int from a 32-bit signed int */
  195. static inline uint32_t
  196. zigzag32 (int32_t v)
  197. {
  198. if (v < 0)
  199. return ((uint32_t)(-v)) * 2 - 1;
  200. else
  201. return v * 2;
  202. }
  203. /* Return the number of bytes required to store
  204. a variable-length signed integer that fits in 32-bit int,
  205. converted to unsigned via the zig-zag algorithm,
  206. then packed using base-128 encoding. */
  207. static inline size_t
  208. sint32_size (int32_t v)
  209. {
  210. return uint32_size(zigzag32(v));
  211. }
  212. /* Return the number of bytes required to store
  213. a variable-length unsigned integer that fits in 64-bit uint
  214. in base-128 encoding. */
  215. static inline size_t
  216. uint64_size (uint64_t v)
  217. {
  218. uint32_t upper_v = (v>>32);
  219. if (upper_v == 0)
  220. return uint32_size ((uint32_t)v);
  221. else if (upper_v < (1<<3))
  222. return 5;
  223. else if (upper_v < (1<<10))
  224. return 6;
  225. else if (upper_v < (1<<17))
  226. return 7;
  227. else if (upper_v < (1<<24))
  228. return 8;
  229. else if (upper_v < (1U<<31))
  230. return 9;
  231. else
  232. return 10;
  233. }
  234. /* return the zigzag-encoded 64-bit unsigned int from a 64-bit signed int */
  235. static inline uint64_t
  236. zigzag64 (int64_t v)
  237. {
  238. if (v < 0)
  239. return ((uint64_t)(-v)) * 2 - 1;
  240. else
  241. return v * 2;
  242. }
  243. /* Return the number of bytes required to store
  244. a variable-length signed integer that fits in 64-bit int,
  245. converted to unsigned via the zig-zag algorithm,
  246. then packed using base-128 encoding. */
  247. static inline size_t
  248. sint64_size (int64_t v)
  249. {
  250. return uint64_size(zigzag64(v));
  251. }
  252. /* Get serialized size of a single field in the message,
  253. including the space needed by the identifying tag. */
  254. static size_t
  255. required_field_get_packed_size (const ProtobufCFieldDescriptor *field,
  256. const void *member)
  257. {
  258. size_t rv = get_tag_size (field->id);
  259. switch (field->type)
  260. {
  261. case PROTOBUF_C_TYPE_SINT32:
  262. return rv + sint32_size (*(const int32_t *) member);
  263. case PROTOBUF_C_TYPE_INT32:
  264. return rv + int32_size (*(const uint32_t *) member);
  265. case PROTOBUF_C_TYPE_UINT32:
  266. return rv + uint32_size (*(const uint32_t *) member);
  267. case PROTOBUF_C_TYPE_SINT64:
  268. return rv + sint64_size (*(const int64_t *) member);
  269. case PROTOBUF_C_TYPE_INT64:
  270. case PROTOBUF_C_TYPE_UINT64:
  271. return rv + uint64_size (*(const uint64_t *) member);
  272. case PROTOBUF_C_TYPE_SFIXED32:
  273. case PROTOBUF_C_TYPE_FIXED32:
  274. return rv + 4;
  275. case PROTOBUF_C_TYPE_SFIXED64:
  276. case PROTOBUF_C_TYPE_FIXED64:
  277. return rv + 8;
  278. case PROTOBUF_C_TYPE_BOOL:
  279. return rv + 1;
  280. case PROTOBUF_C_TYPE_FLOAT:
  281. return rv + 4;
  282. case PROTOBUF_C_TYPE_DOUBLE:
  283. return rv + 8;
  284. case PROTOBUF_C_TYPE_ENUM:
  285. // TODO: is this correct for negative-valued enums?
  286. return rv + uint32_size (*(const uint32_t *) member);
  287. case PROTOBUF_C_TYPE_STRING:
  288. {
  289. const char *str = *(char * const *) member;
  290. size_t len = str ? strlen (str) : 0;
  291. return rv + uint32_size (len) + len;
  292. }
  293. case PROTOBUF_C_TYPE_BYTES:
  294. {
  295. size_t len = ((const ProtobufCBinaryData*) member)->len;
  296. return rv + uint32_size (len) + len;
  297. }
  298. //case PROTOBUF_C_TYPE_GROUP:
  299. case PROTOBUF_C_TYPE_MESSAGE:
  300. {
  301. const ProtobufCMessage *msg = * (ProtobufCMessage * const *) member;
  302. size_t subrv = msg ? protobuf_c_message_get_packed_size (msg) : 0;
  303. return rv + uint32_size (subrv) + subrv;
  304. }
  305. }
  306. PROTOBUF_C_ASSERT_NOT_REACHED ();
  307. return 0;
  308. }
  309. /* Get serialized size of a single optional field in the message,
  310. including the space needed by the identifying tag.
  311. Returns 0 if the optional field isn't set. */
  312. static size_t
  313. optional_field_get_packed_size (const ProtobufCFieldDescriptor *field,
  314. const protobuf_c_boolean *has,
  315. const void *member)
  316. {
  317. if (field->type == PROTOBUF_C_TYPE_MESSAGE
  318. || field->type == PROTOBUF_C_TYPE_STRING)
  319. {
  320. const void *ptr = * (const void * const *) member;
  321. if (ptr == NULL
  322. || ptr == field->default_value)
  323. return 0;
  324. }
  325. else
  326. {
  327. if (!*has)
  328. return 0;
  329. }
  330. return required_field_get_packed_size (field, member);
  331. }
  332. /* Get serialized size of a repeated field in the message,
  333. which may consist of any number of values (including 0).
  334. Includes the space needed by the identifying tags (as needed). */
  335. static size_t
  336. repeated_field_get_packed_size (const ProtobufCFieldDescriptor *field,
  337. size_t count,
  338. const void *member)
  339. {
  340. size_t rv = get_tag_size (field->id) * count;
  341. unsigned i;
  342. void *array = * (void * const *) member;
  343. switch (field->type)
  344. {
  345. case PROTOBUF_C_TYPE_SINT32:
  346. for (i = 0; i < count; i++)
  347. rv += sint32_size (((int32_t*)array)[i]);
  348. break;
  349. case PROTOBUF_C_TYPE_INT32:
  350. for (i = 0; i < count; i++)
  351. rv += int32_size (((uint32_t*)array)[i]);
  352. break;
  353. case PROTOBUF_C_TYPE_UINT32:
  354. case PROTOBUF_C_TYPE_ENUM:
  355. for (i = 0; i < count; i++)
  356. rv += uint32_size (((uint32_t*)array)[i]);
  357. break;
  358. case PROTOBUF_C_TYPE_SINT64:
  359. for (i = 0; i < count; i++)
  360. rv += sint64_size (((int64_t*)array)[i]);
  361. break;
  362. case PROTOBUF_C_TYPE_INT64:
  363. case PROTOBUF_C_TYPE_UINT64:
  364. for (i = 0; i < count; i++)
  365. rv += uint64_size (((uint64_t*)array)[i]);
  366. break;
  367. case PROTOBUF_C_TYPE_SFIXED32:
  368. case PROTOBUF_C_TYPE_FIXED32:
  369. case PROTOBUF_C_TYPE_FLOAT:
  370. rv += 4 * count;
  371. break;
  372. case PROTOBUF_C_TYPE_SFIXED64:
  373. case PROTOBUF_C_TYPE_FIXED64:
  374. case PROTOBUF_C_TYPE_DOUBLE:
  375. rv += 8 * count;
  376. break;
  377. case PROTOBUF_C_TYPE_BOOL:
  378. rv += count;
  379. break;
  380. case PROTOBUF_C_TYPE_STRING:
  381. for (i = 0; i < count; i++)
  382. {
  383. size_t len = strlen (((char**) array)[i]);
  384. rv += uint32_size (len) + len;
  385. }
  386. break;
  387. case PROTOBUF_C_TYPE_BYTES:
  388. for (i = 0; i < count; i++)
  389. {
  390. size_t len = ((ProtobufCBinaryData*) array)[i].len;
  391. rv += uint32_size (len) + len;
  392. }
  393. break;
  394. case PROTOBUF_C_TYPE_MESSAGE:
  395. for (i = 0; i < count; i++)
  396. {
  397. size_t len = protobuf_c_message_get_packed_size (((ProtobufCMessage **) array)[i]);
  398. rv += uint32_size (len) + len;
  399. }
  400. break;
  401. //case PROTOBUF_C_TYPE_GROUP: // NOT SUPPORTED
  402. }
  403. return rv;
  404. }
  405. /* Get the packed size of a unknown field (meaning one that
  406. is passed through mostly uninterpreted... this is done
  407. for forward compatibilty with the addition of new fields). */
  408. static inline size_t
  409. unknown_field_get_packed_size (const ProtobufCMessageUnknownField *field)
  410. {
  411. return get_tag_size (field->tag) + field->len;
  412. }
  413. /* Get the number of bytes that the message will occupy once serialized. */
  414. size_t
  415. protobuf_c_message_get_packed_size(const ProtobufCMessage *message)
  416. {
  417. unsigned i;
  418. size_t rv = 0;
  419. ASSERT_IS_MESSAGE (message);
  420. for (i = 0; i < message->descriptor->n_fields; i++)
  421. {
  422. const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
  423. const void *member = ((const char *) message) + field->offset;
  424. const void *qmember = ((const char *) message) + field->quantifier_offset;
  425. if (field->label == PROTOBUF_C_LABEL_REQUIRED)
  426. rv += required_field_get_packed_size (field, member);
  427. else if (field->label == PROTOBUF_C_LABEL_OPTIONAL)
  428. rv += optional_field_get_packed_size (field, qmember, member);
  429. else
  430. rv += repeated_field_get_packed_size (field, * (const size_t *) qmember, member);
  431. }
  432. for (i = 0; i < message->n_unknown_fields; i++)
  433. rv += unknown_field_get_packed_size (&message->unknown_fields[i]);
  434. return rv;
  435. }
  436. /* === pack() === */
  437. /* Pack an unsigned 32-bit integer in base-128 encoding, and return the number of bytes needed:
  438. this will be 5 or less. */
  439. static inline size_t
  440. uint32_pack (uint32_t value, uint8_t *out)
  441. {
  442. unsigned rv = 0;
  443. if (value >= 0x80)
  444. {
  445. out[rv++] = value | 0x80;
  446. value >>= 7;
  447. if (value >= 0x80)
  448. {
  449. out[rv++] = value | 0x80;
  450. value >>= 7;
  451. if (value >= 0x80)
  452. {
  453. out[rv++] = value | 0x80;
  454. value >>= 7;
  455. if (value >= 0x80)
  456. {
  457. out[rv++] = value | 0x80;
  458. value >>= 7;
  459. }
  460. }
  461. }
  462. }
  463. /* assert: value<128 */
  464. out[rv++] = value;
  465. return rv;
  466. }
  467. /* Pack a 32-bit signed integer, returning the number of bytes needed.
  468. Negative numbers are packed as twos-complement 64-bit integers. */
  469. static inline size_t
  470. int32_pack (int32_t value, uint8_t *out)
  471. {
  472. if (value < 0)
  473. {
  474. out[0] = value | 0x80;
  475. out[1] = (value>>7) | 0x80;
  476. out[2] = (value>>14) | 0x80;
  477. out[3] = (value>>21) | 0x80;
  478. out[4] = (value>>28) | 0x80;
  479. out[5] = out[6] = out[7] = out[8] = 0xff;
  480. out[9] = 0x01;
  481. return 10;
  482. }
  483. else
  484. return uint32_pack (value, out);
  485. }
  486. /* Pack a 32-bit integer in zigwag encoding. */
  487. static inline size_t
  488. sint32_pack (int32_t value, uint8_t *out)
  489. {
  490. return uint32_pack (zigzag32 (value), out);
  491. }
  492. /* Pack a 64-bit unsigned integer that fits in a 64-bit uint,
  493. using base-128 encoding. */
  494. static size_t
  495. uint64_pack (uint64_t value, uint8_t *out)
  496. {
  497. uint32_t hi = value>>32;
  498. uint32_t lo = value;
  499. unsigned rv;
  500. if (hi == 0)
  501. return uint32_pack ((uint32_t)lo, out);
  502. out[0] = (lo) | 0x80;
  503. out[1] = (lo>>7) | 0x80;
  504. out[2] = (lo>>14) | 0x80;
  505. out[3] = (lo>>21) | 0x80;
  506. if (hi < 8)
  507. {
  508. out[4] = (hi<<4) | (lo>>28);
  509. return 5;
  510. }
  511. else
  512. {
  513. out[4] = ((hi&7)<<4) | (lo>>28) | 0x80;
  514. hi >>= 3;
  515. }
  516. rv = 5;
  517. while (hi >= 128)
  518. {
  519. out[rv++] = hi | 0x80;
  520. hi >>= 7;
  521. }
  522. out[rv++] = hi;
  523. return rv;
  524. }
  525. /* Pack a 64-bit signed integer in zigzan encoding,
  526. return the size of the packed output.
  527. (Max returned value is 10) */
  528. static inline size_t
  529. sint64_pack (int64_t value, uint8_t *out)
  530. {
  531. return uint64_pack (zigzag64 (value), out);
  532. }
  533. /* Pack a 32-bit value, little-endian.
  534. Used for fixed32, sfixed32, float) */
  535. static inline size_t
  536. fixed32_pack (uint32_t value, uint8_t *out)
  537. {
  538. #if IS_LITTLE_ENDIAN
  539. memcpy (out, &value, 4);
  540. #else
  541. out[0] = value;
  542. out[1] = value>>8;
  543. out[2] = value>>16;
  544. out[3] = value>>24;
  545. #endif
  546. return 4;
  547. }
  548. static inline size_t
  549. fixed64_pack (uint64_t value, uint8_t *out)
  550. {
  551. #if IS_LITTLE_ENDIAN
  552. memcpy (out, &value, 8);
  553. #else
  554. fixed32_pack (value, out);
  555. fixed32_pack (value>>32, out+4);
  556. #endif
  557. return 8;
  558. }
  559. static inline size_t
  560. boolean_pack (protobuf_c_boolean value, uint8_t *out)
  561. {
  562. *out = value ? 1 : 0;
  563. return 1;
  564. }
  565. static inline size_t
  566. string_pack (const char * str, uint8_t *out)
  567. {
  568. if (str == NULL)
  569. {
  570. out[0] = 0;
  571. return 1;
  572. }
  573. else
  574. {
  575. size_t len = strlen (str);
  576. size_t rv = uint32_pack (len, out);
  577. memcpy (out + rv, str, len);
  578. return rv + len;
  579. }
  580. }
  581. static inline size_t
  582. binary_data_pack (const ProtobufCBinaryData *bd, uint8_t *out)
  583. {
  584. size_t len = bd->len;
  585. size_t rv = uint32_pack (len, out);
  586. memcpy (out + rv, bd->data, len);
  587. return rv + len;
  588. }
  589. static inline size_t
  590. prefixed_message_pack (const ProtobufCMessage *message, uint8_t *out)
  591. {
  592. if (message == NULL)
  593. {
  594. out[0] = 0;
  595. return 1;
  596. }
  597. else
  598. {
  599. size_t rv = protobuf_c_message_pack (message, out + 1);
  600. uint32_t rv_packed_size = uint32_size (rv);
  601. if (rv_packed_size != 1)
  602. memmove (out + rv_packed_size, out + 1, rv);
  603. return uint32_pack (rv, out) + rv;
  604. }
  605. }
  606. /* wire-type will be added in required_field_pack() */
  607. static size_t tag_pack (uint32_t id, uint8_t *out)
  608. {
  609. if (id < (1<<(32-3)))
  610. return uint32_pack (id<<3, out);
  611. else
  612. return uint64_pack (((uint64_t)id) << 3, out);
  613. }
  614. static size_t
  615. required_field_pack (const ProtobufCFieldDescriptor *field,
  616. const void *member,
  617. uint8_t *out)
  618. {
  619. size_t rv = tag_pack (field->id, out);
  620. switch (field->type)
  621. {
  622. case PROTOBUF_C_TYPE_SINT32:
  623. out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  624. return rv + sint32_pack (*(const int32_t *) member, out + rv);
  625. case PROTOBUF_C_TYPE_INT32:
  626. out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  627. return rv + int32_pack (*(const uint32_t *) member, out + rv);
  628. case PROTOBUF_C_TYPE_UINT32:
  629. case PROTOBUF_C_TYPE_ENUM:
  630. out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  631. return rv + uint32_pack (*(const uint32_t *) member, out + rv);
  632. case PROTOBUF_C_TYPE_SINT64:
  633. out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  634. return rv + sint64_pack (*(const int64_t *) member, out + rv);
  635. case PROTOBUF_C_TYPE_INT64:
  636. case PROTOBUF_C_TYPE_UINT64:
  637. out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  638. return rv + uint64_pack (*(const uint64_t *) member, out + rv);
  639. case PROTOBUF_C_TYPE_SFIXED32:
  640. case PROTOBUF_C_TYPE_FIXED32:
  641. case PROTOBUF_C_TYPE_FLOAT:
  642. out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
  643. return rv + fixed32_pack (*(const uint64_t *) member, out + rv);
  644. case PROTOBUF_C_TYPE_SFIXED64:
  645. case PROTOBUF_C_TYPE_FIXED64:
  646. case PROTOBUF_C_TYPE_DOUBLE:
  647. out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
  648. return rv + fixed64_pack (*(const uint64_t *) member, out + rv);
  649. case PROTOBUF_C_TYPE_BOOL:
  650. out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  651. return rv + boolean_pack (*(const protobuf_c_boolean *) member, out + rv);
  652. case PROTOBUF_C_TYPE_STRING:
  653. {
  654. out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
  655. return rv + string_pack (*(char * const *) member, out + rv);
  656. }
  657. case PROTOBUF_C_TYPE_BYTES:
  658. {
  659. const ProtobufCBinaryData * bd = ((const ProtobufCBinaryData*) member);
  660. out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
  661. return rv + binary_data_pack (bd, out + rv);
  662. }
  663. //case PROTOBUF_C_TYPE_GROUP: // NOT SUPPORTED
  664. case PROTOBUF_C_TYPE_MESSAGE:
  665. {
  666. out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
  667. return rv + prefixed_message_pack (*(ProtobufCMessage * const *) member,
  668. out + rv);
  669. }
  670. }
  671. PROTOBUF_C_ASSERT_NOT_REACHED ();
  672. return 0;
  673. }
  674. static size_t
  675. optional_field_pack (const ProtobufCFieldDescriptor *field,
  676. const protobuf_c_boolean *has,
  677. const void *member,
  678. uint8_t *out)
  679. {
  680. if (field->type == PROTOBUF_C_TYPE_MESSAGE
  681. || field->type == PROTOBUF_C_TYPE_STRING)
  682. {
  683. const void *ptr = * (const void * const *) member;
  684. if (ptr == NULL
  685. || ptr == field->default_value)
  686. return 0;
  687. }
  688. else
  689. {
  690. if (!*has)
  691. return 0;
  692. }
  693. return required_field_pack (field, member, out);
  694. }
  695. /* TODO: implement as a table lookup */
  696. static inline size_t sizeof_elt_in_repeated_array (ProtobufCType type)
  697. {
  698. switch (type)
  699. {
  700. case PROTOBUF_C_TYPE_SINT32:
  701. case PROTOBUF_C_TYPE_INT32:
  702. case PROTOBUF_C_TYPE_UINT32:
  703. case PROTOBUF_C_TYPE_SFIXED32:
  704. case PROTOBUF_C_TYPE_FIXED32:
  705. case PROTOBUF_C_TYPE_FLOAT:
  706. case PROTOBUF_C_TYPE_ENUM:
  707. return 4;
  708. case PROTOBUF_C_TYPE_SINT64:
  709. case PROTOBUF_C_TYPE_INT64:
  710. case PROTOBUF_C_TYPE_UINT64:
  711. case PROTOBUF_C_TYPE_SFIXED64:
  712. case PROTOBUF_C_TYPE_FIXED64:
  713. case PROTOBUF_C_TYPE_DOUBLE:
  714. return 8;
  715. case PROTOBUF_C_TYPE_BOOL:
  716. return sizeof (protobuf_c_boolean);
  717. case PROTOBUF_C_TYPE_STRING:
  718. case PROTOBUF_C_TYPE_MESSAGE:
  719. return sizeof (void *);
  720. case PROTOBUF_C_TYPE_BYTES:
  721. return sizeof (ProtobufCBinaryData);
  722. }
  723. PROTOBUF_C_ASSERT_NOT_REACHED ();
  724. return 0;
  725. }
  726. static size_t
  727. repeated_field_pack (const ProtobufCFieldDescriptor *field,
  728. size_t count,
  729. const void *member,
  730. uint8_t *out)
  731. {
  732. char *array = * (char * const *) member;
  733. size_t siz;
  734. unsigned i;
  735. size_t rv = 0;
  736. /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
  737. siz = sizeof_elt_in_repeated_array (field->type);
  738. for (i = 0; i < count; i++)
  739. {
  740. rv += required_field_pack (field, array, out + rv);
  741. array += siz;
  742. }
  743. return rv;
  744. }
  745. static size_t
  746. unknown_field_pack (const ProtobufCMessageUnknownField *field, uint8_t *out)
  747. {
  748. size_t rv = tag_pack (field->tag, out);
  749. out[0] |= field->wire_type;
  750. memcpy (out + rv, field->data, field->len);
  751. return rv + field->len;
  752. }
  753. size_t protobuf_c_message_pack (const ProtobufCMessage *message,
  754. uint8_t *out)
  755. {
  756. unsigned i;
  757. size_t rv = 0;
  758. ASSERT_IS_MESSAGE (message);
  759. for (i = 0; i < message->descriptor->n_fields; i++)
  760. {
  761. const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
  762. const void *member = ((const char *) message) + field->offset;
  763. const void *qmember = ((const char *) message) + field->quantifier_offset;
  764. if (field->label == PROTOBUF_C_LABEL_REQUIRED)
  765. rv += required_field_pack (field, member, out + rv);
  766. else if (field->label == PROTOBUF_C_LABEL_OPTIONAL)
  767. rv += optional_field_pack (field, qmember, member, out + rv);
  768. else
  769. rv += repeated_field_pack (field, * (const size_t *) qmember, member, out + rv);
  770. }
  771. for (i = 0; i < message->n_unknown_fields; i++)
  772. rv += unknown_field_pack (&message->unknown_fields[i], out + rv);
  773. return rv;
  774. }
  775. /* === pack_to_buffer() === */
  776. static size_t
  777. required_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
  778. const void *member,
  779. ProtobufCBuffer *buffer)
  780. {
  781. size_t rv;
  782. uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
  783. rv = tag_pack (field->id, scratch);
  784. switch (field->type)
  785. {
  786. case PROTOBUF_C_TYPE_SINT32:
  787. scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  788. rv += sint32_pack (*(const int32_t *) member, scratch + rv);
  789. buffer->append (buffer, rv, scratch);
  790. break;
  791. case PROTOBUF_C_TYPE_INT32:
  792. scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  793. rv += int32_pack (*(const uint32_t *) member, scratch + rv);
  794. buffer->append (buffer, rv, scratch);
  795. break;
  796. case PROTOBUF_C_TYPE_UINT32:
  797. case PROTOBUF_C_TYPE_ENUM:
  798. scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  799. rv += uint32_pack (*(const uint32_t *) member, scratch + rv);
  800. buffer->append (buffer, rv, scratch);
  801. break;
  802. case PROTOBUF_C_TYPE_SINT64:
  803. scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  804. rv += sint64_pack (*(const int64_t *) member, scratch + rv);
  805. buffer->append (buffer, rv, scratch);
  806. break;
  807. case PROTOBUF_C_TYPE_INT64:
  808. case PROTOBUF_C_TYPE_UINT64:
  809. scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  810. rv += uint64_pack (*(const uint64_t *) member, scratch + rv);
  811. buffer->append (buffer, rv, scratch);
  812. break;
  813. case PROTOBUF_C_TYPE_SFIXED32:
  814. case PROTOBUF_C_TYPE_FIXED32:
  815. case PROTOBUF_C_TYPE_FLOAT:
  816. scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
  817. rv += fixed32_pack (*(const uint64_t *) member, scratch + rv);
  818. buffer->append (buffer, rv, scratch);
  819. break;
  820. case PROTOBUF_C_TYPE_SFIXED64:
  821. case PROTOBUF_C_TYPE_FIXED64:
  822. case PROTOBUF_C_TYPE_DOUBLE:
  823. scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
  824. rv += fixed64_pack (*(const uint64_t *) member, scratch + rv);
  825. buffer->append (buffer, rv, scratch);
  826. break;
  827. case PROTOBUF_C_TYPE_BOOL:
  828. scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  829. rv += boolean_pack (*(const protobuf_c_boolean *) member, scratch + rv);
  830. buffer->append (buffer, rv, scratch);
  831. break;
  832. case PROTOBUF_C_TYPE_STRING:
  833. {
  834. const char *str = *(char * const *) member;
  835. size_t sublen = str ? strlen (str) : 0;
  836. scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
  837. rv += uint32_pack (sublen, scratch + rv);
  838. buffer->append (buffer, rv, scratch);
  839. buffer->append (buffer, sublen, (const uint8_t *) str);
  840. rv += sublen;
  841. break;
  842. }
  843. case PROTOBUF_C_TYPE_BYTES:
  844. {
  845. const ProtobufCBinaryData * bd = ((const ProtobufCBinaryData*) member);
  846. size_t sublen = bd->len;
  847. scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
  848. rv += uint32_pack (sublen, scratch + rv);
  849. buffer->append (buffer, rv, scratch);
  850. buffer->append (buffer, sublen, bd->data);
  851. rv += sublen;
  852. break;
  853. }
  854. //PROTOBUF_C_TYPE_GROUP, // NOT SUPPORTED
  855. case PROTOBUF_C_TYPE_MESSAGE:
  856. {
  857. uint8_t simple_buffer_scratch[256];
  858. size_t sublen;
  859. ProtobufCBufferSimple simple_buffer
  860. = PROTOBUF_C_BUFFER_SIMPLE_INIT (simple_buffer_scratch);
  861. const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
  862. scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
  863. if (msg == NULL)
  864. sublen = 0;
  865. else
  866. sublen = protobuf_c_message_pack_to_buffer (msg, &simple_buffer.base);
  867. rv += uint32_pack (sublen, scratch + rv);
  868. buffer->append (buffer, rv, scratch);
  869. buffer->append (buffer, sublen, simple_buffer.data);
  870. rv += sublen;
  871. PROTOBUF_C_BUFFER_SIMPLE_CLEAR (&simple_buffer);
  872. break;
  873. }
  874. default:
  875. PROTOBUF_C_ASSERT_NOT_REACHED ();
  876. }
  877. return rv;
  878. }
  879. static size_t
  880. optional_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
  881. const protobuf_c_boolean *has,
  882. const void *member,
  883. ProtobufCBuffer *buffer)
  884. {
  885. if (field->type == PROTOBUF_C_TYPE_MESSAGE
  886. || field->type == PROTOBUF_C_TYPE_STRING)
  887. {
  888. const void *ptr = * (const void * const *) member;
  889. if (ptr == NULL
  890. || ptr == field->default_value)
  891. return 0;
  892. }
  893. else
  894. {
  895. if (!*has)
  896. return 0;
  897. }
  898. return required_field_pack_to_buffer (field, member, buffer);
  899. }
  900. static size_t
  901. repeated_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
  902. unsigned count,
  903. const void *member,
  904. ProtobufCBuffer *buffer)
  905. {
  906. char *array = * (char * const *) member;
  907. size_t siz;
  908. unsigned i;
  909. /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
  910. unsigned rv = 0;
  911. siz = sizeof_elt_in_repeated_array (field->type);
  912. for (i = 0; i < count; i++)
  913. {
  914. rv += required_field_pack_to_buffer (field, array, buffer);
  915. array += siz;
  916. }
  917. return rv;
  918. }
  919. static size_t
  920. unknown_field_pack_to_buffer (const ProtobufCMessageUnknownField *field,
  921. ProtobufCBuffer *buffer)
  922. {
  923. uint8_t header[MAX_UINT64_ENCODED_SIZE];
  924. size_t rv = tag_pack (field->tag, header);
  925. header[0] |= field->wire_type;
  926. buffer->append (buffer, rv, header);
  927. buffer->append (buffer, field->len, field->data);
  928. return rv + field->len;
  929. }
  930. size_t
  931. protobuf_c_message_pack_to_buffer (const ProtobufCMessage *message,
  932. ProtobufCBuffer *buffer)
  933. {
  934. unsigned i;
  935. size_t rv = 0;
  936. ASSERT_IS_MESSAGE (message);
  937. for (i = 0; i < message->descriptor->n_fields; i++)
  938. {
  939. const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
  940. const void *member = ((const char *) message) + field->offset;
  941. const void *qmember = ((const char *) message) + field->quantifier_offset;
  942. if (field->label == PROTOBUF_C_LABEL_REQUIRED)
  943. rv += required_field_pack_to_buffer (field, member, buffer);
  944. else if (field->label == PROTOBUF_C_LABEL_OPTIONAL)
  945. rv += optional_field_pack_to_buffer (field, qmember, member, buffer);
  946. else
  947. rv += repeated_field_pack_to_buffer (field, * (const size_t *) qmember, member, buffer);
  948. }
  949. for (i = 0; i < message->n_unknown_fields; i++)
  950. rv += unknown_field_pack_to_buffer (&message->unknown_fields[i], buffer);
  951. return rv;
  952. }
  953. /* === unpacking === */
  954. #if PRINT_UNPACK_ERRORS
  955. # define UNPACK_ERROR(args) do { printf args;printf("\n"); }while(0)
  956. #else
  957. # define UNPACK_ERROR(args) do { } while (0)
  958. #endif
  959. static inline int
  960. int_range_lookup (unsigned n_ranges,
  961. const ProtobufCIntRange *ranges,
  962. int value)
  963. {
  964. unsigned start, n;
  965. if (n_ranges == 0)
  966. return -1;
  967. start = 0;
  968. n = n_ranges;
  969. while (n > 1)
  970. {
  971. unsigned mid = start + n / 2;
  972. if (value < ranges[mid].start_value)
  973. {
  974. n = mid - start;
  975. }
  976. else if (value >= ranges[mid].start_value + (int)(ranges[mid+1].orig_index-ranges[mid].orig_index))
  977. {
  978. unsigned new_start = mid + 1;
  979. n = start + n - new_start;
  980. start = new_start;
  981. }
  982. else
  983. return (value - ranges[mid].start_value) + ranges[mid].orig_index;
  984. }
  985. if (n > 0)
  986. {
  987. unsigned start_orig_index = ranges[start].orig_index;
  988. unsigned range_size = ranges[start+1].orig_index - start_orig_index;
  989. if (ranges[start].start_value <= value
  990. && value < (int)(ranges[start].start_value + range_size))
  991. return (value - ranges[start].start_value) + start_orig_index;
  992. }
  993. return -1;
  994. }
  995. static size_t
  996. parse_tag_and_wiretype (size_t len,
  997. const uint8_t *data,
  998. uint32_t *tag_out,
  999. ProtobufCWireType *wiretype_out)
  1000. {
  1001. unsigned max_rv = len > 5 ? 5 : len;
  1002. uint32_t tag = (data[0]&0x7f) >> 3;
  1003. unsigned shift = 4;
  1004. unsigned rv;
  1005. *wiretype_out = data[0] & 7;
  1006. if ((data[0] & 0x80) == 0)
  1007. {
  1008. *tag_out = tag;
  1009. return 1;
  1010. }
  1011. for (rv = 1; rv < max_rv; rv++)
  1012. if (data[rv] & 0x80)
  1013. {
  1014. tag |= (data[rv] & 0x7f) << shift;
  1015. shift += 7;
  1016. }
  1017. else
  1018. {
  1019. tag |= data[rv] << shift;
  1020. *tag_out = tag;
  1021. return rv + 1;
  1022. }
  1023. return 0; /* error: bad header */
  1024. }
  1025. /* sizeof(ScannedMember) must be <= (1<<BOUND_SIZEOF_SCANNED_MEMBER_LOG2) */
  1026. #define BOUND_SIZEOF_SCANNED_MEMBER_LOG2 5
  1027. typedef struct _ScannedMember ScannedMember;
  1028. struct _ScannedMember
  1029. {
  1030. uint32_t tag;
  1031. uint8_t wire_type;
  1032. uint8_t length_prefix_len;
  1033. const ProtobufCFieldDescriptor *field;
  1034. size_t len;
  1035. const uint8_t *data;
  1036. };
  1037. #define MESSAGE_GET_UNKNOWNS(message) \
  1038. STRUCT_MEMBER_PTR (ProtobufCMessageUnknownFieldArray, \
  1039. (message), (message)->descriptor->unknown_field_array_offset)
  1040. static inline uint32_t
  1041. scan_length_prefixed_data (size_t len, const uint8_t *data, size_t *prefix_len_out)
  1042. {
  1043. unsigned hdr_max = len < 5 ? len : 5;
  1044. unsigned hdr_len;
  1045. uint32_t val = 0;
  1046. unsigned i;
  1047. unsigned shift = 0;
  1048. for (i = 0; i < hdr_max; i++)
  1049. {
  1050. val |= (data[i] & 0x7f) << shift;
  1051. shift += 7;
  1052. if ((data[i] & 0x80) == 0)
  1053. break;
  1054. }
  1055. if (i == hdr_max)
  1056. {
  1057. UNPACK_ERROR (("error parsing length for length-prefixed data"));
  1058. return 0;
  1059. }
  1060. hdr_len = i + 1;
  1061. *prefix_len_out = hdr_len;
  1062. if (hdr_len + val > len)
  1063. {
  1064. UNPACK_ERROR (("data too short after length-prefix of %u",
  1065. val));
  1066. return 0;
  1067. }
  1068. return hdr_len + val;
  1069. }
  1070. static inline uint32_t
  1071. parse_uint32 (unsigned len, const uint8_t *data)
  1072. {
  1073. unsigned rv = data[0] & 0x7f;
  1074. if (len > 1)
  1075. {
  1076. rv |= ((data[1] & 0x7f) << 7);
  1077. if (len > 2)
  1078. {
  1079. rv |= ((data[2] & 0x7f) << 14);
  1080. if (len > 3)
  1081. {
  1082. rv |= ((data[3] & 0x7f) << 21);
  1083. if (len > 4)
  1084. rv |= (data[4] << 28);
  1085. }
  1086. }
  1087. }
  1088. return rv;
  1089. }
  1090. static inline uint32_t
  1091. parse_int32 (unsigned len, const uint8_t *data)
  1092. {
  1093. return parse_uint32 (len, data);
  1094. }
  1095. static inline int32_t
  1096. unzigzag32 (uint32_t v)
  1097. {
  1098. if (v&1)
  1099. return -(v>>1) - 1;
  1100. else
  1101. return v>>1;
  1102. }
  1103. static inline uint32_t
  1104. parse_fixed_uint32 (const uint8_t *data)
  1105. {
  1106. #if IS_LITTLE_ENDIAN
  1107. uint32_t t;
  1108. memcpy (&t, data, 4);
  1109. return t;
  1110. #else
  1111. return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
  1112. #endif
  1113. }
  1114. static uint64_t
  1115. parse_uint64 (unsigned len, const uint8_t *data)
  1116. {
  1117. unsigned shift, i;
  1118. if (len < 5)
  1119. return parse_uint32 (len, data);
  1120. uint64_t rv = ((data[0] & 0x7f))
  1121. | ((data[1] & 0x7f)<<7)
  1122. | ((data[2] & 0x7f)<<14)
  1123. | ((data[3] & 0x7f)<<21);
  1124. shift = 28;
  1125. for (i = 4; i < len; i++)
  1126. {
  1127. rv |= (((uint64_t)(data[i]&0x7f)) << shift);
  1128. shift += 7;
  1129. }
  1130. return rv;
  1131. }
  1132. static inline int64_t
  1133. unzigzag64 (uint64_t v)
  1134. {
  1135. if (v&1)
  1136. return -(v>>1) - 1;
  1137. else
  1138. return v>>1;
  1139. }
  1140. static inline uint64_t
  1141. parse_fixed_uint64 (const uint8_t *data)
  1142. {
  1143. #if IS_LITTLE_ENDIAN
  1144. uint64_t t;
  1145. memcpy (&t, data, 8);
  1146. return t;
  1147. #else
  1148. return (uint64_t)parse_fixed_uint32 (data)
  1149. | (((uint64_t)parse_fixed_uint32(data+4)) << 32);
  1150. #endif
  1151. }
  1152. static protobuf_c_boolean
  1153. parse_boolean (unsigned len, const uint8_t *data)
  1154. {
  1155. unsigned i;
  1156. for (i = 0; i < len; i++)
  1157. if (data[i] & 0x7f)
  1158. return 1;
  1159. return 0;
  1160. }
  1161. static protobuf_c_boolean
  1162. parse_required_member (ScannedMember *scanned_member,
  1163. void *member,
  1164. ProtobufCAllocator *allocator,
  1165. protobuf_c_boolean maybe_clear)
  1166. {
  1167. unsigned len = scanned_member->len;
  1168. const uint8_t *data = scanned_member->data;
  1169. ProtobufCWireType wire_type = scanned_member->wire_type;
  1170. switch (scanned_member->field->type)
  1171. {
  1172. case PROTOBUF_C_TYPE_INT32:
  1173. if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
  1174. return 0;
  1175. *(uint32_t*)member = parse_int32 (len, data);
  1176. return 1;
  1177. case PROTOBUF_C_TYPE_UINT32:
  1178. if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
  1179. return 0;
  1180. *(uint32_t*)member = parse_uint32 (len, data);
  1181. return 1;
  1182. case PROTOBUF_C_TYPE_SINT32:
  1183. if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
  1184. return 0;
  1185. *(int32_t*)member = unzigzag32 (parse_uint32 (len, data));
  1186. return 1;
  1187. case PROTOBUF_C_TYPE_SFIXED32:
  1188. case PROTOBUF_C_TYPE_FIXED32:
  1189. case PROTOBUF_C_TYPE_FLOAT:
  1190. if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT)
  1191. return 0;
  1192. *(uint32_t*)member = parse_fixed_uint32 (data);
  1193. return 1;
  1194. case PROTOBUF_C_TYPE_INT64:
  1195. case PROTOBUF_C_TYPE_UINT64:
  1196. if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
  1197. return 0;
  1198. *(uint64_t*)member = parse_uint64 (len, data);
  1199. return 1;
  1200. case PROTOBUF_C_TYPE_SINT64:
  1201. if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
  1202. return 0;
  1203. *(int64_t*)member = unzigzag64 (parse_uint64 (len, data));
  1204. return 1;
  1205. case PROTOBUF_C_TYPE_SFIXED64:
  1206. case PROTOBUF_C_TYPE_FIXED64:
  1207. case PROTOBUF_C_TYPE_DOUBLE:
  1208. if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT)
  1209. return 0;
  1210. *(uint64_t*)member = parse_fixed_uint64 (data);
  1211. return 1;
  1212. case PROTOBUF_C_TYPE_BOOL:
  1213. *(protobuf_c_boolean*)member = parse_boolean (len, data);
  1214. return 1;
  1215. case PROTOBUF_C_TYPE_ENUM:
  1216. if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
  1217. return 0;
  1218. *(uint32_t*)member = parse_uint32 (len, data);
  1219. return 1;
  1220. case PROTOBUF_C_TYPE_STRING:
  1221. if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
  1222. return 0;
  1223. {
  1224. char **pstr = member;
  1225. unsigned pref_len = scanned_member->length_prefix_len;
  1226. if (maybe_clear && *pstr != NULL)
  1227. {
  1228. const char *def = scanned_member->field->default_value;
  1229. if (*pstr != NULL && *pstr != def)
  1230. FREE (allocator, *pstr);
  1231. }
  1232. DO_ALLOC (*pstr, allocator, len - pref_len + 1, return 0);
  1233. memcpy (*pstr, data + pref_len, len - pref_len);
  1234. (*pstr)[len-pref_len] = 0;
  1235. return 1;
  1236. }
  1237. case PROTOBUF_C_TYPE_BYTES:
  1238. if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
  1239. return 0;
  1240. {
  1241. ProtobufCBinaryData *bd = member;
  1242. const ProtobufCBinaryData *def_bd;
  1243. unsigned pref_len = scanned_member->length_prefix_len;
  1244. def_bd = scanned_member->field->default_value;
  1245. if (maybe_clear && bd->data != NULL && bd->data != def_bd->data)
  1246. FREE (allocator, bd->data);
  1247. DO_ALLOC (bd->data, allocator, len - pref_len, return 0);
  1248. memcpy (bd->data, data + pref_len, len - pref_len);
  1249. bd->len = len - pref_len;
  1250. return 1;
  1251. }
  1252. //case PROTOBUF_C_TYPE_GROUP, // NOT SUPPORTED
  1253. case PROTOBUF_C_TYPE_MESSAGE:
  1254. if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
  1255. return 0;
  1256. {
  1257. ProtobufCMessage **pmessage = member;
  1258. ProtobufCMessage *subm;
  1259. const ProtobufCMessage *def_mess;
  1260. unsigned pref_len = scanned_member->length_prefix_len;
  1261. def_mess = scanned_member->field->default_value;
  1262. if (maybe_clear && *pmessage != NULL && *pmessage != def_mess)
  1263. protobuf_c_message_free_unpacked (*pmessage, allocator);
  1264. subm = protobuf_c_message_unpack (scanned_member->field->descriptor,
  1265. allocator,
  1266. len - pref_len, data + pref_len);
  1267. *pmessage = subm; /* since we freed the message we must clear the field, even if NULL */
  1268. if (subm == NULL)
  1269. return 0;
  1270. return 1;
  1271. }
  1272. }
  1273. return 0;
  1274. }
  1275. static protobuf_c_boolean
  1276. parse_optional_member (ScannedMember *scanned_member,
  1277. void *member,
  1278. ProtobufCMessage *message,
  1279. ProtobufCAllocator *allocator)
  1280. {
  1281. if (!parse_required_member (scanned_member, member, allocator, TRUE))
  1282. return 0;
  1283. if (scanned_member->field->quantifier_offset != 0)
  1284. STRUCT_MEMBER (protobuf_c_boolean,
  1285. message,
  1286. scanned_member->field->quantifier_offset) = 1;
  1287. return 1;
  1288. }
  1289. static protobuf_c_boolean
  1290. parse_repeated_member (ScannedMember *scanned_member,
  1291. void *member,
  1292. ProtobufCMessage *message,
  1293. ProtobufCAllocator *allocator)
  1294. {
  1295. const ProtobufCFieldDescriptor *field = scanned_member->field;
  1296. size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
  1297. size_t siz = sizeof_elt_in_repeated_array (field->type);
  1298. char *array = *(char**)member;
  1299. if (!parse_required_member (scanned_member,
  1300. array + siz * (*p_n),
  1301. allocator,
  1302. FALSE))
  1303. return 0;
  1304. *p_n += 1;
  1305. return 1;
  1306. }
  1307. static protobuf_c_boolean
  1308. parse_member (ScannedMember *scanned_member,
  1309. ProtobufCMessage *message,
  1310. ProtobufCAllocator *allocator)
  1311. {
  1312. const ProtobufCFieldDescriptor *field = scanned_member->field;
  1313. void *member;
  1314. if (field == NULL)
  1315. {
  1316. ProtobufCMessageUnknownField *ufield = message->unknown_fields + (message->n_unknown_fields++);
  1317. ufield->tag = scanned_member->tag;
  1318. ufield->wire_type = scanned_member->wire_type;
  1319. ufield->len = scanned_member->len;
  1320. DO_UNALIGNED_ALLOC (ufield->data, allocator, scanned_member->len, return 0);
  1321. memcpy (ufield->data, scanned_member->data, ufield->len);
  1322. return 1;
  1323. }
  1324. member = (char*)message + field->offset;
  1325. switch (field->label)
  1326. {
  1327. case PROTOBUF_C_LABEL_REQUIRED:
  1328. return parse_required_member (scanned_member, member, allocator, TRUE);
  1329. case PROTOBUF_C_LABEL_OPTIONAL:
  1330. return parse_optional_member (scanned_member, member, message, allocator);
  1331. case PROTOBUF_C_LABEL_REPEATED:
  1332. return parse_repeated_member (scanned_member, member, message, allocator);
  1333. }
  1334. PROTOBUF_C_ASSERT_NOT_REACHED ();
  1335. return 0;
  1336. }
  1337. static inline void
  1338. setup_default_values (ProtobufCMessage *message)
  1339. {
  1340. const ProtobufCMessageDescriptor *desc = message->descriptor;
  1341. unsigned i;
  1342. for (i = 0; i < desc->n_fields; i++)
  1343. if (desc->fields[i].default_value != NULL
  1344. && desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED)
  1345. {
  1346. void *field = STRUCT_MEMBER_P (message, desc->fields[i].offset);
  1347. const void *dv = desc->fields[i].default_value;
  1348. switch (desc->fields[i].type)
  1349. {
  1350. case PROTOBUF_C_TYPE_INT32:
  1351. case PROTOBUF_C_TYPE_SINT32:
  1352. case PROTOBUF_C_TYPE_SFIXED32:
  1353. case PROTOBUF_C_TYPE_UINT32:
  1354. case PROTOBUF_C_TYPE_FIXED32:
  1355. case PROTOBUF_C_TYPE_FLOAT:
  1356. case PROTOBUF_C_TYPE_ENUM:
  1357. memcpy (field, dv, 4);
  1358. break;
  1359. case PROTOBUF_C_TYPE_INT64:
  1360. case PROTOBUF_C_TYPE_SINT64:
  1361. case PROTOBUF_C_TYPE_SFIXED64:
  1362. case PROTOBUF_C_TYPE_UINT64:
  1363. case PROTOBUF_C_TYPE_FIXED64:
  1364. case PROTOBUF_C_TYPE_DOUBLE:
  1365. memcpy (field, dv, 8);
  1366. break;
  1367. case PROTOBUF_C_TYPE_BOOL:
  1368. memcpy (field, dv, sizeof (protobuf_c_boolean));
  1369. break;
  1370. case PROTOBUF_C_TYPE_BYTES:
  1371. memcpy (field, dv, sizeof (ProtobufCBinaryData));
  1372. break;
  1373. case PROTOBUF_C_TYPE_STRING:
  1374. case PROTOBUF_C_TYPE_MESSAGE:
  1375. /* the next line essentially implements a cast from const,
  1376. which is totally unavoidable. */
  1377. *(const void**)field = dv;
  1378. break;
  1379. }
  1380. }
  1381. }
  1382. /* ScannedMember slabs (an unpacking implementation detail).
  1383. Before doing real unpacking, we first scan through the
  1384. elements to see how many there are (for repeated fields),
  1385. and which field to use (for non-repeated fields given twice).
  1386. * In order to avoid allocations for small messages,
  1387. we keep a stack-allocated slab of ScannedMembers of
  1388. size FIRST_SCANNED_MEMBER_SLAB_SIZE (16).
  1389. After we fill that up, we allocate each slab twice
  1390. as large as the previous one. */
  1391. #define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4
  1392. /* The number of slabs, including the stack-allocated ones;
  1393. choose the number so that we would overflow if we needed
  1394. a slab larger than provided. */
  1395. #define MAX_SCANNED_MEMBER_SLAB \
  1396. (sizeof(void*)*8 - 1 \
  1397. - BOUND_SIZEOF_SCANNED_MEMBER_LOG2 \
  1398. - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)
  1399. ProtobufCMessage *
  1400. protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
  1401. ProtobufCAllocator *allocator,
  1402. size_t len,
  1403. const uint8_t *data)
  1404. {
  1405. ProtobufCMessage *rv;
  1406. size_t rem = len;
  1407. const uint8_t *at = data;
  1408. const ProtobufCFieldDescriptor *last_field = desc->fields + 0;
  1409. ScannedMember first_member_slab[1<<FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2];
  1410. /* scanned_member_slabs[i] is an array of arrays of ScannedMember.
  1411. The first slab (scanned_member_slabs[0] is just a pointer to
  1412. first_member_slab), above. All subsequent slabs will be allocated
  1413. using the allocator. */
  1414. ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB+1];
  1415. unsigned which_slab = 0; /* the slab we are currently populating */
  1416. unsigned in_slab_index = 0; /* number of members in the slab */
  1417. size_t n_unknown = 0;
  1418. unsigned f;
  1419. unsigned i_slab;
  1420. ASSERT_IS_MESSAGE_DESCRIPTOR (desc);
  1421. if (allocator == NULL)
  1422. allocator = &protobuf_c_default_allocator;
  1423. DO_ALLOC (rv, allocator, desc->sizeof_message, return NULL);
  1424. scanned_member_slabs[0] = first_member_slab;
  1425. memset (rv, 0, desc->sizeof_message);
  1426. rv->descriptor = desc;
  1427. setup_default_values (rv);
  1428. while (rem > 0)
  1429. {
  1430. uint32_t tag;
  1431. ProtobufCWireType wire_type;
  1432. size_t used = parse_tag_and_wiretype (rem, at, &tag, &wire_type);
  1433. const ProtobufCFieldDescriptor *field;
  1434. ScannedMember tmp;
  1435. if (used == 0)
  1436. {
  1437. UNPACK_ERROR (("error parsing tag/wiretype at offset %u",
  1438. (unsigned)(at-data)));
  1439. goto error_cleanup_during_scan;
  1440. }
  1441. /* XXX: consider optimizing for field[1].id == tag, if field[1] exists! */
  1442. if (last_field->id != tag)
  1443. {
  1444. /* lookup field */
  1445. int field_index = int_range_lookup (desc->n_field_ranges,
  1446. desc->field_ranges,
  1447. tag);
  1448. if (field_index < 0)
  1449. {
  1450. field = NULL;
  1451. n_unknown++;
  1452. }
  1453. else
  1454. {
  1455. field = desc->fields + field_index;
  1456. last_field = field;
  1457. }
  1458. }
  1459. else
  1460. field = last_field;
  1461. at += used;
  1462. rem -= used;
  1463. tmp.tag = tag;
  1464. tmp.wire_type = wire_type;
  1465. tmp.field = field;
  1466. tmp.data = at;
  1467. switch (wire_type)
  1468. {
  1469. case PROTOBUF_C_WIRE_TYPE_VARINT:
  1470. {
  1471. unsigned max_len = rem < 10 ? rem : 10;
  1472. unsigned i;
  1473. for (i = 0; i < max_len; i++)
  1474. if ((at[i] & 0x80) == 0)
  1475. break;
  1476. if (i == max_len)
  1477. {
  1478. UNPACK_ERROR (("unterminated varint at offset %u",
  1479. (unsigned)(at-data)));
  1480. goto error_cleanup_during_scan;
  1481. }
  1482. tmp.len = i + 1;
  1483. }
  1484. break;
  1485. case PROTOBUF_C_WIRE_TYPE_64BIT:
  1486. if (rem < 8)
  1487. {
  1488. UNPACK_ERROR (("too short after 64bit wiretype at offset %u",
  1489. (unsigned)(at-data)));
  1490. goto error_cleanup_during_scan;
  1491. }
  1492. tmp.len = 8;
  1493. break;
  1494. case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED:
  1495. {
  1496. size_t pref_len;
  1497. tmp.len = scan_length_prefixed_data (rem, at, &pref_len);
  1498. if (tmp.len == 0)
  1499. {
  1500. /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */
  1501. goto error_cleanup_during_scan;
  1502. }
  1503. tmp.length_prefix_len = pref_len;
  1504. break;
  1505. }
  1506. case PROTOBUF_C_WIRE_TYPE_32BIT:
  1507. if (rem < 4)
  1508. {
  1509. UNPACK_ERROR (("too short after 32bit wiretype at offset %u",
  1510. (unsigned)(at-data)));
  1511. goto error_cleanup_during_scan;
  1512. }
  1513. tmp.len = 4;
  1514. break;
  1515. default:
  1516. UNPACK_ERROR (("unsupported tag %u at offset %u",
  1517. wire_type, (unsigned)(at-data)));
  1518. goto error_cleanup_during_scan;
  1519. }
  1520. if (in_slab_index == (1U<<(which_slab+FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)))
  1521. {
  1522. size_t size;
  1523. in_slab_index = 0;
  1524. if (which_slab == MAX_SCANNED_MEMBER_SLAB)
  1525. {
  1526. UNPACK_ERROR (("too many fields"));
  1527. goto error_cleanup_during_scan;
  1528. }
  1529. which_slab++;
  1530. size = sizeof(ScannedMember) << (which_slab+FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2);
  1531. /* TODO: consider using alloca() ! */
  1532. if (allocator->tmp_alloc != NULL)
  1533. scanned_member_slabs[which_slab] = TMPALLOC(allocator, size);
  1534. else
  1535. DO_ALLOC (scanned_member_slabs[which_slab], allocator, size, goto error_cleanup_during_scan);
  1536. }
  1537. scanned_member_slabs[which_slab][in_slab_index++] = tmp;
  1538. if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED)
  1539. {
  1540. STRUCT_MEMBER (size_t, rv, field->quantifier_offset) += 1;
  1541. }
  1542. at += tmp.len;
  1543. rem -= tmp.len;
  1544. }
  1545. /* allocate space for repeated fields */
  1546. for (f = 0; f < desc->n_fields; f++)
  1547. if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED)
  1548. {
  1549. const ProtobufCFieldDescriptor *field = desc->fields + f;
  1550. size_t siz = sizeof_elt_in_repeated_array (field->type);
  1551. size_t *n_ptr = STRUCT_MEMBER_PTR (size_t, rv, field->quantifier_offset);
  1552. if (*n_ptr != 0)
  1553. {
  1554. unsigned n = *n_ptr;
  1555. *n_ptr = 0;
  1556. assert(rv->descriptor != NULL);
  1557. #define CLEAR_REMAINING_N_PTRS() \
  1558. for(f++;f < desc->n_fields; f++) \
  1559. { \
  1560. field = desc->fields + f; \
  1561. if (field->label == PROTOBUF_C_LABEL_REPEATED) \
  1562. STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \
  1563. }
  1564. DO_ALLOC (STRUCT_MEMBER (void *, rv, field->offset),
  1565. allocator, siz * n,
  1566. CLEAR_REMAINING_N_PTRS (); goto error_cleanup);
  1567. #undef CLEAR_REMAINING_N_PTRS
  1568. }
  1569. }
  1570. /* allocate space for unknown fields */
  1571. if (n_unknown)
  1572. {
  1573. DO_ALLOC (rv->unknown_fields,
  1574. allocator, n_unknown * sizeof (ProtobufCMessageUnknownField),
  1575. goto error_cleanup);
  1576. }
  1577. /* do real parsing */
  1578. for (i_slab = 0; i_slab <= which_slab; i_slab++)
  1579. {
  1580. unsigned max = (i_slab == which_slab) ? in_slab_index : (1U<<(i_slab+4));
  1581. ScannedMember *slab = scanned_member_slabs[i_slab];
  1582. unsigned j;
  1583. for (j = 0; j < max; j++)
  1584. {
  1585. if (!parse_member (slab + j, rv, allocator))
  1586. {
  1587. UNPACK_ERROR (("error parsing member %s of %s",
  1588. slab->field ? slab->field->name : "*unknown-field*", desc->name));
  1589. goto error_cleanup;
  1590. }
  1591. }
  1592. }
  1593. /* cleanup */
  1594. if (allocator->tmp_alloc == NULL)
  1595. {
  1596. unsigned j;
  1597. for (j = 1; j <= which_slab; j++)
  1598. FREE (allocator, scanned_member_slabs[j]);
  1599. }
  1600. return rv;
  1601. error_cleanup:
  1602. protobuf_c_message_free_unpacked (rv, allocator);
  1603. if (allocator->tmp_alloc == NULL)
  1604. {
  1605. unsigned j;
  1606. for (j = 1; j <= which_slab; j++)
  1607. FREE (allocator, scanned_member_slabs[j]);
  1608. }
  1609. return NULL;
  1610. error_cleanup_during_scan:
  1611. FREE (allocator, rv);
  1612. if (allocator->tmp_alloc == NULL)
  1613. {
  1614. unsigned j;
  1615. for (j = 1; j <= which_slab; j++)
  1616. FREE (allocator, scanned_member_slabs[j]);
  1617. }
  1618. return NULL;
  1619. }
  1620. /* === free_unpacked === */
  1621. void
  1622. protobuf_c_message_free_unpacked (ProtobufCMessage *message,
  1623. ProtobufCAllocator *allocator)
  1624. {
  1625. const ProtobufCMessageDescriptor *desc = message->descriptor;
  1626. unsigned f;
  1627. ASSERT_IS_MESSAGE (message);
  1628. if (allocator == NULL)
  1629. allocator = &protobuf_c_default_allocator;
  1630. message->descriptor = NULL;
  1631. for (f = 0; f < desc->n_fields; f++)
  1632. {
  1633. if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED)
  1634. {
  1635. size_t n = STRUCT_MEMBER (size_t, message, desc->fields[f].quantifier_offset);
  1636. void * arr = STRUCT_MEMBER (void *, message, desc->fields[f].offset);
  1637. if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING)
  1638. {
  1639. unsigned i;
  1640. for (i = 0; i < n; i++)
  1641. FREE (allocator, ((char**)arr)[i]);
  1642. }
  1643. else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES)
  1644. {
  1645. unsigned i;
  1646. for (i = 0; i < n; i++)
  1647. FREE (allocator, ((ProtobufCBinaryData*)arr)[i].data);
  1648. }
  1649. else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE)
  1650. {
  1651. unsigned i;
  1652. for (i = 0; i < n; i++)
  1653. protobuf_c_message_free_unpacked (((ProtobufCMessage**)arr)[i], allocator);
  1654. }
  1655. if (arr != NULL)
  1656. FREE (allocator, arr);
  1657. }
  1658. else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING)
  1659. {
  1660. char *str = STRUCT_MEMBER (char *, message, desc->fields[f].offset);
  1661. if (str && str != desc->fields[f].default_value)
  1662. FREE (allocator, str);
  1663. }
  1664. else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES)
  1665. {
  1666. void *data = STRUCT_MEMBER (ProtobufCBinaryData, message, desc->fields[f].offset).data;
  1667. const ProtobufCBinaryData *default_bd;
  1668. default_bd = desc->fields[f].default_value;
  1669. if (data != NULL
  1670. && (default_bd == NULL || default_bd->data != data))
  1671. FREE (allocator, data);
  1672. }
  1673. else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE)
  1674. {
  1675. ProtobufCMessage *sm;
  1676. sm = STRUCT_MEMBER (ProtobufCMessage *, message,desc->fields[f].offset);
  1677. if (sm && sm != desc->fields[f].default_value)
  1678. protobuf_c_message_free_unpacked (sm, allocator);
  1679. }
  1680. }
  1681. for (f = 0; f < message->n_unknown_fields; f++)
  1682. FREE (allocator, message->unknown_fields[f].data);
  1683. if (message->unknown_fields != NULL)
  1684. FREE (allocator, message->unknown_fields);
  1685. FREE (allocator, message);
  1686. }
  1687. /* === services === */
  1688. typedef void (*DestroyHandler)(void *service);
  1689. typedef void (*GenericHandler)(void *service,
  1690. const ProtobufCMessage *input,
  1691. ProtobufCClosure closure,
  1692. void *closure_data);
  1693. void
  1694. protobuf_c_service_invoke_internal(ProtobufCService *service,
  1695. unsigned method_index,
  1696. const ProtobufCMessage *input,
  1697. ProtobufCClosure closure,
  1698. void *closure_data)
  1699. {
  1700. GenericHandler *handlers;
  1701. GenericHandler handler;
  1702. PROTOBUF_C_ASSERT (method_index < service->descriptor->n_methods);
  1703. handlers = (GenericHandler *) (service + 1);
  1704. handler = handlers[method_index];
  1705. (*handler) (service, input, closure, closure_data);
  1706. }
  1707. void
  1708. protobuf_c_service_generated_init (ProtobufCService *service,
  1709. const ProtobufCServiceDescriptor *descriptor,
  1710. ProtobufCServiceDestroy destroy)
  1711. {
  1712. ASSERT_IS_SERVICE_DESCRIPTOR(descriptor);
  1713. service->descriptor = descriptor;
  1714. service->destroy = destroy;
  1715. service->invoke = protobuf_c_service_invoke_internal;
  1716. memset (service + 1, 0, descriptor->n_methods * sizeof (GenericHandler));
  1717. }
  1718. void protobuf_c_service_destroy (ProtobufCService *service)
  1719. {
  1720. service->destroy (service);
  1721. }
  1722. /* --- querying the descriptors --- */
  1723. const ProtobufCEnumValue *
  1724. protobuf_c_enum_descriptor_get_value_by_name
  1725. (const ProtobufCEnumDescriptor *desc,
  1726. const char *name)
  1727. {
  1728. unsigned start = 0, count = desc->n_value_names;
  1729. while (count > 1)
  1730. {
  1731. unsigned mid = start + count / 2;
  1732. int rv = strcmp (desc->values_by_name[mid].name, name);
  1733. if (rv == 0)
  1734. return desc->values + desc->values_by_name[mid].index;
  1735. else if (rv < 0)
  1736. {
  1737. count = start + count - (mid - 1);
  1738. start = mid + 1;
  1739. }
  1740. else
  1741. count = mid - start;
  1742. }
  1743. if (count == 0)
  1744. return NULL;
  1745. if (strcmp (desc->values_by_name[start].name, name) == 0)
  1746. return desc->values + desc->values_by_name[start].index;
  1747. return NULL;
  1748. }
  1749. const ProtobufCEnumValue *
  1750. protobuf_c_enum_descriptor_get_value
  1751. (const ProtobufCEnumDescriptor *desc,
  1752. int value)
  1753. {
  1754. int rv = int_range_lookup (desc->n_value_ranges, desc->value_ranges, value);
  1755. if (rv < 0)
  1756. return NULL;
  1757. return desc->values + rv;
  1758. }
  1759. const ProtobufCFieldDescriptor *
  1760. protobuf_c_message_descriptor_get_field_by_name
  1761. (const ProtobufCMessageDescriptor *desc,
  1762. const char *name)
  1763. {
  1764. unsigned start = 0, count = desc->n_fields;
  1765. const ProtobufCFieldDescriptor *field;
  1766. while (count > 1)
  1767. {
  1768. unsigned mid = start + count / 2;
  1769. int rv;
  1770. field = desc->fields + desc->fields_sorted_by_name[mid];
  1771. rv = strcmp (field->name, name);
  1772. if (rv == 0)
  1773. return field;
  1774. else if (rv < 0)
  1775. {
  1776. count = start + count - (mid + 1);
  1777. start = mid + 1;
  1778. }
  1779. else
  1780. count = mid - start;
  1781. }
  1782. if (count == 0)
  1783. return NULL;
  1784. field = desc->fields + desc->fields_sorted_by_name[start];
  1785. if (strcmp (field->name, name) == 0)
  1786. return field;
  1787. return NULL;
  1788. }
  1789. const ProtobufCFieldDescriptor *
  1790. protobuf_c_message_descriptor_get_field
  1791. (const ProtobufCMessageDescriptor *desc,
  1792. unsigned value)
  1793. {
  1794. int rv = int_range_lookup (desc->n_field_ranges,
  1795. desc->field_ranges,
  1796. value);
  1797. if (rv < 0)
  1798. return NULL;
  1799. return desc->fields + rv;
  1800. }
  1801. const ProtobufCMethodDescriptor *
  1802. protobuf_c_service_descriptor_get_method_by_name
  1803. (const ProtobufCServiceDescriptor *desc,
  1804. const char *name)
  1805. {
  1806. unsigned start = 0, count = desc->n_methods;
  1807. while (count > 1)
  1808. {
  1809. unsigned mid = start + count / 2;
  1810. int rv = strcmp (desc->methods[desc->method_indices_by_name[mid]].name, name);
  1811. if (rv == 0)
  1812. return desc->methods + desc->method_indices_by_name[mid];
  1813. if (rv < 0)
  1814. {
  1815. count = start + count - (mid - 1);
  1816. start = mid + 1;
  1817. }
  1818. else
  1819. {
  1820. count = mid - start;
  1821. }
  1822. }
  1823. if (count == 0)
  1824. return NULL;
  1825. if (strcmp (desc->methods[desc->method_indices_by_name[start]].name, name) == 0)
  1826. return desc->methods + desc->method_indices_by_name[start];
  1827. return NULL;
  1828. }