pg_query 1.2.0 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (480) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +217 -99
  3. data/README.md +80 -69
  4. data/Rakefile +85 -5
  5. data/ext/pg_query/extconf.rb +4 -31
  6. data/ext/pg_query/guc-file.c +0 -0
  7. data/ext/pg_query/include/access/amapi.h +246 -0
  8. data/ext/pg_query/include/access/attmap.h +52 -0
  9. data/ext/pg_query/include/access/attnum.h +64 -0
  10. data/ext/pg_query/include/access/clog.h +61 -0
  11. data/ext/pg_query/include/access/commit_ts.h +77 -0
  12. data/ext/pg_query/include/access/detoast.h +92 -0
  13. data/ext/pg_query/include/access/genam.h +228 -0
  14. data/ext/pg_query/include/access/gin.h +78 -0
  15. data/ext/pg_query/include/access/htup.h +89 -0
  16. data/ext/pg_query/include/access/htup_details.h +819 -0
  17. data/ext/pg_query/include/access/itup.h +161 -0
  18. data/ext/pg_query/include/access/parallel.h +82 -0
  19. data/ext/pg_query/include/access/printtup.h +35 -0
  20. data/ext/pg_query/include/access/relation.h +28 -0
  21. data/ext/pg_query/include/access/relscan.h +176 -0
  22. data/ext/pg_query/include/access/rmgr.h +35 -0
  23. data/ext/pg_query/include/access/rmgrlist.h +49 -0
  24. data/ext/pg_query/include/access/sdir.h +58 -0
  25. data/ext/pg_query/include/access/skey.h +151 -0
  26. data/ext/pg_query/include/access/stratnum.h +83 -0
  27. data/ext/pg_query/include/access/sysattr.h +29 -0
  28. data/ext/pg_query/include/access/table.h +27 -0
  29. data/ext/pg_query/include/access/tableam.h +1825 -0
  30. data/ext/pg_query/include/access/transam.h +265 -0
  31. data/ext/pg_query/include/access/tupconvert.h +51 -0
  32. data/ext/pg_query/include/access/tupdesc.h +154 -0
  33. data/ext/pg_query/include/access/tupmacs.h +247 -0
  34. data/ext/pg_query/include/access/twophase.h +61 -0
  35. data/ext/pg_query/include/access/xact.h +463 -0
  36. data/ext/pg_query/include/access/xlog.h +398 -0
  37. data/ext/pg_query/include/access/xlog_internal.h +330 -0
  38. data/ext/pg_query/include/access/xlogdefs.h +109 -0
  39. data/ext/pg_query/include/access/xloginsert.h +64 -0
  40. data/ext/pg_query/include/access/xlogreader.h +327 -0
  41. data/ext/pg_query/include/access/xlogrecord.h +227 -0
  42. data/ext/pg_query/include/bootstrap/bootstrap.h +62 -0
  43. data/ext/pg_query/include/c.h +1322 -0
  44. data/ext/pg_query/include/catalog/catalog.h +42 -0
  45. data/ext/pg_query/include/catalog/catversion.h +58 -0
  46. data/ext/pg_query/include/catalog/dependency.h +275 -0
  47. data/ext/pg_query/include/catalog/genbki.h +64 -0
  48. data/ext/pg_query/include/catalog/index.h +199 -0
  49. data/ext/pg_query/include/catalog/indexing.h +366 -0
  50. data/ext/pg_query/include/catalog/namespace.h +188 -0
  51. data/ext/pg_query/include/catalog/objectaccess.h +197 -0
  52. data/ext/pg_query/include/catalog/objectaddress.h +84 -0
  53. data/ext/pg_query/include/catalog/pg_aggregate.h +176 -0
  54. data/ext/pg_query/include/catalog/pg_aggregate_d.h +77 -0
  55. data/ext/pg_query/include/catalog/pg_am.h +60 -0
  56. data/ext/pg_query/include/catalog/pg_am_d.h +45 -0
  57. data/ext/pg_query/include/catalog/pg_attribute.h +204 -0
  58. data/ext/pg_query/include/catalog/pg_attribute_d.h +59 -0
  59. data/ext/pg_query/include/catalog/pg_authid.h +58 -0
  60. data/ext/pg_query/include/catalog/pg_authid_d.h +49 -0
  61. data/ext/pg_query/include/catalog/pg_class.h +200 -0
  62. data/ext/pg_query/include/catalog/pg_class_d.h +103 -0
  63. data/ext/pg_query/include/catalog/pg_collation.h +73 -0
  64. data/ext/pg_query/include/catalog/pg_collation_d.h +45 -0
  65. data/ext/pg_query/include/catalog/pg_constraint.h +247 -0
  66. data/ext/pg_query/include/catalog/pg_constraint_d.h +67 -0
  67. data/ext/pg_query/include/catalog/pg_control.h +250 -0
  68. data/ext/pg_query/include/catalog/pg_conversion.h +72 -0
  69. data/ext/pg_query/include/catalog/pg_conversion_d.h +35 -0
  70. data/ext/pg_query/include/catalog/pg_depend.h +73 -0
  71. data/ext/pg_query/include/catalog/pg_depend_d.h +34 -0
  72. data/ext/pg_query/include/catalog/pg_event_trigger.h +51 -0
  73. data/ext/pg_query/include/catalog/pg_event_trigger_d.h +34 -0
  74. data/ext/pg_query/include/catalog/pg_index.h +80 -0
  75. data/ext/pg_query/include/catalog/pg_index_d.h +56 -0
  76. data/ext/pg_query/include/catalog/pg_language.h +67 -0
  77. data/ext/pg_query/include/catalog/pg_language_d.h +39 -0
  78. data/ext/pg_query/include/catalog/pg_namespace.h +59 -0
  79. data/ext/pg_query/include/catalog/pg_namespace_d.h +34 -0
  80. data/ext/pg_query/include/catalog/pg_opclass.h +85 -0
  81. data/ext/pg_query/include/catalog/pg_opclass_d.h +49 -0
  82. data/ext/pg_query/include/catalog/pg_operator.h +102 -0
  83. data/ext/pg_query/include/catalog/pg_operator_d.h +106 -0
  84. data/ext/pg_query/include/catalog/pg_opfamily.h +60 -0
  85. data/ext/pg_query/include/catalog/pg_opfamily_d.h +47 -0
  86. data/ext/pg_query/include/catalog/pg_partitioned_table.h +63 -0
  87. data/ext/pg_query/include/catalog/pg_partitioned_table_d.h +35 -0
  88. data/ext/pg_query/include/catalog/pg_proc.h +211 -0
  89. data/ext/pg_query/include/catalog/pg_proc_d.h +99 -0
  90. data/ext/pg_query/include/catalog/pg_publication.h +115 -0
  91. data/ext/pg_query/include/catalog/pg_publication_d.h +36 -0
  92. data/ext/pg_query/include/catalog/pg_replication_origin.h +57 -0
  93. data/ext/pg_query/include/catalog/pg_replication_origin_d.h +29 -0
  94. data/ext/pg_query/include/catalog/pg_statistic.h +275 -0
  95. data/ext/pg_query/include/catalog/pg_statistic_d.h +194 -0
  96. data/ext/pg_query/include/catalog/pg_statistic_ext.h +74 -0
  97. data/ext/pg_query/include/catalog/pg_statistic_ext_d.h +40 -0
  98. data/ext/pg_query/include/catalog/pg_transform.h +45 -0
  99. data/ext/pg_query/include/catalog/pg_transform_d.h +32 -0
  100. data/ext/pg_query/include/catalog/pg_trigger.h +137 -0
  101. data/ext/pg_query/include/catalog/pg_trigger_d.h +106 -0
  102. data/ext/pg_query/include/catalog/pg_ts_config.h +50 -0
  103. data/ext/pg_query/include/catalog/pg_ts_config_d.h +32 -0
  104. data/ext/pg_query/include/catalog/pg_ts_dict.h +54 -0
  105. data/ext/pg_query/include/catalog/pg_ts_dict_d.h +33 -0
  106. data/ext/pg_query/include/catalog/pg_ts_parser.h +57 -0
  107. data/ext/pg_query/include/catalog/pg_ts_parser_d.h +35 -0
  108. data/ext/pg_query/include/catalog/pg_ts_template.h +48 -0
  109. data/ext/pg_query/include/catalog/pg_ts_template_d.h +32 -0
  110. data/ext/pg_query/include/catalog/pg_type.h +372 -0
  111. data/ext/pg_query/include/catalog/pg_type_d.h +285 -0
  112. data/ext/pg_query/include/catalog/storage.h +48 -0
  113. data/ext/pg_query/include/commands/async.h +54 -0
  114. data/ext/pg_query/include/commands/dbcommands.h +35 -0
  115. data/ext/pg_query/include/commands/defrem.h +173 -0
  116. data/ext/pg_query/include/commands/event_trigger.h +88 -0
  117. data/ext/pg_query/include/commands/explain.h +127 -0
  118. data/ext/pg_query/include/commands/prepare.h +61 -0
  119. data/ext/pg_query/include/commands/tablespace.h +67 -0
  120. data/ext/pg_query/include/commands/trigger.h +277 -0
  121. data/ext/pg_query/include/commands/user.h +37 -0
  122. data/ext/pg_query/include/commands/vacuum.h +293 -0
  123. data/ext/pg_query/include/commands/variable.h +38 -0
  124. data/ext/pg_query/include/common/file_perm.h +56 -0
  125. data/ext/pg_query/include/common/hashfn.h +104 -0
  126. data/ext/pg_query/include/common/ip.h +37 -0
  127. data/ext/pg_query/include/common/keywords.h +33 -0
  128. data/ext/pg_query/include/common/kwlookup.h +44 -0
  129. data/ext/pg_query/include/common/relpath.h +90 -0
  130. data/ext/pg_query/include/common/string.h +19 -0
  131. data/ext/pg_query/include/common/unicode_combining_table.h +196 -0
  132. data/ext/pg_query/include/datatype/timestamp.h +197 -0
  133. data/ext/pg_query/include/executor/execdesc.h +70 -0
  134. data/ext/pg_query/include/executor/executor.h +614 -0
  135. data/ext/pg_query/include/executor/functions.h +41 -0
  136. data/ext/pg_query/include/executor/instrument.h +101 -0
  137. data/ext/pg_query/include/executor/spi.h +175 -0
  138. data/ext/pg_query/include/executor/tablefunc.h +67 -0
  139. data/ext/pg_query/include/executor/tuptable.h +487 -0
  140. data/ext/pg_query/include/fmgr.h +775 -0
  141. data/ext/pg_query/include/funcapi.h +348 -0
  142. data/ext/pg_query/include/getaddrinfo.h +162 -0
  143. data/ext/pg_query/include/jit/jit.h +105 -0
  144. data/ext/pg_query/include/kwlist_d.h +1072 -0
  145. data/ext/pg_query/include/lib/ilist.h +727 -0
  146. data/ext/pg_query/include/lib/pairingheap.h +102 -0
  147. data/ext/pg_query/include/lib/simplehash.h +1059 -0
  148. data/ext/pg_query/include/lib/stringinfo.h +161 -0
  149. data/ext/pg_query/include/libpq/auth.h +29 -0
  150. data/ext/pg_query/include/libpq/crypt.h +46 -0
  151. data/ext/pg_query/include/libpq/hba.h +140 -0
  152. data/ext/pg_query/include/libpq/libpq-be.h +326 -0
  153. data/ext/pg_query/include/libpq/libpq.h +133 -0
  154. data/ext/pg_query/include/libpq/pqcomm.h +208 -0
  155. data/ext/pg_query/include/libpq/pqformat.h +210 -0
  156. data/ext/pg_query/include/libpq/pqsignal.h +42 -0
  157. data/ext/pg_query/include/mb/pg_wchar.h +672 -0
  158. data/ext/pg_query/include/mb/stringinfo_mb.h +24 -0
  159. data/ext/pg_query/include/miscadmin.h +476 -0
  160. data/ext/pg_query/include/nodes/bitmapset.h +122 -0
  161. data/ext/pg_query/include/nodes/execnodes.h +2520 -0
  162. data/ext/pg_query/include/nodes/extensible.h +160 -0
  163. data/ext/pg_query/include/nodes/lockoptions.h +61 -0
  164. data/ext/pg_query/include/nodes/makefuncs.h +108 -0
  165. data/ext/pg_query/include/nodes/memnodes.h +108 -0
  166. data/ext/pg_query/include/nodes/nodeFuncs.h +162 -0
  167. data/ext/pg_query/include/nodes/nodes.h +842 -0
  168. data/ext/pg_query/include/nodes/params.h +170 -0
  169. data/ext/pg_query/include/nodes/parsenodes.h +3579 -0
  170. data/ext/pg_query/include/nodes/pathnodes.h +2556 -0
  171. data/ext/pg_query/include/nodes/pg_list.h +605 -0
  172. data/ext/pg_query/include/nodes/plannodes.h +1251 -0
  173. data/ext/pg_query/include/nodes/primnodes.h +1541 -0
  174. data/ext/pg_query/include/nodes/print.h +34 -0
  175. data/ext/pg_query/include/nodes/tidbitmap.h +75 -0
  176. data/ext/pg_query/include/nodes/value.h +61 -0
  177. data/ext/pg_query/include/optimizer/cost.h +206 -0
  178. data/ext/pg_query/include/optimizer/geqo.h +88 -0
  179. data/ext/pg_query/include/optimizer/geqo_gene.h +45 -0
  180. data/ext/pg_query/include/optimizer/optimizer.h +199 -0
  181. data/ext/pg_query/include/optimizer/paths.h +249 -0
  182. data/ext/pg_query/include/optimizer/planmain.h +119 -0
  183. data/ext/pg_query/include/parser/analyze.h +49 -0
  184. data/ext/pg_query/include/parser/gram.h +1067 -0
  185. data/ext/pg_query/include/parser/gramparse.h +75 -0
  186. data/ext/pg_query/include/parser/kwlist.h +477 -0
  187. data/ext/pg_query/include/parser/parse_agg.h +68 -0
  188. data/ext/pg_query/include/parser/parse_clause.h +54 -0
  189. data/ext/pg_query/include/parser/parse_coerce.h +97 -0
  190. data/ext/pg_query/include/parser/parse_collate.h +27 -0
  191. data/ext/pg_query/include/parser/parse_expr.h +26 -0
  192. data/ext/pg_query/include/parser/parse_func.h +73 -0
  193. data/ext/pg_query/include/parser/parse_node.h +327 -0
  194. data/ext/pg_query/include/parser/parse_oper.h +67 -0
  195. data/ext/pg_query/include/parser/parse_relation.h +123 -0
  196. data/ext/pg_query/include/parser/parse_target.h +46 -0
  197. data/ext/pg_query/include/parser/parse_type.h +60 -0
  198. data/ext/pg_query/include/parser/parser.h +41 -0
  199. data/ext/pg_query/include/parser/parsetree.h +61 -0
  200. data/ext/pg_query/include/parser/scanner.h +152 -0
  201. data/ext/pg_query/include/parser/scansup.h +30 -0
  202. data/ext/pg_query/include/partitioning/partdefs.h +26 -0
  203. data/ext/pg_query/include/pg_config.h +989 -0
  204. data/ext/pg_query/include/pg_config_ext.h +8 -0
  205. data/ext/pg_query/include/pg_config_manual.h +350 -0
  206. data/ext/pg_query/include/pg_config_os.h +8 -0
  207. data/ext/pg_query/include/pg_getopt.h +56 -0
  208. data/ext/pg_query/include/pg_query.h +121 -0
  209. data/ext/pg_query/include/pg_query_enum_defs.c +2454 -0
  210. data/ext/pg_query/include/pg_query_fingerprint_conds.c +875 -0
  211. data/ext/pg_query/include/pg_query_fingerprint_defs.c +12413 -0
  212. data/ext/pg_query/include/pg_query_json_helper.c +61 -0
  213. data/ext/pg_query/include/pg_query_outfuncs_conds.c +686 -0
  214. data/ext/pg_query/include/pg_query_outfuncs_defs.c +2437 -0
  215. data/ext/pg_query/include/pg_query_readfuncs_conds.c +222 -0
  216. data/ext/pg_query/include/pg_query_readfuncs_defs.c +2878 -0
  217. data/ext/pg_query/include/pg_trace.h +17 -0
  218. data/ext/pg_query/include/pgstat.h +1487 -0
  219. data/ext/pg_query/include/pgtime.h +84 -0
  220. data/ext/pg_query/include/pl_gram.h +385 -0
  221. data/ext/pg_query/include/pl_reserved_kwlist.h +52 -0
  222. data/ext/pg_query/include/pl_reserved_kwlist_d.h +114 -0
  223. data/ext/pg_query/include/pl_unreserved_kwlist.h +112 -0
  224. data/ext/pg_query/include/pl_unreserved_kwlist_d.h +246 -0
  225. data/ext/pg_query/include/plerrcodes.h +990 -0
  226. data/ext/pg_query/include/plpgsql.h +1347 -0
  227. data/ext/pg_query/include/port.h +524 -0
  228. data/ext/pg_query/include/port/atomics.h +524 -0
  229. data/ext/pg_query/include/port/atomics/arch-arm.h +26 -0
  230. data/ext/pg_query/include/port/atomics/arch-ppc.h +254 -0
  231. data/ext/pg_query/include/port/atomics/arch-x86.h +252 -0
  232. data/ext/pg_query/include/port/atomics/fallback.h +170 -0
  233. data/ext/pg_query/include/port/atomics/generic-gcc.h +286 -0
  234. data/ext/pg_query/include/port/atomics/generic.h +401 -0
  235. data/ext/pg_query/include/port/pg_bitutils.h +226 -0
  236. data/ext/pg_query/include/port/pg_bswap.h +161 -0
  237. data/ext/pg_query/include/port/pg_crc32c.h +101 -0
  238. data/ext/pg_query/include/portability/instr_time.h +256 -0
  239. data/ext/pg_query/include/postgres.h +764 -0
  240. data/ext/pg_query/include/postgres_ext.h +74 -0
  241. data/ext/pg_query/include/postmaster/autovacuum.h +83 -0
  242. data/ext/pg_query/include/postmaster/bgworker.h +161 -0
  243. data/ext/pg_query/include/postmaster/bgworker_internals.h +64 -0
  244. data/ext/pg_query/include/postmaster/bgwriter.h +45 -0
  245. data/ext/pg_query/include/postmaster/fork_process.h +17 -0
  246. data/ext/pg_query/include/postmaster/interrupt.h +32 -0
  247. data/ext/pg_query/include/postmaster/pgarch.h +39 -0
  248. data/ext/pg_query/include/postmaster/postmaster.h +77 -0
  249. data/ext/pg_query/include/postmaster/syslogger.h +98 -0
  250. data/ext/pg_query/include/postmaster/walwriter.h +21 -0
  251. data/ext/pg_query/include/protobuf-c.h +1106 -0
  252. data/ext/pg_query/include/protobuf-c/protobuf-c.h +1106 -0
  253. data/ext/pg_query/include/protobuf/pg_query.pb-c.h +10846 -0
  254. data/ext/pg_query/include/protobuf/pg_query.pb.h +124718 -0
  255. data/ext/pg_query/include/regex/regex.h +184 -0
  256. data/ext/pg_query/include/replication/logicallauncher.h +31 -0
  257. data/ext/pg_query/include/replication/logicalproto.h +110 -0
  258. data/ext/pg_query/include/replication/logicalworker.h +19 -0
  259. data/ext/pg_query/include/replication/origin.h +73 -0
  260. data/ext/pg_query/include/replication/reorderbuffer.h +467 -0
  261. data/ext/pg_query/include/replication/slot.h +219 -0
  262. data/ext/pg_query/include/replication/syncrep.h +115 -0
  263. data/ext/pg_query/include/replication/walreceiver.h +340 -0
  264. data/ext/pg_query/include/replication/walsender.h +74 -0
  265. data/ext/pg_query/include/rewrite/prs2lock.h +46 -0
  266. data/ext/pg_query/include/rewrite/rewriteHandler.h +40 -0
  267. data/ext/pg_query/include/rewrite/rewriteManip.h +87 -0
  268. data/ext/pg_query/include/rewrite/rewriteSupport.h +26 -0
  269. data/ext/pg_query/include/storage/backendid.h +37 -0
  270. data/ext/pg_query/include/storage/block.h +121 -0
  271. data/ext/pg_query/include/storage/buf.h +46 -0
  272. data/ext/pg_query/include/storage/bufmgr.h +292 -0
  273. data/ext/pg_query/include/storage/bufpage.h +459 -0
  274. data/ext/pg_query/include/storage/condition_variable.h +62 -0
  275. data/ext/pg_query/include/storage/dsm.h +61 -0
  276. data/ext/pg_query/include/storage/dsm_impl.h +75 -0
  277. data/ext/pg_query/include/storage/fd.h +168 -0
  278. data/ext/pg_query/include/storage/ipc.h +81 -0
  279. data/ext/pg_query/include/storage/item.h +19 -0
  280. data/ext/pg_query/include/storage/itemid.h +184 -0
  281. data/ext/pg_query/include/storage/itemptr.h +206 -0
  282. data/ext/pg_query/include/storage/large_object.h +100 -0
  283. data/ext/pg_query/include/storage/latch.h +190 -0
  284. data/ext/pg_query/include/storage/lmgr.h +114 -0
  285. data/ext/pg_query/include/storage/lock.h +612 -0
  286. data/ext/pg_query/include/storage/lockdefs.h +59 -0
  287. data/ext/pg_query/include/storage/lwlock.h +232 -0
  288. data/ext/pg_query/include/storage/lwlocknames.h +51 -0
  289. data/ext/pg_query/include/storage/off.h +57 -0
  290. data/ext/pg_query/include/storage/pg_sema.h +61 -0
  291. data/ext/pg_query/include/storage/pg_shmem.h +90 -0
  292. data/ext/pg_query/include/storage/pmsignal.h +94 -0
  293. data/ext/pg_query/include/storage/predicate.h +87 -0
  294. data/ext/pg_query/include/storage/proc.h +333 -0
  295. data/ext/pg_query/include/storage/proclist_types.h +51 -0
  296. data/ext/pg_query/include/storage/procsignal.h +75 -0
  297. data/ext/pg_query/include/storage/relfilenode.h +99 -0
  298. data/ext/pg_query/include/storage/s_lock.h +1047 -0
  299. data/ext/pg_query/include/storage/sharedfileset.h +45 -0
  300. data/ext/pg_query/include/storage/shm_mq.h +85 -0
  301. data/ext/pg_query/include/storage/shm_toc.h +58 -0
  302. data/ext/pg_query/include/storage/shmem.h +81 -0
  303. data/ext/pg_query/include/storage/sinval.h +153 -0
  304. data/ext/pg_query/include/storage/sinvaladt.h +43 -0
  305. data/ext/pg_query/include/storage/smgr.h +109 -0
  306. data/ext/pg_query/include/storage/spin.h +77 -0
  307. data/ext/pg_query/include/storage/standby.h +91 -0
  308. data/ext/pg_query/include/storage/standbydefs.h +74 -0
  309. data/ext/pg_query/include/storage/sync.h +62 -0
  310. data/ext/pg_query/include/tcop/cmdtag.h +58 -0
  311. data/ext/pg_query/include/tcop/cmdtaglist.h +217 -0
  312. data/ext/pg_query/include/tcop/deparse_utility.h +108 -0
  313. data/ext/pg_query/include/tcop/dest.h +149 -0
  314. data/ext/pg_query/include/tcop/fastpath.h +21 -0
  315. data/ext/pg_query/include/tcop/pquery.h +45 -0
  316. data/ext/pg_query/include/tcop/tcopprot.h +89 -0
  317. data/ext/pg_query/include/tcop/utility.h +108 -0
  318. data/ext/pg_query/include/tsearch/ts_cache.h +98 -0
  319. data/ext/pg_query/include/utils/acl.h +312 -0
  320. data/ext/pg_query/include/utils/aclchk_internal.h +45 -0
  321. data/ext/pg_query/include/utils/array.h +458 -0
  322. data/ext/pg_query/include/utils/builtins.h +127 -0
  323. data/ext/pg_query/include/utils/bytea.h +27 -0
  324. data/ext/pg_query/include/utils/catcache.h +231 -0
  325. data/ext/pg_query/include/utils/date.h +90 -0
  326. data/ext/pg_query/include/utils/datetime.h +343 -0
  327. data/ext/pg_query/include/utils/datum.h +68 -0
  328. data/ext/pg_query/include/utils/dsa.h +123 -0
  329. data/ext/pg_query/include/utils/dynahash.h +19 -0
  330. data/ext/pg_query/include/utils/elog.h +439 -0
  331. data/ext/pg_query/include/utils/errcodes.h +352 -0
  332. data/ext/pg_query/include/utils/expandeddatum.h +159 -0
  333. data/ext/pg_query/include/utils/expandedrecord.h +231 -0
  334. data/ext/pg_query/include/utils/float.h +356 -0
  335. data/ext/pg_query/include/utils/fmgroids.h +2657 -0
  336. data/ext/pg_query/include/utils/fmgrprotos.h +2646 -0
  337. data/ext/pg_query/include/utils/fmgrtab.h +48 -0
  338. data/ext/pg_query/include/utils/guc.h +443 -0
  339. data/ext/pg_query/include/utils/guc_tables.h +272 -0
  340. data/ext/pg_query/include/utils/hsearch.h +149 -0
  341. data/ext/pg_query/include/utils/inval.h +64 -0
  342. data/ext/pg_query/include/utils/lsyscache.h +197 -0
  343. data/ext/pg_query/include/utils/memdebug.h +82 -0
  344. data/ext/pg_query/include/utils/memutils.h +225 -0
  345. data/ext/pg_query/include/utils/numeric.h +76 -0
  346. data/ext/pg_query/include/utils/palloc.h +136 -0
  347. data/ext/pg_query/include/utils/partcache.h +102 -0
  348. data/ext/pg_query/include/utils/pg_locale.h +119 -0
  349. data/ext/pg_query/include/utils/pg_lsn.h +29 -0
  350. data/ext/pg_query/include/utils/pidfile.h +56 -0
  351. data/ext/pg_query/include/utils/plancache.h +235 -0
  352. data/ext/pg_query/include/utils/portal.h +241 -0
  353. data/ext/pg_query/include/utils/probes.h +114 -0
  354. data/ext/pg_query/include/utils/ps_status.h +25 -0
  355. data/ext/pg_query/include/utils/queryenvironment.h +74 -0
  356. data/ext/pg_query/include/utils/regproc.h +28 -0
  357. data/ext/pg_query/include/utils/rel.h +644 -0
  358. data/ext/pg_query/include/utils/relcache.h +151 -0
  359. data/ext/pg_query/include/utils/reltrigger.h +81 -0
  360. data/ext/pg_query/include/utils/resowner.h +86 -0
  361. data/ext/pg_query/include/utils/rls.h +50 -0
  362. data/ext/pg_query/include/utils/ruleutils.h +44 -0
  363. data/ext/pg_query/include/utils/sharedtuplestore.h +61 -0
  364. data/ext/pg_query/include/utils/snapmgr.h +158 -0
  365. data/ext/pg_query/include/utils/snapshot.h +206 -0
  366. data/ext/pg_query/include/utils/sortsupport.h +276 -0
  367. data/ext/pg_query/include/utils/syscache.h +219 -0
  368. data/ext/pg_query/include/utils/timeout.h +88 -0
  369. data/ext/pg_query/include/utils/timestamp.h +116 -0
  370. data/ext/pg_query/include/utils/tuplesort.h +277 -0
  371. data/ext/pg_query/include/utils/tuplestore.h +91 -0
  372. data/ext/pg_query/include/utils/typcache.h +202 -0
  373. data/ext/pg_query/include/utils/tzparser.h +39 -0
  374. data/ext/pg_query/include/utils/varlena.h +39 -0
  375. data/ext/pg_query/include/utils/xml.h +84 -0
  376. data/ext/pg_query/include/xxhash.h +5445 -0
  377. data/ext/pg_query/include/xxhash/xxhash.h +5445 -0
  378. data/ext/pg_query/pg_query.c +104 -0
  379. data/ext/pg_query/pg_query.pb-c.c +37628 -0
  380. data/ext/pg_query/pg_query_deparse.c +9959 -0
  381. data/ext/pg_query/pg_query_fingerprint.c +295 -0
  382. data/ext/pg_query/pg_query_fingerprint.h +8 -0
  383. data/ext/pg_query/pg_query_internal.h +24 -0
  384. data/ext/pg_query/pg_query_json_plpgsql.c +738 -0
  385. data/ext/pg_query/pg_query_json_plpgsql.h +9 -0
  386. data/ext/pg_query/pg_query_normalize.c +439 -0
  387. data/ext/pg_query/pg_query_outfuncs.h +10 -0
  388. data/ext/pg_query/pg_query_outfuncs_json.c +297 -0
  389. data/ext/pg_query/pg_query_outfuncs_protobuf.c +237 -0
  390. data/ext/pg_query/pg_query_parse.c +148 -0
  391. data/ext/pg_query/pg_query_parse_plpgsql.c +460 -0
  392. data/ext/pg_query/pg_query_readfuncs.h +11 -0
  393. data/ext/pg_query/pg_query_readfuncs_protobuf.c +142 -0
  394. data/ext/pg_query/pg_query_ruby.c +108 -12
  395. data/ext/pg_query/pg_query_scan.c +173 -0
  396. data/ext/pg_query/pg_query_split.c +221 -0
  397. data/ext/pg_query/protobuf-c.c +3660 -0
  398. data/ext/pg_query/src_backend_catalog_namespace.c +1051 -0
  399. data/ext/pg_query/src_backend_catalog_pg_proc.c +142 -0
  400. data/ext/pg_query/src_backend_commands_define.c +117 -0
  401. data/ext/pg_query/src_backend_libpq_pqcomm.c +651 -0
  402. data/ext/pg_query/src_backend_nodes_bitmapset.c +513 -0
  403. data/ext/pg_query/src_backend_nodes_copyfuncs.c +6013 -0
  404. data/ext/pg_query/src_backend_nodes_equalfuncs.c +4003 -0
  405. data/ext/pg_query/src_backend_nodes_extensible.c +99 -0
  406. data/ext/pg_query/src_backend_nodes_list.c +922 -0
  407. data/ext/pg_query/src_backend_nodes_makefuncs.c +417 -0
  408. data/ext/pg_query/src_backend_nodes_nodeFuncs.c +1363 -0
  409. data/ext/pg_query/src_backend_nodes_value.c +84 -0
  410. data/ext/pg_query/src_backend_parser_gram.c +47456 -0
  411. data/ext/pg_query/src_backend_parser_parse_expr.c +313 -0
  412. data/ext/pg_query/src_backend_parser_parser.c +497 -0
  413. data/ext/pg_query/src_backend_parser_scan.c +7091 -0
  414. data/ext/pg_query/src_backend_parser_scansup.c +160 -0
  415. data/ext/pg_query/src_backend_postmaster_postmaster.c +2230 -0
  416. data/ext/pg_query/src_backend_storage_ipc_ipc.c +192 -0
  417. data/ext/pg_query/src_backend_storage_lmgr_s_lock.c +370 -0
  418. data/ext/pg_query/src_backend_tcop_postgres.c +776 -0
  419. data/ext/pg_query/src_backend_utils_adt_datum.c +326 -0
  420. data/ext/pg_query/src_backend_utils_adt_expandeddatum.c +98 -0
  421. data/ext/pg_query/src_backend_utils_adt_format_type.c +136 -0
  422. data/ext/pg_query/src_backend_utils_adt_ruleutils.c +1683 -0
  423. data/ext/pg_query/src_backend_utils_error_assert.c +74 -0
  424. data/ext/pg_query/src_backend_utils_error_elog.c +1748 -0
  425. data/ext/pg_query/src_backend_utils_fmgr_fmgr.c +570 -0
  426. data/ext/pg_query/src_backend_utils_hash_dynahash.c +1086 -0
  427. data/ext/pg_query/src_backend_utils_init_globals.c +168 -0
  428. data/ext/pg_query/src_backend_utils_mb_mbutils.c +839 -0
  429. data/ext/pg_query/src_backend_utils_misc_guc.c +1831 -0
  430. data/ext/pg_query/src_backend_utils_mmgr_aset.c +1560 -0
  431. data/ext/pg_query/src_backend_utils_mmgr_mcxt.c +1006 -0
  432. data/ext/pg_query/src_common_encnames.c +158 -0
  433. data/ext/pg_query/src_common_keywords.c +39 -0
  434. data/ext/pg_query/src_common_kwlist_d.h +1081 -0
  435. data/ext/pg_query/src_common_kwlookup.c +91 -0
  436. data/ext/pg_query/src_common_psprintf.c +158 -0
  437. data/ext/pg_query/src_common_string.c +86 -0
  438. data/ext/pg_query/src_common_stringinfo.c +336 -0
  439. data/ext/pg_query/src_common_wchar.c +1651 -0
  440. data/ext/pg_query/src_pl_plpgsql_src_pl_comp.c +1133 -0
  441. data/ext/pg_query/src_pl_plpgsql_src_pl_funcs.c +877 -0
  442. data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +6533 -0
  443. data/ext/pg_query/src_pl_plpgsql_src_pl_handler.c +107 -0
  444. data/ext/pg_query/src_pl_plpgsql_src_pl_reserved_kwlist_d.h +123 -0
  445. data/ext/pg_query/src_pl_plpgsql_src_pl_scanner.c +671 -0
  446. data/ext/pg_query/src_pl_plpgsql_src_pl_unreserved_kwlist_d.h +255 -0
  447. data/ext/pg_query/src_port_erand48.c +127 -0
  448. data/ext/pg_query/src_port_pg_bitutils.c +246 -0
  449. data/ext/pg_query/src_port_pgsleep.c +69 -0
  450. data/ext/pg_query/src_port_pgstrcasecmp.c +83 -0
  451. data/ext/pg_query/src_port_qsort.c +240 -0
  452. data/ext/pg_query/src_port_random.c +31 -0
  453. data/ext/pg_query/src_port_snprintf.c +1449 -0
  454. data/ext/pg_query/src_port_strerror.c +324 -0
  455. data/ext/pg_query/src_port_strnlen.c +39 -0
  456. data/ext/pg_query/xxhash.c +43 -0
  457. data/lib/pg_query.rb +7 -4
  458. data/lib/pg_query/constants.rb +21 -0
  459. data/lib/pg_query/deparse.rb +15 -1478
  460. data/lib/pg_query/filter_columns.rb +88 -85
  461. data/lib/pg_query/fingerprint.rb +122 -87
  462. data/lib/pg_query/json_field_names.rb +1402 -0
  463. data/lib/pg_query/node.rb +31 -0
  464. data/lib/pg_query/param_refs.rb +42 -37
  465. data/lib/pg_query/parse.rb +220 -200
  466. data/lib/pg_query/parse_error.rb +1 -1
  467. data/lib/pg_query/pg_query_pb.rb +3211 -0
  468. data/lib/pg_query/scan.rb +23 -0
  469. data/lib/pg_query/treewalker.rb +24 -40
  470. data/lib/pg_query/truncate.rb +71 -42
  471. data/lib/pg_query/version.rb +2 -2
  472. metadata +473 -12
  473. data/ext/pg_query/pg_query_ruby.h +0 -10
  474. data/lib/pg_query/deep_dup.rb +0 -16
  475. data/lib/pg_query/deparse/alter_table.rb +0 -42
  476. data/lib/pg_query/deparse/interval.rb +0 -105
  477. data/lib/pg_query/deparse/keywords.rb +0 -159
  478. data/lib/pg_query/deparse/rename.rb +0 -41
  479. data/lib/pg_query/legacy_parsetree.rb +0 -109
  480. data/lib/pg_query/node_types.rb +0 -293
@@ -0,0 +1,221 @@
1
+ #include "pg_query.h"
2
+ #include "pg_query_internal.h"
3
+
4
+ #include "parser/gramparse.h"
5
+ #include "lib/stringinfo.h"
6
+
7
+ #include <unistd.h>
8
+ #include <fcntl.h>
9
+
10
+ PgQuerySplitResult pg_query_split_with_scanner(const char* input)
11
+ {
12
+ MemoryContext ctx = NULL;
13
+ PgQuerySplitResult result = {0};
14
+ core_yyscan_t yyscanner;
15
+ core_yy_extra_type yyextra;
16
+ core_YYSTYPE yylval;
17
+ YYLTYPE yylloc;
18
+ size_t curstmt = 0;
19
+ bool keyword_before_terminator = false;
20
+ int stmtstart = 0;
21
+ bool is_keyword = false;
22
+ size_t open_parens = 0;
23
+
24
+ ctx = pg_query_enter_memory_context();
25
+
26
+ MemoryContext parse_context = CurrentMemoryContext;
27
+
28
+ char stderr_buffer[STDERR_BUFFER_LEN + 1] = {0};
29
+ #ifndef DEBUG
30
+ int stderr_global;
31
+ int stderr_pipe[2];
32
+ #endif
33
+
34
+ #ifndef DEBUG
35
+ // Setup pipe for stderr redirection
36
+ if (pipe(stderr_pipe) != 0) {
37
+ PgQueryError* error = malloc(sizeof(PgQueryError));
38
+
39
+ error->message = strdup("Failed to open pipe, too many open file descriptors")
40
+
41
+ result.error = error;
42
+
43
+ return result;
44
+ }
45
+
46
+ fcntl(stderr_pipe[0], F_SETFL, fcntl(stderr_pipe[0], F_GETFL) | O_NONBLOCK);
47
+
48
+ // Redirect stderr to the pipe
49
+ stderr_global = dup(STDERR_FILENO);
50
+ dup2(stderr_pipe[1], STDERR_FILENO);
51
+ close(stderr_pipe[1]);
52
+ #endif
53
+
54
+ PG_TRY();
55
+ {
56
+ // Really this is stupid, we only run twice so we can pre-allocate the output array correctly
57
+ yyscanner = scanner_init(input, &yyextra, &ScanKeywords, ScanKeywordTokens);
58
+ while (true)
59
+ {
60
+ int tok = core_yylex(&yylval, &yylloc, yyscanner);
61
+ switch (tok) {
62
+ #define PG_KEYWORD(a,b,c) case b: is_keyword = true; break;
63
+ #include "parser/kwlist.h"
64
+ default: is_keyword = false;
65
+ }
66
+ if (is_keyword)
67
+ keyword_before_terminator = true;
68
+ else if (tok == '(')
69
+ open_parens++;
70
+ else if (tok == ')')
71
+ open_parens--;
72
+ else if (keyword_before_terminator && open_parens == 0 && (tok == ';' || tok == 0))
73
+ {
74
+ result.n_stmts++;
75
+ keyword_before_terminator = false;
76
+ }
77
+ if (tok == 0) break;
78
+ }
79
+ scanner_finish(yyscanner);
80
+
81
+ result.stmts = malloc(sizeof(PgQuerySplitStmt *) * result.n_stmts);
82
+
83
+ // Now actually set the output values
84
+ keyword_before_terminator = false;
85
+ open_parens = 0;
86
+ yyscanner = scanner_init(input, &yyextra, &ScanKeywords, ScanKeywordTokens);
87
+ while (true)
88
+ {
89
+ int tok = core_yylex(&yylval, &yylloc, yyscanner);
90
+ switch (tok) {
91
+ #define PG_KEYWORD(a,b,c) case b: is_keyword = true; break;
92
+ #include "parser/kwlist.h"
93
+ default: is_keyword = false;
94
+ }
95
+ if (is_keyword)
96
+ keyword_before_terminator = true;
97
+ else if (tok == '(')
98
+ open_parens++;
99
+ else if (tok == ')')
100
+ open_parens--;
101
+ else if (keyword_before_terminator && open_parens == 0 && (tok == ';' || tok == 0))
102
+ {
103
+ // Add statement up to the current position
104
+ result.stmts[curstmt] = malloc(sizeof(PgQuerySplitStmt));
105
+ result.stmts[curstmt]->stmt_location = stmtstart;
106
+ result.stmts[curstmt]->stmt_len = yylloc - stmtstart;
107
+
108
+ stmtstart = yylloc + 1;
109
+ keyword_before_terminator = false;
110
+
111
+ curstmt++;
112
+ }
113
+ else if (open_parens == 0 && tok == ';') // Advance statement start in case we skip an empty statement
114
+ {
115
+ stmtstart = yylloc + 1;
116
+ }
117
+
118
+ if (tok == 0) break;
119
+ }
120
+
121
+ scanner_finish(yyscanner);
122
+
123
+ #ifndef DEBUG
124
+ // Save stderr for result
125
+ read(stderr_pipe[0], stderr_buffer, STDERR_BUFFER_LEN);
126
+ #endif
127
+
128
+ result.stderr_buffer = strdup(stderr_buffer);
129
+ }
130
+ PG_CATCH();
131
+ {
132
+ ErrorData* error_data;
133
+ PgQueryError* error;
134
+
135
+ MemoryContextSwitchTo(parse_context);
136
+ error_data = CopyErrorData();
137
+
138
+ // Note: This is intentionally malloc so exiting the memory context doesn't free this
139
+ error = malloc(sizeof(PgQueryError));
140
+ error->message = strdup(error_data->message);
141
+ error->filename = strdup(error_data->filename);
142
+ error->funcname = strdup(error_data->funcname);
143
+ error->context = NULL;
144
+ error->lineno = error_data->lineno;
145
+ error->cursorpos = error_data->cursorpos;
146
+
147
+ result.error = error;
148
+ FlushErrorState();
149
+ }
150
+ PG_END_TRY();
151
+
152
+ #ifndef DEBUG
153
+ // Restore stderr, close pipe
154
+ dup2(stderr_global, STDERR_FILENO);
155
+ close(stderr_pipe[0]);
156
+ close(stderr_global);
157
+ #endif
158
+
159
+ pg_query_exit_memory_context(ctx);
160
+
161
+ return result;
162
+ }
163
+
164
+ PgQuerySplitResult pg_query_split_with_parser(const char* input)
165
+ {
166
+ MemoryContext ctx = NULL;
167
+ PgQueryInternalParsetreeAndError parsetree_and_error;
168
+ PgQuerySplitResult result = {};
169
+
170
+ ctx = pg_query_enter_memory_context();
171
+
172
+ parsetree_and_error = pg_query_raw_parse(input);
173
+
174
+ // These are all malloc-ed and will survive exiting the memory context, the caller is responsible to free them now
175
+ result.stderr_buffer = parsetree_and_error.stderr_buffer;
176
+ result.error = parsetree_and_error.error;
177
+
178
+ if (parsetree_and_error.tree != NULL)
179
+ {
180
+ ListCell *lc;
181
+
182
+ result.n_stmts = list_length(parsetree_and_error.tree);
183
+ result.stmts = malloc(sizeof(PgQuerySplitStmt*) * result.n_stmts);
184
+ foreach (lc, parsetree_and_error.tree)
185
+ {
186
+ RawStmt *raw_stmt = castNode(RawStmt, lfirst(lc));
187
+ result.stmts[foreach_current_index(lc)] = malloc(sizeof(PgQuerySplitStmt));
188
+ result.stmts[foreach_current_index(lc)]->stmt_location = raw_stmt->stmt_location;
189
+ if (raw_stmt->stmt_len == 0)
190
+ result.stmts[foreach_current_index(lc)]->stmt_len = strlen(input) - raw_stmt->stmt_location;
191
+ else
192
+ result.stmts[foreach_current_index(lc)]->stmt_len = raw_stmt->stmt_len;
193
+ }
194
+ }
195
+ else
196
+ {
197
+ result.n_stmts = 0;
198
+ result.stmts = NULL;
199
+ }
200
+
201
+ pg_query_exit_memory_context(ctx);
202
+
203
+ return result;
204
+ }
205
+
206
+ void pg_query_free_split_result(PgQuerySplitResult result)
207
+ {
208
+ if (result.error) {
209
+ pg_query_free_error(result.error);
210
+ }
211
+ free(result.stderr_buffer);
212
+
213
+ if (result.stmts != NULL)
214
+ {
215
+ for (int i = 0; i < result.n_stmts; ++i)
216
+ {
217
+ free(result.stmts[i]);
218
+ }
219
+ free(result.stmts);
220
+ }
221
+ }
@@ -0,0 +1,3660 @@
1
+ /*
2
+ * Copyright (c) 2008-2015, Dave Benson and the protobuf-c authors.
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are
7
+ * met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ *
12
+ * * Redistributions in binary form must reproduce the above
13
+ * copyright notice, this list of conditions and the following disclaimer
14
+ * in the documentation and/or other materials provided with the
15
+ * distribution.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+ /*! \file
31
+ * Support library for `protoc-c` generated code.
32
+ *
33
+ * This file implements the public API used by the code generated
34
+ * by `protoc-c`.
35
+ *
36
+ * \authors Dave Benson and the protobuf-c authors
37
+ *
38
+ * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license.
39
+ */
40
+
41
+ /**
42
+ * \todo 64-BIT OPTIMIZATION: certain implementations use 32-bit math
43
+ * even on 64-bit platforms (uint64_size, uint64_pack, parse_uint64).
44
+ *
45
+ * \todo Use size_t consistently.
46
+ */
47
+
48
+ #include <stdlib.h> /* for malloc, free */
49
+ #include <string.h> /* for strcmp, strlen, memcpy, memmove, memset */
50
+
51
+ #include "protobuf-c.h"
52
+
53
+ #define TRUE 1
54
+ #define FALSE 0
55
+
56
+ #define PROTOBUF_C__ASSERT_NOT_REACHED() assert(0)
57
+
58
+ /* Workaround for Microsoft compilers. */
59
+ #ifdef _MSC_VER
60
+ # define inline __inline
61
+ #endif
62
+
63
+ /**
64
+ * \defgroup internal Internal functions and macros
65
+ *
66
+ * These are not exported by the library but are useful to developers working
67
+ * on `libprotobuf-c` itself.
68
+ */
69
+
70
+ /**
71
+ * \defgroup macros Utility macros for manipulating structures
72
+ *
73
+ * Macros and constants used to manipulate the base "classes" generated by
74
+ * `protobuf-c`. They also define limits and check correctness.
75
+ *
76
+ * \ingroup internal
77
+ * @{
78
+ */
79
+
80
+ /** The maximum length of a 64-bit integer in varint encoding. */
81
+ #define MAX_UINT64_ENCODED_SIZE 10
82
+
83
+ #ifndef PROTOBUF_C_UNPACK_ERROR
84
+ # define PROTOBUF_C_UNPACK_ERROR(...)
85
+ #endif
86
+
87
+ const char protobuf_c_empty_string[] = "";
88
+
89
+ /**
90
+ * Internal `ProtobufCMessage` manipulation macro.
91
+ *
92
+ * Base macro for manipulating a `ProtobufCMessage`. Used by STRUCT_MEMBER() and
93
+ * STRUCT_MEMBER_PTR().
94
+ */
95
+ #define STRUCT_MEMBER_P(struct_p, struct_offset) \
96
+ ((void *) ((uint8_t *) (struct_p) + (struct_offset)))
97
+
98
+ /**
99
+ * Return field in a `ProtobufCMessage` based on offset.
100
+ *
101
+ * Take a pointer to a `ProtobufCMessage` and find the field at the offset.
102
+ * Cast it to the passed type.
103
+ */
104
+ #define STRUCT_MEMBER(member_type, struct_p, struct_offset) \
105
+ (*(member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
106
+
107
+ /**
108
+ * Return field in a `ProtobufCMessage` based on offset.
109
+ *
110
+ * Take a pointer to a `ProtobufCMessage` and find the field at the offset. Cast
111
+ * it to a pointer to the passed type.
112
+ */
113
+ #define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \
114
+ ((member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
115
+
116
+ /* Assertions for magic numbers. */
117
+
118
+ #define ASSERT_IS_ENUM_DESCRIPTOR(desc) \
119
+ assert((desc)->magic == PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC)
120
+
121
+ #define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \
122
+ assert((desc)->magic == PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
123
+
124
+ #define ASSERT_IS_MESSAGE(message) \
125
+ ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor)
126
+
127
+ #define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \
128
+ assert((desc)->magic == PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC)
129
+
130
+ /**@}*/
131
+
132
+ /* --- version --- */
133
+
134
+ const char *
135
+ protobuf_c_version(void)
136
+ {
137
+ return PROTOBUF_C_VERSION;
138
+ }
139
+
140
+ uint32_t
141
+ protobuf_c_version_number(void)
142
+ {
143
+ return PROTOBUF_C_VERSION_NUMBER;
144
+ }
145
+
146
+ /* --- allocator --- */
147
+
148
+ static void *
149
+ system_alloc(void *allocator_data, size_t size)
150
+ {
151
+ return malloc(size);
152
+ }
153
+
154
+ static void
155
+ system_free(void *allocator_data, void *data)
156
+ {
157
+ free(data);
158
+ }
159
+
160
+ static inline void *
161
+ do_alloc(ProtobufCAllocator *allocator, size_t size)
162
+ {
163
+ return allocator->alloc(allocator->allocator_data, size);
164
+ }
165
+
166
+ static inline void
167
+ do_free(ProtobufCAllocator *allocator, void *data)
168
+ {
169
+ if (data != NULL)
170
+ allocator->free(allocator->allocator_data, data);
171
+ }
172
+
173
+ /*
174
+ * This allocator uses the system's malloc() and free(). It is the default
175
+ * allocator used if NULL is passed as the ProtobufCAllocator to an exported
176
+ * function.
177
+ */
178
+ static ProtobufCAllocator protobuf_c__allocator = {
179
+ .alloc = &system_alloc,
180
+ .free = &system_free,
181
+ .allocator_data = NULL,
182
+ };
183
+
184
+ /* === buffer-simple === */
185
+
186
+ void
187
+ protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer,
188
+ size_t len, const uint8_t *data)
189
+ {
190
+ ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer;
191
+ size_t new_len = simp->len + len;
192
+
193
+ if (new_len > simp->alloced) {
194
+ ProtobufCAllocator *allocator = simp->allocator;
195
+ size_t new_alloced = simp->alloced * 2;
196
+ uint8_t *new_data;
197
+
198
+ if (allocator == NULL)
199
+ allocator = &protobuf_c__allocator;
200
+ while (new_alloced < new_len)
201
+ new_alloced += new_alloced;
202
+ new_data = do_alloc(allocator, new_alloced);
203
+ if (!new_data)
204
+ return;
205
+ memcpy(new_data, simp->data, simp->len);
206
+ if (simp->must_free_data)
207
+ do_free(allocator, simp->data);
208
+ else
209
+ simp->must_free_data = TRUE;
210
+ simp->data = new_data;
211
+ simp->alloced = new_alloced;
212
+ }
213
+ memcpy(simp->data + simp->len, data, len);
214
+ simp->len = new_len;
215
+ }
216
+
217
+ /**
218
+ * \defgroup packedsz protobuf_c_message_get_packed_size() implementation
219
+ *
220
+ * Routines mainly used by protobuf_c_message_get_packed_size().
221
+ *
222
+ * \ingroup internal
223
+ * @{
224
+ */
225
+
226
+ /**
227
+ * Return the number of bytes required to store the tag for the field. Includes
228
+ * 3 bits for the wire-type, and a single bit that denotes the end-of-tag.
229
+ *
230
+ * \param number
231
+ * Field tag to encode.
232
+ * \return
233
+ * Number of bytes required.
234
+ */
235
+ static inline size_t
236
+ get_tag_size(uint32_t number)
237
+ {
238
+ if (number < (1UL << 4)) {
239
+ return 1;
240
+ } else if (number < (1UL << 11)) {
241
+ return 2;
242
+ } else if (number < (1UL << 18)) {
243
+ return 3;
244
+ } else if (number < (1UL << 25)) {
245
+ return 4;
246
+ } else {
247
+ return 5;
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Return the number of bytes required to store a variable-length unsigned
253
+ * 32-bit integer in base-128 varint encoding.
254
+ *
255
+ * \param v
256
+ * Value to encode.
257
+ * \return
258
+ * Number of bytes required.
259
+ */
260
+ static inline size_t
261
+ uint32_size(uint32_t v)
262
+ {
263
+ if (v < (1UL << 7)) {
264
+ return 1;
265
+ } else if (v < (1UL << 14)) {
266
+ return 2;
267
+ } else if (v < (1UL << 21)) {
268
+ return 3;
269
+ } else if (v < (1UL << 28)) {
270
+ return 4;
271
+ } else {
272
+ return 5;
273
+ }
274
+ }
275
+
276
+ /**
277
+ * Return the number of bytes required to store a variable-length signed 32-bit
278
+ * integer in base-128 varint encoding.
279
+ *
280
+ * \param v
281
+ * Value to encode.
282
+ * \return
283
+ * Number of bytes required.
284
+ */
285
+ static inline size_t
286
+ int32_size(int32_t v)
287
+ {
288
+ if (v < 0) {
289
+ return 10;
290
+ } else if (v < (1L << 7)) {
291
+ return 1;
292
+ } else if (v < (1L << 14)) {
293
+ return 2;
294
+ } else if (v < (1L << 21)) {
295
+ return 3;
296
+ } else if (v < (1L << 28)) {
297
+ return 4;
298
+ } else {
299
+ return 5;
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Return the ZigZag-encoded 32-bit unsigned integer form of a 32-bit signed
305
+ * integer.
306
+ *
307
+ * \param v
308
+ * Value to encode.
309
+ * \return
310
+ * ZigZag encoded integer.
311
+ */
312
+ static inline uint32_t
313
+ zigzag32(int32_t v)
314
+ {
315
+ // Note: the right-shift must be arithmetic
316
+ // Note: left shift must be unsigned because of overflow
317
+ return ((uint32_t)(v) << 1) ^ (uint32_t)(v >> 31);
318
+ }
319
+
320
+ /**
321
+ * Return the number of bytes required to store a signed 32-bit integer,
322
+ * converted to an unsigned 32-bit integer with ZigZag encoding, using base-128
323
+ * varint encoding.
324
+ *
325
+ * \param v
326
+ * Value to encode.
327
+ * \return
328
+ * Number of bytes required.
329
+ */
330
+ static inline size_t
331
+ sint32_size(int32_t v)
332
+ {
333
+ return uint32_size(zigzag32(v));
334
+ }
335
+
336
+ /**
337
+ * Return the number of bytes required to store a 64-bit unsigned integer in
338
+ * base-128 varint encoding.
339
+ *
340
+ * \param v
341
+ * Value to encode.
342
+ * \return
343
+ * Number of bytes required.
344
+ */
345
+ static inline size_t
346
+ uint64_size(uint64_t v)
347
+ {
348
+ uint32_t upper_v = (uint32_t) (v >> 32);
349
+
350
+ if (upper_v == 0) {
351
+ return uint32_size((uint32_t) v);
352
+ } else if (upper_v < (1UL << 3)) {
353
+ return 5;
354
+ } else if (upper_v < (1UL << 10)) {
355
+ return 6;
356
+ } else if (upper_v < (1UL << 17)) {
357
+ return 7;
358
+ } else if (upper_v < (1UL << 24)) {
359
+ return 8;
360
+ } else if (upper_v < (1UL << 31)) {
361
+ return 9;
362
+ } else {
363
+ return 10;
364
+ }
365
+ }
366
+
367
+ /**
368
+ * Return the ZigZag-encoded 64-bit unsigned integer form of a 64-bit signed
369
+ * integer.
370
+ *
371
+ * \param v
372
+ * Value to encode.
373
+ * \return
374
+ * ZigZag encoded integer.
375
+ */
376
+ static inline uint64_t
377
+ zigzag64(int64_t v)
378
+ {
379
+ // Note: the right-shift must be arithmetic
380
+ // Note: left shift must be unsigned because of overflow
381
+ return ((uint64_t)(v) << 1) ^ (uint64_t)(v >> 63);
382
+ }
383
+
384
+ /**
385
+ * Return the number of bytes required to store a signed 64-bit integer,
386
+ * converted to an unsigned 64-bit integer with ZigZag encoding, using base-128
387
+ * varint encoding.
388
+ *
389
+ * \param v
390
+ * Value to encode.
391
+ * \return
392
+ * Number of bytes required.
393
+ */
394
+ static inline size_t
395
+ sint64_size(int64_t v)
396
+ {
397
+ return uint64_size(zigzag64(v));
398
+ }
399
+
400
+ /**
401
+ * Calculate the serialized size of a single required message field, including
402
+ * the space needed by the preceding tag.
403
+ *
404
+ * \param field
405
+ * Field descriptor for member.
406
+ * \param member
407
+ * Field to encode.
408
+ * \return
409
+ * Number of bytes required.
410
+ */
411
+ static size_t
412
+ required_field_get_packed_size(const ProtobufCFieldDescriptor *field,
413
+ const void *member)
414
+ {
415
+ size_t rv = get_tag_size(field->id);
416
+
417
+ switch (field->type) {
418
+ case PROTOBUF_C_TYPE_SINT32:
419
+ return rv + sint32_size(*(const int32_t *) member);
420
+ case PROTOBUF_C_TYPE_ENUM:
421
+ case PROTOBUF_C_TYPE_INT32:
422
+ return rv + int32_size(*(const int32_t *) member);
423
+ case PROTOBUF_C_TYPE_UINT32:
424
+ return rv + uint32_size(*(const uint32_t *) member);
425
+ case PROTOBUF_C_TYPE_SINT64:
426
+ return rv + sint64_size(*(const int64_t *) member);
427
+ case PROTOBUF_C_TYPE_INT64:
428
+ case PROTOBUF_C_TYPE_UINT64:
429
+ return rv + uint64_size(*(const uint64_t *) member);
430
+ case PROTOBUF_C_TYPE_SFIXED32:
431
+ case PROTOBUF_C_TYPE_FIXED32:
432
+ return rv + 4;
433
+ case PROTOBUF_C_TYPE_SFIXED64:
434
+ case PROTOBUF_C_TYPE_FIXED64:
435
+ return rv + 8;
436
+ case PROTOBUF_C_TYPE_BOOL:
437
+ return rv + 1;
438
+ case PROTOBUF_C_TYPE_FLOAT:
439
+ return rv + 4;
440
+ case PROTOBUF_C_TYPE_DOUBLE:
441
+ return rv + 8;
442
+ case PROTOBUF_C_TYPE_STRING: {
443
+ const char *str = *(char * const *) member;
444
+ size_t len = str ? strlen(str) : 0;
445
+ return rv + uint32_size(len) + len;
446
+ }
447
+ case PROTOBUF_C_TYPE_BYTES: {
448
+ size_t len = ((const ProtobufCBinaryData *) member)->len;
449
+ return rv + uint32_size(len) + len;
450
+ }
451
+ case PROTOBUF_C_TYPE_MESSAGE: {
452
+ const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
453
+ size_t subrv = msg ? protobuf_c_message_get_packed_size(msg) : 0;
454
+ return rv + uint32_size(subrv) + subrv;
455
+ }
456
+ }
457
+ PROTOBUF_C__ASSERT_NOT_REACHED();
458
+ return 0;
459
+ }
460
+
461
+ /**
462
+ * Calculate the serialized size of a single oneof message field, including
463
+ * the space needed by the preceding tag. Returns 0 if the oneof field isn't
464
+ * selected or is not set.
465
+ *
466
+ * \param field
467
+ * Field descriptor for member.
468
+ * \param oneof_case
469
+ * Enum value that selects the field in the oneof.
470
+ * \param member
471
+ * Field to encode.
472
+ * \return
473
+ * Number of bytes required.
474
+ */
475
+ static size_t
476
+ oneof_field_get_packed_size(const ProtobufCFieldDescriptor *field,
477
+ uint32_t oneof_case,
478
+ const void *member)
479
+ {
480
+ if (oneof_case != field->id) {
481
+ return 0;
482
+ }
483
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
484
+ field->type == PROTOBUF_C_TYPE_STRING)
485
+ {
486
+ const void *ptr = *(const void * const *) member;
487
+ if (ptr == NULL || ptr == field->default_value)
488
+ return 0;
489
+ }
490
+ return required_field_get_packed_size(field, member);
491
+ }
492
+
493
+ /**
494
+ * Calculate the serialized size of a single optional message field, including
495
+ * the space needed by the preceding tag. Returns 0 if the optional field isn't
496
+ * set.
497
+ *
498
+ * \param field
499
+ * Field descriptor for member.
500
+ * \param has
501
+ * True if the field exists, false if not.
502
+ * \param member
503
+ * Field to encode.
504
+ * \return
505
+ * Number of bytes required.
506
+ */
507
+ static size_t
508
+ optional_field_get_packed_size(const ProtobufCFieldDescriptor *field,
509
+ const protobuf_c_boolean has,
510
+ const void *member)
511
+ {
512
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
513
+ field->type == PROTOBUF_C_TYPE_STRING)
514
+ {
515
+ const void *ptr = *(const void * const *) member;
516
+ if (ptr == NULL || ptr == field->default_value)
517
+ return 0;
518
+ } else {
519
+ if (!has)
520
+ return 0;
521
+ }
522
+ return required_field_get_packed_size(field, member);
523
+ }
524
+
525
+ static protobuf_c_boolean
526
+ field_is_zeroish(const ProtobufCFieldDescriptor *field,
527
+ const void *member)
528
+ {
529
+ protobuf_c_boolean ret = FALSE;
530
+
531
+ switch (field->type) {
532
+ case PROTOBUF_C_TYPE_BOOL:
533
+ ret = (0 == *(const protobuf_c_boolean *) member);
534
+ break;
535
+ case PROTOBUF_C_TYPE_ENUM:
536
+ case PROTOBUF_C_TYPE_SINT32:
537
+ case PROTOBUF_C_TYPE_INT32:
538
+ case PROTOBUF_C_TYPE_UINT32:
539
+ case PROTOBUF_C_TYPE_SFIXED32:
540
+ case PROTOBUF_C_TYPE_FIXED32:
541
+ ret = (0 == *(const uint32_t *) member);
542
+ break;
543
+ case PROTOBUF_C_TYPE_SINT64:
544
+ case PROTOBUF_C_TYPE_INT64:
545
+ case PROTOBUF_C_TYPE_UINT64:
546
+ case PROTOBUF_C_TYPE_SFIXED64:
547
+ case PROTOBUF_C_TYPE_FIXED64:
548
+ ret = (0 == *(const uint64_t *) member);
549
+ break;
550
+ case PROTOBUF_C_TYPE_FLOAT:
551
+ ret = (0 == *(const float *) member);
552
+ break;
553
+ case PROTOBUF_C_TYPE_DOUBLE:
554
+ ret = (0 == *(const double *) member);
555
+ break;
556
+ case PROTOBUF_C_TYPE_STRING:
557
+ ret = (NULL == *(const char * const *) member) ||
558
+ ('\0' == **(const char * const *) member);
559
+ break;
560
+ case PROTOBUF_C_TYPE_BYTES:
561
+ case PROTOBUF_C_TYPE_MESSAGE:
562
+ ret = (NULL == *(const void * const *) member);
563
+ break;
564
+ default:
565
+ ret = TRUE;
566
+ break;
567
+ }
568
+
569
+ return ret;
570
+ }
571
+
572
+ /**
573
+ * Calculate the serialized size of a single unlabeled message field, including
574
+ * the space needed by the preceding tag. Returns 0 if the field isn't set or
575
+ * if it is set to a "zeroish" value (null pointer or 0 for numerical values).
576
+ * Unlabeled fields are supported only in proto3.
577
+ *
578
+ * \param field
579
+ * Field descriptor for member.
580
+ * \param member
581
+ * Field to encode.
582
+ * \return
583
+ * Number of bytes required.
584
+ */
585
+ static size_t
586
+ unlabeled_field_get_packed_size(const ProtobufCFieldDescriptor *field,
587
+ const void *member)
588
+ {
589
+ if (field_is_zeroish(field, member))
590
+ return 0;
591
+ return required_field_get_packed_size(field, member);
592
+ }
593
+
594
+ /**
595
+ * Calculate the serialized size of repeated message fields, which may consist
596
+ * of any number of values (including 0). Includes the space needed by the
597
+ * preceding tags (as needed).
598
+ *
599
+ * \param field
600
+ * Field descriptor for member.
601
+ * \param count
602
+ * Number of repeated field members.
603
+ * \param member
604
+ * Field to encode.
605
+ * \return
606
+ * Number of bytes required.
607
+ */
608
+ static size_t
609
+ repeated_field_get_packed_size(const ProtobufCFieldDescriptor *field,
610
+ size_t count, const void *member)
611
+ {
612
+ size_t header_size;
613
+ size_t rv = 0;
614
+ unsigned i;
615
+ void *array = *(void * const *) member;
616
+
617
+ if (count == 0)
618
+ return 0;
619
+ header_size = get_tag_size(field->id);
620
+ if (0 == (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
621
+ header_size *= count;
622
+
623
+ switch (field->type) {
624
+ case PROTOBUF_C_TYPE_SINT32:
625
+ for (i = 0; i < count; i++)
626
+ rv += sint32_size(((int32_t *) array)[i]);
627
+ break;
628
+ case PROTOBUF_C_TYPE_ENUM:
629
+ case PROTOBUF_C_TYPE_INT32:
630
+ for (i = 0; i < count; i++)
631
+ rv += int32_size(((int32_t *) array)[i]);
632
+ break;
633
+ case PROTOBUF_C_TYPE_UINT32:
634
+ for (i = 0; i < count; i++)
635
+ rv += uint32_size(((uint32_t *) array)[i]);
636
+ break;
637
+ case PROTOBUF_C_TYPE_SINT64:
638
+ for (i = 0; i < count; i++)
639
+ rv += sint64_size(((int64_t *) array)[i]);
640
+ break;
641
+ case PROTOBUF_C_TYPE_INT64:
642
+ case PROTOBUF_C_TYPE_UINT64:
643
+ for (i = 0; i < count; i++)
644
+ rv += uint64_size(((uint64_t *) array)[i]);
645
+ break;
646
+ case PROTOBUF_C_TYPE_SFIXED32:
647
+ case PROTOBUF_C_TYPE_FIXED32:
648
+ case PROTOBUF_C_TYPE_FLOAT:
649
+ rv += 4 * count;
650
+ break;
651
+ case PROTOBUF_C_TYPE_SFIXED64:
652
+ case PROTOBUF_C_TYPE_FIXED64:
653
+ case PROTOBUF_C_TYPE_DOUBLE:
654
+ rv += 8 * count;
655
+ break;
656
+ case PROTOBUF_C_TYPE_BOOL:
657
+ rv += count;
658
+ break;
659
+ case PROTOBUF_C_TYPE_STRING:
660
+ for (i = 0; i < count; i++) {
661
+ size_t len = strlen(((char **) array)[i]);
662
+ rv += uint32_size(len) + len;
663
+ }
664
+ break;
665
+ case PROTOBUF_C_TYPE_BYTES:
666
+ for (i = 0; i < count; i++) {
667
+ size_t len = ((ProtobufCBinaryData *) array)[i].len;
668
+ rv += uint32_size(len) + len;
669
+ }
670
+ break;
671
+ case PROTOBUF_C_TYPE_MESSAGE:
672
+ for (i = 0; i < count; i++) {
673
+ size_t len = protobuf_c_message_get_packed_size(
674
+ ((ProtobufCMessage **) array)[i]);
675
+ rv += uint32_size(len) + len;
676
+ }
677
+ break;
678
+ }
679
+
680
+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
681
+ header_size += uint32_size(rv);
682
+ return header_size + rv;
683
+ }
684
+
685
+ /**
686
+ * Calculate the serialized size of an unknown field, i.e. one that is passed
687
+ * through mostly uninterpreted. This is required for forward compatibility if
688
+ * new fields are added to the message descriptor.
689
+ *
690
+ * \param field
691
+ * Unknown field type.
692
+ * \return
693
+ * Number of bytes required.
694
+ */
695
+ static inline size_t
696
+ unknown_field_get_packed_size(const ProtobufCMessageUnknownField *field)
697
+ {
698
+ return get_tag_size(field->tag) + field->len;
699
+ }
700
+
701
+ /**@}*/
702
+
703
+ /*
704
+ * Calculate the serialized size of the message.
705
+ */
706
+ size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message)
707
+ {
708
+ unsigned i;
709
+ size_t rv = 0;
710
+
711
+ ASSERT_IS_MESSAGE(message);
712
+ for (i = 0; i < message->descriptor->n_fields; i++) {
713
+ const ProtobufCFieldDescriptor *field =
714
+ message->descriptor->fields + i;
715
+ const void *member =
716
+ ((const char *) message) + field->offset;
717
+ const void *qmember =
718
+ ((const char *) message) + field->quantifier_offset;
719
+
720
+ if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
721
+ rv += required_field_get_packed_size(field, member);
722
+ } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
723
+ field->label == PROTOBUF_C_LABEL_NONE) &&
724
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
725
+ rv += oneof_field_get_packed_size(
726
+ field,
727
+ *(const uint32_t *) qmember,
728
+ member
729
+ );
730
+ } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
731
+ rv += optional_field_get_packed_size(
732
+ field,
733
+ *(protobuf_c_boolean *) qmember,
734
+ member
735
+ );
736
+ } else if (field->label == PROTOBUF_C_LABEL_NONE) {
737
+ rv += unlabeled_field_get_packed_size(
738
+ field,
739
+ member
740
+ );
741
+ } else {
742
+ rv += repeated_field_get_packed_size(
743
+ field,
744
+ *(const size_t *) qmember,
745
+ member
746
+ );
747
+ }
748
+ }
749
+ for (i = 0; i < message->n_unknown_fields; i++)
750
+ rv += unknown_field_get_packed_size(&message->unknown_fields[i]);
751
+ return rv;
752
+ }
753
+
754
+ /**
755
+ * \defgroup pack protobuf_c_message_pack() implementation
756
+ *
757
+ * Routines mainly used by protobuf_c_message_pack().
758
+ *
759
+ * \ingroup internal
760
+ * @{
761
+ */
762
+
763
+ /**
764
+ * Pack an unsigned 32-bit integer in base-128 varint encoding and return the
765
+ * number of bytes written, which must be 5 or less.
766
+ *
767
+ * \param value
768
+ * Value to encode.
769
+ * \param[out] out
770
+ * Packed value.
771
+ * \return
772
+ * Number of bytes written to `out`.
773
+ */
774
+ static inline size_t
775
+ uint32_pack(uint32_t value, uint8_t *out)
776
+ {
777
+ unsigned rv = 0;
778
+
779
+ if (value >= 0x80) {
780
+ out[rv++] = value | 0x80;
781
+ value >>= 7;
782
+ if (value >= 0x80) {
783
+ out[rv++] = value | 0x80;
784
+ value >>= 7;
785
+ if (value >= 0x80) {
786
+ out[rv++] = value | 0x80;
787
+ value >>= 7;
788
+ if (value >= 0x80) {
789
+ out[rv++] = value | 0x80;
790
+ value >>= 7;
791
+ }
792
+ }
793
+ }
794
+ }
795
+ /* assert: value<128 */
796
+ out[rv++] = value;
797
+ return rv;
798
+ }
799
+
800
+ /**
801
+ * Pack a signed 32-bit integer and return the number of bytes written.
802
+ * Negative numbers are encoded as two's complement 64-bit integers.
803
+ *
804
+ * \param value
805
+ * Value to encode.
806
+ * \param[out] out
807
+ * Packed value.
808
+ * \return
809
+ * Number of bytes written to `out`.
810
+ */
811
+ static inline size_t
812
+ int32_pack(int32_t value, uint8_t *out)
813
+ {
814
+ if (value < 0) {
815
+ out[0] = value | 0x80;
816
+ out[1] = (value >> 7) | 0x80;
817
+ out[2] = (value >> 14) | 0x80;
818
+ out[3] = (value >> 21) | 0x80;
819
+ out[4] = (value >> 28) | 0x80;
820
+ out[5] = out[6] = out[7] = out[8] = 0xff;
821
+ out[9] = 0x01;
822
+ return 10;
823
+ } else {
824
+ return uint32_pack(value, out);
825
+ }
826
+ }
827
+
828
+ /**
829
+ * Pack a signed 32-bit integer using ZigZag encoding and return the number of
830
+ * bytes written.
831
+ *
832
+ * \param value
833
+ * Value to encode.
834
+ * \param[out] out
835
+ * Packed value.
836
+ * \return
837
+ * Number of bytes written to `out`.
838
+ */
839
+ static inline size_t
840
+ sint32_pack(int32_t value, uint8_t *out)
841
+ {
842
+ return uint32_pack(zigzag32(value), out);
843
+ }
844
+
845
+ /**
846
+ * Pack a 64-bit unsigned integer using base-128 varint encoding and return the
847
+ * number of bytes written.
848
+ *
849
+ * \param value
850
+ * Value to encode.
851
+ * \param[out] out
852
+ * Packed value.
853
+ * \return
854
+ * Number of bytes written to `out`.
855
+ */
856
+ static size_t
857
+ uint64_pack(uint64_t value, uint8_t *out)
858
+ {
859
+ uint32_t hi = (uint32_t) (value >> 32);
860
+ uint32_t lo = (uint32_t) value;
861
+ unsigned rv;
862
+
863
+ if (hi == 0)
864
+ return uint32_pack((uint32_t) lo, out);
865
+ out[0] = (lo) | 0x80;
866
+ out[1] = (lo >> 7) | 0x80;
867
+ out[2] = (lo >> 14) | 0x80;
868
+ out[3] = (lo >> 21) | 0x80;
869
+ if (hi < 8) {
870
+ out[4] = (hi << 4) | (lo >> 28);
871
+ return 5;
872
+ } else {
873
+ out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80;
874
+ hi >>= 3;
875
+ }
876
+ rv = 5;
877
+ while (hi >= 128) {
878
+ out[rv++] = hi | 0x80;
879
+ hi >>= 7;
880
+ }
881
+ out[rv++] = hi;
882
+ return rv;
883
+ }
884
+
885
+ /**
886
+ * Pack a 64-bit signed integer in ZigZag encoding and return the number of
887
+ * bytes written.
888
+ *
889
+ * \param value
890
+ * Value to encode.
891
+ * \param[out] out
892
+ * Packed value.
893
+ * \return
894
+ * Number of bytes written to `out`.
895
+ */
896
+ static inline size_t
897
+ sint64_pack(int64_t value, uint8_t *out)
898
+ {
899
+ return uint64_pack(zigzag64(value), out);
900
+ }
901
+
902
+ /**
903
+ * Pack a 32-bit quantity in little-endian byte order. Used for protobuf wire
904
+ * types fixed32, sfixed32, float. Similar to "htole32".
905
+ *
906
+ * \param value
907
+ * Value to encode.
908
+ * \param[out] out
909
+ * Packed value.
910
+ * \return
911
+ * Number of bytes written to `out`.
912
+ */
913
+ static inline size_t
914
+ fixed32_pack(uint32_t value, void *out)
915
+ {
916
+ #if !defined(WORDS_BIGENDIAN)
917
+ memcpy(out, &value, 4);
918
+ #else
919
+ uint8_t *buf = out;
920
+
921
+ buf[0] = value;
922
+ buf[1] = value >> 8;
923
+ buf[2] = value >> 16;
924
+ buf[3] = value >> 24;
925
+ #endif
926
+ return 4;
927
+ }
928
+
929
+ /**
930
+ * Pack a 64-bit quantity in little-endian byte order. Used for protobuf wire
931
+ * types fixed64, sfixed64, double. Similar to "htole64".
932
+ *
933
+ * \todo The big-endian impl is really only good for 32-bit machines, a 64-bit
934
+ * version would be appreciated, plus a way to decide to use 64-bit math where
935
+ * convenient.
936
+ *
937
+ * \param value
938
+ * Value to encode.
939
+ * \param[out] out
940
+ * Packed value.
941
+ * \return
942
+ * Number of bytes written to `out`.
943
+ */
944
+ static inline size_t
945
+ fixed64_pack(uint64_t value, void *out)
946
+ {
947
+ #if !defined(WORDS_BIGENDIAN)
948
+ memcpy(out, &value, 8);
949
+ #else
950
+ fixed32_pack(value, out);
951
+ fixed32_pack(value >> 32, ((char *) out) + 4);
952
+ #endif
953
+ return 8;
954
+ }
955
+
956
+ /**
957
+ * Pack a boolean value as an integer and return the number of bytes written.
958
+ *
959
+ * \todo Perhaps on some platforms *out = !!value would be a better impl, b/c
960
+ * that is idiomatic C++ in some STL implementations.
961
+ *
962
+ * \param value
963
+ * Value to encode.
964
+ * \param[out] out
965
+ * Packed value.
966
+ * \return
967
+ * Number of bytes written to `out`.
968
+ */
969
+ static inline size_t
970
+ boolean_pack(protobuf_c_boolean value, uint8_t *out)
971
+ {
972
+ *out = value ? TRUE : FALSE;
973
+ return 1;
974
+ }
975
+
976
+ /**
977
+ * Pack a NUL-terminated C string and return the number of bytes written. The
978
+ * output includes a length delimiter.
979
+ *
980
+ * The NULL pointer is treated as an empty string. This isn't really necessary,
981
+ * but it allows people to leave required strings blank. (See Issue #13 in the
982
+ * bug tracker for a little more explanation).
983
+ *
984
+ * \param str
985
+ * String to encode.
986
+ * \param[out] out
987
+ * Packed value.
988
+ * \return
989
+ * Number of bytes written to `out`.
990
+ */
991
+ static inline size_t
992
+ string_pack(const char *str, uint8_t *out)
993
+ {
994
+ if (str == NULL) {
995
+ out[0] = 0;
996
+ return 1;
997
+ } else {
998
+ size_t len = strlen(str);
999
+ size_t rv = uint32_pack(len, out);
1000
+ memcpy(out + rv, str, len);
1001
+ return rv + len;
1002
+ }
1003
+ }
1004
+
1005
+ /**
1006
+ * Pack a ProtobufCBinaryData and return the number of bytes written. The output
1007
+ * includes a length delimiter.
1008
+ *
1009
+ * \param bd
1010
+ * ProtobufCBinaryData to encode.
1011
+ * \param[out] out
1012
+ * Packed value.
1013
+ * \return
1014
+ * Number of bytes written to `out`.
1015
+ */
1016
+ static inline size_t
1017
+ binary_data_pack(const ProtobufCBinaryData *bd, uint8_t *out)
1018
+ {
1019
+ size_t len = bd->len;
1020
+ size_t rv = uint32_pack(len, out);
1021
+ memcpy(out + rv, bd->data, len);
1022
+ return rv + len;
1023
+ }
1024
+
1025
+ /**
1026
+ * Pack a ProtobufCMessage and return the number of bytes written. The output
1027
+ * includes a length delimiter.
1028
+ *
1029
+ * \param message
1030
+ * ProtobufCMessage object to pack.
1031
+ * \param[out] out
1032
+ * Packed message.
1033
+ * \return
1034
+ * Number of bytes written to `out`.
1035
+ */
1036
+ static inline size_t
1037
+ prefixed_message_pack(const ProtobufCMessage *message, uint8_t *out)
1038
+ {
1039
+ if (message == NULL) {
1040
+ out[0] = 0;
1041
+ return 1;
1042
+ } else {
1043
+ size_t rv = protobuf_c_message_pack(message, out + 1);
1044
+ uint32_t rv_packed_size = uint32_size(rv);
1045
+ if (rv_packed_size != 1)
1046
+ memmove(out + rv_packed_size, out + 1, rv);
1047
+ return uint32_pack(rv, out) + rv;
1048
+ }
1049
+ }
1050
+
1051
+ /**
1052
+ * Pack a field tag.
1053
+ *
1054
+ * Wire-type will be added in required_field_pack().
1055
+ *
1056
+ * \todo Just call uint64_pack on 64-bit platforms.
1057
+ *
1058
+ * \param id
1059
+ * Tag value to encode.
1060
+ * \param[out] out
1061
+ * Packed value.
1062
+ * \return
1063
+ * Number of bytes written to `out`.
1064
+ */
1065
+ static size_t
1066
+ tag_pack(uint32_t id, uint8_t *out)
1067
+ {
1068
+ if (id < (1UL << (32 - 3)))
1069
+ return uint32_pack(id << 3, out);
1070
+ else
1071
+ return uint64_pack(((uint64_t) id) << 3, out);
1072
+ }
1073
+
1074
+ /**
1075
+ * Pack a required field and return the number of bytes written.
1076
+ *
1077
+ * \param field
1078
+ * Field descriptor.
1079
+ * \param member
1080
+ * The field member.
1081
+ * \param[out] out
1082
+ * Packed value.
1083
+ * \return
1084
+ * Number of bytes written to `out`.
1085
+ */
1086
+ static size_t
1087
+ required_field_pack(const ProtobufCFieldDescriptor *field,
1088
+ const void *member, uint8_t *out)
1089
+ {
1090
+ size_t rv = tag_pack(field->id, out);
1091
+
1092
+ switch (field->type) {
1093
+ case PROTOBUF_C_TYPE_SINT32:
1094
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1095
+ return rv + sint32_pack(*(const int32_t *) member, out + rv);
1096
+ case PROTOBUF_C_TYPE_ENUM:
1097
+ case PROTOBUF_C_TYPE_INT32:
1098
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1099
+ return rv + int32_pack(*(const int32_t *) member, out + rv);
1100
+ case PROTOBUF_C_TYPE_UINT32:
1101
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1102
+ return rv + uint32_pack(*(const uint32_t *) member, out + rv);
1103
+ case PROTOBUF_C_TYPE_SINT64:
1104
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1105
+ return rv + sint64_pack(*(const int64_t *) member, out + rv);
1106
+ case PROTOBUF_C_TYPE_INT64:
1107
+ case PROTOBUF_C_TYPE_UINT64:
1108
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1109
+ return rv + uint64_pack(*(const uint64_t *) member, out + rv);
1110
+ case PROTOBUF_C_TYPE_SFIXED32:
1111
+ case PROTOBUF_C_TYPE_FIXED32:
1112
+ case PROTOBUF_C_TYPE_FLOAT:
1113
+ out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
1114
+ return rv + fixed32_pack(*(const uint32_t *) member, out + rv);
1115
+ case PROTOBUF_C_TYPE_SFIXED64:
1116
+ case PROTOBUF_C_TYPE_FIXED64:
1117
+ case PROTOBUF_C_TYPE_DOUBLE:
1118
+ out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
1119
+ return rv + fixed64_pack(*(const uint64_t *) member, out + rv);
1120
+ case PROTOBUF_C_TYPE_BOOL:
1121
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1122
+ return rv + boolean_pack(*(const protobuf_c_boolean *) member, out + rv);
1123
+ case PROTOBUF_C_TYPE_STRING:
1124
+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1125
+ return rv + string_pack(*(char *const *) member, out + rv);
1126
+ case PROTOBUF_C_TYPE_BYTES:
1127
+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1128
+ return rv + binary_data_pack((const ProtobufCBinaryData *) member, out + rv);
1129
+ case PROTOBUF_C_TYPE_MESSAGE:
1130
+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1131
+ return rv + prefixed_message_pack(*(ProtobufCMessage * const *) member, out + rv);
1132
+ }
1133
+ PROTOBUF_C__ASSERT_NOT_REACHED();
1134
+ return 0;
1135
+ }
1136
+
1137
+ /**
1138
+ * Pack a oneof field and return the number of bytes written. Only packs the
1139
+ * field that is selected by the case enum.
1140
+ *
1141
+ * \param field
1142
+ * Field descriptor.
1143
+ * \param oneof_case
1144
+ * Enum value that selects the field in the oneof.
1145
+ * \param member
1146
+ * The field member.
1147
+ * \param[out] out
1148
+ * Packed value.
1149
+ * \return
1150
+ * Number of bytes written to `out`.
1151
+ */
1152
+ static size_t
1153
+ oneof_field_pack(const ProtobufCFieldDescriptor *field,
1154
+ uint32_t oneof_case,
1155
+ const void *member, uint8_t *out)
1156
+ {
1157
+ if (oneof_case != field->id) {
1158
+ return 0;
1159
+ }
1160
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1161
+ field->type == PROTOBUF_C_TYPE_STRING)
1162
+ {
1163
+ const void *ptr = *(const void * const *) member;
1164
+ if (ptr == NULL || ptr == field->default_value)
1165
+ return 0;
1166
+ }
1167
+ return required_field_pack(field, member, out);
1168
+ }
1169
+
1170
+ /**
1171
+ * Pack an optional field and return the number of bytes written.
1172
+ *
1173
+ * \param field
1174
+ * Field descriptor.
1175
+ * \param has
1176
+ * Whether the field is set.
1177
+ * \param member
1178
+ * The field member.
1179
+ * \param[out] out
1180
+ * Packed value.
1181
+ * \return
1182
+ * Number of bytes written to `out`.
1183
+ */
1184
+ static size_t
1185
+ optional_field_pack(const ProtobufCFieldDescriptor *field,
1186
+ const protobuf_c_boolean has,
1187
+ const void *member, uint8_t *out)
1188
+ {
1189
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1190
+ field->type == PROTOBUF_C_TYPE_STRING)
1191
+ {
1192
+ const void *ptr = *(const void * const *) member;
1193
+ if (ptr == NULL || ptr == field->default_value)
1194
+ return 0;
1195
+ } else {
1196
+ if (!has)
1197
+ return 0;
1198
+ }
1199
+ return required_field_pack(field, member, out);
1200
+ }
1201
+
1202
+ /**
1203
+ * Pack an unlabeled field and return the number of bytes written.
1204
+ *
1205
+ * \param field
1206
+ * Field descriptor.
1207
+ * \param member
1208
+ * The field member.
1209
+ * \param[out] out
1210
+ * Packed value.
1211
+ * \return
1212
+ * Number of bytes written to `out`.
1213
+ */
1214
+ static size_t
1215
+ unlabeled_field_pack(const ProtobufCFieldDescriptor *field,
1216
+ const void *member, uint8_t *out)
1217
+ {
1218
+ if (field_is_zeroish(field, member))
1219
+ return 0;
1220
+ return required_field_pack(field, member, out);
1221
+ }
1222
+
1223
+ /**
1224
+ * Given a field type, return the in-memory size.
1225
+ *
1226
+ * \todo Implement as a table lookup.
1227
+ *
1228
+ * \param type
1229
+ * Field type.
1230
+ * \return
1231
+ * Size of the field.
1232
+ */
1233
+ static inline size_t
1234
+ sizeof_elt_in_repeated_array(ProtobufCType type)
1235
+ {
1236
+ switch (type) {
1237
+ case PROTOBUF_C_TYPE_SINT32:
1238
+ case PROTOBUF_C_TYPE_INT32:
1239
+ case PROTOBUF_C_TYPE_UINT32:
1240
+ case PROTOBUF_C_TYPE_SFIXED32:
1241
+ case PROTOBUF_C_TYPE_FIXED32:
1242
+ case PROTOBUF_C_TYPE_FLOAT:
1243
+ case PROTOBUF_C_TYPE_ENUM:
1244
+ return 4;
1245
+ case PROTOBUF_C_TYPE_SINT64:
1246
+ case PROTOBUF_C_TYPE_INT64:
1247
+ case PROTOBUF_C_TYPE_UINT64:
1248
+ case PROTOBUF_C_TYPE_SFIXED64:
1249
+ case PROTOBUF_C_TYPE_FIXED64:
1250
+ case PROTOBUF_C_TYPE_DOUBLE:
1251
+ return 8;
1252
+ case PROTOBUF_C_TYPE_BOOL:
1253
+ return sizeof(protobuf_c_boolean);
1254
+ case PROTOBUF_C_TYPE_STRING:
1255
+ case PROTOBUF_C_TYPE_MESSAGE:
1256
+ return sizeof(void *);
1257
+ case PROTOBUF_C_TYPE_BYTES:
1258
+ return sizeof(ProtobufCBinaryData);
1259
+ }
1260
+ PROTOBUF_C__ASSERT_NOT_REACHED();
1261
+ return 0;
1262
+ }
1263
+
1264
+ /**
1265
+ * Pack an array of 32-bit quantities.
1266
+ *
1267
+ * \param[out] out
1268
+ * Destination.
1269
+ * \param[in] in
1270
+ * Source.
1271
+ * \param[in] n
1272
+ * Number of elements in the source array.
1273
+ */
1274
+ static void
1275
+ copy_to_little_endian_32(void *out, const void *in, const unsigned n)
1276
+ {
1277
+ #if !defined(WORDS_BIGENDIAN)
1278
+ memcpy(out, in, n * 4);
1279
+ #else
1280
+ unsigned i;
1281
+ const uint32_t *ini = in;
1282
+ for (i = 0; i < n; i++)
1283
+ fixed32_pack(ini[i], (uint32_t *) out + i);
1284
+ #endif
1285
+ }
1286
+
1287
+ /**
1288
+ * Pack an array of 64-bit quantities.
1289
+ *
1290
+ * \param[out] out
1291
+ * Destination.
1292
+ * \param[in] in
1293
+ * Source.
1294
+ * \param[in] n
1295
+ * Number of elements in the source array.
1296
+ */
1297
+ static void
1298
+ copy_to_little_endian_64(void *out, const void *in, const unsigned n)
1299
+ {
1300
+ #if !defined(WORDS_BIGENDIAN)
1301
+ memcpy(out, in, n * 8);
1302
+ #else
1303
+ unsigned i;
1304
+ const uint64_t *ini = in;
1305
+ for (i = 0; i < n; i++)
1306
+ fixed64_pack(ini[i], (uint64_t *) out + i);
1307
+ #endif
1308
+ }
1309
+
1310
+ /**
1311
+ * Get the minimum number of bytes required to pack a field value of a
1312
+ * particular type.
1313
+ *
1314
+ * \param type
1315
+ * Field type.
1316
+ * \return
1317
+ * Number of bytes.
1318
+ */
1319
+ static unsigned
1320
+ get_type_min_size(ProtobufCType type)
1321
+ {
1322
+ if (type == PROTOBUF_C_TYPE_SFIXED32 ||
1323
+ type == PROTOBUF_C_TYPE_FIXED32 ||
1324
+ type == PROTOBUF_C_TYPE_FLOAT)
1325
+ {
1326
+ return 4;
1327
+ }
1328
+ if (type == PROTOBUF_C_TYPE_SFIXED64 ||
1329
+ type == PROTOBUF_C_TYPE_FIXED64 ||
1330
+ type == PROTOBUF_C_TYPE_DOUBLE)
1331
+ {
1332
+ return 8;
1333
+ }
1334
+ return 1;
1335
+ }
1336
+
1337
+ /**
1338
+ * Packs the elements of a repeated field and returns the serialised field and
1339
+ * its length.
1340
+ *
1341
+ * \param field
1342
+ * Field descriptor.
1343
+ * \param count
1344
+ * Number of elements in the repeated field array.
1345
+ * \param member
1346
+ * Pointer to the elements for this repeated field.
1347
+ * \param[out] out
1348
+ * Serialised representation of the repeated field.
1349
+ * \return
1350
+ * Number of bytes serialised to `out`.
1351
+ */
1352
+ static size_t
1353
+ repeated_field_pack(const ProtobufCFieldDescriptor *field,
1354
+ size_t count, const void *member, uint8_t *out)
1355
+ {
1356
+ void *array = *(void * const *) member;
1357
+ unsigned i;
1358
+
1359
+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
1360
+ unsigned header_len;
1361
+ unsigned len_start;
1362
+ unsigned min_length;
1363
+ unsigned payload_len;
1364
+ unsigned length_size_min;
1365
+ unsigned actual_length_size;
1366
+ uint8_t *payload_at;
1367
+
1368
+ if (count == 0)
1369
+ return 0;
1370
+ header_len = tag_pack(field->id, out);
1371
+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1372
+ len_start = header_len;
1373
+ min_length = get_type_min_size(field->type) * count;
1374
+ length_size_min = uint32_size(min_length);
1375
+ header_len += length_size_min;
1376
+ payload_at = out + header_len;
1377
+
1378
+ switch (field->type) {
1379
+ case PROTOBUF_C_TYPE_SFIXED32:
1380
+ case PROTOBUF_C_TYPE_FIXED32:
1381
+ case PROTOBUF_C_TYPE_FLOAT:
1382
+ copy_to_little_endian_32(payload_at, array, count);
1383
+ payload_at += count * 4;
1384
+ break;
1385
+ case PROTOBUF_C_TYPE_SFIXED64:
1386
+ case PROTOBUF_C_TYPE_FIXED64:
1387
+ case PROTOBUF_C_TYPE_DOUBLE:
1388
+ copy_to_little_endian_64(payload_at, array, count);
1389
+ payload_at += count * 8;
1390
+ break;
1391
+ case PROTOBUF_C_TYPE_ENUM:
1392
+ case PROTOBUF_C_TYPE_INT32: {
1393
+ const int32_t *arr = (const int32_t *) array;
1394
+ for (i = 0; i < count; i++)
1395
+ payload_at += int32_pack(arr[i], payload_at);
1396
+ break;
1397
+ }
1398
+ case PROTOBUF_C_TYPE_SINT32: {
1399
+ const int32_t *arr = (const int32_t *) array;
1400
+ for (i = 0; i < count; i++)
1401
+ payload_at += sint32_pack(arr[i], payload_at);
1402
+ break;
1403
+ }
1404
+ case PROTOBUF_C_TYPE_SINT64: {
1405
+ const int64_t *arr = (const int64_t *) array;
1406
+ for (i = 0; i < count; i++)
1407
+ payload_at += sint64_pack(arr[i], payload_at);
1408
+ break;
1409
+ }
1410
+ case PROTOBUF_C_TYPE_UINT32: {
1411
+ const uint32_t *arr = (const uint32_t *) array;
1412
+ for (i = 0; i < count; i++)
1413
+ payload_at += uint32_pack(arr[i], payload_at);
1414
+ break;
1415
+ }
1416
+ case PROTOBUF_C_TYPE_INT64:
1417
+ case PROTOBUF_C_TYPE_UINT64: {
1418
+ const uint64_t *arr = (const uint64_t *) array;
1419
+ for (i = 0; i < count; i++)
1420
+ payload_at += uint64_pack(arr[i], payload_at);
1421
+ break;
1422
+ }
1423
+ case PROTOBUF_C_TYPE_BOOL: {
1424
+ const protobuf_c_boolean *arr = (const protobuf_c_boolean *) array;
1425
+ for (i = 0; i < count; i++)
1426
+ payload_at += boolean_pack(arr[i], payload_at);
1427
+ break;
1428
+ }
1429
+ default:
1430
+ PROTOBUF_C__ASSERT_NOT_REACHED();
1431
+ }
1432
+
1433
+ payload_len = payload_at - (out + header_len);
1434
+ actual_length_size = uint32_size(payload_len);
1435
+ if (length_size_min != actual_length_size) {
1436
+ assert(actual_length_size == length_size_min + 1);
1437
+ memmove(out + header_len + 1, out + header_len,
1438
+ payload_len);
1439
+ header_len++;
1440
+ }
1441
+ uint32_pack(payload_len, out + len_start);
1442
+ return header_len + payload_len;
1443
+ } else {
1444
+ /* not "packed" cased */
1445
+ /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
1446
+ size_t rv = 0;
1447
+ unsigned siz = sizeof_elt_in_repeated_array(field->type);
1448
+
1449
+ for (i = 0; i < count; i++) {
1450
+ rv += required_field_pack(field, array, out + rv);
1451
+ array = (char *)array + siz;
1452
+ }
1453
+ return rv;
1454
+ }
1455
+ }
1456
+
1457
+ static size_t
1458
+ unknown_field_pack(const ProtobufCMessageUnknownField *field, uint8_t *out)
1459
+ {
1460
+ size_t rv = tag_pack(field->tag, out);
1461
+ out[0] |= field->wire_type;
1462
+ memcpy(out + rv, field->data, field->len);
1463
+ return rv + field->len;
1464
+ }
1465
+
1466
+ /**@}*/
1467
+
1468
+ size_t
1469
+ protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out)
1470
+ {
1471
+ unsigned i;
1472
+ size_t rv = 0;
1473
+
1474
+ ASSERT_IS_MESSAGE(message);
1475
+ for (i = 0; i < message->descriptor->n_fields; i++) {
1476
+ const ProtobufCFieldDescriptor *field =
1477
+ message->descriptor->fields + i;
1478
+ const void *member = ((const char *) message) + field->offset;
1479
+
1480
+ /*
1481
+ * It doesn't hurt to compute qmember (a pointer to the
1482
+ * quantifier field of the structure), but the pointer is only
1483
+ * valid if the field is:
1484
+ * - a repeated field, or
1485
+ * - a field that is part of a oneof
1486
+ * - an optional field that isn't a pointer type
1487
+ * (Meaning: not a message or a string).
1488
+ */
1489
+ const void *qmember =
1490
+ ((const char *) message) + field->quantifier_offset;
1491
+
1492
+ if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
1493
+ rv += required_field_pack(field, member, out + rv);
1494
+ } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
1495
+ field->label == PROTOBUF_C_LABEL_NONE) &&
1496
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
1497
+ rv += oneof_field_pack(
1498
+ field,
1499
+ *(const uint32_t *) qmember,
1500
+ member,
1501
+ out + rv
1502
+ );
1503
+ } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
1504
+ rv += optional_field_pack(
1505
+ field,
1506
+ *(const protobuf_c_boolean *) qmember,
1507
+ member,
1508
+ out + rv
1509
+ );
1510
+ } else if (field->label == PROTOBUF_C_LABEL_NONE) {
1511
+ rv += unlabeled_field_pack(field, member, out + rv);
1512
+ } else {
1513
+ rv += repeated_field_pack(field, *(const size_t *) qmember,
1514
+ member, out + rv);
1515
+ }
1516
+ }
1517
+ for (i = 0; i < message->n_unknown_fields; i++)
1518
+ rv += unknown_field_pack(&message->unknown_fields[i], out + rv);
1519
+ return rv;
1520
+ }
1521
+
1522
+ /**
1523
+ * \defgroup packbuf protobuf_c_message_pack_to_buffer() implementation
1524
+ *
1525
+ * Routines mainly used by protobuf_c_message_pack_to_buffer().
1526
+ *
1527
+ * \ingroup internal
1528
+ * @{
1529
+ */
1530
+
1531
+ /**
1532
+ * Pack a required field to a virtual buffer.
1533
+ *
1534
+ * \param field
1535
+ * Field descriptor.
1536
+ * \param member
1537
+ * The element to be packed.
1538
+ * \param[out] buffer
1539
+ * Virtual buffer to append data to.
1540
+ * \return
1541
+ * Number of bytes packed.
1542
+ */
1543
+ static size_t
1544
+ required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1545
+ const void *member, ProtobufCBuffer *buffer)
1546
+ {
1547
+ size_t rv;
1548
+ uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
1549
+
1550
+ rv = tag_pack(field->id, scratch);
1551
+ switch (field->type) {
1552
+ case PROTOBUF_C_TYPE_SINT32:
1553
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1554
+ rv += sint32_pack(*(const int32_t *) member, scratch + rv);
1555
+ buffer->append(buffer, rv, scratch);
1556
+ break;
1557
+ case PROTOBUF_C_TYPE_ENUM:
1558
+ case PROTOBUF_C_TYPE_INT32:
1559
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1560
+ rv += int32_pack(*(const int32_t *) member, scratch + rv);
1561
+ buffer->append(buffer, rv, scratch);
1562
+ break;
1563
+ case PROTOBUF_C_TYPE_UINT32:
1564
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1565
+ rv += uint32_pack(*(const uint32_t *) member, scratch + rv);
1566
+ buffer->append(buffer, rv, scratch);
1567
+ break;
1568
+ case PROTOBUF_C_TYPE_SINT64:
1569
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1570
+ rv += sint64_pack(*(const int64_t *) member, scratch + rv);
1571
+ buffer->append(buffer, rv, scratch);
1572
+ break;
1573
+ case PROTOBUF_C_TYPE_INT64:
1574
+ case PROTOBUF_C_TYPE_UINT64:
1575
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1576
+ rv += uint64_pack(*(const uint64_t *) member, scratch + rv);
1577
+ buffer->append(buffer, rv, scratch);
1578
+ break;
1579
+ case PROTOBUF_C_TYPE_SFIXED32:
1580
+ case PROTOBUF_C_TYPE_FIXED32:
1581
+ case PROTOBUF_C_TYPE_FLOAT:
1582
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
1583
+ rv += fixed32_pack(*(const uint32_t *) member, scratch + rv);
1584
+ buffer->append(buffer, rv, scratch);
1585
+ break;
1586
+ case PROTOBUF_C_TYPE_SFIXED64:
1587
+ case PROTOBUF_C_TYPE_FIXED64:
1588
+ case PROTOBUF_C_TYPE_DOUBLE:
1589
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
1590
+ rv += fixed64_pack(*(const uint64_t *) member, scratch + rv);
1591
+ buffer->append(buffer, rv, scratch);
1592
+ break;
1593
+ case PROTOBUF_C_TYPE_BOOL:
1594
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1595
+ rv += boolean_pack(*(const protobuf_c_boolean *) member, scratch + rv);
1596
+ buffer->append(buffer, rv, scratch);
1597
+ break;
1598
+ case PROTOBUF_C_TYPE_STRING: {
1599
+ const char *str = *(char *const *) member;
1600
+ size_t sublen = str ? strlen(str) : 0;
1601
+
1602
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1603
+ rv += uint32_pack(sublen, scratch + rv);
1604
+ buffer->append(buffer, rv, scratch);
1605
+ buffer->append(buffer, sublen, (const uint8_t *) str);
1606
+ rv += sublen;
1607
+ break;
1608
+ }
1609
+ case PROTOBUF_C_TYPE_BYTES: {
1610
+ const ProtobufCBinaryData *bd = ((const ProtobufCBinaryData *) member);
1611
+ size_t sublen = bd->len;
1612
+
1613
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1614
+ rv += uint32_pack(sublen, scratch + rv);
1615
+ buffer->append(buffer, rv, scratch);
1616
+ buffer->append(buffer, sublen, bd->data);
1617
+ rv += sublen;
1618
+ break;
1619
+ }
1620
+ case PROTOBUF_C_TYPE_MESSAGE: {
1621
+ uint8_t simple_buffer_scratch[256];
1622
+ size_t sublen;
1623
+ const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
1624
+ ProtobufCBufferSimple simple_buffer =
1625
+ PROTOBUF_C_BUFFER_SIMPLE_INIT(simple_buffer_scratch);
1626
+
1627
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1628
+ if (msg == NULL)
1629
+ sublen = 0;
1630
+ else
1631
+ sublen = protobuf_c_message_pack_to_buffer(msg, &simple_buffer.base);
1632
+ rv += uint32_pack(sublen, scratch + rv);
1633
+ buffer->append(buffer, rv, scratch);
1634
+ buffer->append(buffer, sublen, simple_buffer.data);
1635
+ rv += sublen;
1636
+ PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple_buffer);
1637
+ break;
1638
+ }
1639
+ default:
1640
+ PROTOBUF_C__ASSERT_NOT_REACHED();
1641
+ }
1642
+ return rv;
1643
+ }
1644
+
1645
+ /**
1646
+ * Pack a oneof field to a buffer. Only packs the field that is selected by the case enum.
1647
+ *
1648
+ * \param field
1649
+ * Field descriptor.
1650
+ * \param oneof_case
1651
+ * Enum value that selects the field in the oneof.
1652
+ * \param member
1653
+ * The element to be packed.
1654
+ * \param[out] buffer
1655
+ * Virtual buffer to append data to.
1656
+ * \return
1657
+ * Number of bytes serialised to `buffer`.
1658
+ */
1659
+ static size_t
1660
+ oneof_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1661
+ uint32_t oneof_case,
1662
+ const void *member, ProtobufCBuffer *buffer)
1663
+ {
1664
+ if (oneof_case != field->id) {
1665
+ return 0;
1666
+ }
1667
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1668
+ field->type == PROTOBUF_C_TYPE_STRING)
1669
+ {
1670
+ const void *ptr = *(const void *const *) member;
1671
+ if (ptr == NULL || ptr == field->default_value)
1672
+ return 0;
1673
+ }
1674
+ return required_field_pack_to_buffer(field, member, buffer);
1675
+ }
1676
+
1677
+ /**
1678
+ * Pack an optional field to a buffer.
1679
+ *
1680
+ * \param field
1681
+ * Field descriptor.
1682
+ * \param has
1683
+ * Whether the field is set.
1684
+ * \param member
1685
+ * The element to be packed.
1686
+ * \param[out] buffer
1687
+ * Virtual buffer to append data to.
1688
+ * \return
1689
+ * Number of bytes serialised to `buffer`.
1690
+ */
1691
+ static size_t
1692
+ optional_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1693
+ const protobuf_c_boolean has,
1694
+ const void *member, ProtobufCBuffer *buffer)
1695
+ {
1696
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1697
+ field->type == PROTOBUF_C_TYPE_STRING)
1698
+ {
1699
+ const void *ptr = *(const void *const *) member;
1700
+ if (ptr == NULL || ptr == field->default_value)
1701
+ return 0;
1702
+ } else {
1703
+ if (!has)
1704
+ return 0;
1705
+ }
1706
+ return required_field_pack_to_buffer(field, member, buffer);
1707
+ }
1708
+
1709
+ /**
1710
+ * Pack an unlabeled field to a buffer.
1711
+ *
1712
+ * \param field
1713
+ * Field descriptor.
1714
+ * \param member
1715
+ * The element to be packed.
1716
+ * \param[out] buffer
1717
+ * Virtual buffer to append data to.
1718
+ * \return
1719
+ * Number of bytes serialised to `buffer`.
1720
+ */
1721
+ static size_t
1722
+ unlabeled_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1723
+ const void *member, ProtobufCBuffer *buffer)
1724
+ {
1725
+ if (field_is_zeroish(field, member))
1726
+ return 0;
1727
+ return required_field_pack_to_buffer(field, member, buffer);
1728
+ }
1729
+
1730
+ /**
1731
+ * Get the packed size of an array of same field type.
1732
+ *
1733
+ * \param field
1734
+ * Field descriptor.
1735
+ * \param count
1736
+ * Number of elements of this type.
1737
+ * \param array
1738
+ * The elements to get the size of.
1739
+ * \return
1740
+ * Number of bytes required.
1741
+ */
1742
+ static size_t
1743
+ get_packed_payload_length(const ProtobufCFieldDescriptor *field,
1744
+ unsigned count, const void *array)
1745
+ {
1746
+ unsigned rv = 0;
1747
+ unsigned i;
1748
+
1749
+ switch (field->type) {
1750
+ case PROTOBUF_C_TYPE_SFIXED32:
1751
+ case PROTOBUF_C_TYPE_FIXED32:
1752
+ case PROTOBUF_C_TYPE_FLOAT:
1753
+ return count * 4;
1754
+ case PROTOBUF_C_TYPE_SFIXED64:
1755
+ case PROTOBUF_C_TYPE_FIXED64:
1756
+ case PROTOBUF_C_TYPE_DOUBLE:
1757
+ return count * 8;
1758
+ case PROTOBUF_C_TYPE_ENUM:
1759
+ case PROTOBUF_C_TYPE_INT32: {
1760
+ const int32_t *arr = (const int32_t *) array;
1761
+ for (i = 0; i < count; i++)
1762
+ rv += int32_size(arr[i]);
1763
+ break;
1764
+ }
1765
+ case PROTOBUF_C_TYPE_SINT32: {
1766
+ const int32_t *arr = (const int32_t *) array;
1767
+ for (i = 0; i < count; i++)
1768
+ rv += sint32_size(arr[i]);
1769
+ break;
1770
+ }
1771
+ case PROTOBUF_C_TYPE_UINT32: {
1772
+ const uint32_t *arr = (const uint32_t *) array;
1773
+ for (i = 0; i < count; i++)
1774
+ rv += uint32_size(arr[i]);
1775
+ break;
1776
+ }
1777
+ case PROTOBUF_C_TYPE_SINT64: {
1778
+ const int64_t *arr = (const int64_t *) array;
1779
+ for (i = 0; i < count; i++)
1780
+ rv += sint64_size(arr[i]);
1781
+ break;
1782
+ }
1783
+ case PROTOBUF_C_TYPE_INT64:
1784
+ case PROTOBUF_C_TYPE_UINT64: {
1785
+ const uint64_t *arr = (const uint64_t *) array;
1786
+ for (i = 0; i < count; i++)
1787
+ rv += uint64_size(arr[i]);
1788
+ break;
1789
+ }
1790
+ case PROTOBUF_C_TYPE_BOOL:
1791
+ return count;
1792
+ default:
1793
+ PROTOBUF_C__ASSERT_NOT_REACHED();
1794
+ }
1795
+ return rv;
1796
+ }
1797
+
1798
+ /**
1799
+ * Pack an array of same field type to a virtual buffer.
1800
+ *
1801
+ * \param field
1802
+ * Field descriptor.
1803
+ * \param count
1804
+ * Number of elements of this type.
1805
+ * \param array
1806
+ * The elements to get the size of.
1807
+ * \param[out] buffer
1808
+ * Virtual buffer to append data to.
1809
+ * \return
1810
+ * Number of bytes packed.
1811
+ */
1812
+ static size_t
1813
+ pack_buffer_packed_payload(const ProtobufCFieldDescriptor *field,
1814
+ unsigned count, const void *array,
1815
+ ProtobufCBuffer *buffer)
1816
+ {
1817
+ uint8_t scratch[16];
1818
+ size_t rv = 0;
1819
+ unsigned i;
1820
+
1821
+ switch (field->type) {
1822
+ case PROTOBUF_C_TYPE_SFIXED32:
1823
+ case PROTOBUF_C_TYPE_FIXED32:
1824
+ case PROTOBUF_C_TYPE_FLOAT:
1825
+ #if !defined(WORDS_BIGENDIAN)
1826
+ rv = count * 4;
1827
+ goto no_packing_needed;
1828
+ #else
1829
+ for (i = 0; i < count; i++) {
1830
+ unsigned len = fixed32_pack(((uint32_t *) array)[i], scratch);
1831
+ buffer->append(buffer, len, scratch);
1832
+ rv += len;
1833
+ }
1834
+ break;
1835
+ #endif
1836
+ case PROTOBUF_C_TYPE_SFIXED64:
1837
+ case PROTOBUF_C_TYPE_FIXED64:
1838
+ case PROTOBUF_C_TYPE_DOUBLE:
1839
+ #if !defined(WORDS_BIGENDIAN)
1840
+ rv = count * 8;
1841
+ goto no_packing_needed;
1842
+ #else
1843
+ for (i = 0; i < count; i++) {
1844
+ unsigned len = fixed64_pack(((uint64_t *) array)[i], scratch);
1845
+ buffer->append(buffer, len, scratch);
1846
+ rv += len;
1847
+ }
1848
+ break;
1849
+ #endif
1850
+ case PROTOBUF_C_TYPE_ENUM:
1851
+ case PROTOBUF_C_TYPE_INT32:
1852
+ for (i = 0; i < count; i++) {
1853
+ unsigned len = int32_pack(((int32_t *) array)[i], scratch);
1854
+ buffer->append(buffer, len, scratch);
1855
+ rv += len;
1856
+ }
1857
+ break;
1858
+ case PROTOBUF_C_TYPE_SINT32:
1859
+ for (i = 0; i < count; i++) {
1860
+ unsigned len = sint32_pack(((int32_t *) array)[i], scratch);
1861
+ buffer->append(buffer, len, scratch);
1862
+ rv += len;
1863
+ }
1864
+ break;
1865
+ case PROTOBUF_C_TYPE_UINT32:
1866
+ for (i = 0; i < count; i++) {
1867
+ unsigned len = uint32_pack(((uint32_t *) array)[i], scratch);
1868
+ buffer->append(buffer, len, scratch);
1869
+ rv += len;
1870
+ }
1871
+ break;
1872
+ case PROTOBUF_C_TYPE_SINT64:
1873
+ for (i = 0; i < count; i++) {
1874
+ unsigned len = sint64_pack(((int64_t *) array)[i], scratch);
1875
+ buffer->append(buffer, len, scratch);
1876
+ rv += len;
1877
+ }
1878
+ break;
1879
+ case PROTOBUF_C_TYPE_INT64:
1880
+ case PROTOBUF_C_TYPE_UINT64:
1881
+ for (i = 0; i < count; i++) {
1882
+ unsigned len = uint64_pack(((uint64_t *) array)[i], scratch);
1883
+ buffer->append(buffer, len, scratch);
1884
+ rv += len;
1885
+ }
1886
+ break;
1887
+ case PROTOBUF_C_TYPE_BOOL:
1888
+ for (i = 0; i < count; i++) {
1889
+ unsigned len = boolean_pack(((protobuf_c_boolean *) array)[i], scratch);
1890
+ buffer->append(buffer, len, scratch);
1891
+ rv += len;
1892
+ }
1893
+ return count;
1894
+ default:
1895
+ PROTOBUF_C__ASSERT_NOT_REACHED();
1896
+ }
1897
+ return rv;
1898
+
1899
+ #if !defined(WORDS_BIGENDIAN)
1900
+ no_packing_needed:
1901
+ buffer->append(buffer, rv, array);
1902
+ return rv;
1903
+ #endif
1904
+ }
1905
+
1906
+ static size_t
1907
+ repeated_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1908
+ unsigned count, const void *member,
1909
+ ProtobufCBuffer *buffer)
1910
+ {
1911
+ char *array = *(char * const *) member;
1912
+
1913
+ if (count == 0)
1914
+ return 0;
1915
+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
1916
+ uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
1917
+ size_t rv = tag_pack(field->id, scratch);
1918
+ size_t payload_len = get_packed_payload_length(field, count, array);
1919
+ size_t tmp;
1920
+
1921
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1922
+ rv += uint32_pack(payload_len, scratch + rv);
1923
+ buffer->append(buffer, rv, scratch);
1924
+ tmp = pack_buffer_packed_payload(field, count, array, buffer);
1925
+ assert(tmp == payload_len);
1926
+ return rv + payload_len;
1927
+ } else {
1928
+ size_t siz;
1929
+ unsigned i;
1930
+ /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
1931
+ unsigned rv = 0;
1932
+
1933
+ siz = sizeof_elt_in_repeated_array(field->type);
1934
+ for (i = 0; i < count; i++) {
1935
+ rv += required_field_pack_to_buffer(field, array, buffer);
1936
+ array += siz;
1937
+ }
1938
+ return rv;
1939
+ }
1940
+ }
1941
+
1942
+ static size_t
1943
+ unknown_field_pack_to_buffer(const ProtobufCMessageUnknownField *field,
1944
+ ProtobufCBuffer *buffer)
1945
+ {
1946
+ uint8_t header[MAX_UINT64_ENCODED_SIZE];
1947
+ size_t rv = tag_pack(field->tag, header);
1948
+
1949
+ header[0] |= field->wire_type;
1950
+ buffer->append(buffer, rv, header);
1951
+ buffer->append(buffer, field->len, field->data);
1952
+ return rv + field->len;
1953
+ }
1954
+
1955
+ /**@}*/
1956
+
1957
+ size_t
1958
+ protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message,
1959
+ ProtobufCBuffer *buffer)
1960
+ {
1961
+ unsigned i;
1962
+ size_t rv = 0;
1963
+
1964
+ ASSERT_IS_MESSAGE(message);
1965
+ for (i = 0; i < message->descriptor->n_fields; i++) {
1966
+ const ProtobufCFieldDescriptor *field =
1967
+ message->descriptor->fields + i;
1968
+ const void *member =
1969
+ ((const char *) message) + field->offset;
1970
+ const void *qmember =
1971
+ ((const char *) message) + field->quantifier_offset;
1972
+
1973
+ if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
1974
+ rv += required_field_pack_to_buffer(field, member, buffer);
1975
+ } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
1976
+ field->label == PROTOBUF_C_LABEL_NONE) &&
1977
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
1978
+ rv += oneof_field_pack_to_buffer(
1979
+ field,
1980
+ *(const uint32_t *) qmember,
1981
+ member,
1982
+ buffer
1983
+ );
1984
+ } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
1985
+ rv += optional_field_pack_to_buffer(
1986
+ field,
1987
+ *(const protobuf_c_boolean *) qmember,
1988
+ member,
1989
+ buffer
1990
+ );
1991
+ } else if (field->label == PROTOBUF_C_LABEL_NONE) {
1992
+ rv += unlabeled_field_pack_to_buffer(
1993
+ field,
1994
+ member,
1995
+ buffer
1996
+ );
1997
+ } else {
1998
+ rv += repeated_field_pack_to_buffer(
1999
+ field,
2000
+ *(const size_t *) qmember,
2001
+ member,
2002
+ buffer
2003
+ );
2004
+ }
2005
+ }
2006
+ for (i = 0; i < message->n_unknown_fields; i++)
2007
+ rv += unknown_field_pack_to_buffer(&message->unknown_fields[i], buffer);
2008
+
2009
+ return rv;
2010
+ }
2011
+
2012
+ /**
2013
+ * \defgroup unpack unpacking implementation
2014
+ *
2015
+ * Routines mainly used by the unpacking functions.
2016
+ *
2017
+ * \ingroup internal
2018
+ * @{
2019
+ */
2020
+
2021
+ static inline int
2022
+ int_range_lookup(unsigned n_ranges, const ProtobufCIntRange *ranges, int value)
2023
+ {
2024
+ unsigned n;
2025
+ unsigned start;
2026
+
2027
+ if (n_ranges == 0)
2028
+ return -1;
2029
+ start = 0;
2030
+ n = n_ranges;
2031
+ while (n > 1) {
2032
+ unsigned mid = start + n / 2;
2033
+
2034
+ if (value < ranges[mid].start_value) {
2035
+ n = mid - start;
2036
+ } else if (value >= ranges[mid].start_value +
2037
+ (int) (ranges[mid + 1].orig_index -
2038
+ ranges[mid].orig_index))
2039
+ {
2040
+ unsigned new_start = mid + 1;
2041
+ n = start + n - new_start;
2042
+ start = new_start;
2043
+ } else
2044
+ return (value - ranges[mid].start_value) +
2045
+ ranges[mid].orig_index;
2046
+ }
2047
+ if (n > 0) {
2048
+ unsigned start_orig_index = ranges[start].orig_index;
2049
+ unsigned range_size =
2050
+ ranges[start + 1].orig_index - start_orig_index;
2051
+
2052
+ if (ranges[start].start_value <= value &&
2053
+ value < (int) (ranges[start].start_value + range_size))
2054
+ {
2055
+ return (value - ranges[start].start_value) +
2056
+ start_orig_index;
2057
+ }
2058
+ }
2059
+ return -1;
2060
+ }
2061
+
2062
+ static size_t
2063
+ parse_tag_and_wiretype(size_t len,
2064
+ const uint8_t *data,
2065
+ uint32_t *tag_out,
2066
+ ProtobufCWireType *wiretype_out)
2067
+ {
2068
+ unsigned max_rv = len > 5 ? 5 : len;
2069
+ uint32_t tag = (data[0] & 0x7f) >> 3;
2070
+ unsigned shift = 4;
2071
+ unsigned rv;
2072
+
2073
+ /* 0 is not a valid tag value */
2074
+ if ((data[0] & 0xf8) == 0) {
2075
+ return 0;
2076
+ }
2077
+
2078
+ *wiretype_out = data[0] & 7;
2079
+ if ((data[0] & 0x80) == 0) {
2080
+ *tag_out = tag;
2081
+ return 1;
2082
+ }
2083
+ for (rv = 1; rv < max_rv; rv++) {
2084
+ if (data[rv] & 0x80) {
2085
+ tag |= (data[rv] & 0x7f) << shift;
2086
+ shift += 7;
2087
+ } else {
2088
+ tag |= data[rv] << shift;
2089
+ *tag_out = tag;
2090
+ return rv + 1;
2091
+ }
2092
+ }
2093
+ return 0; /* error: bad header */
2094
+ }
2095
+
2096
+ /* sizeof(ScannedMember) must be <= (1UL<<BOUND_SIZEOF_SCANNED_MEMBER_LOG2) */
2097
+ #define BOUND_SIZEOF_SCANNED_MEMBER_LOG2 5
2098
+ typedef struct _ScannedMember ScannedMember;
2099
+ /** Field as it's being read. */
2100
+ struct _ScannedMember {
2101
+ uint32_t tag; /**< Field tag. */
2102
+ uint8_t wire_type; /**< Field type. */
2103
+ uint8_t length_prefix_len; /**< Prefix length. */
2104
+ const ProtobufCFieldDescriptor *field; /**< Field descriptor. */
2105
+ size_t len; /**< Field length. */
2106
+ const uint8_t *data; /**< Pointer to field data. */
2107
+ };
2108
+
2109
+ static inline size_t
2110
+ scan_length_prefixed_data(size_t len, const uint8_t *data,
2111
+ size_t *prefix_len_out)
2112
+ {
2113
+ unsigned hdr_max = len < 5 ? len : 5;
2114
+ unsigned hdr_len;
2115
+ size_t val = 0;
2116
+ unsigned i;
2117
+ unsigned shift = 0;
2118
+
2119
+ for (i = 0; i < hdr_max; i++) {
2120
+ val |= ((size_t)data[i] & 0x7f) << shift;
2121
+ shift += 7;
2122
+ if ((data[i] & 0x80) == 0)
2123
+ break;
2124
+ }
2125
+ if (i == hdr_max) {
2126
+ PROTOBUF_C_UNPACK_ERROR("error parsing length for length-prefixed data");
2127
+ return 0;
2128
+ }
2129
+ hdr_len = i + 1;
2130
+ *prefix_len_out = hdr_len;
2131
+ if (val > INT_MAX) {
2132
+ // Protobuf messages should always be less than 2 GiB in size.
2133
+ // We also want to return early here so that hdr_len + val does
2134
+ // not overflow on 32-bit systems.
2135
+ PROTOBUF_C_UNPACK_ERROR("length prefix of %lu is too large", val);
2136
+ return 0;
2137
+ }
2138
+ if (hdr_len + val > len) {
2139
+ PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %lu", val);
2140
+ return 0;
2141
+ }
2142
+ return hdr_len + val;
2143
+ }
2144
+
2145
+ static size_t
2146
+ max_b128_numbers(size_t len, const uint8_t *data)
2147
+ {
2148
+ size_t rv = 0;
2149
+ while (len--)
2150
+ if ((*data++ & 0x80) == 0)
2151
+ ++rv;
2152
+ return rv;
2153
+ }
2154
+
2155
+ /**@}*/
2156
+
2157
+ /**
2158
+ * Merge earlier message into a latter message.
2159
+ *
2160
+ * For numeric types and strings, if the same value appears multiple
2161
+ * times, the parser accepts the last value it sees. For embedded
2162
+ * message fields, the parser merges multiple instances of the same
2163
+ * field. That is, all singular scalar fields in the latter instance
2164
+ * replace those in the former, singular embedded messages are merged,
2165
+ * and repeated fields are concatenated.
2166
+ *
2167
+ * The earlier message should be freed after calling this function, as
2168
+ * some of its fields may have been reused and changed to their default
2169
+ * values during the merge.
2170
+ */
2171
+ static protobuf_c_boolean
2172
+ merge_messages(ProtobufCMessage *earlier_msg,
2173
+ ProtobufCMessage *latter_msg,
2174
+ ProtobufCAllocator *allocator)
2175
+ {
2176
+ unsigned i;
2177
+ const ProtobufCFieldDescriptor *fields =
2178
+ latter_msg->descriptor->fields;
2179
+ for (i = 0; i < latter_msg->descriptor->n_fields; i++) {
2180
+ if (fields[i].label == PROTOBUF_C_LABEL_REPEATED) {
2181
+ size_t *n_earlier =
2182
+ STRUCT_MEMBER_PTR(size_t, earlier_msg,
2183
+ fields[i].quantifier_offset);
2184
+ uint8_t **p_earlier =
2185
+ STRUCT_MEMBER_PTR(uint8_t *, earlier_msg,
2186
+ fields[i].offset);
2187
+ size_t *n_latter =
2188
+ STRUCT_MEMBER_PTR(size_t, latter_msg,
2189
+ fields[i].quantifier_offset);
2190
+ uint8_t **p_latter =
2191
+ STRUCT_MEMBER_PTR(uint8_t *, latter_msg,
2192
+ fields[i].offset);
2193
+
2194
+ if (*n_earlier > 0) {
2195
+ if (*n_latter > 0) {
2196
+ /* Concatenate the repeated field */
2197
+ size_t el_size =
2198
+ sizeof_elt_in_repeated_array(fields[i].type);
2199
+ uint8_t *new_field;
2200
+
2201
+ new_field = do_alloc(allocator,
2202
+ (*n_earlier + *n_latter) * el_size);
2203
+ if (!new_field)
2204
+ return FALSE;
2205
+
2206
+ memcpy(new_field, *p_earlier,
2207
+ *n_earlier * el_size);
2208
+ memcpy(new_field +
2209
+ *n_earlier * el_size,
2210
+ *p_latter,
2211
+ *n_latter * el_size);
2212
+
2213
+ do_free(allocator, *p_latter);
2214
+ do_free(allocator, *p_earlier);
2215
+ *p_latter = new_field;
2216
+ *n_latter = *n_earlier + *n_latter;
2217
+ } else {
2218
+ /* Zero copy the repeated field from the earlier message */
2219
+ *n_latter = *n_earlier;
2220
+ *p_latter = *p_earlier;
2221
+ }
2222
+ /* Make sure the field does not get double freed */
2223
+ *n_earlier = 0;
2224
+ *p_earlier = 0;
2225
+ }
2226
+ } else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL ||
2227
+ fields[i].label == PROTOBUF_C_LABEL_NONE) {
2228
+ const ProtobufCFieldDescriptor *field;
2229
+ uint32_t *earlier_case_p = STRUCT_MEMBER_PTR(uint32_t,
2230
+ earlier_msg,
2231
+ fields[i].
2232
+ quantifier_offset);
2233
+ uint32_t *latter_case_p = STRUCT_MEMBER_PTR(uint32_t,
2234
+ latter_msg,
2235
+ fields[i].
2236
+ quantifier_offset);
2237
+ protobuf_c_boolean need_to_merge = FALSE;
2238
+ void *earlier_elem;
2239
+ void *latter_elem;
2240
+ const void *def_val;
2241
+
2242
+ if (fields[i].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) {
2243
+ if (*latter_case_p == 0) {
2244
+ /* lookup correct oneof field */
2245
+ int field_index =
2246
+ int_range_lookup(
2247
+ latter_msg->descriptor
2248
+ ->n_field_ranges,
2249
+ latter_msg->descriptor
2250
+ ->field_ranges,
2251
+ *earlier_case_p);
2252
+ if (field_index < 0)
2253
+ return FALSE;
2254
+ field = latter_msg->descriptor->fields +
2255
+ field_index;
2256
+ } else {
2257
+ /* Oneof is present in the latter message, move on */
2258
+ continue;
2259
+ }
2260
+ } else {
2261
+ field = &fields[i];
2262
+ }
2263
+
2264
+ earlier_elem = STRUCT_MEMBER_P(earlier_msg, field->offset);
2265
+ latter_elem = STRUCT_MEMBER_P(latter_msg, field->offset);
2266
+ def_val = field->default_value;
2267
+
2268
+ switch (field->type) {
2269
+ case PROTOBUF_C_TYPE_MESSAGE: {
2270
+ ProtobufCMessage *em = *(ProtobufCMessage **) earlier_elem;
2271
+ ProtobufCMessage *lm = *(ProtobufCMessage **) latter_elem;
2272
+ if (em != NULL) {
2273
+ if (lm != NULL) {
2274
+ if (!merge_messages(em, lm, allocator))
2275
+ return FALSE;
2276
+ /* Already merged */
2277
+ need_to_merge = FALSE;
2278
+ } else {
2279
+ /* Zero copy the message */
2280
+ need_to_merge = TRUE;
2281
+ }
2282
+ }
2283
+ break;
2284
+ }
2285
+ case PROTOBUF_C_TYPE_BYTES: {
2286
+ uint8_t *e_data =
2287
+ ((ProtobufCBinaryData *) earlier_elem)->data;
2288
+ uint8_t *l_data =
2289
+ ((ProtobufCBinaryData *) latter_elem)->data;
2290
+ const ProtobufCBinaryData *d_bd =
2291
+ (ProtobufCBinaryData *) def_val;
2292
+
2293
+ need_to_merge =
2294
+ (e_data != NULL &&
2295
+ (d_bd == NULL ||
2296
+ e_data != d_bd->data)) &&
2297
+ (l_data == NULL ||
2298
+ (d_bd != NULL &&
2299
+ l_data == d_bd->data));
2300
+ break;
2301
+ }
2302
+ case PROTOBUF_C_TYPE_STRING: {
2303
+ char *e_str = *(char **) earlier_elem;
2304
+ char *l_str = *(char **) latter_elem;
2305
+ const char *d_str = def_val;
2306
+
2307
+ need_to_merge = e_str != d_str && l_str == d_str;
2308
+ break;
2309
+ }
2310
+ default: {
2311
+ /* Could be has field or case enum, the logic is
2312
+ * equivalent, since 0 (FALSE) means not set for
2313
+ * oneof */
2314
+ need_to_merge = (*earlier_case_p != 0) &&
2315
+ (*latter_case_p == 0);
2316
+ break;
2317
+ }
2318
+ }
2319
+
2320
+ if (need_to_merge) {
2321
+ size_t el_size =
2322
+ sizeof_elt_in_repeated_array(field->type);
2323
+ memcpy(latter_elem, earlier_elem, el_size);
2324
+ /*
2325
+ * Reset the element from the old message to 0
2326
+ * to make sure earlier message deallocation
2327
+ * doesn't corrupt zero-copied data in the new
2328
+ * message, earlier message will be freed after
2329
+ * this function is called anyway
2330
+ */
2331
+ memset(earlier_elem, 0, el_size);
2332
+
2333
+ if (field->quantifier_offset != 0) {
2334
+ /* Set the has field or the case enum,
2335
+ * if applicable */
2336
+ *latter_case_p = *earlier_case_p;
2337
+ *earlier_case_p = 0;
2338
+ }
2339
+ }
2340
+ }
2341
+ }
2342
+ return TRUE;
2343
+ }
2344
+
2345
+ /**
2346
+ * Count packed elements.
2347
+ *
2348
+ * Given a raw slab of packed-repeated values, determine the number of
2349
+ * elements. This function detects certain kinds of errors but not
2350
+ * others; the remaining error checking is done by
2351
+ * parse_packed_repeated_member().
2352
+ */
2353
+ static protobuf_c_boolean
2354
+ count_packed_elements(ProtobufCType type,
2355
+ size_t len, const uint8_t *data, size_t *count_out)
2356
+ {
2357
+ switch (type) {
2358
+ case PROTOBUF_C_TYPE_SFIXED32:
2359
+ case PROTOBUF_C_TYPE_FIXED32:
2360
+ case PROTOBUF_C_TYPE_FLOAT:
2361
+ if (len % 4 != 0) {
2362
+ PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 4 for fixed-length 32-bit types");
2363
+ return FALSE;
2364
+ }
2365
+ *count_out = len / 4;
2366
+ return TRUE;
2367
+ case PROTOBUF_C_TYPE_SFIXED64:
2368
+ case PROTOBUF_C_TYPE_FIXED64:
2369
+ case PROTOBUF_C_TYPE_DOUBLE:
2370
+ if (len % 8 != 0) {
2371
+ PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 8 for fixed-length 64-bit types");
2372
+ return FALSE;
2373
+ }
2374
+ *count_out = len / 8;
2375
+ return TRUE;
2376
+ case PROTOBUF_C_TYPE_ENUM:
2377
+ case PROTOBUF_C_TYPE_INT32:
2378
+ case PROTOBUF_C_TYPE_SINT32:
2379
+ case PROTOBUF_C_TYPE_UINT32:
2380
+ case PROTOBUF_C_TYPE_INT64:
2381
+ case PROTOBUF_C_TYPE_SINT64:
2382
+ case PROTOBUF_C_TYPE_UINT64:
2383
+ *count_out = max_b128_numbers(len, data);
2384
+ return TRUE;
2385
+ case PROTOBUF_C_TYPE_BOOL:
2386
+ *count_out = len;
2387
+ return TRUE;
2388
+ case PROTOBUF_C_TYPE_STRING:
2389
+ case PROTOBUF_C_TYPE_BYTES:
2390
+ case PROTOBUF_C_TYPE_MESSAGE:
2391
+ default:
2392
+ PROTOBUF_C_UNPACK_ERROR("bad protobuf-c type %u for packed-repeated", type);
2393
+ return FALSE;
2394
+ }
2395
+ }
2396
+
2397
+ static inline uint32_t
2398
+ parse_uint32(unsigned len, const uint8_t *data)
2399
+ {
2400
+ uint32_t rv = data[0] & 0x7f;
2401
+ if (len > 1) {
2402
+ rv |= ((uint32_t) (data[1] & 0x7f) << 7);
2403
+ if (len > 2) {
2404
+ rv |= ((uint32_t) (data[2] & 0x7f) << 14);
2405
+ if (len > 3) {
2406
+ rv |= ((uint32_t) (data[3] & 0x7f) << 21);
2407
+ if (len > 4)
2408
+ rv |= ((uint32_t) (data[4]) << 28);
2409
+ }
2410
+ }
2411
+ }
2412
+ return rv;
2413
+ }
2414
+
2415
+ static inline uint32_t
2416
+ parse_int32(unsigned len, const uint8_t *data)
2417
+ {
2418
+ return parse_uint32(len, data);
2419
+ }
2420
+
2421
+ static inline int32_t
2422
+ unzigzag32(uint32_t v)
2423
+ {
2424
+ // Note: Using unsigned types prevents undefined behavior
2425
+ return (int32_t)((v >> 1) ^ (~(v & 1) + 1));
2426
+ }
2427
+
2428
+ static inline uint32_t
2429
+ parse_fixed_uint32(const uint8_t *data)
2430
+ {
2431
+ #if !defined(WORDS_BIGENDIAN)
2432
+ uint32_t t;
2433
+ memcpy(&t, data, 4);
2434
+ return t;
2435
+ #else
2436
+ return data[0] |
2437
+ ((uint32_t) (data[1]) << 8) |
2438
+ ((uint32_t) (data[2]) << 16) |
2439
+ ((uint32_t) (data[3]) << 24);
2440
+ #endif
2441
+ }
2442
+
2443
+ static uint64_t
2444
+ parse_uint64(unsigned len, const uint8_t *data)
2445
+ {
2446
+ unsigned shift, i;
2447
+ uint64_t rv;
2448
+
2449
+ if (len < 5)
2450
+ return parse_uint32(len, data);
2451
+ rv = ((uint64_t) (data[0] & 0x7f)) |
2452
+ ((uint64_t) (data[1] & 0x7f) << 7) |
2453
+ ((uint64_t) (data[2] & 0x7f) << 14) |
2454
+ ((uint64_t) (data[3] & 0x7f) << 21);
2455
+ shift = 28;
2456
+ for (i = 4; i < len; i++) {
2457
+ rv |= (((uint64_t) (data[i] & 0x7f)) << shift);
2458
+ shift += 7;
2459
+ }
2460
+ return rv;
2461
+ }
2462
+
2463
+ static inline int64_t
2464
+ unzigzag64(uint64_t v)
2465
+ {
2466
+ // Note: Using unsigned types prevents undefined behavior
2467
+ return (int64_t)((v >> 1) ^ (~(v & 1) + 1));
2468
+ }
2469
+
2470
+ static inline uint64_t
2471
+ parse_fixed_uint64(const uint8_t *data)
2472
+ {
2473
+ #if !defined(WORDS_BIGENDIAN)
2474
+ uint64_t t;
2475
+ memcpy(&t, data, 8);
2476
+ return t;
2477
+ #else
2478
+ return (uint64_t) parse_fixed_uint32(data) |
2479
+ (((uint64_t) parse_fixed_uint32(data + 4)) << 32);
2480
+ #endif
2481
+ }
2482
+
2483
+ static protobuf_c_boolean
2484
+ parse_boolean(unsigned len, const uint8_t *data)
2485
+ {
2486
+ unsigned i;
2487
+ for (i = 0; i < len; i++)
2488
+ if (data[i] & 0x7f)
2489
+ return TRUE;
2490
+ return FALSE;
2491
+ }
2492
+
2493
+ static protobuf_c_boolean
2494
+ parse_required_member(ScannedMember *scanned_member,
2495
+ void *member,
2496
+ ProtobufCAllocator *allocator,
2497
+ protobuf_c_boolean maybe_clear)
2498
+ {
2499
+ unsigned len = scanned_member->len;
2500
+ const uint8_t *data = scanned_member->data;
2501
+ ProtobufCWireType wire_type = scanned_member->wire_type;
2502
+
2503
+ switch (scanned_member->field->type) {
2504
+ case PROTOBUF_C_TYPE_ENUM:
2505
+ case PROTOBUF_C_TYPE_INT32:
2506
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2507
+ return FALSE;
2508
+ *(int32_t *) member = parse_int32(len, data);
2509
+ return TRUE;
2510
+ case PROTOBUF_C_TYPE_UINT32:
2511
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2512
+ return FALSE;
2513
+ *(uint32_t *) member = parse_uint32(len, data);
2514
+ return TRUE;
2515
+ case PROTOBUF_C_TYPE_SINT32:
2516
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2517
+ return FALSE;
2518
+ *(int32_t *) member = unzigzag32(parse_uint32(len, data));
2519
+ return TRUE;
2520
+ case PROTOBUF_C_TYPE_SFIXED32:
2521
+ case PROTOBUF_C_TYPE_FIXED32:
2522
+ case PROTOBUF_C_TYPE_FLOAT:
2523
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT)
2524
+ return FALSE;
2525
+ *(uint32_t *) member = parse_fixed_uint32(data);
2526
+ return TRUE;
2527
+ case PROTOBUF_C_TYPE_INT64:
2528
+ case PROTOBUF_C_TYPE_UINT64:
2529
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2530
+ return FALSE;
2531
+ *(uint64_t *) member = parse_uint64(len, data);
2532
+ return TRUE;
2533
+ case PROTOBUF_C_TYPE_SINT64:
2534
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2535
+ return FALSE;
2536
+ *(int64_t *) member = unzigzag64(parse_uint64(len, data));
2537
+ return TRUE;
2538
+ case PROTOBUF_C_TYPE_SFIXED64:
2539
+ case PROTOBUF_C_TYPE_FIXED64:
2540
+ case PROTOBUF_C_TYPE_DOUBLE:
2541
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT)
2542
+ return FALSE;
2543
+ *(uint64_t *) member = parse_fixed_uint64(data);
2544
+ return TRUE;
2545
+ case PROTOBUF_C_TYPE_BOOL:
2546
+ *(protobuf_c_boolean *) member = parse_boolean(len, data);
2547
+ return TRUE;
2548
+ case PROTOBUF_C_TYPE_STRING: {
2549
+ char **pstr = member;
2550
+ unsigned pref_len = scanned_member->length_prefix_len;
2551
+
2552
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2553
+ return FALSE;
2554
+
2555
+ if (maybe_clear && *pstr != NULL) {
2556
+ const char *def = scanned_member->field->default_value;
2557
+ if (*pstr != NULL && *pstr != def)
2558
+ do_free(allocator, *pstr);
2559
+ }
2560
+ *pstr = do_alloc(allocator, len - pref_len + 1);
2561
+ if (*pstr == NULL)
2562
+ return FALSE;
2563
+ memcpy(*pstr, data + pref_len, len - pref_len);
2564
+ (*pstr)[len - pref_len] = 0;
2565
+ return TRUE;
2566
+ }
2567
+ case PROTOBUF_C_TYPE_BYTES: {
2568
+ ProtobufCBinaryData *bd = member;
2569
+ const ProtobufCBinaryData *def_bd;
2570
+ unsigned pref_len = scanned_member->length_prefix_len;
2571
+
2572
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2573
+ return FALSE;
2574
+
2575
+ def_bd = scanned_member->field->default_value;
2576
+ if (maybe_clear &&
2577
+ bd->data != NULL &&
2578
+ (def_bd == NULL || bd->data != def_bd->data))
2579
+ {
2580
+ do_free(allocator, bd->data);
2581
+ }
2582
+ if (len - pref_len > 0) {
2583
+ bd->data = do_alloc(allocator, len - pref_len);
2584
+ if (bd->data == NULL)
2585
+ return FALSE;
2586
+ memcpy(bd->data, data + pref_len, len - pref_len);
2587
+ } else {
2588
+ bd->data = NULL;
2589
+ }
2590
+ bd->len = len - pref_len;
2591
+ return TRUE;
2592
+ }
2593
+ case PROTOBUF_C_TYPE_MESSAGE: {
2594
+ ProtobufCMessage **pmessage = member;
2595
+ ProtobufCMessage *subm;
2596
+ const ProtobufCMessage *def_mess;
2597
+ protobuf_c_boolean merge_successful = TRUE;
2598
+ unsigned pref_len = scanned_member->length_prefix_len;
2599
+
2600
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2601
+ return FALSE;
2602
+
2603
+ def_mess = scanned_member->field->default_value;
2604
+ subm = protobuf_c_message_unpack(scanned_member->field->descriptor,
2605
+ allocator,
2606
+ len - pref_len,
2607
+ data + pref_len);
2608
+
2609
+ if (maybe_clear &&
2610
+ *pmessage != NULL &&
2611
+ *pmessage != def_mess)
2612
+ {
2613
+ if (subm != NULL)
2614
+ merge_successful = merge_messages(*pmessage, subm, allocator);
2615
+ /* Delete the previous message */
2616
+ protobuf_c_message_free_unpacked(*pmessage, allocator);
2617
+ }
2618
+ *pmessage = subm;
2619
+ if (subm == NULL || !merge_successful)
2620
+ return FALSE;
2621
+ return TRUE;
2622
+ }
2623
+ }
2624
+ return FALSE;
2625
+ }
2626
+
2627
+ static protobuf_c_boolean
2628
+ parse_oneof_member (ScannedMember *scanned_member,
2629
+ void *member,
2630
+ ProtobufCMessage *message,
2631
+ ProtobufCAllocator *allocator)
2632
+ {
2633
+ uint32_t *oneof_case = STRUCT_MEMBER_PTR(uint32_t, message,
2634
+ scanned_member->field->quantifier_offset);
2635
+
2636
+ /* If we have already parsed a member of this oneof, free it. */
2637
+ if (*oneof_case != 0) {
2638
+ const ProtobufCFieldDescriptor *old_field;
2639
+ size_t el_size;
2640
+ /* lookup field */
2641
+ int field_index =
2642
+ int_range_lookup(message->descriptor->n_field_ranges,
2643
+ message->descriptor->field_ranges,
2644
+ *oneof_case);
2645
+ if (field_index < 0)
2646
+ return FALSE;
2647
+ old_field = message->descriptor->fields + field_index;
2648
+ el_size = sizeof_elt_in_repeated_array(old_field->type);
2649
+
2650
+ switch (old_field->type) {
2651
+ case PROTOBUF_C_TYPE_STRING: {
2652
+ char **pstr = member;
2653
+ const char *def = old_field->default_value;
2654
+ if (*pstr != NULL && *pstr != def)
2655
+ do_free(allocator, *pstr);
2656
+ break;
2657
+ }
2658
+ case PROTOBUF_C_TYPE_BYTES: {
2659
+ ProtobufCBinaryData *bd = member;
2660
+ const ProtobufCBinaryData *def_bd = old_field->default_value;
2661
+ if (bd->data != NULL &&
2662
+ (def_bd == NULL || bd->data != def_bd->data))
2663
+ {
2664
+ do_free(allocator, bd->data);
2665
+ }
2666
+ break;
2667
+ }
2668
+ case PROTOBUF_C_TYPE_MESSAGE: {
2669
+ ProtobufCMessage **pmessage = member;
2670
+ const ProtobufCMessage *def_mess = old_field->default_value;
2671
+ if (*pmessage != NULL && *pmessage != def_mess)
2672
+ protobuf_c_message_free_unpacked(*pmessage, allocator);
2673
+ break;
2674
+ }
2675
+ default:
2676
+ break;
2677
+ }
2678
+
2679
+ memset (member, 0, el_size);
2680
+ }
2681
+ if (!parse_required_member (scanned_member, member, allocator, TRUE))
2682
+ return FALSE;
2683
+
2684
+ *oneof_case = scanned_member->tag;
2685
+ return TRUE;
2686
+ }
2687
+
2688
+
2689
+ static protobuf_c_boolean
2690
+ parse_optional_member(ScannedMember *scanned_member,
2691
+ void *member,
2692
+ ProtobufCMessage *message,
2693
+ ProtobufCAllocator *allocator)
2694
+ {
2695
+ if (!parse_required_member(scanned_member, member, allocator, TRUE))
2696
+ return FALSE;
2697
+ if (scanned_member->field->quantifier_offset != 0)
2698
+ STRUCT_MEMBER(protobuf_c_boolean,
2699
+ message,
2700
+ scanned_member->field->quantifier_offset) = TRUE;
2701
+ return TRUE;
2702
+ }
2703
+
2704
+ static protobuf_c_boolean
2705
+ parse_repeated_member(ScannedMember *scanned_member,
2706
+ void *member,
2707
+ ProtobufCMessage *message,
2708
+ ProtobufCAllocator *allocator)
2709
+ {
2710
+ const ProtobufCFieldDescriptor *field = scanned_member->field;
2711
+ size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
2712
+ size_t siz = sizeof_elt_in_repeated_array(field->type);
2713
+ char *array = *(char **) member;
2714
+
2715
+ if (!parse_required_member(scanned_member, array + siz * (*p_n),
2716
+ allocator, FALSE))
2717
+ {
2718
+ return FALSE;
2719
+ }
2720
+ *p_n += 1;
2721
+ return TRUE;
2722
+ }
2723
+
2724
+ static unsigned
2725
+ scan_varint(unsigned len, const uint8_t *data)
2726
+ {
2727
+ unsigned i;
2728
+ if (len > 10)
2729
+ len = 10;
2730
+ for (i = 0; i < len; i++)
2731
+ if ((data[i] & 0x80) == 0)
2732
+ break;
2733
+ if (i == len)
2734
+ return 0;
2735
+ return i + 1;
2736
+ }
2737
+
2738
+ static protobuf_c_boolean
2739
+ parse_packed_repeated_member(ScannedMember *scanned_member,
2740
+ void *member,
2741
+ ProtobufCMessage *message)
2742
+ {
2743
+ const ProtobufCFieldDescriptor *field = scanned_member->field;
2744
+ size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
2745
+ size_t siz = sizeof_elt_in_repeated_array(field->type);
2746
+ void *array = *(char **) member + siz * (*p_n);
2747
+ const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len;
2748
+ size_t rem = scanned_member->len - scanned_member->length_prefix_len;
2749
+ size_t count = 0;
2750
+ unsigned i;
2751
+
2752
+ switch (field->type) {
2753
+ case PROTOBUF_C_TYPE_SFIXED32:
2754
+ case PROTOBUF_C_TYPE_FIXED32:
2755
+ case PROTOBUF_C_TYPE_FLOAT:
2756
+ count = (scanned_member->len - scanned_member->length_prefix_len) / 4;
2757
+ #if !defined(WORDS_BIGENDIAN)
2758
+ goto no_unpacking_needed;
2759
+ #else
2760
+ for (i = 0; i < count; i++) {
2761
+ ((uint32_t *) array)[i] = parse_fixed_uint32(at);
2762
+ at += 4;
2763
+ }
2764
+ break;
2765
+ #endif
2766
+ case PROTOBUF_C_TYPE_SFIXED64:
2767
+ case PROTOBUF_C_TYPE_FIXED64:
2768
+ case PROTOBUF_C_TYPE_DOUBLE:
2769
+ count = (scanned_member->len - scanned_member->length_prefix_len) / 8;
2770
+ #if !defined(WORDS_BIGENDIAN)
2771
+ goto no_unpacking_needed;
2772
+ #else
2773
+ for (i = 0; i < count; i++) {
2774
+ ((uint64_t *) array)[i] = parse_fixed_uint64(at);
2775
+ at += 8;
2776
+ }
2777
+ break;
2778
+ #endif
2779
+ case PROTOBUF_C_TYPE_ENUM:
2780
+ case PROTOBUF_C_TYPE_INT32:
2781
+ while (rem > 0) {
2782
+ unsigned s = scan_varint(rem, at);
2783
+ if (s == 0) {
2784
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int32 value");
2785
+ return FALSE;
2786
+ }
2787
+ ((int32_t *) array)[count++] = parse_int32(s, at);
2788
+ at += s;
2789
+ rem -= s;
2790
+ }
2791
+ break;
2792
+ case PROTOBUF_C_TYPE_SINT32:
2793
+ while (rem > 0) {
2794
+ unsigned s = scan_varint(rem, at);
2795
+ if (s == 0) {
2796
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint32 value");
2797
+ return FALSE;
2798
+ }
2799
+ ((int32_t *) array)[count++] = unzigzag32(parse_uint32(s, at));
2800
+ at += s;
2801
+ rem -= s;
2802
+ }
2803
+ break;
2804
+ case PROTOBUF_C_TYPE_UINT32:
2805
+ while (rem > 0) {
2806
+ unsigned s = scan_varint(rem, at);
2807
+ if (s == 0) {
2808
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated enum or uint32 value");
2809
+ return FALSE;
2810
+ }
2811
+ ((uint32_t *) array)[count++] = parse_uint32(s, at);
2812
+ at += s;
2813
+ rem -= s;
2814
+ }
2815
+ break;
2816
+
2817
+ case PROTOBUF_C_TYPE_SINT64:
2818
+ while (rem > 0) {
2819
+ unsigned s = scan_varint(rem, at);
2820
+ if (s == 0) {
2821
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint64 value");
2822
+ return FALSE;
2823
+ }
2824
+ ((int64_t *) array)[count++] = unzigzag64(parse_uint64(s, at));
2825
+ at += s;
2826
+ rem -= s;
2827
+ }
2828
+ break;
2829
+ case PROTOBUF_C_TYPE_INT64:
2830
+ case PROTOBUF_C_TYPE_UINT64:
2831
+ while (rem > 0) {
2832
+ unsigned s = scan_varint(rem, at);
2833
+ if (s == 0) {
2834
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int64/uint64 value");
2835
+ return FALSE;
2836
+ }
2837
+ ((int64_t *) array)[count++] = parse_uint64(s, at);
2838
+ at += s;
2839
+ rem -= s;
2840
+ }
2841
+ break;
2842
+ case PROTOBUF_C_TYPE_BOOL:
2843
+ count = rem;
2844
+ for (i = 0; i < count; i++) {
2845
+ if (at[i] > 1) {
2846
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value");
2847
+ return FALSE;
2848
+ }
2849
+ ((protobuf_c_boolean *) array)[i] = at[i];
2850
+ }
2851
+ break;
2852
+ default:
2853
+ PROTOBUF_C__ASSERT_NOT_REACHED();
2854
+ }
2855
+ *p_n += count;
2856
+ return TRUE;
2857
+
2858
+ #if !defined(WORDS_BIGENDIAN)
2859
+ no_unpacking_needed:
2860
+ memcpy(array, at, count * siz);
2861
+ *p_n += count;
2862
+ return TRUE;
2863
+ #endif
2864
+ }
2865
+
2866
+ static protobuf_c_boolean
2867
+ is_packable_type(ProtobufCType type)
2868
+ {
2869
+ return
2870
+ type != PROTOBUF_C_TYPE_STRING &&
2871
+ type != PROTOBUF_C_TYPE_BYTES &&
2872
+ type != PROTOBUF_C_TYPE_MESSAGE;
2873
+ }
2874
+
2875
+ static protobuf_c_boolean
2876
+ parse_member(ScannedMember *scanned_member,
2877
+ ProtobufCMessage *message,
2878
+ ProtobufCAllocator *allocator)
2879
+ {
2880
+ const ProtobufCFieldDescriptor *field = scanned_member->field;
2881
+ void *member;
2882
+
2883
+ if (field == NULL) {
2884
+ ProtobufCMessageUnknownField *ufield =
2885
+ message->unknown_fields +
2886
+ (message->n_unknown_fields++);
2887
+ ufield->tag = scanned_member->tag;
2888
+ ufield->wire_type = scanned_member->wire_type;
2889
+ ufield->len = scanned_member->len;
2890
+ ufield->data = do_alloc(allocator, scanned_member->len);
2891
+ if (ufield->data == NULL)
2892
+ return FALSE;
2893
+ memcpy(ufield->data, scanned_member->data, ufield->len);
2894
+ return TRUE;
2895
+ }
2896
+ member = (char *) message + field->offset;
2897
+ switch (field->label) {
2898
+ case PROTOBUF_C_LABEL_REQUIRED:
2899
+ return parse_required_member(scanned_member, member,
2900
+ allocator, TRUE);
2901
+ case PROTOBUF_C_LABEL_OPTIONAL:
2902
+ case PROTOBUF_C_LABEL_NONE:
2903
+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF)) {
2904
+ return parse_oneof_member(scanned_member, member,
2905
+ message, allocator);
2906
+ } else {
2907
+ return parse_optional_member(scanned_member, member,
2908
+ message, allocator);
2909
+ }
2910
+ case PROTOBUF_C_LABEL_REPEATED:
2911
+ if (scanned_member->wire_type ==
2912
+ PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
2913
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
2914
+ is_packable_type(field->type)))
2915
+ {
2916
+ return parse_packed_repeated_member(scanned_member,
2917
+ member, message);
2918
+ } else {
2919
+ return parse_repeated_member(scanned_member,
2920
+ member, message,
2921
+ allocator);
2922
+ }
2923
+ }
2924
+ PROTOBUF_C__ASSERT_NOT_REACHED();
2925
+ return 0;
2926
+ }
2927
+
2928
+ /**
2929
+ * Initialise messages generated by old code.
2930
+ *
2931
+ * This function is used if desc->message_init == NULL (which occurs
2932
+ * for old code, and which would be useful to support allocating
2933
+ * descriptors dynamically).
2934
+ */
2935
+ static void
2936
+ message_init_generic(const ProtobufCMessageDescriptor *desc,
2937
+ ProtobufCMessage *message)
2938
+ {
2939
+ unsigned i;
2940
+
2941
+ memset(message, 0, desc->sizeof_message);
2942
+ message->descriptor = desc;
2943
+ for (i = 0; i < desc->n_fields; i++) {
2944
+ if (desc->fields[i].default_value != NULL &&
2945
+ desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED)
2946
+ {
2947
+ void *field =
2948
+ STRUCT_MEMBER_P(message, desc->fields[i].offset);
2949
+ const void *dv = desc->fields[i].default_value;
2950
+
2951
+ switch (desc->fields[i].type) {
2952
+ case PROTOBUF_C_TYPE_INT32:
2953
+ case PROTOBUF_C_TYPE_SINT32:
2954
+ case PROTOBUF_C_TYPE_SFIXED32:
2955
+ case PROTOBUF_C_TYPE_UINT32:
2956
+ case PROTOBUF_C_TYPE_FIXED32:
2957
+ case PROTOBUF_C_TYPE_FLOAT:
2958
+ case PROTOBUF_C_TYPE_ENUM:
2959
+ memcpy(field, dv, 4);
2960
+ break;
2961
+ case PROTOBUF_C_TYPE_INT64:
2962
+ case PROTOBUF_C_TYPE_SINT64:
2963
+ case PROTOBUF_C_TYPE_SFIXED64:
2964
+ case PROTOBUF_C_TYPE_UINT64:
2965
+ case PROTOBUF_C_TYPE_FIXED64:
2966
+ case PROTOBUF_C_TYPE_DOUBLE:
2967
+ memcpy(field, dv, 8);
2968
+ break;
2969
+ case PROTOBUF_C_TYPE_BOOL:
2970
+ memcpy(field, dv, sizeof(protobuf_c_boolean));
2971
+ break;
2972
+ case PROTOBUF_C_TYPE_BYTES:
2973
+ memcpy(field, dv, sizeof(ProtobufCBinaryData));
2974
+ break;
2975
+
2976
+ case PROTOBUF_C_TYPE_STRING:
2977
+ case PROTOBUF_C_TYPE_MESSAGE:
2978
+ /*
2979
+ * The next line essentially implements a cast
2980
+ * from const, which is totally unavoidable.
2981
+ */
2982
+ *(const void **) field = dv;
2983
+ break;
2984
+ }
2985
+ }
2986
+ }
2987
+ }
2988
+
2989
+ /**@}*/
2990
+
2991
+ /*
2992
+ * ScannedMember slabs (an unpacking implementation detail). Before doing real
2993
+ * unpacking, we first scan through the elements to see how many there are (for
2994
+ * repeated fields), and which field to use (for non-repeated fields given
2995
+ * twice).
2996
+ *
2997
+ * In order to avoid allocations for small messages, we keep a stack-allocated
2998
+ * slab of ScannedMembers of size FIRST_SCANNED_MEMBER_SLAB_SIZE (16). After we
2999
+ * fill that up, we allocate each slab twice as large as the previous one.
3000
+ */
3001
+ #define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4
3002
+
3003
+ /*
3004
+ * The number of slabs, including the stack-allocated ones; choose the number so
3005
+ * that we would overflow if we needed a slab larger than provided.
3006
+ */
3007
+ #define MAX_SCANNED_MEMBER_SLAB \
3008
+ (sizeof(unsigned int)*8 - 1 \
3009
+ - BOUND_SIZEOF_SCANNED_MEMBER_LOG2 \
3010
+ - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)
3011
+
3012
+ #define REQUIRED_FIELD_BITMAP_SET(index) \
3013
+ (required_fields_bitmap[(index)/8] |= (1UL<<((index)%8)))
3014
+
3015
+ #define REQUIRED_FIELD_BITMAP_IS_SET(index) \
3016
+ (required_fields_bitmap[(index)/8] & (1UL<<((index)%8)))
3017
+
3018
+ ProtobufCMessage *
3019
+ protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc,
3020
+ ProtobufCAllocator *allocator,
3021
+ size_t len, const uint8_t *data)
3022
+ {
3023
+ ProtobufCMessage *rv;
3024
+ size_t rem = len;
3025
+ const uint8_t *at = data;
3026
+ const ProtobufCFieldDescriptor *last_field = desc->fields + 0;
3027
+ ScannedMember first_member_slab[1UL <<
3028
+ FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2];
3029
+
3030
+ /*
3031
+ * scanned_member_slabs[i] is an array of arrays of ScannedMember.
3032
+ * The first slab (scanned_member_slabs[0] is just a pointer to
3033
+ * first_member_slab), above. All subsequent slabs will be allocated
3034
+ * using the allocator.
3035
+ */
3036
+ ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB + 1];
3037
+ unsigned which_slab = 0; /* the slab we are currently populating */
3038
+ unsigned in_slab_index = 0; /* number of members in the slab */
3039
+ size_t n_unknown = 0;
3040
+ unsigned f;
3041
+ unsigned j;
3042
+ unsigned i_slab;
3043
+ unsigned last_field_index = 0;
3044
+ unsigned required_fields_bitmap_len;
3045
+ unsigned char required_fields_bitmap_stack[16];
3046
+ unsigned char *required_fields_bitmap = required_fields_bitmap_stack;
3047
+ protobuf_c_boolean required_fields_bitmap_alloced = FALSE;
3048
+
3049
+ ASSERT_IS_MESSAGE_DESCRIPTOR(desc);
3050
+
3051
+ if (allocator == NULL)
3052
+ allocator = &protobuf_c__allocator;
3053
+
3054
+ rv = do_alloc(allocator, desc->sizeof_message);
3055
+ if (!rv)
3056
+ return (NULL);
3057
+ scanned_member_slabs[0] = first_member_slab;
3058
+
3059
+ required_fields_bitmap_len = (desc->n_fields + 7) / 8;
3060
+ if (required_fields_bitmap_len > sizeof(required_fields_bitmap_stack)) {
3061
+ required_fields_bitmap = do_alloc(allocator, required_fields_bitmap_len);
3062
+ if (!required_fields_bitmap) {
3063
+ do_free(allocator, rv);
3064
+ return (NULL);
3065
+ }
3066
+ required_fields_bitmap_alloced = TRUE;
3067
+ }
3068
+ memset(required_fields_bitmap, 0, required_fields_bitmap_len);
3069
+
3070
+ /*
3071
+ * Generated code always defines "message_init". However, we provide a
3072
+ * fallback for (1) users of old protobuf-c generated-code that do not
3073
+ * provide the function, and (2) descriptors constructed from some other
3074
+ * source (most likely, direct construction from the .proto file).
3075
+ */
3076
+ if (desc->message_init != NULL)
3077
+ protobuf_c_message_init(desc, rv);
3078
+ else
3079
+ message_init_generic(desc, rv);
3080
+
3081
+ while (rem > 0) {
3082
+ uint32_t tag;
3083
+ ProtobufCWireType wire_type;
3084
+ size_t used = parse_tag_and_wiretype(rem, at, &tag, &wire_type);
3085
+ const ProtobufCFieldDescriptor *field;
3086
+ ScannedMember tmp;
3087
+
3088
+ if (used == 0) {
3089
+ PROTOBUF_C_UNPACK_ERROR("error parsing tag/wiretype at offset %u",
3090
+ (unsigned) (at - data));
3091
+ goto error_cleanup_during_scan;
3092
+ }
3093
+ /*
3094
+ * \todo Consider optimizing for field[1].id == tag, if field[1]
3095
+ * exists!
3096
+ */
3097
+ if (last_field == NULL || last_field->id != tag) {
3098
+ /* lookup field */
3099
+ int field_index =
3100
+ int_range_lookup(desc->n_field_ranges,
3101
+ desc->field_ranges,
3102
+ tag);
3103
+ if (field_index < 0) {
3104
+ field = NULL;
3105
+ n_unknown++;
3106
+ } else {
3107
+ field = desc->fields + field_index;
3108
+ last_field = field;
3109
+ last_field_index = field_index;
3110
+ }
3111
+ } else {
3112
+ field = last_field;
3113
+ }
3114
+
3115
+ if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED)
3116
+ REQUIRED_FIELD_BITMAP_SET(last_field_index);
3117
+
3118
+ at += used;
3119
+ rem -= used;
3120
+ tmp.tag = tag;
3121
+ tmp.wire_type = wire_type;
3122
+ tmp.field = field;
3123
+ tmp.data = at;
3124
+ tmp.length_prefix_len = 0;
3125
+
3126
+ switch (wire_type) {
3127
+ case PROTOBUF_C_WIRE_TYPE_VARINT: {
3128
+ unsigned max_len = rem < 10 ? rem : 10;
3129
+ unsigned i;
3130
+
3131
+ for (i = 0; i < max_len; i++)
3132
+ if ((at[i] & 0x80) == 0)
3133
+ break;
3134
+ if (i == max_len) {
3135
+ PROTOBUF_C_UNPACK_ERROR("unterminated varint at offset %u",
3136
+ (unsigned) (at - data));
3137
+ goto error_cleanup_during_scan;
3138
+ }
3139
+ tmp.len = i + 1;
3140
+ break;
3141
+ }
3142
+ case PROTOBUF_C_WIRE_TYPE_64BIT:
3143
+ if (rem < 8) {
3144
+ PROTOBUF_C_UNPACK_ERROR("too short after 64bit wiretype at offset %u",
3145
+ (unsigned) (at - data));
3146
+ goto error_cleanup_during_scan;
3147
+ }
3148
+ tmp.len = 8;
3149
+ break;
3150
+ case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED: {
3151
+ size_t pref_len;
3152
+
3153
+ tmp.len = scan_length_prefixed_data(rem, at, &pref_len);
3154
+ if (tmp.len == 0) {
3155
+ /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */
3156
+ goto error_cleanup_during_scan;
3157
+ }
3158
+ tmp.length_prefix_len = pref_len;
3159
+ break;
3160
+ }
3161
+ case PROTOBUF_C_WIRE_TYPE_32BIT:
3162
+ if (rem < 4) {
3163
+ PROTOBUF_C_UNPACK_ERROR("too short after 32bit wiretype at offset %u",
3164
+ (unsigned) (at - data));
3165
+ goto error_cleanup_during_scan;
3166
+ }
3167
+ tmp.len = 4;
3168
+ break;
3169
+ default:
3170
+ PROTOBUF_C_UNPACK_ERROR("unsupported tag %u at offset %u",
3171
+ wire_type, (unsigned) (at - data));
3172
+ goto error_cleanup_during_scan;
3173
+ }
3174
+
3175
+ if (in_slab_index == (1UL <<
3176
+ (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)))
3177
+ {
3178
+ size_t size;
3179
+
3180
+ in_slab_index = 0;
3181
+ if (which_slab == MAX_SCANNED_MEMBER_SLAB) {
3182
+ PROTOBUF_C_UNPACK_ERROR("too many fields");
3183
+ goto error_cleanup_during_scan;
3184
+ }
3185
+ which_slab++;
3186
+ size = sizeof(ScannedMember)
3187
+ << (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2);
3188
+ scanned_member_slabs[which_slab] = do_alloc(allocator, size);
3189
+ if (scanned_member_slabs[which_slab] == NULL)
3190
+ goto error_cleanup_during_scan;
3191
+ }
3192
+ scanned_member_slabs[which_slab][in_slab_index++] = tmp;
3193
+
3194
+ if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED) {
3195
+ size_t *n = STRUCT_MEMBER_PTR(size_t, rv,
3196
+ field->quantifier_offset);
3197
+ if (wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
3198
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
3199
+ is_packable_type(field->type)))
3200
+ {
3201
+ size_t count;
3202
+ if (!count_packed_elements(field->type,
3203
+ tmp.len -
3204
+ tmp.length_prefix_len,
3205
+ tmp.data +
3206
+ tmp.length_prefix_len,
3207
+ &count))
3208
+ {
3209
+ PROTOBUF_C_UNPACK_ERROR("counting packed elements");
3210
+ goto error_cleanup_during_scan;
3211
+ }
3212
+ *n += count;
3213
+ } else {
3214
+ *n += 1;
3215
+ }
3216
+ }
3217
+
3218
+ at += tmp.len;
3219
+ rem -= tmp.len;
3220
+ }
3221
+
3222
+ /* allocate space for repeated fields, also check that all required fields have been set */
3223
+ for (f = 0; f < desc->n_fields; f++) {
3224
+ const ProtobufCFieldDescriptor *field = desc->fields + f;
3225
+ if (field->label == PROTOBUF_C_LABEL_REPEATED) {
3226
+ size_t siz =
3227
+ sizeof_elt_in_repeated_array(field->type);
3228
+ size_t *n_ptr =
3229
+ STRUCT_MEMBER_PTR(size_t, rv,
3230
+ field->quantifier_offset);
3231
+ if (*n_ptr != 0) {
3232
+ unsigned n = *n_ptr;
3233
+ void *a;
3234
+ *n_ptr = 0;
3235
+ assert(rv->descriptor != NULL);
3236
+ #define CLEAR_REMAINING_N_PTRS() \
3237
+ for(f++;f < desc->n_fields; f++) \
3238
+ { \
3239
+ field = desc->fields + f; \
3240
+ if (field->label == PROTOBUF_C_LABEL_REPEATED) \
3241
+ STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \
3242
+ }
3243
+ a = do_alloc(allocator, siz * n);
3244
+ if (!a) {
3245
+ CLEAR_REMAINING_N_PTRS();
3246
+ goto error_cleanup;
3247
+ }
3248
+ STRUCT_MEMBER(void *, rv, field->offset) = a;
3249
+ }
3250
+ } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
3251
+ if (field->default_value == NULL &&
3252
+ !REQUIRED_FIELD_BITMAP_IS_SET(f))
3253
+ {
3254
+ CLEAR_REMAINING_N_PTRS();
3255
+ PROTOBUF_C_UNPACK_ERROR("message '%s': missing required field '%s'",
3256
+ desc->name, field->name);
3257
+ goto error_cleanup;
3258
+ }
3259
+ }
3260
+ }
3261
+ #undef CLEAR_REMAINING_N_PTRS
3262
+
3263
+ /* allocate space for unknown fields */
3264
+ if (n_unknown) {
3265
+ rv->unknown_fields = do_alloc(allocator,
3266
+ n_unknown * sizeof(ProtobufCMessageUnknownField));
3267
+ if (rv->unknown_fields == NULL)
3268
+ goto error_cleanup;
3269
+ }
3270
+
3271
+ /* do real parsing */
3272
+ for (i_slab = 0; i_slab <= which_slab; i_slab++) {
3273
+ unsigned max = (i_slab == which_slab) ?
3274
+ in_slab_index : (1UL << (i_slab + 4));
3275
+ ScannedMember *slab = scanned_member_slabs[i_slab];
3276
+
3277
+ for (j = 0; j < max; j++) {
3278
+ if (!parse_member(slab + j, rv, allocator)) {
3279
+ PROTOBUF_C_UNPACK_ERROR("error parsing member %s of %s",
3280
+ slab->field ? slab->field->name : "*unknown-field*",
3281
+ desc->name);
3282
+ goto error_cleanup;
3283
+ }
3284
+ }
3285
+ }
3286
+
3287
+ /* cleanup */
3288
+ for (j = 1; j <= which_slab; j++)
3289
+ do_free(allocator, scanned_member_slabs[j]);
3290
+ if (required_fields_bitmap_alloced)
3291
+ do_free(allocator, required_fields_bitmap);
3292
+ return rv;
3293
+
3294
+ error_cleanup:
3295
+ protobuf_c_message_free_unpacked(rv, allocator);
3296
+ for (j = 1; j <= which_slab; j++)
3297
+ do_free(allocator, scanned_member_slabs[j]);
3298
+ if (required_fields_bitmap_alloced)
3299
+ do_free(allocator, required_fields_bitmap);
3300
+ return NULL;
3301
+
3302
+ error_cleanup_during_scan:
3303
+ do_free(allocator, rv);
3304
+ for (j = 1; j <= which_slab; j++)
3305
+ do_free(allocator, scanned_member_slabs[j]);
3306
+ if (required_fields_bitmap_alloced)
3307
+ do_free(allocator, required_fields_bitmap);
3308
+ return NULL;
3309
+ }
3310
+
3311
+ void
3312
+ protobuf_c_message_free_unpacked(ProtobufCMessage *message,
3313
+ ProtobufCAllocator *allocator)
3314
+ {
3315
+ const ProtobufCMessageDescriptor *desc;
3316
+ unsigned f;
3317
+
3318
+ if (message == NULL)
3319
+ return;
3320
+
3321
+ desc = message->descriptor;
3322
+
3323
+ ASSERT_IS_MESSAGE(message);
3324
+
3325
+ if (allocator == NULL)
3326
+ allocator = &protobuf_c__allocator;
3327
+ message->descriptor = NULL;
3328
+ for (f = 0; f < desc->n_fields; f++) {
3329
+ if (0 != (desc->fields[f].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) &&
3330
+ desc->fields[f].id !=
3331
+ STRUCT_MEMBER(uint32_t, message, desc->fields[f].quantifier_offset))
3332
+ {
3333
+ /* This is not the selected oneof, skip it */
3334
+ continue;
3335
+ }
3336
+
3337
+ if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) {
3338
+ size_t n = STRUCT_MEMBER(size_t,
3339
+ message,
3340
+ desc->fields[f].quantifier_offset);
3341
+ void *arr = STRUCT_MEMBER(void *,
3342
+ message,
3343
+ desc->fields[f].offset);
3344
+
3345
+ if (arr != NULL) {
3346
+ if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
3347
+ unsigned i;
3348
+ for (i = 0; i < n; i++)
3349
+ do_free(allocator, ((char **) arr)[i]);
3350
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
3351
+ unsigned i;
3352
+ for (i = 0; i < n; i++)
3353
+ do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data);
3354
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
3355
+ unsigned i;
3356
+ for (i = 0; i < n; i++)
3357
+ protobuf_c_message_free_unpacked(
3358
+ ((ProtobufCMessage **) arr)[i],
3359
+ allocator
3360
+ );
3361
+ }
3362
+ do_free(allocator, arr);
3363
+ }
3364
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
3365
+ char *str = STRUCT_MEMBER(char *, message,
3366
+ desc->fields[f].offset);
3367
+
3368
+ if (str && str != desc->fields[f].default_value)
3369
+ do_free(allocator, str);
3370
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
3371
+ void *data = STRUCT_MEMBER(ProtobufCBinaryData, message,
3372
+ desc->fields[f].offset).data;
3373
+ const ProtobufCBinaryData *default_bd;
3374
+
3375
+ default_bd = desc->fields[f].default_value;
3376
+ if (data != NULL &&
3377
+ (default_bd == NULL ||
3378
+ default_bd->data != data))
3379
+ {
3380
+ do_free(allocator, data);
3381
+ }
3382
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
3383
+ ProtobufCMessage *sm;
3384
+
3385
+ sm = STRUCT_MEMBER(ProtobufCMessage *, message,
3386
+ desc->fields[f].offset);
3387
+ if (sm && sm != desc->fields[f].default_value)
3388
+ protobuf_c_message_free_unpacked(sm, allocator);
3389
+ }
3390
+ }
3391
+
3392
+ for (f = 0; f < message->n_unknown_fields; f++)
3393
+ do_free(allocator, message->unknown_fields[f].data);
3394
+ if (message->unknown_fields != NULL)
3395
+ do_free(allocator, message->unknown_fields);
3396
+
3397
+ do_free(allocator, message);
3398
+ }
3399
+
3400
+ void
3401
+ protobuf_c_message_init(const ProtobufCMessageDescriptor * descriptor,
3402
+ void *message)
3403
+ {
3404
+ descriptor->message_init((ProtobufCMessage *) (message));
3405
+ }
3406
+
3407
+ protobuf_c_boolean
3408
+ protobuf_c_message_check(const ProtobufCMessage *message)
3409
+ {
3410
+ unsigned i;
3411
+
3412
+ if (!message ||
3413
+ !message->descriptor ||
3414
+ message->descriptor->magic != PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
3415
+ {
3416
+ return FALSE;
3417
+ }
3418
+
3419
+ for (i = 0; i < message->descriptor->n_fields; i++) {
3420
+ const ProtobufCFieldDescriptor *f = message->descriptor->fields + i;
3421
+ ProtobufCType type = f->type;
3422
+ ProtobufCLabel label = f->label;
3423
+ void *field = STRUCT_MEMBER_P (message, f->offset);
3424
+
3425
+ if (f->flags & PROTOBUF_C_FIELD_FLAG_ONEOF) {
3426
+ const uint32_t *oneof_case = STRUCT_MEMBER_P (message, f->quantifier_offset);
3427
+ if (f->id != *oneof_case) {
3428
+ continue; //Do not check if it is an unpopulated oneof member.
3429
+ }
3430
+ }
3431
+
3432
+ if (label == PROTOBUF_C_LABEL_REPEATED) {
3433
+ size_t *quantity = STRUCT_MEMBER_P (message, f->quantifier_offset);
3434
+
3435
+ if (*quantity > 0 && *(void **) field == NULL) {
3436
+ return FALSE;
3437
+ }
3438
+
3439
+ if (type == PROTOBUF_C_TYPE_MESSAGE) {
3440
+ ProtobufCMessage **submessage = *(ProtobufCMessage ***) field;
3441
+ unsigned j;
3442
+ for (j = 0; j < *quantity; j++) {
3443
+ if (!protobuf_c_message_check(submessage[j]))
3444
+ return FALSE;
3445
+ }
3446
+ } else if (type == PROTOBUF_C_TYPE_STRING) {
3447
+ char **string = *(char ***) field;
3448
+ unsigned j;
3449
+ for (j = 0; j < *quantity; j++) {
3450
+ if (!string[j])
3451
+ return FALSE;
3452
+ }
3453
+ } else if (type == PROTOBUF_C_TYPE_BYTES) {
3454
+ ProtobufCBinaryData *bd = *(ProtobufCBinaryData **) field;
3455
+ unsigned j;
3456
+ for (j = 0; j < *quantity; j++) {
3457
+ if (bd[j].len > 0 && bd[j].data == NULL)
3458
+ return FALSE;
3459
+ }
3460
+ }
3461
+
3462
+ } else { /* PROTOBUF_C_LABEL_REQUIRED or PROTOBUF_C_LABEL_OPTIONAL */
3463
+
3464
+ if (type == PROTOBUF_C_TYPE_MESSAGE) {
3465
+ ProtobufCMessage *submessage = *(ProtobufCMessage **) field;
3466
+ if (label == PROTOBUF_C_LABEL_REQUIRED || submessage != NULL) {
3467
+ if (!protobuf_c_message_check(submessage))
3468
+ return FALSE;
3469
+ }
3470
+ } else if (type == PROTOBUF_C_TYPE_STRING) {
3471
+ char *string = *(char **) field;
3472
+ if (label == PROTOBUF_C_LABEL_REQUIRED && string == NULL)
3473
+ return FALSE;
3474
+ } else if (type == PROTOBUF_C_TYPE_BYTES) {
3475
+ protobuf_c_boolean *has = STRUCT_MEMBER_P (message, f->quantifier_offset);
3476
+ ProtobufCBinaryData *bd = field;
3477
+ if (label == PROTOBUF_C_LABEL_REQUIRED || *has == TRUE) {
3478
+ if (bd->len > 0 && bd->data == NULL)
3479
+ return FALSE;
3480
+ }
3481
+ }
3482
+ }
3483
+ }
3484
+
3485
+ return TRUE;
3486
+ }
3487
+
3488
+ /* === services === */
3489
+
3490
+ typedef void (*GenericHandler) (void *service,
3491
+ const ProtobufCMessage *input,
3492
+ ProtobufCClosure closure,
3493
+ void *closure_data);
3494
+ void
3495
+ protobuf_c_service_invoke_internal(ProtobufCService *service,
3496
+ unsigned method_index,
3497
+ const ProtobufCMessage *input,
3498
+ ProtobufCClosure closure,
3499
+ void *closure_data)
3500
+ {
3501
+ GenericHandler *handlers;
3502
+ GenericHandler handler;
3503
+
3504
+ /*
3505
+ * Verify that method_index is within range. If this fails, you are
3506
+ * likely invoking a newly added method on an old service. (Although
3507
+ * other memory corruption bugs can cause this assertion too.)
3508
+ */
3509
+ assert(method_index < service->descriptor->n_methods);
3510
+
3511
+ /*
3512
+ * Get the array of virtual methods (which are enumerated by the
3513
+ * generated code).
3514
+ */
3515
+ handlers = (GenericHandler *) (service + 1);
3516
+
3517
+ /*
3518
+ * Get our method and invoke it.
3519
+ * \todo Seems like handler == NULL is a situation that needs handling.
3520
+ */
3521
+ handler = handlers[method_index];
3522
+ (*handler)(service, input, closure, closure_data);
3523
+ }
3524
+
3525
+ void
3526
+ protobuf_c_service_generated_init(ProtobufCService *service,
3527
+ const ProtobufCServiceDescriptor *descriptor,
3528
+ ProtobufCServiceDestroy destroy)
3529
+ {
3530
+ ASSERT_IS_SERVICE_DESCRIPTOR(descriptor);
3531
+ service->descriptor = descriptor;
3532
+ service->destroy = destroy;
3533
+ service->invoke = protobuf_c_service_invoke_internal;
3534
+ memset(service + 1, 0, descriptor->n_methods * sizeof(GenericHandler));
3535
+ }
3536
+
3537
+ void protobuf_c_service_destroy(ProtobufCService *service)
3538
+ {
3539
+ service->destroy(service);
3540
+ }
3541
+
3542
+ /* --- querying the descriptors --- */
3543
+
3544
+ const ProtobufCEnumValue *
3545
+ protobuf_c_enum_descriptor_get_value_by_name(const ProtobufCEnumDescriptor *desc,
3546
+ const char *name)
3547
+ {
3548
+ unsigned start = 0;
3549
+ unsigned count;
3550
+
3551
+ if (desc == NULL || desc->values_by_name == NULL)
3552
+ return NULL;
3553
+
3554
+ count = desc->n_value_names;
3555
+
3556
+ while (count > 1) {
3557
+ unsigned mid = start + count / 2;
3558
+ int rv = strcmp(desc->values_by_name[mid].name, name);
3559
+ if (rv == 0)
3560
+ return desc->values + desc->values_by_name[mid].index;
3561
+ else if (rv < 0) {
3562
+ count = start + count - (mid + 1);
3563
+ start = mid + 1;
3564
+ } else
3565
+ count = mid - start;
3566
+ }
3567
+ if (count == 0)
3568
+ return NULL;
3569
+ if (strcmp(desc->values_by_name[start].name, name) == 0)
3570
+ return desc->values + desc->values_by_name[start].index;
3571
+ return NULL;
3572
+ }
3573
+
3574
+ const ProtobufCEnumValue *
3575
+ protobuf_c_enum_descriptor_get_value(const ProtobufCEnumDescriptor *desc,
3576
+ int value)
3577
+ {
3578
+ int rv = int_range_lookup(desc->n_value_ranges, desc->value_ranges, value);
3579
+ if (rv < 0)
3580
+ return NULL;
3581
+ return desc->values + rv;
3582
+ }
3583
+
3584
+ const ProtobufCFieldDescriptor *
3585
+ protobuf_c_message_descriptor_get_field_by_name(const ProtobufCMessageDescriptor *desc,
3586
+ const char *name)
3587
+ {
3588
+ unsigned start = 0;
3589
+ unsigned count;
3590
+ const ProtobufCFieldDescriptor *field;
3591
+
3592
+ if (desc == NULL || desc->fields_sorted_by_name == NULL)
3593
+ return NULL;
3594
+
3595
+ count = desc->n_fields;
3596
+
3597
+ while (count > 1) {
3598
+ unsigned mid = start + count / 2;
3599
+ int rv;
3600
+ field = desc->fields + desc->fields_sorted_by_name[mid];
3601
+ rv = strcmp(field->name, name);
3602
+ if (rv == 0)
3603
+ return field;
3604
+ else if (rv < 0) {
3605
+ count = start + count - (mid + 1);
3606
+ start = mid + 1;
3607
+ } else
3608
+ count = mid - start;
3609
+ }
3610
+ if (count == 0)
3611
+ return NULL;
3612
+ field = desc->fields + desc->fields_sorted_by_name[start];
3613
+ if (strcmp(field->name, name) == 0)
3614
+ return field;
3615
+ return NULL;
3616
+ }
3617
+
3618
+ const ProtobufCFieldDescriptor *
3619
+ protobuf_c_message_descriptor_get_field(const ProtobufCMessageDescriptor *desc,
3620
+ unsigned value)
3621
+ {
3622
+ int rv = int_range_lookup(desc->n_field_ranges,desc->field_ranges, value);
3623
+ if (rv < 0)
3624
+ return NULL;
3625
+ return desc->fields + rv;
3626
+ }
3627
+
3628
+ const ProtobufCMethodDescriptor *
3629
+ protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescriptor *desc,
3630
+ const char *name)
3631
+ {
3632
+ unsigned start = 0;
3633
+ unsigned count;
3634
+
3635
+ if (desc == NULL || desc->method_indices_by_name == NULL)
3636
+ return NULL;
3637
+
3638
+ count = desc->n_methods;
3639
+
3640
+ while (count > 1) {
3641
+ unsigned mid = start + count / 2;
3642
+ unsigned mid_index = desc->method_indices_by_name[mid];
3643
+ const char *mid_name = desc->methods[mid_index].name;
3644
+ int rv = strcmp(mid_name, name);
3645
+
3646
+ if (rv == 0)
3647
+ return desc->methods + desc->method_indices_by_name[mid];
3648
+ if (rv < 0) {
3649
+ count = start + count - (mid + 1);
3650
+ start = mid + 1;
3651
+ } else {
3652
+ count = mid - start;
3653
+ }
3654
+ }
3655
+ if (count == 0)
3656
+ return NULL;
3657
+ if (strcmp(desc->methods[desc->method_indices_by_name[start]].name, name) == 0)
3658
+ return desc->methods + desc->method_indices_by_name[start];
3659
+ return NULL;
3660
+ }