grpc 1.47.0 → 1.48.0.pre1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (574) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +105 -47
  3. data/include/grpc/compression.h +1 -1
  4. data/include/grpc/event_engine/event_engine.h +20 -11
  5. data/include/grpc/event_engine/slice_buffer.h +8 -2
  6. data/include/grpc/grpc.h +3 -3
  7. data/include/grpc/impl/codegen/compression_types.h +2 -1
  8. data/include/grpc/impl/codegen/connectivity_state.h +2 -1
  9. data/include/grpc/impl/codegen/gpr_types.h +2 -1
  10. data/include/grpc/impl/codegen/grpc_types.h +2 -1
  11. data/include/grpc/impl/codegen/port_platform.h +6 -3
  12. data/src/core/ext/filters/census/grpc_context.cc +3 -0
  13. data/src/core/ext/filters/channel_idle/channel_idle_filter.cc +17 -5
  14. data/src/core/ext/filters/channel_idle/channel_idle_filter.h +16 -0
  15. data/src/core/ext/filters/channel_idle/idle_filter_state.h +2 -0
  16. data/src/core/ext/filters/client_channel/backup_poller.cc +3 -1
  17. data/src/core/ext/filters/client_channel/channel_connectivity.cc +2 -2
  18. data/src/core/ext/filters/client_channel/client_channel.cc +51 -65
  19. data/src/core/ext/filters/client_channel/client_channel.h +19 -4
  20. data/src/core/ext/filters/client_channel/config_selector.h +1 -1
  21. data/src/core/ext/filters/client_channel/connector.h +1 -1
  22. data/src/core/ext/filters/client_channel/dynamic_filters.cc +6 -4
  23. data/src/core/ext/filters/client_channel/dynamic_filters.h +1 -1
  24. data/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc +1 -1
  25. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +2 -2
  26. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h +1 -0
  27. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +73 -43
  28. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.cc +1 -1
  29. data/src/core/ext/filters/client_channel/lb_policy/oob_backend_metric.cc +0 -1
  30. data/src/core/ext/filters/client_channel/lb_policy/outlier_detection/outlier_detection.cc +33 -35
  31. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +106 -112
  32. data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +91 -42
  33. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc +177 -138
  34. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h +4 -1
  35. data/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc +47 -44
  36. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +118 -103
  37. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +83 -78
  38. data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +57 -67
  39. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +2 -2
  40. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +5 -7
  41. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +13 -17
  42. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +3 -3
  43. data/src/core/ext/filters/client_channel/lb_policy.h +0 -7
  44. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +3 -5
  45. data/src/core/ext/filters/client_channel/proxy_mapper_registry.cc +0 -1
  46. data/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc +3 -1
  47. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +6 -6
  48. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +5 -5
  49. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +10 -5
  50. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +12 -3
  51. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +5 -5
  52. data/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc +3 -4
  53. data/src/core/ext/filters/client_channel/resolver/polling_resolver.cc +1 -1
  54. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +1 -0
  55. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +24 -15
  56. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.h +3 -1
  57. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +7 -7
  58. data/src/core/ext/filters/client_channel/retry_filter.cc +35 -36
  59. data/src/core/ext/filters/client_channel/retry_filter.h +1 -0
  60. data/src/core/ext/filters/client_channel/retry_service_config.cc +4 -4
  61. data/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc +2 -1
  62. data/src/core/ext/filters/client_channel/subchannel.cc +53 -50
  63. data/src/core/ext/filters/client_channel/subchannel.h +6 -22
  64. data/src/core/ext/filters/client_channel/subchannel_interface.h +10 -18
  65. data/src/core/ext/filters/client_channel/subchannel_stream_client.cc +12 -97
  66. data/src/core/ext/filters/client_channel/subchannel_stream_client.h +5 -9
  67. data/src/core/ext/filters/deadline/deadline_filter.cc +12 -7
  68. data/src/core/ext/filters/deadline/deadline_filter.h +8 -1
  69. data/src/core/ext/filters/fault_injection/fault_injection_filter.cc +21 -2
  70. data/src/core/ext/filters/fault_injection/fault_injection_filter.h +8 -3
  71. data/src/core/ext/filters/fault_injection/service_config_parser.cc +7 -4
  72. data/src/core/ext/filters/fault_injection/service_config_parser.h +17 -3
  73. data/src/core/ext/filters/http/client/http_client_filter.cc +16 -5
  74. data/src/core/ext/filters/http/client/http_client_filter.h +8 -1
  75. data/src/core/ext/filters/http/client_authority_filter.cc +11 -10
  76. data/src/core/ext/filters/http/client_authority_filter.h +5 -2
  77. data/src/core/ext/filters/http/http_filters_plugin.cc +9 -1
  78. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +64 -187
  79. data/src/core/ext/filters/http/message_compress/message_compress_filter.h +1 -2
  80. data/src/core/ext/filters/http/message_compress/message_decompress_filter.cc +42 -106
  81. data/src/core/ext/filters/http/message_compress/message_decompress_filter.h +1 -0
  82. data/src/core/ext/filters/http/server/http_server_filter.cc +16 -9
  83. data/src/core/ext/filters/http/server/http_server_filter.h +6 -1
  84. data/src/core/ext/filters/message_size/message_size_filter.cc +25 -15
  85. data/src/core/ext/filters/message_size/message_size_filter.h +13 -0
  86. data/src/core/ext/filters/rbac/rbac_filter.cc +14 -3
  87. data/src/core/ext/filters/rbac/rbac_filter.h +8 -0
  88. data/src/core/ext/filters/rbac/rbac_service_config_parser.cc +13 -2
  89. data/src/core/ext/filters/rbac/rbac_service_config_parser.h +14 -2
  90. data/src/core/ext/filters/server_config_selector/server_config_selector.cc +1 -0
  91. data/src/core/ext/filters/server_config_selector/server_config_selector.h +9 -0
  92. data/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc +22 -2
  93. data/src/core/ext/filters/server_config_selector/server_config_selector_filter.h +1 -0
  94. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +4 -4
  95. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +15 -15
  96. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +196 -476
  97. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +1 -1
  98. data/src/core/ext/transport/chttp2/transport/flow_control.cc +141 -261
  99. data/src/core/ext/transport/chttp2/transport/flow_control.h +176 -289
  100. data/src/core/ext/transport/chttp2/transport/frame_data.cc +57 -215
  101. data/src/core/ext/transport/chttp2/transport/frame_data.h +10 -36
  102. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +0 -41
  103. data/src/core/ext/transport/chttp2/transport/frame_window_update.cc +7 -12
  104. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +7 -6
  105. data/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +0 -2
  106. data/src/core/ext/transport/chttp2/transport/internal.h +9 -111
  107. data/src/core/ext/transport/chttp2/transport/parsing.cc +51 -38
  108. data/src/core/ext/transport/chttp2/transport/stream_lists.cc +0 -4
  109. data/src/core/ext/transport/chttp2/transport/writing.cc +18 -21
  110. data/src/core/ext/transport/inproc/inproc_plugin.cc +0 -1
  111. data/src/core/ext/transport/inproc/inproc_transport.cc +85 -81
  112. data/src/core/ext/transport/inproc/inproc_transport.h +3 -1
  113. data/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c +52 -0
  114. data/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h +164 -0
  115. data/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.c +46 -0
  116. data/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h +94 -0
  117. data/src/core/ext/xds/certificate_provider_factory.h +6 -1
  118. data/src/core/ext/xds/certificate_provider_registry.cc +8 -8
  119. data/src/core/ext/xds/certificate_provider_registry.h +3 -1
  120. data/src/core/ext/xds/certificate_provider_store.cc +2 -0
  121. data/src/core/ext/xds/certificate_provider_store.h +9 -0
  122. data/src/core/ext/xds/file_watcher_certificate_provider_factory.cc +9 -0
  123. data/src/core/ext/xds/file_watcher_certificate_provider_factory.h +8 -0
  124. data/src/core/ext/xds/upb_utils.h +1 -2
  125. data/src/core/ext/xds/xds_api.cc +16 -18
  126. data/src/core/ext/xds/xds_api.h +12 -5
  127. data/src/core/ext/xds/xds_bootstrap.cc +37 -24
  128. data/src/core/ext/xds/xds_bootstrap.h +9 -11
  129. data/src/core/ext/xds/xds_certificate_provider.cc +12 -3
  130. data/src/core/ext/xds/xds_certificate_provider.h +16 -1
  131. data/src/core/ext/xds/xds_channel_stack_modifier.cc +9 -0
  132. data/src/core/ext/xds/xds_channel_stack_modifier.h +5 -1
  133. data/src/core/ext/xds/xds_client.cc +71 -22
  134. data/src/core/ext/xds/xds_client.h +17 -3
  135. data/src/core/ext/xds/xds_client_stats.cc +3 -4
  136. data/src/core/ext/xds/xds_client_stats.h +4 -3
  137. data/src/core/ext/xds/xds_cluster.cc +21 -10
  138. data/src/core/ext/xds/xds_cluster.h +9 -1
  139. data/src/core/ext/xds/xds_cluster_specifier_plugin.cc +16 -7
  140. data/src/core/ext/xds/xds_cluster_specifier_plugin.h +1 -8
  141. data/src/core/ext/xds/xds_common_types.cc +36 -22
  142. data/src/core/ext/xds/xds_common_types.h +12 -4
  143. data/src/core/ext/xds/xds_endpoint.cc +25 -15
  144. data/src/core/ext/xds/xds_endpoint.h +13 -5
  145. data/src/core/ext/xds/xds_http_fault_filter.cc +7 -5
  146. data/src/core/ext/xds/xds_http_fault_filter.h +3 -1
  147. data/src/core/ext/xds/xds_http_filters.cc +7 -0
  148. data/src/core/ext/xds/xds_http_filters.h +3 -3
  149. data/src/core/ext/xds/xds_http_rbac_filter.cc +16 -0
  150. data/src/core/ext/xds/xds_http_rbac_filter.h +7 -0
  151. data/src/core/ext/xds/xds_lb_policy_registry.cc +291 -0
  152. data/src/core/ext/xds/xds_lb_policy_registry.h +72 -0
  153. data/src/core/ext/xds/xds_listener.cc +51 -33
  154. data/src/core/ext/xds/xds_listener.h +10 -1
  155. data/src/core/ext/xds/xds_resource_type.h +3 -3
  156. data/src/core/ext/xds/xds_resource_type_impl.h +7 -3
  157. data/src/core/ext/xds/xds_route_config.cc +56 -28
  158. data/src/core/ext/xds/xds_route_config.h +11 -2
  159. data/src/core/ext/xds/xds_routing.cc +16 -0
  160. data/src/core/ext/xds/xds_routing.h +7 -2
  161. data/src/core/ext/xds/xds_server_config_fetcher.cc +54 -6
  162. data/src/core/lib/address_utils/parse_address.cc +5 -8
  163. data/src/core/lib/address_utils/parse_address.h +3 -2
  164. data/src/core/lib/address_utils/sockaddr_utils.cc +8 -7
  165. data/src/core/lib/address_utils/sockaddr_utils.h +2 -0
  166. data/src/core/lib/avl/avl.h +3 -3
  167. data/src/core/lib/backoff/backoff.cc +1 -1
  168. data/src/core/lib/backoff/backoff.h +1 -1
  169. data/src/core/lib/channel/call_tracer.h +3 -3
  170. data/src/core/lib/channel/channel_args.h +1 -0
  171. data/src/core/lib/channel/channel_args_preconditioning.cc +1 -0
  172. data/src/core/lib/channel/channel_fwd.h +26 -0
  173. data/src/core/lib/channel/channel_stack.cc +4 -4
  174. data/src/core/lib/channel/channel_stack.h +1 -11
  175. data/src/core/lib/channel/channel_stack_builder.h +2 -5
  176. data/src/core/lib/channel/channel_stack_builder_impl.cc +1 -1
  177. data/src/core/lib/channel/channel_stack_builder_impl.h +1 -0
  178. data/src/core/lib/channel/channelz.cc +2 -1
  179. data/src/core/lib/channel/channelz.h +2 -3
  180. data/src/core/lib/channel/channelz_registry.cc +4 -5
  181. data/src/core/lib/channel/connected_channel.cc +1 -0
  182. data/src/core/lib/channel/connected_channel.h +1 -0
  183. data/src/core/lib/channel/promise_based_filter.cc +11 -5
  184. data/src/core/lib/channel/promise_based_filter.h +2 -0
  185. data/src/core/lib/compression/compression.cc +6 -1
  186. data/src/core/lib/compression/compression_internal.cc +3 -6
  187. data/src/core/lib/compression/compression_internal.h +3 -2
  188. data/src/core/lib/compression/message_compress.cc +3 -1
  189. data/src/core/lib/compression/message_compress.h +2 -3
  190. data/src/core/lib/debug/stats.cc +9 -9
  191. data/src/core/lib/debug/stats.h +2 -1
  192. data/src/core/lib/debug/stats_data.cc +2 -1
  193. data/src/core/lib/debug/stats_data.h +0 -4
  194. data/src/core/lib/debug/trace.h +13 -12
  195. data/src/core/lib/event_engine/default_event_engine_factory.cc +1 -1
  196. data/src/core/lib/event_engine/event_engine.cc +24 -19
  197. data/src/core/lib/event_engine/event_engine_factory.h +2 -2
  198. data/src/core/lib/event_engine/{iomgr_engine.cc → iomgr_engine/iomgr_engine.cc} +44 -91
  199. data/src/core/lib/event_engine/{iomgr_engine.h → iomgr_engine/iomgr_engine.h} +20 -16
  200. data/src/core/lib/event_engine/iomgr_engine/thread_pool.cc +123 -0
  201. data/src/core/lib/event_engine/iomgr_engine/thread_pool.h +70 -0
  202. data/src/core/lib/event_engine/iomgr_engine/time_averaged_stats.cc +62 -0
  203. data/src/core/lib/event_engine/iomgr_engine/time_averaged_stats.h +81 -0
  204. data/src/core/lib/event_engine/iomgr_engine/timer.cc +312 -0
  205. data/src/core/lib/event_engine/iomgr_engine/timer.h +193 -0
  206. data/src/core/lib/event_engine/iomgr_engine/timer_heap.cc +107 -0
  207. data/src/core/lib/event_engine/iomgr_engine/timer_heap.h +56 -0
  208. data/src/core/lib/event_engine/iomgr_engine/timer_manager.cc +254 -0
  209. data/src/core/lib/event_engine/iomgr_engine/timer_manager.h +111 -0
  210. data/src/core/lib/event_engine/promise.h +69 -0
  211. data/src/core/lib/gpr/time_posix.cc +6 -9
  212. data/src/core/lib/gpr/time_windows.cc +10 -7
  213. data/src/core/lib/gprpp/manual_constructor.h +0 -67
  214. data/src/core/lib/gprpp/status_helper.cc +44 -30
  215. data/src/core/lib/gprpp/time.cc +8 -0
  216. data/src/core/lib/gprpp/time.h +4 -0
  217. data/src/core/lib/http/format_request.cc +5 -4
  218. data/src/core/lib/http/format_request.h +1 -1
  219. data/src/core/lib/http/httpcli.cc +18 -12
  220. data/src/core/lib/http/httpcli.h +19 -3
  221. data/src/core/lib/http/httpcli_security_connector.cc +16 -4
  222. data/src/core/lib/http/httpcli_ssl_credentials.h +3 -1
  223. data/src/core/lib/http/parser.cc +6 -7
  224. data/src/core/lib/http/parser.h +3 -0
  225. data/src/core/lib/iomgr/call_combiner.cc +2 -2
  226. data/src/core/lib/iomgr/endpoint.h +1 -1
  227. data/src/core/lib/iomgr/endpoint_cfstream.cc +2 -2
  228. data/src/core/lib/iomgr/error.cc +11 -9
  229. data/src/core/lib/iomgr/error.h +9 -5
  230. data/src/core/lib/iomgr/ev_epoll1_linux.cc +57 -18
  231. data/src/core/lib/iomgr/ev_epoll1_linux.h +1 -1
  232. data/src/core/lib/iomgr/ev_poll_posix.cc +77 -52
  233. data/src/core/lib/iomgr/ev_poll_posix.h +2 -2
  234. data/src/core/lib/iomgr/ev_posix.cc +54 -92
  235. data/src/core/lib/iomgr/ev_posix.h +5 -3
  236. data/src/core/lib/iomgr/fork_posix.cc +1 -1
  237. data/src/core/lib/iomgr/iomgr.cc +7 -0
  238. data/src/core/lib/iomgr/iomgr_posix.cc +1 -0
  239. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +1 -0
  240. data/src/core/lib/iomgr/load_file.cc +1 -1
  241. data/src/core/lib/iomgr/resolve_address_posix.cc +1 -1
  242. data/src/core/lib/iomgr/resolve_address_windows.cc +1 -1
  243. data/src/core/lib/iomgr/tcp_client.cc +12 -7
  244. data/src/core/lib/iomgr/tcp_client.h +24 -13
  245. data/src/core/lib/iomgr/tcp_client_cfstream.cc +15 -9
  246. data/src/core/lib/iomgr/tcp_client_posix.cc +143 -25
  247. data/src/core/lib/iomgr/tcp_client_posix.h +1 -1
  248. data/src/core/lib/iomgr/tcp_client_windows.cc +14 -10
  249. data/src/core/lib/iomgr/tcp_posix.cc +91 -29
  250. data/src/core/lib/iomgr/tcp_server_posix.cc +7 -7
  251. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +12 -12
  252. data/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc +2 -2
  253. data/src/core/lib/iomgr/tcp_server_windows.cc +7 -7
  254. data/src/core/lib/iomgr/tcp_windows.cc +5 -5
  255. data/src/core/lib/iomgr/unix_sockets_posix.cc +2 -2
  256. data/src/core/lib/iomgr/wakeup_fd_pipe.cc +2 -2
  257. data/src/core/lib/iomgr/wakeup_fd_posix.cc +15 -12
  258. data/src/core/lib/iomgr/wakeup_fd_posix.h +0 -2
  259. data/src/core/lib/iomgr/work_serializer.h +2 -3
  260. data/src/core/lib/matchers/matchers.cc +6 -3
  261. data/src/core/lib/matchers/matchers.h +2 -0
  262. data/src/core/lib/promise/activity.cc +0 -1
  263. data/src/core/lib/promise/activity.h +7 -13
  264. data/src/core/lib/promise/loop.h +1 -0
  265. data/src/core/lib/promise/promise.h +1 -0
  266. data/src/core/lib/promise/sleep.cc +36 -31
  267. data/src/core/lib/promise/sleep.h +25 -25
  268. data/src/core/lib/resolver/resolver.cc +5 -0
  269. data/src/core/lib/resolver/resolver.h +3 -0
  270. data/src/core/lib/resolver/resolver_factory.h +5 -2
  271. data/src/core/lib/resolver/resolver_registry.cc +2 -9
  272. data/src/core/lib/resolver/resolver_registry.h +12 -1
  273. data/src/core/lib/resolver/server_address.cc +8 -0
  274. data/src/core/lib/resolver/server_address.h +9 -2
  275. data/src/core/lib/resource_quota/memory_quota.cc +18 -60
  276. data/src/core/lib/resource_quota/memory_quota.h +11 -25
  277. data/src/core/lib/security/authorization/authorization_policy_provider.h +7 -0
  278. data/src/core/lib/security/authorization/authorization_policy_provider_vtable.cc +4 -0
  279. data/src/core/lib/security/authorization/evaluate_args.cc +9 -3
  280. data/src/core/lib/security/authorization/evaluate_args.h +6 -3
  281. data/src/core/lib/security/authorization/grpc_authorization_engine.cc +6 -0
  282. data/src/core/lib/security/authorization/grpc_authorization_engine.h +7 -0
  283. data/src/core/lib/security/authorization/grpc_server_authz_filter.cc +12 -0
  284. data/src/core/lib/security/authorization/grpc_server_authz_filter.h +12 -1
  285. data/src/core/lib/security/authorization/matchers.cc +9 -1
  286. data/src/core/lib/security/authorization/matchers.h +7 -0
  287. data/src/core/lib/security/authorization/rbac_policy.cc +5 -0
  288. data/src/core/lib/security/authorization/rbac_policy.h +7 -0
  289. data/src/core/lib/security/context/security_context.cc +5 -2
  290. data/src/core/lib/security/context/security_context.h +14 -2
  291. data/src/core/lib/security/credentials/alts/alts_credentials.cc +4 -2
  292. data/src/core/lib/security/credentials/alts/alts_credentials.h +6 -1
  293. data/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc +1 -3
  294. data/src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc +1 -4
  295. data/src/core/lib/security/credentials/call_creds_util.cc +8 -0
  296. data/src/core/lib/security/credentials/call_creds_util.h +1 -0
  297. data/src/core/lib/security/credentials/channel_creds_registry.h +6 -1
  298. data/src/core/lib/security/credentials/channel_creds_registry_init.cc +10 -0
  299. data/src/core/lib/security/credentials/composite/composite_credentials.cc +4 -4
  300. data/src/core/lib/security/credentials/composite/composite_credentials.h +16 -2
  301. data/src/core/lib/security/credentials/credentials.cc +4 -8
  302. data/src/core/lib/security/credentials/credentials.h +10 -8
  303. data/src/core/lib/security/credentials/external/aws_external_account_credentials.cc +28 -10
  304. data/src/core/lib/security/credentials/external/aws_external_account_credentials.h +10 -0
  305. data/src/core/lib/security/credentials/external/aws_request_signer.cc +9 -0
  306. data/src/core/lib/security/credentials/external/external_account_credentials.cc +24 -9
  307. data/src/core/lib/security/credentials/external/external_account_credentials.h +11 -0
  308. data/src/core/lib/security/credentials/external/file_external_account_credentials.cc +12 -4
  309. data/src/core/lib/security/credentials/external/file_external_account_credentials.h +6 -0
  310. data/src/core/lib/security/credentials/external/url_external_account_credentials.cc +20 -4
  311. data/src/core/lib/security/credentials/external/url_external_account_credentials.h +10 -0
  312. data/src/core/lib/security/credentials/fake/fake_credentials.cc +8 -6
  313. data/src/core/lib/security/credentials/fake/fake_credentials.h +13 -1
  314. data/src/core/lib/security/credentials/google_default/credentials_generic.cc +1 -0
  315. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +27 -10
  316. data/src/core/lib/security/credentials/google_default/google_default_credentials.h +10 -1
  317. data/src/core/lib/security/credentials/iam/iam_credentials.cc +9 -3
  318. data/src/core/lib/security/credentials/iam/iam_credentials.h +10 -0
  319. data/src/core/lib/security/credentials/insecure/insecure_credentials.cc +4 -0
  320. data/src/core/lib/security/credentials/insecure/insecure_credentials.h +5 -0
  321. data/src/core/lib/security/credentials/jwt/json_token.cc +5 -2
  322. data/src/core/lib/security/credentials/jwt/json_token.h +2 -2
  323. data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +11 -5
  324. data/src/core/lib/security/credentials/jwt/jwt_credentials.h +14 -0
  325. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +28 -3
  326. data/src/core/lib/security/credentials/jwt/jwt_verifier.h +4 -2
  327. data/src/core/lib/security/credentials/local/local_credentials.cc +4 -3
  328. data/src/core/lib/security/credentials/local/local_credentials.h +7 -0
  329. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +26 -13
  330. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +20 -0
  331. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +8 -7
  332. data/src/core/lib/security/credentials/plugin/plugin_credentials.h +24 -0
  333. data/src/core/lib/security/credentials/ssl/ssl_credentials.cc +5 -0
  334. data/src/core/lib/security/credentials/ssl/ssl_credentials.h +13 -0
  335. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc +6 -6
  336. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h +9 -3
  337. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc +29 -10
  338. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h +9 -4
  339. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc +9 -2
  340. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h +6 -7
  341. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +4 -5
  342. data/src/core/lib/security/credentials/tls/tls_credentials.cc +7 -2
  343. data/src/core/lib/security/credentials/tls/tls_credentials.h +5 -1
  344. data/src/core/lib/security/credentials/tls/tls_utils.cc +2 -0
  345. data/src/core/lib/security/credentials/tls/tls_utils.h +1 -1
  346. data/src/core/lib/security/credentials/xds/xds_credentials.cc +8 -1
  347. data/src/core/lib/security/credentials/xds/xds_credentials.h +14 -0
  348. data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +22 -2
  349. data/src/core/lib/security/security_connector/alts/alts_security_connector.h +6 -3
  350. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +17 -1
  351. data/src/core/lib/security/security_connector/fake/fake_security_connector.h +2 -2
  352. data/src/core/lib/security/security_connector/insecure/insecure_security_connector.cc +9 -0
  353. data/src/core/lib/security/security_connector/insecure/insecure_security_connector.h +17 -2
  354. data/src/core/lib/security/security_connector/load_system_roots_fallback.cc +5 -3
  355. data/src/core/lib/security/security_connector/{load_system_roots_linux.cc → load_system_roots_supported.cc} +27 -19
  356. data/src/core/lib/security/security_connector/{load_system_roots_linux.h → load_system_roots_supported.h} +5 -5
  357. data/src/core/lib/security/security_connector/local/local_security_connector.cc +22 -3
  358. data/src/core/lib/security/security_connector/local/local_security_connector.h +6 -2
  359. data/src/core/lib/security/security_connector/security_connector.cc +20 -18
  360. data/src/core/lib/security/security_connector/security_connector.h +18 -6
  361. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +18 -6
  362. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.h +4 -2
  363. data/src/core/lib/security/security_connector/ssl_utils.cc +12 -2
  364. data/src/core/lib/security/security_connector/ssl_utils.h +10 -7
  365. data/src/core/lib/security/security_connector/ssl_utils_config.h +1 -1
  366. data/src/core/lib/security/security_connector/tls/tls_security_connector.cc +21 -13
  367. data/src/core/lib/security/security_connector/tls/tls_security_connector.h +23 -3
  368. data/src/core/lib/security/transport/auth_filters.h +7 -0
  369. data/src/core/lib/security/transport/client_auth_filter.cc +18 -9
  370. data/src/core/lib/security/transport/secure_endpoint.cc +63 -13
  371. data/src/core/lib/security/transport/secure_endpoint.h +4 -3
  372. data/src/core/lib/security/transport/security_handshaker.cc +44 -11
  373. data/src/core/lib/security/transport/security_handshaker.h +4 -0
  374. data/src/core/lib/security/transport/server_auth_filter.cc +26 -4
  375. data/src/core/lib/security/util/json_util.cc +3 -2
  376. data/src/core/lib/security/util/json_util.h +0 -2
  377. data/src/core/lib/service_config/service_config_call_data.h +2 -1
  378. data/src/core/lib/service_config/service_config_impl.cc +6 -6
  379. data/src/core/lib/service_config/service_config_impl.h +1 -3
  380. data/src/core/lib/service_config/service_config_parser.cc +2 -4
  381. data/src/core/lib/slice/slice_buffer.cc +30 -1
  382. data/src/core/lib/slice/slice_buffer.h +37 -6
  383. data/src/core/lib/slice/slice_string_helpers.cc +0 -20
  384. data/src/core/lib/slice/slice_string_helpers.h +0 -4
  385. data/src/core/lib/surface/call.cc +53 -115
  386. data/src/core/lib/surface/call.h +5 -1
  387. data/src/core/lib/surface/channel.h +2 -0
  388. data/src/core/lib/surface/channel_ping.cc +1 -1
  389. data/src/core/lib/surface/completion_queue.cc +15 -14
  390. data/src/core/lib/surface/completion_queue.h +2 -1
  391. data/src/core/lib/surface/init.cc +0 -1
  392. data/src/core/lib/surface/lame_client.cc +1 -1
  393. data/src/core/lib/surface/lame_client.h +1 -1
  394. data/src/core/lib/surface/server.cc +14 -8
  395. data/src/core/lib/surface/server.h +4 -1
  396. data/src/core/lib/surface/validate_metadata.cc +1 -1
  397. data/src/core/lib/surface/version.cc +2 -2
  398. data/src/core/lib/transport/error_utils.cc +13 -7
  399. data/src/core/lib/transport/handshaker.cc +3 -3
  400. data/src/core/lib/transport/http_connect_handshaker.cc +4 -4
  401. data/src/core/lib/transport/tcp_connect_handshaker.cc +2 -2
  402. data/src/core/lib/transport/transport.cc +0 -3
  403. data/src/core/lib/transport/transport.h +20 -14
  404. data/src/core/lib/transport/transport_fwd.h +20 -0
  405. data/src/core/lib/transport/transport_impl.h +1 -0
  406. data/src/core/lib/transport/transport_op_string.cc +9 -9
  407. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +1 -1
  408. data/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc +9 -1
  409. data/src/core/tsi/fake_transport_security.cc +13 -1
  410. data/src/core/tsi/fake_transport_security.h +6 -0
  411. data/src/core/tsi/ssl_transport_security.cc +1 -1
  412. data/src/core/tsi/transport_security_grpc.cc +3 -2
  413. data/src/core/tsi/transport_security_grpc.h +5 -2
  414. data/src/ruby/ext/grpc/ext-export-truffleruby.clang +2 -0
  415. data/src/ruby/ext/grpc/ext-export-truffleruby.gcc +7 -0
  416. data/src/ruby/ext/grpc/ext-export.clang +1 -0
  417. data/src/ruby/ext/grpc/ext-export.gcc +1 -0
  418. data/src/ruby/ext/grpc/extconf.rb +49 -18
  419. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +1 -1
  420. data/src/ruby/lib/grpc/errors.rb +1 -1
  421. data/src/ruby/lib/grpc/version.rb +1 -1
  422. data/src/ruby/spec/generic/client_stub_spec.rb +23 -23
  423. data/third_party/abseil-cpp/absl/algorithm/container.h +1 -1
  424. data/third_party/abseil-cpp/absl/base/attributes.h +49 -22
  425. data/third_party/abseil-cpp/absl/base/casts.h +61 -68
  426. data/third_party/abseil-cpp/absl/base/config.h +182 -41
  427. data/third_party/abseil-cpp/absl/base/internal/cycleclock.cc +12 -42
  428. data/third_party/abseil-cpp/absl/base/internal/cycleclock.h +67 -2
  429. data/third_party/abseil-cpp/absl/base/internal/direct_mmap.h +3 -3
  430. data/third_party/abseil-cpp/absl/base/internal/endian.h +17 -62
  431. data/third_party/abseil-cpp/absl/base/internal/fast_type_id.h +2 -0
  432. data/third_party/abseil-cpp/absl/base/internal/invoke.h +54 -0
  433. data/third_party/abseil-cpp/absl/base/internal/prefetch.h +138 -0
  434. data/third_party/abseil-cpp/absl/base/internal/raw_logging.cc +29 -22
  435. data/third_party/abseil-cpp/absl/base/internal/raw_logging.h +13 -12
  436. data/third_party/abseil-cpp/absl/base/internal/spinlock.cc +3 -0
  437. data/third_party/abseil-cpp/absl/base/internal/spinlock.h +8 -0
  438. data/third_party/abseil-cpp/absl/base/internal/spinlock_linux.inc +2 -5
  439. data/third_party/abseil-cpp/absl/base/internal/strerror.cc +88 -0
  440. data/third_party/abseil-cpp/absl/base/internal/strerror.h +39 -0
  441. data/third_party/abseil-cpp/absl/base/internal/sysinfo.cc +0 -1
  442. data/third_party/abseil-cpp/absl/base/internal/thread_identity.cc +2 -1
  443. data/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc +6 -7
  444. data/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h +12 -3
  445. data/third_party/abseil-cpp/absl/base/log_severity.cc +28 -0
  446. data/third_party/abseil-cpp/absl/base/log_severity.h +51 -0
  447. data/third_party/abseil-cpp/absl/base/optimization.h +19 -11
  448. data/third_party/abseil-cpp/absl/base/options.h +1 -1
  449. data/third_party/abseil-cpp/absl/base/thread_annotations.h +2 -2
  450. data/third_party/abseil-cpp/absl/container/fixed_array.h +2 -0
  451. data/third_party/abseil-cpp/absl/container/flat_hash_map.h +11 -4
  452. data/third_party/abseil-cpp/absl/container/flat_hash_set.h +15 -9
  453. data/third_party/abseil-cpp/absl/container/inlined_vector.h +20 -9
  454. data/third_party/abseil-cpp/absl/container/internal/common.h +6 -5
  455. data/third_party/abseil-cpp/absl/container/internal/container_memory.h +10 -28
  456. data/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc +68 -20
  457. data/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h +29 -11
  458. data/third_party/abseil-cpp/absl/container/internal/inlined_vector.h +59 -38
  459. data/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc +4 -0
  460. data/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h +515 -184
  461. data/third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc +45 -88
  462. data/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc +4 -0
  463. data/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h +3 -2
  464. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc +8 -3
  465. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc +8 -3
  466. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h +2 -1
  467. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc +8 -3
  468. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc +20 -18
  469. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc +8 -3
  470. data/third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc +15 -2
  471. data/third_party/abseil-cpp/absl/debugging/symbolize.cc +6 -1
  472. data/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc +46 -7
  473. data/third_party/abseil-cpp/absl/functional/bind_front.h +10 -1
  474. data/third_party/abseil-cpp/absl/functional/function_ref.h +2 -1
  475. data/third_party/abseil-cpp/absl/hash/hash.h +82 -8
  476. data/third_party/abseil-cpp/absl/hash/internal/hash.h +218 -23
  477. data/third_party/abseil-cpp/absl/numeric/bits.h +2 -1
  478. data/third_party/abseil-cpp/absl/numeric/int128.cc +4 -2
  479. data/third_party/abseil-cpp/absl/numeric/int128.h +2 -2
  480. data/third_party/abseil-cpp/absl/profiling/internal/sample_recorder.h +21 -6
  481. data/third_party/abseil-cpp/absl/random/bernoulli_distribution.h +4 -4
  482. data/third_party/abseil-cpp/absl/random/distributions.h +3 -3
  483. data/third_party/abseil-cpp/absl/random/internal/distribution_caller.h +3 -0
  484. data/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits.h +2 -1
  485. data/third_party/abseil-cpp/absl/random/internal/generate_real.h +2 -2
  486. data/third_party/abseil-cpp/absl/random/internal/nonsecure_base.h +59 -48
  487. data/third_party/abseil-cpp/absl/random/internal/pcg_engine.h +1 -1
  488. data/third_party/abseil-cpp/absl/random/internal/randen.h +5 -11
  489. data/third_party/abseil-cpp/absl/random/internal/randen_detect.cc +6 -2
  490. data/third_party/abseil-cpp/absl/random/internal/randen_engine.h +48 -23
  491. data/third_party/abseil-cpp/absl/random/internal/salted_seed_seq.h +24 -26
  492. data/third_party/abseil-cpp/absl/random/internal/traits.h +53 -5
  493. data/third_party/abseil-cpp/absl/random/internal/uniform_helper.h +5 -5
  494. data/third_party/abseil-cpp/absl/random/internal/wide_multiply.h +33 -48
  495. data/third_party/abseil-cpp/absl/random/log_uniform_int_distribution.h +9 -10
  496. data/third_party/abseil-cpp/absl/random/poisson_distribution.h +7 -4
  497. data/third_party/abseil-cpp/absl/random/seed_sequences.h +1 -0
  498. data/third_party/abseil-cpp/absl/random/uniform_int_distribution.h +2 -2
  499. data/third_party/abseil-cpp/absl/random/uniform_real_distribution.h +1 -1
  500. data/third_party/abseil-cpp/absl/random/zipf_distribution.h +4 -3
  501. data/third_party/abseil-cpp/absl/status/internal/status_internal.h +17 -0
  502. data/third_party/abseil-cpp/absl/status/status.cc +174 -2
  503. data/third_party/abseil-cpp/absl/status/status.h +22 -12
  504. data/third_party/abseil-cpp/absl/status/statusor.h +9 -3
  505. data/third_party/abseil-cpp/absl/strings/ascii.h +4 -4
  506. data/third_party/abseil-cpp/absl/strings/cord.cc +194 -913
  507. data/third_party/abseil-cpp/absl/strings/cord.h +202 -81
  508. data/third_party/abseil-cpp/absl/strings/cord_analysis.cc +188 -0
  509. data/third_party/abseil-cpp/absl/strings/cord_analysis.h +44 -0
  510. data/third_party/abseil-cpp/absl/strings/cord_buffer.cc +30 -0
  511. data/third_party/abseil-cpp/absl/strings/cord_buffer.h +572 -0
  512. data/third_party/abseil-cpp/absl/strings/internal/cord_data_edge.h +63 -0
  513. data/third_party/abseil-cpp/absl/strings/internal/cord_internal.cc +20 -32
  514. data/third_party/abseil-cpp/absl/strings/internal/cord_internal.h +123 -88
  515. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree.cc +149 -49
  516. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree.h +44 -59
  517. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc +3 -1
  518. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.h +4 -2
  519. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.cc +3 -2
  520. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.h +5 -4
  521. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_consume.cc +7 -74
  522. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_crc.cc +54 -0
  523. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_crc.h +102 -0
  524. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_flat.h +58 -17
  525. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.cc +13 -11
  526. data/third_party/abseil-cpp/absl/strings/internal/cordz_info.cc +11 -38
  527. data/third_party/abseil-cpp/absl/strings/internal/cordz_statistics.h +1 -0
  528. data/third_party/abseil-cpp/absl/strings/internal/cordz_update_tracker.h +4 -2
  529. data/third_party/abseil-cpp/absl/strings/internal/escaping.cc +6 -5
  530. data/third_party/abseil-cpp/absl/strings/internal/ostringstream.cc +1 -1
  531. data/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc +1 -1
  532. data/third_party/abseil-cpp/absl/strings/internal/str_format/arg.h +1 -1
  533. data/third_party/abseil-cpp/absl/strings/internal/str_format/bind.h +38 -7
  534. data/third_party/abseil-cpp/absl/strings/internal/str_format/checker.h +7 -2
  535. data/third_party/abseil-cpp/absl/strings/internal/str_format/extension.cc +4 -5
  536. data/third_party/abseil-cpp/absl/strings/internal/str_format/extension.h +5 -2
  537. data/third_party/abseil-cpp/absl/strings/internal/str_format/output.h +2 -1
  538. data/third_party/abseil-cpp/absl/strings/internal/str_format/parser.h +4 -2
  539. data/third_party/abseil-cpp/absl/strings/internal/str_join_internal.h +9 -6
  540. data/third_party/abseil-cpp/absl/strings/internal/string_constant.h +10 -2
  541. data/third_party/abseil-cpp/absl/strings/internal/utf8.cc +9 -9
  542. data/third_party/abseil-cpp/absl/strings/numbers.cc +8 -8
  543. data/third_party/abseil-cpp/absl/strings/numbers.h +26 -23
  544. data/third_party/abseil-cpp/absl/strings/str_cat.h +20 -13
  545. data/third_party/abseil-cpp/absl/strings/str_join.h +9 -15
  546. data/third_party/abseil-cpp/absl/strings/str_split.h +1 -2
  547. data/third_party/abseil-cpp/absl/strings/string_view.cc +2 -13
  548. data/third_party/abseil-cpp/absl/strings/string_view.h +3 -2
  549. data/third_party/abseil-cpp/absl/strings/strip.h +8 -6
  550. data/third_party/abseil-cpp/absl/strings/substitute.h +10 -2
  551. data/third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc +9 -6
  552. data/third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.h +0 -4
  553. data/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc +0 -4
  554. data/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.h +1 -6
  555. data/third_party/abseil-cpp/absl/synchronization/internal/waiter.cc +0 -25
  556. data/third_party/abseil-cpp/absl/synchronization/internal/waiter.h +10 -4
  557. data/third_party/abseil-cpp/absl/synchronization/mutex.cc +75 -40
  558. data/third_party/abseil-cpp/absl/synchronization/mutex.h +17 -9
  559. data/third_party/abseil-cpp/absl/synchronization/notification.h +3 -2
  560. data/third_party/abseil-cpp/absl/time/duration.cc +5 -4
  561. data/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h +11 -7
  562. data/third_party/abseil-cpp/absl/time/time.h +16 -12
  563. data/third_party/abseil-cpp/absl/types/internal/optional.h +8 -0
  564. data/third_party/abseil-cpp/absl/types/internal/variant.h +3 -3
  565. data/third_party/abseil-cpp/absl/types/optional.h +17 -14
  566. data/third_party/abseil-cpp/absl/types/span.h +2 -1
  567. metadata +39 -15
  568. data/src/core/lib/slice/slice_split.cc +0 -103
  569. data/src/core/lib/slice/slice_split.h +0 -36
  570. data/src/core/lib/transport/byte_stream.cc +0 -165
  571. data/src/core/lib/transport/byte_stream.h +0 -170
  572. data/third_party/abseil-cpp/absl/cleanup/cleanup.h +0 -140
  573. data/third_party/abseil-cpp/absl/cleanup/internal/cleanup.h +0 -100
  574. data/third_party/abseil-cpp/absl/container/internal/have_sse.h +0 -50
@@ -34,9 +34,12 @@
34
34
  #include "absl/base/port.h"
35
35
  #include "absl/container/fixed_array.h"
36
36
  #include "absl/container/inlined_vector.h"
37
+ #include "absl/strings/cord_buffer.h"
37
38
  #include "absl/strings/escaping.h"
39
+ #include "absl/strings/internal/cord_data_edge.h"
38
40
  #include "absl/strings/internal/cord_internal.h"
39
41
  #include "absl/strings/internal/cord_rep_btree.h"
42
+ #include "absl/strings/internal/cord_rep_crc.h"
40
43
  #include "absl/strings/internal/cord_rep_flat.h"
41
44
  #include "absl/strings/internal/cordz_statistics.h"
42
45
  #include "absl/strings/internal/cordz_update_scope.h"
@@ -52,7 +55,7 @@ ABSL_NAMESPACE_BEGIN
52
55
 
53
56
  using ::absl::cord_internal::CordRep;
54
57
  using ::absl::cord_internal::CordRepBtree;
55
- using ::absl::cord_internal::CordRepConcat;
58
+ using ::absl::cord_internal::CordRepCrc;
56
59
  using ::absl::cord_internal::CordRepExternal;
57
60
  using ::absl::cord_internal::CordRepFlat;
58
61
  using ::absl::cord_internal::CordRepSubstring;
@@ -64,56 +67,6 @@ using ::absl::cord_internal::kMinFlatLength;
64
67
  using ::absl::cord_internal::kInlinedVectorSize;
65
68
  using ::absl::cord_internal::kMaxBytesToCopy;
66
69
 
67
- constexpr uint64_t Fibonacci(unsigned char n, uint64_t a = 0, uint64_t b = 1) {
68
- return n == 0 ? a : Fibonacci(n - 1, b, a + b);
69
- }
70
-
71
- static_assert(Fibonacci(63) == 6557470319842,
72
- "Fibonacci values computed incorrectly");
73
-
74
- // Minimum length required for a given depth tree -- a tree is considered
75
- // balanced if
76
- // length(t) >= min_length[depth(t)]
77
- // The root node depth is allowed to become twice as large to reduce rebalancing
78
- // for larger strings (see IsRootBalanced).
79
- static constexpr uint64_t min_length[] = {
80
- Fibonacci(2), Fibonacci(3), Fibonacci(4), Fibonacci(5),
81
- Fibonacci(6), Fibonacci(7), Fibonacci(8), Fibonacci(9),
82
- Fibonacci(10), Fibonacci(11), Fibonacci(12), Fibonacci(13),
83
- Fibonacci(14), Fibonacci(15), Fibonacci(16), Fibonacci(17),
84
- Fibonacci(18), Fibonacci(19), Fibonacci(20), Fibonacci(21),
85
- Fibonacci(22), Fibonacci(23), Fibonacci(24), Fibonacci(25),
86
- Fibonacci(26), Fibonacci(27), Fibonacci(28), Fibonacci(29),
87
- Fibonacci(30), Fibonacci(31), Fibonacci(32), Fibonacci(33),
88
- Fibonacci(34), Fibonacci(35), Fibonacci(36), Fibonacci(37),
89
- Fibonacci(38), Fibonacci(39), Fibonacci(40), Fibonacci(41),
90
- Fibonacci(42), Fibonacci(43), Fibonacci(44), Fibonacci(45),
91
- Fibonacci(46), Fibonacci(47),
92
- 0xffffffffffffffffull, // Avoid overflow
93
- };
94
-
95
- static const int kMinLengthSize = ABSL_ARRAYSIZE(min_length);
96
-
97
- static inline bool btree_enabled() {
98
- return cord_internal::cord_btree_enabled.load(
99
- std::memory_order_relaxed);
100
- }
101
-
102
- static inline bool IsRootBalanced(CordRep* node) {
103
- if (!node->IsConcat()) {
104
- return true;
105
- } else if (node->concat()->depth() <= 15) {
106
- return true;
107
- } else if (node->concat()->depth() > kMinLengthSize) {
108
- return false;
109
- } else {
110
- // Allow depth to become twice as large as implied by fibonacci rule to
111
- // reduce rebalancing for larger strings.
112
- return (node->length >= min_length[node->concat()->depth() / 2]);
113
- }
114
- }
115
-
116
- static CordRep* Rebalance(CordRep* node);
117
70
  static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
118
71
  int indent = 0);
119
72
  static bool VerifyNode(CordRep* root, CordRep* start_node,
@@ -135,75 +88,6 @@ static inline CordRep* VerifyTree(CordRep* node) {
135
88
  return node;
136
89
  }
137
90
 
138
- // Return the depth of a node
139
- static int Depth(const CordRep* rep) {
140
- if (rep->IsConcat()) {
141
- return rep->concat()->depth();
142
- } else {
143
- return 0;
144
- }
145
- }
146
-
147
- static void SetConcatChildren(CordRepConcat* concat, CordRep* left,
148
- CordRep* right) {
149
- concat->left = left;
150
- concat->right = right;
151
-
152
- concat->length = left->length + right->length;
153
- concat->set_depth(1 + std::max(Depth(left), Depth(right)));
154
- }
155
-
156
- // Create a concatenation of the specified nodes.
157
- // Does not change the refcounts of "left" and "right".
158
- // The returned node has a refcount of 1.
159
- static CordRep* RawConcat(CordRep* left, CordRep* right) {
160
- // Avoid making degenerate concat nodes (one child is empty)
161
- if (left == nullptr) return right;
162
- if (right == nullptr) return left;
163
- if (left->length == 0) {
164
- CordRep::Unref(left);
165
- return right;
166
- }
167
- if (right->length == 0) {
168
- CordRep::Unref(right);
169
- return left;
170
- }
171
-
172
- CordRepConcat* rep = new CordRepConcat();
173
- rep->tag = cord_internal::CONCAT;
174
- SetConcatChildren(rep, left, right);
175
-
176
- return rep;
177
- }
178
-
179
- static CordRep* Concat(CordRep* left, CordRep* right) {
180
- CordRep* rep = RawConcat(left, right);
181
- if (rep != nullptr && !IsRootBalanced(rep)) {
182
- rep = Rebalance(rep);
183
- }
184
- return VerifyTree(rep);
185
- }
186
-
187
- // Make a balanced tree out of an array of leaf nodes.
188
- static CordRep* MakeBalancedTree(CordRep** reps, size_t n) {
189
- // Make repeated passes over the array, merging adjacent pairs
190
- // until we are left with just a single node.
191
- while (n > 1) {
192
- size_t dst = 0;
193
- for (size_t src = 0; src < n; src += 2) {
194
- if (src + 1 < n) {
195
- reps[dst] = Concat(reps[src], reps[src + 1]);
196
- } else {
197
- reps[dst] = reps[src];
198
- }
199
- dst++;
200
- }
201
- n = dst;
202
- }
203
-
204
- return reps[0];
205
- }
206
-
207
91
  static CordRepFlat* CreateFlat(const char* data, size_t length,
208
92
  size_t alloc_hint) {
209
93
  CordRepFlat* flat = CordRepFlat::New(length + alloc_hint);
@@ -229,21 +113,7 @@ static CordRep* NewBtree(const char* data, size_t length, size_t alloc_hint) {
229
113
  // The returned node has a refcount of 1.
230
114
  static CordRep* NewTree(const char* data, size_t length, size_t alloc_hint) {
231
115
  if (length == 0) return nullptr;
232
- if (btree_enabled()) {
233
- return NewBtree(data, length, alloc_hint);
234
- }
235
- absl::FixedArray<CordRep*> reps((length - 1) / kMaxFlatLength + 1);
236
- size_t n = 0;
237
- do {
238
- const size_t len = std::min(length, kMaxFlatLength);
239
- CordRepFlat* rep = CordRepFlat::New(len + alloc_hint);
240
- rep->length = len;
241
- memcpy(rep->Data(), data, len);
242
- reps[n++] = VerifyTree(rep);
243
- data += len;
244
- length -= len;
245
- } while (length != 0);
246
- return MakeBalancedTree(reps.data(), n);
116
+ return NewBtree(data, length, alloc_hint);
247
117
  }
248
118
 
249
119
  namespace cord_internal {
@@ -258,22 +128,6 @@ void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) {
258
128
 
259
129
  } // namespace cord_internal
260
130
 
261
- static CordRep* NewSubstring(CordRep* child, size_t offset, size_t length) {
262
- // Never create empty substring nodes
263
- if (length == 0) {
264
- CordRep::Unref(child);
265
- return nullptr;
266
- } else {
267
- CordRepSubstring* rep = new CordRepSubstring();
268
- assert((offset + length) <= child->length);
269
- rep->length = length;
270
- rep->tag = cord_internal::SUBSTRING;
271
- rep->start = offset;
272
- rep->child = child;
273
- return VerifyTree(rep);
274
- }
275
- }
276
-
277
131
  // Creates a CordRep from the provided string. If the string is large enough,
278
132
  // and not wasteful, we move the string into an external cord rep, preserving
279
133
  // the already allocated string contents.
@@ -306,13 +160,14 @@ static CordRep* CordRepFromString(std::string&& src) {
306
160
  // --------------------------------------------------------------------
307
161
  // Cord::InlineRep functions
308
162
 
163
+ #ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
309
164
  constexpr unsigned char Cord::InlineRep::kMaxInline;
165
+ #endif
310
166
 
311
- inline void Cord::InlineRep::set_data(const char* data, size_t n,
312
- bool nullify_tail) {
167
+ inline void Cord::InlineRep::set_data(const char* data, size_t n) {
313
168
  static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15");
314
169
 
315
- cord_internal::SmallMemmove(data_.as_chars(), data, n, nullify_tail);
170
+ cord_internal::SmallMemmove<true>(data_.as_chars(), data, n);
316
171
  set_inline_size(n);
317
172
  }
318
173
 
@@ -341,7 +196,9 @@ inline void Cord::InlineRep::remove_prefix(size_t n) {
341
196
  // Returns `rep` converted into a CordRepBtree.
342
197
  // Directly returns `rep` if `rep` is already a CordRepBtree.
343
198
  static CordRepBtree* ForceBtree(CordRep* rep) {
344
- return rep->IsBtree() ? rep->btree() : CordRepBtree::Create(rep);
199
+ return rep->IsBtree()
200
+ ? rep->btree()
201
+ : CordRepBtree::Create(cord_internal::RemoveCrcNode(rep));
345
202
  }
346
203
 
347
204
  void Cord::InlineRep::AppendTreeToInlined(CordRep* tree,
@@ -349,11 +206,7 @@ void Cord::InlineRep::AppendTreeToInlined(CordRep* tree,
349
206
  assert(!is_tree());
350
207
  if (!data_.is_empty()) {
351
208
  CordRepFlat* flat = MakeFlatWithExtraCapacity(0);
352
- if (btree_enabled()) {
353
- tree = CordRepBtree::Append(CordRepBtree::Create(flat), tree);
354
- } else {
355
- tree = Concat(flat, tree);
356
- }
209
+ tree = CordRepBtree::Append(CordRepBtree::Create(flat), tree);
357
210
  }
358
211
  EmplaceTree(tree, method);
359
212
  }
@@ -361,16 +214,14 @@ void Cord::InlineRep::AppendTreeToInlined(CordRep* tree,
361
214
  void Cord::InlineRep::AppendTreeToTree(CordRep* tree, MethodIdentifier method) {
362
215
  assert(is_tree());
363
216
  const CordzUpdateScope scope(data_.cordz_info(), method);
364
- if (btree_enabled()) {
365
- tree = CordRepBtree::Append(ForceBtree(data_.as_tree()), tree);
366
- } else {
367
- tree = Concat(data_.as_tree(), tree);
368
- }
217
+ tree = CordRepBtree::Append(ForceBtree(data_.as_tree()), tree);
369
218
  SetTree(tree, scope);
370
219
  }
371
220
 
372
221
  void Cord::InlineRep::AppendTree(CordRep* tree, MethodIdentifier method) {
373
- if (tree == nullptr) return;
222
+ assert(tree != nullptr);
223
+ assert(tree->length != 0);
224
+ assert(!tree->IsCrc());
374
225
  if (data_.is_tree()) {
375
226
  AppendTreeToTree(tree, method);
376
227
  } else {
@@ -383,11 +234,7 @@ void Cord::InlineRep::PrependTreeToInlined(CordRep* tree,
383
234
  assert(!is_tree());
384
235
  if (!data_.is_empty()) {
385
236
  CordRepFlat* flat = MakeFlatWithExtraCapacity(0);
386
- if (btree_enabled()) {
387
- tree = CordRepBtree::Prepend(CordRepBtree::Create(flat), tree);
388
- } else {
389
- tree = Concat(tree, flat);
390
- }
237
+ tree = CordRepBtree::Prepend(CordRepBtree::Create(flat), tree);
391
238
  }
392
239
  EmplaceTree(tree, method);
393
240
  }
@@ -396,16 +243,14 @@ void Cord::InlineRep::PrependTreeToTree(CordRep* tree,
396
243
  MethodIdentifier method) {
397
244
  assert(is_tree());
398
245
  const CordzUpdateScope scope(data_.cordz_info(), method);
399
- if (btree_enabled()) {
400
- tree = CordRepBtree::Prepend(ForceBtree(data_.as_tree()), tree);
401
- } else {
402
- tree = Concat(tree, data_.as_tree());
403
- }
246
+ tree = CordRepBtree::Prepend(ForceBtree(data_.as_tree()), tree);
404
247
  SetTree(tree, scope);
405
248
  }
406
249
 
407
250
  void Cord::InlineRep::PrependTree(CordRep* tree, MethodIdentifier method) {
408
251
  assert(tree != nullptr);
252
+ assert(tree->length != 0);
253
+ assert(!tree->IsCrc());
409
254
  if (data_.is_tree()) {
410
255
  PrependTreeToTree(tree, method);
411
256
  } else {
@@ -419,7 +264,7 @@ void Cord::InlineRep::PrependTree(CordRep* tree, MethodIdentifier method) {
419
264
  // written to region and the actual size increase will be written to size.
420
265
  static inline bool PrepareAppendRegion(CordRep* root, char** region,
421
266
  size_t* size, size_t max_length) {
422
- if (root->IsBtree() && root->refcount.IsMutable()) {
267
+ if (root->IsBtree() && root->refcount.IsOne()) {
423
268
  Span<char> span = root->btree()->GetAppendBuffer(max_length);
424
269
  if (!span.empty()) {
425
270
  *region = span.data();
@@ -428,13 +273,8 @@ static inline bool PrepareAppendRegion(CordRep* root, char** region,
428
273
  }
429
274
  }
430
275
 
431
- // Search down the right-hand path for a non-full FLAT node.
432
276
  CordRep* dst = root;
433
- while (dst->IsConcat() && dst->refcount.IsMutable()) {
434
- dst = dst->concat()->right;
435
- }
436
-
437
- if (!dst->IsFlat() || !dst->refcount.IsMutable()) {
277
+ if (!dst->IsFlat() || !dst->refcount.IsOne()) {
438
278
  *region = nullptr;
439
279
  *size = 0;
440
280
  return false;
@@ -448,12 +288,7 @@ static inline bool PrepareAppendRegion(CordRep* root, char** region,
448
288
  return false;
449
289
  }
450
290
 
451
- size_t size_increase = std::min(capacity - in_use, max_length);
452
-
453
- // We need to update the length fields for all nodes, including the leaf node.
454
- for (CordRep* rep = root; rep != dst; rep = rep->concat()->right) {
455
- rep->length += size_increase;
456
- }
291
+ const size_t size_increase = std::min(capacity - in_use, max_length);
457
292
  dst->length += size_increase;
458
293
 
459
294
  *region = dst->flat()->Data() + in_use;
@@ -461,90 +296,6 @@ static inline bool PrepareAppendRegion(CordRep* root, char** region,
461
296
  return true;
462
297
  }
463
298
 
464
- template <bool has_length>
465
- void Cord::InlineRep::GetAppendRegion(char** region, size_t* size,
466
- size_t length) {
467
- auto constexpr method = CordzUpdateTracker::kGetAppendRegion;
468
-
469
- CordRep* root = tree();
470
- size_t sz = root ? root->length : inline_size();
471
- if (root == nullptr) {
472
- size_t available = kMaxInline - sz;
473
- if (available >= (has_length ? length : 1)) {
474
- *region = data_.as_chars() + sz;
475
- *size = has_length ? length : available;
476
- set_inline_size(has_length ? sz + length : kMaxInline);
477
- return;
478
- }
479
- }
480
-
481
- size_t extra = has_length ? length : (std::max)(sz, kMinFlatLength);
482
- CordRep* rep = root ? root : MakeFlatWithExtraCapacity(extra);
483
- CordzUpdateScope scope(root ? data_.cordz_info() : nullptr, method);
484
- if (PrepareAppendRegion(rep, region, size, length)) {
485
- CommitTree(root, rep, scope, method);
486
- return;
487
- }
488
-
489
- // Allocate new node.
490
- CordRepFlat* new_node = CordRepFlat::New(extra);
491
- new_node->length = std::min(new_node->Capacity(), length);
492
- *region = new_node->Data();
493
- *size = new_node->length;
494
-
495
- if (btree_enabled()) {
496
- rep = CordRepBtree::Append(ForceBtree(rep), new_node);
497
- } else {
498
- rep = Concat(rep, new_node);
499
- }
500
- CommitTree(root, rep, scope, method);
501
- }
502
-
503
- // Computes the memory side of the provided edge which must be a valid data edge
504
- // for a btrtee, i.e., a FLAT, EXTERNAL or SUBSTRING of a FLAT or EXTERNAL node.
505
- static bool RepMemoryUsageDataEdge(const CordRep* rep,
506
- size_t* total_mem_usage) {
507
- size_t maybe_sub_size = 0;
508
- if (ABSL_PREDICT_FALSE(rep->IsSubstring())) {
509
- maybe_sub_size = sizeof(cord_internal::CordRepSubstring);
510
- rep = rep->substring()->child;
511
- }
512
- if (rep->IsFlat()) {
513
- *total_mem_usage += maybe_sub_size + rep->flat()->AllocatedSize();
514
- return true;
515
- }
516
- if (rep->IsExternal()) {
517
- // We don't know anything about the embedded / bound data, but we can safely
518
- // assume it is 'at least' a word / pointer to data. In the future we may
519
- // choose to use the 'data' byte as a tag to identify the types of some
520
- // well-known externals, such as a std::string instance.
521
- *total_mem_usage += maybe_sub_size +
522
- sizeof(cord_internal::CordRepExternalImpl<intptr_t>) +
523
- rep->length;
524
- return true;
525
- }
526
- return false;
527
- }
528
-
529
- // If the rep is a leaf, this will increment the value at total_mem_usage and
530
- // will return true.
531
- static bool RepMemoryUsageLeaf(const CordRep* rep, size_t* total_mem_usage) {
532
- if (rep->IsFlat()) {
533
- *total_mem_usage += rep->flat()->AllocatedSize();
534
- return true;
535
- }
536
- if (rep->IsExternal()) {
537
- // We don't know anything about the embedded / bound data, but we can safely
538
- // assume it is 'at least' a word / pointer to data. In the future we may
539
- // choose to use the 'data' byte as a tag to identify the types of some
540
- // well-known externals, such as a std::string instance.
541
- *total_mem_usage +=
542
- sizeof(cord_internal::CordRepExternalImpl<intptr_t>) + rep->length;
543
- return true;
544
- }
545
- return false;
546
- }
547
-
548
299
  void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) {
549
300
  assert(&src != this);
550
301
  assert(is_tree() || src.is_tree());
@@ -581,7 +332,7 @@ Cord::Cord(absl::string_view src, MethodIdentifier method)
581
332
  : contents_(InlineData::kDefaultInit) {
582
333
  const size_t n = src.size();
583
334
  if (n <= InlineRep::kMaxInline) {
584
- contents_.set_data(src.data(), n, true);
335
+ contents_.set_data(src.data(), n);
585
336
  } else {
586
337
  CordRep* rep = NewTree(src.data(), n, 0);
587
338
  contents_.EmplaceTree(rep, method);
@@ -591,7 +342,7 @@ Cord::Cord(absl::string_view src, MethodIdentifier method)
591
342
  template <typename T, Cord::EnableIfString<T>>
592
343
  Cord::Cord(T&& src) : contents_(InlineData::kDefaultInit) {
593
344
  if (src.size() <= InlineRep::kMaxInline) {
594
- contents_.set_data(src.data(), src.size(), true);
345
+ contents_.set_data(src.data(), src.size());
595
346
  } else {
596
347
  CordRep* rep = CordRepFromString(std::forward<T>(src));
597
348
  contents_.EmplaceTree(rep, CordzUpdateTracker::kConstructorString);
@@ -642,14 +393,14 @@ Cord& Cord::operator=(absl::string_view src) {
642
393
  // - MaybeUntrackCord must be called before set_data() clobbers cordz_info.
643
394
  // - set_data() must be called before Unref(tree) as it may reference tree.
644
395
  if (tree != nullptr) CordzInfo::MaybeUntrackCord(contents_.cordz_info());
645
- contents_.set_data(data, length, true);
396
+ contents_.set_data(data, length);
646
397
  if (tree != nullptr) CordRep::Unref(tree);
647
398
  return *this;
648
399
  }
649
400
  if (tree != nullptr) {
650
401
  CordzUpdateScope scope(contents_.cordz_info(), method);
651
402
  if (tree->IsFlat() && tree->flat()->Capacity() >= length &&
652
- tree->refcount.IsMutable()) {
403
+ tree->refcount.IsOne()) {
653
404
  // Copy in place if the existing FLAT node is reusable.
654
405
  memmove(tree->flat()->Data(), data, length);
655
406
  tree->length = length;
@@ -675,6 +426,7 @@ void Cord::InlineRep::AppendArray(absl::string_view src,
675
426
  const CordRep* const root = rep;
676
427
  CordzUpdateScope scope(root ? cordz_info() : nullptr, method);
677
428
  if (root != nullptr) {
429
+ rep = cord_internal::RemoveCrcNode(rep);
678
430
  char* region;
679
431
  if (PrepareAppendRegion(rep, &region, &appended, src.size())) {
680
432
  memcpy(region, src.data(), appended);
@@ -705,27 +457,11 @@ void Cord::InlineRep::AppendArray(absl::string_view src,
705
457
  return;
706
458
  }
707
459
 
708
- if (btree_enabled()) {
709
- // TODO(b/192061034): keep legacy 10% growth rate: consider other rates.
710
- rep = ForceBtree(rep);
711
- const size_t min_growth = std::max<size_t>(rep->length / 10, src.size());
712
- rep = CordRepBtree::Append(rep->btree(), src, min_growth - src.size());
713
- } else {
714
- // Use new block(s) for any remaining bytes that were not handled above.
715
- // Alloc extra memory only if the right child of the root of the new tree
716
- // is going to be a FLAT node, which will permit further inplace appends.
717
- size_t length = src.size();
718
- if (src.size() < kMaxFlatLength) {
719
- // The new length is either
720
- // - old size + 10%
721
- // - old_size + src.size()
722
- // This will cause a reasonable conservative step-up in size that is
723
- // still large enough to avoid excessive amounts of small fragments
724
- // being added.
725
- length = std::max<size_t>(rep->length / 10, src.size());
726
- }
727
- rep = Concat(rep, NewTree(src.data(), src.size(), length - src.size()));
728
- }
460
+ // TODO(b/192061034): keep legacy 10% growth rate: consider other rates.
461
+ rep = ForceBtree(rep);
462
+ const size_t min_growth = std::max<size_t>(rep->length / 10, src.size());
463
+ rep = CordRepBtree::Append(rep->btree(), src, min_growth - src.size());
464
+
729
465
  CommitTree(root, rep, scope, method);
730
466
  }
731
467
 
@@ -746,7 +482,8 @@ inline void Cord::AppendImpl(C&& src) {
746
482
  // Since destination is empty, we can avoid allocating a node,
747
483
  if (src.contents_.is_tree()) {
748
484
  // by taking the tree directly
749
- CordRep* rep = std::forward<C>(src).TakeRep();
485
+ CordRep* rep =
486
+ cord_internal::RemoveCrcNode(std::forward<C>(src).TakeRep());
750
487
  contents_.EmplaceTree(rep, method);
751
488
  } else {
752
489
  // or copying over inline data
@@ -782,10 +519,50 @@ inline void Cord::AppendImpl(C&& src) {
782
519
  }
783
520
 
784
521
  // Guaranteed to be a tree (kMaxBytesToCopy > kInlinedSize)
785
- CordRep* rep = std::forward<C>(src).TakeRep();
522
+ CordRep* rep = cord_internal::RemoveCrcNode(std::forward<C>(src).TakeRep());
786
523
  contents_.AppendTree(rep, CordzUpdateTracker::kAppendCord);
787
524
  }
788
525
 
526
+ static CordRep::ExtractResult ExtractAppendBuffer(CordRep* rep,
527
+ size_t min_capacity) {
528
+ switch (rep->tag) {
529
+ case cord_internal::BTREE:
530
+ return CordRepBtree::ExtractAppendBuffer(rep->btree(), min_capacity);
531
+ default:
532
+ if (rep->IsFlat() && rep->refcount.IsOne() &&
533
+ rep->flat()->Capacity() - rep->length >= min_capacity) {
534
+ return {nullptr, rep};
535
+ }
536
+ return {rep, nullptr};
537
+ }
538
+ }
539
+
540
+ static CordBuffer CreateAppendBuffer(InlineData& data, size_t capacity) {
541
+ // Watch out for overflow, people can ask for size_t::max().
542
+ const size_t size = data.inline_size();
543
+ capacity = (std::min)(std::numeric_limits<size_t>::max() - size, capacity);
544
+ CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(size + capacity);
545
+ cord_internal::SmallMemmove(buffer.data(), data.as_chars(), size);
546
+ buffer.SetLength(size);
547
+ data = {};
548
+ return buffer;
549
+ }
550
+
551
+ CordBuffer Cord::GetAppendBufferSlowPath(size_t capacity, size_t min_capacity) {
552
+ auto constexpr method = CordzUpdateTracker::kGetAppendBuffer;
553
+ CordRep* tree = contents_.tree();
554
+ if (tree != nullptr) {
555
+ CordzUpdateScope scope(contents_.cordz_info(), method);
556
+ CordRep::ExtractResult result = ExtractAppendBuffer(tree, min_capacity);
557
+ if (result.extracted != nullptr) {
558
+ contents_.SetTreeOrEmpty(result.tree, scope);
559
+ return CordBuffer(result.extracted->flat());
560
+ }
561
+ return CordBuffer::CreateWithDefaultLimit(capacity);
562
+ }
563
+ return CreateAppendBuffer(contents_.data_, capacity);
564
+ }
565
+
789
566
  void Cord::Append(const Cord& src) {
790
567
  AppendImpl(src);
791
568
  }
@@ -810,7 +587,8 @@ void Cord::Prepend(const Cord& src) {
810
587
  CordRep* src_tree = src.contents_.tree();
811
588
  if (src_tree != nullptr) {
812
589
  CordRep::Ref(src_tree);
813
- contents_.PrependTree(src_tree, CordzUpdateTracker::kPrependCord);
590
+ contents_.PrependTree(cord_internal::RemoveCrcNode(src_tree),
591
+ CordzUpdateTracker::kPrependCord);
814
592
  return;
815
593
  }
816
594
 
@@ -837,103 +615,45 @@ void Cord::PrependArray(absl::string_view src, MethodIdentifier method) {
837
615
  contents_.PrependTree(rep, method);
838
616
  }
839
617
 
840
- template <typename T, Cord::EnableIfString<T>>
841
- inline void Cord::Prepend(T&& src) {
842
- if (src.size() <= kMaxBytesToCopy) {
843
- Prepend(absl::string_view(src));
618
+ void Cord::AppendPrecise(absl::string_view src, MethodIdentifier method) {
619
+ assert(!src.empty());
620
+ assert(src.size() <= cord_internal::kMaxFlatLength);
621
+ if (contents_.remaining_inline_capacity() >= src.size()) {
622
+ const size_t inline_length = contents_.inline_size();
623
+ memcpy(contents_.data_.as_chars() + inline_length, src.data(), src.size());
624
+ contents_.set_inline_size(inline_length + src.size());
844
625
  } else {
845
- CordRep* rep = CordRepFromString(std::forward<T>(src));
846
- contents_.PrependTree(rep, CordzUpdateTracker::kPrependString);
626
+ contents_.AppendTree(CordRepFlat::Create(src), method);
847
627
  }
848
628
  }
849
629
 
850
- template void Cord::Prepend(std::string&& src);
851
-
852
- static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
853
- if (n >= node->length) return nullptr;
854
- if (n == 0) return CordRep::Ref(node);
855
- absl::InlinedVector<CordRep*, kInlinedVectorSize> rhs_stack;
856
-
857
- while (node->IsConcat()) {
858
- assert(n <= node->length);
859
- if (n < node->concat()->left->length) {
860
- // Push right to stack, descend left.
861
- rhs_stack.push_back(node->concat()->right);
862
- node = node->concat()->left;
863
- } else {
864
- // Drop left, descend right.
865
- n -= node->concat()->left->length;
866
- node = node->concat()->right;
867
- }
868
- }
869
- assert(n <= node->length);
870
-
871
- if (n == 0) {
872
- CordRep::Ref(node);
630
+ void Cord::PrependPrecise(absl::string_view src, MethodIdentifier method) {
631
+ assert(!src.empty());
632
+ assert(src.size() <= cord_internal::kMaxFlatLength);
633
+ if (contents_.remaining_inline_capacity() >= src.size()) {
634
+ const size_t inline_length = contents_.inline_size();
635
+ char data[InlineRep::kMaxInline + 1] = {0};
636
+ memcpy(data, src.data(), src.size());
637
+ memcpy(data + src.size(), contents_.data(), inline_length);
638
+ memcpy(contents_.data_.as_chars(), data, InlineRep::kMaxInline + 1);
639
+ contents_.set_inline_size(inline_length + src.size());
873
640
  } else {
874
- size_t start = n;
875
- size_t len = node->length - n;
876
- if (node->IsSubstring()) {
877
- // Consider in-place update of node, similar to in RemoveSuffixFrom().
878
- start += node->substring()->start;
879
- node = node->substring()->child;
880
- }
881
- node = NewSubstring(CordRep::Ref(node), start, len);
882
- }
883
- while (!rhs_stack.empty()) {
884
- node = Concat(node, CordRep::Ref(rhs_stack.back()));
885
- rhs_stack.pop_back();
641
+ contents_.PrependTree(CordRepFlat::Create(src), method);
886
642
  }
887
- return node;
888
643
  }
889
644
 
890
- // RemoveSuffixFrom() is very similar to RemovePrefixFrom(), with the
891
- // exception that removing a suffix has an optimization where a node may be
892
- // edited in place iff that node and all its ancestors have a refcount of 1.
893
- static CordRep* RemoveSuffixFrom(CordRep* node, size_t n) {
894
- if (n >= node->length) return nullptr;
895
- if (n == 0) return CordRep::Ref(node);
896
- absl::InlinedVector<CordRep*, kInlinedVectorSize> lhs_stack;
897
- bool inplace_ok = node->refcount.IsMutable();
898
-
899
- while (node->IsConcat()) {
900
- assert(n <= node->length);
901
- if (n < node->concat()->right->length) {
902
- // Push left to stack, descend right.
903
- lhs_stack.push_back(node->concat()->left);
904
- node = node->concat()->right;
905
- } else {
906
- // Drop right, descend left.
907
- n -= node->concat()->right->length;
908
- node = node->concat()->left;
909
- }
910
- inplace_ok = inplace_ok && node->refcount.IsMutable();
911
- }
912
- assert(n <= node->length);
913
-
914
- if (n == 0) {
915
- CordRep::Ref(node);
916
- } else if (inplace_ok && !node->IsExternal()) {
917
- // Consider making a new buffer if the current node capacity is much
918
- // larger than the new length.
919
- CordRep::Ref(node);
920
- node->length -= n;
645
+ template <typename T, Cord::EnableIfString<T>>
646
+ inline void Cord::Prepend(T&& src) {
647
+ if (src.size() <= kMaxBytesToCopy) {
648
+ Prepend(absl::string_view(src));
921
649
  } else {
922
- size_t start = 0;
923
- size_t len = node->length - n;
924
- if (node->IsSubstring()) {
925
- start = node->substring()->start;
926
- node = node->substring()->child;
927
- }
928
- node = NewSubstring(CordRep::Ref(node), start, len);
929
- }
930
- while (!lhs_stack.empty()) {
931
- node = Concat(CordRep::Ref(lhs_stack.back()), node);
932
- lhs_stack.pop_back();
650
+ CordRep* rep = CordRepFromString(std::forward<T>(src));
651
+ contents_.PrependTree(rep, CordzUpdateTracker::kPrependString);
933
652
  }
934
- return node;
935
653
  }
936
654
 
655
+ template void Cord::Prepend(std::string&& src);
656
+
937
657
  void Cord::RemovePrefix(size_t n) {
938
658
  ABSL_INTERNAL_CHECK(n <= size(),
939
659
  absl::StrCat("Requested prefix size ", n,
@@ -944,14 +664,21 @@ void Cord::RemovePrefix(size_t n) {
944
664
  } else {
945
665
  auto constexpr method = CordzUpdateTracker::kRemovePrefix;
946
666
  CordzUpdateScope scope(contents_.cordz_info(), method);
947
- if (tree->IsBtree()) {
667
+ tree = cord_internal::RemoveCrcNode(tree);
668
+ if (n >= tree->length) {
669
+ CordRep::Unref(tree);
670
+ tree = nullptr;
671
+ } else if (tree->IsBtree()) {
948
672
  CordRep* old = tree;
949
673
  tree = tree->btree()->SubTree(n, tree->length - n);
950
674
  CordRep::Unref(old);
675
+ } else if (tree->IsSubstring() && tree->refcount.IsOne()) {
676
+ tree->substring()->start += n;
677
+ tree->length -= n;
951
678
  } else {
952
- CordRep* newrep = RemovePrefixFrom(tree, n);
679
+ CordRep* rep = CordRepSubstring::Substring(tree, n, tree->length - n);
953
680
  CordRep::Unref(tree);
954
- tree = VerifyTree(newrep);
681
+ tree = rep;
955
682
  }
956
683
  contents_.SetTreeOrEmpty(tree, scope);
957
684
  }
@@ -967,68 +694,24 @@ void Cord::RemoveSuffix(size_t n) {
967
694
  } else {
968
695
  auto constexpr method = CordzUpdateTracker::kRemoveSuffix;
969
696
  CordzUpdateScope scope(contents_.cordz_info(), method);
970
- if (tree->IsBtree()) {
697
+ tree = cord_internal::RemoveCrcNode(tree);
698
+ if (n >= tree->length) {
699
+ CordRep::Unref(tree);
700
+ tree = nullptr;
701
+ } else if (tree->IsBtree()) {
971
702
  tree = CordRepBtree::RemoveSuffix(tree->btree(), n);
703
+ } else if (!tree->IsExternal() && tree->refcount.IsOne()) {
704
+ assert(tree->IsFlat() || tree->IsSubstring());
705
+ tree->length -= n;
972
706
  } else {
973
- CordRep* newrep = RemoveSuffixFrom(tree, n);
707
+ CordRep* rep = CordRepSubstring::Substring(tree, 0, tree->length - n);
974
708
  CordRep::Unref(tree);
975
- tree = VerifyTree(newrep);
709
+ tree = rep;
976
710
  }
977
711
  contents_.SetTreeOrEmpty(tree, scope);
978
712
  }
979
713
  }
980
714
 
981
- // Work item for NewSubRange().
982
- struct SubRange {
983
- SubRange(CordRep* a_node, size_t a_pos, size_t a_n)
984
- : node(a_node), pos(a_pos), n(a_n) {}
985
- CordRep* node; // nullptr means concat last 2 results.
986
- size_t pos;
987
- size_t n;
988
- };
989
-
990
- static CordRep* NewSubRange(CordRep* node, size_t pos, size_t n) {
991
- absl::InlinedVector<CordRep*, kInlinedVectorSize> results;
992
- absl::InlinedVector<SubRange, kInlinedVectorSize> todo;
993
- todo.push_back(SubRange(node, pos, n));
994
- do {
995
- const SubRange& sr = todo.back();
996
- node = sr.node;
997
- pos = sr.pos;
998
- n = sr.n;
999
- todo.pop_back();
1000
-
1001
- if (node == nullptr) {
1002
- assert(results.size() >= 2);
1003
- CordRep* right = results.back();
1004
- results.pop_back();
1005
- CordRep* left = results.back();
1006
- results.pop_back();
1007
- results.push_back(Concat(left, right));
1008
- } else if (pos == 0 && n == node->length) {
1009
- results.push_back(CordRep::Ref(node));
1010
- } else if (!node->IsConcat()) {
1011
- if (node->IsSubstring()) {
1012
- pos += node->substring()->start;
1013
- node = node->substring()->child;
1014
- }
1015
- results.push_back(NewSubstring(CordRep::Ref(node), pos, n));
1016
- } else if (pos + n <= node->concat()->left->length) {
1017
- todo.push_back(SubRange(node->concat()->left, pos, n));
1018
- } else if (pos >= node->concat()->left->length) {
1019
- pos -= node->concat()->left->length;
1020
- todo.push_back(SubRange(node->concat()->right, pos, n));
1021
- } else {
1022
- size_t left_n = node->concat()->left->length - pos;
1023
- todo.push_back(SubRange(nullptr, 0, 0)); // Concat()
1024
- todo.push_back(SubRange(node->concat()->right, 0, n - left_n));
1025
- todo.push_back(SubRange(node->concat()->left, pos, left_n));
1026
- }
1027
- } while (!todo.empty());
1028
- assert(results.size() == 1);
1029
- return results[0];
1030
- }
1031
-
1032
715
  Cord Cord::Subcord(size_t pos, size_t new_size) const {
1033
716
  Cord sub_cord;
1034
717
  size_t length = size();
@@ -1038,9 +721,7 @@ Cord Cord::Subcord(size_t pos, size_t new_size) const {
1038
721
 
1039
722
  CordRep* tree = contents_.tree();
1040
723
  if (tree == nullptr) {
1041
- // sub_cord is newly constructed, no need to re-zero-out the tail of
1042
- // contents_ memory.
1043
- sub_cord.contents_.set_data(contents_.data() + pos, new_size, false);
724
+ sub_cord.contents_.set_data(contents_.data() + pos, new_size);
1044
725
  return sub_cord;
1045
726
  }
1046
727
 
@@ -1060,156 +741,17 @@ Cord Cord::Subcord(size_t pos, size_t new_size) const {
1060
741
  return sub_cord;
1061
742
  }
1062
743
 
744
+ tree = cord_internal::SkipCrcNode(tree);
1063
745
  if (tree->IsBtree()) {
1064
746
  tree = tree->btree()->SubTree(pos, new_size);
1065
747
  } else {
1066
- tree = NewSubRange(tree, pos, new_size);
748
+ tree = CordRepSubstring::Substring(tree, pos, new_size);
1067
749
  }
1068
750
  sub_cord.contents_.EmplaceTree(tree, contents_.data_,
1069
751
  CordzUpdateTracker::kSubCord);
1070
752
  return sub_cord;
1071
753
  }
1072
754
 
1073
- // --------------------------------------------------------------------
1074
- // Balancing
1075
-
1076
- class CordForest {
1077
- public:
1078
- explicit CordForest(size_t length)
1079
- : root_length_(length), trees_(kMinLengthSize, nullptr) {}
1080
-
1081
- void Build(CordRep* cord_root) {
1082
- std::vector<CordRep*> pending = {cord_root};
1083
-
1084
- while (!pending.empty()) {
1085
- CordRep* node = pending.back();
1086
- pending.pop_back();
1087
- CheckNode(node);
1088
- if (ABSL_PREDICT_FALSE(!node->IsConcat())) {
1089
- AddNode(node);
1090
- continue;
1091
- }
1092
-
1093
- CordRepConcat* concat_node = node->concat();
1094
- if (concat_node->depth() >= kMinLengthSize ||
1095
- concat_node->length < min_length[concat_node->depth()]) {
1096
- pending.push_back(concat_node->right);
1097
- pending.push_back(concat_node->left);
1098
-
1099
- if (concat_node->refcount.IsOne()) {
1100
- concat_node->left = concat_freelist_;
1101
- concat_freelist_ = concat_node;
1102
- } else {
1103
- CordRep::Ref(concat_node->right);
1104
- CordRep::Ref(concat_node->left);
1105
- CordRep::Unref(concat_node);
1106
- }
1107
- } else {
1108
- AddNode(node);
1109
- }
1110
- }
1111
- }
1112
-
1113
- CordRep* ConcatNodes() {
1114
- CordRep* sum = nullptr;
1115
- for (auto* node : trees_) {
1116
- if (node == nullptr) continue;
1117
-
1118
- sum = PrependNode(node, sum);
1119
- root_length_ -= node->length;
1120
- if (root_length_ == 0) break;
1121
- }
1122
- ABSL_INTERNAL_CHECK(sum != nullptr, "Failed to locate sum node");
1123
- return VerifyTree(sum);
1124
- }
1125
-
1126
- private:
1127
- CordRep* AppendNode(CordRep* node, CordRep* sum) {
1128
- return (sum == nullptr) ? node : MakeConcat(sum, node);
1129
- }
1130
-
1131
- CordRep* PrependNode(CordRep* node, CordRep* sum) {
1132
- return (sum == nullptr) ? node : MakeConcat(node, sum);
1133
- }
1134
-
1135
- void AddNode(CordRep* node) {
1136
- CordRep* sum = nullptr;
1137
-
1138
- // Collect together everything with which we will merge with node
1139
- int i = 0;
1140
- for (; node->length > min_length[i + 1]; ++i) {
1141
- auto& tree_at_i = trees_[i];
1142
-
1143
- if (tree_at_i == nullptr) continue;
1144
- sum = PrependNode(tree_at_i, sum);
1145
- tree_at_i = nullptr;
1146
- }
1147
-
1148
- sum = AppendNode(node, sum);
1149
-
1150
- // Insert sum into appropriate place in the forest
1151
- for (; sum->length >= min_length[i]; ++i) {
1152
- auto& tree_at_i = trees_[i];
1153
- if (tree_at_i == nullptr) continue;
1154
-
1155
- sum = MakeConcat(tree_at_i, sum);
1156
- tree_at_i = nullptr;
1157
- }
1158
-
1159
- // min_length[0] == 1, which means sum->length >= min_length[0]
1160
- assert(i > 0);
1161
- trees_[i - 1] = sum;
1162
- }
1163
-
1164
- // Make concat node trying to resue existing CordRepConcat nodes we
1165
- // already collected in the concat_freelist_.
1166
- CordRep* MakeConcat(CordRep* left, CordRep* right) {
1167
- if (concat_freelist_ == nullptr) return RawConcat(left, right);
1168
-
1169
- CordRepConcat* rep = concat_freelist_;
1170
- if (concat_freelist_->left == nullptr) {
1171
- concat_freelist_ = nullptr;
1172
- } else {
1173
- concat_freelist_ = concat_freelist_->left->concat();
1174
- }
1175
- SetConcatChildren(rep, left, right);
1176
-
1177
- return rep;
1178
- }
1179
-
1180
- static void CheckNode(CordRep* node) {
1181
- ABSL_INTERNAL_CHECK(node->length != 0u, "");
1182
- if (node->IsConcat()) {
1183
- ABSL_INTERNAL_CHECK(node->concat()->left != nullptr, "");
1184
- ABSL_INTERNAL_CHECK(node->concat()->right != nullptr, "");
1185
- ABSL_INTERNAL_CHECK(node->length == (node->concat()->left->length +
1186
- node->concat()->right->length),
1187
- "");
1188
- }
1189
- }
1190
-
1191
- size_t root_length_;
1192
-
1193
- // use an inlined vector instead of a flat array to get bounds checking
1194
- absl::InlinedVector<CordRep*, kInlinedVectorSize> trees_;
1195
-
1196
- // List of concat nodes we can re-use for Cord balancing.
1197
- CordRepConcat* concat_freelist_ = nullptr;
1198
- };
1199
-
1200
- static CordRep* Rebalance(CordRep* node) {
1201
- VerifyTree(node);
1202
- assert(node->IsConcat());
1203
-
1204
- if (node->length == 0) {
1205
- return nullptr;
1206
- }
1207
-
1208
- CordForest forest(node->length);
1209
- forest.Build(node);
1210
- return forest.ConcatNodes();
1211
- }
1212
-
1213
755
  // --------------------------------------------------------------------
1214
756
  // Comparators
1215
757
 
@@ -1256,7 +798,7 @@ inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
1256
798
  return absl::string_view(data_.as_chars(), data_.inline_size());
1257
799
  }
1258
800
 
1259
- CordRep* node = tree();
801
+ CordRep* node = cord_internal::SkipCrcNode(tree());
1260
802
  if (node->IsFlat()) {
1261
803
  return absl::string_view(node->flat()->Data(), node->length);
1262
804
  }
@@ -1274,11 +816,6 @@ inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
1274
816
  return tree->Data(tree->begin());
1275
817
  }
1276
818
 
1277
- // Walk down the left branches until we hit a non-CONCAT node.
1278
- while (node->IsConcat()) {
1279
- node = node->concat()->left;
1280
- }
1281
-
1282
819
  // Get the child node if we encounter a SUBSTRING.
1283
820
  size_t offset = 0;
1284
821
  size_t length = node->length;
@@ -1298,6 +835,28 @@ inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
1298
835
  return absl::string_view(node->external()->base + offset, length);
1299
836
  }
1300
837
 
838
+ void Cord::SetExpectedChecksum(uint32_t crc) {
839
+ auto constexpr method = CordzUpdateTracker::kSetExpectedChecksum;
840
+ if (empty()) return;
841
+
842
+ if (!contents_.is_tree()) {
843
+ CordRep* rep = contents_.MakeFlatWithExtraCapacity(0);
844
+ rep = CordRepCrc::New(rep, crc);
845
+ contents_.EmplaceTree(rep, method);
846
+ } else {
847
+ const CordzUpdateScope scope(contents_.data_.cordz_info(), method);
848
+ CordRep* rep = CordRepCrc::New(contents_.data_.as_tree(), crc);
849
+ contents_.SetTree(rep, scope);
850
+ }
851
+ }
852
+
853
+ absl::optional<uint32_t> Cord::ExpectedChecksum() const {
854
+ if (!contents_.is_tree() || !contents_.tree()->IsCrc()) {
855
+ return absl::nullopt;
856
+ }
857
+ return contents_.tree()->crc()->crc;
858
+ }
859
+
1301
860
  inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size,
1302
861
  size_t size_to_compare) const {
1303
862
  auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) {
@@ -1473,42 +1032,6 @@ void Cord::CopyToArraySlowPath(char* dst) const {
1473
1032
  }
1474
1033
  }
1475
1034
 
1476
- Cord::ChunkIterator& Cord::ChunkIterator::AdvanceStack() {
1477
- auto& stack_of_right_children = stack_of_right_children_;
1478
- if (stack_of_right_children.empty()) {
1479
- assert(!current_chunk_.empty()); // Called on invalid iterator.
1480
- // We have reached the end of the Cord.
1481
- return *this;
1482
- }
1483
-
1484
- // Process the next node on the stack.
1485
- CordRep* node = stack_of_right_children.back();
1486
- stack_of_right_children.pop_back();
1487
-
1488
- // Walk down the left branches until we hit a non-CONCAT node. Save the
1489
- // right children to the stack for subsequent traversal.
1490
- while (node->IsConcat()) {
1491
- stack_of_right_children.push_back(node->concat()->right);
1492
- node = node->concat()->left;
1493
- }
1494
-
1495
- // Get the child node if we encounter a SUBSTRING.
1496
- size_t offset = 0;
1497
- size_t length = node->length;
1498
- if (node->IsSubstring()) {
1499
- offset = node->substring()->start;
1500
- node = node->substring()->child;
1501
- }
1502
-
1503
- assert(node->IsExternal() || node->IsFlat());
1504
- assert(length != 0);
1505
- const char* data =
1506
- node->IsExternal() ? node->external()->base : node->flat()->Data();
1507
- current_chunk_ = absl::string_view(data + offset, length);
1508
- current_leaf_ = node;
1509
- return *this;
1510
- }
1511
-
1512
1035
  Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
1513
1036
  ABSL_HARDENING_ASSERT(bytes_remaining_ >= n &&
1514
1037
  "Attempted to iterate past `end()`");
@@ -1551,166 +1074,33 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
1551
1074
  return subcord;
1552
1075
  }
1553
1076
 
1554
- auto& stack_of_right_children = stack_of_right_children_;
1555
- if (n < current_chunk_.size()) {
1556
- // Range to read is a proper subrange of the current chunk.
1557
- assert(current_leaf_ != nullptr);
1558
- CordRep* subnode = CordRep::Ref(current_leaf_);
1559
- const char* data = subnode->IsExternal() ? subnode->external()->base
1560
- : subnode->flat()->Data();
1561
- subnode = NewSubstring(subnode, current_chunk_.data() - data, n);
1562
- subcord.contents_.EmplaceTree(VerifyTree(subnode), method);
1563
- RemoveChunkPrefix(n);
1564
- return subcord;
1565
- }
1566
-
1567
- // Range to read begins with a proper subrange of the current chunk.
1568
- assert(!current_chunk_.empty());
1077
+ // Short circuit if reading the entire data edge.
1569
1078
  assert(current_leaf_ != nullptr);
1570
- CordRep* subnode = CordRep::Ref(current_leaf_);
1571
- if (current_chunk_.size() < subnode->length) {
1572
- const char* data = subnode->IsExternal() ? subnode->external()->base
1573
- : subnode->flat()->Data();
1574
- subnode = NewSubstring(subnode, current_chunk_.data() - data,
1575
- current_chunk_.size());
1576
- }
1577
- n -= current_chunk_.size();
1578
- bytes_remaining_ -= current_chunk_.size();
1579
-
1580
- // Process the next node(s) on the stack, reading whole subtrees depending on
1581
- // their length and how many bytes we are advancing.
1582
- CordRep* node = nullptr;
1583
- while (!stack_of_right_children.empty()) {
1584
- node = stack_of_right_children.back();
1585
- stack_of_right_children.pop_back();
1586
- if (node->length > n) break;
1587
- // TODO(qrczak): This might unnecessarily recreate existing concat nodes.
1588
- // Avoiding that would need pretty complicated logic (instead of
1589
- // current_leaf, keep current_subtree_ which points to the highest node
1590
- // such that the current leaf can be found on the path of left children
1591
- // starting from current_subtree_; delay creating subnode while node is
1592
- // below current_subtree_; find the proper node along the path of left
1593
- // children starting from current_subtree_ if this loop exits while staying
1594
- // below current_subtree_; etc.; alternatively, push parents instead of
1595
- // right children on the stack).
1596
- subnode = Concat(subnode, CordRep::Ref(node));
1597
- n -= node->length;
1598
- bytes_remaining_ -= node->length;
1599
- node = nullptr;
1600
- }
1601
-
1602
- if (node == nullptr) {
1603
- // We have reached the end of the Cord.
1604
- assert(bytes_remaining_ == 0);
1605
- subcord.contents_.EmplaceTree(VerifyTree(subnode), method);
1079
+ if (n == current_leaf_->length) {
1080
+ bytes_remaining_ = 0;
1081
+ current_chunk_ = {};
1082
+ CordRep* tree = CordRep::Ref(current_leaf_);
1083
+ subcord.contents_.EmplaceTree(VerifyTree(tree), method);
1606
1084
  return subcord;
1607
1085
  }
1608
1086
 
1609
- // Walk down the appropriate branches until we hit a non-CONCAT node. Save the
1610
- // right children to the stack for subsequent traversal.
1611
- while (node->IsConcat()) {
1612
- if (node->concat()->left->length > n) {
1613
- // Push right, descend left.
1614
- stack_of_right_children.push_back(node->concat()->right);
1615
- node = node->concat()->left;
1616
- } else {
1617
- // Read left, descend right.
1618
- subnode = Concat(subnode, CordRep::Ref(node->concat()->left));
1619
- n -= node->concat()->left->length;
1620
- bytes_remaining_ -= node->concat()->left->length;
1621
- node = node->concat()->right;
1622
- }
1623
- }
1624
-
1625
- // Get the child node if we encounter a SUBSTRING.
1626
- size_t offset = 0;
1627
- size_t length = node->length;
1628
- if (node->IsSubstring()) {
1629
- offset = node->substring()->start;
1630
- node = node->substring()->child;
1631
- }
1087
+ // From this point on, we need a partial substring node.
1088
+ // Get pointer to the underlying flat or external data payload and
1089
+ // compute data pointer and offset into current flat or external.
1090
+ CordRep* payload = current_leaf_->IsSubstring()
1091
+ ? current_leaf_->substring()->child
1092
+ : current_leaf_;
1093
+ const char* data = payload->IsExternal() ? payload->external()->base
1094
+ : payload->flat()->Data();
1095
+ const size_t offset = current_chunk_.data() - data;
1632
1096
 
1633
- // Range to read ends with a proper (possibly empty) subrange of the current
1634
- // chunk.
1635
- assert(node->IsExternal() || node->IsFlat());
1636
- assert(length > n);
1637
- if (n > 0) {
1638
- subnode = Concat(subnode, NewSubstring(CordRep::Ref(node), offset, n));
1639
- }
1640
- const char* data =
1641
- node->IsExternal() ? node->external()->base : node->flat()->Data();
1642
- current_chunk_ = absl::string_view(data + offset + n, length - n);
1643
- current_leaf_ = node;
1097
+ auto* tree = CordRepSubstring::Substring(payload, offset, n);
1098
+ subcord.contents_.EmplaceTree(VerifyTree(tree), method);
1644
1099
  bytes_remaining_ -= n;
1645
- subcord.contents_.EmplaceTree(VerifyTree(subnode), method);
1100
+ current_chunk_.remove_prefix(n);
1646
1101
  return subcord;
1647
1102
  }
1648
1103
 
1649
- void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
1650
- assert(bytes_remaining_ >= n && "Attempted to iterate past `end()`");
1651
- assert(n >= current_chunk_.size()); // This should only be called when
1652
- // iterating to a new node.
1653
-
1654
- n -= current_chunk_.size();
1655
- bytes_remaining_ -= current_chunk_.size();
1656
-
1657
- if (stack_of_right_children_.empty()) {
1658
- // We have reached the end of the Cord.
1659
- assert(bytes_remaining_ == 0);
1660
- return;
1661
- }
1662
-
1663
- // Process the next node(s) on the stack, skipping whole subtrees depending on
1664
- // their length and how many bytes we are advancing.
1665
- CordRep* node = nullptr;
1666
- auto& stack_of_right_children = stack_of_right_children_;
1667
- while (!stack_of_right_children.empty()) {
1668
- node = stack_of_right_children.back();
1669
- stack_of_right_children.pop_back();
1670
- if (node->length > n) break;
1671
- n -= node->length;
1672
- bytes_remaining_ -= node->length;
1673
- node = nullptr;
1674
- }
1675
-
1676
- if (node == nullptr) {
1677
- // We have reached the end of the Cord.
1678
- assert(bytes_remaining_ == 0);
1679
- return;
1680
- }
1681
-
1682
- // Walk down the appropriate branches until we hit a non-CONCAT node. Save the
1683
- // right children to the stack for subsequent traversal.
1684
- while (node->IsConcat()) {
1685
- if (node->concat()->left->length > n) {
1686
- // Push right, descend left.
1687
- stack_of_right_children.push_back(node->concat()->right);
1688
- node = node->concat()->left;
1689
- } else {
1690
- // Skip left, descend right.
1691
- n -= node->concat()->left->length;
1692
- bytes_remaining_ -= node->concat()->left->length;
1693
- node = node->concat()->right;
1694
- }
1695
- }
1696
-
1697
- // Get the child node if we encounter a SUBSTRING.
1698
- size_t offset = 0;
1699
- size_t length = node->length;
1700
- if (node->IsSubstring()) {
1701
- offset = node->substring()->start;
1702
- node = node->substring()->child;
1703
- }
1704
-
1705
- assert(node->IsExternal() || node->IsFlat());
1706
- assert(length > n);
1707
- const char* data =
1708
- node->IsExternal() ? node->external()->base : node->flat()->Data();
1709
- current_chunk_ = absl::string_view(data + offset + n, length - n);
1710
- current_leaf_ = node;
1711
- bytes_remaining_ -= n;
1712
- }
1713
-
1714
1104
  char Cord::operator[](size_t i) const {
1715
1105
  ABSL_HARDENING_ASSERT(i < size());
1716
1106
  size_t offset = i;
@@ -1718,6 +1108,7 @@ char Cord::operator[](size_t i) const {
1718
1108
  if (rep == nullptr) {
1719
1109
  return contents_.data()[i];
1720
1110
  }
1111
+ rep = cord_internal::SkipCrcNode(rep);
1721
1112
  while (true) {
1722
1113
  assert(rep != nullptr);
1723
1114
  assert(offset < rep->length);
@@ -1729,16 +1120,6 @@ char Cord::operator[](size_t i) const {
1729
1120
  } else if (rep->IsExternal()) {
1730
1121
  // Get the "i"th character from the external array.
1731
1122
  return rep->external()->base[offset];
1732
- } else if (rep->IsConcat()) {
1733
- // Recursively branch to the side of the concatenation that the "i"th
1734
- // character is on.
1735
- size_t left_length = rep->concat()->left->length;
1736
- if (offset < left_length) {
1737
- rep = rep->concat()->left;
1738
- } else {
1739
- offset -= left_length;
1740
- rep = rep->concat()->right;
1741
- }
1742
1123
  } else {
1743
1124
  // This must be a substring a node, so bypass it to get to the child.
1744
1125
  assert(rep->IsSubstring());
@@ -1778,6 +1159,7 @@ absl::string_view Cord::FlattenSlowPath() {
1778
1159
 
1779
1160
  /* static */ bool Cord::GetFlatAux(CordRep* rep, absl::string_view* fragment) {
1780
1161
  assert(rep != nullptr);
1162
+ rep = cord_internal::SkipCrcNode(rep);
1781
1163
  if (rep->IsFlat()) {
1782
1164
  *fragment = absl::string_view(rep->flat()->Data(), rep->length);
1783
1165
  return true;
@@ -1807,6 +1189,9 @@ absl::string_view Cord::FlattenSlowPath() {
1807
1189
  /* static */ void Cord::ForEachChunkAux(
1808
1190
  absl::cord_internal::CordRep* rep,
1809
1191
  absl::FunctionRef<void(absl::string_view)> callback) {
1192
+ assert(rep != nullptr);
1193
+ rep = cord_internal::SkipCrcNode(rep);
1194
+
1810
1195
  if (rep->IsBtree()) {
1811
1196
  ChunkIterator it(rep), end;
1812
1197
  while (it != end) {
@@ -1816,44 +1201,13 @@ absl::string_view Cord::FlattenSlowPath() {
1816
1201
  return;
1817
1202
  }
1818
1203
 
1819
- assert(rep != nullptr);
1820
- int stack_pos = 0;
1821
- constexpr int stack_max = 128;
1822
- // Stack of right branches for tree traversal
1823
- absl::cord_internal::CordRep* stack[stack_max];
1824
- absl::cord_internal::CordRep* current_node = rep;
1825
- while (true) {
1826
- if (current_node->IsConcat()) {
1827
- if (stack_pos == stack_max) {
1828
- // There's no more room on our stack array to add another right branch,
1829
- // and the idea is to avoid allocations, so call this function
1830
- // recursively to navigate this subtree further. (This is not something
1831
- // we expect to happen in practice).
1832
- ForEachChunkAux(current_node, callback);
1833
-
1834
- // Pop the next right branch and iterate.
1835
- current_node = stack[--stack_pos];
1836
- continue;
1837
- } else {
1838
- // Save the right branch for later traversal and continue down the left
1839
- // branch.
1840
- stack[stack_pos++] = current_node->concat()->right;
1841
- current_node = current_node->concat()->left;
1842
- continue;
1843
- }
1844
- }
1845
- // This is a leaf node, so invoke our callback.
1846
- absl::string_view chunk;
1847
- bool success = GetFlatAux(current_node, &chunk);
1848
- assert(success);
1849
- if (success) {
1850
- callback(chunk);
1851
- }
1852
- if (stack_pos == 0) {
1853
- // end of traversal
1854
- return;
1855
- }
1856
- current_node = stack[--stack_pos];
1204
+ // This is a leaf node, so invoke our callback.
1205
+ absl::cord_internal::CordRep* current_node = cord_internal::SkipCrcNode(rep);
1206
+ absl::string_view chunk;
1207
+ bool success = GetFlatAux(current_node, &chunk);
1208
+ assert(success);
1209
+ if (success) {
1210
+ callback(chunk);
1857
1211
  }
1858
1212
  }
1859
1213
 
@@ -1868,14 +1222,11 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
1868
1222
  *os << " [";
1869
1223
  if (include_data) *os << static_cast<void*>(rep);
1870
1224
  *os << "]";
1871
- *os << " " << (IsRootBalanced(rep) ? 'b' : 'u');
1872
1225
  *os << " " << std::setw(indent) << "";
1873
- if (rep->IsConcat()) {
1874
- *os << "CONCAT depth=" << Depth(rep) << "\n";
1226
+ if (rep->IsCrc()) {
1227
+ *os << "CRC crc=" << rep->crc()->crc << "\n";
1875
1228
  indent += kIndentStep;
1876
- indents.push_back(indent);
1877
- stack.push_back(rep->concat()->right);
1878
- rep = rep->concat()->left;
1229
+ rep = rep->crc()->child;
1879
1230
  } else if (rep->IsSubstring()) {
1880
1231
  *os << "SUBSTRING @ " << rep->substring()->start << "\n";
1881
1232
  indent += kIndentStep;
@@ -1912,7 +1263,7 @@ static std::string ReportError(CordRep* root, CordRep* node) {
1912
1263
  }
1913
1264
 
1914
1265
  static bool VerifyNode(CordRep* root, CordRep* start_node,
1915
- bool full_validation) {
1266
+ bool /* full_validation */) {
1916
1267
  absl::InlinedVector<CordRep*, 2> worklist;
1917
1268
  worklist.push_back(start_node);
1918
1269
  do {
@@ -1922,21 +1273,10 @@ static bool VerifyNode(CordRep* root, CordRep* start_node,
1922
1273
  ABSL_INTERNAL_CHECK(node != nullptr, ReportError(root, node));
1923
1274
  if (node != root) {
1924
1275
  ABSL_INTERNAL_CHECK(node->length != 0, ReportError(root, node));
1276
+ ABSL_INTERNAL_CHECK(!node->IsCrc(), ReportError(root, node));
1925
1277
  }
1926
1278
 
1927
- if (node->IsConcat()) {
1928
- ABSL_INTERNAL_CHECK(node->concat()->left != nullptr,
1929
- ReportError(root, node));
1930
- ABSL_INTERNAL_CHECK(node->concat()->right != nullptr,
1931
- ReportError(root, node));
1932
- ABSL_INTERNAL_CHECK((node->length == node->concat()->left->length +
1933
- node->concat()->right->length),
1934
- ReportError(root, node));
1935
- if (full_validation) {
1936
- worklist.push_back(node->concat()->right);
1937
- worklist.push_back(node->concat()->left);
1938
- }
1939
- } else if (node->IsFlat()) {
1279
+ if (node->IsFlat()) {
1940
1280
  ABSL_INTERNAL_CHECK(node->length <= node->flat()->Capacity(),
1941
1281
  ReportError(root, node));
1942
1282
  } else if (node->IsExternal()) {
@@ -1949,75 +1289,17 @@ static bool VerifyNode(CordRep* root, CordRep* start_node,
1949
1289
  ABSL_INTERNAL_CHECK(node->substring()->start + node->length <=
1950
1290
  node->substring()->child->length,
1951
1291
  ReportError(root, node));
1292
+ } else if (node->IsCrc()) {
1293
+ ABSL_INTERNAL_CHECK(node->crc()->child != nullptr,
1294
+ ReportError(root, node));
1295
+ ABSL_INTERNAL_CHECK(node->crc()->length == node->crc()->child->length,
1296
+ ReportError(root, node));
1297
+ worklist.push_back(node->crc()->child);
1952
1298
  }
1953
1299
  } while (!worklist.empty());
1954
1300
  return true;
1955
1301
  }
1956
1302
 
1957
- // Traverses the tree and computes the total memory allocated.
1958
- /* static */ size_t Cord::MemoryUsageAux(const CordRep* rep) {
1959
- size_t total_mem_usage = 0;
1960
-
1961
- // Allow a quick exit for the common case that the root is a leaf.
1962
- if (RepMemoryUsageLeaf(rep, &total_mem_usage)) {
1963
- return total_mem_usage;
1964
- }
1965
-
1966
- // Iterate over the tree. cur_node is never a leaf node and leaf nodes will
1967
- // never be appended to tree_stack. This reduces overhead from manipulating
1968
- // tree_stack.
1969
- absl::InlinedVector<const CordRep*, kInlinedVectorSize> tree_stack;
1970
- const CordRep* cur_node = rep;
1971
- while (true) {
1972
- const CordRep* next_node = nullptr;
1973
-
1974
- if (cur_node->IsConcat()) {
1975
- total_mem_usage += sizeof(CordRepConcat);
1976
- const CordRep* left = cur_node->concat()->left;
1977
- if (!RepMemoryUsageLeaf(left, &total_mem_usage)) {
1978
- next_node = left;
1979
- }
1980
-
1981
- const CordRep* right = cur_node->concat()->right;
1982
- if (!RepMemoryUsageLeaf(right, &total_mem_usage)) {
1983
- if (next_node) {
1984
- tree_stack.push_back(next_node);
1985
- }
1986
- next_node = right;
1987
- }
1988
- } else if (cur_node->IsBtree()) {
1989
- total_mem_usage += sizeof(CordRepBtree);
1990
- const CordRepBtree* node = cur_node->btree();
1991
- if (node->height() == 0) {
1992
- for (const CordRep* edge : node->Edges()) {
1993
- RepMemoryUsageDataEdge(edge, &total_mem_usage);
1994
- }
1995
- } else {
1996
- for (const CordRep* edge : node->Edges()) {
1997
- tree_stack.push_back(edge);
1998
- }
1999
- }
2000
- } else {
2001
- // Since cur_node is not a leaf or a concat node it must be a substring.
2002
- assert(cur_node->IsSubstring());
2003
- total_mem_usage += sizeof(CordRepSubstring);
2004
- next_node = cur_node->substring()->child;
2005
- if (RepMemoryUsageLeaf(next_node, &total_mem_usage)) {
2006
- next_node = nullptr;
2007
- }
2008
- }
2009
-
2010
- if (!next_node) {
2011
- if (tree_stack.empty()) {
2012
- return total_mem_usage;
2013
- }
2014
- next_node = tree_stack.back();
2015
- tree_stack.pop_back();
2016
- }
2017
- cur_node = next_node;
2018
- }
2019
- }
2020
-
2021
1303
  std::ostream& operator<<(std::ostream& out, const Cord& cord) {
2022
1304
  for (absl::string_view chunk : cord.Chunks()) {
2023
1305
  out.write(chunk.data(), chunk.size());
@@ -2035,7 +1317,6 @@ uint8_t CordTestAccess::LengthToTag(size_t s) {
2035
1317
  ABSL_INTERNAL_CHECK(s <= kMaxFlatLength, absl::StrCat("Invalid length ", s));
2036
1318
  return cord_internal::AllocatedSizeToTag(s + cord_internal::kFlatOverhead);
2037
1319
  }
2038
- size_t CordTestAccess::SizeofCordRepConcat() { return sizeof(CordRepConcat); }
2039
1320
  size_t CordTestAccess::SizeofCordRepExternal() {
2040
1321
  return sizeof(CordRepExternal);
2041
1322
  }