grpc 1.37.1 → 1.38.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 (544) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +64 -58
  3. data/include/grpc/event_engine/README.md +38 -0
  4. data/include/grpc/event_engine/channel_args.h +28 -0
  5. data/include/grpc/event_engine/event_engine.h +336 -0
  6. data/include/grpc/event_engine/port.h +39 -0
  7. data/include/grpc/event_engine/slice_allocator.h +81 -0
  8. data/include/grpc/grpc.h +2 -2
  9. data/include/grpc/grpc_security_constants.h +14 -0
  10. data/include/grpc/impl/codegen/grpc_types.h +11 -0
  11. data/include/grpc/impl/codegen/port_platform.h +5 -0
  12. data/include/grpc/module.modulemap +14 -14
  13. data/src/core/ext/filters/client_channel/backup_poller.cc +3 -3
  14. data/src/core/ext/filters/client_channel/channel_connectivity.cc +177 -202
  15. data/src/core/ext/filters/client_channel/client_channel.cc +628 -3101
  16. data/src/core/ext/filters/client_channel/client_channel.h +489 -55
  17. data/src/core/ext/filters/client_channel/client_channel_channelz.h +1 -1
  18. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +4 -1
  19. data/src/core/ext/filters/client_channel/config_selector.h +1 -1
  20. data/src/core/ext/filters/client_channel/connector.h +1 -1
  21. data/src/core/ext/filters/client_channel/dynamic_filters.cc +9 -10
  22. data/src/core/ext/filters/client_channel/dynamic_filters.h +3 -3
  23. data/src/core/ext/filters/client_channel/health/health_check_client.cc +26 -27
  24. data/src/core/ext/filters/client_channel/health/health_check_client.h +27 -26
  25. data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +24 -21
  26. data/src/core/ext/filters/client_channel/lb_policy.cc +1 -1
  27. data/src/core/ext/filters/client_channel/lb_policy.h +4 -4
  28. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +6 -6
  29. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +46 -43
  30. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +1 -1
  31. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +2 -1
  32. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +5 -5
  33. data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +14 -12
  34. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +4 -4
  35. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +1 -1
  36. data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +15 -15
  37. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +36 -30
  38. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +23 -23
  39. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +31 -46
  40. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +84 -61
  41. data/src/core/ext/filters/client_channel/lb_policy_factory.h +1 -1
  42. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +4 -4
  43. data/src/core/ext/filters/client_channel/lb_policy_registry.h +1 -1
  44. data/src/core/ext/filters/client_channel/resolver.h +2 -2
  45. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +23 -15
  46. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +1 -1
  47. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc +3 -3
  48. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +2 -2
  49. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +14 -14
  50. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +33 -24
  51. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +1 -1
  52. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc +1 -1
  53. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +1 -1
  54. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +17 -9
  55. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +20 -28
  56. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +7 -5
  57. data/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc +13 -11
  58. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +1 -1
  59. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +43 -28
  60. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +32 -239
  61. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +20 -49
  62. data/src/core/ext/filters/client_channel/retry_filter.cc +2188 -0
  63. data/src/core/ext/filters/client_channel/retry_filter.h +30 -0
  64. data/src/core/ext/filters/client_channel/retry_service_config.cc +287 -0
  65. data/src/core/ext/filters/client_channel/retry_service_config.h +90 -0
  66. data/src/core/ext/filters/client_channel/server_address.cc +1 -1
  67. data/src/core/ext/filters/client_channel/service_config.cc +15 -14
  68. data/src/core/ext/filters/client_channel/service_config.h +7 -6
  69. data/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc +5 -4
  70. data/src/core/ext/filters/client_channel/service_config_parser.cc +6 -6
  71. data/src/core/ext/filters/client_channel/service_config_parser.h +7 -4
  72. data/src/core/ext/filters/client_channel/subchannel.cc +17 -16
  73. data/src/core/ext/filters/client_channel/subchannel.h +7 -6
  74. data/src/core/ext/filters/client_idle/client_idle_filter.cc +16 -15
  75. data/src/core/ext/filters/deadline/deadline_filter.cc +10 -10
  76. data/src/core/ext/filters/fault_injection/fault_injection_filter.cc +19 -18
  77. data/src/core/ext/filters/fault_injection/service_config_parser.cc +5 -5
  78. data/src/core/ext/filters/fault_injection/service_config_parser.h +1 -1
  79. data/src/core/ext/filters/http/client/http_client_filter.cc +28 -21
  80. data/src/core/ext/filters/http/client_authority_filter.cc +3 -3
  81. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +23 -22
  82. data/src/core/ext/filters/http/message_compress/message_decompress_filter.cc +21 -21
  83. data/src/core/ext/filters/http/server/http_server_filter.cc +27 -23
  84. data/src/core/ext/filters/max_age/max_age_filter.cc +12 -10
  85. data/src/core/ext/filters/message_size/message_size_filter.cc +14 -11
  86. data/src/core/ext/filters/message_size/message_size_filter.h +1 -1
  87. data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc +4 -3
  88. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +7 -7
  89. data/src/core/ext/transport/chttp2/client/chttp2_connector.h +7 -7
  90. data/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +2 -2
  91. data/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc +1 -1
  92. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +3 -3
  93. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +44 -45
  94. data/src/core/ext/transport/chttp2/server/chttp2_server.h +2 -2
  95. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc +3 -4
  96. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc +2 -2
  97. data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc +3 -4
  98. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +129 -116
  99. data/src/core/ext/transport/chttp2/transport/context_list.cc +4 -5
  100. data/src/core/ext/transport/chttp2/transport/context_list.h +4 -4
  101. data/src/core/ext/transport/chttp2/transport/flow_control.cc +3 -3
  102. data/src/core/ext/transport/chttp2/transport/flow_control.h +8 -8
  103. data/src/core/ext/transport/chttp2/transport/frame_data.cc +8 -8
  104. data/src/core/ext/transport/chttp2/transport/frame_data.h +10 -10
  105. data/src/core/ext/transport/chttp2/transport/frame_goaway.cc +7 -8
  106. data/src/core/ext/transport/chttp2/transport/frame_goaway.h +6 -6
  107. data/src/core/ext/transport/chttp2/transport/frame_ping.cc +7 -8
  108. data/src/core/ext/transport/chttp2/transport/frame_ping.h +7 -6
  109. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +7 -7
  110. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +6 -6
  111. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +6 -5
  112. data/src/core/ext/transport/chttp2/transport/frame_settings.h +6 -6
  113. data/src/core/ext/transport/chttp2/transport/frame_window_update.cc +4 -6
  114. data/src/core/ext/transport/chttp2/transport/frame_window_update.h +4 -6
  115. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +237 -208
  116. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +10 -10
  117. data/src/core/ext/transport/chttp2/transport/hpack_table.cc +4 -3
  118. data/src/core/ext/transport/chttp2/transport/hpack_table.h +4 -4
  119. data/src/core/ext/transport/chttp2/transport/incoming_metadata.cc +2 -2
  120. data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +2 -2
  121. data/src/core/ext/transport/chttp2/transport/internal.h +31 -27
  122. data/src/core/ext/transport/chttp2/transport/parsing.cc +63 -56
  123. data/src/core/ext/transport/chttp2/transport/writing.cc +7 -3
  124. data/src/core/ext/transport/inproc/inproc_transport.cc +30 -29
  125. data/src/core/ext/xds/certificate_provider_factory.h +1 -1
  126. data/src/core/ext/xds/certificate_provider_store.h +3 -3
  127. data/src/core/ext/xds/file_watcher_certificate_provider_factory.cc +3 -3
  128. data/src/core/ext/xds/file_watcher_certificate_provider_factory.h +2 -2
  129. data/src/core/ext/xds/xds_api.cc +101 -93
  130. data/src/core/ext/xds/xds_api.h +6 -6
  131. data/src/core/ext/xds/xds_bootstrap.cc +97 -159
  132. data/src/core/ext/xds/xds_bootstrap.h +19 -24
  133. data/src/core/ext/xds/xds_certificate_provider.cc +4 -4
  134. data/src/core/ext/xds/xds_certificate_provider.h +4 -4
  135. data/src/core/ext/xds/xds_channel_args.h +5 -2
  136. data/src/core/ext/xds/xds_client.cc +310 -178
  137. data/src/core/ext/xds/xds_client.h +41 -27
  138. data/src/core/ext/xds/xds_client_stats.h +3 -2
  139. data/src/core/ext/xds/xds_server_config_fetcher.cc +34 -20
  140. data/src/core/lib/{iomgr → address_utils}/parse_address.cc +17 -17
  141. data/src/core/lib/{iomgr → address_utils}/parse_address.h +7 -7
  142. data/src/core/lib/{iomgr → address_utils}/sockaddr_utils.cc +3 -20
  143. data/src/core/lib/{iomgr → address_utils}/sockaddr_utils.h +6 -11
  144. data/src/core/lib/channel/channel_stack.cc +10 -9
  145. data/src/core/lib/channel/channel_stack.h +10 -9
  146. data/src/core/lib/channel/channel_stack_builder.cc +2 -2
  147. data/src/core/lib/channel/channel_stack_builder.h +1 -1
  148. data/src/core/lib/channel/channelz.cc +21 -13
  149. data/src/core/lib/channel/connected_channel.cc +4 -4
  150. data/src/core/lib/channel/handshaker.cc +7 -6
  151. data/src/core/lib/channel/handshaker.h +5 -5
  152. data/src/core/lib/event_engine/slice_allocator.cc +59 -0
  153. data/src/core/lib/event_engine/sockaddr.cc +38 -0
  154. data/src/core/lib/gprpp/ref_counted.h +28 -14
  155. data/src/core/lib/gprpp/status_helper.cc +407 -0
  156. data/src/core/lib/gprpp/status_helper.h +180 -0
  157. data/src/core/lib/http/httpcli.cc +11 -11
  158. data/src/core/lib/http/httpcli_security_connector.cc +11 -7
  159. data/src/core/lib/http/parser.cc +16 -16
  160. data/src/core/lib/http/parser.h +4 -4
  161. data/src/core/lib/iomgr/buffer_list.cc +7 -9
  162. data/src/core/lib/iomgr/buffer_list.h +4 -5
  163. data/src/core/lib/iomgr/call_combiner.cc +15 -12
  164. data/src/core/lib/iomgr/call_combiner.h +12 -14
  165. data/src/core/lib/iomgr/cfstream_handle.cc +3 -3
  166. data/src/core/lib/iomgr/cfstream_handle.h +1 -1
  167. data/src/core/lib/iomgr/closure.h +7 -6
  168. data/src/core/lib/iomgr/combiner.cc +14 -12
  169. data/src/core/lib/iomgr/combiner.h +2 -2
  170. data/src/core/lib/iomgr/endpoint.cc +1 -1
  171. data/src/core/lib/iomgr/endpoint.h +2 -2
  172. data/src/core/lib/iomgr/endpoint_cfstream.cc +11 -13
  173. data/src/core/lib/iomgr/endpoint_pair_windows.cc +1 -1
  174. data/src/core/lib/iomgr/error.cc +167 -61
  175. data/src/core/lib/iomgr/error.h +217 -106
  176. data/src/core/lib/iomgr/error_cfstream.cc +3 -2
  177. data/src/core/lib/iomgr/error_cfstream.h +2 -2
  178. data/src/core/lib/iomgr/error_internal.h +5 -1
  179. data/src/core/lib/iomgr/ev_apple.cc +5 -5
  180. data/src/core/lib/iomgr/ev_epoll1_linux.cc +19 -19
  181. data/src/core/lib/iomgr/ev_epollex_linux.cc +48 -45
  182. data/src/core/lib/iomgr/ev_poll_posix.cc +26 -23
  183. data/src/core/lib/iomgr/ev_posix.cc +9 -8
  184. data/src/core/lib/iomgr/ev_posix.h +9 -9
  185. data/src/core/lib/iomgr/exec_ctx.cc +4 -4
  186. data/src/core/lib/iomgr/exec_ctx.h +1 -1
  187. data/src/core/lib/iomgr/executor.cc +8 -8
  188. data/src/core/lib/iomgr/executor.h +2 -2
  189. data/src/core/lib/iomgr/iomgr.cc +1 -1
  190. data/src/core/lib/iomgr/iomgr.h +1 -1
  191. data/src/core/lib/iomgr/iomgr_custom.cc +1 -1
  192. data/src/core/lib/iomgr/iomgr_internal.cc +2 -2
  193. data/src/core/lib/iomgr/iomgr_internal.h +3 -3
  194. data/src/core/lib/iomgr/iomgr_posix.cc +1 -1
  195. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +2 -2
  196. data/src/core/lib/iomgr/iomgr_windows.cc +1 -1
  197. data/src/core/lib/iomgr/load_file.cc +4 -4
  198. data/src/core/lib/iomgr/load_file.h +2 -2
  199. data/src/core/lib/iomgr/lockfree_event.cc +5 -5
  200. data/src/core/lib/iomgr/lockfree_event.h +1 -1
  201. data/src/core/lib/iomgr/pollset.cc +5 -5
  202. data/src/core/lib/iomgr/pollset.h +9 -9
  203. data/src/core/lib/iomgr/pollset_custom.cc +5 -5
  204. data/src/core/lib/iomgr/pollset_windows.cc +5 -5
  205. data/src/core/lib/iomgr/port.h +1 -1
  206. data/src/core/lib/iomgr/python_util.h +1 -1
  207. data/src/core/lib/iomgr/resolve_address.cc +3 -3
  208. data/src/core/lib/iomgr/resolve_address.h +6 -6
  209. data/src/core/lib/iomgr/resolve_address_custom.cc +10 -9
  210. data/src/core/lib/iomgr/resolve_address_custom.h +3 -3
  211. data/src/core/lib/iomgr/resolve_address_posix.cc +3 -3
  212. data/src/core/lib/iomgr/resolve_address_windows.cc +4 -4
  213. data/src/core/lib/iomgr/resource_quota.cc +11 -10
  214. data/src/core/lib/iomgr/socket_utils_common_posix.cc +22 -20
  215. data/src/core/lib/iomgr/socket_utils_posix.h +20 -20
  216. data/src/core/lib/iomgr/tcp_client_cfstream.cc +4 -4
  217. data/src/core/lib/iomgr/tcp_client_custom.cc +5 -6
  218. data/src/core/lib/iomgr/tcp_client_posix.cc +15 -17
  219. data/src/core/lib/iomgr/tcp_client_posix.h +3 -4
  220. data/src/core/lib/iomgr/tcp_client_windows.cc +5 -5
  221. data/src/core/lib/iomgr/tcp_custom.cc +14 -16
  222. data/src/core/lib/iomgr/tcp_custom.h +13 -12
  223. data/src/core/lib/iomgr/tcp_posix.cc +36 -34
  224. data/src/core/lib/iomgr/tcp_server.cc +6 -6
  225. data/src/core/lib/iomgr/tcp_server.h +12 -11
  226. data/src/core/lib/iomgr/tcp_server_custom.cc +23 -21
  227. data/src/core/lib/iomgr/tcp_server_posix.cc +22 -21
  228. data/src/core/lib/iomgr/tcp_server_utils_posix.h +13 -12
  229. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +19 -17
  230. data/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc +9 -9
  231. data/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.cc +4 -4
  232. data/src/core/lib/iomgr/tcp_server_windows.cc +26 -25
  233. data/src/core/lib/iomgr/tcp_uv.cc +25 -23
  234. data/src/core/lib/iomgr/tcp_windows.cc +13 -13
  235. data/src/core/lib/iomgr/tcp_windows.h +2 -2
  236. data/src/core/lib/iomgr/timer_custom.cc +2 -1
  237. data/src/core/lib/iomgr/timer_custom.h +1 -1
  238. data/src/core/lib/iomgr/timer_generic.cc +6 -6
  239. data/src/core/lib/iomgr/udp_server.cc +21 -20
  240. data/src/core/lib/iomgr/unix_sockets_posix.cc +3 -3
  241. data/src/core/lib/iomgr/unix_sockets_posix.h +2 -2
  242. data/src/core/lib/iomgr/unix_sockets_posix_noop.cc +10 -7
  243. data/src/core/lib/iomgr/wakeup_fd_eventfd.cc +3 -3
  244. data/src/core/lib/iomgr/wakeup_fd_pipe.cc +4 -4
  245. data/src/core/lib/iomgr/wakeup_fd_posix.cc +3 -3
  246. data/src/core/lib/iomgr/wakeup_fd_posix.h +8 -6
  247. data/src/core/lib/iomgr/work_serializer.h +17 -1
  248. data/src/core/lib/json/json.h +1 -1
  249. data/src/core/lib/json/json_reader.cc +4 -4
  250. data/src/core/lib/matchers/matchers.cc +39 -39
  251. data/src/core/lib/matchers/matchers.h +28 -28
  252. data/src/core/lib/security/credentials/composite/composite_credentials.cc +4 -4
  253. data/src/core/lib/security/credentials/composite/composite_credentials.h +2 -2
  254. data/src/core/lib/security/credentials/credentials.h +2 -2
  255. data/src/core/lib/security/credentials/external/aws_external_account_credentials.cc +17 -13
  256. data/src/core/lib/security/credentials/external/aws_external_account_credentials.h +13 -11
  257. data/src/core/lib/security/credentials/external/aws_request_signer.cc +2 -1
  258. data/src/core/lib/security/credentials/external/aws_request_signer.h +1 -1
  259. data/src/core/lib/security/credentials/external/external_account_credentials.cc +15 -12
  260. data/src/core/lib/security/credentials/external/external_account_credentials.h +9 -8
  261. data/src/core/lib/security/credentials/external/file_external_account_credentials.cc +5 -4
  262. data/src/core/lib/security/credentials/external/file_external_account_credentials.h +4 -3
  263. data/src/core/lib/security/credentials/external/url_external_account_credentials.cc +8 -8
  264. data/src/core/lib/security/credentials/external/url_external_account_credentials.h +9 -7
  265. data/src/core/lib/security/credentials/fake/fake_credentials.cc +2 -2
  266. data/src/core/lib/security/credentials/fake/fake_credentials.h +2 -2
  267. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +9 -9
  268. data/src/core/lib/security/credentials/iam/iam_credentials.cc +2 -2
  269. data/src/core/lib/security/credentials/iam/iam_credentials.h +2 -2
  270. data/src/core/lib/security/credentials/jwt/json_token.cc +2 -2
  271. data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +3 -3
  272. data/src/core/lib/security/credentials/jwt/jwt_credentials.h +2 -2
  273. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +7 -5
  274. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +21 -19
  275. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +5 -5
  276. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +5 -5
  277. data/src/core/lib/security/credentials/plugin/plugin_credentials.h +2 -2
  278. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc +8 -7
  279. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h +9 -9
  280. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc +19 -13
  281. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +4 -0
  282. data/src/core/lib/security/credentials/xds/xds_credentials.cc +3 -3
  283. data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +13 -3
  284. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +13 -3
  285. data/src/core/lib/security/security_connector/insecure/insecure_security_connector.cc +2 -2
  286. data/src/core/lib/security/security_connector/insecure/insecure_security_connector.h +12 -2
  287. data/src/core/lib/security/security_connector/load_system_roots_linux.cc +1 -1
  288. data/src/core/lib/security/security_connector/local/local_security_connector.cc +14 -4
  289. data/src/core/lib/security/security_connector/security_connector.h +9 -4
  290. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +16 -6
  291. data/src/core/lib/security/security_connector/ssl_utils.cc +22 -4
  292. data/src/core/lib/security/security_connector/ssl_utils.h +4 -4
  293. data/src/core/lib/security/security_connector/tls/tls_security_connector.cc +56 -60
  294. data/src/core/lib/security/security_connector/tls/tls_security_connector.h +66 -48
  295. data/src/core/lib/security/transport/client_auth_filter.cc +18 -10
  296. data/src/core/lib/security/transport/secure_endpoint.cc +4 -4
  297. data/src/core/lib/security/transport/security_handshaker.cc +33 -32
  298. data/src/core/lib/security/transport/server_auth_filter.cc +19 -13
  299. data/src/core/lib/security/transport/tsi_error.cc +2 -1
  300. data/src/core/lib/security/transport/tsi_error.h +2 -1
  301. data/src/core/lib/security/util/json_util.cc +2 -2
  302. data/src/core/lib/security/util/json_util.h +1 -1
  303. data/src/core/lib/surface/call.cc +46 -45
  304. data/src/core/lib/surface/call.h +2 -2
  305. data/src/core/lib/surface/channel.cc +6 -6
  306. data/src/core/lib/surface/channel.h +3 -2
  307. data/src/core/lib/surface/channel_ping.cc +1 -1
  308. data/src/core/lib/surface/completion_queue.cc +46 -47
  309. data/src/core/lib/surface/completion_queue.h +2 -1
  310. data/src/core/lib/surface/lame_client.cc +11 -11
  311. data/src/core/lib/surface/lame_client.h +1 -1
  312. data/src/core/lib/surface/server.cc +28 -22
  313. data/src/core/lib/surface/server.h +16 -15
  314. data/src/core/lib/surface/validate_metadata.cc +7 -7
  315. data/src/core/lib/surface/validate_metadata.h +3 -2
  316. data/src/core/lib/surface/version.cc +4 -2
  317. data/src/core/lib/transport/byte_stream.cc +5 -5
  318. data/src/core/lib/transport/byte_stream.h +8 -8
  319. data/src/core/lib/transport/connectivity_state.cc +1 -1
  320. data/src/core/lib/transport/error_utils.cc +19 -8
  321. data/src/core/lib/transport/error_utils.h +11 -5
  322. data/src/core/lib/transport/metadata_batch.cc +37 -37
  323. data/src/core/lib/transport/metadata_batch.h +19 -18
  324. data/src/core/lib/transport/transport.cc +4 -3
  325. data/src/core/lib/transport/transport.h +4 -4
  326. data/src/core/lib/transport/transport_op_string.cc +5 -5
  327. data/src/core/tsi/alts/crypt/gsec.h +4 -0
  328. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +5 -4
  329. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +7 -6
  330. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h +2 -1
  331. data/src/core/tsi/ssl_transport_security.cc +32 -14
  332. data/src/core/tsi/ssl_transport_security.h +3 -4
  333. data/src/ruby/bin/math_services_pb.rb +1 -1
  334. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +1 -1
  335. data/src/ruby/lib/grpc/version.rb +1 -1
  336. data/src/ruby/pb/grpc/health/v1/health_services_pb.rb +1 -1
  337. data/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb +6 -6
  338. data/third_party/abseil-cpp/absl/algorithm/container.h +3 -3
  339. data/third_party/abseil-cpp/absl/base/attributes.h +24 -4
  340. data/third_party/abseil-cpp/absl/base/call_once.h +2 -9
  341. data/third_party/abseil-cpp/absl/base/config.h +37 -9
  342. data/third_party/abseil-cpp/absl/base/dynamic_annotations.h +24 -10
  343. data/third_party/abseil-cpp/absl/base/internal/direct_mmap.h +4 -1
  344. data/third_party/abseil-cpp/absl/base/internal/endian.h +61 -0
  345. data/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h +2 -3
  346. data/third_party/abseil-cpp/absl/base/internal/raw_logging.cc +34 -32
  347. data/third_party/abseil-cpp/absl/base/internal/raw_logging.h +16 -6
  348. data/third_party/abseil-cpp/absl/base/internal/spinlock.cc +11 -2
  349. data/third_party/abseil-cpp/absl/base/internal/spinlock.h +14 -5
  350. data/third_party/abseil-cpp/absl/base/internal/spinlock_akaros.inc +2 -2
  351. data/third_party/abseil-cpp/absl/base/internal/spinlock_linux.inc +3 -3
  352. data/third_party/abseil-cpp/absl/base/internal/spinlock_posix.inc +2 -2
  353. data/third_party/abseil-cpp/absl/base/internal/spinlock_wait.h +11 -11
  354. data/third_party/abseil-cpp/absl/base/internal/spinlock_win32.inc +5 -5
  355. data/third_party/abseil-cpp/absl/base/internal/sysinfo.cc +1 -1
  356. data/third_party/abseil-cpp/absl/base/internal/thread_identity.cc +5 -2
  357. data/third_party/abseil-cpp/absl/base/internal/thread_identity.h +43 -42
  358. data/third_party/abseil-cpp/absl/base/internal/throw_delegate.cc +111 -7
  359. data/third_party/abseil-cpp/absl/base/internal/unaligned_access.h +0 -76
  360. data/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc +1 -3
  361. data/third_party/abseil-cpp/absl/base/log_severity.h +4 -4
  362. data/third_party/abseil-cpp/absl/base/macros.h +11 -0
  363. data/third_party/abseil-cpp/absl/base/optimization.h +10 -7
  364. data/third_party/abseil-cpp/absl/base/options.h +1 -1
  365. data/third_party/abseil-cpp/absl/base/port.h +0 -1
  366. data/third_party/abseil-cpp/absl/base/thread_annotations.h +1 -1
  367. data/third_party/abseil-cpp/absl/container/fixed_array.h +2 -2
  368. data/third_party/abseil-cpp/absl/container/inlined_vector.h +5 -3
  369. data/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h +1 -1
  370. data/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc +5 -1
  371. data/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h +2 -1
  372. data/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc +2 -1
  373. data/third_party/abseil-cpp/absl/container/internal/inlined_vector.h +141 -66
  374. data/third_party/abseil-cpp/absl/container/internal/layout.h +4 -4
  375. data/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc +14 -1
  376. data/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h +136 -136
  377. data/third_party/abseil-cpp/absl/debugging/internal/demangle.cc +16 -12
  378. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc +5 -2
  379. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h +3 -12
  380. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc +6 -1
  381. data/third_party/abseil-cpp/absl/debugging/internal/symbolize.h +3 -5
  382. data/third_party/abseil-cpp/absl/debugging/symbolize_darwin.inc +2 -2
  383. data/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc +2 -2
  384. data/third_party/abseil-cpp/absl/hash/internal/city.cc +15 -12
  385. data/third_party/abseil-cpp/absl/hash/internal/city.h +1 -19
  386. data/third_party/abseil-cpp/absl/hash/internal/hash.cc +25 -10
  387. data/third_party/abseil-cpp/absl/hash/internal/hash.h +86 -37
  388. data/third_party/abseil-cpp/absl/hash/internal/wyhash.cc +111 -0
  389. data/third_party/abseil-cpp/absl/hash/internal/wyhash.h +48 -0
  390. data/third_party/abseil-cpp/absl/meta/type_traits.h +16 -2
  391. data/third_party/abseil-cpp/absl/numeric/bits.h +177 -0
  392. data/third_party/abseil-cpp/absl/numeric/int128.cc +3 -3
  393. data/third_party/abseil-cpp/absl/numeric/internal/bits.h +358 -0
  394. data/third_party/abseil-cpp/absl/numeric/internal/representation.h +55 -0
  395. data/third_party/abseil-cpp/absl/status/internal/status_internal.h +18 -0
  396. data/third_party/abseil-cpp/absl/status/internal/statusor_internal.h +4 -7
  397. data/third_party/abseil-cpp/absl/status/status.cc +29 -22
  398. data/third_party/abseil-cpp/absl/status/status.h +81 -20
  399. data/third_party/abseil-cpp/absl/status/statusor.h +3 -3
  400. data/third_party/abseil-cpp/absl/strings/charconv.cc +5 -5
  401. data/third_party/abseil-cpp/absl/strings/cord.cc +326 -371
  402. data/third_party/abseil-cpp/absl/strings/cord.h +182 -64
  403. data/third_party/abseil-cpp/absl/strings/escaping.cc +4 -4
  404. data/third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc +6 -6
  405. data/third_party/abseil-cpp/absl/strings/internal/cord_internal.cc +83 -0
  406. data/third_party/abseil-cpp/absl/strings/internal/cord_internal.h +387 -17
  407. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_flat.h +146 -0
  408. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.cc +897 -0
  409. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.h +589 -0
  410. data/third_party/abseil-cpp/absl/strings/internal/cord_rep_ring_reader.h +114 -0
  411. data/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc +14 -0
  412. data/third_party/abseil-cpp/absl/strings/internal/str_format/arg.h +14 -0
  413. data/third_party/abseil-cpp/absl/strings/internal/str_format/bind.cc +15 -1
  414. data/third_party/abseil-cpp/absl/strings/internal/str_format/bind.h +19 -4
  415. data/third_party/abseil-cpp/absl/strings/internal/str_format/checker.h +14 -0
  416. data/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc +36 -18
  417. data/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.h +14 -0
  418. data/third_party/abseil-cpp/absl/strings/internal/str_format/parser.cc +14 -0
  419. data/third_party/abseil-cpp/absl/strings/internal/str_format/parser.h +14 -0
  420. data/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h +15 -40
  421. data/third_party/abseil-cpp/absl/strings/internal/string_constant.h +64 -0
  422. data/third_party/abseil-cpp/absl/strings/match.cc +6 -3
  423. data/third_party/abseil-cpp/absl/strings/match.h +16 -6
  424. data/third_party/abseil-cpp/absl/strings/numbers.cc +132 -4
  425. data/third_party/abseil-cpp/absl/strings/numbers.h +10 -10
  426. data/third_party/abseil-cpp/absl/strings/str_join.h +1 -1
  427. data/third_party/abseil-cpp/absl/strings/str_split.h +38 -4
  428. data/third_party/abseil-cpp/absl/synchronization/internal/futex.h +154 -0
  429. data/third_party/abseil-cpp/absl/synchronization/internal/kernel_timeout.h +2 -1
  430. data/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc +2 -2
  431. data/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.h +4 -4
  432. data/third_party/abseil-cpp/absl/synchronization/internal/waiter.cc +1 -65
  433. data/third_party/abseil-cpp/absl/synchronization/internal/waiter.h +2 -6
  434. data/third_party/abseil-cpp/absl/synchronization/mutex.cc +71 -59
  435. data/third_party/abseil-cpp/absl/synchronization/mutex.h +79 -62
  436. data/third_party/abseil-cpp/absl/time/clock.cc +146 -130
  437. data/third_party/abseil-cpp/absl/time/clock.h +2 -2
  438. data/third_party/abseil-cpp/absl/time/duration.cc +3 -2
  439. data/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h +7 -11
  440. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc +7 -1
  441. data/third_party/abseil-cpp/absl/time/internal/cctz/src/tzfile.h +4 -4
  442. data/third_party/abseil-cpp/absl/time/time.cc +4 -3
  443. data/third_party/abseil-cpp/absl/time/time.h +26 -24
  444. data/third_party/abseil-cpp/absl/types/internal/variant.h +1 -1
  445. data/third_party/abseil-cpp/absl/types/variant.h +9 -4
  446. data/third_party/boringssl-with-bazel/err_data.c +477 -461
  447. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_bool.c +1 -1
  448. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_object.c +1 -1
  449. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_type.c +18 -8
  450. data/third_party/boringssl-with-bazel/src/crypto/asn1/asn1_lib.c +1 -2
  451. data/third_party/boringssl-with-bazel/src/crypto/asn1/asn1_locl.h +5 -0
  452. data/third_party/boringssl-with-bazel/src/crypto/asn1/tasn_enc.c +1 -1
  453. data/third_party/boringssl-with-bazel/src/crypto/asn1/tasn_fre.c +1 -1
  454. data/third_party/boringssl-with-bazel/src/crypto/cipher_extra/e_tls.c +1 -88
  455. data/third_party/boringssl-with-bazel/src/crypto/cipher_extra/internal.h +14 -3
  456. data/third_party/boringssl-with-bazel/src/crypto/cipher_extra/tls_cbc.c +119 -273
  457. data/third_party/boringssl-with-bazel/src/crypto/err/err.c +87 -80
  458. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bcm.c +1 -0
  459. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/internal.h +1 -1
  460. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/cipher/cipher.c +11 -3
  461. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/cipher/e_aes.c +25 -2
  462. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/digest/digests.c +10 -2
  463. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/digest/md32_common.h +4 -43
  464. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec.c +4 -0
  465. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec_key.c +0 -1
  466. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/internal.h +0 -4
  467. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ecdsa/ecdsa.c +104 -93
  468. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ecdsa/internal.h +39 -0
  469. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/md4/md4.c +43 -46
  470. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/md5/md5.c +43 -46
  471. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/cbc.c +33 -22
  472. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/cfb.c +9 -8
  473. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/ctr.c +9 -8
  474. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/gcm.c +17 -13
  475. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/internal.h +1 -22
  476. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/modes/ofb.c +2 -1
  477. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/urandom.c +26 -7
  478. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/self_check/fips.c +79 -0
  479. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/self_check/self_check.c +14 -9
  480. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/sha/sha1.c +45 -48
  481. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/sha/sha256.c +38 -43
  482. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/sha/sha512.c +37 -45
  483. data/third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c +103 -42
  484. data/third_party/boringssl-with-bazel/src/crypto/hpke/internal.h +58 -37
  485. data/third_party/boringssl-with-bazel/src/crypto/internal.h +65 -0
  486. data/third_party/boringssl-with-bazel/src/crypto/mem.c +14 -0
  487. data/third_party/boringssl-with-bazel/src/crypto/obj/obj.c +3 -3
  488. data/third_party/boringssl-with-bazel/src/crypto/pkcs7/pkcs7_x509.c +1 -1
  489. data/third_party/boringssl-with-bazel/src/crypto/pkcs8/pkcs8_x509.c +95 -48
  490. data/third_party/boringssl-with-bazel/src/crypto/rand_extra/rand_extra.c +1 -1
  491. data/third_party/boringssl-with-bazel/src/crypto/thread_pthread.c +0 -28
  492. data/third_party/boringssl-with-bazel/src/crypto/x509/internal.h +19 -0
  493. data/third_party/boringssl-with-bazel/src/crypto/x509/t_req.c +2 -0
  494. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_att.c +19 -25
  495. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_cmp.c +3 -2
  496. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_req.c +39 -89
  497. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_set.c +9 -16
  498. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_vfy.c +1 -1
  499. data/third_party/boringssl-with-bazel/src/crypto/x509/x_algor.c +21 -17
  500. data/third_party/boringssl-with-bazel/src/crypto/x509/x_attrib.c +7 -25
  501. data/third_party/boringssl-with-bazel/src/crypto/x509/x_crl.c +5 -0
  502. data/third_party/boringssl-with-bazel/src/crypto/x509/x_pubkey.c +25 -22
  503. data/third_party/boringssl-with-bazel/src/crypto/x509/x_val.c +2 -0
  504. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_cpols.c +2 -4
  505. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_purp.c +1 -1
  506. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_skey.c +1 -0
  507. data/third_party/boringssl-with-bazel/src/include/openssl/aead.h +0 -3
  508. data/third_party/boringssl-with-bazel/src/include/openssl/asn1.h +120 -41
  509. data/third_party/boringssl-with-bazel/src/include/openssl/base.h +9 -0
  510. data/third_party/boringssl-with-bazel/src/include/openssl/cipher.h +0 -8
  511. data/third_party/boringssl-with-bazel/src/include/openssl/crypto.h +24 -4
  512. data/third_party/boringssl-with-bazel/src/include/openssl/ec.h +5 -2
  513. data/third_party/boringssl-with-bazel/src/include/openssl/ecdsa.h +19 -0
  514. data/third_party/boringssl-with-bazel/src/include/openssl/err.h +3 -2
  515. data/third_party/boringssl-with-bazel/src/include/openssl/evp.h +1 -38
  516. data/third_party/boringssl-with-bazel/src/{crypto/x509/x509_r2x.c → include/openssl/evp_errors.h} +41 -58
  517. data/third_party/boringssl-with-bazel/src/include/openssl/obj.h +24 -5
  518. data/third_party/boringssl-with-bazel/src/include/openssl/pkcs7.h +2 -0
  519. data/third_party/boringssl-with-bazel/src/include/openssl/pkcs8.h +9 -1
  520. data/third_party/boringssl-with-bazel/src/include/openssl/rand.h +2 -2
  521. data/third_party/boringssl-with-bazel/src/include/openssl/ssl.h +185 -17
  522. data/third_party/boringssl-with-bazel/src/include/openssl/tls1.h +1 -0
  523. data/third_party/boringssl-with-bazel/src/include/openssl/x509.h +416 -121
  524. data/third_party/boringssl-with-bazel/src/include/openssl/x509v3.h +2 -0
  525. data/third_party/boringssl-with-bazel/src/ssl/d1_both.cc +5 -0
  526. data/third_party/boringssl-with-bazel/src/ssl/encrypted_client_hello.cc +444 -0
  527. data/third_party/boringssl-with-bazel/src/ssl/handoff.cc +244 -1
  528. data/third_party/boringssl-with-bazel/src/ssl/handshake.cc +43 -12
  529. data/third_party/boringssl-with-bazel/src/ssl/handshake_server.cc +149 -8
  530. data/third_party/boringssl-with-bazel/src/ssl/internal.h +220 -46
  531. data/third_party/boringssl-with-bazel/src/ssl/s3_both.cc +7 -1
  532. data/third_party/boringssl-with-bazel/src/ssl/ssl_cert.cc +4 -6
  533. data/third_party/boringssl-with-bazel/src/ssl/ssl_key_share.cc +23 -26
  534. data/third_party/boringssl-with-bazel/src/ssl/ssl_lib.cc +74 -15
  535. data/third_party/boringssl-with-bazel/src/ssl/t1_lib.cc +98 -64
  536. data/third_party/boringssl-with-bazel/src/ssl/tls13_both.cc +34 -4
  537. data/third_party/boringssl-with-bazel/src/ssl/tls13_server.cc +205 -100
  538. data/third_party/boringssl-with-bazel/src/ssl/tls_method.cc +4 -2
  539. metadata +68 -45
  540. data/src/core/lib/iomgr/poller/eventmanager_libuv.cc +0 -88
  541. data/src/core/lib/iomgr/poller/eventmanager_libuv.h +0 -88
  542. data/third_party/abseil-cpp/absl/base/internal/bits.h +0 -219
  543. data/third_party/abseil-cpp/absl/synchronization/internal/mutex_nonprod.inc +0 -249
  544. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/is_fips.c +0 -29
@@ -0,0 +1,55 @@
1
+ // Copyright 2021 The Abseil Authors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #ifndef ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_
16
+ #define ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_
17
+
18
+ #include <limits>
19
+
20
+ #include "absl/base/config.h"
21
+
22
+ namespace absl {
23
+ ABSL_NAMESPACE_BEGIN
24
+ namespace numeric_internal {
25
+
26
+ // Returns true iff long double is represented as a pair of doubles added
27
+ // together.
28
+ inline constexpr bool IsDoubleDouble() {
29
+ // A double-double value always has exactly twice the precision of a double
30
+ // value--one double carries the high digits and one double carries the low
31
+ // digits. This property is not shared with any other common floating-point
32
+ // representation, so this test won't trigger false positives. For reference,
33
+ // this table gives the number of bits of precision of each common
34
+ // floating-point representation:
35
+ //
36
+ // type precision
37
+ // IEEE single 24 b
38
+ // IEEE double 53
39
+ // x86 long double 64
40
+ // double-double 106
41
+ // IEEE quadruple 113
42
+ //
43
+ // Note in particular that a quadruple-precision float has greater precision
44
+ // than a double-double float despite taking up the same amount of memory; the
45
+ // quad has more of its bits allocated to the mantissa than the double-double
46
+ // has.
47
+ return std::numeric_limits<long double>::digits ==
48
+ 2 * std::numeric_limits<double>::digits;
49
+ }
50
+
51
+ } // namespace numeric_internal
52
+ ABSL_NAMESPACE_END
53
+ } // namespace absl
54
+
55
+ #endif // ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_
@@ -19,6 +19,17 @@
19
19
  #include "absl/container/inlined_vector.h"
20
20
  #include "absl/strings/cord.h"
21
21
 
22
+ #ifndef SWIG
23
+ // Disabled for SWIG as it doesn't parse attributes correctly.
24
+ namespace absl {
25
+ ABSL_NAMESPACE_BEGIN
26
+ // Returned Status objects may not be ignored. Codesearch doesn't handle ifdefs
27
+ // as part of a class definitions (b/6995610), so we use a forward declaration.
28
+ class ABSL_MUST_USE_RESULT Status;
29
+ ABSL_NAMESPACE_END
30
+ } // namespace absl
31
+ #endif // !SWIG
32
+
22
33
  namespace absl {
23
34
  ABSL_NAMESPACE_BEGIN
24
35
 
@@ -36,6 +47,13 @@ using Payloads = absl::InlinedVector<Payload, 1>;
36
47
 
37
48
  // Reference-counted representation of Status data.
38
49
  struct StatusRep {
50
+ StatusRep(absl::StatusCode code, std::string message,
51
+ std::unique_ptr<status_internal::Payloads> payloads)
52
+ : ref(int32_t{1}),
53
+ code(code),
54
+ message(std::move(message)),
55
+ payloads(std::move(payloads)) {}
56
+
39
57
  std::atomic<int32_t> ref;
40
58
  absl::StatusCode code;
41
59
  std::string message;
@@ -17,6 +17,7 @@
17
17
  #include <type_traits>
18
18
  #include <utility>
19
19
 
20
+ #include "absl/base/attributes.h"
20
21
  #include "absl/meta/type_traits.h"
21
22
  #include "absl/status/status.h"
22
23
  #include "absl/utility/utility.h"
@@ -135,18 +136,14 @@ class Helper {
135
136
  public:
136
137
  // Move type-agnostic error handling to the .cc.
137
138
  static void HandleInvalidStatusCtorArg(Status*);
138
- static void Crash(const absl::Status& status);
139
+ ABSL_ATTRIBUTE_NORETURN static void Crash(const absl::Status& status);
139
140
  };
140
141
 
141
142
  // Construct an instance of T in `p` through placement new, passing Args... to
142
143
  // the constructor.
143
144
  // This abstraction is here mostly for the gcc performance fix.
144
145
  template <typename T, typename... Args>
145
- void PlacementNew(void* p, Args&&... args) {
146
- #if defined(__GNUC__) && !defined(__clang__)
147
- // Teach gcc that 'p' cannot be null, fixing code size issues.
148
- if (p == nullptr) __builtin_unreachable();
149
- #endif
146
+ ABSL_ATTRIBUTE_NONNULL(1) void PlacementNew(void* p, Args&&... args) {
150
147
  new (p) T(std::forward<Args>(args)...);
151
148
  }
152
149
 
@@ -215,7 +212,7 @@ class StatusOrData {
215
212
  template <typename U,
216
213
  absl::enable_if_t<std::is_constructible<absl::Status, U&&>::value,
217
214
  int> = 0>
218
- explicit StatusOrData(U&& v) : status_(v) {
215
+ explicit StatusOrData(U&& v) : status_(std::forward<U>(v)) {
219
216
  EnsureNotOk();
220
217
  }
221
218
 
@@ -207,13 +207,12 @@ void Status::UnrefNonInlined(uintptr_t rep) {
207
207
  }
208
208
  }
209
209
 
210
- uintptr_t Status::NewRep(absl::StatusCode code, absl::string_view msg,
211
- std::unique_ptr<status_internal::Payloads> payloads) {
212
- status_internal::StatusRep* rep = new status_internal::StatusRep;
213
- rep->ref.store(1, std::memory_order_relaxed);
214
- rep->code = code;
215
- rep->message.assign(msg.data(), msg.size());
216
- rep->payloads = std::move(payloads);
210
+ uintptr_t Status::NewRep(
211
+ absl::StatusCode code, absl::string_view msg,
212
+ std::unique_ptr<status_internal::Payloads> payloads) {
213
+ status_internal::StatusRep* rep = new status_internal::StatusRep(
214
+ code, std::string(msg.data(), msg.size()),
215
+ std::move(payloads));
217
216
  return PointerToRep(rep);
218
217
  }
219
218
 
@@ -239,8 +238,9 @@ absl::StatusCode Status::code() const {
239
238
  void Status::PrepareToModify() {
240
239
  ABSL_RAW_CHECK(!ok(), "PrepareToModify shouldn't be called on OK status.");
241
240
  if (IsInlined(rep_)) {
242
- rep_ = NewRep(static_cast<absl::StatusCode>(raw_code()),
243
- absl::string_view(), nullptr);
241
+ rep_ =
242
+ NewRep(static_cast<absl::StatusCode>(raw_code()), absl::string_view(),
243
+ nullptr);
244
244
  return;
245
245
  }
246
246
 
@@ -251,7 +251,8 @@ void Status::PrepareToModify() {
251
251
  if (rep->payloads) {
252
252
  payloads = absl::make_unique<status_internal::Payloads>(*rep->payloads);
253
253
  }
254
- rep_ = NewRep(rep->code, message(), std::move(payloads));
254
+ rep_ = NewRep(rep->code, message(),
255
+ std::move(payloads));
255
256
  UnrefNonInlined(rep_i);
256
257
  }
257
258
  }
@@ -290,20 +291,26 @@ bool Status::EqualsSlow(const absl::Status& a, const absl::Status& b) {
290
291
  return true;
291
292
  }
292
293
 
293
- std::string Status::ToStringSlow() const {
294
+ std::string Status::ToStringSlow(StatusToStringMode mode) const {
294
295
  std::string text;
295
296
  absl::StrAppend(&text, absl::StatusCodeToString(code()), ": ", message());
296
- status_internal::StatusPayloadPrinter printer =
297
- status_internal::GetStatusPayloadPrinter();
298
- this->ForEachPayload([&](absl::string_view type_url,
299
- const absl::Cord& payload) {
300
- absl::optional<std::string> result;
301
- if (printer) result = printer(type_url, payload);
302
- absl::StrAppend(
303
- &text, " [", type_url, "='",
304
- result.has_value() ? *result : absl::CHexEscape(std::string(payload)),
305
- "']");
306
- });
297
+
298
+ const bool with_payload = (mode & StatusToStringMode::kWithPayload) ==
299
+ StatusToStringMode::kWithPayload;
300
+
301
+ if (with_payload) {
302
+ status_internal::StatusPayloadPrinter printer =
303
+ status_internal::GetStatusPayloadPrinter();
304
+ this->ForEachPayload([&](absl::string_view type_url,
305
+ const absl::Cord& payload) {
306
+ absl::optional<std::string> result;
307
+ if (printer) result = printer(type_url, payload);
308
+ absl::StrAppend(
309
+ &text, " [", type_url, "='",
310
+ result.has_value() ? *result : absl::CHexEscape(std::string(payload)),
311
+ "']");
312
+ });
313
+ }
307
314
 
308
315
  return text;
309
316
  }
@@ -57,6 +57,7 @@
57
57
  #include "absl/container/inlined_vector.h"
58
58
  #include "absl/status/internal/status_internal.h"
59
59
  #include "absl/strings/cord.h"
60
+ #include "absl/strings/string_view.h"
60
61
  #include "absl/types/optional.h"
61
62
 
62
63
  namespace absl {
@@ -98,7 +99,7 @@ enum class StatusCode : int {
98
99
 
99
100
  // StatusCode::kCancelled
100
101
  //
101
- // kCanelled (gRPC code "CANCELLED") indicates the operation was cancelled,
102
+ // kCancelled (gRPC code "CANCELLED") indicates the operation was cancelled,
102
103
  // typically by the caller.
103
104
  kCancelled = 1,
104
105
 
@@ -198,9 +199,9 @@ enum class StatusCode : int {
198
199
  // `kAborted`, and `kUnavailable`.
199
200
  kAborted = 10,
200
201
 
201
- // StatusCode::kOutofRange
202
+ // StatusCode::kOutOfRange
202
203
  //
203
- // kOutofRange (gRPC code "OUT_OF_RANGE") indicates the operation was
204
+ // kOutOfRange (gRPC code "OUT_OF_RANGE") indicates the operation was
204
205
  // attempted past the valid range, such as seeking or reading past an
205
206
  // end-of-file.
206
207
  //
@@ -279,6 +280,57 @@ std::string StatusCodeToString(StatusCode code);
279
280
  // Streams StatusCodeToString(code) to `os`.
280
281
  std::ostream& operator<<(std::ostream& os, StatusCode code);
281
282
 
283
+ // absl::StatusToStringMode
284
+ //
285
+ // An `absl::StatusToStringMode` is an enumerated type indicating how
286
+ // `absl::Status::ToString()` should construct the output string for an non-ok
287
+ // status.
288
+ enum class StatusToStringMode : int {
289
+ // ToString will not contain any extra data (such as payloads). It will only
290
+ // contain the error code and message, if any.
291
+ kWithNoExtraData = 0,
292
+ // ToString will contain the payloads.
293
+ kWithPayload = 1 << 0,
294
+ // ToString will include all the extra data this Status has.
295
+ kWithEverything = ~kWithNoExtraData,
296
+ };
297
+
298
+ // absl::StatusToStringMode is specified as a bitmask type, which means the
299
+ // following operations must be provided:
300
+ inline constexpr StatusToStringMode operator&(StatusToStringMode lhs,
301
+ StatusToStringMode rhs) {
302
+ return static_cast<StatusToStringMode>(static_cast<int>(lhs) &
303
+ static_cast<int>(rhs));
304
+ }
305
+ inline constexpr StatusToStringMode operator|(StatusToStringMode lhs,
306
+ StatusToStringMode rhs) {
307
+ return static_cast<StatusToStringMode>(static_cast<int>(lhs) |
308
+ static_cast<int>(rhs));
309
+ }
310
+ inline constexpr StatusToStringMode operator^(StatusToStringMode lhs,
311
+ StatusToStringMode rhs) {
312
+ return static_cast<StatusToStringMode>(static_cast<int>(lhs) ^
313
+ static_cast<int>(rhs));
314
+ }
315
+ inline constexpr StatusToStringMode operator~(StatusToStringMode arg) {
316
+ return static_cast<StatusToStringMode>(~static_cast<int>(arg));
317
+ }
318
+ inline StatusToStringMode& operator&=(StatusToStringMode& lhs,
319
+ StatusToStringMode rhs) {
320
+ lhs = lhs & rhs;
321
+ return lhs;
322
+ }
323
+ inline StatusToStringMode& operator|=(StatusToStringMode& lhs,
324
+ StatusToStringMode rhs) {
325
+ lhs = lhs | rhs;
326
+ return lhs;
327
+ }
328
+ inline StatusToStringMode& operator^=(StatusToStringMode& lhs,
329
+ StatusToStringMode rhs) {
330
+ lhs = lhs ^ rhs;
331
+ return lhs;
332
+ }
333
+
282
334
  // absl::Status
283
335
  //
284
336
  // The `absl::Status` class is generally used to gracefully handle errors
@@ -360,7 +412,12 @@ std::ostream& operator<<(std::ostream& os, StatusCode code);
360
412
  // return result;
361
413
  // }
362
414
  //
363
- class ABSL_MUST_USE_RESULT Status final {
415
+ // For documentation see https://abseil.io/docs/cpp/guides/status.
416
+ //
417
+ // Returned Status objects may not be ignored. status_internal.h has a forward
418
+ // declaration of the form
419
+ // class ABSL_MUST_USE_RESULT Status;
420
+ class Status final {
364
421
  public:
365
422
  // Constructors
366
423
 
@@ -370,10 +427,10 @@ class ABSL_MUST_USE_RESULT Status final {
370
427
  Status();
371
428
 
372
429
  // Creates a status in the canonical error space with the specified
373
- // `absl::StatusCode` and error message. If `code == absl::StatusCode::kOk`,
430
+ // `absl::StatusCode` and error message. If `code == absl::StatusCode::kOk`, // NOLINT
374
431
  // `msg` is ignored and an object identical to an OK status is constructed.
375
432
  //
376
- // The `msg` string must be in UTF-8. The implementation may complain (e.g.,
433
+ // The `msg` string must be in UTF-8. The implementation may complain (e.g., // NOLINT
377
434
  // by printing a warning) if it is not.
378
435
  Status(absl::StatusCode code, absl::string_view msg);
379
436
 
@@ -442,15 +499,17 @@ class ABSL_MUST_USE_RESULT Status final {
442
499
 
443
500
  // Status::ToString()
444
501
  //
445
- // Returns a combination of the error code name, the message and any
446
- // associated payload messages. This string is designed simply to be human
447
- // readable and its exact format should not be load bearing. Do not depend on
448
- // the exact format of the result of `ToString()` which is subject to change.
502
+ // Returns a string based on the `mode`. By default, it returns combination of
503
+ // the error code name, the message and any associated payload messages. This
504
+ // string is designed simply to be human readable and its exact format should
505
+ // not be load bearing. Do not depend on the exact format of the result of
506
+ // `ToString()` which is subject to change.
449
507
  //
450
508
  // The printed code name and the message are generally substrings of the
451
509
  // result, and the payloads to be printed use the status payload printer
452
510
  // mechanism (which is internal).
453
- std::string ToString() const;
511
+ std::string ToString(
512
+ StatusToStringMode mode = StatusToStringMode::kWithPayload) const;
454
513
 
455
514
  // Status::IgnoreError()
456
515
  //
@@ -550,8 +609,9 @@ class ABSL_MUST_USE_RESULT Status final {
550
609
  status_internal::Payloads* GetPayloads();
551
610
 
552
611
  // Takes ownership of payload.
553
- static uintptr_t NewRep(absl::StatusCode code, absl::string_view msg,
554
- std::unique_ptr<status_internal::Payloads> payload);
612
+ static uintptr_t NewRep(
613
+ absl::StatusCode code, absl::string_view msg,
614
+ std::unique_ptr<status_internal::Payloads> payload);
555
615
  static bool EqualsSlow(const absl::Status& a, const absl::Status& b);
556
616
 
557
617
  // MSVC 14.0 limitation requires the const.
@@ -580,8 +640,7 @@ class ABSL_MUST_USE_RESULT Status final {
580
640
  static uintptr_t PointerToRep(status_internal::StatusRep* r);
581
641
  static status_internal::StatusRep* RepToPointer(uintptr_t r);
582
642
 
583
- // Returns string for non-ok Status.
584
- std::string ToStringSlow() const;
643
+ std::string ToStringSlow(StatusToStringMode mode) const;
585
644
 
586
645
  // Status supports two different representations.
587
646
  // - When the low bit is off it is an inlined representation.
@@ -704,9 +763,11 @@ inline Status::Status(Status&& x) noexcept : rep_(x.rep_) {
704
763
 
705
764
  inline Status& Status::operator=(Status&& x) {
706
765
  uintptr_t old_rep = rep_;
707
- rep_ = x.rep_;
708
- x.rep_ = MovedFromRep();
709
- Unref(old_rep);
766
+ if (x.rep_ != old_rep) {
767
+ rep_ = x.rep_;
768
+ x.rep_ = MovedFromRep();
769
+ Unref(old_rep);
770
+ }
710
771
  return *this;
711
772
  }
712
773
 
@@ -743,8 +804,8 @@ inline bool operator!=(const Status& lhs, const Status& rhs) {
743
804
  return !(lhs == rhs);
744
805
  }
745
806
 
746
- inline std::string Status::ToString() const {
747
- return ok() ? "OK" : ToStringSlow();
807
+ inline std::string Status::ToString(StatusToStringMode mode) const {
808
+ return ok() ? "OK" : ToStringSlow(mode);
748
809
  }
749
810
 
750
811
  inline void Status::IgnoreError() const {
@@ -129,13 +129,13 @@ class ABSL_MUST_USE_RESULT StatusOr;
129
129
  // Example:
130
130
  //
131
131
  // absl::StatusOr<int> i = GetCount();
132
- // if (foo.ok()) {
132
+ // if (i.ok()) {
133
133
  // updated_total += *i
134
134
  // }
135
135
  //
136
136
  // NOTE: using `absl::StatusOr<T>::value()` when no valid value is present will
137
137
  // throw an exception if exceptions are enabled or terminate the process when
138
- // execeptions are not enabled.
138
+ // exceptions are not enabled.
139
139
  //
140
140
  // Example:
141
141
  //
@@ -542,7 +542,7 @@ class StatusOr : private internal_statusor::StatusOrData<T>,
542
542
 
543
543
  // StatusOr<T>::value_or()
544
544
  //
545
- // Returns the current value of `this->ok() == true`. Otherwise constructs a
545
+ // Returns the current value if `this->ok() == true`. Otherwise constructs a
546
546
  // value using the provided `default_value`.
547
547
  //
548
548
  // Unlike `value`, this function returns by value, copying the current value
@@ -20,7 +20,7 @@
20
20
  #include <cstring>
21
21
 
22
22
  #include "absl/base/casts.h"
23
- #include "absl/base/internal/bits.h"
23
+ #include "absl/numeric/bits.h"
24
24
  #include "absl/numeric/int128.h"
25
25
  #include "absl/strings/internal/charconv_bigint.h"
26
26
  #include "absl/strings/internal/charconv_parse.h"
@@ -242,11 +242,11 @@ struct CalculatedFloat {
242
242
 
243
243
  // Returns the bit width of the given uint128. (Equivalently, returns 128
244
244
  // minus the number of leading zero bits.)
245
- int BitWidth(uint128 value) {
245
+ unsigned BitWidth(uint128 value) {
246
246
  if (Uint128High64(value) == 0) {
247
- return 64 - base_internal::CountLeadingZeros64(Uint128Low64(value));
247
+ return static_cast<unsigned>(bit_width(Uint128Low64(value)));
248
248
  }
249
- return 128 - base_internal::CountLeadingZeros64(Uint128High64(value));
249
+ return 128 - countl_zero(Uint128High64(value));
250
250
  }
251
251
 
252
252
  // Calculates how far to the right a mantissa needs to be shifted to create a
@@ -519,7 +519,7 @@ CalculatedFloat CalculateFromParsedHexadecimal(
519
519
  const strings_internal::ParsedFloat& parsed_hex) {
520
520
  uint64_t mantissa = parsed_hex.mantissa;
521
521
  int exponent = parsed_hex.exponent;
522
- int mantissa_width = 64 - base_internal::CountLeadingZeros64(mantissa);
522
+ auto mantissa_width = static_cast<unsigned>(bit_width(mantissa));
523
523
  const int shift = NormalizedShiftSize<FloatType>(mantissa_width, exponent);
524
524
  bool result_exact;
525
525
  exponent += shift;
@@ -36,6 +36,8 @@
36
36
  #include "absl/container/inlined_vector.h"
37
37
  #include "absl/strings/escaping.h"
38
38
  #include "absl/strings/internal/cord_internal.h"
39
+ #include "absl/strings/internal/cord_rep_flat.h"
40
+ #include "absl/strings/internal/cord_rep_ring.h"
39
41
  #include "absl/strings/internal/resize_uninitialized.h"
40
42
  #include "absl/strings/str_cat.h"
41
43
  #include "absl/strings/str_format.h"
@@ -48,98 +50,20 @@ ABSL_NAMESPACE_BEGIN
48
50
  using ::absl::cord_internal::CordRep;
49
51
  using ::absl::cord_internal::CordRepConcat;
50
52
  using ::absl::cord_internal::CordRepExternal;
53
+ using ::absl::cord_internal::CordRepFlat;
54
+ using ::absl::cord_internal::CordRepRing;
51
55
  using ::absl::cord_internal::CordRepSubstring;
56
+ using ::absl::cord_internal::kMinFlatLength;
57
+ using ::absl::cord_internal::kMaxFlatLength;
52
58
 
53
- // Various representations that we allow
54
- enum CordRepKind {
55
- CONCAT = 0,
56
- EXTERNAL = 1,
57
- SUBSTRING = 2,
59
+ using ::absl::cord_internal::CONCAT;
60
+ using ::absl::cord_internal::EXTERNAL;
61
+ using ::absl::cord_internal::FLAT;
62
+ using ::absl::cord_internal::RING;
63
+ using ::absl::cord_internal::SUBSTRING;
58
64
 
59
- // We have different tags for different sized flat arrays,
60
- // starting with FLAT
61
- FLAT = 3,
62
- };
63
-
64
- namespace cord_internal {
65
-
66
- inline CordRepConcat* CordRep::concat() {
67
- assert(tag == CONCAT);
68
- return static_cast<CordRepConcat*>(this);
69
- }
70
-
71
- inline const CordRepConcat* CordRep::concat() const {
72
- assert(tag == CONCAT);
73
- return static_cast<const CordRepConcat*>(this);
74
- }
75
-
76
- inline CordRepSubstring* CordRep::substring() {
77
- assert(tag == SUBSTRING);
78
- return static_cast<CordRepSubstring*>(this);
79
- }
80
-
81
- inline const CordRepSubstring* CordRep::substring() const {
82
- assert(tag == SUBSTRING);
83
- return static_cast<const CordRepSubstring*>(this);
84
- }
85
-
86
- inline CordRepExternal* CordRep::external() {
87
- assert(tag == EXTERNAL);
88
- return static_cast<CordRepExternal*>(this);
89
- }
90
-
91
- inline const CordRepExternal* CordRep::external() const {
92
- assert(tag == EXTERNAL);
93
- return static_cast<const CordRepExternal*>(this);
94
- }
95
-
96
- } // namespace cord_internal
97
-
98
- static const size_t kFlatOverhead = offsetof(CordRep, data);
99
-
100
- // Largest and smallest flat node lengths we are willing to allocate
101
- // Flat allocation size is stored in tag, which currently can encode sizes up
102
- // to 4K, encoded as multiple of either 8 or 32 bytes.
103
- // If we allow for larger sizes, we need to change this to 8/64, 16/128, etc.
104
- static constexpr size_t kMaxFlatSize = 4096;
105
- static constexpr size_t kMaxFlatLength = kMaxFlatSize - kFlatOverhead;
106
- static constexpr size_t kMinFlatLength = 32 - kFlatOverhead;
107
-
108
- // Prefer copying blocks of at most this size, otherwise reference count.
109
- static const size_t kMaxBytesToCopy = 511;
110
-
111
- // Helper functions for rounded div, and rounding to exact sizes.
112
- static size_t DivUp(size_t n, size_t m) { return (n + m - 1) / m; }
113
- static size_t RoundUp(size_t n, size_t m) { return DivUp(n, m) * m; }
114
-
115
- // Returns the size to the nearest equal or larger value that can be
116
- // expressed exactly as a tag value.
117
- static size_t RoundUpForTag(size_t size) {
118
- return RoundUp(size, (size <= 1024) ? 8 : 32);
119
- }
120
-
121
- // Converts the allocated size to a tag, rounding down if the size
122
- // does not exactly match a 'tag expressible' size value. The result is
123
- // undefined if the size exceeds the maximum size that can be encoded in
124
- // a tag, i.e., if size is larger than TagToAllocatedSize(<max tag>).
125
- static uint8_t AllocatedSizeToTag(size_t size) {
126
- const size_t tag = (size <= 1024) ? size / 8 : 128 + size / 32 - 1024 / 32;
127
- assert(tag <= std::numeric_limits<uint8_t>::max());
128
- return tag;
129
- }
130
-
131
- // Converts the provided tag to the corresponding allocated size
132
- static constexpr size_t TagToAllocatedSize(uint8_t tag) {
133
- return (tag <= 128) ? (tag * 8) : (1024 + (tag - 128) * 32);
134
- }
135
-
136
- // Converts the provided tag to the corresponding available data length
137
- static constexpr size_t TagToLength(uint8_t tag) {
138
- return TagToAllocatedSize(tag) - kFlatOverhead;
139
- }
140
-
141
- // Enforce that kMaxFlatSize maps to a well-known exact tag value.
142
- static_assert(TagToAllocatedSize(224) == kMaxFlatSize, "Bad tag logic");
65
+ using ::absl::cord_internal::kInlinedVectorSize;
66
+ using ::absl::cord_internal::kMaxBytesToCopy;
143
67
 
144
68
  constexpr uint64_t Fibonacci(unsigned char n, uint64_t a = 0, uint64_t b = 1) {
145
69
  return n == 0 ? a : Fibonacci(n - 1, b, a + b);
@@ -171,16 +95,10 @@ static constexpr uint64_t min_length[] = {
171
95
 
172
96
  static const int kMinLengthSize = ABSL_ARRAYSIZE(min_length);
173
97
 
174
- // The inlined size to use with absl::InlinedVector.
175
- //
176
- // Note: The InlinedVectors in this file (and in cord.h) do not need to use
177
- // the same value for their inlined size. The fact that they do is historical.
178
- // It may be desirable for each to use a different inlined size optimized for
179
- // that InlinedVector's usage.
180
- //
181
- // TODO(jgm): Benchmark to see if there's a more optimal value than 47 for
182
- // the inlined vector size (47 exists for backward compatibility).
183
- static const int kInlinedVectorSize = 47;
98
+ static inline bool cord_ring_enabled() {
99
+ return cord_internal::cord_ring_buffer_enabled.load(
100
+ std::memory_order_relaxed);
101
+ }
184
102
 
185
103
  static inline bool IsRootBalanced(CordRep* node) {
186
104
  if (node->tag != CONCAT) {
@@ -197,7 +115,8 @@ static inline bool IsRootBalanced(CordRep* node) {
197
115
  }
198
116
 
199
117
  static CordRep* Rebalance(CordRep* node);
200
- static void DumpNode(CordRep* rep, bool include_data, std::ostream* os);
118
+ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
119
+ int indent = 0);
201
120
  static bool VerifyNode(CordRep* root, CordRep* start_node,
202
121
  bool full_validation);
203
122
 
@@ -217,96 +136,6 @@ static inline CordRep* VerifyTree(CordRep* node) {
217
136
  return node;
218
137
  }
219
138
 
220
- // --------------------------------------------------------------------
221
- // Memory management
222
-
223
- inline CordRep* Ref(CordRep* rep) {
224
- if (rep != nullptr) {
225
- rep->refcount.Increment();
226
- }
227
- return rep;
228
- }
229
-
230
- // This internal routine is called from the cold path of Unref below. Keeping it
231
- // in a separate routine allows good inlining of Unref into many profitable call
232
- // sites. However, the call to this function can be highly disruptive to the
233
- // register pressure in those callers. To minimize the cost to callers, we use
234
- // a special LLVM calling convention that preserves most registers. This allows
235
- // the call to this routine in cold paths to not disrupt the caller's register
236
- // pressure. This calling convention is not available on all platforms; we
237
- // intentionally allow LLVM to ignore the attribute rather than attempting to
238
- // hardcode the list of supported platforms.
239
- #if defined(__clang__) && !defined(__i386__)
240
- #pragma clang diagnostic push
241
- #pragma clang diagnostic ignored "-Wattributes"
242
- __attribute__((preserve_most))
243
- #pragma clang diagnostic pop
244
- #endif
245
- static void UnrefInternal(CordRep* rep) {
246
- assert(rep != nullptr);
247
-
248
- absl::InlinedVector<CordRep*, kInlinedVectorSize> pending;
249
- while (true) {
250
- if (rep->tag == CONCAT) {
251
- CordRepConcat* rep_concat = rep->concat();
252
- CordRep* right = rep_concat->right;
253
- if (!right->refcount.Decrement()) {
254
- pending.push_back(right);
255
- }
256
- CordRep* left = rep_concat->left;
257
- delete rep_concat;
258
- rep = nullptr;
259
- if (!left->refcount.Decrement()) {
260
- rep = left;
261
- continue;
262
- }
263
- } else if (rep->tag == EXTERNAL) {
264
- CordRepExternal* rep_external = rep->external();
265
- rep_external->releaser_invoker(rep_external);
266
- rep = nullptr;
267
- } else if (rep->tag == SUBSTRING) {
268
- CordRepSubstring* rep_substring = rep->substring();
269
- CordRep* child = rep_substring->child;
270
- delete rep_substring;
271
- rep = nullptr;
272
- if (!child->refcount.Decrement()) {
273
- rep = child;
274
- continue;
275
- }
276
- } else {
277
- // Flat CordReps are allocated and constructed with raw ::operator new
278
- // and placement new, and must be destructed and deallocated
279
- // accordingly.
280
- #if defined(__cpp_sized_deallocation)
281
- size_t size = TagToAllocatedSize(rep->tag);
282
- rep->~CordRep();
283
- ::operator delete(rep, size);
284
- #else
285
- rep->~CordRep();
286
- ::operator delete(rep);
287
- #endif
288
- rep = nullptr;
289
- }
290
-
291
- if (!pending.empty()) {
292
- rep = pending.back();
293
- pending.pop_back();
294
- } else {
295
- break;
296
- }
297
- }
298
- }
299
-
300
- inline void Unref(CordRep* rep) {
301
- // Fast-path for two common, hot cases: a null rep and a shared root.
302
- if (ABSL_PREDICT_TRUE(rep == nullptr ||
303
- rep->refcount.DecrementExpectHighRefcount())) {
304
- return;
305
- }
306
-
307
- UnrefInternal(rep);
308
- }
309
-
310
139
  // Return the depth of a node
311
140
  static int Depth(const CordRep* rep) {
312
141
  if (rep->tag == CONCAT) {
@@ -330,12 +159,14 @@ static void SetConcatChildren(CordRepConcat* concat, CordRep* left,
330
159
  // The returned node has a refcount of 1.
331
160
  static CordRep* RawConcat(CordRep* left, CordRep* right) {
332
161
  // Avoid making degenerate concat nodes (one child is empty)
333
- if (left == nullptr || left->length == 0) {
334
- Unref(left);
162
+ if (left == nullptr) return right;
163
+ if (right == nullptr) return left;
164
+ if (left->length == 0) {
165
+ CordRep::Unref(left);
335
166
  return right;
336
167
  }
337
- if (right == nullptr || right->length == 0) {
338
- Unref(right);
168
+ if (right->length == 0) {
169
+ CordRep::Unref(right);
339
170
  return left;
340
171
  }
341
172
 
@@ -374,20 +205,27 @@ static CordRep* MakeBalancedTree(CordRep** reps, size_t n) {
374
205
  return reps[0];
375
206
  }
376
207
 
377
- // Create a new flat node.
378
- static CordRep* NewFlat(size_t length_hint) {
379
- if (length_hint <= kMinFlatLength) {
380
- length_hint = kMinFlatLength;
381
- } else if (length_hint > kMaxFlatLength) {
382
- length_hint = kMaxFlatLength;
383
- }
208
+ static CordRepFlat* CreateFlat(const char* data, size_t length,
209
+ size_t alloc_hint) {
210
+ CordRepFlat* flat = CordRepFlat::New(length + alloc_hint);
211
+ flat->length = length;
212
+ memcpy(flat->Data(), data, length);
213
+ return flat;
214
+ }
384
215
 
385
- // Round size up so it matches a size we can exactly express in a tag.
386
- const size_t size = RoundUpForTag(length_hint + kFlatOverhead);
387
- void* const raw_rep = ::operator new(size);
388
- CordRep* rep = new (raw_rep) CordRep();
389
- rep->tag = AllocatedSizeToTag(size);
390
- return VerifyTree(rep);
216
+ // Creates a new flat or ringbuffer out of the specified array.
217
+ // The returned node has a refcount of 1.
218
+ static CordRep* RingNewTree(const char* data, size_t length,
219
+ size_t alloc_hint) {
220
+ if (length <= kMaxFlatLength) {
221
+ return CreateFlat(data, length, alloc_hint);
222
+ }
223
+ CordRepFlat* flat = CreateFlat(data, kMaxFlatLength, 0);
224
+ data += kMaxFlatLength;
225
+ length -= kMaxFlatLength;
226
+ size_t extra = (length - 1) / kMaxFlatLength + 1;
227
+ auto* root = CordRepRing::Create(flat, extra);
228
+ return CordRepRing::Append(root, {data, length}, alloc_hint);
391
229
  }
392
230
 
393
231
  // Create a new tree out of the specified array.
@@ -396,13 +234,16 @@ static CordRep* NewTree(const char* data,
396
234
  size_t length,
397
235
  size_t alloc_hint) {
398
236
  if (length == 0) return nullptr;
237
+ if (cord_ring_enabled()) {
238
+ return RingNewTree(data, length, alloc_hint);
239
+ }
399
240
  absl::FixedArray<CordRep*> reps((length - 1) / kMaxFlatLength + 1);
400
241
  size_t n = 0;
401
242
  do {
402
243
  const size_t len = std::min(length, kMaxFlatLength);
403
- CordRep* rep = NewFlat(len + alloc_hint);
244
+ CordRepFlat* rep = CordRepFlat::New(len + alloc_hint);
404
245
  rep->length = len;
405
- memcpy(rep->data, data, len);
246
+ memcpy(rep->Data(), data, len);
406
247
  reps[n++] = VerifyTree(rep);
407
248
  data += len;
408
249
  length -= len;
@@ -425,7 +266,7 @@ void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) {
425
266
  static CordRep* NewSubstring(CordRep* child, size_t offset, size_t length) {
426
267
  // Never create empty substring nodes
427
268
  if (length == 0) {
428
- Unref(child);
269
+ CordRep::Unref(child);
429
270
  return nullptr;
430
271
  } else {
431
272
  CordRepSubstring* rep = new CordRepSubstring();
@@ -447,50 +288,58 @@ inline void Cord::InlineRep::set_data(const char* data, size_t n,
447
288
  bool nullify_tail) {
448
289
  static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15");
449
290
 
450
- cord_internal::SmallMemmove(data_, data, n, nullify_tail);
451
- data_[kMaxInline] = static_cast<char>(n);
291
+ cord_internal::SmallMemmove(data_.as_chars(), data, n, nullify_tail);
292
+ set_inline_size(n);
452
293
  }
453
294
 
454
295
  inline char* Cord::InlineRep::set_data(size_t n) {
455
296
  assert(n <= kMaxInline);
456
- memset(data_, 0, sizeof(data_));
457
- data_[kMaxInline] = static_cast<char>(n);
458
- return data_;
297
+ ResetToEmpty();
298
+ set_inline_size(n);
299
+ return data_.as_chars();
459
300
  }
460
301
 
461
302
  inline CordRep* Cord::InlineRep::force_tree(size_t extra_hint) {
462
- size_t len = data_[kMaxInline];
463
- CordRep* result;
464
- if (len > kMaxInline) {
465
- memcpy(&result, data_, sizeof(result));
466
- } else {
467
- result = NewFlat(len + extra_hint);
468
- result->length = len;
469
- memcpy(result->data, data_, len);
470
- set_tree(result);
303
+ if (data_.is_tree()) {
304
+ return data_.as_tree();
471
305
  }
306
+
307
+ size_t len = inline_size();
308
+ CordRepFlat* result = CordRepFlat::New(len + extra_hint);
309
+ result->length = len;
310
+ static_assert(kMinFlatLength >= sizeof(data_), "");
311
+ memcpy(result->Data(), data_.as_chars(), sizeof(data_));
312
+ set_tree(result);
472
313
  return result;
473
314
  }
474
315
 
475
316
  inline void Cord::InlineRep::reduce_size(size_t n) {
476
- size_t tag = data_[kMaxInline];
317
+ size_t tag = inline_size();
477
318
  assert(tag <= kMaxInline);
478
319
  assert(tag >= n);
479
320
  tag -= n;
480
- memset(data_ + tag, 0, n);
481
- data_[kMaxInline] = static_cast<char>(tag);
321
+ memset(data_.as_chars() + tag, 0, n);
322
+ set_inline_size(static_cast<char>(tag));
482
323
  }
483
324
 
484
325
  inline void Cord::InlineRep::remove_prefix(size_t n) {
485
- cord_internal::SmallMemmove(data_, data_ + n, data_[kMaxInline] - n);
326
+ cord_internal::SmallMemmove(data_.as_chars(), data_.as_chars() + n,
327
+ inline_size() - n);
486
328
  reduce_size(n);
487
329
  }
488
330
 
331
+ // Returns `rep` converted into a CordRepRing.
332
+ // Directly returns `rep` if `rep` is already a CordRepRing.
333
+ static CordRepRing* ForceRing(CordRep* rep, size_t extra) {
334
+ return (rep->tag == RING) ? rep->ring() : CordRepRing::Create(rep, extra);
335
+ }
336
+
489
337
  void Cord::InlineRep::AppendTree(CordRep* tree) {
490
338
  if (tree == nullptr) return;
491
- size_t len = data_[kMaxInline];
492
- if (len == 0) {
339
+ if (data_.is_empty()) {
493
340
  set_tree(tree);
341
+ } else if (cord_ring_enabled()) {
342
+ set_tree(CordRepRing::Append(ForceRing(force_tree(0), 1), tree));
494
343
  } else {
495
344
  set_tree(Concat(force_tree(0), tree));
496
345
  }
@@ -498,9 +347,10 @@ void Cord::InlineRep::AppendTree(CordRep* tree) {
498
347
 
499
348
  void Cord::InlineRep::PrependTree(CordRep* tree) {
500
349
  assert(tree != nullptr);
501
- size_t len = data_[kMaxInline];
502
- if (len == 0) {
350
+ if (data_.is_empty()) {
503
351
  set_tree(tree);
352
+ } else if (cord_ring_enabled()) {
353
+ set_tree(CordRepRing::Prepend(ForceRing(force_tree(0), 1), tree));
504
354
  } else {
505
355
  set_tree(Concat(tree, force_tree(0)));
506
356
  }
@@ -512,6 +362,15 @@ void Cord::InlineRep::PrependTree(CordRep* tree) {
512
362
  // written to region and the actual size increase will be written to size.
513
363
  static inline bool PrepareAppendRegion(CordRep* root, char** region,
514
364
  size_t* size, size_t max_length) {
365
+ if (root->tag == RING && root->refcount.IsOne()) {
366
+ Span<char> span = root->ring()->GetAppendBuffer(max_length);
367
+ if (!span.empty()) {
368
+ *region = span.data();
369
+ *size = span.size();
370
+ return true;
371
+ }
372
+ }
373
+
515
374
  // Search down the right-hand path for a non-full FLAT node.
516
375
  CordRep* dst = root;
517
376
  while (dst->tag == CONCAT && dst->refcount.IsOne()) {
@@ -525,7 +384,7 @@ static inline bool PrepareAppendRegion(CordRep* root, char** region,
525
384
  }
526
385
 
527
386
  const size_t in_use = dst->length;
528
- const size_t capacity = TagToLength(dst->tag);
387
+ const size_t capacity = dst->flat()->Capacity();
529
388
  if (in_use == capacity) {
530
389
  *region = nullptr;
531
390
  *size = 0;
@@ -540,7 +399,7 @@ static inline bool PrepareAppendRegion(CordRep* root, char** region,
540
399
  }
541
400
  dst->length += size_increase;
542
401
 
543
- *region = dst->data + in_use;
402
+ *region = dst->flat()->Data() + in_use;
544
403
  *size = size_increase;
545
404
  return true;
546
405
  }
@@ -554,12 +413,14 @@ void Cord::InlineRep::GetAppendRegion(char** region, size_t* size,
554
413
  }
555
414
 
556
415
  // Try to fit in the inline buffer if possible.
557
- size_t inline_length = data_[kMaxInline];
558
- if (inline_length < kMaxInline && max_length <= kMaxInline - inline_length) {
559
- *region = data_ + inline_length;
560
- *size = max_length;
561
- data_[kMaxInline] = static_cast<char>(inline_length + max_length);
562
- return;
416
+ if (!is_tree()) {
417
+ size_t inline_length = inline_size();
418
+ if (max_length <= kMaxInline - inline_length) {
419
+ *region = data_.as_chars() + inline_length;
420
+ *size = max_length;
421
+ set_inline_size(inline_length + max_length);
422
+ return;
423
+ }
563
424
  }
564
425
 
565
426
  CordRep* root = force_tree(max_length);
@@ -569,12 +430,16 @@ void Cord::InlineRep::GetAppendRegion(char** region, size_t* size,
569
430
  }
570
431
 
571
432
  // Allocate new node.
572
- CordRep* new_node =
573
- NewFlat(std::max(static_cast<size_t>(root->length), max_length));
574
- new_node->length =
575
- std::min(static_cast<size_t>(TagToLength(new_node->tag)), max_length);
576
- *region = new_node->data;
433
+ CordRepFlat* new_node =
434
+ CordRepFlat::New(std::max(static_cast<size_t>(root->length), max_length));
435
+ new_node->length = std::min(new_node->Capacity(), max_length);
436
+ *region = new_node->Data();
577
437
  *size = new_node->length;
438
+
439
+ if (cord_ring_enabled()) {
440
+ replace_tree(CordRepRing::Append(ForceRing(root, 1), new_node));
441
+ return;
442
+ }
578
443
  replace_tree(Concat(root, new_node));
579
444
  }
580
445
 
@@ -582,12 +447,14 @@ void Cord::InlineRep::GetAppendRegion(char** region, size_t* size) {
582
447
  const size_t max_length = std::numeric_limits<size_t>::max();
583
448
 
584
449
  // Try to fit in the inline buffer if possible.
585
- size_t inline_length = data_[kMaxInline];
586
- if (inline_length < kMaxInline) {
587
- *region = data_ + inline_length;
588
- *size = kMaxInline - inline_length;
589
- data_[kMaxInline] = kMaxInline;
590
- return;
450
+ if (!data_.is_tree()) {
451
+ size_t inline_length = inline_size();
452
+ if (inline_length < kMaxInline) {
453
+ *region = data_.as_chars() + inline_length;
454
+ *size = kMaxInline - inline_length;
455
+ set_inline_size(kMaxInline);
456
+ return;
457
+ }
591
458
  }
592
459
 
593
460
  CordRep* root = force_tree(max_length);
@@ -597,10 +464,15 @@ void Cord::InlineRep::GetAppendRegion(char** region, size_t* size) {
597
464
  }
598
465
 
599
466
  // Allocate new node.
600
- CordRep* new_node = NewFlat(root->length);
601
- new_node->length = TagToLength(new_node->tag);
602
- *region = new_node->data;
467
+ CordRepFlat* new_node = CordRepFlat::New(root->length);
468
+ new_node->length = new_node->Capacity();
469
+ *region = new_node->Data();
603
470
  *size = new_node->length;
471
+
472
+ if (cord_ring_enabled()) {
473
+ replace_tree(CordRepRing::Append(ForceRing(root, 1), new_node));
474
+ return;
475
+ }
604
476
  replace_tree(Concat(root, new_node));
605
477
  }
606
478
 
@@ -608,7 +480,7 @@ void Cord::InlineRep::GetAppendRegion(char** region, size_t* size) {
608
480
  // will return true.
609
481
  static bool RepMemoryUsageLeaf(const CordRep* rep, size_t* total_mem_usage) {
610
482
  if (rep->tag >= FLAT) {
611
- *total_mem_usage += TagToAllocatedSize(rep->tag);
483
+ *total_mem_usage += rep->flat()->AllocatedSize();
612
484
  return true;
613
485
  }
614
486
  if (rep->tag == EXTERNAL) {
@@ -621,26 +493,24 @@ static bool RepMemoryUsageLeaf(const CordRep* rep, size_t* total_mem_usage) {
621
493
  void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) {
622
494
  ClearSlow();
623
495
 
624
- memcpy(data_, src.data_, sizeof(data_));
496
+ data_ = src.data_;
625
497
  if (is_tree()) {
626
- Ref(tree());
498
+ data_.set_profiled(false);
499
+ CordRep::Ref(tree());
500
+ clear_cordz_info();
627
501
  }
628
502
  }
629
503
 
630
504
  void Cord::InlineRep::ClearSlow() {
631
505
  if (is_tree()) {
632
- Unref(tree());
506
+ CordRep::Unref(tree());
633
507
  }
634
- memset(data_, 0, sizeof(data_));
508
+ ResetToEmpty();
635
509
  }
636
510
 
637
511
  // --------------------------------------------------------------------
638
512
  // Constructors and destructors
639
513
 
640
- Cord::Cord(const Cord& src) : contents_(src.contents_) {
641
- Ref(contents_.tree()); // Does nothing if contents_ has embedded data
642
- }
643
-
644
514
  Cord::Cord(absl::string_view src) {
645
515
  const size_t n = src.size();
646
516
  if (n <= InlineRep::kMaxInline) {
@@ -684,14 +554,18 @@ template Cord::Cord(std::string&& src);
684
554
  // The destruction code is separate so that the compiler can determine
685
555
  // that it does not need to call the destructor on a moved-from Cord.
686
556
  void Cord::DestroyCordSlow() {
687
- Unref(VerifyTree(contents_.tree()));
557
+ if (CordRep* tree = contents_.tree()) {
558
+ CordRep::Unref(VerifyTree(tree));
559
+ }
688
560
  }
689
561
 
690
562
  // --------------------------------------------------------------------
691
563
  // Mutators
692
564
 
693
565
  void Cord::Clear() {
694
- Unref(contents_.clear());
566
+ if (CordRep* tree = contents_.clear()) {
567
+ CordRep::Unref(tree);
568
+ }
695
569
  }
696
570
 
697
571
  Cord& Cord::operator=(absl::string_view src) {
@@ -702,19 +576,20 @@ Cord& Cord::operator=(absl::string_view src) {
702
576
  if (length <= InlineRep::kMaxInline) {
703
577
  // Embed into this->contents_
704
578
  contents_.set_data(data, length, true);
705
- Unref(tree);
579
+ if (tree) CordRep::Unref(tree);
706
580
  return *this;
707
581
  }
708
582
  if (tree != nullptr && tree->tag >= FLAT &&
709
- TagToLength(tree->tag) >= length && tree->refcount.IsOne()) {
583
+ tree->flat()->Capacity() >= length &&
584
+ tree->refcount.IsOne()) {
710
585
  // Copy in place if the existing FLAT node is reusable.
711
- memmove(tree->data, data, length);
586
+ memmove(tree->flat()->Data(), data, length);
712
587
  tree->length = length;
713
588
  VerifyTree(tree);
714
589
  return *this;
715
590
  }
716
591
  contents_.set_tree(NewTree(data, length, 0));
717
- Unref(tree);
592
+ if (tree) CordRep::Unref(tree);
718
593
  return *this;
719
594
  }
720
595
 
@@ -734,24 +609,25 @@ template Cord& Cord::operator=(std::string&& src);
734
609
  // we keep it here to make diffs easier.
735
610
  void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) {
736
611
  if (src_size == 0) return; // memcpy(_, nullptr, 0) is undefined.
737
- // Try to fit in the inline buffer if possible.
738
- size_t inline_length = data_[kMaxInline];
739
- if (inline_length < kMaxInline && src_size <= kMaxInline - inline_length) {
740
- // Append new data to embedded array
741
- data_[kMaxInline] = static_cast<char>(inline_length + src_size);
742
- memcpy(data_ + inline_length, src_data, src_size);
743
- return;
744
- }
745
-
746
- CordRep* root = tree();
747
612
 
748
613
  size_t appended = 0;
749
- if (root) {
614
+ CordRep* root = nullptr;
615
+ if (is_tree()) {
616
+ root = data_.as_tree();
750
617
  char* region;
751
618
  if (PrepareAppendRegion(root, &region, &appended, src_size)) {
752
619
  memcpy(region, src_data, appended);
753
620
  }
754
621
  } else {
622
+ // Try to fit in the inline buffer if possible.
623
+ size_t inline_length = inline_size();
624
+ if (src_size <= kMaxInline - inline_length) {
625
+ // Append new data to embedded array
626
+ memcpy(data_.as_chars() + inline_length, src_data, src_size);
627
+ set_inline_size(inline_length + src_size);
628
+ return;
629
+ }
630
+
755
631
  // It is possible that src_data == data_, but when we transition from an
756
632
  // InlineRep to a tree we need to assign data_ = root via set_tree. To
757
633
  // avoid corrupting the source data before we copy it, delay calling
@@ -760,10 +636,11 @@ void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) {
760
636
  // either double the inlined size, or the added size + 10%.
761
637
  const size_t size1 = inline_length * 2 + src_size;
762
638
  const size_t size2 = inline_length + src_size / 10;
763
- root = NewFlat(std::max<size_t>(size1, size2));
764
- appended = std::min(src_size, TagToLength(root->tag) - inline_length);
765
- memcpy(root->data, data_, inline_length);
766
- memcpy(root->data + inline_length, src_data, appended);
639
+ root = CordRepFlat::New(std::max<size_t>(size1, size2));
640
+ appended = std::min(
641
+ src_size, root->flat()->Capacity() - inline_length);
642
+ memcpy(root->flat()->Data(), data_.as_chars(), inline_length);
643
+ memcpy(root->flat()->Data() + inline_length, src_data, appended);
767
644
  root->length = inline_length + appended;
768
645
  set_tree(root);
769
646
  }
@@ -774,6 +651,13 @@ void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) {
774
651
  return;
775
652
  }
776
653
 
654
+ if (cord_ring_enabled()) {
655
+ absl::string_view data(src_data, src_size);
656
+ root = ForceRing(root, (data.size() - 1) / kMaxFlatLength + 1);
657
+ replace_tree(CordRepRing::Append(root->ring(), data));
658
+ return;
659
+ }
660
+
777
661
  // Use new block(s) for any remaining bytes that were not handled above.
778
662
  // Alloc extra memory only if the right child of the root of the new tree is
779
663
  // going to be a FLAT node, which will permit further inplace appends.
@@ -790,7 +674,7 @@ void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) {
790
674
  }
791
675
 
792
676
  inline CordRep* Cord::TakeRep() const& {
793
- return Ref(contents_.tree());
677
+ return CordRep::Ref(contents_.tree());
794
678
  }
795
679
 
796
680
  inline CordRep* Cord::TakeRep() && {
@@ -819,7 +703,7 @@ inline void Cord::AppendImpl(C&& src) {
819
703
  }
820
704
  if (src_tree->tag >= FLAT) {
821
705
  // src tree just has one flat node.
822
- contents_.AppendArray(src_tree->data, src_size);
706
+ contents_.AppendArray(src_tree->flat()->Data(), src_size);
823
707
  return;
824
708
  }
825
709
  if (&src == this) {
@@ -834,6 +718,7 @@ inline void Cord::AppendImpl(C&& src) {
834
718
  return;
835
719
  }
836
720
 
721
+ // Guaranteed to be a tree (kMaxBytesToCopy > kInlinedSize)
837
722
  contents_.AppendTree(std::forward<C>(src).TakeRep());
838
723
  }
839
724
 
@@ -855,7 +740,7 @@ template void Cord::Append(std::string&& src);
855
740
  void Cord::Prepend(const Cord& src) {
856
741
  CordRep* src_tree = src.contents_.tree();
857
742
  if (src_tree != nullptr) {
858
- Ref(src_tree);
743
+ CordRep::Ref(src_tree);
859
744
  contents_.PrependTree(src_tree);
860
745
  return;
861
746
  }
@@ -867,18 +752,19 @@ void Cord::Prepend(const Cord& src) {
867
752
 
868
753
  void Cord::Prepend(absl::string_view src) {
869
754
  if (src.empty()) return; // memcpy(_, nullptr, 0) is undefined.
870
- size_t cur_size = contents_.size();
871
- if (!contents_.is_tree() && cur_size + src.size() <= InlineRep::kMaxInline) {
872
- // Use embedded storage.
873
- char data[InlineRep::kMaxInline + 1] = {0};
874
- data[InlineRep::kMaxInline] = cur_size + src.size(); // set size
875
- memcpy(data, src.data(), src.size());
876
- memcpy(data + src.size(), contents_.data(), cur_size);
877
- memcpy(reinterpret_cast<void*>(&contents_), data,
878
- InlineRep::kMaxInline + 1);
879
- } else {
880
- contents_.PrependTree(NewTree(src.data(), src.size(), 0));
755
+ if (!contents_.is_tree()) {
756
+ size_t cur_size = contents_.inline_size();
757
+ if (cur_size + src.size() <= InlineRep::kMaxInline) {
758
+ // Use embedded storage.
759
+ char data[InlineRep::kMaxInline + 1] = {0};
760
+ memcpy(data, src.data(), src.size());
761
+ memcpy(data + src.size(), contents_.data(), cur_size);
762
+ memcpy(contents_.data_.as_chars(), data, InlineRep::kMaxInline + 1);
763
+ contents_.set_inline_size(cur_size + src.size());
764
+ return;
765
+ }
881
766
  }
767
+ contents_.PrependTree(NewTree(src.data(), src.size(), 0));
882
768
  }
883
769
 
884
770
  template <typename T, Cord::EnableIfString<T>>
@@ -894,7 +780,7 @@ template void Cord::Prepend(std::string&& src);
894
780
 
895
781
  static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
896
782
  if (n >= node->length) return nullptr;
897
- if (n == 0) return Ref(node);
783
+ if (n == 0) return CordRep::Ref(node);
898
784
  absl::InlinedVector<CordRep*, kInlinedVectorSize> rhs_stack;
899
785
 
900
786
  while (node->tag == CONCAT) {
@@ -912,7 +798,7 @@ static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
912
798
  assert(n <= node->length);
913
799
 
914
800
  if (n == 0) {
915
- Ref(node);
801
+ CordRep::Ref(node);
916
802
  } else {
917
803
  size_t start = n;
918
804
  size_t len = node->length - n;
@@ -921,10 +807,10 @@ static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
921
807
  start += node->substring()->start;
922
808
  node = node->substring()->child;
923
809
  }
924
- node = NewSubstring(Ref(node), start, len);
810
+ node = NewSubstring(CordRep::Ref(node), start, len);
925
811
  }
926
812
  while (!rhs_stack.empty()) {
927
- node = Concat(node, Ref(rhs_stack.back()));
813
+ node = Concat(node, CordRep::Ref(rhs_stack.back()));
928
814
  rhs_stack.pop_back();
929
815
  }
930
816
  return node;
@@ -935,7 +821,7 @@ static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
935
821
  // edited in place iff that node and all its ancestors have a refcount of 1.
936
822
  static CordRep* RemoveSuffixFrom(CordRep* node, size_t n) {
937
823
  if (n >= node->length) return nullptr;
938
- if (n == 0) return Ref(node);
824
+ if (n == 0) return CordRep::Ref(node);
939
825
  absl::InlinedVector<CordRep*, kInlinedVectorSize> lhs_stack;
940
826
  bool inplace_ok = node->refcount.IsOne();
941
827
 
@@ -955,11 +841,11 @@ static CordRep* RemoveSuffixFrom(CordRep* node, size_t n) {
955
841
  assert(n <= node->length);
956
842
 
957
843
  if (n == 0) {
958
- Ref(node);
844
+ CordRep::Ref(node);
959
845
  } else if (inplace_ok && node->tag != EXTERNAL) {
960
846
  // Consider making a new buffer if the current node capacity is much
961
847
  // larger than the new length.
962
- Ref(node);
848
+ CordRep::Ref(node);
963
849
  node->length -= n;
964
850
  } else {
965
851
  size_t start = 0;
@@ -968,10 +854,10 @@ static CordRep* RemoveSuffixFrom(CordRep* node, size_t n) {
968
854
  start = node->substring()->start;
969
855
  node = node->substring()->child;
970
856
  }
971
- node = NewSubstring(Ref(node), start, len);
857
+ node = NewSubstring(CordRep::Ref(node), start, len);
972
858
  }
973
859
  while (!lhs_stack.empty()) {
974
- node = Concat(Ref(lhs_stack.back()), node);
860
+ node = Concat(CordRep::Ref(lhs_stack.back()), node);
975
861
  lhs_stack.pop_back();
976
862
  }
977
863
  return node;
@@ -984,9 +870,11 @@ void Cord::RemovePrefix(size_t n) {
984
870
  CordRep* tree = contents_.tree();
985
871
  if (tree == nullptr) {
986
872
  contents_.remove_prefix(n);
873
+ } else if (tree->tag == RING) {
874
+ contents_.replace_tree(CordRepRing::RemovePrefix(tree->ring(), n));
987
875
  } else {
988
876
  CordRep* newrep = RemovePrefixFrom(tree, n);
989
- Unref(tree);
877
+ CordRep::Unref(tree);
990
878
  contents_.replace_tree(VerifyTree(newrep));
991
879
  }
992
880
  }
@@ -998,9 +886,11 @@ void Cord::RemoveSuffix(size_t n) {
998
886
  CordRep* tree = contents_.tree();
999
887
  if (tree == nullptr) {
1000
888
  contents_.reduce_size(n);
889
+ } else if (tree->tag == RING) {
890
+ contents_.replace_tree(CordRepRing::RemoveSuffix(tree->ring(), n));
1001
891
  } else {
1002
892
  CordRep* newrep = RemoveSuffixFrom(tree, n);
1003
- Unref(tree);
893
+ CordRep::Unref(tree);
1004
894
  contents_.replace_tree(VerifyTree(newrep));
1005
895
  }
1006
896
  }
@@ -1033,13 +923,13 @@ static CordRep* NewSubRange(CordRep* node, size_t pos, size_t n) {
1033
923
  results.pop_back();
1034
924
  results.push_back(Concat(left, right));
1035
925
  } else if (pos == 0 && n == node->length) {
1036
- results.push_back(Ref(node));
926
+ results.push_back(CordRep::Ref(node));
1037
927
  } else if (node->tag != CONCAT) {
1038
928
  if (node->tag == SUBSTRING) {
1039
929
  pos += node->substring()->start;
1040
930
  node = node->substring()->child;
1041
931
  }
1042
- results.push_back(NewSubstring(Ref(node), pos, n));
932
+ results.push_back(NewSubstring(CordRep::Ref(node), pos, n));
1043
933
  } else if (pos + n <= node->concat()->left->length) {
1044
934
  todo.push_back(SubRange(node->concat()->left, pos, n));
1045
935
  } else if (pos >= node->concat()->left->length) {
@@ -1071,7 +961,7 @@ Cord Cord::Subcord(size_t pos, size_t new_size) const {
1071
961
  } else if (new_size <= InlineRep::kMaxInline) {
1072
962
  Cord::ChunkIterator it = chunk_begin();
1073
963
  it.AdvanceBytes(pos);
1074
- char* dest = sub_cord.contents_.data_;
964
+ char* dest = sub_cord.contents_.data_.as_chars();
1075
965
  size_t remaining_size = new_size;
1076
966
  while (remaining_size > it->size()) {
1077
967
  cord_internal::SmallMemmove(dest, it->data(), it->size());
@@ -1080,7 +970,10 @@ Cord Cord::Subcord(size_t pos, size_t new_size) const {
1080
970
  ++it;
1081
971
  }
1082
972
  cord_internal::SmallMemmove(dest, it->data(), remaining_size);
1083
- sub_cord.contents_.data_[InlineRep::kMaxInline] = new_size;
973
+ sub_cord.contents_.set_inline_size(new_size);
974
+ } else if (tree->tag == RING) {
975
+ tree = CordRepRing::SubRing(CordRep::Ref(tree)->ring(), pos, new_size);
976
+ sub_cord.contents_.set_tree(tree);
1084
977
  } else {
1085
978
  sub_cord.contents_.set_tree(NewSubRange(tree, pos, new_size));
1086
979
  }
@@ -1117,9 +1010,9 @@ class CordForest {
1117
1010
  concat_node->left = concat_freelist_;
1118
1011
  concat_freelist_ = concat_node;
1119
1012
  } else {
1120
- Ref(concat_node->right);
1121
- Ref(concat_node->left);
1122
- Unref(concat_node);
1013
+ CordRep::Ref(concat_node->right);
1014
+ CordRep::Ref(concat_node->left);
1015
+ CordRep::Unref(concat_node);
1123
1016
  }
1124
1017
  } else {
1125
1018
  AddNode(node);
@@ -1269,20 +1162,23 @@ bool ComputeCompareResult<bool>(int memcmp_res) {
1269
1162
  // Helper routine. Locates the first flat chunk of the Cord without
1270
1163
  // initializing the iterator.
1271
1164
  inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
1272
- size_t n = data_[kMaxInline];
1273
- if (n <= kMaxInline) {
1274
- return absl::string_view(data_, n);
1165
+ if (!is_tree()) {
1166
+ return absl::string_view(data_.as_chars(), data_.inline_size());
1275
1167
  }
1276
1168
 
1277
1169
  CordRep* node = tree();
1278
1170
  if (node->tag >= FLAT) {
1279
- return absl::string_view(node->data, node->length);
1171
+ return absl::string_view(node->flat()->Data(), node->length);
1280
1172
  }
1281
1173
 
1282
1174
  if (node->tag == EXTERNAL) {
1283
1175
  return absl::string_view(node->external()->base, node->length);
1284
1176
  }
1285
1177
 
1178
+ if (node->tag == RING) {
1179
+ return node->ring()->entry_data(node->ring()->head());
1180
+ }
1181
+
1286
1182
  // Walk down the left branches until we hit a non-CONCAT node.
1287
1183
  while (node->tag == CONCAT) {
1288
1184
  node = node->concat()->left;
@@ -1299,7 +1195,7 @@ inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
1299
1195
  }
1300
1196
 
1301
1197
  if (node->tag >= FLAT) {
1302
- return absl::string_view(node->data + offset, length);
1198
+ return absl::string_view(node->flat()->Data() + offset, length);
1303
1199
  }
1304
1200
 
1305
1201
  assert((node->tag == EXTERNAL) && "Expect FLAT or EXTERNAL node here");
@@ -1482,26 +1378,22 @@ void Cord::CopyToArraySlowPath(char* dst) const {
1482
1378
  }
1483
1379
  }
1484
1380
 
1485
- Cord::ChunkIterator& Cord::ChunkIterator::operator++() {
1486
- ABSL_HARDENING_ASSERT(bytes_remaining_ > 0 &&
1487
- "Attempted to iterate past `end()`");
1488
- assert(bytes_remaining_ >= current_chunk_.size());
1489
- bytes_remaining_ -= current_chunk_.size();
1490
-
1491
- if (stack_of_right_children_.empty()) {
1381
+ Cord::ChunkIterator& Cord::ChunkIterator::AdvanceStack() {
1382
+ auto& stack_of_right_children = stack_of_right_children_;
1383
+ if (stack_of_right_children.empty()) {
1492
1384
  assert(!current_chunk_.empty()); // Called on invalid iterator.
1493
1385
  // We have reached the end of the Cord.
1494
1386
  return *this;
1495
1387
  }
1496
1388
 
1497
1389
  // Process the next node on the stack.
1498
- CordRep* node = stack_of_right_children_.back();
1499
- stack_of_right_children_.pop_back();
1390
+ CordRep* node = stack_of_right_children.back();
1391
+ stack_of_right_children.pop_back();
1500
1392
 
1501
1393
  // Walk down the left branches until we hit a non-CONCAT node. Save the
1502
1394
  // right children to the stack for subsequent traversal.
1503
1395
  while (node->tag == CONCAT) {
1504
- stack_of_right_children_.push_back(node->concat()->right);
1396
+ stack_of_right_children.push_back(node->concat()->right);
1505
1397
  node = node->concat()->left;
1506
1398
  }
1507
1399
 
@@ -1516,7 +1408,7 @@ Cord::ChunkIterator& Cord::ChunkIterator::operator++() {
1516
1408
  assert(node->tag == EXTERNAL || node->tag >= FLAT);
1517
1409
  assert(length != 0);
1518
1410
  const char* data =
1519
- node->tag == EXTERNAL ? node->external()->base : node->data;
1411
+ node->tag == EXTERNAL ? node->external()->base : node->flat()->Data();
1520
1412
  current_chunk_ = absl::string_view(data + offset, length);
1521
1413
  current_leaf_ = node;
1522
1414
  return *this;
@@ -1544,12 +1436,32 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
1544
1436
  }
1545
1437
  return subcord;
1546
1438
  }
1439
+
1440
+ if (ring_reader_) {
1441
+ size_t chunk_size = current_chunk_.size();
1442
+ if (n <= chunk_size && n <= kMaxBytesToCopy) {
1443
+ subcord = Cord(current_chunk_.substr(0, n));
1444
+ } else {
1445
+ auto* ring = CordRep::Ref(ring_reader_.ring())->ring();
1446
+ size_t offset = ring_reader_.length() - bytes_remaining_;
1447
+ subcord.contents_.set_tree(CordRepRing::SubRing(ring, offset, n));
1448
+ }
1449
+ if (n < chunk_size) {
1450
+ bytes_remaining_ -= n;
1451
+ current_chunk_.remove_prefix(n);
1452
+ } else {
1453
+ AdvanceBytesRing(n);
1454
+ }
1455
+ return subcord;
1456
+ }
1457
+
1458
+ auto& stack_of_right_children = stack_of_right_children_;
1547
1459
  if (n < current_chunk_.size()) {
1548
1460
  // Range to read is a proper subrange of the current chunk.
1549
1461
  assert(current_leaf_ != nullptr);
1550
- CordRep* subnode = Ref(current_leaf_);
1551
- const char* data =
1552
- subnode->tag == EXTERNAL ? subnode->external()->base : subnode->data;
1462
+ CordRep* subnode = CordRep::Ref(current_leaf_);
1463
+ const char* data = subnode->tag == EXTERNAL ? subnode->external()->base
1464
+ : subnode->flat()->Data();
1553
1465
  subnode = NewSubstring(subnode, current_chunk_.data() - data, n);
1554
1466
  subcord.contents_.set_tree(VerifyTree(subnode));
1555
1467
  RemoveChunkPrefix(n);
@@ -1559,10 +1471,10 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
1559
1471
  // Range to read begins with a proper subrange of the current chunk.
1560
1472
  assert(!current_chunk_.empty());
1561
1473
  assert(current_leaf_ != nullptr);
1562
- CordRep* subnode = Ref(current_leaf_);
1474
+ CordRep* subnode = CordRep::Ref(current_leaf_);
1563
1475
  if (current_chunk_.size() < subnode->length) {
1564
- const char* data =
1565
- subnode->tag == EXTERNAL ? subnode->external()->base : subnode->data;
1476
+ const char* data = subnode->tag == EXTERNAL ? subnode->external()->base
1477
+ : subnode->flat()->Data();
1566
1478
  subnode = NewSubstring(subnode, current_chunk_.data() - data,
1567
1479
  current_chunk_.size());
1568
1480
  }
@@ -1572,20 +1484,20 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
1572
1484
  // Process the next node(s) on the stack, reading whole subtrees depending on
1573
1485
  // their length and how many bytes we are advancing.
1574
1486
  CordRep* node = nullptr;
1575
- while (!stack_of_right_children_.empty()) {
1576
- node = stack_of_right_children_.back();
1577
- stack_of_right_children_.pop_back();
1487
+ while (!stack_of_right_children.empty()) {
1488
+ node = stack_of_right_children.back();
1489
+ stack_of_right_children.pop_back();
1578
1490
  if (node->length > n) break;
1579
1491
  // TODO(qrczak): This might unnecessarily recreate existing concat nodes.
1580
1492
  // Avoiding that would need pretty complicated logic (instead of
1581
- // current_leaf_, keep current_subtree_ which points to the highest node
1493
+ // current_leaf, keep current_subtree_ which points to the highest node
1582
1494
  // such that the current leaf can be found on the path of left children
1583
1495
  // starting from current_subtree_; delay creating subnode while node is
1584
1496
  // below current_subtree_; find the proper node along the path of left
1585
1497
  // children starting from current_subtree_ if this loop exits while staying
1586
1498
  // below current_subtree_; etc.; alternatively, push parents instead of
1587
1499
  // right children on the stack).
1588
- subnode = Concat(subnode, Ref(node));
1500
+ subnode = Concat(subnode, CordRep::Ref(node));
1589
1501
  n -= node->length;
1590
1502
  bytes_remaining_ -= node->length;
1591
1503
  node = nullptr;
@@ -1603,11 +1515,11 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
1603
1515
  while (node->tag == CONCAT) {
1604
1516
  if (node->concat()->left->length > n) {
1605
1517
  // Push right, descend left.
1606
- stack_of_right_children_.push_back(node->concat()->right);
1518
+ stack_of_right_children.push_back(node->concat()->right);
1607
1519
  node = node->concat()->left;
1608
1520
  } else {
1609
1521
  // Read left, descend right.
1610
- subnode = Concat(subnode, Ref(node->concat()->left));
1522
+ subnode = Concat(subnode, CordRep::Ref(node->concat()->left));
1611
1523
  n -= node->concat()->left->length;
1612
1524
  bytes_remaining_ -= node->concat()->left->length;
1613
1525
  node = node->concat()->right;
@@ -1626,9 +1538,11 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
1626
1538
  // chunk.
1627
1539
  assert(node->tag == EXTERNAL || node->tag >= FLAT);
1628
1540
  assert(length > n);
1629
- if (n > 0) subnode = Concat(subnode, NewSubstring(Ref(node), offset, n));
1541
+ if (n > 0) {
1542
+ subnode = Concat(subnode, NewSubstring(CordRep::Ref(node), offset, n));
1543
+ }
1630
1544
  const char* data =
1631
- node->tag == EXTERNAL ? node->external()->base : node->data;
1545
+ node->tag == EXTERNAL ? node->external()->base : node->flat()->Data();
1632
1546
  current_chunk_ = absl::string_view(data + offset + n, length - n);
1633
1547
  current_leaf_ = node;
1634
1548
  bytes_remaining_ -= n;
@@ -1644,12 +1558,19 @@ void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
1644
1558
  n -= current_chunk_.size();
1645
1559
  bytes_remaining_ -= current_chunk_.size();
1646
1560
 
1561
+ if (stack_of_right_children_.empty()) {
1562
+ // We have reached the end of the Cord.
1563
+ assert(bytes_remaining_ == 0);
1564
+ return;
1565
+ }
1566
+
1647
1567
  // Process the next node(s) on the stack, skipping whole subtrees depending on
1648
1568
  // their length and how many bytes we are advancing.
1649
1569
  CordRep* node = nullptr;
1650
- while (!stack_of_right_children_.empty()) {
1651
- node = stack_of_right_children_.back();
1652
- stack_of_right_children_.pop_back();
1570
+ auto& stack_of_right_children = stack_of_right_children_;
1571
+ while (!stack_of_right_children.empty()) {
1572
+ node = stack_of_right_children.back();
1573
+ stack_of_right_children.pop_back();
1653
1574
  if (node->length > n) break;
1654
1575
  n -= node->length;
1655
1576
  bytes_remaining_ -= node->length;
@@ -1667,7 +1588,7 @@ void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
1667
1588
  while (node->tag == CONCAT) {
1668
1589
  if (node->concat()->left->length > n) {
1669
1590
  // Push right, descend left.
1670
- stack_of_right_children_.push_back(node->concat()->right);
1591
+ stack_of_right_children.push_back(node->concat()->right);
1671
1592
  node = node->concat()->left;
1672
1593
  } else {
1673
1594
  // Skip left, descend right.
@@ -1688,7 +1609,7 @@ void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
1688
1609
  assert(node->tag == EXTERNAL || node->tag >= FLAT);
1689
1610
  assert(length > n);
1690
1611
  const char* data =
1691
- node->tag == EXTERNAL ? node->external()->base : node->data;
1612
+ node->tag == EXTERNAL ? node->external()->base : node->flat()->Data();
1692
1613
  current_chunk_ = absl::string_view(data + offset + n, length - n);
1693
1614
  current_leaf_ = node;
1694
1615
  bytes_remaining_ -= n;
@@ -1706,7 +1627,9 @@ char Cord::operator[](size_t i) const {
1706
1627
  assert(offset < rep->length);
1707
1628
  if (rep->tag >= FLAT) {
1708
1629
  // Get the "i"th character directly from the flat array.
1709
- return rep->data[offset];
1630
+ return rep->flat()->Data()[offset];
1631
+ } else if (rep->tag == RING) {
1632
+ return rep->ring()->GetCharacter(offset);
1710
1633
  } else if (rep->tag == EXTERNAL) {
1711
1634
  // Get the "i"th character from the external array.
1712
1635
  return rep->external()->base[offset];
@@ -1737,9 +1660,9 @@ absl::string_view Cord::FlattenSlowPath() {
1737
1660
  // Try to put the contents into a new flat rep. If they won't fit in the
1738
1661
  // biggest possible flat node, use an external rep instead.
1739
1662
  if (total_size <= kMaxFlatLength) {
1740
- new_rep = NewFlat(total_size);
1663
+ new_rep = CordRepFlat::New(total_size);
1741
1664
  new_rep->length = total_size;
1742
- new_buffer = new_rep->data;
1665
+ new_buffer = new_rep->flat()->Data();
1743
1666
  CopyToArraySlowPath(new_buffer);
1744
1667
  } else {
1745
1668
  new_buffer = std::allocator<char>().allocate(total_size);
@@ -1750,7 +1673,9 @@ absl::string_view Cord::FlattenSlowPath() {
1750
1673
  s.size());
1751
1674
  });
1752
1675
  }
1753
- Unref(contents_.tree());
1676
+ if (CordRep* tree = contents_.tree()) {
1677
+ CordRep::Unref(tree);
1678
+ }
1754
1679
  contents_.set_tree(new_rep);
1755
1680
  return absl::string_view(new_buffer, total_size);
1756
1681
  }
@@ -1758,7 +1683,7 @@ absl::string_view Cord::FlattenSlowPath() {
1758
1683
  /* static */ bool Cord::GetFlatAux(CordRep* rep, absl::string_view* fragment) {
1759
1684
  assert(rep != nullptr);
1760
1685
  if (rep->tag >= FLAT) {
1761
- *fragment = absl::string_view(rep->data, rep->length);
1686
+ *fragment = absl::string_view(rep->flat()->Data(), rep->length);
1762
1687
  return true;
1763
1688
  } else if (rep->tag == EXTERNAL) {
1764
1689
  *fragment = absl::string_view(rep->external()->base, rep->length);
@@ -1766,8 +1691,8 @@ absl::string_view Cord::FlattenSlowPath() {
1766
1691
  } else if (rep->tag == SUBSTRING) {
1767
1692
  CordRep* child = rep->substring()->child;
1768
1693
  if (child->tag >= FLAT) {
1769
- *fragment =
1770
- absl::string_view(child->data + rep->substring()->start, rep->length);
1694
+ *fragment = absl::string_view(
1695
+ child->flat()->Data() + rep->substring()->start, rep->length);
1771
1696
  return true;
1772
1697
  } else if (child->tag == EXTERNAL) {
1773
1698
  *fragment = absl::string_view(
@@ -1781,6 +1706,15 @@ absl::string_view Cord::FlattenSlowPath() {
1781
1706
  /* static */ void Cord::ForEachChunkAux(
1782
1707
  absl::cord_internal::CordRep* rep,
1783
1708
  absl::FunctionRef<void(absl::string_view)> callback) {
1709
+ if (rep->tag == RING) {
1710
+ ChunkIterator it(rep), end;
1711
+ while (it != end) {
1712
+ callback(*it);
1713
+ ++it;
1714
+ }
1715
+ return;
1716
+ }
1717
+
1784
1718
  assert(rep != nullptr);
1785
1719
  int stack_pos = 0;
1786
1720
  constexpr int stack_max = 128;
@@ -1822,9 +1756,9 @@ absl::string_view Cord::FlattenSlowPath() {
1822
1756
  }
1823
1757
  }
1824
1758
 
1825
- static void DumpNode(CordRep* rep, bool include_data, std::ostream* os) {
1759
+ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
1760
+ int indent) {
1826
1761
  const int kIndentStep = 1;
1827
- int indent = 0;
1828
1762
  absl::InlinedVector<CordRep*, kInlinedVectorSize> stack;
1829
1763
  absl::InlinedVector<int, kInlinedVectorSize> indents;
1830
1764
  for (;;) {
@@ -1845,17 +1779,28 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os) {
1845
1779
  *os << "SUBSTRING @ " << rep->substring()->start << "\n";
1846
1780
  indent += kIndentStep;
1847
1781
  rep = rep->substring()->child;
1848
- } else { // Leaf
1782
+ } else { // Leaf or ring
1849
1783
  if (rep->tag == EXTERNAL) {
1850
1784
  *os << "EXTERNAL [";
1851
1785
  if (include_data)
1852
1786
  *os << absl::CEscape(std::string(rep->external()->base, rep->length));
1853
1787
  *os << "]\n";
1854
- } else {
1855
- *os << "FLAT cap=" << TagToLength(rep->tag) << " [";
1788
+ } else if (rep->tag >= FLAT) {
1789
+ *os << "FLAT cap=" << rep->flat()->Capacity()
1790
+ << " [";
1856
1791
  if (include_data)
1857
- *os << absl::CEscape(std::string(rep->data, rep->length));
1792
+ *os << absl::CEscape(std::string(rep->flat()->Data(), rep->length));
1858
1793
  *os << "]\n";
1794
+ } else {
1795
+ assert(rep->tag == RING);
1796
+ auto* ring = rep->ring();
1797
+ *os << "RING, entries = " << ring->entries() << "\n";
1798
+ CordRepRing::index_type head = ring->head();
1799
+ do {
1800
+ DumpNode(ring->entry_child(head), include_data, os,
1801
+ indent + kIndentStep);
1802
+ head = ring->advance(head);;
1803
+ } while (head != ring->tail());
1859
1804
  }
1860
1805
  if (stack.empty()) break;
1861
1806
  rep = stack.back();
@@ -1900,8 +1845,9 @@ static bool VerifyNode(CordRep* root, CordRep* start_node,
1900
1845
  worklist.push_back(node->concat()->left);
1901
1846
  }
1902
1847
  } else if (node->tag >= FLAT) {
1903
- ABSL_INTERNAL_CHECK(node->length <= TagToLength(node->tag),
1904
- ReportError(root, node));
1848
+ ABSL_INTERNAL_CHECK(
1849
+ node->length <= node->flat()->Capacity(),
1850
+ ReportError(root, node));
1905
1851
  } else if (node->tag == EXTERNAL) {
1906
1852
  ABSL_INTERNAL_CHECK(node->external()->base != nullptr,
1907
1853
  ReportError(root, node));
@@ -1948,6 +1894,15 @@ static bool VerifyNode(CordRep* root, CordRep* start_node,
1948
1894
  }
1949
1895
  next_node = right;
1950
1896
  }
1897
+ } else if (cur_node->tag == RING) {
1898
+ total_mem_usage += CordRepRing::AllocSize(cur_node->ring()->capacity());
1899
+ const CordRepRing* ring = cur_node->ring();
1900
+ CordRepRing::index_type pos = ring->head(), tail = ring->tail();
1901
+ do {
1902
+ CordRep* node = ring->entry_child(pos);
1903
+ assert(node->tag >= FLAT || node->tag == EXTERNAL);
1904
+ RepMemoryUsageLeaf(node, &total_mem_usage);
1905
+ } while ((pos = ring->advance(pos)) != tail);
1951
1906
  } else {
1952
1907
  // Since cur_node is not a leaf or a concat node it must be a substring.
1953
1908
  assert(cur_node->tag == SUBSTRING);
@@ -1977,14 +1932,14 @@ std::ostream& operator<<(std::ostream& out, const Cord& cord) {
1977
1932
  }
1978
1933
 
1979
1934
  namespace strings_internal {
1980
- size_t CordTestAccess::FlatOverhead() { return kFlatOverhead; }
1981
- size_t CordTestAccess::MaxFlatLength() { return kMaxFlatLength; }
1935
+ size_t CordTestAccess::FlatOverhead() { return cord_internal::kFlatOverhead; }
1936
+ size_t CordTestAccess::MaxFlatLength() { return cord_internal::kMaxFlatLength; }
1982
1937
  size_t CordTestAccess::FlatTagToLength(uint8_t tag) {
1983
- return TagToLength(tag);
1938
+ return cord_internal::TagToLength(tag);
1984
1939
  }
1985
1940
  uint8_t CordTestAccess::LengthToTag(size_t s) {
1986
1941
  ABSL_INTERNAL_CHECK(s <= kMaxFlatLength, absl::StrCat("Invalid length ", s));
1987
- return AllocatedSizeToTag(s + kFlatOverhead);
1942
+ return cord_internal::AllocatedSizeToTag(s + cord_internal::kFlatOverhead);
1988
1943
  }
1989
1944
  size_t CordTestAccess::SizeofCordRepConcat() { return sizeof(CordRepConcat); }
1990
1945
  size_t CordTestAccess::SizeofCordRepExternal() {