couchbase 4.4.2 → 4.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/BUILDING.md +182 -0
  2. package/CMakeLists.txt +13 -0
  3. package/CONTRIBUTING.md +1 -1
  4. package/README.md +4 -2
  5. package/deps/couchbase-cxx-cache/boringssl/e31ea00c1ea52052d2d78d44006cc88c80fa24a9/boringssl/src/BUILDING.md +206 -0
  6. package/deps/couchbase-cxx-client/CMakeLists.txt +18 -13
  7. package/deps/couchbase-cxx-client/README.md +2 -2
  8. package/deps/couchbase-cxx-client/cmake/APKBUILD.in +54 -0
  9. package/deps/couchbase-cxx-client/cmake/CompilerWarnings.cmake +0 -5
  10. package/deps/couchbase-cxx-client/cmake/Packaging.cmake +177 -10
  11. package/deps/couchbase-cxx-client/cmake/RPath.cmake +10 -0
  12. package/deps/couchbase-cxx-client/cmake/Testing.cmake +1 -1
  13. package/deps/couchbase-cxx-client/cmake/VersionInfo.cmake +28 -2
  14. package/deps/couchbase-cxx-client/cmake/build_version.hxx.in +1 -0
  15. package/deps/couchbase-cxx-client/cmake/couchbase-cxx-client.spec.in +45 -6
  16. package/deps/couchbase-cxx-client/cmake/couchbase_cxx_client.pc.in +2 -2
  17. package/deps/couchbase-cxx-client/cmake/debian/changelog.in +5 -0
  18. package/deps/couchbase-cxx-client/cmake/debian/compat +1 -0
  19. package/deps/couchbase-cxx-client/cmake/debian/control +40 -0
  20. package/deps/couchbase-cxx-client/cmake/debian/rules +41 -0
  21. package/deps/couchbase-cxx-client/cmake/debian/source/format +1 -0
  22. package/deps/couchbase-cxx-client/core/agent_group.cxx +8 -0
  23. package/deps/couchbase-cxx-client/core/agent_group.hxx +4 -0
  24. package/deps/couchbase-cxx-client/core/bucket.cxx +16 -20
  25. package/deps/couchbase-cxx-client/core/bucket.hxx +12 -12
  26. package/deps/couchbase-cxx-client/core/cluster.cxx +44 -52
  27. package/deps/couchbase-cxx-client/core/cluster_agent.cxx +8 -0
  28. package/deps/couchbase-cxx-client/core/cluster_agent.hxx +4 -0
  29. package/deps/couchbase-cxx-client/core/collections_component.cxx +2 -2
  30. package/deps/couchbase-cxx-client/core/columnar/agent.cxx +2 -2
  31. package/deps/couchbase-cxx-client/core/columnar/agent.hxx +1 -1
  32. package/deps/couchbase-cxx-client/core/columnar/management_component.cxx +3 -3
  33. package/deps/couchbase-cxx-client/core/columnar/query_component.cxx +103 -45
  34. package/deps/couchbase-cxx-client/core/columnar/query_component.hxx +1 -0
  35. package/deps/couchbase-cxx-client/core/free_form_http_request.hxx +8 -0
  36. package/deps/couchbase-cxx-client/core/http_component.cxx +55 -24
  37. package/deps/couchbase-cxx-client/core/http_component.hxx +4 -0
  38. package/deps/couchbase-cxx-client/core/impl/analytics.cxx +1 -0
  39. package/deps/couchbase-cxx-client/core/impl/analytics_index_manager.cxx +15 -15
  40. package/deps/couchbase-cxx-client/core/impl/bootstrap_error.hxx +10 -2
  41. package/deps/couchbase-cxx-client/core/impl/bucket.cxx +1 -1
  42. package/deps/couchbase-cxx-client/core/impl/bucket_manager.cxx +6 -6
  43. package/deps/couchbase-cxx-client/core/impl/cluster.cxx +36 -40
  44. package/deps/couchbase-cxx-client/core/impl/collection.cxx +29 -5
  45. package/deps/couchbase-cxx-client/core/impl/collection_manager.cxx +5 -5
  46. package/deps/couchbase-cxx-client/core/impl/error.cxx +24 -3
  47. package/deps/couchbase-cxx-client/core/impl/get_replica.hxx +2 -0
  48. package/deps/couchbase-cxx-client/core/impl/lookup_in_replica.hxx +2 -0
  49. package/deps/couchbase-cxx-client/core/impl/observe_poll.cxx +13 -5
  50. package/deps/couchbase-cxx-client/core/impl/observe_poll.hxx +1 -3
  51. package/deps/couchbase-cxx-client/core/impl/observe_seqno.hxx +2 -0
  52. package/deps/couchbase-cxx-client/core/impl/query.cxx +1 -0
  53. package/deps/couchbase-cxx-client/core/impl/query_index_manager.cxx +6 -6
  54. package/deps/couchbase-cxx-client/core/impl/scan_result.cxx +1 -1
  55. package/deps/couchbase-cxx-client/core/impl/search.cxx +2 -0
  56. package/deps/couchbase-cxx-client/core/impl/search_index_manager.cxx +12 -12
  57. package/deps/couchbase-cxx-client/core/io/http_command.hxx +31 -20
  58. package/deps/couchbase-cxx-client/core/io/http_session.cxx +5 -0
  59. package/deps/couchbase-cxx-client/core/io/http_session.hxx +17 -4
  60. package/deps/couchbase-cxx-client/core/io/http_session_manager.hxx +97 -49
  61. package/deps/couchbase-cxx-client/core/io/mcbp_command.hxx +15 -14
  62. package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +48 -33
  63. package/deps/couchbase-cxx-client/core/io/streams.cxx +256 -0
  64. package/deps/couchbase-cxx-client/core/io/streams.hxx +31 -155
  65. package/deps/couchbase-cxx-client/core/logger/configuration.hxx +5 -0
  66. package/deps/couchbase-cxx-client/core/logger/custom_rotating_file_sink.cxx +2 -3
  67. package/deps/couchbase-cxx-client/core/logger/logger.cxx +39 -7
  68. package/deps/couchbase-cxx-client/core/logger/logger.hxx +7 -0
  69. package/deps/couchbase-cxx-client/core/meta/features.hxx +11 -0
  70. package/deps/couchbase-cxx-client/core/meta/version.cxx +47 -6
  71. package/deps/couchbase-cxx-client/core/metrics/meter_wrapper.cxx +188 -0
  72. package/deps/couchbase-cxx-client/core/metrics/meter_wrapper.hxx +73 -0
  73. package/deps/couchbase-cxx-client/core/operations/document_analytics.cxx +23 -17
  74. package/deps/couchbase-cxx-client/core/operations/document_analytics.hxx +1 -0
  75. package/deps/couchbase-cxx-client/core/operations/document_append.hxx +2 -0
  76. package/deps/couchbase-cxx-client/core/operations/document_decrement.hxx +2 -0
  77. package/deps/couchbase-cxx-client/core/operations/document_exists.hxx +2 -0
  78. package/deps/couchbase-cxx-client/core/operations/document_get.hxx +2 -0
  79. package/deps/couchbase-cxx-client/core/operations/document_get_all_replicas.hxx +2 -0
  80. package/deps/couchbase-cxx-client/core/operations/document_get_and_lock.hxx +2 -0
  81. package/deps/couchbase-cxx-client/core/operations/document_get_and_touch.hxx +2 -0
  82. package/deps/couchbase-cxx-client/core/operations/document_get_any_replica.hxx +2 -0
  83. package/deps/couchbase-cxx-client/core/operations/document_get_projected.hxx +2 -0
  84. package/deps/couchbase-cxx-client/core/operations/document_increment.hxx +2 -0
  85. package/deps/couchbase-cxx-client/core/operations/document_insert.hxx +2 -0
  86. package/deps/couchbase-cxx-client/core/operations/document_lookup_in.hxx +2 -0
  87. package/deps/couchbase-cxx-client/core/operations/document_lookup_in_all_replicas.hxx +2 -0
  88. package/deps/couchbase-cxx-client/core/operations/document_lookup_in_any_replica.hxx +2 -0
  89. package/deps/couchbase-cxx-client/core/operations/document_mutate_in.hxx +2 -0
  90. package/deps/couchbase-cxx-client/core/operations/document_prepend.hxx +2 -0
  91. package/deps/couchbase-cxx-client/core/operations/document_query.hxx +1 -0
  92. package/deps/couchbase-cxx-client/core/operations/document_remove.hxx +2 -0
  93. package/deps/couchbase-cxx-client/core/operations/document_replace.hxx +2 -0
  94. package/deps/couchbase-cxx-client/core/operations/document_search.hxx +1 -0
  95. package/deps/couchbase-cxx-client/core/operations/document_touch.hxx +2 -0
  96. package/deps/couchbase-cxx-client/core/operations/document_unlock.hxx +2 -0
  97. package/deps/couchbase-cxx-client/core/operations/document_upsert.hxx +2 -0
  98. package/deps/couchbase-cxx-client/core/operations/document_view.hxx +1 -0
  99. package/deps/couchbase-cxx-client/core/operations/http_noop.hxx +2 -0
  100. package/deps/couchbase-cxx-client/core/operations/management/analytics_dataset_create.hxx +1 -0
  101. package/deps/couchbase-cxx-client/core/operations/management/analytics_dataset_drop.hxx +1 -0
  102. package/deps/couchbase-cxx-client/core/operations/management/analytics_dataset_get_all.hxx +1 -0
  103. package/deps/couchbase-cxx-client/core/operations/management/analytics_dataverse_create.hxx +1 -0
  104. package/deps/couchbase-cxx-client/core/operations/management/analytics_dataverse_drop.hxx +1 -0
  105. package/deps/couchbase-cxx-client/core/operations/management/analytics_get_pending_mutations.hxx +2 -0
  106. package/deps/couchbase-cxx-client/core/operations/management/analytics_index_create.hxx +1 -0
  107. package/deps/couchbase-cxx-client/core/operations/management/analytics_index_drop.hxx +1 -0
  108. package/deps/couchbase-cxx-client/core/operations/management/analytics_index_get_all.hxx +1 -0
  109. package/deps/couchbase-cxx-client/core/operations/management/analytics_link_connect.hxx +1 -0
  110. package/deps/couchbase-cxx-client/core/operations/management/analytics_link_create.hxx +1 -0
  111. package/deps/couchbase-cxx-client/core/operations/management/analytics_link_disconnect.hxx +1 -0
  112. package/deps/couchbase-cxx-client/core/operations/management/analytics_link_drop.hxx +1 -0
  113. package/deps/couchbase-cxx-client/core/operations/management/analytics_link_get_all.cxx +23 -15
  114. package/deps/couchbase-cxx-client/core/operations/management/analytics_link_get_all.hxx +4 -3
  115. package/deps/couchbase-cxx-client/core/operations/management/analytics_link_replace.hxx +1 -0
  116. package/deps/couchbase-cxx-client/core/operations/management/bucket_create.hxx +1 -0
  117. package/deps/couchbase-cxx-client/core/operations/management/bucket_describe.cxx +2 -1
  118. package/deps/couchbase-cxx-client/core/operations/management/bucket_describe.hxx +1 -0
  119. package/deps/couchbase-cxx-client/core/operations/management/bucket_drop.cxx +3 -1
  120. package/deps/couchbase-cxx-client/core/operations/management/bucket_drop.hxx +1 -0
  121. package/deps/couchbase-cxx-client/core/operations/management/bucket_flush.cxx +3 -1
  122. package/deps/couchbase-cxx-client/core/operations/management/bucket_flush.hxx +1 -0
  123. package/deps/couchbase-cxx-client/core/operations/management/bucket_get.cxx +3 -1
  124. package/deps/couchbase-cxx-client/core/operations/management/bucket_get.hxx +1 -0
  125. package/deps/couchbase-cxx-client/core/operations/management/bucket_get_all.hxx +1 -0
  126. package/deps/couchbase-cxx-client/core/operations/management/bucket_update.cxx +3 -1
  127. package/deps/couchbase-cxx-client/core/operations/management/bucket_update.hxx +1 -0
  128. package/deps/couchbase-cxx-client/core/operations/management/change_password.hxx +1 -0
  129. package/deps/couchbase-cxx-client/core/operations/management/cluster_describe.hxx +1 -0
  130. package/deps/couchbase-cxx-client/core/operations/management/cluster_developer_preview_enable.hxx +1 -0
  131. package/deps/couchbase-cxx-client/core/operations/management/collection_create.cxx +3 -2
  132. package/deps/couchbase-cxx-client/core/operations/management/collection_create.hxx +2 -0
  133. package/deps/couchbase-cxx-client/core/operations/management/collection_drop.cxx +5 -2
  134. package/deps/couchbase-cxx-client/core/operations/management/collection_drop.hxx +1 -0
  135. package/deps/couchbase-cxx-client/core/operations/management/collection_update.cxx +4 -2
  136. package/deps/couchbase-cxx-client/core/operations/management/collection_update.hxx +2 -0
  137. package/deps/couchbase-cxx-client/core/operations/management/collections_manifest_get.hxx +2 -0
  138. package/deps/couchbase-cxx-client/core/operations/management/eventing_deploy_function.hxx +3 -2
  139. package/deps/couchbase-cxx-client/core/operations/management/eventing_drop_function.hxx +3 -2
  140. package/deps/couchbase-cxx-client/core/operations/management/eventing_get_all_functions.hxx +3 -2
  141. package/deps/couchbase-cxx-client/core/operations/management/eventing_get_function.hxx +3 -2
  142. package/deps/couchbase-cxx-client/core/operations/management/eventing_get_status.hxx +3 -2
  143. package/deps/couchbase-cxx-client/core/operations/management/eventing_pause_function.hxx +3 -2
  144. package/deps/couchbase-cxx-client/core/operations/management/eventing_resume_function.hxx +3 -2
  145. package/deps/couchbase-cxx-client/core/operations/management/eventing_undeploy_function.hxx +3 -2
  146. package/deps/couchbase-cxx-client/core/operations/management/eventing_upsert_function.hxx +3 -2
  147. package/deps/couchbase-cxx-client/core/operations/management/freeform.hxx +2 -0
  148. package/deps/couchbase-cxx-client/core/operations/management/group_drop.hxx +1 -0
  149. package/deps/couchbase-cxx-client/core/operations/management/group_get.hxx +1 -0
  150. package/deps/couchbase-cxx-client/core/operations/management/group_get_all.hxx +1 -0
  151. package/deps/couchbase-cxx-client/core/operations/management/group_upsert.cxx +3 -3
  152. package/deps/couchbase-cxx-client/core/operations/management/group_upsert.hxx +1 -0
  153. package/deps/couchbase-cxx-client/core/operations/management/query_index_build.hxx +2 -0
  154. package/deps/couchbase-cxx-client/core/operations/management/query_index_build_deferred.hxx +3 -0
  155. package/deps/couchbase-cxx-client/core/operations/management/query_index_create.hxx +1 -0
  156. package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.hxx +1 -0
  157. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.hxx +2 -0
  158. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.hxx +3 -0
  159. package/deps/couchbase-cxx-client/core/operations/management/role_get_all.hxx +1 -0
  160. package/deps/couchbase-cxx-client/core/operations/management/scope_create.cxx +2 -1
  161. package/deps/couchbase-cxx-client/core/operations/management/scope_create.hxx +1 -0
  162. package/deps/couchbase-cxx-client/core/operations/management/scope_drop.cxx +4 -1
  163. package/deps/couchbase-cxx-client/core/operations/management/scope_drop.hxx +1 -0
  164. package/deps/couchbase-cxx-client/core/operations/management/scope_get_all.cxx +3 -1
  165. package/deps/couchbase-cxx-client/core/operations/management/scope_get_all.hxx +1 -0
  166. package/deps/couchbase-cxx-client/core/operations/management/search_get_stats.hxx +1 -0
  167. package/deps/couchbase-cxx-client/core/operations/management/search_index_analyze_document.cxx +3 -2
  168. package/deps/couchbase-cxx-client/core/operations/management/search_index_analyze_document.hxx +1 -0
  169. package/deps/couchbase-cxx-client/core/operations/management/search_index_control_ingest.cxx +3 -2
  170. package/deps/couchbase-cxx-client/core/operations/management/search_index_control_ingest.hxx +1 -0
  171. package/deps/couchbase-cxx-client/core/operations/management/search_index_control_plan_freeze.cxx +3 -2
  172. package/deps/couchbase-cxx-client/core/operations/management/search_index_control_plan_freeze.hxx +1 -0
  173. package/deps/couchbase-cxx-client/core/operations/management/search_index_control_query.cxx +3 -2
  174. package/deps/couchbase-cxx-client/core/operations/management/search_index_control_query.hxx +1 -0
  175. package/deps/couchbase-cxx-client/core/operations/management/search_index_drop.cxx +5 -2
  176. package/deps/couchbase-cxx-client/core/operations/management/search_index_drop.hxx +1 -0
  177. package/deps/couchbase-cxx-client/core/operations/management/search_index_get.cxx +5 -2
  178. package/deps/couchbase-cxx-client/core/operations/management/search_index_get.hxx +1 -0
  179. package/deps/couchbase-cxx-client/core/operations/management/search_index_get_all.cxx +4 -2
  180. package/deps/couchbase-cxx-client/core/operations/management/search_index_get_all.hxx +1 -0
  181. package/deps/couchbase-cxx-client/core/operations/management/search_index_get_documents_count.cxx +3 -2
  182. package/deps/couchbase-cxx-client/core/operations/management/search_index_get_documents_count.hxx +2 -0
  183. package/deps/couchbase-cxx-client/core/operations/management/search_index_get_stats.hxx +1 -0
  184. package/deps/couchbase-cxx-client/core/operations/management/search_index_upsert.cxx +5 -2
  185. package/deps/couchbase-cxx-client/core/operations/management/search_index_upsert.hxx +1 -0
  186. package/deps/couchbase-cxx-client/core/operations/management/user_drop.hxx +1 -0
  187. package/deps/couchbase-cxx-client/core/operations/management/user_get.hxx +1 -0
  188. package/deps/couchbase-cxx-client/core/operations/management/user_get_all.hxx +1 -0
  189. package/deps/couchbase-cxx-client/core/operations/management/user_upsert.cxx +3 -3
  190. package/deps/couchbase-cxx-client/core/operations/management/user_upsert.hxx +1 -0
  191. package/deps/couchbase-cxx-client/core/operations/management/view_index_drop.cxx +2 -1
  192. package/deps/couchbase-cxx-client/core/operations/management/view_index_drop.hxx +1 -0
  193. package/deps/couchbase-cxx-client/core/operations/management/view_index_get.cxx +2 -1
  194. package/deps/couchbase-cxx-client/core/operations/management/view_index_get.hxx +1 -0
  195. package/deps/couchbase-cxx-client/core/operations/management/view_index_get_all.cxx +3 -1
  196. package/deps/couchbase-cxx-client/core/operations/management/view_index_get_all.hxx +2 -0
  197. package/deps/couchbase-cxx-client/core/operations/management/view_index_upsert.cxx +2 -1
  198. package/deps/couchbase-cxx-client/core/operations/management/view_index_upsert.hxx +1 -0
  199. package/deps/couchbase-cxx-client/core/origin.cxx +37 -17
  200. package/deps/couchbase-cxx-client/core/platform/base64.cc +1 -1
  201. package/deps/couchbase-cxx-client/core/platform/random.cc +2 -0
  202. package/deps/couchbase-cxx-client/core/platform/uuid.h +6 -6
  203. package/deps/couchbase-cxx-client/core/row_streamer.cxx +1 -1
  204. package/deps/couchbase-cxx-client/core/sasl/scram-sha/stringutils.cc +1 -1
  205. package/deps/couchbase-cxx-client/core/sasl/scram-sha/stringutils.h +4 -4
  206. package/deps/couchbase-cxx-client/core/topology/configuration.hxx +2 -0
  207. package/deps/couchbase-cxx-client/core/topology/configuration_json.hxx +8 -0
  208. package/deps/couchbase-cxx-client/core/tracing/constants.hxx +3 -0
  209. package/deps/couchbase-cxx-client/core/tracing/tracer_wrapper.cxx +87 -0
  210. package/deps/couchbase-cxx-client/core/tracing/tracer_wrapper.hxx +57 -0
  211. package/deps/couchbase-cxx-client/core/transactions/async_attempt_context.hxx +9 -21
  212. package/deps/couchbase-cxx-client/core/transactions/attempt_context.hxx +6 -33
  213. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +57 -56
  214. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.hxx +17 -18
  215. package/deps/couchbase-cxx-client/core/transactions/staged_mutation.cxx +2 -2
  216. package/deps/couchbase-cxx-client/core/transactions/transaction_context.cxx +2 -2
  217. package/deps/couchbase-cxx-client/core/transactions/transaction_get_result.hxx +0 -20
  218. package/deps/couchbase-cxx-client/core/transactions/transactions.cxx +2 -2
  219. package/deps/couchbase-cxx-client/core/utils/connection_string.cxx +128 -52
  220. package/deps/couchbase-cxx-client/couchbase/analytics_options.hxx +4 -3
  221. package/deps/couchbase-cxx-client/couchbase/codec/tao_json_serializer.hxx +1 -1
  222. package/deps/couchbase-cxx-client/couchbase/common_options.hxx +16 -1
  223. package/deps/couchbase-cxx-client/couchbase/metrics/otel_meter.hxx +16 -20
  224. package/deps/couchbase-cxx-client/couchbase/mutate_in_specs.hxx +2 -2
  225. package/deps/couchbase-cxx-client/couchbase/query_options.hxx +4 -3
  226. package/deps/couchbase-cxx-client/couchbase/search_options.hxx +1 -1
  227. package/dist/analyticsindexmanager.d.ts +98 -14
  228. package/dist/analyticsindexmanager.js +452 -411
  229. package/dist/binding.d.ts +53 -4
  230. package/dist/bindingutilities.d.ts +26 -1
  231. package/dist/bindingutilities.js +108 -1
  232. package/dist/couchbase.d.ts +3 -1
  233. package/dist/couchbase.js +2 -0
  234. package/dist/rangeScan.d.ts +1 -1
  235. package/dist/rangeScan.js +1 -1
  236. package/dist/transactions.d.ts +34 -3
  237. package/dist/transactions.js +25 -18
  238. package/dist/transcoders.d.ts +68 -0
  239. package/dist/transcoders.js +194 -1
  240. package/dist/usermanager.d.ts +14 -14
  241. package/dist/usermanager.js +178 -228
  242. package/dist/utilities.js +4 -6
  243. package/dist/utilities_internal.js +1 -2
  244. package/package.json +9 -8
  245. package/src/binding.cpp +13 -13
  246. package/src/connection.cpp +22 -0
  247. package/src/connection.hpp +12 -0
  248. package/src/connection_autogen.cpp +100 -0
  249. package/src/jstocbpp_autogen.hpp +315 -8
  250. package/src/jstocbpp_transactions.hpp +1 -2
  251. package/tools/gen-bindings-js.js +38 -3
  252. package/tools/gen-bindings-json.py +575 -328
@@ -1,21 +1,36 @@
1
- import os
1
+ # Copyright 2016-2024. Couchbase, Inc.
2
+ # All Rights Reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
2
16
  import json
17
+ import os
18
+ import pathlib
3
19
  import re
4
- import clang.cindex
20
+ import subprocess
21
+ import sys
5
22
 
6
23
  from functools import reduce
24
+ from typing import (Dict, List, Optional, Tuple)
25
+
26
+ import clang.cindex
7
27
 
8
- # configurable part
28
+ # START CONFIGURATION
9
29
 
10
- CLANG_VERSION='13.0.1'
11
- # homebrew installs for llvm (brew info llvm gives details):
12
- # x64: /usr/local/opt/llvm/lib
13
- # arm64: /opt/homebrew/opt/llvm/lib
14
- llvmLibPath = "/usr/local/Cellar/llvm/13.0.1_1/lib/"
30
+ CXX_CLIENT_ROOT = os.path.join(pathlib.Path(__file__).parent.parent, 'deps', 'couchbase-cxx-client')
31
+ CXX_CLIENT_CACHE = os.path.join(pathlib.Path(__file__).parent.parent, 'deps', 'couchbase-cxx-cache')
15
32
 
16
- cxx_client_root = "../deps/couchbase-cxx-client"
17
- cxx_client_cache = "../deps/couchbase-cxx-cache"
18
- cxx_deps_include_paths = {
33
+ CXX_DEPS_INCLUDE_PATHS = {
19
34
  'asio': ['-I{0}/asio/{1}/asio/asio/include'],
20
35
  'fmt': ['-I{0}/fmt/{1}/fmt/include'],
21
36
  'gsl': ['-I{0}/gsl/{1}/gsl/include'],
@@ -25,7 +40,7 @@ cxx_deps_include_paths = {
25
40
  'spdlog': ['-I{0}/spdlog/{1}/spdlog/include'],
26
41
  }
27
42
 
28
- fileList = [
43
+ FILE_LIST = [
29
44
  "core/management/analytics_dataset.hxx",
30
45
  "core/management/analytics_index.hxx",
31
46
  "core/management/analytics_link_azure_blob_external.hxx",
@@ -76,7 +91,7 @@ fileList = [
76
91
  "core/vector_query_combination.hxx",
77
92
  ]
78
93
 
79
- typeList = [
94
+ TYPE_LIST = [
80
95
  "couchbase::core::management::analytics::dataset",
81
96
  "couchbase::core::management::analytics::index",
82
97
  "couchbase::core::management::analytics::azure_blob_external_link",
@@ -171,331 +186,563 @@ typeList = [
171
186
  "couchbase::read_preference"
172
187
  ]
173
188
 
174
- # end of configurable part
175
-
176
- clang.cindex.Config.set_library_path(llvmLibPath)
177
-
178
- def set_cxx_deps_include_paths(dep, includes):
179
- cpm_path = os.path.join(cxx_client_cache, dep)
180
- dir_pattern = r'[0-9a-z]{40}'
181
- cpm_hash_dir = next((d for d in os.listdir(cpm_path)
182
- if os.path.isdir(os.path.join(cpm_path, d)) and re.match(dir_pattern, d)),
183
- None)
184
- if not cpm_hash_dir:
185
- raise Exception(f'Unable to find CPM hash directory for path: {cpm_path}.')
186
- return list(map(lambda p: p.format(cxx_client_cache, cpm_hash_dir), includes))
187
-
188
- def list_headers_in_dir(path):
189
- # enumerates a folder but keeps the full pathing for the files returned
190
- # and removes certain files we don't want (like non-hxx, _json.hxx or _fmt.hxx)
191
-
192
- # list all the files in the folder
193
- files = os.listdir(path)
194
- # only include .hxx files
195
- files = list(filter(lambda x: x.endswith('.hxx'), files))
196
- # add the folder path back on
197
- files = list(map(lambda x: path + x, files))
198
- return files
199
-
200
-
201
- # parse through the list of files specified and expand wildcards
202
- fullFileList = []
203
- for filePath in fileList:
204
- if "*" in filePath:
205
- # wildcard path
206
- basePath = filePath[:-1]
207
- if "*" in basePath:
208
- # if there is still a wildcard, we have an issue...
209
- raise NotImplementedError(
210
- "wildcard only supported at end of file path")
211
- files = list_headers_in_dir(os.path.join(cxx_client_root, basePath))
212
- fullFileList = fullFileList + files
213
- else:
214
- # normal path
215
- fullFileList.append(os.path.join(cxx_client_root, filePath))
216
-
217
- # exclude _json.hxx files
218
- fullFileList = list(
219
- filter(lambda x: not x.endswith('_json.hxx'), fullFileList))
220
- # exclude _fmt.hxx files
221
- fullFileList = list(
222
- filter(lambda x: not x.endswith('_fmt.hxx'), fullFileList))
223
-
224
-
225
- # generate a list of regexps from the type list (for handling wildcards)
226
- typeListRe = list(map(lambda x: x.replace("*", "(.*)") + "(.*)", typeList))
227
-
228
-
229
- def is_included_type(name, with_durability=False):
230
-
231
- # TODO(brett19): This should be generalized somehow...
232
- if "is_compound_operation" in name:
233
- return False
234
-
235
- if "replica_context" in name:
236
- return False
237
-
238
- if with_durability is True and '_with_legacy_durability' not in name:
239
- return False
240
-
241
- for x in typeListRe:
242
- if re.fullmatch(x, name):
243
- return True
244
- return False
245
-
189
+ STD_COMPARATOR_TEMPLATES = ["std::less<{0}>", "std::greater<{0}>", "std::less_equal<{0}>", "std::greater_equal<{0}>"]
190
+ # flatten the list of lists
191
+ STD_COMPARATORS = list(reduce(lambda a, b: a + b,
192
+ list(map(lambda c: [c.format(s) for s in ['', 'void']], STD_COMPARATOR_TEMPLATES)),
193
+ []))
246
194
 
247
- opTypes = []
248
- opEnums = []
195
+ INTERNAL_STRUCTS = []
196
+ UNNAMED_STRUCT_DELIM = '::(unnamed struct'
249
197
 
198
+ # IMPORTANT: the templates must exist in the TYPE_LIST
199
+ TEMPLATED_REQUESTS = {
200
+ 'analytics_link_create_request': {
201
+ 'template_name': 'analytics_link_type',
202
+ 'templates': ['couchbase::core::management::analytics::azure_blob_external_link',
203
+ 'couchbase::core::management::analytics::couchbase_remote_link',
204
+ 'couchbase::core::management::analytics::s3_external_link']
205
+ },
206
+ 'analytics_link_replace_request': {
207
+ 'template_name': 'analytics_link_type',
208
+ 'templates': ['couchbase::core::management::analytics::azure_blob_external_link',
209
+ 'couchbase::core::management::analytics::couchbase_remote_link',
210
+ 'couchbase::core::management::analytics::s3_external_link']
211
+ },
212
+ }
250
213
 
251
- def parse_type(type):
252
- typeStr = type.get_canonical().spelling
253
- return parse_type_str(typeStr)
214
+ # END - CONFIGURATION
215
+
216
+
217
+ class BindingsGenerator:
218
+
219
+ def __init__(self,
220
+ llvm_clang_version: Optional[str] = None,
221
+ llvm_libdir: Optional[str] = None,
222
+ llvm_includedir: Optional[str] = None,
223
+ system_headers: Optional[str] = None,
224
+ verbose: Optional[bool] = False) -> None:
225
+ self._op_types = []
226
+ self._op_enums = []
227
+ self._full_file_list = []
228
+ # generate a list of regexps from the type list (for handling wildcards)
229
+ self._type_list_re = list(map(lambda x: x.replace("*", "(.*)") + "(.*)", TYPE_LIST))
230
+ self._verbose = verbose
231
+ self.configure_generator(llvm_clang_version, llvm_libdir, llvm_includedir, system_headers)
232
+
233
+ def configure_generator(self,
234
+ version: Optional[str] = None,
235
+ libdir: Optional[str] = None,
236
+ includedir: Optional[str] = None,
237
+ system_headers: Optional[str] = None) -> None:
238
+ if version is None:
239
+ version = os.environ.get('CN_LLVM_VERSION')
240
+ if version is None:
241
+ BindingsGenerator.find_llvm()
242
+ version = BindingsGenerator.get_llvm_version()
243
+ if version is None:
244
+ raise ValueError('Missing LLVM version.')
245
+
246
+ if includedir is None:
247
+ includedir = os.environ.get('CN_LLVM_INCLUDE')
248
+ if includedir is None:
249
+ includedir = BindingsGenerator.get_llvm_includedir()
250
+ if includedir is None:
251
+ raise ValueError('Missing LLVM include directory.')
252
+
253
+ if libdir is None:
254
+ libdir = os.environ.get('CN_LLVM_LIB')
255
+ if libdir is None:
256
+ libdir = BindingsGenerator.get_llvm_libdir()
257
+ if libdir is None:
258
+ raise ValueError('Missing LLVM lib directory.')
259
+
260
+ if system_headers is None:
261
+ system_headers = os.environ.get('CN_SYS_HEADERS')
262
+ if system_headers is None:
263
+ system_headers = BindingsGenerator.get_system_headers()
264
+ if system_headers is None:
265
+ raise ValueError('Missing system headers path.')
266
+
267
+ if self._verbose:
268
+ print(f'Using libdir={libdir}')
269
+ clang.cindex.Config.set_library_path(libdir)
270
+
271
+ self._include_paths = [
272
+ '-I/opt/homebrew/opt/llvm/include/c++/v1',
273
+ f'-I{CXX_CLIENT_ROOT}/',
274
+ f'-I/opt/homebrew/Cellar/llvm/{version}/lib/clang/{version[:2]}/include',
275
+ f'-I{system_headers}/usr/include'
276
+ ]
277
+
278
+ for dep, inc in CXX_DEPS_INCLUDE_PATHS.items():
279
+ self._include_paths.extend(BindingsGenerator.set_cxx_deps_include_paths(dep, inc))
280
+
281
+ if self._verbose:
282
+ print(f'Include paths={self._include_paths}')
283
+
284
+ self.set_file_list()
285
+
286
+ def gen_bindings(self) -> None:
287
+
288
+ for headerPath in self._full_file_list:
289
+ print("processing " + headerPath)
290
+ index = clang.cindex.Index.create()
291
+ if self._verbose is True:
292
+ args = ['-std=c++17', '-v', f'-isysroot{os.getcwd()}'] + self._include_paths
293
+ else:
294
+ args = ['-std=c++17', f'-isysroot{os.getcwd()}'] + self._include_paths
295
+ translation_unit = index.parse(headerPath, args=args)
296
+
297
+ # output clang compiler diagnostics information (for debugging)
298
+ if 1:
299
+ for diagnostic in translation_unit.diagnostics:
300
+ diagnosticMsg = diagnostic.format()
301
+ print(diagnostic)
302
+
303
+ self.traverse(translation_unit.cursor, [], headerPath)
304
+
305
+ jsonData = json.dumps({
306
+ 'op_structs': self._op_types,
307
+ 'op_enums': self._op_enums
308
+ })
309
+
310
+ f = open("bindings.json", "w")
311
+ f.write(jsonData)
312
+ f.close()
313
+
314
+ def set_file_list(self) -> None:
315
+ for file_path in FILE_LIST:
316
+ if "*" in file_path:
317
+ # wildcard path
318
+ basePath = file_path[:-1]
319
+ if "*" in basePath:
320
+ # if there is still a wildcard, we have an issue...
321
+ raise NotImplementedError(
322
+ "wildcard only supported at end of file path")
323
+ if basePath[-1] != os.path.sep:
324
+ tokens = basePath.split(os.path.sep)
325
+ # filter = tokens[-1]
326
+ files = BindingsGenerator.list_headers_in_dir(os.path.join(CXX_CLIENT_ROOT, *tokens[:-1]),
327
+ tokens[-1])
328
+ else:
329
+ files = BindingsGenerator.list_headers_in_dir(os.path.join(CXX_CLIENT_ROOT, basePath))
330
+ self._full_file_list = self._full_file_list + files
331
+ else:
332
+ # normal path
333
+ self._full_file_list.append(os.path.join(CXX_CLIENT_ROOT, file_path))
334
+
335
+ # exclude _json.hxx files
336
+ self._full_file_list = list(filter(lambda x: not x.endswith('_json.hxx'), self._full_file_list))
337
+ # exclude _fmt.hxx files
338
+ self._full_file_list = list(filter(lambda x: not x.endswith('_fmt.hxx'), self._full_file_list))
339
+
340
+ def traverse(self, node, namespace, main_file) -> None:
341
+ # only scan the elements of the file we parsed
342
+ if node.location.file is not None and node.location.file.name != main_file:
343
+ return
344
+
345
+ if node.kind == clang.cindex.CursorKind.STRUCT_DECL or node.kind == clang.cindex.CursorKind.CLASS_DECL:
346
+ full_struct_name = "::".join([*namespace, node.displayname])
347
+ if full_struct_name.endswith('::') or UNNAMED_STRUCT_DELIM in full_struct_name:
348
+ if full_struct_name.endswith('::'):
349
+ struct_name = full_struct_name
350
+ else:
351
+ struct_name = full_struct_name.split(UNNAMED_STRUCT_DELIM)[0]
352
+ match = next((s for s in INTERNAL_STRUCTS if struct_name in s), None)
353
+ if match:
354
+ full_struct_name = match
355
+
356
+ if (BindingsGenerator.is_included_type(full_struct_name, self._type_list_re)
357
+ or full_struct_name in INTERNAL_STRUCTS):
358
+ struct_fields = []
359
+ parents = []
360
+ for child in node.get_children():
361
+ if child.kind == clang.cindex.CursorKind.FIELD_DECL:
362
+ struct_type = BindingsGenerator.parse_type(child.type)
363
+ type_str = child.type.get_canonical().spelling
364
+ if 'unnamed' in type_str:
365
+ name_tokens = type_str.split('::')
366
+ name_override = '::'.join(name_tokens[:-1] + [child.displayname])
367
+ struct_type['name'] = name_override
368
+ INTERNAL_STRUCTS.append(name_override)
369
+
370
+ struct_fields.append({
371
+ "name": child.displayname,
372
+ "type": struct_type,
373
+ })
374
+ elif child.kind == clang.cindex.CursorKind.CXX_BASE_SPECIFIER:
375
+ parents.append("::".join([*namespace, child.displayname]))
376
+
377
+ if len(parents) > 0:
378
+ part_op_types = [ot for ot in self._op_types if ot['name'] in parents]
379
+ print(f'{part_op_types=}')
380
+ for sot in part_op_types:
381
+ struct_fields.extend(sot['fields'])
382
+
383
+ # replica read changes introduced duplicate get requests
384
+ if any(map(lambda op: op['name'] == full_struct_name, self._op_types)):
385
+ return
386
+
387
+ self._op_types.append({
388
+ "name": full_struct_name,
389
+ "fields": struct_fields,
390
+ })
391
+ if node.kind == clang.cindex.CursorKind.TYPE_ALIAS_DECL:
392
+ full_struct_name = "::".join([*namespace, node.displayname])
393
+ if BindingsGenerator.is_included_type(full_struct_name, self._type_list_re, with_durability=True):
394
+ type_ref = next((c for c in node.get_children() if c.kind == clang.cindex.CursorKind.TYPE_REF), None)
395
+ if type_ref:
396
+ base_request_name = type_ref.displayname.replace('struct', '').strip()
397
+ base_request = next((op for op in self._op_types if op['name'] == base_request_name), None)
398
+ if base_request:
399
+ new_fields = [f for f in base_request['fields'] if f['name'] != 'durability_level']
400
+ new_fields.extend([
401
+ {"name": "persist_to", "type": {"name": "couchbase::persist_to"}},
402
+ {"name": "replicate_to", "type": {"name": "couchbase::replicate_to"}}
403
+ ])
254
404
 
255
- std_comparator_templates = ["std::less<{0}>", "std::greater<{0}>", "std::less_equal<{0}>", "std::greater_equal<{0}>"]
256
- # flatten the list of lists
257
- std_comparators = list(reduce(lambda a, b: a + b,
258
- list(map(lambda c: [c.format(s) for s in ['', 'void']], std_comparator_templates)),
259
- []))
405
+ self._op_types.append({
406
+ "name": full_struct_name,
407
+ "fields": new_fields
408
+ })
409
+ if node.kind == clang.cindex.CursorKind.ENUM_DECL:
410
+ full_enum_name = "::".join([*namespace, node.displayname])
411
+ if BindingsGenerator.is_included_type(full_enum_name, self._type_list_re):
412
+ enumValues = []
413
+
414
+ for child in node.get_children():
415
+ if child.kind == clang.cindex.CursorKind.ENUM_CONSTANT_DECL:
416
+ enumValues.append({
417
+ "name": child.displayname,
418
+ "value": child.enum_value,
419
+ })
420
+ self._op_enums.append({
421
+ "name": full_enum_name,
422
+ "type": BindingsGenerator.parse_type(node.enum_type),
423
+ "values": enumValues,
424
+ })
425
+
426
+ if node.kind == clang.cindex.CursorKind.NAMESPACE:
427
+ namespace = [*namespace, node.displayname]
428
+ if node.kind == clang.cindex.CursorKind.CLASS_DECL:
429
+ namespace = [*namespace, node.displayname]
430
+ if node.kind == clang.cindex.CursorKind.STRUCT_DECL:
431
+ namespace = [*namespace, node.displayname]
432
+ if node.kind == clang.cindex.CursorKind.CLASS_TEMPLATE:
433
+ name_tokens = node.displayname.split('<')
434
+ if len(name_tokens) == 2 and name_tokens[0] in TEMPLATED_REQUESTS:
435
+ req = TEMPLATED_REQUESTS.get(name_tokens[0])
436
+ full_struct_name = "::".join([*namespace, node.displayname])
437
+ for template in req['templates']:
438
+ struct_fields = []
439
+ for child in node.get_children():
440
+ if child.kind == clang.cindex.CursorKind.FIELD_DECL:
441
+ type_str = child.type.get_canonical().spelling
442
+ if 'type-parameter' in type_str:
443
+ struct_type = {
444
+ 'name': 'template',
445
+ 'of': {'name': template}}
446
+ else:
447
+ struct_type = BindingsGenerator.parse_type(child.type)
448
+ # print(f'struct_type={child.type}; type.kind={child.type.kind}; {type_str=}, displayname={child.displayname}')
449
+ struct_fields.append({
450
+ "name": child.displayname,
451
+ "type": struct_type,
452
+ })
453
+ self._op_types.append({
454
+ "name": full_struct_name.replace(req['template_name'], template),
455
+ "fields": struct_fields,
456
+ })
457
+ # return
458
+
459
+ for child in node.get_children():
460
+ self.traverse(child, namespace, main_file)
461
+
462
+ @staticmethod
463
+ def set_cxx_deps_include_paths(dep, includes):
464
+ cpm_path = os.path.join(CXX_CLIENT_CACHE, dep)
465
+ dir_pattern = r'[0-9a-z]{40}'
466
+ cpm_hash_dir = next((d for d in os.listdir(cpm_path)
467
+ if os.path.isdir(os.path.join(cpm_path, d)) and re.match(dir_pattern, d)),
468
+ None)
469
+ if not cpm_hash_dir:
470
+ raise Exception(f'Unable to find CPM hash directory for path: {cpm_path}.')
471
+ return list(map(lambda p: p.format(CXX_CLIENT_CACHE, cpm_hash_dir), includes))
472
+
473
+ @staticmethod
474
+ def list_headers_in_dir(path: str, file_startswith: Optional[str] = None) -> List[str]:
475
+ # enumerates a folder but keeps the full pathing for the files returned
476
+ # and removes certain files we don't want (like non-hxx, _json.hxx or _fmt.hxx)
477
+
478
+ # list all the files in the folder
479
+ files = os.listdir(path)
480
+
481
+ if file_startswith is not None:
482
+ files = list(filter(lambda f: f.endswith('.hxx') and f.startswith(file_startswith), files))
483
+ # add the folder path back on
484
+ files = list(map(lambda f: os.path.join(path, f), files))
485
+ else:
486
+ # only include .hxx files
487
+ files = list(filter(lambda f: f.endswith('.hxx'), files))
488
+ # add the folder path back on
489
+ files = list(map(lambda f: path + f, files))
490
+ return files
491
+
492
+ @staticmethod
493
+ def is_included_type(name: str, type_list_re: List[str], with_durability: Optional[bool] = False) -> bool:
494
+
495
+ # TODO(brett19): This should be generalized somehow...
496
+ if "is_compound_operation" in name:
497
+ return False
498
+
499
+ if "replica_context" in name:
500
+ return False
501
+
502
+ if with_durability is True and '_with_legacy_durability' not in name:
503
+ return False
504
+
505
+ for x in type_list_re:
506
+ if re.fullmatch(x, name):
507
+ return True
508
+ return False
260
509
 
261
- def parse_type_str(typeStr):
262
- if typeStr == "std::mutex":
263
- return {"name": "std::mutex"}
264
- if typeStr == "std::string":
265
- return {"name": "std::string"}
266
- if typeStr == "std::chrono::duration<long long>":
267
- return {"name": "std::chrono::seconds"}
268
- if typeStr == "std::chrono::duration<long long, std::ratio<1, 1000>>":
269
- return {"name": "std::chrono::milliseconds"}
270
- if typeStr == "std::chrono::duration<long long, std::ratio<1, 1000000>>":
271
- return {"name": "std::chrono::microseconds"}
272
- if typeStr == "std::chrono::duration<long long, std::ratio<1, 1000000000>>":
273
- return {"name": "std::chrono::nanoseconds"}
274
- if typeStr == "std::error_code":
275
- return {"name": "std::error_code"}
276
- if typeStr == "std::monostate":
277
- return {"name": "std::monostate"}
278
- if typeStr == "std::byte":
279
- return {"name": "std::byte"}
280
- if typeStr == "unsigned long":
281
- return {"name": "std::size_t"}
282
- if typeStr == "char":
283
- return {"name": "std::int8_t"}
284
- if typeStr == "unsigned char":
285
- return {"name": "std::uint8_t"}
286
- if typeStr == "short":
287
- return {"name": "std::int16_t"}
288
- if typeStr == "unsigned short":
289
- return {"name": "std::uint16_t"}
290
- if typeStr == "int":
291
- return {"name": "std::int32_t"}
292
- if typeStr == "unsigned int":
293
- return {"name": "std::uint32_t"}
294
- if typeStr == "long long":
295
- return {"name": "std::int64_t"}
296
- if typeStr == "unsigned long long":
297
- return {"name": "std::uint64_t"}
298
- if typeStr == "bool":
299
- return {"name": "std::bool"}
300
- if typeStr == "float":
301
- return {"name": "std::float"}
302
- if typeStr == "double":
303
- return {"name": "std::double"}
304
- if typeStr == "std::nullptr_t":
305
- return {"name": "std::nullptr_t"}
306
- if typeStr in std_comparators:
307
- if 'void' in typeStr:
308
- return {"name": typeStr.replace("void", "")}
309
- return {"name": typeStr}
310
-
311
- tplParts = typeStr.split("<", 1)
312
- if len(tplParts) > 1:
313
- tplClassName = tplParts[0]
314
- tplParams = tplParts[1][:-1]
315
- if tplClassName == "std::function":
316
- return {
317
- "name": "std::function"
318
- }
319
- if tplClassName == "std::optional":
320
- return {
321
- "name": "std::optional",
322
- "of": parse_type_str(tplParams)
323
- }
324
- if tplClassName == "std::vector":
325
- return {
326
- "name": "std::vector",
327
- "of": parse_type_str(tplParams)
328
- }
329
- if tplClassName == "std::set":
330
- return {
331
- "name": "std::set",
332
- "of": parse_type_str(tplParams)
333
- }
334
- if tplClassName == "std::variant":
335
- variantParts = tplParams.split(", ")
336
- variantTypes = []
337
- for variantPart in variantParts:
338
- variantTypes.append(parse_type_str(variantPart))
339
- return {
340
- "name": "std::variant",
341
- "of": variantTypes
342
- }
343
- if tplClassName == "std::array":
344
- variantParts = tplParams.split(", ")
345
- if len(variantParts) != 2:
346
- print("FAILED TO PARSE ARRAY TYPES: " + typeStr)
347
- return {"name": "unknown", "str": typeStr}
348
- return {
349
- "name": "std::array",
350
- "of": parse_type_str(variantParts[0]),
351
- "size": int(variantParts[1])
352
- }
353
- if tplClassName == "std::map":
354
- variantParts = tplParams.split(", ")
355
- if len(variantParts) < 2 or len(variantParts) > 3:
356
- print("FAILED TO PARSE MAP TYPES: " + typeStr)
357
- return {"name": "unknown", "str": typeStr}
358
-
359
- if len(variantParts) == 2:
510
+ @staticmethod
511
+ def parse_type(type_: str) -> Dict[str, str]:
512
+ type_str = type_.get_canonical().spelling
513
+ return BindingsGenerator.parse_type_str(type_str)
514
+
515
+ @staticmethod
516
+ def parse_type_str(type_str: str) -> Dict[str, str]:
517
+ if type_str == "std::mutex":
518
+ return {"name": "std::mutex"}
519
+ if type_str == "std::string":
520
+ return {"name": "std::string"}
521
+ if type_str == "std::chrono::duration<long long>":
522
+ return {"name": "std::chrono::seconds"}
523
+ if type_str == "std::chrono::duration<long long, std::ratio<1, 1000>>":
524
+ return {"name": "std::chrono::milliseconds"}
525
+ if type_str == "std::chrono::duration<long long, std::ratio<1, 1000000>>":
526
+ return {"name": "std::chrono::microseconds"}
527
+ if type_str == "std::chrono::duration<long long, std::ratio<1, 1000000000>>":
528
+ return {"name": "std::chrono::nanoseconds"}
529
+ if type_str == "std::error_code":
530
+ return {"name": "std::error_code"}
531
+ if type_str == "std::monostate":
532
+ return {"name": "std::monostate"}
533
+ if type_str == "std::byte":
534
+ return {"name": "std::byte"}
535
+ if type_str == "unsigned long":
536
+ return {"name": "std::size_t"}
537
+ if type_str == "char":
538
+ return {"name": "std::int8_t"}
539
+ if type_str == "unsigned char":
540
+ return {"name": "std::uint8_t"}
541
+ if type_str == "short":
542
+ return {"name": "std::int16_t"}
543
+ if type_str == "unsigned short":
544
+ return {"name": "std::uint16_t"}
545
+ if type_str == "int":
546
+ return {"name": "std::int32_t"}
547
+ if type_str == "unsigned int":
548
+ return {"name": "std::uint32_t"}
549
+ if type_str == "long long":
550
+ return {"name": "std::int64_t"}
551
+ if type_str == "unsigned long long":
552
+ return {"name": "std::uint64_t"}
553
+ if type_str == "bool":
554
+ return {"name": "std::bool"}
555
+ if type_str == "float":
556
+ return {"name": "std::float"}
557
+ if type_str == "double":
558
+ return {"name": "std::double"}
559
+ if type_str == "std::nullptr_t":
560
+ return {"name": "std::nullptr_t"}
561
+ if type_str in STD_COMPARATORS:
562
+ if 'void' in type_str:
563
+ return {"name": type_str.replace("void", "")}
564
+ return {"name": type_str}
565
+
566
+ tplParts = type_str.split("<", 1)
567
+ if len(tplParts) > 1:
568
+ tplClassName = tplParts[0]
569
+ tplParams = tplParts[1][:-1]
570
+ if tplClassName == "std::function":
360
571
  return {
361
- "name": "std::map",
362
- "of": parse_type_str(variantParts[0]),
363
- "to": parse_type_str(variantParts[1])
572
+ "name": "std::function"
364
573
  }
365
- else:
574
+ if tplClassName == "std::optional":
366
575
  return {
367
- "name": "std::map",
368
- "of": parse_type_str(variantParts[0]),
369
- "to": parse_type_str(variantParts[1]),
370
- "comparator": parse_type_str(variantParts[2])
576
+ "name": "std::optional",
577
+ "of": BindingsGenerator.parse_type_str(tplParams)
578
+ }
579
+ if tplClassName == "std::vector":
580
+ return {
581
+ "name": "std::vector",
582
+ "of": BindingsGenerator.parse_type_str(tplParams)
583
+ }
584
+ if tplClassName == "std::set":
585
+ return {
586
+ "name": "std::set",
587
+ "of": BindingsGenerator. parse_type_str(tplParams)
588
+ }
589
+ if tplClassName == "std::variant":
590
+ variantParts = tplParams.split(", ")
591
+ variantTypes = []
592
+ for variantPart in variantParts:
593
+ variantTypes.append(BindingsGenerator.parse_type_str(variantPart))
594
+ return {
595
+ "name": "std::variant",
596
+ "of": variantTypes
597
+ }
598
+ if tplClassName == "std::array":
599
+ variantParts = tplParams.split(", ")
600
+ if len(variantParts) != 2:
601
+ print("FAILED TO PARSE ARRAY TYPES: " + type_str)
602
+ return {"name": "unknown", "str": type_str}
603
+ return {
604
+ "name": "std::array",
605
+ "of": BindingsGenerator.parse_type_str(variantParts[0]),
606
+ "size": int(variantParts[1])
607
+ }
608
+ if tplClassName == "std::map":
609
+ variantParts = tplParams.split(", ")
610
+ if len(variantParts) < 2 or len(variantParts) > 3:
611
+ print("FAILED TO PARSE MAP TYPES: " + type_str)
612
+ return {"name": "unknown", "str": type_str}
613
+
614
+ if len(variantParts) == 2:
615
+ return {
616
+ "name": "std::map",
617
+ "of": BindingsGenerator.parse_type_str(variantParts[0]),
618
+ "to": BindingsGenerator.parse_type_str(variantParts[1])
619
+ }
620
+ else:
621
+ return {
622
+ "name": "std::map",
623
+ "of": BindingsGenerator.parse_type_str(variantParts[0]),
624
+ "to": BindingsGenerator.parse_type_str(variantParts[1]),
625
+ "comparator": BindingsGenerator.parse_type_str(variantParts[2])
626
+ }
627
+
628
+ if tplClassName == "std::shared_ptr":
629
+ return {
630
+ "name": "std::shared_ptr",
631
+ "of": BindingsGenerator.parse_type_str(tplParams)
371
632
  }
372
633
 
373
- if tplClassName == "std::shared_ptr":
374
- return {
375
- "name": "std::shared_ptr",
376
- "of": parse_type_str(tplParams)
377
- }
378
-
379
- if not typeStr.startswith("couchbase::"):
380
- print("FAILED TO PARSE STRING TYPE: " + typeStr)
381
- return {"name": "unknown", "str": typeStr}
382
-
383
- if 'unnamed struct' in typeStr:
384
- print("WARNING: Found unnamed struct: " + typeStr)
385
-
386
- return {"name": typeStr}
634
+ if not type_str.startswith("couchbase::"):
635
+ print("FAILED TO PARSE STRING TYPE: " + type_str)
636
+ return {"name": "unknown", "str": type_str}
387
637
 
388
- internal_structs = []
389
- UNNAMED_STRUCT_DELIM = '::(unnamed struct'
638
+ if 'unnamed struct' in type_str:
639
+ print("WARNING: Found unnamed struct: " + type_str)
390
640
 
391
- def traverse(node, namespace, main_file):
392
- # only scan the elements of the file we parsed
393
- if node.location.file != None and node.location.file.name != main_file:
394
- return
395
-
396
- if node.kind == clang.cindex.CursorKind.STRUCT_DECL or node.kind == clang.cindex.CursorKind.CLASS_DECL:
397
- fullStructName = "::".join([*namespace, node.displayname])
398
- if fullStructName.endswith('::') or UNNAMED_STRUCT_DELIM in fullStructName:
399
- struct_name = fullStructName if fullStructName.endswith('::') else fullStructName.split(UNNAMED_STRUCT_DELIM)[0]
400
- match = next((s for s in internal_structs if struct_name in s), None)
401
- if match:
402
- fullStructName = match
403
-
404
- if is_included_type(fullStructName) or fullStructName in internal_structs:
405
- structFields = []
406
- for child in node.get_children():
407
- if child.kind == clang.cindex.CursorKind.FIELD_DECL:
408
- struct_type = parse_type(child.type)
409
- type_str = child.type.get_canonical().spelling
410
- if 'unnamed' in type_str:
411
- name_tokens = type_str.split('::')
412
- name_override = '::'.join(name_tokens[:-1] + [child.displayname])
413
- struct_type['name'] = name_override
414
- internal_structs.append(name_override)
415
-
416
- structFields.append({
417
- "name": child.displayname,
418
- "type": struct_type,
419
- })
420
- # replica read changes introduced duplicate get requests
421
- if any(map(lambda op: op['name'] == fullStructName, opTypes)):
422
- return
423
-
424
- opTypes.append({
425
- "name": fullStructName,
426
- "fields": structFields,
427
- })
428
- if node.kind == clang.cindex.CursorKind.TYPE_ALIAS_DECL:
429
- fullStructName = "::".join([*namespace, node.displayname])
430
- if is_included_type(fullStructName, with_durability=True):
431
- type_ref = next((c for c in node.get_children() if c.kind == clang.cindex.CursorKind.TYPE_REF), None)
432
- if type_ref:
433
- base_request_name = type_ref.displayname.replace('struct', '').strip()
434
- base_request = next((op for op in opTypes if op['name'] == base_request_name), None)
435
- if base_request:
436
- new_fields = [f for f in base_request['fields'] if f['name'] != 'durability_level']
437
- new_fields.extend([
438
- {"name":"persist_to", "type":{"name":"couchbase::persist_to"}},
439
- {"name":"replicate_to", "type":{"name":"couchbase::replicate_to"}}
440
- ])
641
+ return {"name": type_str}
441
642
 
442
- opTypes.append({
443
- "name": fullStructName,
444
- "fields": new_fields
445
- })
446
- if node.kind == clang.cindex.CursorKind.ENUM_DECL:
447
- fullEnumName = "::".join([*namespace, node.displayname])
448
- if is_included_type(fullEnumName):
449
- enumValues = []
450
-
451
- for child in node.get_children():
452
- if child.kind == clang.cindex.CursorKind.ENUM_CONSTANT_DECL:
453
- enumValues.append({
454
- "name": child.displayname,
455
- "value": child.enum_value,
456
- })
457
- opEnums.append({
458
- "name": fullEnumName,
459
- "type": parse_type(node.enum_type),
460
- "values": enumValues,
461
- })
462
-
463
- if node.kind == clang.cindex.CursorKind.NAMESPACE:
464
- namespace = [*namespace, node.displayname]
465
- if node.kind == clang.cindex.CursorKind.CLASS_DECL:
466
- namespace = [*namespace, node.displayname]
467
- if node.kind == clang.cindex.CursorKind.STRUCT_DECL:
468
- namespace = [*namespace, node.displayname]
469
-
470
- for child in node.get_children():
471
- traverse(child, namespace, main_file)
472
-
473
- include_paths = [
474
- f'-I{cxx_client_root}/',
475
- f'-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/{CLANG_VERSION}/include',
476
- ]
477
- for dep, inc in cxx_deps_include_paths.items():
478
- include_paths.extend(set_cxx_deps_include_paths(dep, inc))
479
-
480
- for headerPath in fullFileList:
481
- print("processing " + headerPath)
482
- index = clang.cindex.Index.create()
483
- args = ['-std=c++17'] + include_paths
484
- translation_unit = index.parse(headerPath, args=args)
485
-
486
- # output clang compiler diagnostics information (for debugging)
487
- if 1:
488
- for diagnostic in translation_unit.diagnostics:
489
- diagnosticMsg = diagnostic.format()
490
- print(diagnostic)
491
-
492
- traverse(translation_unit.cursor, [], headerPath)
493
-
494
- jsonData = json.dumps({
495
- 'op_structs': opTypes,
496
- 'op_enums': opEnums
497
- })
498
-
499
- f = open("bindings.json", "w")
500
- f.write(jsonData)
501
- f.close()
643
+ @staticmethod
644
+ def sh(command: str, piped: Optional[bool] = False) -> Tuple[str, int]:
645
+ try:
646
+ if piped is True:
647
+ proc = subprocess.Popen(command,
648
+ stdin=subprocess.PIPE,
649
+ stdout=subprocess.PIPE,
650
+ stderr=subprocess.PIPE,
651
+ shell=True)
652
+ else:
653
+ proc = subprocess.Popen(command,
654
+ stdout=subprocess.PIPE,
655
+ stderr=subprocess.PIPE,
656
+ shell=True)
657
+ stdout, stderr = proc.communicate()
658
+ stderr = stderr.decode('utf-8')
659
+ if stderr != '':
660
+ return stderr, 1
661
+ return stdout.decode('utf-8'), 0
662
+ except FileNotFoundError:
663
+ return "Error: Command not found.", 1
664
+
665
+ @staticmethod
666
+ def find_llvm() -> None:
667
+ if sys.platform == 'darwin':
668
+ output, err = BindingsGenerator.sh('which clang')
669
+ if err:
670
+ raise Exception(f'Unable to determine clang binary. Error code: {err}.')
671
+ if 'llvm' not in output.strip():
672
+ # TODO: aarch64 v. x86_64
673
+ os_path = os.environ.get('PATH').split(':')
674
+ os_path = ['/opt/homebrew/opt/llvm/bin'] + os_path
675
+ os.environ.update(**{'PATH': ':'.join(os_path)})
676
+ output, err = BindingsGenerator.sh('which clang')
677
+ if err:
678
+ raise Exception(f'Unable to determine clang binary. Error code: {err}.')
679
+ if 'llvm' not in output.strip():
680
+ raise Exception('Unable to set LLVM as default.')
681
+ elif sys.platform == 'linux':
682
+ print('Under construction')
683
+ else:
684
+ raise ValueError('Unsupported platform')
685
+
686
+ @staticmethod
687
+ def get_llvm_version() -> str:
688
+ output, err = BindingsGenerator.sh('llvm-config --version')
689
+ if err:
690
+ raise Exception(f'Unable to determine LLVM version. Error code: {err}')
691
+ return output.strip()
692
+
693
+ @staticmethod
694
+ def get_llvm_includedir() -> str:
695
+ output, err = BindingsGenerator.sh('llvm-config --includedir')
696
+ if err:
697
+ raise Exception(f'Unable to determine LLVM includedir. Error code: {err}')
698
+ return output.strip()
699
+
700
+ @staticmethod
701
+ def get_llvm_libdir() -> str:
702
+ output, err = BindingsGenerator.sh('llvm-config --libdir')
703
+ if err:
704
+ raise Exception(f'Unable to determine LLVM libdir. Error code: {err}')
705
+ return output.strip()
706
+
707
+ @staticmethod
708
+ def get_system_headers() -> str:
709
+ if sys.platform == 'darwin':
710
+ output, err = BindingsGenerator.sh('xcrun --show-sdk-path')
711
+ if err:
712
+ raise Exception(f'Unable to determine system header path. Error code: {err}.')
713
+ return output.strip()
714
+ elif sys.platform == 'linux':
715
+ print('Under construction')
716
+ else:
717
+ raise ValueError('Unsupported platform')
718
+
719
+
720
+ if __name__ == '__main__':
721
+ from argparse import ArgumentParser
722
+ ap = ArgumentParser(description='Parse git version to PEP-440 version')
723
+ ap.add_argument('-v',
724
+ '--version',
725
+ help='Set CN_LLVM_VERSION, or use command: llvm-config --version')
726
+ ap.add_argument('-i',
727
+ '--includedir',
728
+ help='Set CN_LLVM_INCLUDE, or use command: llvm-config --includedir')
729
+ ap.add_argument('-l',
730
+ '--libdir',
731
+ help='Set CN_LLVM_LIB, or use command: llvm-config --libdir')
732
+ ap.add_argument('-s',
733
+ '--system-headers',
734
+ help='SET CN_SYS_HEADERS, or use command: xcrun --show-sdk-path')
735
+ options = ap.parse_args()
736
+
737
+ generator = BindingsGenerator(options.version,
738
+ options.libdir,
739
+ options.includedir,
740
+ options.system_headers)
741
+ generator.gen_bindings()
742
+
743
+
744
+ """
745
+
746
+ https://github.com/llvm/llvm-project/issues/86009
747
+
748
+ """