grpc 1.28.0 → 1.30.0

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 (497) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +7694 -11190
  3. data/include/grpc/grpc.h +2 -2
  4. data/include/grpc/grpc_security.h +22 -9
  5. data/include/grpc/grpc_security_constants.h +1 -0
  6. data/include/grpc/impl/codegen/grpc_types.h +19 -21
  7. data/include/grpc/impl/codegen/port_platform.h +6 -2
  8. data/include/grpc/module.modulemap +24 -39
  9. data/src/core/ext/filters/client_channel/backend_metric.cc +7 -4
  10. data/src/core/ext/filters/client_channel/client_channel.cc +203 -236
  11. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +3 -2
  12. data/src/core/ext/filters/client_channel/health/health_check_client.cc +7 -22
  13. data/src/core/ext/filters/client_channel/health/health_check_client.h +3 -3
  14. data/src/core/ext/filters/client_channel/http_proxy.cc +17 -10
  15. data/src/core/ext/filters/client_channel/lb_policy.cc +19 -18
  16. data/src/core/ext/filters/client_channel/lb_policy.h +42 -33
  17. data/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc +83 -0
  18. data/src/core/ext/filters/client_channel/lb_policy/address_filtering.h +99 -0
  19. data/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc +10 -4
  20. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +240 -301
  21. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.cc +89 -0
  22. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h +40 -0
  23. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +11 -9
  24. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +3 -2
  25. data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +871 -0
  26. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +1 -1
  27. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +5 -11
  28. data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +734 -0
  29. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +84 -37
  30. data/src/core/ext/filters/client_channel/lb_policy/xds/eds.cc +938 -0
  31. data/src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc +528 -0
  32. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.h +1 -2
  33. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc +834 -0
  34. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +6 -2
  35. data/src/core/ext/filters/client_channel/local_subchannel_pool.h +2 -1
  36. data/src/core/ext/filters/client_channel/parse_address.cc +22 -21
  37. data/src/core/ext/filters/client_channel/resolver.cc +5 -8
  38. data/src/core/ext/filters/client_channel/resolver.h +12 -14
  39. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +73 -59
  40. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc +35 -35
  41. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +8 -7
  42. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc +16 -20
  43. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +4 -4
  44. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +72 -117
  45. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +184 -133
  46. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +5 -3
  47. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +7 -4
  48. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +40 -43
  49. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +93 -102
  50. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +0 -4
  51. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +2 -2
  52. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +32 -5
  53. data/src/core/ext/filters/client_channel/resolver_factory.h +2 -2
  54. data/src/core/ext/filters/client_channel/resolver_registry.cc +6 -3
  55. data/src/core/ext/filters/client_channel/resolver_registry.h +8 -8
  56. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +16 -16
  57. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +19 -16
  58. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +20 -31
  59. data/src/core/ext/filters/client_channel/resolving_lb_policy.h +4 -3
  60. data/src/core/ext/filters/client_channel/server_address.cc +6 -9
  61. data/src/core/ext/filters/client_channel/server_address.h +6 -12
  62. data/src/core/ext/filters/client_channel/service_config.cc +104 -144
  63. data/src/core/ext/filters/client_channel/service_config.h +28 -98
  64. data/src/core/ext/filters/client_channel/service_config_call_data.h +68 -0
  65. data/src/core/ext/filters/client_channel/service_config_parser.cc +87 -0
  66. data/src/core/ext/filters/client_channel/service_config_parser.h +89 -0
  67. data/src/core/ext/filters/client_channel/subchannel.cc +54 -24
  68. data/src/core/ext/filters/client_channel/subchannel.h +35 -11
  69. data/src/core/ext/filters/client_channel/xds/xds_api.cc +348 -221
  70. data/src/core/ext/filters/client_channel/xds/xds_api.h +37 -37
  71. data/src/core/ext/filters/client_channel/xds/xds_bootstrap.cc +44 -49
  72. data/src/core/ext/filters/client_channel/xds/xds_bootstrap.h +4 -3
  73. data/src/core/ext/filters/client_channel/xds/xds_channel_secure.cc +4 -2
  74. data/src/core/ext/filters/client_channel/xds/xds_client.cc +532 -339
  75. data/src/core/ext/filters/client_channel/xds/xds_client.h +57 -22
  76. data/src/core/ext/filters/client_channel/xds/xds_client_stats.cc +11 -12
  77. data/src/core/ext/filters/client_channel/xds/xds_client_stats.h +31 -19
  78. data/src/core/ext/filters/http/client/http_client_filter.cc +23 -28
  79. data/src/core/ext/filters/http/client_authority_filter.cc +4 -4
  80. data/src/core/ext/filters/http/http_filters_plugin.cc +27 -12
  81. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +258 -221
  82. data/src/core/ext/filters/http/message_compress/message_decompress_filter.cc +358 -0
  83. data/src/core/ext/filters/http/message_compress/message_decompress_filter.h +29 -0
  84. data/src/core/ext/filters/message_size/message_size_filter.cc +7 -10
  85. data/src/core/ext/filters/message_size/message_size_filter.h +4 -4
  86. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +4 -4
  87. data/src/core/ext/transport/chttp2/transport/bin_encoder.cc +4 -6
  88. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +23 -22
  89. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +1 -0
  90. data/src/core/ext/transport/chttp2/transport/flow_control.cc +3 -3
  91. data/src/core/ext/transport/chttp2/transport/frame_goaway.h +2 -3
  92. data/src/core/ext/transport/chttp2/transport/frame_ping.h +2 -3
  93. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +2 -3
  94. data/src/core/ext/transport/chttp2/transport/frame_settings.h +2 -3
  95. data/src/core/ext/transport/chttp2/transport/frame_window_update.h +2 -3
  96. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +29 -16
  97. data/src/core/ext/transport/chttp2/transport/hpack_encoder.h +2 -3
  98. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +2 -3
  99. data/src/core/ext/transport/chttp2/transport/hpack_table.h +2 -2
  100. data/src/core/ext/transport/chttp2/transport/http2_settings.h +4 -5
  101. data/src/core/ext/transport/chttp2/transport/huffsyms.h +2 -3
  102. data/src/core/ext/transport/chttp2/transport/internal.h +14 -21
  103. data/src/core/ext/transport/chttp2/transport/stream_map.h +2 -3
  104. data/src/core/ext/transport/chttp2/transport/writing.cc +15 -8
  105. data/src/core/ext/transport/inproc/inproc_transport.cc +19 -0
  106. data/src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c +4 -229
  107. data/src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h +5 -875
  108. data/src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c +114 -0
  109. data/src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h +418 -0
  110. data/src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c +72 -0
  111. data/src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h +197 -0
  112. data/src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c +105 -0
  113. data/src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h +378 -0
  114. data/src/core/ext/upb-generated/envoy/api/v2/cds.upb.c +1 -0
  115. data/src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c +21 -8
  116. data/src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h +43 -7
  117. data/src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c +1 -0
  118. data/src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c +1 -0
  119. data/src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c +1 -0
  120. data/src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c +2 -1
  121. data/src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c +35 -0
  122. data/src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h +78 -0
  123. data/src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c +47 -26
  124. data/src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h +115 -65
  125. data/src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c +1 -0
  126. data/src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c +34 -0
  127. data/src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h +72 -0
  128. data/src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c +2 -1
  129. data/src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c +24 -20
  130. data/src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h +28 -13
  131. data/src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c +1 -0
  132. data/src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c +38 -18
  133. data/src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h +88 -6
  134. data/src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c +34 -0
  135. data/src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h +89 -0
  136. data/src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c +1 -0
  137. data/src/core/ext/upb-generated/envoy/api/v2/eds.upb.c +1 -0
  138. data/src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c +1 -0
  139. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c +1 -0
  140. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c +9 -6
  141. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.h +12 -4
  142. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c +1 -0
  143. data/src/core/ext/upb-generated/envoy/api/v2/lds.upb.c +1 -0
  144. data/src/core/ext/upb-generated/envoy/api/v2/listener.upb.c +15 -10
  145. data/src/core/ext/upb-generated/envoy/api/v2/listener.upb.h +16 -0
  146. data/src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c +1 -0
  147. data/src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c +2 -1
  148. data/src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c +1 -0
  149. data/src/core/ext/upb-generated/envoy/api/v2/rds.upb.c +1 -0
  150. data/src/core/ext/upb-generated/envoy/api/v2/route.upb.c +1 -0
  151. data/src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c +1 -0
  152. data/src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c +63 -41
  153. data/src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.h +173 -77
  154. data/src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c +1 -0
  155. data/src/core/ext/upb-generated/envoy/api/v2/srds.upb.c +1 -0
  156. data/src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c +1 -0
  157. data/src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c +48 -28
  158. data/src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h +90 -30
  159. data/src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c +1 -0
  160. data/src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c +51 -0
  161. data/src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h +125 -0
  162. data/src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c +1 -0
  163. data/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c +4 -2
  164. data/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h +4 -0
  165. data/src/core/ext/upb-generated/envoy/type/http.upb.c +1 -0
  166. data/src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c +16 -0
  167. data/src/core/ext/upb-generated/envoy/type/matcher/regex.upb.h +36 -0
  168. data/src/core/ext/upb-generated/envoy/type/matcher/string.upb.c +1 -0
  169. data/src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c +1 -0
  170. data/src/core/ext/upb-generated/envoy/type/percent.upb.c +1 -0
  171. data/src/core/ext/upb-generated/envoy/type/range.upb.c +1 -0
  172. data/src/core/ext/upb-generated/envoy/type/semantic_version.upb.c +1 -0
  173. data/src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c +1 -0
  174. data/src/core/ext/upb-generated/google/protobuf/descriptor.upb.c +9 -8
  175. data/src/core/ext/upb-generated/google/protobuf/descriptor.upb.h +30 -24
  176. data/src/core/ext/upb-generated/udpa/annotations/status.upb.c +28 -0
  177. data/src/core/ext/upb-generated/udpa/annotations/status.upb.h +65 -0
  178. data/src/core/ext/upb-generated/validate/validate.upb.c +21 -20
  179. data/src/core/ext/upb-generated/validate/validate.upb.h +69 -63
  180. data/src/core/lib/channel/channel_args.cc +15 -14
  181. data/src/core/lib/channel/channel_args.h +3 -1
  182. data/src/core/lib/channel/channel_stack.h +20 -13
  183. data/src/core/lib/channel/channelz.cc +5 -6
  184. data/src/core/lib/channel/channelz.h +3 -2
  185. data/src/core/lib/channel/channelz_registry.cc +5 -3
  186. data/src/core/lib/channel/connected_channel.cc +7 -5
  187. data/src/core/lib/channel/context.h +1 -1
  188. data/src/core/lib/channel/handshaker.cc +11 -13
  189. data/src/core/lib/channel/handshaker.h +4 -2
  190. data/src/core/lib/channel/handshaker_registry.cc +5 -17
  191. data/src/core/lib/channel/status_util.cc +2 -3
  192. data/src/core/lib/compression/message_compress.cc +5 -1
  193. data/src/core/lib/debug/stats.cc +21 -27
  194. data/src/core/lib/debug/stats.h +3 -1
  195. data/src/core/lib/gpr/spinlock.h +2 -3
  196. data/src/core/lib/gpr/string.cc +2 -26
  197. data/src/core/lib/gpr/string.h +0 -16
  198. data/src/core/lib/gpr/sync_abseil.cc +2 -0
  199. data/src/core/lib/gpr/time.cc +4 -0
  200. data/src/core/lib/gpr/time_posix.cc +1 -1
  201. data/src/core/lib/gprpp/atomic.h +6 -6
  202. data/src/core/lib/gprpp/fork.cc +1 -1
  203. data/src/core/lib/gprpp/host_port.cc +29 -35
  204. data/src/core/lib/gprpp/host_port.h +14 -17
  205. data/src/core/lib/gprpp/map.h +5 -11
  206. data/src/core/lib/gprpp/ref_counted_ptr.h +5 -0
  207. data/src/core/lib/http/format_request.cc +46 -65
  208. data/src/core/lib/http/httpcli.cc +2 -3
  209. data/src/core/lib/http/httpcli.h +2 -3
  210. data/src/core/lib/http/httpcli_security_connector.cc +5 -5
  211. data/src/core/lib/http/parser.h +2 -3
  212. data/src/core/lib/iomgr/buffer_list.h +22 -21
  213. data/src/core/lib/iomgr/call_combiner.h +3 -2
  214. data/src/core/lib/iomgr/cfstream_handle.cc +3 -2
  215. data/src/core/lib/iomgr/closure.h +2 -3
  216. data/src/core/lib/iomgr/dualstack_socket_posix.cc +47 -0
  217. data/src/core/lib/iomgr/endpoint_cfstream.cc +2 -3
  218. data/src/core/lib/iomgr/endpoint_pair.h +2 -3
  219. data/src/core/lib/iomgr/error.cc +6 -9
  220. data/src/core/lib/iomgr/error.h +0 -1
  221. data/src/core/lib/iomgr/ev_apple.cc +356 -0
  222. data/src/core/lib/iomgr/ev_apple.h +43 -0
  223. data/src/core/lib/iomgr/ev_epoll1_linux.cc +20 -23
  224. data/src/core/lib/iomgr/ev_epollex_linux.cc +2 -3
  225. data/src/core/lib/iomgr/ev_poll_posix.cc +3 -3
  226. data/src/core/lib/iomgr/ev_posix.cc +2 -3
  227. data/src/core/lib/iomgr/exec_ctx.h +14 -2
  228. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +84 -20
  229. data/src/core/lib/iomgr/pollset_set_custom.cc +10 -10
  230. data/src/core/lib/{gprpp/optional.h → iomgr/pollset_uv.h} +11 -12
  231. data/src/core/lib/iomgr/port.h +1 -0
  232. data/src/core/lib/iomgr/python_util.h +46 -0
  233. data/src/core/lib/iomgr/resolve_address.h +4 -6
  234. data/src/core/lib/iomgr/resolve_address_custom.cc +29 -39
  235. data/src/core/lib/iomgr/resolve_address_custom.h +4 -2
  236. data/src/core/lib/iomgr/resolve_address_posix.cc +10 -11
  237. data/src/core/lib/iomgr/resolve_address_windows.cc +8 -17
  238. data/src/core/lib/iomgr/resource_quota.cc +4 -6
  239. data/src/core/lib/iomgr/sockaddr_utils.cc +23 -29
  240. data/src/core/lib/iomgr/sockaddr_utils.h +9 -14
  241. data/src/core/lib/iomgr/socket_factory_posix.h +2 -3
  242. data/src/core/lib/iomgr/socket_mutator.h +2 -3
  243. data/src/core/lib/iomgr/socket_utils_common_posix.cc +7 -26
  244. data/src/core/lib/iomgr/socket_utils_posix.h +3 -0
  245. data/src/core/lib/iomgr/tcp_client_cfstream.cc +5 -7
  246. data/src/core/lib/iomgr/tcp_client_posix.cc +8 -5
  247. data/src/core/lib/iomgr/tcp_client_windows.cc +2 -3
  248. data/src/core/lib/iomgr/tcp_custom.cc +2 -3
  249. data/src/core/lib/iomgr/tcp_server_custom.cc +5 -9
  250. data/src/core/lib/iomgr/tcp_server_posix.cc +5 -4
  251. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +5 -4
  252. data/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc +8 -11
  253. data/src/core/lib/iomgr/tcp_uv.cc +3 -2
  254. data/src/core/lib/iomgr/time_averaged_stats.h +2 -3
  255. data/src/core/lib/iomgr/timer_generic.cc +2 -3
  256. data/src/core/lib/{gprpp/inlined_vector.h → iomgr/timer_generic.h} +19 -17
  257. data/src/core/lib/iomgr/timer_heap.h +2 -3
  258. data/src/core/lib/iomgr/udp_server.cc +9 -14
  259. data/src/core/lib/json/json.h +3 -2
  260. data/src/core/lib/json/json_reader.cc +5 -5
  261. data/src/core/lib/json/json_writer.cc +13 -12
  262. data/src/core/lib/security/credentials/composite/composite_credentials.cc +12 -0
  263. data/src/core/lib/security/credentials/composite/composite_credentials.h +6 -3
  264. data/src/core/lib/security/credentials/credentials.cc +0 -84
  265. data/src/core/lib/security/credentials/credentials.h +8 -59
  266. data/src/core/lib/security/credentials/fake/fake_credentials.h +4 -0
  267. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +3 -8
  268. data/src/core/lib/security/credentials/iam/iam_credentials.cc +8 -6
  269. data/src/core/lib/security/credentials/iam/iam_credentials.h +4 -0
  270. data/src/core/lib/security/credentials/jwt/json_token.cc +1 -1
  271. data/src/core/lib/security/credentials/jwt/json_token.h +2 -5
  272. data/src/core/lib/security/credentials/jwt/jwt_credentials.h +12 -0
  273. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +8 -15
  274. data/src/core/lib/security/credentials/jwt/jwt_verifier.h +2 -3
  275. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +55 -27
  276. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +9 -3
  277. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +13 -0
  278. data/src/core/lib/security/credentials/plugin/plugin_credentials.h +2 -0
  279. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +23 -13
  280. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +38 -11
  281. data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +21 -6
  282. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +7 -7
  283. data/src/core/lib/security/security_connector/load_system_roots_linux.cc +3 -2
  284. data/src/core/lib/security/security_connector/local/local_security_connector.cc +1 -1
  285. data/src/core/lib/security/security_connector/security_connector.h +1 -1
  286. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +20 -25
  287. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.h +4 -6
  288. data/src/core/lib/security/security_connector/ssl_utils.cc +59 -12
  289. data/src/core/lib/security/security_connector/ssl_utils.h +12 -10
  290. data/src/core/lib/security/security_connector/tls/tls_security_connector.cc +77 -51
  291. data/src/core/lib/security/security_connector/tls/tls_security_connector.h +27 -5
  292. data/src/core/lib/security/transport/client_auth_filter.cc +1 -2
  293. data/src/core/lib/slice/slice_intern.cc +2 -3
  294. data/src/core/lib/slice/slice_internal.h +14 -0
  295. data/src/core/lib/slice/slice_utils.h +9 -0
  296. data/src/core/lib/surface/byte_buffer_reader.cc +2 -47
  297. data/src/core/lib/surface/call.cc +2 -3
  298. data/src/core/lib/surface/call_log_batch.cc +50 -58
  299. data/src/core/lib/surface/channel.cc +53 -31
  300. data/src/core/lib/surface/channel.h +35 -4
  301. data/src/core/lib/surface/channel_ping.cc +2 -3
  302. data/src/core/lib/surface/completion_queue.cc +33 -33
  303. data/src/core/lib/surface/event_string.cc +18 -25
  304. data/src/core/lib/surface/event_string.h +3 -1
  305. data/src/core/lib/surface/init_secure.cc +1 -4
  306. data/src/core/lib/surface/server.cc +570 -369
  307. data/src/core/lib/surface/server.h +32 -0
  308. data/src/core/lib/surface/version.cc +2 -2
  309. data/src/core/lib/transport/byte_stream.h +7 -2
  310. data/src/core/lib/transport/connectivity_state.cc +7 -6
  311. data/src/core/lib/transport/connectivity_state.h +5 -3
  312. data/src/core/lib/transport/metadata.cc +3 -3
  313. data/src/core/lib/transport/metadata_batch.h +2 -3
  314. data/src/core/lib/transport/static_metadata.h +1 -1
  315. data/src/core/lib/transport/status_conversion.cc +6 -14
  316. data/src/core/lib/transport/transport.cc +2 -3
  317. data/src/core/lib/transport/transport.h +3 -2
  318. data/src/core/lib/transport/transport_op_string.cc +61 -102
  319. data/src/core/lib/uri/uri_parser.h +2 -3
  320. data/src/core/plugin_registry/grpc_plugin_registry.cc +20 -4
  321. data/src/core/tsi/alts/crypt/aes_gcm.cc +0 -2
  322. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +8 -1
  323. data/src/core/tsi/alts/handshaker/alts_handshaker_client.h +8 -4
  324. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +32 -2
  325. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +9 -1
  326. data/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h +2 -3
  327. data/src/core/tsi/fake_transport_security.cc +10 -15
  328. data/src/core/tsi/ssl/session_cache/ssl_session.h +0 -2
  329. data/src/core/tsi/ssl/session_cache/ssl_session_cache.h +0 -2
  330. data/src/core/tsi/ssl_transport_security.cc +52 -39
  331. data/src/core/tsi/ssl_transport_security.h +8 -8
  332. data/src/core/tsi/ssl_types.h +0 -2
  333. data/src/core/tsi/transport_security.h +6 -9
  334. data/src/core/tsi/transport_security_grpc.h +2 -3
  335. data/src/core/tsi/transport_security_interface.h +3 -3
  336. data/src/ruby/ext/grpc/rb_call.c +9 -1
  337. data/src/ruby/lib/grpc/errors.rb +103 -42
  338. data/src/ruby/lib/grpc/generic/active_call.rb +2 -3
  339. data/src/ruby/lib/grpc/generic/interceptors.rb +4 -4
  340. data/src/ruby/lib/grpc/generic/rpc_server.rb +9 -10
  341. data/src/ruby/lib/grpc/generic/service.rb +5 -4
  342. data/src/ruby/lib/grpc/structs.rb +1 -1
  343. data/src/ruby/lib/grpc/version.rb +1 -1
  344. data/src/ruby/pb/generate_proto_ruby.sh +5 -3
  345. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +11 -0
  346. data/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb +16 -0
  347. data/src/ruby/spec/debug_message_spec.rb +134 -0
  348. data/src/ruby/spec/generic/service_spec.rb +2 -0
  349. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_ruby_style.proto +5 -0
  350. data/src/ruby/spec/pb/codegen/package_option_spec.rb +2 -0
  351. data/src/ruby/spec/testdata/ca.pem +18 -13
  352. data/src/ruby/spec/testdata/client.key +26 -14
  353. data/src/ruby/spec/testdata/client.pem +18 -12
  354. data/src/ruby/spec/testdata/server1.key +26 -14
  355. data/src/ruby/spec/testdata/server1.pem +20 -14
  356. data/third_party/abseil-cpp/absl/time/civil_time.cc +175 -0
  357. data/third_party/abseil-cpp/absl/time/civil_time.h +538 -0
  358. data/third_party/abseil-cpp/absl/time/clock.cc +569 -0
  359. data/third_party/abseil-cpp/absl/time/clock.h +74 -0
  360. data/third_party/abseil-cpp/absl/time/duration.cc +922 -0
  361. data/third_party/abseil-cpp/absl/time/format.cc +153 -0
  362. data/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time.h +332 -0
  363. data/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h +622 -0
  364. data/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h +384 -0
  365. data/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h +102 -0
  366. data/third_party/abseil-cpp/absl/time/internal/cctz/src/civil_time_detail.cc +94 -0
  367. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc +140 -0
  368. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.h +52 -0
  369. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc +922 -0
  370. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc +45 -0
  371. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.h +76 -0
  372. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc +121 -0
  373. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h +93 -0
  374. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc +958 -0
  375. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h +138 -0
  376. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc +308 -0
  377. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.h +55 -0
  378. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc +187 -0
  379. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc +159 -0
  380. data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.h +132 -0
  381. data/third_party/abseil-cpp/absl/time/internal/cctz/src/tzfile.h +122 -0
  382. data/third_party/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc +115 -0
  383. data/third_party/abseil-cpp/absl/time/internal/get_current_time_chrono.inc +31 -0
  384. data/third_party/abseil-cpp/absl/time/internal/get_current_time_posix.inc +24 -0
  385. data/third_party/abseil-cpp/absl/time/time.cc +499 -0
  386. data/third_party/abseil-cpp/absl/time/time.h +1584 -0
  387. data/third_party/boringssl-with-bazel/err_data.c +329 -297
  388. data/third_party/boringssl-with-bazel/src/crypto/cipher_extra/derive_key.c +1 -1
  389. data/third_party/boringssl-with-bazel/src/crypto/cpu-arm-linux.c +7 -5
  390. data/third_party/boringssl-with-bazel/src/crypto/cpu-intel.c +13 -4
  391. data/third_party/boringssl-with-bazel/src/crypto/crypto.c +11 -0
  392. data/third_party/boringssl-with-bazel/src/{third_party/fiat → crypto/curve25519}/curve25519.c +18 -26
  393. data/third_party/boringssl-with-bazel/src/{third_party/fiat → crypto/curve25519}/curve25519_tables.h +13 -21
  394. data/third_party/boringssl-with-bazel/src/{third_party/fiat → crypto/curve25519}/internal.h +14 -22
  395. data/third_party/boringssl-with-bazel/src/crypto/curve25519/spake25519.c +1 -1
  396. data/third_party/boringssl-with-bazel/src/crypto/dh/dh.c +15 -0
  397. data/third_party/boringssl-with-bazel/src/crypto/dsa/dsa.c +10 -0
  398. data/third_party/boringssl-with-bazel/src/crypto/ec_extra/hash_to_curve.c +425 -0
  399. data/third_party/boringssl-with-bazel/src/crypto/ec_extra/internal.h +78 -0
  400. data/third_party/boringssl-with-bazel/src/crypto/ecdh_extra/ecdh_extra.c +2 -2
  401. data/third_party/boringssl-with-bazel/src/crypto/err/err.c +33 -32
  402. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/aes/aes_nohw.c +1 -1
  403. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bcm.c +2 -1
  404. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/exponentiation.c +3 -3
  405. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/internal.h +14 -11
  406. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/montgomery.c +8 -8
  407. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/mul.c +30 -154
  408. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/digest/digests.c +16 -0
  409. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec.c +289 -117
  410. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec_key.c +13 -27
  411. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec_montgomery.c +96 -55
  412. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/felem.c +25 -7
  413. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/internal.h +432 -160
  414. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/oct.c +63 -71
  415. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p224-64.c +5 -14
  416. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256-x86_64-table.h +9481 -9485
  417. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256-x86_64.c +80 -99
  418. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256.c +736 -0
  419. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256_table.h +297 -0
  420. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/scalar.c +90 -11
  421. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/simple.c +125 -148
  422. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/simple_mul.c +189 -3
  423. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/wnaf.c +61 -18
  424. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ecdh/ecdh.c +2 -2
  425. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ecdsa/ecdsa.c +20 -5
  426. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/fork_detect.c +137 -0
  427. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/fork_detect.h +49 -0
  428. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/getrandom_fillin.h +64 -0
  429. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/internal.h +41 -5
  430. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/rand.c +32 -17
  431. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/urandom.c +24 -114
  432. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/blinding.c +4 -0
  433. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/internal.h +1 -0
  434. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa.c +51 -38
  435. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa_impl.c +15 -1
  436. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/sha/sha512.c +44 -35
  437. data/third_party/boringssl-with-bazel/src/crypto/mem.c +29 -12
  438. data/third_party/boringssl-with-bazel/src/crypto/obj/obj_dat.h +15 -1
  439. data/third_party/boringssl-with-bazel/src/crypto/rand_extra/deterministic.c +6 -10
  440. data/third_party/boringssl-with-bazel/src/crypto/rand_extra/windows.c +16 -0
  441. data/third_party/boringssl-with-bazel/src/crypto/thread_pthread.c +4 -0
  442. data/third_party/boringssl-with-bazel/src/crypto/thread_win.c +4 -0
  443. data/third_party/boringssl-with-bazel/src/crypto/trust_token/internal.h +278 -0
  444. data/third_party/boringssl-with-bazel/src/crypto/trust_token/pmbtoken.c +1474 -0
  445. data/third_party/boringssl-with-bazel/src/crypto/trust_token/trust_token.c +720 -0
  446. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_set.c +16 -0
  447. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_vfy.c +5 -0
  448. data/third_party/boringssl-with-bazel/src/crypto/x509/x509name.c +4 -3
  449. data/third_party/boringssl-with-bazel/src/include/openssl/base.h +5 -1
  450. data/third_party/boringssl-with-bazel/src/include/openssl/crypto.h +9 -4
  451. data/third_party/boringssl-with-bazel/src/include/openssl/dh.h +20 -0
  452. data/third_party/boringssl-with-bazel/src/include/openssl/digest.h +1 -0
  453. data/third_party/boringssl-with-bazel/src/include/openssl/dsa.h +16 -0
  454. data/third_party/boringssl-with-bazel/src/include/openssl/ecdsa.h +6 -0
  455. data/third_party/boringssl-with-bazel/src/include/openssl/err.h +2 -0
  456. data/third_party/boringssl-with-bazel/src/include/openssl/nid.h +5 -0
  457. data/third_party/boringssl-with-bazel/src/include/openssl/rand.h +3 -17
  458. data/third_party/boringssl-with-bazel/src/include/openssl/rsa.h +31 -0
  459. data/third_party/boringssl-with-bazel/src/include/openssl/sha.h +26 -0
  460. data/third_party/boringssl-with-bazel/src/include/openssl/ssl.h +172 -77
  461. data/third_party/boringssl-with-bazel/src/include/openssl/tls1.h +1 -0
  462. data/third_party/boringssl-with-bazel/src/include/openssl/trust_token.h +291 -0
  463. data/third_party/boringssl-with-bazel/src/include/openssl/x509.h +5 -3
  464. data/third_party/boringssl-with-bazel/src/include/openssl/x509_vfy.h +1 -0
  465. data/third_party/boringssl-with-bazel/src/ssl/d1_both.cc +0 -4
  466. data/third_party/boringssl-with-bazel/src/ssl/d1_lib.cc +3 -3
  467. data/third_party/boringssl-with-bazel/src/ssl/dtls_method.cc +13 -4
  468. data/third_party/boringssl-with-bazel/src/ssl/handoff.cc +146 -57
  469. data/third_party/boringssl-with-bazel/src/ssl/handshake.cc +14 -3
  470. data/third_party/boringssl-with-bazel/src/ssl/handshake_client.cc +28 -20
  471. data/third_party/boringssl-with-bazel/src/ssl/handshake_server.cc +12 -4
  472. data/third_party/boringssl-with-bazel/src/ssl/internal.h +64 -47
  473. data/third_party/boringssl-with-bazel/src/ssl/s3_both.cc +10 -10
  474. data/third_party/boringssl-with-bazel/src/ssl/s3_lib.cc +2 -2
  475. data/third_party/boringssl-with-bazel/src/ssl/s3_pkt.cc +21 -21
  476. data/third_party/boringssl-with-bazel/src/ssl/ssl_asn1.cc +29 -0
  477. data/third_party/boringssl-with-bazel/src/ssl/ssl_cert.cc +4 -0
  478. data/third_party/boringssl-with-bazel/src/ssl/ssl_lib.cc +6 -1
  479. data/third_party/boringssl-with-bazel/src/ssl/ssl_privkey.cc +13 -2
  480. data/third_party/boringssl-with-bazel/src/ssl/ssl_session.cc +64 -5
  481. data/third_party/boringssl-with-bazel/src/ssl/ssl_stat.cc +6 -0
  482. data/third_party/boringssl-with-bazel/src/ssl/t1_enc.cc +6 -2
  483. data/third_party/boringssl-with-bazel/src/ssl/t1_lib.cc +47 -53
  484. data/third_party/boringssl-with-bazel/src/ssl/tls13_both.cc +1 -1
  485. data/third_party/boringssl-with-bazel/src/ssl/tls13_client.cc +98 -27
  486. data/third_party/boringssl-with-bazel/src/ssl/tls13_enc.cc +23 -75
  487. data/third_party/boringssl-with-bazel/src/ssl/tls13_server.cc +50 -20
  488. data/third_party/boringssl-with-bazel/src/ssl/tls_method.cc +63 -25
  489. data/third_party/boringssl-with-bazel/src/third_party/fiat/curve25519_32.h +245 -175
  490. data/third_party/boringssl-with-bazel/src/third_party/fiat/curve25519_64.h +135 -75
  491. data/third_party/boringssl-with-bazel/src/third_party/fiat/p256_32.h +1593 -1672
  492. data/third_party/boringssl-with-bazel/src/third_party/fiat/p256_64.h +512 -503
  493. metadata +111 -37
  494. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +0 -1754
  495. data/src/core/lib/gprpp/string_view.h +0 -60
  496. data/src/core/tsi/grpc_shadow_boringssl.h +0 -3311
  497. data/third_party/boringssl-with-bazel/src/third_party/fiat/p256.c +0 -1063
@@ -0,0 +1,45 @@
1
+ // Copyright 2016 Google Inc. All Rights Reserved.
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
+ #include "time_zone_if.h"
16
+
17
+ #include "absl/base/config.h"
18
+ #include "time_zone_info.h"
19
+ #include "time_zone_libc.h"
20
+
21
+ namespace absl {
22
+ ABSL_NAMESPACE_BEGIN
23
+ namespace time_internal {
24
+ namespace cctz {
25
+
26
+ std::unique_ptr<TimeZoneIf> TimeZoneIf::Load(const std::string& name) {
27
+ // Support "libc:localtime" and "libc:*" to access the legacy
28
+ // localtime and UTC support respectively from the C library.
29
+ if (name.compare(0, 5, "libc:") == 0) {
30
+ return std::unique_ptr<TimeZoneIf>(new TimeZoneLibC(name.substr(5)));
31
+ }
32
+
33
+ // Otherwise use the "zoneinfo" implementation by default.
34
+ std::unique_ptr<TimeZoneInfo> tz(new TimeZoneInfo);
35
+ if (!tz->Load(name)) tz.reset();
36
+ return std::unique_ptr<TimeZoneIf>(tz.release());
37
+ }
38
+
39
+ // Defined out-of-line to avoid emitting a weak vtable in all TUs.
40
+ TimeZoneIf::~TimeZoneIf() {}
41
+
42
+ } // namespace cctz
43
+ } // namespace time_internal
44
+ ABSL_NAMESPACE_END
45
+ } // namespace absl
@@ -0,0 +1,76 @@
1
+ // Copyright 2016 Google Inc. All Rights Reserved.
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_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_
16
+ #define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_
17
+
18
+ #include <chrono>
19
+ #include <cstdint>
20
+ #include <memory>
21
+ #include <string>
22
+
23
+ #include "absl/base/config.h"
24
+ #include "absl/time/internal/cctz/include/cctz/civil_time.h"
25
+ #include "absl/time/internal/cctz/include/cctz/time_zone.h"
26
+
27
+ namespace absl {
28
+ ABSL_NAMESPACE_BEGIN
29
+ namespace time_internal {
30
+ namespace cctz {
31
+
32
+ // A simple interface used to hide time-zone complexities from time_zone::Impl.
33
+ // Subclasses implement the functions for civil-time conversions in the zone.
34
+ class TimeZoneIf {
35
+ public:
36
+ // A factory function for TimeZoneIf implementations.
37
+ static std::unique_ptr<TimeZoneIf> Load(const std::string& name);
38
+
39
+ virtual ~TimeZoneIf();
40
+
41
+ virtual time_zone::absolute_lookup BreakTime(
42
+ const time_point<seconds>& tp) const = 0;
43
+ virtual time_zone::civil_lookup MakeTime(const civil_second& cs) const = 0;
44
+
45
+ virtual bool NextTransition(const time_point<seconds>& tp,
46
+ time_zone::civil_transition* trans) const = 0;
47
+ virtual bool PrevTransition(const time_point<seconds>& tp,
48
+ time_zone::civil_transition* trans) const = 0;
49
+
50
+ virtual std::string Version() const = 0;
51
+ virtual std::string Description() const = 0;
52
+
53
+ protected:
54
+ TimeZoneIf() {}
55
+ };
56
+
57
+ // Convert between time_point<seconds> and a count of seconds since the
58
+ // Unix epoch. We assume that the std::chrono::system_clock and the
59
+ // Unix clock are second aligned, but not that they share an epoch.
60
+ inline std::int_fast64_t ToUnixSeconds(const time_point<seconds>& tp) {
61
+ return (tp - std::chrono::time_point_cast<seconds>(
62
+ std::chrono::system_clock::from_time_t(0)))
63
+ .count();
64
+ }
65
+ inline time_point<seconds> FromUnixSeconds(std::int_fast64_t t) {
66
+ return std::chrono::time_point_cast<seconds>(
67
+ std::chrono::system_clock::from_time_t(0)) +
68
+ seconds(t);
69
+ }
70
+
71
+ } // namespace cctz
72
+ } // namespace time_internal
73
+ ABSL_NAMESPACE_END
74
+ } // namespace absl
75
+
76
+ #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_
@@ -0,0 +1,121 @@
1
+ // Copyright 2016 Google Inc. All Rights Reserved.
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
+ #include "time_zone_impl.h"
16
+
17
+ #include <deque>
18
+ #include <mutex>
19
+ #include <string>
20
+ #include <unordered_map>
21
+ #include <utility>
22
+
23
+ #include "absl/base/config.h"
24
+ #include "time_zone_fixed.h"
25
+
26
+ namespace absl {
27
+ ABSL_NAMESPACE_BEGIN
28
+ namespace time_internal {
29
+ namespace cctz {
30
+
31
+ namespace {
32
+
33
+ // time_zone::Impls are linked into a map to support fast lookup by name.
34
+ using TimeZoneImplByName =
35
+ std::unordered_map<std::string, const time_zone::Impl*>;
36
+ TimeZoneImplByName* time_zone_map = nullptr;
37
+
38
+ // Mutual exclusion for time_zone_map.
39
+ std::mutex& TimeZoneMutex() {
40
+ // This mutex is intentionally "leaked" to avoid the static deinitialization
41
+ // order fiasco (std::mutex's destructor is not trivial on many platforms).
42
+ static std::mutex* time_zone_mutex = new std::mutex;
43
+ return *time_zone_mutex;
44
+ }
45
+
46
+ } // namespace
47
+
48
+ time_zone time_zone::Impl::UTC() { return time_zone(UTCImpl()); }
49
+
50
+ bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) {
51
+ const time_zone::Impl* const utc_impl = UTCImpl();
52
+
53
+ // First check for UTC (which is never a key in time_zone_map).
54
+ auto offset = seconds::zero();
55
+ if (FixedOffsetFromName(name, &offset) && offset == seconds::zero()) {
56
+ *tz = time_zone(utc_impl);
57
+ return true;
58
+ }
59
+
60
+ // Then check, under a shared lock, whether the time zone has already
61
+ // been loaded. This is the common path. TODO: Move to shared_mutex.
62
+ {
63
+ std::lock_guard<std::mutex> lock(TimeZoneMutex());
64
+ if (time_zone_map != nullptr) {
65
+ TimeZoneImplByName::const_iterator itr = time_zone_map->find(name);
66
+ if (itr != time_zone_map->end()) {
67
+ *tz = time_zone(itr->second);
68
+ return itr->second != utc_impl;
69
+ }
70
+ }
71
+ }
72
+
73
+ // Now check again, under an exclusive lock.
74
+ std::lock_guard<std::mutex> lock(TimeZoneMutex());
75
+ if (time_zone_map == nullptr) time_zone_map = new TimeZoneImplByName;
76
+ const Impl*& impl = (*time_zone_map)[name];
77
+ if (impl == nullptr) {
78
+ // The first thread in loads the new time zone.
79
+ Impl* new_impl = new Impl(name);
80
+ new_impl->zone_ = TimeZoneIf::Load(new_impl->name_);
81
+ if (new_impl->zone_ == nullptr) {
82
+ delete new_impl; // free the nascent Impl
83
+ impl = utc_impl; // and fallback to UTC
84
+ } else {
85
+ impl = new_impl; // install new time zone
86
+ }
87
+ }
88
+ *tz = time_zone(impl);
89
+ return impl != utc_impl;
90
+ }
91
+
92
+ void time_zone::Impl::ClearTimeZoneMapTestOnly() {
93
+ std::lock_guard<std::mutex> lock(TimeZoneMutex());
94
+ if (time_zone_map != nullptr) {
95
+ // Existing time_zone::Impl* entries are in the wild, so we can't delete
96
+ // them. Instead, we move them to a private container, where they are
97
+ // logically unreachable but not "leaked". Future requests will result
98
+ // in reloading the data.
99
+ static auto* cleared = new std::deque<const time_zone::Impl*>;
100
+ for (const auto& element : *time_zone_map) {
101
+ cleared->push_back(element.second);
102
+ }
103
+ time_zone_map->clear();
104
+ }
105
+ }
106
+
107
+ time_zone::Impl::Impl(const std::string& name) : name_(name) {}
108
+
109
+ const time_zone::Impl* time_zone::Impl::UTCImpl() {
110
+ static Impl* utc_impl = [] {
111
+ Impl* impl = new Impl("UTC");
112
+ impl->zone_ = TimeZoneIf::Load(impl->name_); // never fails
113
+ return impl;
114
+ }();
115
+ return utc_impl;
116
+ }
117
+
118
+ } // namespace cctz
119
+ } // namespace time_internal
120
+ ABSL_NAMESPACE_END
121
+ } // namespace absl
@@ -0,0 +1,93 @@
1
+ // Copyright 2016 Google Inc. All Rights Reserved.
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_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_
16
+ #define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_
17
+
18
+ #include <memory>
19
+ #include <string>
20
+
21
+ #include "absl/base/config.h"
22
+ #include "absl/time/internal/cctz/include/cctz/civil_time.h"
23
+ #include "absl/time/internal/cctz/include/cctz/time_zone.h"
24
+ #include "time_zone_if.h"
25
+ #include "time_zone_info.h"
26
+
27
+ namespace absl {
28
+ ABSL_NAMESPACE_BEGIN
29
+ namespace time_internal {
30
+ namespace cctz {
31
+
32
+ // time_zone::Impl is the internal object referenced by a cctz::time_zone.
33
+ class time_zone::Impl {
34
+ public:
35
+ // The UTC time zone. Also used for other time zones that fail to load.
36
+ static time_zone UTC();
37
+
38
+ // Load a named time zone. Returns false if the name is invalid, or if
39
+ // some other kind of error occurs. Note that loading "UTC" never fails.
40
+ static bool LoadTimeZone(const std::string& name, time_zone* tz);
41
+
42
+ // Clears the map of cached time zones. Primarily for use in benchmarks
43
+ // that gauge the performance of loading/parsing the time-zone data.
44
+ static void ClearTimeZoneMapTestOnly();
45
+
46
+ // The primary key is the time-zone ID (e.g., "America/New_York").
47
+ const std::string& Name() const {
48
+ // TODO: It would nice if the zoneinfo data included the zone name.
49
+ return name_;
50
+ }
51
+
52
+ // Breaks a time_point down to civil-time components in this time zone.
53
+ time_zone::absolute_lookup BreakTime(const time_point<seconds>& tp) const {
54
+ return zone_->BreakTime(tp);
55
+ }
56
+
57
+ // Converts the civil-time components in this time zone into a time_point.
58
+ // That is, the opposite of BreakTime(). The requested civil time may be
59
+ // ambiguous or illegal due to a change of UTC offset.
60
+ time_zone::civil_lookup MakeTime(const civil_second& cs) const {
61
+ return zone_->MakeTime(cs);
62
+ }
63
+
64
+ // Finds the time of the next/previous offset change in this time zone.
65
+ bool NextTransition(const time_point<seconds>& tp,
66
+ time_zone::civil_transition* trans) const {
67
+ return zone_->NextTransition(tp, trans);
68
+ }
69
+ bool PrevTransition(const time_point<seconds>& tp,
70
+ time_zone::civil_transition* trans) const {
71
+ return zone_->PrevTransition(tp, trans);
72
+ }
73
+
74
+ // Returns an implementation-defined version std::string for this time zone.
75
+ std::string Version() const { return zone_->Version(); }
76
+
77
+ // Returns an implementation-defined description of this time zone.
78
+ std::string Description() const { return zone_->Description(); }
79
+
80
+ private:
81
+ explicit Impl(const std::string& name);
82
+ static const Impl* UTCImpl();
83
+
84
+ const std::string name_;
85
+ std::unique_ptr<TimeZoneIf> zone_;
86
+ };
87
+
88
+ } // namespace cctz
89
+ } // namespace time_internal
90
+ ABSL_NAMESPACE_END
91
+ } // namespace absl
92
+
93
+ #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_
@@ -0,0 +1,958 @@
1
+ // Copyright 2016 Google Inc. All Rights Reserved.
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
+ // This file implements the TimeZoneIf interface using the "zoneinfo"
16
+ // data provided by the IANA Time Zone Database (i.e., the only real game
17
+ // in town).
18
+ //
19
+ // TimeZoneInfo represents the history of UTC-offset changes within a time
20
+ // zone. Most changes are due to daylight-saving rules, but occasionally
21
+ // shifts are made to the time-zone's base offset. The database only attempts
22
+ // to be definitive for times since 1970, so be wary of local-time conversions
23
+ // before that. Also, rule and zone-boundary changes are made at the whim
24
+ // of governments, so the conversion of future times needs to be taken with
25
+ // a grain of salt.
26
+ //
27
+ // For more information see tzfile(5), http://www.iana.org/time-zones, or
28
+ // https://en.wikipedia.org/wiki/Zoneinfo.
29
+ //
30
+ // Note that we assume the proleptic Gregorian calendar and 60-second
31
+ // minutes throughout.
32
+
33
+ #include "time_zone_info.h"
34
+
35
+ #include <algorithm>
36
+ #include <cassert>
37
+ #include <chrono>
38
+ #include <cstdint>
39
+ #include <cstdio>
40
+ #include <cstdlib>
41
+ #include <cstring>
42
+ #include <functional>
43
+ #include <iostream>
44
+ #include <memory>
45
+ #include <sstream>
46
+ #include <string>
47
+
48
+ #include "absl/base/config.h"
49
+ #include "absl/time/internal/cctz/include/cctz/civil_time.h"
50
+ #include "time_zone_fixed.h"
51
+ #include "time_zone_posix.h"
52
+
53
+ namespace absl {
54
+ ABSL_NAMESPACE_BEGIN
55
+ namespace time_internal {
56
+ namespace cctz {
57
+
58
+ namespace {
59
+
60
+ inline bool IsLeap(year_t year) {
61
+ return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
62
+ }
63
+
64
+ // The number of days in non-leap and leap years respectively.
65
+ const std::int_least32_t kDaysPerYear[2] = {365, 366};
66
+
67
+ // The day offsets of the beginning of each (1-based) month in non-leap and
68
+ // leap years respectively (e.g., 335 days before December in a leap year).
69
+ const std::int_least16_t kMonthOffsets[2][1 + 12 + 1] = {
70
+ {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
71
+ {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},
72
+ };
73
+
74
+ // We reject leap-second encoded zoneinfo and so assume 60-second minutes.
75
+ const std::int_least32_t kSecsPerDay = 24 * 60 * 60;
76
+
77
+ // 400-year chunks always have 146097 days (20871 weeks).
78
+ const std::int_least64_t kSecsPer400Years = 146097LL * kSecsPerDay;
79
+
80
+ // Like kDaysPerYear[] but scaled up by a factor of kSecsPerDay.
81
+ const std::int_least32_t kSecsPerYear[2] = {
82
+ 365 * kSecsPerDay,
83
+ 366 * kSecsPerDay,
84
+ };
85
+
86
+ // Single-byte, unsigned numeric values are encoded directly.
87
+ inline std::uint_fast8_t Decode8(const char* cp) {
88
+ return static_cast<std::uint_fast8_t>(*cp) & 0xff;
89
+ }
90
+
91
+ // Multi-byte, numeric values are encoded using a MSB first,
92
+ // twos-complement representation. These helpers decode, from
93
+ // the given address, 4-byte and 8-byte values respectively.
94
+ // Note: If int_fastXX_t == intXX_t and this machine is not
95
+ // twos complement, then there will be at least one input value
96
+ // we cannot represent.
97
+ std::int_fast32_t Decode32(const char* cp) {
98
+ std::uint_fast32_t v = 0;
99
+ for (int i = 0; i != (32 / 8); ++i) v = (v << 8) | Decode8(cp++);
100
+ const std::int_fast32_t s32max = 0x7fffffff;
101
+ const auto s32maxU = static_cast<std::uint_fast32_t>(s32max);
102
+ if (v <= s32maxU) return static_cast<std::int_fast32_t>(v);
103
+ return static_cast<std::int_fast32_t>(v - s32maxU - 1) - s32max - 1;
104
+ }
105
+
106
+ std::int_fast64_t Decode64(const char* cp) {
107
+ std::uint_fast64_t v = 0;
108
+ for (int i = 0; i != (64 / 8); ++i) v = (v << 8) | Decode8(cp++);
109
+ const std::int_fast64_t s64max = 0x7fffffffffffffff;
110
+ const auto s64maxU = static_cast<std::uint_fast64_t>(s64max);
111
+ if (v <= s64maxU) return static_cast<std::int_fast64_t>(v);
112
+ return static_cast<std::int_fast64_t>(v - s64maxU - 1) - s64max - 1;
113
+ }
114
+
115
+ // Generate a year-relative offset for a PosixTransition.
116
+ std::int_fast64_t TransOffset(bool leap_year, int jan1_weekday,
117
+ const PosixTransition& pt) {
118
+ std::int_fast64_t days = 0;
119
+ switch (pt.date.fmt) {
120
+ case PosixTransition::J: {
121
+ days = pt.date.j.day;
122
+ if (!leap_year || days < kMonthOffsets[1][3]) days -= 1;
123
+ break;
124
+ }
125
+ case PosixTransition::N: {
126
+ days = pt.date.n.day;
127
+ break;
128
+ }
129
+ case PosixTransition::M: {
130
+ const bool last_week = (pt.date.m.week == 5);
131
+ days = kMonthOffsets[leap_year][pt.date.m.month + last_week];
132
+ const std::int_fast64_t weekday = (jan1_weekday + days) % 7;
133
+ if (last_week) {
134
+ days -= (weekday + 7 - 1 - pt.date.m.weekday) % 7 + 1;
135
+ } else {
136
+ days += (pt.date.m.weekday + 7 - weekday) % 7;
137
+ days += (pt.date.m.week - 1) * 7;
138
+ }
139
+ break;
140
+ }
141
+ }
142
+ return (days * kSecsPerDay) + pt.time.offset;
143
+ }
144
+
145
+ inline time_zone::civil_lookup MakeUnique(const time_point<seconds>& tp) {
146
+ time_zone::civil_lookup cl;
147
+ cl.kind = time_zone::civil_lookup::UNIQUE;
148
+ cl.pre = cl.trans = cl.post = tp;
149
+ return cl;
150
+ }
151
+
152
+ inline time_zone::civil_lookup MakeUnique(std::int_fast64_t unix_time) {
153
+ return MakeUnique(FromUnixSeconds(unix_time));
154
+ }
155
+
156
+ inline time_zone::civil_lookup MakeSkipped(const Transition& tr,
157
+ const civil_second& cs) {
158
+ time_zone::civil_lookup cl;
159
+ cl.kind = time_zone::civil_lookup::SKIPPED;
160
+ cl.pre = FromUnixSeconds(tr.unix_time - 1 + (cs - tr.prev_civil_sec));
161
+ cl.trans = FromUnixSeconds(tr.unix_time);
162
+ cl.post = FromUnixSeconds(tr.unix_time - (tr.civil_sec - cs));
163
+ return cl;
164
+ }
165
+
166
+ inline time_zone::civil_lookup MakeRepeated(const Transition& tr,
167
+ const civil_second& cs) {
168
+ time_zone::civil_lookup cl;
169
+ cl.kind = time_zone::civil_lookup::REPEATED;
170
+ cl.pre = FromUnixSeconds(tr.unix_time - 1 - (tr.prev_civil_sec - cs));
171
+ cl.trans = FromUnixSeconds(tr.unix_time);
172
+ cl.post = FromUnixSeconds(tr.unix_time + (cs - tr.civil_sec));
173
+ return cl;
174
+ }
175
+
176
+ inline civil_second YearShift(const civil_second& cs, year_t shift) {
177
+ return civil_second(cs.year() + shift, cs.month(), cs.day(), cs.hour(),
178
+ cs.minute(), cs.second());
179
+ }
180
+
181
+ } // namespace
182
+
183
+ // What (no leap-seconds) UTC+seconds zoneinfo would look like.
184
+ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) {
185
+ transition_types_.resize(1);
186
+ TransitionType& tt(transition_types_.back());
187
+ tt.utc_offset = static_cast<std::int_least32_t>(offset.count());
188
+ tt.is_dst = false;
189
+ tt.abbr_index = 0;
190
+
191
+ // We temporarily add some redundant, contemporary (2013 through 2023)
192
+ // transitions for performance reasons. See TimeZoneInfo::LocalTime().
193
+ // TODO: Fix the performance issue and remove the extra transitions.
194
+ transitions_.clear();
195
+ transitions_.reserve(12);
196
+ for (const std::int_fast64_t unix_time : {
197
+ -(1LL << 59), // BIG_BANG
198
+ 1356998400LL, // 2013-01-01T00:00:00+00:00
199
+ 1388534400LL, // 2014-01-01T00:00:00+00:00
200
+ 1420070400LL, // 2015-01-01T00:00:00+00:00
201
+ 1451606400LL, // 2016-01-01T00:00:00+00:00
202
+ 1483228800LL, // 2017-01-01T00:00:00+00:00
203
+ 1514764800LL, // 2018-01-01T00:00:00+00:00
204
+ 1546300800LL, // 2019-01-01T00:00:00+00:00
205
+ 1577836800LL, // 2020-01-01T00:00:00+00:00
206
+ 1609459200LL, // 2021-01-01T00:00:00+00:00
207
+ 1640995200LL, // 2022-01-01T00:00:00+00:00
208
+ 1672531200LL, // 2023-01-01T00:00:00+00:00
209
+ 2147483647LL, // 2^31 - 1
210
+ }) {
211
+ Transition& tr(*transitions_.emplace(transitions_.end()));
212
+ tr.unix_time = unix_time;
213
+ tr.type_index = 0;
214
+ tr.civil_sec = LocalTime(tr.unix_time, tt).cs;
215
+ tr.prev_civil_sec = tr.civil_sec - 1;
216
+ }
217
+
218
+ default_transition_type_ = 0;
219
+ abbreviations_ = FixedOffsetToAbbr(offset);
220
+ abbreviations_.append(1, '\0'); // add NUL
221
+ future_spec_.clear(); // never needed for a fixed-offset zone
222
+ extended_ = false;
223
+
224
+ tt.civil_max = LocalTime(seconds::max().count(), tt).cs;
225
+ tt.civil_min = LocalTime(seconds::min().count(), tt).cs;
226
+
227
+ transitions_.shrink_to_fit();
228
+ return true;
229
+ }
230
+
231
+ // Builds the in-memory header using the raw bytes from the file.
232
+ bool TimeZoneInfo::Header::Build(const tzhead& tzh) {
233
+ std::int_fast32_t v;
234
+ if ((v = Decode32(tzh.tzh_timecnt)) < 0) return false;
235
+ timecnt = static_cast<std::size_t>(v);
236
+ if ((v = Decode32(tzh.tzh_typecnt)) < 0) return false;
237
+ typecnt = static_cast<std::size_t>(v);
238
+ if ((v = Decode32(tzh.tzh_charcnt)) < 0) return false;
239
+ charcnt = static_cast<std::size_t>(v);
240
+ if ((v = Decode32(tzh.tzh_leapcnt)) < 0) return false;
241
+ leapcnt = static_cast<std::size_t>(v);
242
+ if ((v = Decode32(tzh.tzh_ttisstdcnt)) < 0) return false;
243
+ ttisstdcnt = static_cast<std::size_t>(v);
244
+ if ((v = Decode32(tzh.tzh_ttisutcnt)) < 0) return false;
245
+ ttisutcnt = static_cast<std::size_t>(v);
246
+ return true;
247
+ }
248
+
249
+ // How many bytes of data are associated with this header. The result
250
+ // depends upon whether this is a section with 4-byte or 8-byte times.
251
+ std::size_t TimeZoneInfo::Header::DataLength(std::size_t time_len) const {
252
+ std::size_t len = 0;
253
+ len += (time_len + 1) * timecnt; // unix_time + type_index
254
+ len += (4 + 1 + 1) * typecnt; // utc_offset + is_dst + abbr_index
255
+ len += 1 * charcnt; // abbreviations
256
+ len += (time_len + 4) * leapcnt; // leap-time + TAI-UTC
257
+ len += 1 * ttisstdcnt; // UTC/local indicators
258
+ len += 1 * ttisutcnt; // standard/wall indicators
259
+ return len;
260
+ }
261
+
262
+ // Check that the TransitionType has the expected offset/is_dst/abbreviation.
263
+ void TimeZoneInfo::CheckTransition(const std::string& name,
264
+ const TransitionType& tt,
265
+ std::int_fast32_t offset, bool is_dst,
266
+ const std::string& abbr) const {
267
+ if (tt.utc_offset != offset || tt.is_dst != is_dst ||
268
+ &abbreviations_[tt.abbr_index] != abbr) {
269
+ std::clog << name << ": Transition"
270
+ << " offset=" << tt.utc_offset << "/"
271
+ << (tt.is_dst ? "DST" : "STD")
272
+ << "/abbr=" << &abbreviations_[tt.abbr_index]
273
+ << " does not match POSIX spec '" << future_spec_ << "'\n";
274
+ }
275
+ }
276
+
277
+ // zic(8) can generate no-op transitions when a zone changes rules at an
278
+ // instant when there is actually no discontinuity. So we check whether
279
+ // two transitions have equivalent types (same offset/is_dst/abbr).
280
+ bool TimeZoneInfo::EquivTransitions(std::uint_fast8_t tt1_index,
281
+ std::uint_fast8_t tt2_index) const {
282
+ if (tt1_index == tt2_index) return true;
283
+ const TransitionType& tt1(transition_types_[tt1_index]);
284
+ const TransitionType& tt2(transition_types_[tt2_index]);
285
+ if (tt1.is_dst != tt2.is_dst) return false;
286
+ if (tt1.utc_offset != tt2.utc_offset) return false;
287
+ if (tt1.abbr_index != tt2.abbr_index) return false;
288
+ return true;
289
+ }
290
+
291
+ // Use the POSIX-TZ-environment-variable-style string to handle times
292
+ // in years after the last transition stored in the zoneinfo data.
293
+ void TimeZoneInfo::ExtendTransitions(const std::string& name,
294
+ const Header& hdr) {
295
+ extended_ = false;
296
+ bool extending = !future_spec_.empty();
297
+
298
+ PosixTimeZone posix;
299
+ if (extending && !ParsePosixSpec(future_spec_, &posix)) {
300
+ std::clog << name << ": Failed to parse '" << future_spec_ << "'\n";
301
+ extending = false;
302
+ }
303
+
304
+ if (extending && posix.dst_abbr.empty()) { // std only
305
+ // The future specification should match the last/default transition,
306
+ // and that means that handling the future will fall out naturally.
307
+ std::uint_fast8_t index = default_transition_type_;
308
+ if (hdr.timecnt != 0) index = transitions_[hdr.timecnt - 1].type_index;
309
+ const TransitionType& tt(transition_types_[index]);
310
+ CheckTransition(name, tt, posix.std_offset, false, posix.std_abbr);
311
+ extending = false;
312
+ }
313
+
314
+ if (extending && hdr.timecnt < 2) {
315
+ std::clog << name << ": Too few transitions for POSIX spec\n";
316
+ extending = false;
317
+ }
318
+
319
+ if (!extending) {
320
+ // Ensure that there is always a transition in the second half of the
321
+ // time line (the BIG_BANG transition is in the first half) so that the
322
+ // signed difference between a civil_second and the civil_second of its
323
+ // previous transition is always representable, without overflow.
324
+ const Transition& last(transitions_.back());
325
+ if (last.unix_time < 0) {
326
+ const std::uint_fast8_t type_index = last.type_index;
327
+ Transition& tr(*transitions_.emplace(transitions_.end()));
328
+ tr.unix_time = 2147483647; // 2038-01-19T03:14:07+00:00
329
+ tr.type_index = type_index;
330
+ }
331
+ return; // last transition wins
332
+ }
333
+
334
+ // Extend the transitions for an additional 400 years using the
335
+ // future specification. Years beyond those can be handled by
336
+ // mapping back to a cycle-equivalent year within that range.
337
+ // zic(8) should probably do this so that we don't have to.
338
+ // TODO: Reduce the extension by the number of compatible
339
+ // transitions already in place.
340
+ transitions_.reserve(hdr.timecnt + 400 * 2 + 1);
341
+ transitions_.resize(hdr.timecnt + 400 * 2);
342
+ extended_ = true;
343
+
344
+ // The future specification should match the last two transitions,
345
+ // and those transitions should have different is_dst flags. Note
346
+ // that nothing says the UTC offset used by the is_dst transition
347
+ // must be greater than that used by the !is_dst transition. (See
348
+ // Europe/Dublin, for example.)
349
+ const Transition* tr0 = &transitions_[hdr.timecnt - 1];
350
+ const Transition* tr1 = &transitions_[hdr.timecnt - 2];
351
+ const TransitionType* tt0 = &transition_types_[tr0->type_index];
352
+ const TransitionType* tt1 = &transition_types_[tr1->type_index];
353
+ const TransitionType& dst(tt0->is_dst ? *tt0 : *tt1);
354
+ const TransitionType& std(tt0->is_dst ? *tt1 : *tt0);
355
+ CheckTransition(name, dst, posix.dst_offset, true, posix.dst_abbr);
356
+ CheckTransition(name, std, posix.std_offset, false, posix.std_abbr);
357
+
358
+ // Add the transitions to tr1 and back to tr0 for each extra year.
359
+ last_year_ = LocalTime(tr0->unix_time, *tt0).cs.year();
360
+ bool leap_year = IsLeap(last_year_);
361
+ const civil_day jan1(last_year_, 1, 1);
362
+ std::int_fast64_t jan1_time = civil_second(jan1) - civil_second();
363
+ int jan1_weekday = (static_cast<int>(get_weekday(jan1)) + 1) % 7;
364
+ Transition* tr = &transitions_[hdr.timecnt]; // next trans to fill
365
+ if (LocalTime(tr1->unix_time, *tt1).cs.year() != last_year_) {
366
+ // Add a single extra transition to align to a calendar year.
367
+ transitions_.resize(transitions_.size() + 1);
368
+ assert(tr == &transitions_[hdr.timecnt]); // no reallocation
369
+ const PosixTransition& pt1(tt0->is_dst ? posix.dst_end : posix.dst_start);
370
+ std::int_fast64_t tr1_offset = TransOffset(leap_year, jan1_weekday, pt1);
371
+ tr->unix_time = jan1_time + tr1_offset - tt0->utc_offset;
372
+ tr++->type_index = tr1->type_index;
373
+ tr0 = &transitions_[hdr.timecnt];
374
+ tr1 = &transitions_[hdr.timecnt - 1];
375
+ tt0 = &transition_types_[tr0->type_index];
376
+ tt1 = &transition_types_[tr1->type_index];
377
+ }
378
+ const PosixTransition& pt1(tt0->is_dst ? posix.dst_end : posix.dst_start);
379
+ const PosixTransition& pt0(tt0->is_dst ? posix.dst_start : posix.dst_end);
380
+ for (const year_t limit = last_year_ + 400; last_year_ < limit;) {
381
+ last_year_ += 1; // an additional year of generated transitions
382
+ jan1_time += kSecsPerYear[leap_year];
383
+ jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % 7;
384
+ leap_year = !leap_year && IsLeap(last_year_);
385
+ std::int_fast64_t tr1_offset = TransOffset(leap_year, jan1_weekday, pt1);
386
+ tr->unix_time = jan1_time + tr1_offset - tt0->utc_offset;
387
+ tr++->type_index = tr1->type_index;
388
+ std::int_fast64_t tr0_offset = TransOffset(leap_year, jan1_weekday, pt0);
389
+ tr->unix_time = jan1_time + tr0_offset - tt1->utc_offset;
390
+ tr++->type_index = tr0->type_index;
391
+ }
392
+ assert(tr == &transitions_[0] + transitions_.size());
393
+ }
394
+
395
+ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
396
+ // Read and validate the header.
397
+ tzhead tzh;
398
+ if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false;
399
+ if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0)
400
+ return false;
401
+ Header hdr;
402
+ if (!hdr.Build(tzh)) return false;
403
+ std::size_t time_len = 4;
404
+ if (tzh.tzh_version[0] != '\0') {
405
+ // Skip the 4-byte data.
406
+ if (zip->Skip(hdr.DataLength(time_len)) != 0) return false;
407
+ // Read and validate the header for the 8-byte data.
408
+ if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false;
409
+ if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0)
410
+ return false;
411
+ if (tzh.tzh_version[0] == '\0') return false;
412
+ if (!hdr.Build(tzh)) return false;
413
+ time_len = 8;
414
+ }
415
+ if (hdr.typecnt == 0) return false;
416
+ if (hdr.leapcnt != 0) {
417
+ // This code assumes 60-second minutes so we do not want
418
+ // the leap-second encoded zoneinfo. We could reverse the
419
+ // compensation, but the "right" encoding is rarely used
420
+ // so currently we simply reject such data.
421
+ return false;
422
+ }
423
+ if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt) return false;
424
+ if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt) return false;
425
+
426
+ // Read the data into a local buffer.
427
+ std::size_t len = hdr.DataLength(time_len);
428
+ std::vector<char> tbuf(len);
429
+ if (zip->Read(tbuf.data(), len) != len) return false;
430
+ const char* bp = tbuf.data();
431
+
432
+ // Decode and validate the transitions.
433
+ transitions_.reserve(hdr.timecnt + 2); // We might add a couple.
434
+ transitions_.resize(hdr.timecnt);
435
+ for (std::size_t i = 0; i != hdr.timecnt; ++i) {
436
+ transitions_[i].unix_time = (time_len == 4) ? Decode32(bp) : Decode64(bp);
437
+ bp += time_len;
438
+ if (i != 0) {
439
+ // Check that the transitions are ordered by time (as zic guarantees).
440
+ if (!Transition::ByUnixTime()(transitions_[i - 1], transitions_[i]))
441
+ return false; // out of order
442
+ }
443
+ }
444
+ bool seen_type_0 = false;
445
+ for (std::size_t i = 0; i != hdr.timecnt; ++i) {
446
+ transitions_[i].type_index = Decode8(bp++);
447
+ if (transitions_[i].type_index >= hdr.typecnt) return false;
448
+ if (transitions_[i].type_index == 0) seen_type_0 = true;
449
+ }
450
+
451
+ // Decode and validate the transition types.
452
+ transition_types_.resize(hdr.typecnt);
453
+ for (std::size_t i = 0; i != hdr.typecnt; ++i) {
454
+ transition_types_[i].utc_offset =
455
+ static_cast<std::int_least32_t>(Decode32(bp));
456
+ if (transition_types_[i].utc_offset >= kSecsPerDay ||
457
+ transition_types_[i].utc_offset <= -kSecsPerDay)
458
+ return false;
459
+ bp += 4;
460
+ transition_types_[i].is_dst = (Decode8(bp++) != 0);
461
+ transition_types_[i].abbr_index = Decode8(bp++);
462
+ if (transition_types_[i].abbr_index >= hdr.charcnt) return false;
463
+ }
464
+
465
+ // Determine the before-first-transition type.
466
+ default_transition_type_ = 0;
467
+ if (seen_type_0 && hdr.timecnt != 0) {
468
+ std::uint_fast8_t index = 0;
469
+ if (transition_types_[0].is_dst) {
470
+ index = transitions_[0].type_index;
471
+ while (index != 0 && transition_types_[index].is_dst) --index;
472
+ }
473
+ while (index != hdr.typecnt && transition_types_[index].is_dst) ++index;
474
+ if (index != hdr.typecnt) default_transition_type_ = index;
475
+ }
476
+
477
+ // Copy all the abbreviations.
478
+ abbreviations_.assign(bp, hdr.charcnt);
479
+ bp += hdr.charcnt;
480
+
481
+ // Skip the unused portions. We've already dispensed with leap-second
482
+ // encoded zoneinfo. The ttisstd/ttisgmt indicators only apply when
483
+ // interpreting a POSIX spec that does not include start/end rules, and
484
+ // that isn't the case here (see "zic -p").
485
+ bp += (8 + 4) * hdr.leapcnt; // leap-time + TAI-UTC
486
+ bp += 1 * hdr.ttisstdcnt; // UTC/local indicators
487
+ bp += 1 * hdr.ttisutcnt; // standard/wall indicators
488
+ assert(bp == tbuf.data() + tbuf.size());
489
+
490
+ future_spec_.clear();
491
+ if (tzh.tzh_version[0] != '\0') {
492
+ // Snarf up the NL-enclosed future POSIX spec. Note
493
+ // that version '3' files utilize an extended format.
494
+ auto get_char = [](ZoneInfoSource* azip) -> int {
495
+ unsigned char ch; // all non-EOF results are positive
496
+ return (azip->Read(&ch, 1) == 1) ? ch : EOF;
497
+ };
498
+ if (get_char(zip) != '\n') return false;
499
+ for (int c = get_char(zip); c != '\n'; c = get_char(zip)) {
500
+ if (c == EOF) return false;
501
+ future_spec_.push_back(static_cast<char>(c));
502
+ }
503
+ }
504
+
505
+ // We don't check for EOF so that we're forwards compatible.
506
+
507
+ // If we did not find version information during the standard loading
508
+ // process (as of tzh_version '3' that is unsupported), then ask the
509
+ // ZoneInfoSource for any out-of-bound version std::string it may be privy to.
510
+ if (version_.empty()) {
511
+ version_ = zip->Version();
512
+ }
513
+
514
+ // Trim redundant transitions. zic may have added these to work around
515
+ // differences between the glibc and reference implementations (see
516
+ // zic.c:dontmerge) and the Qt library (see zic.c:WORK_AROUND_QTBUG_53071).
517
+ // For us, they just get in the way when we do future_spec_ extension.
518
+ while (hdr.timecnt > 1) {
519
+ if (!EquivTransitions(transitions_[hdr.timecnt - 1].type_index,
520
+ transitions_[hdr.timecnt - 2].type_index)) {
521
+ break;
522
+ }
523
+ hdr.timecnt -= 1;
524
+ }
525
+ transitions_.resize(hdr.timecnt);
526
+
527
+ // Ensure that there is always a transition in the first half of the
528
+ // time line (the second half is handled in ExtendTransitions()) so that
529
+ // the signed difference between a civil_second and the civil_second of
530
+ // its previous transition is always representable, without overflow.
531
+ // A contemporary zic will usually have already done this for us.
532
+ if (transitions_.empty() || transitions_.front().unix_time >= 0) {
533
+ Transition& tr(*transitions_.emplace(transitions_.begin()));
534
+ tr.unix_time = -(1LL << 59); // see tz/zic.c "BIG_BANG"
535
+ tr.type_index = default_transition_type_;
536
+ hdr.timecnt += 1;
537
+ }
538
+
539
+ // Extend the transitions using the future specification.
540
+ ExtendTransitions(name, hdr);
541
+
542
+ // Compute the local civil time for each transition and the preceding
543
+ // second. These will be used for reverse conversions in MakeTime().
544
+ const TransitionType* ttp = &transition_types_[default_transition_type_];
545
+ for (std::size_t i = 0; i != transitions_.size(); ++i) {
546
+ Transition& tr(transitions_[i]);
547
+ tr.prev_civil_sec = LocalTime(tr.unix_time, *ttp).cs - 1;
548
+ ttp = &transition_types_[tr.type_index];
549
+ tr.civil_sec = LocalTime(tr.unix_time, *ttp).cs;
550
+ if (i != 0) {
551
+ // Check that the transitions are ordered by civil time. Essentially
552
+ // this means that an offset change cannot cross another such change.
553
+ // No one does this in practice, and we depend on it in MakeTime().
554
+ if (!Transition::ByCivilTime()(transitions_[i - 1], tr))
555
+ return false; // out of order
556
+ }
557
+ }
558
+
559
+ // Compute the maximum/minimum civil times that can be converted to a
560
+ // time_point<seconds> for each of the zone's transition types.
561
+ for (auto& tt : transition_types_) {
562
+ tt.civil_max = LocalTime(seconds::max().count(), tt).cs;
563
+ tt.civil_min = LocalTime(seconds::min().count(), tt).cs;
564
+ }
565
+
566
+ transitions_.shrink_to_fit();
567
+ return true;
568
+ }
569
+
570
+ namespace {
571
+
572
+ // fopen(3) adaptor.
573
+ inline FILE* FOpen(const char* path, const char* mode) {
574
+ #if defined(_MSC_VER)
575
+ FILE* fp;
576
+ if (fopen_s(&fp, path, mode) != 0) fp = nullptr;
577
+ return fp;
578
+ #else
579
+ return fopen(path, mode); // TODO: Enable the close-on-exec flag.
580
+ #endif
581
+ }
582
+
583
+ // A stdio(3)-backed implementation of ZoneInfoSource.
584
+ class FileZoneInfoSource : public ZoneInfoSource {
585
+ public:
586
+ static std::unique_ptr<ZoneInfoSource> Open(const std::string& name);
587
+
588
+ std::size_t Read(void* ptr, std::size_t size) override {
589
+ size = std::min(size, len_);
590
+ std::size_t nread = fread(ptr, 1, size, fp_.get());
591
+ len_ -= nread;
592
+ return nread;
593
+ }
594
+ int Skip(std::size_t offset) override {
595
+ offset = std::min(offset, len_);
596
+ int rc = fseek(fp_.get(), static_cast<long>(offset), SEEK_CUR);
597
+ if (rc == 0) len_ -= offset;
598
+ return rc;
599
+ }
600
+ std::string Version() const override {
601
+ // TODO: It would nice if the zoneinfo data included the tzdb version.
602
+ return std::string();
603
+ }
604
+
605
+ protected:
606
+ explicit FileZoneInfoSource(
607
+ FILE* fp, std::size_t len = std::numeric_limits<std::size_t>::max())
608
+ : fp_(fp, fclose), len_(len) {}
609
+
610
+ private:
611
+ std::unique_ptr<FILE, int (*)(FILE*)> fp_;
612
+ std::size_t len_;
613
+ };
614
+
615
+ std::unique_ptr<ZoneInfoSource> FileZoneInfoSource::Open(
616
+ const std::string& name) {
617
+ // Use of the "file:" prefix is intended for testing purposes only.
618
+ const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0;
619
+
620
+ // Map the time-zone name to a path name.
621
+ std::string path;
622
+ if (pos == name.size() || name[pos] != '/') {
623
+ const char* tzdir = "/usr/share/zoneinfo";
624
+ char* tzdir_env = nullptr;
625
+ #if defined(_MSC_VER)
626
+ _dupenv_s(&tzdir_env, nullptr, "TZDIR");
627
+ #else
628
+ tzdir_env = std::getenv("TZDIR");
629
+ #endif
630
+ if (tzdir_env && *tzdir_env) tzdir = tzdir_env;
631
+ path += tzdir;
632
+ path += '/';
633
+ #if defined(_MSC_VER)
634
+ free(tzdir_env);
635
+ #endif
636
+ }
637
+ path.append(name, pos, std::string::npos);
638
+
639
+ // Open the zoneinfo file.
640
+ FILE* fp = FOpen(path.c_str(), "rb");
641
+ if (fp == nullptr) return nullptr;
642
+ std::size_t length = 0;
643
+ if (fseek(fp, 0, SEEK_END) == 0) {
644
+ long offset = ftell(fp);
645
+ if (offset >= 0) {
646
+ length = static_cast<std::size_t>(offset);
647
+ }
648
+ rewind(fp);
649
+ }
650
+ return std::unique_ptr<ZoneInfoSource>(new FileZoneInfoSource(fp, length));
651
+ }
652
+
653
+ class AndroidZoneInfoSource : public FileZoneInfoSource {
654
+ public:
655
+ static std::unique_ptr<ZoneInfoSource> Open(const std::string& name);
656
+ std::string Version() const override { return version_; }
657
+
658
+ private:
659
+ explicit AndroidZoneInfoSource(FILE* fp, std::size_t len, const char* vers)
660
+ : FileZoneInfoSource(fp, len), version_(vers) {}
661
+ std::string version_;
662
+ };
663
+
664
+ std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open(
665
+ const std::string& name) {
666
+ // Use of the "file:" prefix is intended for testing purposes only.
667
+ const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0;
668
+
669
+ // See Android's libc/tzcode/bionic.cpp for additional information.
670
+ for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata",
671
+ "/system/usr/share/zoneinfo/tzdata"}) {
672
+ std::unique_ptr<FILE, int (*)(FILE*)> fp(FOpen(tzdata, "rb"), fclose);
673
+ if (fp.get() == nullptr) continue;
674
+
675
+ char hbuf[24]; // covers header.zonetab_offset too
676
+ if (fread(hbuf, 1, sizeof(hbuf), fp.get()) != sizeof(hbuf)) continue;
677
+ if (strncmp(hbuf, "tzdata", 6) != 0) continue;
678
+ const char* vers = (hbuf[11] == '\0') ? hbuf + 6 : "";
679
+ const std::int_fast32_t index_offset = Decode32(hbuf + 12);
680
+ const std::int_fast32_t data_offset = Decode32(hbuf + 16);
681
+ if (index_offset < 0 || data_offset < index_offset) continue;
682
+ if (fseek(fp.get(), static_cast<long>(index_offset), SEEK_SET) != 0)
683
+ continue;
684
+
685
+ char ebuf[52]; // covers entry.unused too
686
+ const std::size_t index_size =
687
+ static_cast<std::size_t>(data_offset - index_offset);
688
+ const std::size_t zonecnt = index_size / sizeof(ebuf);
689
+ if (zonecnt * sizeof(ebuf) != index_size) continue;
690
+ for (std::size_t i = 0; i != zonecnt; ++i) {
691
+ if (fread(ebuf, 1, sizeof(ebuf), fp.get()) != sizeof(ebuf)) break;
692
+ const std::int_fast32_t start = data_offset + Decode32(ebuf + 40);
693
+ const std::int_fast32_t length = Decode32(ebuf + 44);
694
+ if (start < 0 || length < 0) break;
695
+ ebuf[40] = '\0'; // ensure zone name is NUL terminated
696
+ if (strcmp(name.c_str() + pos, ebuf) == 0) {
697
+ if (fseek(fp.get(), static_cast<long>(start), SEEK_SET) != 0) break;
698
+ return std::unique_ptr<ZoneInfoSource>(new AndroidZoneInfoSource(
699
+ fp.release(), static_cast<std::size_t>(length), vers));
700
+ }
701
+ }
702
+ }
703
+
704
+ return nullptr;
705
+ }
706
+
707
+ } // namespace
708
+
709
+ bool TimeZoneInfo::Load(const std::string& name) {
710
+ // We can ensure that the loading of UTC or any other fixed-offset
711
+ // zone never fails because the simple, fixed-offset state can be
712
+ // internally generated. Note that this depends on our choice to not
713
+ // accept leap-second encoded ("right") zoneinfo.
714
+ auto offset = seconds::zero();
715
+ if (FixedOffsetFromName(name, &offset)) {
716
+ return ResetToBuiltinUTC(offset);
717
+ }
718
+
719
+ // Find and use a ZoneInfoSource to load the named zone.
720
+ auto zip = cctz_extension::zone_info_source_factory(
721
+ name, [](const std::string& name) -> std::unique_ptr<ZoneInfoSource> {
722
+ if (auto zip = FileZoneInfoSource::Open(name)) return zip;
723
+ if (auto zip = AndroidZoneInfoSource::Open(name)) return zip;
724
+ return nullptr;
725
+ });
726
+ return zip != nullptr && Load(name, zip.get());
727
+ }
728
+
729
+ // BreakTime() translation for a particular transition type.
730
+ time_zone::absolute_lookup TimeZoneInfo::LocalTime(
731
+ std::int_fast64_t unix_time, const TransitionType& tt) const {
732
+ // A civil time in "+offset" looks like (time+offset) in UTC.
733
+ // Note: We perform two additions in the civil_second domain to
734
+ // sidestep the chance of overflow in (unix_time + tt.utc_offset).
735
+ return {(civil_second() + unix_time) + tt.utc_offset, tt.utc_offset,
736
+ tt.is_dst, &abbreviations_[tt.abbr_index]};
737
+ }
738
+
739
+ // BreakTime() translation for a particular transition.
740
+ time_zone::absolute_lookup TimeZoneInfo::LocalTime(std::int_fast64_t unix_time,
741
+ const Transition& tr) const {
742
+ const TransitionType& tt = transition_types_[tr.type_index];
743
+ // Note: (unix_time - tr.unix_time) will never overflow as we
744
+ // have ensured that there is always a "nearby" transition.
745
+ return {tr.civil_sec + (unix_time - tr.unix_time), // TODO: Optimize.
746
+ tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]};
747
+ }
748
+
749
+ // MakeTime() translation with a conversion-preserving +N * 400-year shift.
750
+ time_zone::civil_lookup TimeZoneInfo::TimeLocal(const civil_second& cs,
751
+ year_t c4_shift) const {
752
+ assert(last_year_ - 400 < cs.year() && cs.year() <= last_year_);
753
+ time_zone::civil_lookup cl = MakeTime(cs);
754
+ if (c4_shift > seconds::max().count() / kSecsPer400Years) {
755
+ cl.pre = cl.trans = cl.post = time_point<seconds>::max();
756
+ } else {
757
+ const auto offset = seconds(c4_shift * kSecsPer400Years);
758
+ const auto limit = time_point<seconds>::max() - offset;
759
+ for (auto* tp : {&cl.pre, &cl.trans, &cl.post}) {
760
+ if (*tp > limit) {
761
+ *tp = time_point<seconds>::max();
762
+ } else {
763
+ *tp += offset;
764
+ }
765
+ }
766
+ }
767
+ return cl;
768
+ }
769
+
770
+ time_zone::absolute_lookup TimeZoneInfo::BreakTime(
771
+ const time_point<seconds>& tp) const {
772
+ std::int_fast64_t unix_time = ToUnixSeconds(tp);
773
+ const std::size_t timecnt = transitions_.size();
774
+ assert(timecnt != 0); // We always add a transition.
775
+
776
+ if (unix_time < transitions_[0].unix_time) {
777
+ return LocalTime(unix_time, transition_types_[default_transition_type_]);
778
+ }
779
+ if (unix_time >= transitions_[timecnt - 1].unix_time) {
780
+ // After the last transition. If we extended the transitions using
781
+ // future_spec_, shift back to a supported year using the 400-year
782
+ // cycle of calendaric equivalence and then compensate accordingly.
783
+ if (extended_) {
784
+ const std::int_fast64_t diff =
785
+ unix_time - transitions_[timecnt - 1].unix_time;
786
+ const year_t shift = diff / kSecsPer400Years + 1;
787
+ const auto d = seconds(shift * kSecsPer400Years);
788
+ time_zone::absolute_lookup al = BreakTime(tp - d);
789
+ al.cs = YearShift(al.cs, shift * 400);
790
+ return al;
791
+ }
792
+ return LocalTime(unix_time, transitions_[timecnt - 1]);
793
+ }
794
+
795
+ const std::size_t hint = local_time_hint_.load(std::memory_order_relaxed);
796
+ if (0 < hint && hint < timecnt) {
797
+ if (transitions_[hint - 1].unix_time <= unix_time) {
798
+ if (unix_time < transitions_[hint].unix_time) {
799
+ return LocalTime(unix_time, transitions_[hint - 1]);
800
+ }
801
+ }
802
+ }
803
+
804
+ const Transition target = {unix_time, 0, civil_second(), civil_second()};
805
+ const Transition* begin = &transitions_[0];
806
+ const Transition* tr = std::upper_bound(begin, begin + timecnt, target,
807
+ Transition::ByUnixTime());
808
+ local_time_hint_.store(static_cast<std::size_t>(tr - begin),
809
+ std::memory_order_relaxed);
810
+ return LocalTime(unix_time, *--tr);
811
+ }
812
+
813
+ time_zone::civil_lookup TimeZoneInfo::MakeTime(const civil_second& cs) const {
814
+ const std::size_t timecnt = transitions_.size();
815
+ assert(timecnt != 0); // We always add a transition.
816
+
817
+ // Find the first transition after our target civil time.
818
+ const Transition* tr = nullptr;
819
+ const Transition* begin = &transitions_[0];
820
+ const Transition* end = begin + timecnt;
821
+ if (cs < begin->civil_sec) {
822
+ tr = begin;
823
+ } else if (cs >= transitions_[timecnt - 1].civil_sec) {
824
+ tr = end;
825
+ } else {
826
+ const std::size_t hint = time_local_hint_.load(std::memory_order_relaxed);
827
+ if (0 < hint && hint < timecnt) {
828
+ if (transitions_[hint - 1].civil_sec <= cs) {
829
+ if (cs < transitions_[hint].civil_sec) {
830
+ tr = begin + hint;
831
+ }
832
+ }
833
+ }
834
+ if (tr == nullptr) {
835
+ const Transition target = {0, 0, cs, civil_second()};
836
+ tr = std::upper_bound(begin, end, target, Transition::ByCivilTime());
837
+ time_local_hint_.store(static_cast<std::size_t>(tr - begin),
838
+ std::memory_order_relaxed);
839
+ }
840
+ }
841
+
842
+ if (tr == begin) {
843
+ if (tr->prev_civil_sec >= cs) {
844
+ // Before first transition, so use the default offset.
845
+ const TransitionType& tt(transition_types_[default_transition_type_]);
846
+ if (cs < tt.civil_min) return MakeUnique(time_point<seconds>::min());
847
+ return MakeUnique(cs - (civil_second() + tt.utc_offset));
848
+ }
849
+ // tr->prev_civil_sec < cs < tr->civil_sec
850
+ return MakeSkipped(*tr, cs);
851
+ }
852
+
853
+ if (tr == end) {
854
+ if (cs > (--tr)->prev_civil_sec) {
855
+ // After the last transition. If we extended the transitions using
856
+ // future_spec_, shift back to a supported year using the 400-year
857
+ // cycle of calendaric equivalence and then compensate accordingly.
858
+ if (extended_ && cs.year() > last_year_) {
859
+ const year_t shift = (cs.year() - last_year_ - 1) / 400 + 1;
860
+ return TimeLocal(YearShift(cs, shift * -400), shift);
861
+ }
862
+ const TransitionType& tt(transition_types_[tr->type_index]);
863
+ if (cs > tt.civil_max) return MakeUnique(time_point<seconds>::max());
864
+ return MakeUnique(tr->unix_time + (cs - tr->civil_sec));
865
+ }
866
+ // tr->civil_sec <= cs <= tr->prev_civil_sec
867
+ return MakeRepeated(*tr, cs);
868
+ }
869
+
870
+ if (tr->prev_civil_sec < cs) {
871
+ // tr->prev_civil_sec < cs < tr->civil_sec
872
+ return MakeSkipped(*tr, cs);
873
+ }
874
+
875
+ if (cs <= (--tr)->prev_civil_sec) {
876
+ // tr->civil_sec <= cs <= tr->prev_civil_sec
877
+ return MakeRepeated(*tr, cs);
878
+ }
879
+
880
+ // In between transitions.
881
+ return MakeUnique(tr->unix_time + (cs - tr->civil_sec));
882
+ }
883
+
884
+ std::string TimeZoneInfo::Version() const { return version_; }
885
+
886
+ std::string TimeZoneInfo::Description() const {
887
+ std::ostringstream oss;
888
+ oss << "#trans=" << transitions_.size();
889
+ oss << " #types=" << transition_types_.size();
890
+ oss << " spec='" << future_spec_ << "'";
891
+ return oss.str();
892
+ }
893
+
894
+ bool TimeZoneInfo::NextTransition(const time_point<seconds>& tp,
895
+ time_zone::civil_transition* trans) const {
896
+ if (transitions_.empty()) return false;
897
+ const Transition* begin = &transitions_[0];
898
+ const Transition* end = begin + transitions_.size();
899
+ if (begin->unix_time <= -(1LL << 59)) {
900
+ // Do not report the BIG_BANG found in recent zoneinfo data as it is
901
+ // really a sentinel, not a transition. See tz/zic.c.
902
+ ++begin;
903
+ }
904
+ std::int_fast64_t unix_time = ToUnixSeconds(tp);
905
+ const Transition target = {unix_time, 0, civil_second(), civil_second()};
906
+ const Transition* tr =
907
+ std::upper_bound(begin, end, target, Transition::ByUnixTime());
908
+ for (; tr != end; ++tr) { // skip no-op transitions
909
+ std::uint_fast8_t prev_type_index =
910
+ (tr == begin) ? default_transition_type_ : tr[-1].type_index;
911
+ if (!EquivTransitions(prev_type_index, tr[0].type_index)) break;
912
+ }
913
+ // When tr == end we return false, ignoring future_spec_.
914
+ if (tr == end) return false;
915
+ trans->from = tr->prev_civil_sec + 1;
916
+ trans->to = tr->civil_sec;
917
+ return true;
918
+ }
919
+
920
+ bool TimeZoneInfo::PrevTransition(const time_point<seconds>& tp,
921
+ time_zone::civil_transition* trans) const {
922
+ if (transitions_.empty()) return false;
923
+ const Transition* begin = &transitions_[0];
924
+ const Transition* end = begin + transitions_.size();
925
+ if (begin->unix_time <= -(1LL << 59)) {
926
+ // Do not report the BIG_BANG found in recent zoneinfo data as it is
927
+ // really a sentinel, not a transition. See tz/zic.c.
928
+ ++begin;
929
+ }
930
+ std::int_fast64_t unix_time = ToUnixSeconds(tp);
931
+ if (FromUnixSeconds(unix_time) != tp) {
932
+ if (unix_time == std::numeric_limits<std::int_fast64_t>::max()) {
933
+ if (end == begin) return false; // Ignore future_spec_.
934
+ trans->from = (--end)->prev_civil_sec + 1;
935
+ trans->to = end->civil_sec;
936
+ return true;
937
+ }
938
+ unix_time += 1; // ceils
939
+ }
940
+ const Transition target = {unix_time, 0, civil_second(), civil_second()};
941
+ const Transition* tr =
942
+ std::lower_bound(begin, end, target, Transition::ByUnixTime());
943
+ for (; tr != begin; --tr) { // skip no-op transitions
944
+ std::uint_fast8_t prev_type_index =
945
+ (tr - 1 == begin) ? default_transition_type_ : tr[-2].type_index;
946
+ if (!EquivTransitions(prev_type_index, tr[-1].type_index)) break;
947
+ }
948
+ // When tr == end we return the "last" transition, ignoring future_spec_.
949
+ if (tr == begin) return false;
950
+ trans->from = (--tr)->prev_civil_sec + 1;
951
+ trans->to = tr->civil_sec;
952
+ return true;
953
+ }
954
+
955
+ } // namespace cctz
956
+ } // namespace time_internal
957
+ ABSL_NAMESPACE_END
958
+ } // namespace absl