pg_query 1.3.0 → 2.1.0

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