PageRenderTime 56ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/iOS/Framework/AppBlade/CrashReporter/Dependencies/protobuf-2.0.3/src/protobuf-c.c

https://github.com/where/Fork_AppBlade_SDK
C | 1758 lines | 1631 code | 79 blank | 48 comment | 322 complexity | f3993856583f294fda4fdf0ad082fd43 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  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. #include <stdio.h> /* for occasional printf()s */
  17. #include <stdlib.h> /* for abort(), malloc() etc */
  18. #include <string.h> /* for strlen(), memcpy(), memmove() */
  19. #define PRINT_UNPACK_ERRORS 1
  20. #include "protobuf-c.h"
  21. #define MAX_UINT64_ENCODED_SIZE 10
  22. /* convenience macros */
  23. #define TMPALLOC(allocator, size) ((allocator)->tmp_alloc ((allocator)->allocator_data, (size)))
  24. #define ALLOC(allocator, size) ((allocator)->alloc ((allocator)->allocator_data, (size)))
  25. #define FREE(allocator, ptr) ((allocator)->free ((allocator)->allocator_data, (ptr)))
  26. #define UNALIGNED_ALLOC(allocator, size) ALLOC (allocator, size) /* placeholder */
  27. #define STRUCT_MEMBER_P(struct_p, struct_offset) \
  28. ((void *) ((uint8_t*) (struct_p) + (struct_offset)))
  29. #define STRUCT_MEMBER(member_type, struct_p, struct_offset) \
  30. (*(member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset)))
  31. #define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \
  32. ((member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset)))
  33. #define TRUE 1
  34. #define FALSE 0
  35. #define ASSERT_IS_ENUM_DESCRIPTOR(desc) \
  36. assert((desc)->magic == PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC)
  37. #define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \
  38. assert((desc)->magic == PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC)
  39. #define ASSERT_IS_MESSAGE(message) \
  40. ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor)
  41. #define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \
  42. assert((desc)->magic == PROTOBUF_C_SERVICE_DESCRIPTOR_MAGIC)
  43. /* --- allocator --- */
  44. static void protobuf_c_out_of_memory_default (void)
  45. {
  46. fprintf (stderr, "Out Of Memory!!!\n");
  47. abort ();
  48. }
  49. void (*protobuf_c_out_of_memory) (void) = protobuf_c_out_of_memory_default;
  50. static void *system_alloc(void *allocator_data, size_t size)
  51. {
  52. void *rv;
  53. (void) allocator_data;
  54. if (size == 0)
  55. return NULL;
  56. rv = malloc (size);
  57. if (rv == NULL)
  58. protobuf_c_out_of_memory ();
  59. return rv;
  60. }
  61. static void system_free (void *allocator_data, void *data)
  62. {
  63. (void) allocator_data;
  64. if (data)
  65. free (data);
  66. }
  67. ProtobufCAllocator protobuf_c_default_allocator =
  68. {
  69. system_alloc,
  70. system_free,
  71. NULL,
  72. 8192,
  73. NULL
  74. };
  75. ProtobufCAllocator protobuf_c_system_allocator =
  76. {
  77. system_alloc,
  78. system_free,
  79. NULL,
  80. 8192,
  81. NULL
  82. };
  83. /* === buffer-simple === */
  84. void
  85. protobuf_c_buffer_simple_append (ProtobufCBuffer *buffer,
  86. size_t len,
  87. const uint8_t *data)
  88. {
  89. ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer;
  90. size_t new_len = simp->len + len;
  91. if (new_len > simp->alloced)
  92. {
  93. size_t new_alloced = simp->alloced * 2;
  94. uint8_t *new_data;
  95. while (new_alloced < new_len)
  96. new_alloced += new_alloced;
  97. new_data = ALLOC (&protobuf_c_default_allocator, new_alloced);
  98. memcpy (new_data, simp->data, simp->len);
  99. if (simp->must_free_data)
  100. FREE (&protobuf_c_default_allocator, simp->data);
  101. else
  102. simp->must_free_data = 1;
  103. simp->data = new_data;
  104. simp->alloced = new_alloced;
  105. }
  106. memcpy (simp->data + simp->len, data, len);
  107. simp->len = new_len;
  108. }
  109. /* === get_packed_size() === */
  110. static inline size_t
  111. get_tag_size (unsigned number)
  112. {
  113. if (number < (1<<4))
  114. return 1;
  115. else if (number < (1<<11))
  116. return 2;
  117. else if (number < (1<<18))
  118. return 3;
  119. else if (number < (1<<25))
  120. return 4;
  121. else
  122. return 5;
  123. }
  124. static inline size_t
  125. uint32_size (uint32_t v)
  126. {
  127. if (v < (1<<7))
  128. return 1;
  129. else if (v < (1<<14))
  130. return 2;
  131. else if (v < (1<<21))
  132. return 3;
  133. else if (v < (1<<28))
  134. return 4;
  135. else
  136. return 5;
  137. }
  138. static inline size_t
  139. int32_size (int32_t v)
  140. {
  141. if (v < 0)
  142. return 10;
  143. else
  144. if (v < (1<<7))
  145. return 1;
  146. else if (v < (1<<14))
  147. return 2;
  148. else if (v < (1<<21))
  149. return 3;
  150. else if (v < (1<<28))
  151. return 4;
  152. else
  153. return 5;
  154. }
  155. static inline uint32_t
  156. zigzag32 (int32_t v)
  157. {
  158. if (v < 0)
  159. return ((uint32_t)(-v)) * 2 - 1;
  160. else
  161. return v * 2;
  162. }
  163. static inline size_t
  164. sint32_size (int32_t v)
  165. {
  166. return uint32_size(zigzag32(v));
  167. }
  168. static inline size_t
  169. uint64_size (uint64_t v)
  170. {
  171. uint32_t upper_v = (v>>32);
  172. if (upper_v == 0)
  173. return uint32_size ((uint32_t)v);
  174. else if (upper_v < (1<<3))
  175. return 5;
  176. else if (upper_v < (1<<10))
  177. return 6;
  178. else if (upper_v < (1<<17))
  179. return 7;
  180. else if (upper_v < (1<<24))
  181. return 8;
  182. else if (upper_v < (1U<<31))
  183. return 9;
  184. else
  185. return 10;
  186. }
  187. static inline uint64_t
  188. zigzag64 (int64_t v)
  189. {
  190. if (v < 0)
  191. return ((uint64_t)(-v)) * 2 - 1;
  192. else
  193. return v * 2;
  194. }
  195. static inline size_t
  196. sint64_size (int64_t v)
  197. {
  198. return uint64_size(zigzag64(v));
  199. }
  200. static size_t
  201. required_field_get_packed_size (const ProtobufCFieldDescriptor *field,
  202. const void *member)
  203. {
  204. size_t rv = get_tag_size (field->id);
  205. switch (field->type)
  206. {
  207. case PROTOBUF_C_TYPE_SINT32:
  208. return rv + sint32_size (*(const int32_t *) member);
  209. case PROTOBUF_C_TYPE_INT32:
  210. return rv + int32_size (*(const uint32_t *) member);
  211. case PROTOBUF_C_TYPE_UINT32:
  212. return rv + uint32_size (*(const uint32_t *) member);
  213. case PROTOBUF_C_TYPE_SINT64:
  214. return rv + sint64_size (*(const int64_t *) member);
  215. case PROTOBUF_C_TYPE_INT64:
  216. case PROTOBUF_C_TYPE_UINT64:
  217. return rv + uint64_size (*(const uint64_t *) member);
  218. case PROTOBUF_C_TYPE_SFIXED32:
  219. case PROTOBUF_C_TYPE_FIXED32:
  220. return rv + 4;
  221. case PROTOBUF_C_TYPE_SFIXED64:
  222. case PROTOBUF_C_TYPE_FIXED64:
  223. return rv + 8;
  224. case PROTOBUF_C_TYPE_BOOL:
  225. return rv + 1;
  226. case PROTOBUF_C_TYPE_FLOAT:
  227. return rv + 4;
  228. case PROTOBUF_C_TYPE_DOUBLE:
  229. return rv + 8;
  230. case PROTOBUF_C_TYPE_ENUM:
  231. // TODO: is this correct for negative-valued enums?
  232. return rv + uint32_size (*(const uint32_t *) member);
  233. case PROTOBUF_C_TYPE_STRING:
  234. {
  235. size_t len = strlen (*(char * const *) member);
  236. return rv + uint32_size (len) + len;
  237. }
  238. case PROTOBUF_C_TYPE_BYTES:
  239. {
  240. size_t len = ((const ProtobufCBinaryData*) member)->len;
  241. return rv + uint32_size (len) + len;
  242. }
  243. //case PROTOBUF_C_TYPE_GROUP:
  244. case PROTOBUF_C_TYPE_MESSAGE:
  245. {
  246. size_t subrv = protobuf_c_message_get_packed_size (*(ProtobufCMessage * const *) member);
  247. return rv + uint32_size (subrv) + subrv;
  248. }
  249. }
  250. PROTOBUF_C_ASSERT_NOT_REACHED ();
  251. return 0;
  252. }
  253. static size_t
  254. optional_field_get_packed_size (const ProtobufCFieldDescriptor *field,
  255. const protobuf_c_boolean *has,
  256. const void *member)
  257. {
  258. if (field->type == PROTOBUF_C_TYPE_MESSAGE
  259. || field->type == PROTOBUF_C_TYPE_STRING)
  260. {
  261. const void *ptr = * (const void * const *) member;
  262. if (ptr == NULL
  263. || ptr == field->default_value)
  264. return 0;
  265. }
  266. else
  267. {
  268. if (!*has)
  269. return 0;
  270. }
  271. return required_field_get_packed_size (field, member);
  272. }
  273. static size_t
  274. repeated_field_get_packed_size (const ProtobufCFieldDescriptor *field,
  275. size_t count,
  276. const void *member)
  277. {
  278. size_t rv = get_tag_size (field->id) * count;
  279. unsigned i;
  280. void *array = * (void * const *) member;
  281. switch (field->type)
  282. {
  283. case PROTOBUF_C_TYPE_SINT32:
  284. for (i = 0; i < count; i++)
  285. rv += sint32_size (((int32_t*)array)[i]);
  286. break;
  287. case PROTOBUF_C_TYPE_INT32:
  288. for (i = 0; i < count; i++)
  289. rv += int32_size (((uint32_t*)array)[i]);
  290. break;
  291. case PROTOBUF_C_TYPE_UINT32:
  292. case PROTOBUF_C_TYPE_ENUM:
  293. for (i = 0; i < count; i++)
  294. rv += uint32_size (((uint32_t*)array)[i]);
  295. break;
  296. case PROTOBUF_C_TYPE_SINT64:
  297. for (i = 0; i < count; i++)
  298. rv += sint64_size (((int64_t*)array)[i]);
  299. break;
  300. case PROTOBUF_C_TYPE_INT64:
  301. case PROTOBUF_C_TYPE_UINT64:
  302. for (i = 0; i < count; i++)
  303. rv += uint64_size (((uint64_t*)array)[i]);
  304. break;
  305. case PROTOBUF_C_TYPE_SFIXED32:
  306. case PROTOBUF_C_TYPE_FIXED32:
  307. case PROTOBUF_C_TYPE_FLOAT:
  308. rv += 4 * count;
  309. break;
  310. case PROTOBUF_C_TYPE_SFIXED64:
  311. case PROTOBUF_C_TYPE_FIXED64:
  312. case PROTOBUF_C_TYPE_DOUBLE:
  313. rv += 8 * count;
  314. break;
  315. case PROTOBUF_C_TYPE_BOOL:
  316. rv += count;
  317. break;
  318. case PROTOBUF_C_TYPE_STRING:
  319. for (i = 0; i < count; i++)
  320. {
  321. size_t len = strlen (((char**) array)[i]);
  322. rv += uint32_size (len) + len;
  323. }
  324. break;
  325. case PROTOBUF_C_TYPE_BYTES:
  326. for (i = 0; i < count; i++)
  327. {
  328. size_t len = ((ProtobufCBinaryData*) array)[i].len;
  329. rv += uint32_size (len) + len;
  330. }
  331. break;
  332. case PROTOBUF_C_TYPE_MESSAGE:
  333. for (i = 0; i < count; i++)
  334. {
  335. size_t len = protobuf_c_message_get_packed_size (((ProtobufCMessage **) array)[i]);
  336. rv += uint32_size (len) + len;
  337. }
  338. break;
  339. //case PROTOBUF_C_TYPE_GROUP: // NOT SUPPORTED
  340. }
  341. return rv;
  342. }
  343. static inline size_t
  344. unknown_field_get_packed_size (const ProtobufCMessageUnknownField *field)
  345. {
  346. return get_tag_size (field->tag) + field->len;
  347. }
  348. size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message)
  349. {
  350. unsigned i;
  351. size_t rv = 0;
  352. ASSERT_IS_MESSAGE (message);
  353. for (i = 0; i < message->descriptor->n_fields; i++)
  354. {
  355. const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
  356. const void *member = ((const char *) message) + field->offset;
  357. const void *qmember = ((const char *) message) + field->quantifier_offset;
  358. if (field->label == PROTOBUF_C_LABEL_REQUIRED)
  359. rv += required_field_get_packed_size (field, member);
  360. else if (field->label == PROTOBUF_C_LABEL_OPTIONAL)
  361. rv += optional_field_get_packed_size (field, qmember, member);
  362. else
  363. rv += repeated_field_get_packed_size (field, * (const size_t *) qmember, member);
  364. }
  365. for (i = 0; i < message->n_unknown_fields; i++)
  366. rv += unknown_field_get_packed_size (&message->unknown_fields[i]);
  367. return rv;
  368. }
  369. /* === pack() === */
  370. static inline size_t
  371. uint32_pack (uint32_t value, uint8_t *out)
  372. {
  373. unsigned rv = 0;
  374. if (value >= 0x80)
  375. {
  376. out[rv++] = value | 0x80;
  377. value >>= 7;
  378. if (value >= 0x80)
  379. {
  380. out[rv++] = value | 0x80;
  381. value >>= 7;
  382. if (value >= 0x80)
  383. {
  384. out[rv++] = value | 0x80;
  385. value >>= 7;
  386. if (value >= 0x80)
  387. {
  388. out[rv++] = value | 0x80;
  389. value >>= 7;
  390. }
  391. }
  392. }
  393. }
  394. /* assert: value<128 */
  395. out[rv++] = value;
  396. return rv;
  397. }
  398. static inline size_t
  399. int32_pack (int32_t value, uint8_t *out)
  400. {
  401. if (value < 0)
  402. {
  403. out[0] = value | 0x80;
  404. out[1] = (value>>7) | 0x80;
  405. out[2] = (value>>14) | 0x80;
  406. out[3] = (value>>21) | 0x80;
  407. out[4] = (value>>28) | 0x80;
  408. out[5] = out[6] = out[7] = out[8] = 0xff;
  409. out[9] = 0x01;
  410. return 10;
  411. }
  412. else
  413. return uint32_pack (value, out);
  414. }
  415. static inline size_t sint32_pack (int32_t value, uint8_t *out)
  416. {
  417. return uint32_pack (zigzag32 (value), out);
  418. }
  419. static size_t
  420. uint64_pack (uint64_t value, uint8_t *out)
  421. {
  422. uint32_t hi = value>>32;
  423. uint32_t lo = value;
  424. unsigned rv;
  425. if (hi == 0)
  426. return uint32_pack ((uint32_t)lo, out);
  427. out[0] = (lo) | 0x80;
  428. out[1] = (lo>>7) | 0x80;
  429. out[2] = (lo>>14) | 0x80;
  430. out[3] = (lo>>21) | 0x80;
  431. if (hi < 8)
  432. {
  433. out[4] = (hi<<4) | (lo>>28);
  434. return 5;
  435. }
  436. else
  437. {
  438. out[4] = ((hi&7)<<4) | (lo>>28) | 0x80;
  439. hi >>= 3;
  440. }
  441. rv = 5;
  442. while (hi >= 128)
  443. {
  444. out[rv++] = hi | 0x80;
  445. hi >>= 7;
  446. }
  447. out[rv++] = hi;
  448. return rv;
  449. }
  450. static inline size_t sint64_pack (int64_t value, uint8_t *out)
  451. {
  452. return uint64_pack (zigzag64 (value), out);
  453. }
  454. static inline size_t fixed32_pack (uint32_t value, uint8_t *out)
  455. {
  456. #if __LITTLE_ENDIAN__
  457. memcpy (out, &value, 4);
  458. #else
  459. out[0] = value;
  460. out[1] = value>>8;
  461. out[2] = value>>16;
  462. out[3] = value>>24;
  463. #endif
  464. return 4;
  465. }
  466. static inline size_t fixed64_pack (uint64_t value, uint8_t *out)
  467. {
  468. #if __LITTLE_ENDIAN__
  469. memcpy (out, &value, 8);
  470. #else
  471. fixed32_pack (value, out);
  472. fixed32_pack (value>>32, out+4);
  473. #endif
  474. return 8;
  475. }
  476. static inline size_t boolean_pack (protobuf_c_boolean value, uint8_t *out)
  477. {
  478. *out = value ? 1 : 0;
  479. return 1;
  480. }
  481. static inline size_t string_pack (const char * str, uint8_t *out)
  482. {
  483. size_t len = strlen (str);
  484. size_t rv = uint32_pack (len, out);
  485. memcpy (out + rv, str, len);
  486. return rv + len;
  487. }
  488. static inline size_t binary_data_pack (const ProtobufCBinaryData *bd, uint8_t *out)
  489. {
  490. size_t len = bd->len;
  491. size_t rv = uint32_pack (len, out);
  492. memcpy (out + rv, bd->data, len);
  493. return rv + len;
  494. }
  495. static inline size_t
  496. prefixed_message_pack (const ProtobufCMessage *message, uint8_t *out)
  497. {
  498. size_t rv = protobuf_c_message_pack (message, out + 1);
  499. uint32_t rv_packed_size = uint32_size (rv);
  500. if (rv_packed_size != 1)
  501. memmove (out + rv_packed_size, out + 1, rv);
  502. return uint32_pack (rv, out) + rv;
  503. }
  504. /* wire-type will be added in required_field_pack() */
  505. static size_t tag_pack (uint32_t id, uint8_t *out)
  506. {
  507. if (id < (1<<(32-3)))
  508. return uint32_pack (id<<3, out);
  509. else
  510. return uint64_pack (((uint64_t)id) << 3, out);
  511. }
  512. static size_t
  513. required_field_pack (const ProtobufCFieldDescriptor *field,
  514. const void *member,
  515. uint8_t *out)
  516. {
  517. size_t rv = tag_pack (field->id, out);
  518. switch (field->type)
  519. {
  520. case PROTOBUF_C_TYPE_SINT32:
  521. out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  522. return rv + sint32_pack (*(const int32_t *) member, out + rv);
  523. case PROTOBUF_C_TYPE_INT32:
  524. out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  525. return rv + int32_pack (*(const uint32_t *) member, out + rv);
  526. case PROTOBUF_C_TYPE_UINT32:
  527. case PROTOBUF_C_TYPE_ENUM:
  528. out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  529. return rv + uint32_pack (*(const uint32_t *) member, out + rv);
  530. case PROTOBUF_C_TYPE_SINT64:
  531. out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  532. return rv + sint64_pack (*(const int64_t *) member, out + rv);
  533. case PROTOBUF_C_TYPE_INT64:
  534. case PROTOBUF_C_TYPE_UINT64:
  535. out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  536. return rv + uint64_pack (*(const uint64_t *) member, out + rv);
  537. case PROTOBUF_C_TYPE_SFIXED32:
  538. case PROTOBUF_C_TYPE_FIXED32:
  539. case PROTOBUF_C_TYPE_FLOAT:
  540. out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
  541. return rv + fixed32_pack (*(const uint64_t *) member, out + rv);
  542. case PROTOBUF_C_TYPE_SFIXED64:
  543. case PROTOBUF_C_TYPE_FIXED64:
  544. case PROTOBUF_C_TYPE_DOUBLE:
  545. out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
  546. return rv + fixed64_pack (*(const uint64_t *) member, out + rv);
  547. case PROTOBUF_C_TYPE_BOOL:
  548. out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  549. return rv + boolean_pack (*(const protobuf_c_boolean *) member, out + rv);
  550. case PROTOBUF_C_TYPE_STRING:
  551. {
  552. out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
  553. return rv + string_pack (*(char * const *) member, out + rv);
  554. }
  555. case PROTOBUF_C_TYPE_BYTES:
  556. {
  557. const ProtobufCBinaryData * bd = ((const ProtobufCBinaryData*) member);
  558. out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
  559. return rv + binary_data_pack (bd, out + rv);
  560. }
  561. //case PROTOBUF_C_TYPE_GROUP: // NOT SUPPORTED
  562. case PROTOBUF_C_TYPE_MESSAGE:
  563. {
  564. out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
  565. return rv + prefixed_message_pack (*(ProtobufCMessage * const *) member,
  566. out + rv);
  567. }
  568. }
  569. PROTOBUF_C_ASSERT_NOT_REACHED ();
  570. return 0;
  571. }
  572. static size_t
  573. optional_field_pack (const ProtobufCFieldDescriptor *field,
  574. const protobuf_c_boolean *has,
  575. const void *member,
  576. uint8_t *out)
  577. {
  578. if (field->type == PROTOBUF_C_TYPE_MESSAGE
  579. || field->type == PROTOBUF_C_TYPE_STRING)
  580. {
  581. const void *ptr = * (const void * const *) member;
  582. if (ptr == NULL
  583. || ptr == field->default_value)
  584. return 0;
  585. }
  586. else
  587. {
  588. if (!*has)
  589. return 0;
  590. }
  591. return required_field_pack (field, member, out);
  592. }
  593. /* TODO: implement as a table lookup */
  594. static inline size_t sizeof_elt_in_repeated_array (ProtobufCType type)
  595. {
  596. switch (type)
  597. {
  598. case PROTOBUF_C_TYPE_SINT32:
  599. case PROTOBUF_C_TYPE_INT32:
  600. case PROTOBUF_C_TYPE_UINT32:
  601. case PROTOBUF_C_TYPE_SFIXED32:
  602. case PROTOBUF_C_TYPE_FIXED32:
  603. case PROTOBUF_C_TYPE_FLOAT:
  604. case PROTOBUF_C_TYPE_ENUM:
  605. return 4;
  606. case PROTOBUF_C_TYPE_SINT64:
  607. case PROTOBUF_C_TYPE_INT64:
  608. case PROTOBUF_C_TYPE_UINT64:
  609. case PROTOBUF_C_TYPE_SFIXED64:
  610. case PROTOBUF_C_TYPE_FIXED64:
  611. case PROTOBUF_C_TYPE_DOUBLE:
  612. return 8;
  613. case PROTOBUF_C_TYPE_BOOL:
  614. return sizeof (protobuf_c_boolean);
  615. case PROTOBUF_C_TYPE_STRING:
  616. case PROTOBUF_C_TYPE_MESSAGE:
  617. return sizeof (void *);
  618. case PROTOBUF_C_TYPE_BYTES:
  619. return sizeof (ProtobufCBinaryData);
  620. }
  621. PROTOBUF_C_ASSERT_NOT_REACHED ();
  622. return 0;
  623. }
  624. static size_t
  625. repeated_field_pack (const ProtobufCFieldDescriptor *field,
  626. size_t count,
  627. const void *member,
  628. uint8_t *out)
  629. {
  630. char *array = * (char * const *) member;
  631. size_t siz;
  632. unsigned i;
  633. size_t rv = 0;
  634. /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
  635. siz = sizeof_elt_in_repeated_array (field->type);
  636. for (i = 0; i < count; i++)
  637. {
  638. rv += required_field_pack (field, array, out + rv);
  639. array += siz;
  640. }
  641. return rv;
  642. }
  643. static size_t
  644. unknown_field_pack (const ProtobufCMessageUnknownField *field, uint8_t *out)
  645. {
  646. size_t rv = tag_pack (field->tag, out);
  647. out[0] |= field->wire_type;
  648. memcpy (out + rv, field->data, field->len);
  649. return rv + field->len;
  650. }
  651. size_t protobuf_c_message_pack (const ProtobufCMessage *message,
  652. uint8_t *out)
  653. {
  654. unsigned i;
  655. size_t rv = 0;
  656. ASSERT_IS_MESSAGE (message);
  657. for (i = 0; i < message->descriptor->n_fields; i++)
  658. {
  659. const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
  660. const void *member = ((const char *) message) + field->offset;
  661. const void *qmember = ((const char *) message) + field->quantifier_offset;
  662. if (field->label == PROTOBUF_C_LABEL_REQUIRED)
  663. rv += required_field_pack (field, member, out + rv);
  664. else if (field->label == PROTOBUF_C_LABEL_OPTIONAL)
  665. rv += optional_field_pack (field, qmember, member, out + rv);
  666. else
  667. rv += repeated_field_pack (field, * (const size_t *) qmember, member, out + rv);
  668. }
  669. for (i = 0; i < message->n_unknown_fields; i++)
  670. rv += unknown_field_pack (&message->unknown_fields[i], out + rv);
  671. return rv;
  672. }
  673. /* === pack_to_buffer() === */
  674. static size_t
  675. required_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
  676. const void *member,
  677. ProtobufCBuffer *buffer)
  678. {
  679. size_t rv;
  680. uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
  681. rv = tag_pack (field->id, scratch);
  682. switch (field->type)
  683. {
  684. case PROTOBUF_C_TYPE_SINT32:
  685. scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  686. rv += sint32_pack (*(const int32_t *) member, scratch + rv);
  687. buffer->append (buffer, rv, scratch);
  688. break;
  689. case PROTOBUF_C_TYPE_INT32:
  690. scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  691. rv += int32_pack (*(const uint32_t *) member, scratch + rv);
  692. buffer->append (buffer, rv, scratch);
  693. break;
  694. case PROTOBUF_C_TYPE_UINT32:
  695. case PROTOBUF_C_TYPE_ENUM:
  696. scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  697. rv += uint32_pack (*(const uint32_t *) member, scratch + rv);
  698. buffer->append (buffer, rv, scratch);
  699. break;
  700. case PROTOBUF_C_TYPE_SINT64:
  701. scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  702. rv += sint64_pack (*(const int64_t *) member, scratch + rv);
  703. buffer->append (buffer, rv, scratch);
  704. break;
  705. case PROTOBUF_C_TYPE_INT64:
  706. case PROTOBUF_C_TYPE_UINT64:
  707. scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  708. rv += uint64_pack (*(const uint64_t *) member, scratch + rv);
  709. buffer->append (buffer, rv, scratch);
  710. break;
  711. case PROTOBUF_C_TYPE_SFIXED32:
  712. case PROTOBUF_C_TYPE_FIXED32:
  713. case PROTOBUF_C_TYPE_FLOAT:
  714. scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
  715. rv += fixed32_pack (*(const uint64_t *) member, scratch + rv);
  716. buffer->append (buffer, rv, scratch);
  717. break;
  718. case PROTOBUF_C_TYPE_SFIXED64:
  719. case PROTOBUF_C_TYPE_FIXED64:
  720. case PROTOBUF_C_TYPE_DOUBLE:
  721. scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
  722. rv += fixed64_pack (*(const uint64_t *) member, scratch + rv);
  723. buffer->append (buffer, rv, scratch);
  724. break;
  725. case PROTOBUF_C_TYPE_BOOL:
  726. scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
  727. rv += boolean_pack (*(const protobuf_c_boolean *) member, scratch + rv);
  728. buffer->append (buffer, rv, scratch);
  729. break;
  730. case PROTOBUF_C_TYPE_STRING:
  731. {
  732. size_t sublen = strlen (*(char * const *) member);
  733. scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
  734. rv += uint32_pack (sublen, scratch + rv);
  735. buffer->append (buffer, rv, scratch);
  736. buffer->append (buffer, sublen, *(uint8_t * const *)member);
  737. rv += sublen;
  738. break;
  739. }
  740. case PROTOBUF_C_TYPE_BYTES:
  741. {
  742. const ProtobufCBinaryData * bd = ((const ProtobufCBinaryData*) member);
  743. size_t sublen = bd->len;
  744. scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
  745. rv += uint32_pack (sublen, scratch + rv);
  746. buffer->append (buffer, rv, scratch);
  747. buffer->append (buffer, sublen, bd->data);
  748. rv += sublen;
  749. break;
  750. }
  751. //PROTOBUF_C_TYPE_GROUP, // NOT SUPPORTED
  752. case PROTOBUF_C_TYPE_MESSAGE:
  753. {
  754. uint8_t simple_buffer_scratch[256];
  755. size_t sublen;
  756. ProtobufCBufferSimple simple_buffer
  757. = PROTOBUF_C_BUFFER_SIMPLE_INIT (simple_buffer_scratch);
  758. scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
  759. sublen = protobuf_c_message_pack_to_buffer (*(ProtobufCMessage * const *) member,
  760. &simple_buffer.base);
  761. rv += uint32_pack (sublen, scratch + rv);
  762. buffer->append (buffer, rv, scratch);
  763. buffer->append (buffer, sublen, simple_buffer.data);
  764. rv += sublen;
  765. PROTOBUF_C_BUFFER_SIMPLE_CLEAR (&simple_buffer);
  766. break;
  767. }
  768. default:
  769. PROTOBUF_C_ASSERT_NOT_REACHED ();
  770. }
  771. return rv;
  772. }
  773. static size_t
  774. optional_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
  775. const protobuf_c_boolean *has,
  776. const void *member,
  777. ProtobufCBuffer *buffer)
  778. {
  779. if (field->type == PROTOBUF_C_TYPE_MESSAGE
  780. || field->type == PROTOBUF_C_TYPE_STRING)
  781. {
  782. const void *ptr = * (const void * const *) member;
  783. if (ptr == NULL
  784. || ptr == field->default_value)
  785. return 0;
  786. }
  787. else
  788. {
  789. if (!*has)
  790. return 0;
  791. }
  792. return required_field_pack_to_buffer (field, member, buffer);
  793. }
  794. static size_t
  795. repeated_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
  796. unsigned count,
  797. const void *member,
  798. ProtobufCBuffer *buffer)
  799. {
  800. char *array = * (char * const *) member;
  801. size_t siz;
  802. unsigned i;
  803. /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
  804. unsigned rv = 0;
  805. siz = sizeof_elt_in_repeated_array (field->type);
  806. for (i = 0; i < count; i++)
  807. {
  808. rv += required_field_pack_to_buffer (field, array, buffer);
  809. array += siz;
  810. }
  811. return rv;
  812. }
  813. static size_t
  814. unknown_field_pack_to_buffer (const ProtobufCMessageUnknownField *field,
  815. ProtobufCBuffer *buffer)
  816. {
  817. uint8_t header[MAX_UINT64_ENCODED_SIZE];
  818. size_t rv = tag_pack (field->tag, header);
  819. header[0] |= field->wire_type;
  820. buffer->append (buffer, rv, header);
  821. buffer->append (buffer, field->len, field->data);
  822. return rv + field->len;
  823. }
  824. size_t
  825. protobuf_c_message_pack_to_buffer (const ProtobufCMessage *message,
  826. ProtobufCBuffer *buffer)
  827. {
  828. unsigned i;
  829. size_t rv = 0;
  830. ASSERT_IS_MESSAGE (message);
  831. for (i = 0; i < message->descriptor->n_fields; i++)
  832. {
  833. const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
  834. const void *member = ((const char *) message) + field->offset;
  835. const void *qmember = ((const char *) message) + field->quantifier_offset;
  836. if (field->label == PROTOBUF_C_LABEL_REQUIRED)
  837. rv += required_field_pack_to_buffer (field, member, buffer);
  838. else if (field->label == PROTOBUF_C_LABEL_OPTIONAL)
  839. rv += optional_field_pack_to_buffer (field, qmember, member, buffer);
  840. else
  841. rv += repeated_field_pack_to_buffer (field, * (const size_t *) qmember, member, buffer);
  842. }
  843. for (i = 0; i < message->n_unknown_fields; i++)
  844. rv += unknown_field_pack_to_buffer (&message->unknown_fields[i], buffer);
  845. return rv;
  846. }
  847. /* === unpacking === */
  848. #if PRINT_UNPACK_ERRORS
  849. # define UNPACK_ERROR(args) do { printf args;printf("\n"); }while(0)
  850. #else
  851. # define UNPACK_ERROR(args) do { } while (0)
  852. #endif
  853. static inline int
  854. int_range_lookup (unsigned n_ranges,
  855. const ProtobufCIntRange *ranges,
  856. int value)
  857. {
  858. unsigned start, n;
  859. if (n_ranges == 0)
  860. return -1;
  861. start = 0;
  862. n = n_ranges;
  863. while (n > 1)
  864. {
  865. unsigned mid = start + n / 2;
  866. if (value < ranges[mid].start_value)
  867. {
  868. n = mid - start;
  869. }
  870. else if (value >= ranges[mid].start_value + (int)(ranges[mid+1].orig_index-ranges[mid].orig_index))
  871. {
  872. unsigned new_start = mid + 1;
  873. n = start + n - new_start;
  874. start = new_start;
  875. }
  876. else
  877. return (value - ranges[mid].start_value) + ranges[mid].orig_index;
  878. }
  879. if (n > 0)
  880. {
  881. unsigned start_orig_index = ranges[start].orig_index;
  882. unsigned range_size = ranges[start+1].orig_index - start_orig_index;
  883. if (ranges[start].start_value <= value
  884. && value < (int)(ranges[start].start_value + range_size))
  885. return (value - ranges[start].start_value) + start_orig_index;
  886. }
  887. return -1;
  888. }
  889. static size_t
  890. parse_tag_and_wiretype (size_t len,
  891. const uint8_t *data,
  892. uint32_t *tag_out,
  893. ProtobufCWireType *wiretype_out)
  894. {
  895. unsigned max_rv = len > 5 ? 5 : len;
  896. uint32_t tag = (data[0]&0x7f) >> 3;
  897. unsigned shift = 4;
  898. unsigned rv;
  899. *wiretype_out = data[0] & 7;
  900. if ((data[0] & 0x80) == 0)
  901. {
  902. *tag_out = tag;
  903. return 1;
  904. }
  905. for (rv = 1; rv < max_rv; rv++)
  906. if (data[rv] & 0x80)
  907. {
  908. tag |= (data[rv] & 0x7f) << shift;
  909. shift += 7;
  910. }
  911. else
  912. {
  913. tag |= data[rv] << shift;
  914. *tag_out = tag;
  915. return rv + 1;
  916. }
  917. return 0; /* error: bad header */
  918. }
  919. typedef struct _ScannedMember ScannedMember;
  920. struct _ScannedMember
  921. {
  922. uint32_t tag;
  923. const ProtobufCFieldDescriptor *field;
  924. uint8_t wire_type;
  925. uint8_t length_prefix_len;
  926. size_t len;
  927. const uint8_t *data;
  928. };
  929. #define MESSAGE_GET_UNKNOWNS(message) \
  930. STRUCT_MEMBER_PTR (ProtobufCMessageUnknownFieldArray, \
  931. (message), (message)->descriptor->unknown_field_array_offset)
  932. static inline uint32_t
  933. scan_length_prefixed_data (size_t len, const uint8_t *data, size_t *prefix_len_out)
  934. {
  935. unsigned hdr_max = len < 5 ? len : 5;
  936. unsigned hdr_len;
  937. uint32_t val = 0;
  938. unsigned i;
  939. unsigned shift = 0;
  940. for (i = 0; i < hdr_max; i++)
  941. {
  942. val |= (data[i] & 0x7f) << shift;
  943. shift += 7;
  944. if ((data[i] & 0x80) == 0)
  945. break;
  946. }
  947. if (i == hdr_max)
  948. {
  949. UNPACK_ERROR (("error parsing length for length-prefixed data"));
  950. return 0;
  951. }
  952. hdr_len = i + 1;
  953. *prefix_len_out = hdr_len;
  954. if (hdr_len + val > len)
  955. {
  956. UNPACK_ERROR (("data too short after length-prefix of %u",
  957. val));
  958. return 0;
  959. }
  960. return hdr_len + val;
  961. }
  962. static inline uint32_t
  963. parse_uint32 (unsigned len, const uint8_t *data)
  964. {
  965. unsigned rv = data[0] & 0x7f;
  966. if (len > 1)
  967. {
  968. rv |= ((data[1] & 0x7f) << 7);
  969. if (len > 2)
  970. {
  971. rv |= ((data[2] & 0x7f) << 14);
  972. if (len > 3)
  973. {
  974. rv |= ((data[3] & 0x7f) << 21);
  975. if (len > 4)
  976. rv |= (data[4] << 28);
  977. }
  978. }
  979. }
  980. return rv;
  981. }
  982. static inline uint32_t
  983. parse_int32 (unsigned len, const uint8_t *data)
  984. {
  985. return parse_uint32 (len, data);
  986. }
  987. static inline int32_t
  988. unzigzag32 (uint32_t v)
  989. {
  990. if (v&1)
  991. return -(v>>1) - 1;
  992. else
  993. return v>>1;
  994. }
  995. static inline uint32_t
  996. parse_fixed_uint32 (const uint8_t *data)
  997. {
  998. #if __LITTLE_ENDIAN__
  999. uint32_t t;
  1000. memcpy (&t, data, 4);
  1001. return t;
  1002. #else
  1003. return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
  1004. #endif
  1005. }
  1006. static uint64_t
  1007. parse_uint64 (unsigned len, const uint8_t *data)
  1008. {
  1009. unsigned shift, i;
  1010. if (len < 5)
  1011. return parse_uint32 (len, data);
  1012. uint64_t rv = ((data[0] & 0x7f))
  1013. | ((data[1] & 0x7f)<<7)
  1014. | ((data[2] & 0x7f)<<14)
  1015. | ((data[3] & 0x7f)<<21);
  1016. shift = 28;
  1017. for (i = 4; i < len; i++)
  1018. {
  1019. rv |= (((uint64_t)(data[i]&0x7f)) << shift);
  1020. shift += 7;
  1021. }
  1022. return rv;
  1023. }
  1024. static inline int64_t
  1025. unzigzag64 (uint64_t v)
  1026. {
  1027. if (v&1)
  1028. return -(v>>1) - 1;
  1029. else
  1030. return v>>1;
  1031. }
  1032. static inline uint64_t
  1033. parse_fixed_uint64 (const uint8_t *data)
  1034. {
  1035. #if __LITTLE_ENDIAN__
  1036. uint64_t t;
  1037. memcpy (&t, data, 8);
  1038. return t;
  1039. #else
  1040. return (uint64_t)parse_fixed_uint32 (data)
  1041. | (((uint64_t)parse_fixed_uint32(data+4)) << 32);
  1042. #endif
  1043. }
  1044. static protobuf_c_boolean
  1045. parse_boolean (unsigned len, const uint8_t *data)
  1046. {
  1047. unsigned i;
  1048. for (i = 0; i < len; i++)
  1049. if (data[i] & 0x7f)
  1050. return 1;
  1051. return 0;
  1052. }
  1053. static protobuf_c_boolean
  1054. parse_required_member (ScannedMember *scanned_member,
  1055. void *member,
  1056. ProtobufCAllocator *allocator,
  1057. protobuf_c_boolean maybe_clear)
  1058. {
  1059. unsigned len = scanned_member->len;
  1060. const uint8_t *data = scanned_member->data;
  1061. ProtobufCWireType wire_type = scanned_member->wire_type;
  1062. switch (scanned_member->field->type)
  1063. {
  1064. case PROTOBUF_C_TYPE_INT32:
  1065. if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
  1066. return 0;
  1067. *(uint32_t*)member = parse_int32 (len, data);
  1068. return 1;
  1069. case PROTOBUF_C_TYPE_UINT32:
  1070. if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
  1071. return 0;
  1072. *(uint32_t*)member = parse_uint32 (len, data);
  1073. return 1;
  1074. case PROTOBUF_C_TYPE_SINT32:
  1075. if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
  1076. return 0;
  1077. *(int32_t*)member = unzigzag32 (parse_uint32 (len, data));
  1078. return 1;
  1079. case PROTOBUF_C_TYPE_SFIXED32:
  1080. case PROTOBUF_C_TYPE_FIXED32:
  1081. case PROTOBUF_C_TYPE_FLOAT:
  1082. if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT)
  1083. return 0;
  1084. *(uint32_t*)member = parse_fixed_uint32 (data);
  1085. return 1;
  1086. case PROTOBUF_C_TYPE_INT64:
  1087. case PROTOBUF_C_TYPE_UINT64:
  1088. if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
  1089. return 0;
  1090. *(uint64_t*)member = parse_uint64 (len, data);
  1091. return 1;
  1092. case PROTOBUF_C_TYPE_SINT64:
  1093. if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
  1094. return 0;
  1095. *(int64_t*)member = unzigzag64 (parse_uint64 (len, data));
  1096. return 1;
  1097. case PROTOBUF_C_TYPE_SFIXED64:
  1098. case PROTOBUF_C_TYPE_FIXED64:
  1099. case PROTOBUF_C_TYPE_DOUBLE:
  1100. if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT)
  1101. return 0;
  1102. *(uint64_t*)member = parse_fixed_uint64 (data);
  1103. return 1;
  1104. case PROTOBUF_C_TYPE_BOOL:
  1105. *(protobuf_c_boolean*)member = parse_boolean (len, data);
  1106. return 1;
  1107. case PROTOBUF_C_TYPE_ENUM:
  1108. if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
  1109. return 0;
  1110. *(uint32_t*)member = parse_uint32 (len, data);
  1111. return 1;
  1112. case PROTOBUF_C_TYPE_STRING:
  1113. if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
  1114. return 0;
  1115. {
  1116. char **pstr = member;
  1117. unsigned pref_len = scanned_member->length_prefix_len;
  1118. if (maybe_clear && *pstr != NULL)
  1119. {
  1120. const char *def = scanned_member->field->default_value;
  1121. if (*pstr != NULL && *pstr != def)
  1122. FREE (allocator, *pstr);
  1123. }
  1124. *pstr = ALLOC (allocator, len - pref_len + 1);
  1125. memcpy (*pstr, data + pref_len, len - pref_len);
  1126. (*pstr)[len-pref_len] = 0;
  1127. return 1;
  1128. }
  1129. case PROTOBUF_C_TYPE_BYTES:
  1130. if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
  1131. return 0;
  1132. {
  1133. ProtobufCBinaryData *bd = member;
  1134. const ProtobufCBinaryData *def_bd;
  1135. unsigned pref_len = scanned_member->length_prefix_len;
  1136. def_bd = scanned_member->field->default_value;
  1137. if (maybe_clear && bd->data != NULL && bd->data != def_bd->data)
  1138. FREE (allocator, bd->data);
  1139. bd->data = ALLOC (allocator, len - pref_len);
  1140. memcpy (bd->data, data + pref_len, len - pref_len);
  1141. bd->len = len - pref_len;
  1142. return 1;
  1143. }
  1144. //case PROTOBUF_C_TYPE_GROUP, // NOT SUPPORTED
  1145. case PROTOBUF_C_TYPE_MESSAGE:
  1146. if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
  1147. return 0;
  1148. {
  1149. ProtobufCMessage **pmessage = member;
  1150. ProtobufCMessage *subm;
  1151. const ProtobufCMessage *def_mess;
  1152. unsigned pref_len = scanned_member->length_prefix_len;
  1153. def_mess = scanned_member->field->default_value;
  1154. if (maybe_clear && *pmessage != NULL && *pmessage != def_mess)
  1155. protobuf_c_message_free_unpacked (*pmessage, allocator);
  1156. subm = protobuf_c_message_unpack (scanned_member->field->descriptor,
  1157. allocator,
  1158. len - pref_len, data + pref_len);
  1159. *pmessage = subm;
  1160. if (subm == NULL)
  1161. return 0;
  1162. return 1;
  1163. }
  1164. }
  1165. return 0;
  1166. }
  1167. static protobuf_c_boolean
  1168. parse_optional_member (ScannedMember *scanned_member,
  1169. void *member,
  1170. ProtobufCMessage *message,
  1171. ProtobufCAllocator *allocator)
  1172. {
  1173. if (!parse_required_member (scanned_member, member, allocator, TRUE))
  1174. return 0;
  1175. if (scanned_member->field->quantifier_offset != 0)
  1176. STRUCT_MEMBER (protobuf_c_boolean,
  1177. message,
  1178. scanned_member->field->quantifier_offset) = 1;
  1179. return 1;
  1180. }
  1181. static protobuf_c_boolean
  1182. parse_repeated_member (ScannedMember *scanned_member,
  1183. void *member,
  1184. ProtobufCMessage *message,
  1185. ProtobufCAllocator *allocator)
  1186. {
  1187. const ProtobufCFieldDescriptor *field = scanned_member->field;
  1188. size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
  1189. size_t siz = sizeof_elt_in_repeated_array (field->type);
  1190. char *array = *(char**)member;
  1191. if (!parse_required_member (scanned_member,
  1192. array + siz * (*p_n),
  1193. allocator,
  1194. FALSE))
  1195. return 0;
  1196. *p_n += 1;
  1197. return 1;
  1198. }
  1199. static protobuf_c_boolean
  1200. parse_member (ScannedMember *scanned_member,
  1201. ProtobufCMessage *message,
  1202. ProtobufCAllocator *allocator)
  1203. {
  1204. const ProtobufCFieldDescriptor *field = scanned_member->field;
  1205. void *member;
  1206. if (field == NULL)
  1207. {
  1208. ProtobufCMessageUnknownField *ufield = message->unknown_fields + (message->n_unknown_fields++);
  1209. ufield->tag = scanned_member->tag;
  1210. ufield->wire_type = scanned_member->wire_type;
  1211. ufield->len = scanned_member->len;
  1212. ufield->data = UNALIGNED_ALLOC (allocator, scanned_member->len);
  1213. memcpy (ufield->data, scanned_member->data, ufield->len);
  1214. return 1;
  1215. }
  1216. member = (char*)message + field->offset;
  1217. switch (field->label)
  1218. {
  1219. case PROTOBUF_C_LABEL_REQUIRED:
  1220. return parse_required_member (scanned_member, member, allocator, TRUE);
  1221. case PROTOBUF_C_LABEL_OPTIONAL:
  1222. return parse_optional_member (scanned_member, member, message, allocator);
  1223. case PROTOBUF_C_LABEL_REPEATED:
  1224. return parse_repeated_member (scanned_member, member, message, allocator);
  1225. }
  1226. PROTOBUF_C_ASSERT_NOT_REACHED ();
  1227. return 0;
  1228. }
  1229. static inline void
  1230. setup_default_values (ProtobufCMessage *message)
  1231. {
  1232. const ProtobufCMessageDescriptor *desc = message->descriptor;
  1233. unsigned i;
  1234. for (i = 0; i < desc->n_fields; i++)
  1235. if (desc->fields[i].default_value != NULL
  1236. && desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED)
  1237. {
  1238. void *field = STRUCT_MEMBER_P (message, desc->fields[i].offset);
  1239. const void *dv = desc->fields[i].default_value;
  1240. switch (desc->fields[i].type)
  1241. {
  1242. case PROTOBUF_C_TYPE_INT32:
  1243. case PROTOBUF_C_TYPE_SINT32:
  1244. case PROTOBUF_C_TYPE_SFIXED32:
  1245. case PROTOBUF_C_TYPE_UINT32:
  1246. case PROTOBUF_C_TYPE_FIXED32:
  1247. case PROTOBUF_C_TYPE_FLOAT:
  1248. case PROTOBUF_C_TYPE_ENUM:
  1249. memcpy (field, dv, 4);
  1250. break;
  1251. case PROTOBUF_C_TYPE_INT64:
  1252. case PROTOBUF_C_TYPE_SINT64:
  1253. case PROTOBUF_C_TYPE_SFIXED64:
  1254. case PROTOBUF_C_TYPE_UINT64:
  1255. case PROTOBUF_C_TYPE_FIXED64:
  1256. case PROTOBUF_C_TYPE_DOUBLE:
  1257. memcpy (field, dv, 8);
  1258. break;
  1259. case PROTOBUF_C_TYPE_BOOL:
  1260. memcpy (field, dv, sizeof (protobuf_c_boolean));
  1261. break;
  1262. case PROTOBUF_C_TYPE_BYTES:
  1263. memcpy (field, dv, sizeof (ProtobufCBinaryData));
  1264. break;
  1265. case PROTOBUF_C_TYPE_STRING:
  1266. case PROTOBUF_C_TYPE_MESSAGE:
  1267. /* the next line essentially implements a cast from const,
  1268. which is totally unavoidable. */
  1269. *(const void**)field = dv;
  1270. break;
  1271. }
  1272. }
  1273. }
  1274. ProtobufCMessage *
  1275. protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
  1276. ProtobufCAllocator *allocator,
  1277. size_t len,
  1278. const uint8_t *data)
  1279. {
  1280. ProtobufCMessage *rv;
  1281. size_t rem = len;
  1282. const uint8_t *at = data;
  1283. const ProtobufCFieldDescriptor *last_field = desc->fields + 0;
  1284. ScannedMember first_member_slab[16];
  1285. ScannedMember *scanned_member_slabs[30]; /* size of member i is (1<<(i+4)) */
  1286. unsigned which_slab = 0;
  1287. unsigned in_slab_index = 0;
  1288. size_t n_unknown = 0;
  1289. unsigned f;
  1290. unsigned i_slab;
  1291. ASSERT_IS_MESSAGE_DESCRIPTOR (desc);
  1292. if (allocator == NULL)
  1293. allocator = &protobuf_c_default_allocator;
  1294. rv = ALLOC (allocator, desc->sizeof_message);
  1295. scanned_member_slabs[0] = first_member_slab;
  1296. memset (rv, 0, desc->sizeof_message);
  1297. rv->descriptor = desc;
  1298. setup_default_values (rv);
  1299. while (rem > 0)
  1300. {
  1301. uint32_t tag = 0; // landonf - 12/17/2008 (uninitialized compiler warning)
  1302. ProtobufCWireType wire_type;
  1303. size_t used = parse_tag_and_wiretype (rem, at, &tag, &wire_type);
  1304. const ProtobufCFieldDescriptor *field;
  1305. ScannedMember tmp;
  1306. memset(&tmp, 0, sizeof(tmp)); // landonf - 12/17/2008 (uninitialized compiler warning)
  1307. if (used == 0)
  1308. {
  1309. UNPACK_ERROR (("error parsing tag/wiretype at offset %u",
  1310. (unsigned)(at-data)));
  1311. goto error_cleanup;
  1312. }
  1313. /* XXX: consider optimizing for field[1].id == tag, if field[1] exists! */
  1314. if (last_field->id != tag)
  1315. {
  1316. /* lookup field */
  1317. int field_index = int_range_lookup (desc->n_field_ranges,
  1318. desc->field_ranges,
  1319. tag);
  1320. if (field_index < 0)
  1321. {
  1322. field = NULL;
  1323. n_unknown++;
  1324. }
  1325. else
  1326. {
  1327. field = desc->fields + field_index;
  1328. last_field = field;
  1329. }
  1330. }
  1331. else
  1332. field = last_field;
  1333. at += used;
  1334. rem -= used;
  1335. tmp.tag = tag;
  1336. tmp.wire_type = wire_type;
  1337. tmp.field = field;
  1338. tmp.data = at;
  1339. switch (wire_type)
  1340. {
  1341. case PROTOBUF_C_WIRE_TYPE_VARINT:
  1342. {
  1343. unsigned max_len = rem < 10 ? rem : 10;
  1344. unsigned i;
  1345. for (i = 0; i < max_len; i++)
  1346. if ((at[i] & 0x80) == 0)
  1347. break;
  1348. if (i == max_len)
  1349. {
  1350. UNPACK_ERROR (("unterminated varint at offset %u",
  1351. (unsigned)(at-data)));
  1352. goto error_cleanup;
  1353. }
  1354. tmp.len = i + 1;
  1355. }
  1356. break;
  1357. case PROTOBUF_C_WIRE_TYPE_64BIT:
  1358. if (rem < 8)
  1359. {
  1360. UNPACK_ERROR (("too short after 64bit wiretype at offset %u",
  1361. (unsigned)(at-data)));
  1362. goto error_cleanup;
  1363. }
  1364. tmp.len = 8;
  1365. break;
  1366. case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED:
  1367. {
  1368. size_t pref_len = 0; // landonf - 12/17/2008 (uninitialized compiler warning)
  1369. tmp.len = scan_length_prefixed_data (rem, at, &pref_len);
  1370. if (tmp.len == 0)
  1371. {
  1372. /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */
  1373. goto error_cleanup;
  1374. }
  1375. tmp.length_prefix_len = pref_len;
  1376. break;
  1377. }
  1378. case PROTOBUF_C_WIRE_TYPE_START_GROUP:
  1379. case PROTOBUF_C_WIRE_TYPE_END_GROUP:
  1380. // landonf - 12/18/2008 (Do not assert unreachable if a group tag is found, as this
  1381. // crashed the decoder on valid input)
  1382. UNPACK_ERROR (("unsupported group tag at offset %u",
  1383. (unsigned)(at-data)));
  1384. goto error_cleanup;
  1385. case PROTOBUF_C_WIRE_TYPE_32BIT:
  1386. if (rem < 4)
  1387. {
  1388. UNPACK_ERROR (("too short after 32bit wiretype at offset %u",
  1389. (unsigned)(at-data)));
  1390. goto error_cleanup;
  1391. }
  1392. tmp.len = 4;
  1393. break;
  1394. }
  1395. if (in_slab_index == (1U<<(which_slab+4)))
  1396. {
  1397. size_t size;
  1398. in_slab_index = 0;
  1399. which_slab++;
  1400. size = sizeof(ScannedMember) << (which_slab+4);
  1401. /* TODO: consider using alloca() ! */
  1402. if (allocator->tmp_alloc != NULL)
  1403. scanned_member_slabs[which_slab] = TMPALLOC(allocator, size);
  1404. else
  1405. scanned_member_slabs[which_slab] = ALLOC(allocator, size);
  1406. }
  1407. scanned_member_slabs[which_slab][in_slab_index++] = tmp;
  1408. if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED)
  1409. {
  1410. size_t *n_ptr = (size_t*)((char*)rv + field->quantifier_offset);
  1411. (*n_ptr) += 1;
  1412. }
  1413. at += tmp.len;
  1414. rem -= tmp.len;
  1415. }
  1416. /* allocate space for repeated fields */
  1417. for (f = 0; f < desc->n_fields; f++)
  1418. if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED)
  1419. {
  1420. const ProtobufCFieldDescriptor *field = desc->fields + f;
  1421. size_t siz = sizeof_elt_in_repeated_array (field->type);
  1422. size_t *n_ptr = STRUCT_MEMBER_PTR (size_t, rv, field->quantifier_offset);
  1423. if (*n_ptr != 0)
  1424. {
  1425. STRUCT_MEMBER (void *, rv, field->offset) = ALLOC (allocator, siz * (*n_ptr));
  1426. *n_ptr = 0;
  1427. }
  1428. }
  1429. /* allocate space for unknown fields */
  1430. if (n_unknown)
  1431. {
  1432. rv->unknown_fields = ALLOC (allocator, n_unknown * sizeof (ProtobufCMessageUnknownField));
  1433. }
  1434. /* do real parsing */
  1435. for (i_slab = 0; i_slab <= which_slab; i_slab++)
  1436. {
  1437. unsigned max = (i_slab == which_slab) ? in_slab_index : (1U<<(i_slab+4));
  1438. ScannedMember *slab = scanned_member_slabs[i_slab];
  1439. unsigned j;
  1440. for (j = 0; j < max; j++)
  1441. {
  1442. if (!parse_member (slab + j, rv, allocator))
  1443. {
  1444. UNPACK_ERROR (("error parsing member %s of %s",
  1445. slab->field ? slab->field->name : "(unknown)", desc->name));
  1446. goto error_cleanup;
  1447. }
  1448. }
  1449. }
  1450. /* cleanup */
  1451. if (allocator->tmp_alloc == NULL)
  1452. {
  1453. unsigned j;
  1454. for (j = 1; j <= which_slab; j++)
  1455. FREE (allocator, scanned_member_slabs[j]);
  1456. }
  1457. return rv;
  1458. error_cleanup:
  1459. protobuf_c_message_free_unpacked (rv, allocator);
  1460. if (allocator->tmp_alloc == NULL)
  1461. {
  1462. unsigned j;
  1463. for (j = 1; j <= which_slab; j++)
  1464. FREE (allocator, scanned_member_slabs[j]);
  1465. }
  1466. return NULL;
  1467. }
  1468. /* === free_unpacked === */
  1469. void
  1470. protobuf_c_message_free_unpacked (ProtobufCMessage *message,
  1471. ProtobufCAllocator *allocator)
  1472. {
  1473. const ProtobufCMessageDescriptor *desc = message->descriptor;
  1474. unsigned f;
  1475. ASSERT_IS_MESSAGE (message);
  1476. if (allocator == NULL)
  1477. allocator = &protobuf_c_default_allocator;
  1478. message->descriptor = NULL;
  1479. for (f = 0; f < desc->n_fields; f++)
  1480. {
  1481. if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED)
  1482. {
  1483. size_t n = STRUCT_MEMBER (size_t, message, desc->fields[f].quantifier_offset);
  1484. void * arr = STRUCT_MEMBER (void *, message, desc->fields[f].offset);
  1485. if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING && arr != NULL)
  1486. {
  1487. unsigned i;
  1488. for (i = 0; i < n; i++)
  1489. FREE (allocator, ((char**)arr)[i]);
  1490. }
  1491. else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES && arr != NULL)
  1492. {
  1493. unsigned i;
  1494. for (i = 0; i < n; i++)
  1495. FREE (allocator, ((ProtobufCBinaryData*)arr)[i].data);
  1496. }
  1497. else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE && arr != NULL)
  1498. {
  1499. unsigned i;
  1500. for (i = 0; i < n; i++)
  1501. protobuf_c_message_free_unpacked (((ProtobufCMessage**)arr)[i], allocator);
  1502. }
  1503. if (arr != NULL)
  1504. FREE (allocator, arr);
  1505. }
  1506. else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING)
  1507. {
  1508. char *str = STRUCT_MEMBER (char *, message, desc->fields[f].offset);
  1509. if (str && str != desc->fields[f].default_value)
  1510. FREE (allocator, str);
  1511. }
  1512. else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES)
  1513. {
  1514. void *data = STRUCT_MEMBER (ProtobufCBinaryData, message, desc->fields[f].offset).data;
  1515. const ProtobufCBinaryData *default_bd;
  1516. default_bd = desc->fields[f].default_value;
  1517. if (data != NULL
  1518. && (default_bd == NULL || default_bd->data != data))
  1519. FREE (allocator, data);
  1520. }
  1521. else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE)
  1522. {
  1523. ProtobufCMessage *sm;
  1524. sm = STRUCT_MEMBER (ProtobufCMessage *, message,desc->fields[f].offset);
  1525. if (sm && sm != desc->fields[f].default_value)
  1526. protobuf_c_message_free_unpacked (sm, allocator);
  1527. }
  1528. }
  1529. FREE (allocator, message);
  1530. }
  1531. /* === services === */
  1532. typedef struct _ServiceMachgen ServiceMachgen;
  1533. struct _ServiceMachgen
  1534. {
  1535. ProtobufCService base;
  1536. void *service;
  1537. };
  1538. typedef void (*DestroyHandler)(void *service);
  1539. typedef void (*GenericHandler)(void *service,
  1540. const ProtobufCMessage *input,
  1541. ProtobufCClosure closure,
  1542. void *closure_data);
  1543. static void
  1544. service_machgen_invoke(ProtobufCService *service,
  1545. unsigned method_index,
  1546. const ProtobufCMessage *input,
  1547. ProtobufCClosure closure,
  1548. void *closure_data)
  1549. {
  1550. GenericHandler *handlers;
  1551. GenericHandler handler;
  1552. ServiceMachgen *machgen = (ServiceMachgen *) service;
  1553. PROTOBUF_C_ASSERT (method_index < service->descriptor->n_methods);
  1554. handlers = (GenericHandler *) machgen->service;
  1555. handler = handlers[method_index];
  1556. (*handler) (machgen->service, input, closure, closure_data);
  1557. }
  1558. void
  1559. protobuf_c_service_generated_init (ProtobufCService *service,
  1560. const ProtobufCServiceDescriptor *descriptor,
  1561. ProtobufCServiceDestroy destroy)
  1562. {
  1563. ASSERT_IS_SERVICE_DESCRIPTOR(descriptor);
  1564. service->descriptor = descriptor;
  1565. service->destroy = destroy;
  1566. service->invoke = service_machgen_invoke;
  1567. memset (service + 1, 0, descriptor->n_methods * sizeof (GenericHandler));
  1568. }
  1569. void protobuf_c_service_destroy (ProtobufCService *service)
  1570. {
  1571. service-

Large files files are truncated, but you can click here to view the full file