grpc 1.28.0 → 1.30.2
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.
- checksums.yaml +4 -4
- data/Makefile +7694 -11190
- data/include/grpc/grpc.h +2 -2
- data/include/grpc/grpc_security.h +30 -9
- data/include/grpc/grpc_security_constants.h +1 -0
- data/include/grpc/impl/codegen/grpc_types.h +19 -21
- data/include/grpc/impl/codegen/port_platform.h +6 -2
- data/include/grpc/module.modulemap +24 -39
- data/src/core/ext/filters/client_channel/backend_metric.cc +7 -4
- data/src/core/ext/filters/client_channel/client_channel.cc +212 -241
- data/src/core/ext/filters/client_channel/client_channel_plugin.cc +3 -2
- data/src/core/ext/filters/client_channel/health/health_check_client.cc +7 -22
- data/src/core/ext/filters/client_channel/health/health_check_client.h +3 -3
- data/src/core/ext/filters/client_channel/http_proxy.cc +17 -10
- data/src/core/ext/filters/client_channel/lb_policy.cc +19 -18
- data/src/core/ext/filters/client_channel/lb_policy.h +42 -33
- data/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc +83 -0
- data/src/core/ext/filters/client_channel/lb_policy/address_filtering.h +99 -0
- data/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc +10 -4
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +240 -301
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.cc +89 -0
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h +40 -0
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +11 -9
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +3 -2
- data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +871 -0
- data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +1 -1
- data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +5 -11
- data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +734 -0
- data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +84 -37
- data/src/core/ext/filters/client_channel/lb_policy/xds/eds.cc +938 -0
- data/src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc +528 -0
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds.h +1 -2
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc +834 -0
- data/src/core/ext/filters/client_channel/lb_policy_registry.cc +6 -2
- data/src/core/ext/filters/client_channel/local_subchannel_pool.h +2 -1
- data/src/core/ext/filters/client_channel/parse_address.cc +22 -21
- data/src/core/ext/filters/client_channel/resolver.cc +5 -8
- data/src/core/ext/filters/client_channel/resolver.h +12 -14
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +73 -59
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc +35 -35
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +8 -7
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc +16 -20
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +4 -4
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +72 -117
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +184 -133
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +5 -3
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +7 -4
- data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +40 -43
- data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +93 -102
- data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +0 -4
- data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +2 -2
- data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +32 -5
- data/src/core/ext/filters/client_channel/resolver_factory.h +2 -2
- data/src/core/ext/filters/client_channel/resolver_registry.cc +6 -3
- data/src/core/ext/filters/client_channel/resolver_registry.h +8 -8
- data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +16 -16
- data/src/core/ext/filters/client_channel/resolver_result_parsing.h +19 -16
- data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +20 -31
- data/src/core/ext/filters/client_channel/resolving_lb_policy.h +4 -3
- data/src/core/ext/filters/client_channel/server_address.cc +6 -9
- data/src/core/ext/filters/client_channel/server_address.h +6 -12
- data/src/core/ext/filters/client_channel/service_config.cc +104 -144
- data/src/core/ext/filters/client_channel/service_config.h +28 -98
- data/src/core/ext/filters/client_channel/service_config_call_data.h +68 -0
- data/src/core/ext/filters/client_channel/service_config_parser.cc +87 -0
- data/src/core/ext/filters/client_channel/service_config_parser.h +89 -0
- data/src/core/ext/filters/client_channel/subchannel.cc +54 -24
- data/src/core/ext/filters/client_channel/subchannel.h +35 -11
- data/src/core/ext/filters/client_channel/xds/xds_api.cc +348 -221
- data/src/core/ext/filters/client_channel/xds/xds_api.h +37 -37
- data/src/core/ext/filters/client_channel/xds/xds_bootstrap.cc +44 -49
- data/src/core/ext/filters/client_channel/xds/xds_bootstrap.h +4 -3
- data/src/core/ext/filters/client_channel/xds/xds_channel_secure.cc +4 -2
- data/src/core/ext/filters/client_channel/xds/xds_client.cc +532 -339
- data/src/core/ext/filters/client_channel/xds/xds_client.h +57 -22
- data/src/core/ext/filters/client_channel/xds/xds_client_stats.cc +11 -12
- data/src/core/ext/filters/client_channel/xds/xds_client_stats.h +31 -19
- data/src/core/ext/filters/http/client/http_client_filter.cc +23 -28
- data/src/core/ext/filters/http/client_authority_filter.cc +4 -4
- data/src/core/ext/filters/http/http_filters_plugin.cc +27 -12
- data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +258 -221
- data/src/core/ext/filters/http/message_compress/message_decompress_filter.cc +358 -0
- data/src/core/ext/filters/http/message_compress/message_decompress_filter.h +29 -0
- data/src/core/ext/filters/message_size/message_size_filter.cc +7 -10
- data/src/core/ext/filters/message_size/message_size_filter.h +4 -4
- data/src/core/ext/transport/chttp2/server/chttp2_server.cc +4 -4
- data/src/core/ext/transport/chttp2/transport/bin_encoder.cc +4 -6
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +23 -22
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +1 -0
- data/src/core/ext/transport/chttp2/transport/flow_control.cc +3 -3
- data/src/core/ext/transport/chttp2/transport/frame_goaway.h +2 -3
- data/src/core/ext/transport/chttp2/transport/frame_ping.h +2 -3
- data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +2 -3
- data/src/core/ext/transport/chttp2/transport/frame_settings.h +2 -3
- data/src/core/ext/transport/chttp2/transport/frame_window_update.h +2 -3
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +29 -16
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.h +2 -3
- data/src/core/ext/transport/chttp2/transport/hpack_parser.h +2 -3
- data/src/core/ext/transport/chttp2/transport/hpack_table.h +2 -2
- data/src/core/ext/transport/chttp2/transport/http2_settings.h +4 -5
- data/src/core/ext/transport/chttp2/transport/huffsyms.h +2 -3
- data/src/core/ext/transport/chttp2/transport/internal.h +14 -21
- data/src/core/ext/transport/chttp2/transport/stream_map.h +2 -3
- data/src/core/ext/transport/chttp2/transport/writing.cc +15 -8
- data/src/core/ext/transport/inproc/inproc_transport.cc +19 -0
- data/src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c +4 -229
- data/src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h +5 -875
- data/src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c +114 -0
- data/src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h +418 -0
- data/src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c +72 -0
- data/src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h +197 -0
- data/src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c +105 -0
- data/src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h +378 -0
- data/src/core/ext/upb-generated/envoy/api/v2/cds.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c +21 -8
- data/src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h +43 -7
- data/src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c +2 -1
- data/src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c +35 -0
- data/src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h +78 -0
- data/src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c +47 -26
- data/src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h +115 -65
- data/src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c +34 -0
- data/src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h +72 -0
- data/src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c +2 -1
- data/src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c +24 -20
- data/src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h +28 -13
- data/src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c +38 -18
- data/src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h +88 -6
- data/src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c +34 -0
- data/src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h +89 -0
- data/src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/eds.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c +9 -6
- data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.h +12 -4
- data/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/lds.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/listener.upb.c +15 -10
- data/src/core/ext/upb-generated/envoy/api/v2/listener.upb.h +16 -0
- data/src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c +2 -1
- data/src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/rds.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/route.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c +63 -41
- data/src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.h +173 -77
- data/src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/api/v2/srds.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c +48 -28
- data/src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h +90 -30
- data/src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c +51 -0
- data/src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h +125 -0
- data/src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c +4 -2
- data/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h +4 -0
- data/src/core/ext/upb-generated/envoy/type/http.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c +16 -0
- data/src/core/ext/upb-generated/envoy/type/matcher/regex.upb.h +36 -0
- data/src/core/ext/upb-generated/envoy/type/matcher/string.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/type/percent.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/type/range.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/type/semantic_version.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c +1 -0
- data/src/core/ext/upb-generated/google/protobuf/descriptor.upb.c +9 -8
- data/src/core/ext/upb-generated/google/protobuf/descriptor.upb.h +30 -24
- data/src/core/ext/upb-generated/udpa/annotations/status.upb.c +28 -0
- data/src/core/ext/upb-generated/udpa/annotations/status.upb.h +65 -0
- data/src/core/ext/upb-generated/validate/validate.upb.c +21 -20
- data/src/core/ext/upb-generated/validate/validate.upb.h +69 -63
- data/src/core/lib/channel/channel_args.cc +15 -14
- data/src/core/lib/channel/channel_args.h +3 -1
- data/src/core/lib/channel/channel_stack.h +20 -13
- data/src/core/lib/channel/channelz.cc +5 -6
- data/src/core/lib/channel/channelz.h +3 -2
- data/src/core/lib/channel/channelz_registry.cc +5 -3
- data/src/core/lib/channel/connected_channel.cc +7 -5
- data/src/core/lib/channel/context.h +1 -1
- data/src/core/lib/channel/handshaker.cc +11 -13
- data/src/core/lib/channel/handshaker.h +4 -2
- data/src/core/lib/channel/handshaker_registry.cc +5 -17
- data/src/core/lib/channel/status_util.cc +2 -3
- data/src/core/lib/compression/message_compress.cc +5 -1
- data/src/core/lib/debug/stats.cc +21 -27
- data/src/core/lib/debug/stats.h +3 -1
- data/src/core/lib/gpr/spinlock.h +2 -3
- data/src/core/lib/gpr/string.cc +2 -26
- data/src/core/lib/gpr/string.h +0 -16
- data/src/core/lib/gpr/sync_abseil.cc +2 -0
- data/src/core/lib/gpr/time.cc +4 -0
- data/src/core/lib/gpr/time_posix.cc +1 -1
- data/src/core/lib/gprpp/atomic.h +6 -6
- data/src/core/lib/gprpp/fork.cc +1 -1
- data/src/core/lib/gprpp/host_port.cc +29 -35
- data/src/core/lib/gprpp/host_port.h +14 -17
- data/src/core/lib/gprpp/map.h +5 -11
- data/src/core/lib/gprpp/ref_counted_ptr.h +5 -0
- data/src/core/lib/http/format_request.cc +46 -65
- data/src/core/lib/http/httpcli.cc +2 -3
- data/src/core/lib/http/httpcli.h +2 -3
- data/src/core/lib/http/httpcli_security_connector.cc +5 -5
- data/src/core/lib/http/parser.h +2 -3
- data/src/core/lib/iomgr/buffer_list.h +22 -21
- data/src/core/lib/iomgr/call_combiner.h +3 -2
- data/src/core/lib/iomgr/cfstream_handle.cc +3 -2
- data/src/core/lib/iomgr/closure.h +2 -3
- data/src/core/lib/iomgr/dualstack_socket_posix.cc +47 -0
- data/src/core/lib/iomgr/endpoint_cfstream.cc +2 -3
- data/src/core/lib/iomgr/endpoint_pair.h +2 -3
- data/src/core/lib/iomgr/error.cc +6 -9
- data/src/core/lib/iomgr/error.h +0 -1
- data/src/core/lib/iomgr/ev_apple.cc +356 -0
- data/src/core/lib/iomgr/ev_apple.h +43 -0
- data/src/core/lib/iomgr/ev_epoll1_linux.cc +20 -23
- data/src/core/lib/iomgr/ev_epollex_linux.cc +2 -3
- data/src/core/lib/iomgr/ev_poll_posix.cc +3 -3
- data/src/core/lib/iomgr/ev_posix.cc +2 -3
- data/src/core/lib/iomgr/exec_ctx.h +14 -2
- data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +84 -20
- data/src/core/lib/iomgr/pollset_set_custom.cc +10 -10
- data/src/core/lib/{gprpp/optional.h → iomgr/pollset_uv.h} +11 -12
- data/src/core/lib/iomgr/port.h +1 -0
- data/src/core/lib/iomgr/python_util.h +46 -0
- data/src/core/lib/iomgr/resolve_address.h +4 -6
- data/src/core/lib/iomgr/resolve_address_custom.cc +29 -39
- data/src/core/lib/iomgr/resolve_address_custom.h +4 -2
- data/src/core/lib/iomgr/resolve_address_posix.cc +10 -11
- data/src/core/lib/iomgr/resolve_address_windows.cc +8 -17
- data/src/core/lib/iomgr/resource_quota.cc +4 -6
- data/src/core/lib/iomgr/sockaddr_utils.cc +23 -29
- data/src/core/lib/iomgr/sockaddr_utils.h +9 -14
- data/src/core/lib/iomgr/socket_factory_posix.h +2 -3
- data/src/core/lib/iomgr/socket_mutator.h +2 -3
- data/src/core/lib/iomgr/socket_utils_common_posix.cc +7 -26
- data/src/core/lib/iomgr/socket_utils_posix.h +3 -0
- data/src/core/lib/iomgr/tcp_client_cfstream.cc +5 -7
- data/src/core/lib/iomgr/tcp_client_posix.cc +8 -5
- data/src/core/lib/iomgr/tcp_client_windows.cc +2 -3
- data/src/core/lib/iomgr/tcp_custom.cc +2 -3
- data/src/core/lib/iomgr/tcp_server_custom.cc +5 -9
- data/src/core/lib/iomgr/tcp_server_posix.cc +5 -4
- data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +5 -4
- data/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc +8 -11
- data/src/core/lib/iomgr/tcp_uv.cc +3 -2
- data/src/core/lib/iomgr/time_averaged_stats.h +2 -3
- data/src/core/lib/iomgr/timer_generic.cc +2 -3
- data/src/core/lib/{gprpp/inlined_vector.h → iomgr/timer_generic.h} +19 -17
- data/src/core/lib/iomgr/timer_heap.h +2 -3
- data/src/core/lib/iomgr/udp_server.cc +9 -14
- data/src/core/lib/json/json.h +3 -2
- data/src/core/lib/json/json_reader.cc +5 -5
- data/src/core/lib/json/json_writer.cc +13 -12
- data/src/core/lib/security/credentials/composite/composite_credentials.cc +12 -0
- data/src/core/lib/security/credentials/composite/composite_credentials.h +6 -3
- data/src/core/lib/security/credentials/credentials.cc +0 -84
- data/src/core/lib/security/credentials/credentials.h +8 -59
- data/src/core/lib/security/credentials/fake/fake_credentials.h +4 -0
- data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +3 -8
- data/src/core/lib/security/credentials/iam/iam_credentials.cc +8 -6
- data/src/core/lib/security/credentials/iam/iam_credentials.h +4 -0
- data/src/core/lib/security/credentials/jwt/json_token.cc +1 -1
- data/src/core/lib/security/credentials/jwt/json_token.h +2 -5
- data/src/core/lib/security/credentials/jwt/jwt_credentials.h +12 -0
- data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +8 -15
- data/src/core/lib/security/credentials/jwt/jwt_verifier.h +2 -3
- data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +55 -27
- data/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +9 -3
- data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +13 -0
- data/src/core/lib/security/credentials/plugin/plugin_credentials.h +2 -0
- data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +23 -13
- data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +38 -11
- data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +21 -6
- data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +7 -7
- data/src/core/lib/security/security_connector/load_system_roots_linux.cc +3 -2
- data/src/core/lib/security/security_connector/local/local_security_connector.cc +1 -1
- data/src/core/lib/security/security_connector/security_connector.h +1 -1
- data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +20 -25
- data/src/core/lib/security/security_connector/ssl/ssl_security_connector.h +4 -6
- data/src/core/lib/security/security_connector/ssl_utils.cc +59 -12
- data/src/core/lib/security/security_connector/ssl_utils.h +12 -10
- data/src/core/lib/security/security_connector/tls/tls_security_connector.cc +77 -51
- data/src/core/lib/security/security_connector/tls/tls_security_connector.h +27 -5
- data/src/core/lib/security/transport/auth_filters.h +0 -5
- data/src/core/lib/security/transport/client_auth_filter.cc +1 -2
- data/src/core/lib/slice/slice_intern.cc +2 -3
- data/src/core/lib/slice/slice_internal.h +14 -0
- data/src/core/lib/slice/slice_utils.h +9 -0
- data/src/core/lib/surface/byte_buffer_reader.cc +2 -47
- data/src/core/lib/surface/call.cc +2 -3
- data/src/core/lib/surface/call_log_batch.cc +50 -58
- data/src/core/lib/surface/channel.cc +53 -31
- data/src/core/lib/surface/channel.h +35 -4
- data/src/core/lib/surface/channel_ping.cc +2 -3
- data/src/core/lib/surface/completion_queue.cc +33 -33
- data/src/core/lib/surface/event_string.cc +18 -25
- data/src/core/lib/surface/event_string.h +3 -1
- data/src/core/lib/surface/init_secure.cc +1 -4
- data/src/core/lib/surface/server.cc +570 -369
- data/src/core/lib/surface/server.h +32 -0
- data/src/core/lib/surface/version.cc +2 -2
- data/src/core/lib/transport/byte_stream.h +7 -2
- data/src/core/lib/transport/connectivity_state.cc +7 -6
- data/src/core/lib/transport/connectivity_state.h +5 -3
- data/src/core/lib/transport/metadata.cc +3 -3
- data/src/core/lib/transport/metadata_batch.h +2 -3
- data/src/core/lib/transport/static_metadata.h +1 -1
- data/src/core/lib/transport/status_conversion.cc +6 -14
- data/src/core/lib/transport/transport.cc +2 -3
- data/src/core/lib/transport/transport.h +3 -2
- data/src/core/lib/transport/transport_op_string.cc +61 -102
- data/src/core/lib/uri/uri_parser.h +2 -3
- data/src/core/plugin_registry/grpc_plugin_registry.cc +20 -4
- data/src/core/tsi/alts/crypt/aes_gcm.cc +0 -2
- data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +8 -1
- data/src/core/tsi/alts/handshaker/alts_handshaker_client.h +8 -4
- data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +32 -2
- data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +9 -1
- data/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h +2 -3
- data/src/core/tsi/fake_transport_security.cc +10 -15
- data/src/core/tsi/ssl/session_cache/ssl_session.h +0 -2
- data/src/core/tsi/ssl/session_cache/ssl_session_cache.h +0 -2
- data/src/core/tsi/ssl_transport_security.cc +52 -39
- data/src/core/tsi/ssl_transport_security.h +8 -8
- data/src/core/tsi/ssl_types.h +0 -2
- data/src/core/tsi/transport_security.h +6 -9
- data/src/core/tsi/transport_security_grpc.h +2 -3
- data/src/core/tsi/transport_security_interface.h +3 -3
- data/src/ruby/ext/grpc/rb_call.c +9 -1
- data/src/ruby/ext/grpc/rb_call_credentials.c +3 -2
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +4 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +6 -0
- data/src/ruby/lib/grpc/errors.rb +103 -42
- data/src/ruby/lib/grpc/generic/active_call.rb +2 -3
- data/src/ruby/lib/grpc/generic/interceptors.rb +4 -4
- data/src/ruby/lib/grpc/generic/rpc_server.rb +9 -10
- data/src/ruby/lib/grpc/generic/service.rb +5 -4
- data/src/ruby/lib/grpc/structs.rb +1 -1
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/src/ruby/pb/generate_proto_ruby.sh +5 -3
- data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +11 -0
- data/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb +16 -0
- data/src/ruby/spec/debug_message_spec.rb +134 -0
- data/src/ruby/spec/generic/service_spec.rb +2 -0
- data/src/ruby/spec/pb/codegen/grpc/testing/package_options_import2.proto +23 -0
- data/src/ruby/spec/pb/codegen/grpc/testing/package_options_ruby_style.proto +7 -0
- data/src/ruby/spec/pb/codegen/package_option_spec.rb +7 -1
- data/src/ruby/spec/support/services.rb +10 -4
- data/src/ruby/spec/testdata/ca.pem +18 -13
- data/src/ruby/spec/testdata/client.key +26 -14
- data/src/ruby/spec/testdata/client.pem +18 -12
- data/src/ruby/spec/testdata/server1.key +26 -14
- data/src/ruby/spec/testdata/server1.pem +20 -14
- data/third_party/abseil-cpp/absl/time/civil_time.cc +175 -0
- data/third_party/abseil-cpp/absl/time/civil_time.h +538 -0
- data/third_party/abseil-cpp/absl/time/clock.cc +569 -0
- data/third_party/abseil-cpp/absl/time/clock.h +74 -0
- data/third_party/abseil-cpp/absl/time/duration.cc +922 -0
- data/third_party/abseil-cpp/absl/time/format.cc +153 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time.h +332 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h +622 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h +384 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h +102 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/civil_time_detail.cc +94 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc +140 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.h +52 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc +922 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc +45 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.h +76 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc +121 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h +93 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc +958 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h +138 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc +308 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.h +55 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc +187 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc +159 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.h +132 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/tzfile.h +122 -0
- data/third_party/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc +115 -0
- data/third_party/abseil-cpp/absl/time/internal/get_current_time_chrono.inc +31 -0
- data/third_party/abseil-cpp/absl/time/internal/get_current_time_posix.inc +24 -0
- data/third_party/abseil-cpp/absl/time/time.cc +499 -0
- data/third_party/abseil-cpp/absl/time/time.h +1584 -0
- data/third_party/boringssl-with-bazel/err_data.c +329 -297
- data/third_party/boringssl-with-bazel/src/crypto/cipher_extra/derive_key.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/cpu-arm-linux.c +7 -5
- data/third_party/boringssl-with-bazel/src/crypto/cpu-intel.c +13 -4
- data/third_party/boringssl-with-bazel/src/crypto/crypto.c +11 -0
- data/third_party/boringssl-with-bazel/src/{third_party/fiat → crypto/curve25519}/curve25519.c +18 -26
- data/third_party/boringssl-with-bazel/src/{third_party/fiat → crypto/curve25519}/curve25519_tables.h +13 -21
- data/third_party/boringssl-with-bazel/src/{third_party/fiat → crypto/curve25519}/internal.h +14 -22
- data/third_party/boringssl-with-bazel/src/crypto/curve25519/spake25519.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/dh/dh.c +15 -0
- data/third_party/boringssl-with-bazel/src/crypto/dsa/dsa.c +10 -0
- data/third_party/boringssl-with-bazel/src/crypto/ec_extra/hash_to_curve.c +425 -0
- data/third_party/boringssl-with-bazel/src/crypto/ec_extra/internal.h +78 -0
- data/third_party/boringssl-with-bazel/src/crypto/ecdh_extra/ecdh_extra.c +2 -2
- data/third_party/boringssl-with-bazel/src/crypto/err/err.c +33 -32
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/aes/aes_nohw.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bcm.c +2 -1
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/exponentiation.c +3 -3
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/internal.h +14 -11
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/montgomery.c +8 -8
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/mul.c +30 -154
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/digest/digests.c +16 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec.c +289 -117
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec_key.c +13 -27
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec_montgomery.c +96 -55
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/felem.c +25 -7
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/internal.h +432 -160
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/oct.c +63 -71
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p224-64.c +5 -14
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256-x86_64-table.h +9481 -9485
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256-x86_64.c +80 -99
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256.c +736 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256_table.h +297 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/scalar.c +90 -11
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/simple.c +125 -148
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/simple_mul.c +189 -3
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/wnaf.c +61 -18
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ecdh/ecdh.c +2 -2
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ecdsa/ecdsa.c +20 -5
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/fork_detect.c +137 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/fork_detect.h +49 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/getrandom_fillin.h +64 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/internal.h +41 -5
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/rand.c +32 -17
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/urandom.c +24 -114
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/blinding.c +4 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/internal.h +1 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa.c +51 -38
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa_impl.c +15 -1
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/sha/sha512.c +44 -35
- data/third_party/boringssl-with-bazel/src/crypto/mem.c +29 -12
- data/third_party/boringssl-with-bazel/src/crypto/obj/obj_dat.h +15 -1
- data/third_party/boringssl-with-bazel/src/crypto/rand_extra/deterministic.c +6 -10
- data/third_party/boringssl-with-bazel/src/crypto/rand_extra/windows.c +16 -0
- data/third_party/boringssl-with-bazel/src/crypto/thread_pthread.c +4 -0
- data/third_party/boringssl-with-bazel/src/crypto/thread_win.c +4 -0
- data/third_party/boringssl-with-bazel/src/crypto/trust_token/internal.h +278 -0
- data/third_party/boringssl-with-bazel/src/crypto/trust_token/pmbtoken.c +1474 -0
- data/third_party/boringssl-with-bazel/src/crypto/trust_token/trust_token.c +720 -0
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509_set.c +16 -0
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509_vfy.c +5 -0
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509name.c +4 -3
- data/third_party/boringssl-with-bazel/src/include/openssl/base.h +5 -1
- data/third_party/boringssl-with-bazel/src/include/openssl/crypto.h +9 -4
- data/third_party/boringssl-with-bazel/src/include/openssl/dh.h +20 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/digest.h +1 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/dsa.h +16 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/ecdsa.h +6 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/err.h +2 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/nid.h +5 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/rand.h +3 -17
- data/third_party/boringssl-with-bazel/src/include/openssl/rsa.h +31 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/sha.h +26 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/ssl.h +172 -77
- data/third_party/boringssl-with-bazel/src/include/openssl/tls1.h +1 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/trust_token.h +291 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/x509.h +5 -3
- data/third_party/boringssl-with-bazel/src/include/openssl/x509_vfy.h +1 -0
- data/third_party/boringssl-with-bazel/src/ssl/d1_both.cc +0 -4
- data/third_party/boringssl-with-bazel/src/ssl/d1_lib.cc +3 -3
- data/third_party/boringssl-with-bazel/src/ssl/dtls_method.cc +13 -4
- data/third_party/boringssl-with-bazel/src/ssl/handoff.cc +146 -57
- data/third_party/boringssl-with-bazel/src/ssl/handshake.cc +14 -3
- data/third_party/boringssl-with-bazel/src/ssl/handshake_client.cc +28 -20
- data/third_party/boringssl-with-bazel/src/ssl/handshake_server.cc +12 -4
- data/third_party/boringssl-with-bazel/src/ssl/internal.h +64 -47
- data/third_party/boringssl-with-bazel/src/ssl/s3_both.cc +10 -10
- data/third_party/boringssl-with-bazel/src/ssl/s3_lib.cc +2 -2
- data/third_party/boringssl-with-bazel/src/ssl/s3_pkt.cc +21 -21
- data/third_party/boringssl-with-bazel/src/ssl/ssl_asn1.cc +29 -0
- data/third_party/boringssl-with-bazel/src/ssl/ssl_cert.cc +4 -0
- data/third_party/boringssl-with-bazel/src/ssl/ssl_lib.cc +6 -1
- data/third_party/boringssl-with-bazel/src/ssl/ssl_privkey.cc +13 -2
- data/third_party/boringssl-with-bazel/src/ssl/ssl_session.cc +64 -5
- data/third_party/boringssl-with-bazel/src/ssl/ssl_stat.cc +6 -0
- data/third_party/boringssl-with-bazel/src/ssl/t1_enc.cc +6 -2
- data/third_party/boringssl-with-bazel/src/ssl/t1_lib.cc +47 -53
- data/third_party/boringssl-with-bazel/src/ssl/tls13_both.cc +1 -1
- data/third_party/boringssl-with-bazel/src/ssl/tls13_client.cc +98 -27
- data/third_party/boringssl-with-bazel/src/ssl/tls13_enc.cc +23 -75
- data/third_party/boringssl-with-bazel/src/ssl/tls13_server.cc +50 -20
- data/third_party/boringssl-with-bazel/src/ssl/tls_method.cc +63 -25
- data/third_party/boringssl-with-bazel/src/third_party/fiat/curve25519_32.h +245 -175
- data/third_party/boringssl-with-bazel/src/third_party/fiat/curve25519_64.h +135 -75
- data/third_party/boringssl-with-bazel/src/third_party/fiat/p256_32.h +1593 -1672
- data/third_party/boringssl-with-bazel/src/third_party/fiat/p256_64.h +512 -503
- metadata +115 -39
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +0 -1754
- data/src/core/lib/gprpp/string_view.h +0 -60
- data/src/core/tsi/grpc_shadow_boringssl.h +0 -3311
- 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
|