grpc 1.28.0 → 1.30.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grpc might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Makefile +7694 -11190
- data/include/grpc/grpc.h +2 -2
- data/include/grpc/grpc_security.h +22 -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 +203 -236
- 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/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/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_ruby_style.proto +5 -0
- data/src/ruby/spec/pb/codegen/package_option_spec.rb +2 -0
- 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 +111 -37
- 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,94 @@
|
|
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 "absl/time/internal/cctz/include/cctz/civil_time_detail.h"
|
16
|
+
|
17
|
+
#include <iomanip>
|
18
|
+
#include <ostream>
|
19
|
+
#include <sstream>
|
20
|
+
|
21
|
+
#include "absl/base/config.h"
|
22
|
+
|
23
|
+
namespace absl {
|
24
|
+
ABSL_NAMESPACE_BEGIN
|
25
|
+
namespace time_internal {
|
26
|
+
namespace cctz {
|
27
|
+
namespace detail {
|
28
|
+
|
29
|
+
// Output stream operators output a format matching YYYY-MM-DDThh:mm:ss,
|
30
|
+
// while omitting fields inferior to the type's alignment. For example,
|
31
|
+
// civil_day is formatted only as YYYY-MM-DD.
|
32
|
+
std::ostream& operator<<(std::ostream& os, const civil_year& y) {
|
33
|
+
std::stringstream ss;
|
34
|
+
ss << y.year(); // No padding.
|
35
|
+
return os << ss.str();
|
36
|
+
}
|
37
|
+
std::ostream& operator<<(std::ostream& os, const civil_month& m) {
|
38
|
+
std::stringstream ss;
|
39
|
+
ss << civil_year(m) << '-';
|
40
|
+
ss << std::setfill('0') << std::setw(2) << m.month();
|
41
|
+
return os << ss.str();
|
42
|
+
}
|
43
|
+
std::ostream& operator<<(std::ostream& os, const civil_day& d) {
|
44
|
+
std::stringstream ss;
|
45
|
+
ss << civil_month(d) << '-';
|
46
|
+
ss << std::setfill('0') << std::setw(2) << d.day();
|
47
|
+
return os << ss.str();
|
48
|
+
}
|
49
|
+
std::ostream& operator<<(std::ostream& os, const civil_hour& h) {
|
50
|
+
std::stringstream ss;
|
51
|
+
ss << civil_day(h) << 'T';
|
52
|
+
ss << std::setfill('0') << std::setw(2) << h.hour();
|
53
|
+
return os << ss.str();
|
54
|
+
}
|
55
|
+
std::ostream& operator<<(std::ostream& os, const civil_minute& m) {
|
56
|
+
std::stringstream ss;
|
57
|
+
ss << civil_hour(m) << ':';
|
58
|
+
ss << std::setfill('0') << std::setw(2) << m.minute();
|
59
|
+
return os << ss.str();
|
60
|
+
}
|
61
|
+
std::ostream& operator<<(std::ostream& os, const civil_second& s) {
|
62
|
+
std::stringstream ss;
|
63
|
+
ss << civil_minute(s) << ':';
|
64
|
+
ss << std::setfill('0') << std::setw(2) << s.second();
|
65
|
+
return os << ss.str();
|
66
|
+
}
|
67
|
+
|
68
|
+
////////////////////////////////////////////////////////////////////////
|
69
|
+
|
70
|
+
std::ostream& operator<<(std::ostream& os, weekday wd) {
|
71
|
+
switch (wd) {
|
72
|
+
case weekday::monday:
|
73
|
+
return os << "Monday";
|
74
|
+
case weekday::tuesday:
|
75
|
+
return os << "Tuesday";
|
76
|
+
case weekday::wednesday:
|
77
|
+
return os << "Wednesday";
|
78
|
+
case weekday::thursday:
|
79
|
+
return os << "Thursday";
|
80
|
+
case weekday::friday:
|
81
|
+
return os << "Friday";
|
82
|
+
case weekday::saturday:
|
83
|
+
return os << "Saturday";
|
84
|
+
case weekday::sunday:
|
85
|
+
return os << "Sunday";
|
86
|
+
}
|
87
|
+
return os; // Should never get here, but -Wreturn-type may warn without this.
|
88
|
+
}
|
89
|
+
|
90
|
+
} // namespace detail
|
91
|
+
} // namespace cctz
|
92
|
+
} // namespace time_internal
|
93
|
+
ABSL_NAMESPACE_END
|
94
|
+
} // namespace absl
|
@@ -0,0 +1,140 @@
|
|
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_fixed.h"
|
16
|
+
|
17
|
+
#include <algorithm>
|
18
|
+
#include <cassert>
|
19
|
+
#include <chrono>
|
20
|
+
#include <cstring>
|
21
|
+
#include <string>
|
22
|
+
|
23
|
+
#include "absl/base/config.h"
|
24
|
+
|
25
|
+
namespace absl {
|
26
|
+
ABSL_NAMESPACE_BEGIN
|
27
|
+
namespace time_internal {
|
28
|
+
namespace cctz {
|
29
|
+
|
30
|
+
namespace {
|
31
|
+
|
32
|
+
// The prefix used for the internal names of fixed-offset zones.
|
33
|
+
const char kFixedZonePrefix[] = "Fixed/UTC";
|
34
|
+
|
35
|
+
const char kDigits[] = "0123456789";
|
36
|
+
|
37
|
+
char* Format02d(char* p, int v) {
|
38
|
+
*p++ = kDigits[(v / 10) % 10];
|
39
|
+
*p++ = kDigits[v % 10];
|
40
|
+
return p;
|
41
|
+
}
|
42
|
+
|
43
|
+
int Parse02d(const char* p) {
|
44
|
+
if (const char* ap = std::strchr(kDigits, *p)) {
|
45
|
+
int v = static_cast<int>(ap - kDigits);
|
46
|
+
if (const char* bp = std::strchr(kDigits, *++p)) {
|
47
|
+
return (v * 10) + static_cast<int>(bp - kDigits);
|
48
|
+
}
|
49
|
+
}
|
50
|
+
return -1;
|
51
|
+
}
|
52
|
+
|
53
|
+
} // namespace
|
54
|
+
|
55
|
+
bool FixedOffsetFromName(const std::string& name, seconds* offset) {
|
56
|
+
if (name.compare(0, std::string::npos, "UTC", 3) == 0) {
|
57
|
+
*offset = seconds::zero();
|
58
|
+
return true;
|
59
|
+
}
|
60
|
+
|
61
|
+
const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
|
62
|
+
const char* const ep = kFixedZonePrefix + prefix_len;
|
63
|
+
if (name.size() != prefix_len + 9) // <prefix>+99:99:99
|
64
|
+
return false;
|
65
|
+
if (!std::equal(kFixedZonePrefix, ep, name.begin())) return false;
|
66
|
+
const char* np = name.data() + prefix_len;
|
67
|
+
if (np[0] != '+' && np[0] != '-') return false;
|
68
|
+
if (np[3] != ':' || np[6] != ':') // see note below about large offsets
|
69
|
+
return false;
|
70
|
+
|
71
|
+
int hours = Parse02d(np + 1);
|
72
|
+
if (hours == -1) return false;
|
73
|
+
int mins = Parse02d(np + 4);
|
74
|
+
if (mins == -1) return false;
|
75
|
+
int secs = Parse02d(np + 7);
|
76
|
+
if (secs == -1) return false;
|
77
|
+
|
78
|
+
secs += ((hours * 60) + mins) * 60;
|
79
|
+
if (secs > 24 * 60 * 60) return false; // outside supported offset range
|
80
|
+
*offset = seconds(secs * (np[0] == '-' ? -1 : 1)); // "-" means west
|
81
|
+
return true;
|
82
|
+
}
|
83
|
+
|
84
|
+
std::string FixedOffsetToName(const seconds& offset) {
|
85
|
+
if (offset == seconds::zero()) return "UTC";
|
86
|
+
if (offset < std::chrono::hours(-24) || offset > std::chrono::hours(24)) {
|
87
|
+
// We don't support fixed-offset zones more than 24 hours
|
88
|
+
// away from UTC to avoid complications in rendering such
|
89
|
+
// offsets and to (somewhat) limit the total number of zones.
|
90
|
+
return "UTC";
|
91
|
+
}
|
92
|
+
int offset_seconds = static_cast<int>(offset.count());
|
93
|
+
const char sign = (offset_seconds < 0 ? '-' : '+');
|
94
|
+
int offset_minutes = offset_seconds / 60;
|
95
|
+
offset_seconds %= 60;
|
96
|
+
if (sign == '-') {
|
97
|
+
if (offset_seconds > 0) {
|
98
|
+
offset_seconds -= 60;
|
99
|
+
offset_minutes += 1;
|
100
|
+
}
|
101
|
+
offset_seconds = -offset_seconds;
|
102
|
+
offset_minutes = -offset_minutes;
|
103
|
+
}
|
104
|
+
int offset_hours = offset_minutes / 60;
|
105
|
+
offset_minutes %= 60;
|
106
|
+
const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
|
107
|
+
char buf[prefix_len + sizeof("-24:00:00")];
|
108
|
+
char* ep = std::copy(kFixedZonePrefix, kFixedZonePrefix + prefix_len, buf);
|
109
|
+
*ep++ = sign;
|
110
|
+
ep = Format02d(ep, offset_hours);
|
111
|
+
*ep++ = ':';
|
112
|
+
ep = Format02d(ep, offset_minutes);
|
113
|
+
*ep++ = ':';
|
114
|
+
ep = Format02d(ep, offset_seconds);
|
115
|
+
*ep++ = '\0';
|
116
|
+
assert(ep == buf + sizeof(buf));
|
117
|
+
return buf;
|
118
|
+
}
|
119
|
+
|
120
|
+
std::string FixedOffsetToAbbr(const seconds& offset) {
|
121
|
+
std::string abbr = FixedOffsetToName(offset);
|
122
|
+
const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
|
123
|
+
if (abbr.size() == prefix_len + 9) { // <prefix>+99:99:99
|
124
|
+
abbr.erase(0, prefix_len); // +99:99:99
|
125
|
+
abbr.erase(6, 1); // +99:9999
|
126
|
+
abbr.erase(3, 1); // +999999
|
127
|
+
if (abbr[5] == '0' && abbr[6] == '0') { // +999900
|
128
|
+
abbr.erase(5, 2); // +9999
|
129
|
+
if (abbr[3] == '0' && abbr[4] == '0') { // +9900
|
130
|
+
abbr.erase(3, 2); // +99
|
131
|
+
}
|
132
|
+
}
|
133
|
+
}
|
134
|
+
return abbr;
|
135
|
+
}
|
136
|
+
|
137
|
+
} // namespace cctz
|
138
|
+
} // namespace time_internal
|
139
|
+
ABSL_NAMESPACE_END
|
140
|
+
} // namespace absl
|
@@ -0,0 +1,52 @@
|
|
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_FIXED_H_
|
16
|
+
#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_
|
17
|
+
|
18
|
+
#include <string>
|
19
|
+
|
20
|
+
#include "absl/base/config.h"
|
21
|
+
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
|
22
|
+
|
23
|
+
namespace absl {
|
24
|
+
ABSL_NAMESPACE_BEGIN
|
25
|
+
namespace time_internal {
|
26
|
+
namespace cctz {
|
27
|
+
|
28
|
+
// Helper functions for dealing with the names and abbreviations
|
29
|
+
// of time zones that are a fixed offset (seconds east) from UTC.
|
30
|
+
// FixedOffsetFromName() extracts the offset from a valid fixed-offset
|
31
|
+
// name, while FixedOffsetToName() and FixedOffsetToAbbr() generate
|
32
|
+
// the canonical zone name and abbreviation respectively for the given
|
33
|
+
// offset.
|
34
|
+
//
|
35
|
+
// A fixed-offset name looks like "Fixed/UTC<+-><hours>:<mins>:<secs>".
|
36
|
+
// Its abbreviation is of the form "UTC(<+->H?H(MM(SS)?)?)?" where the
|
37
|
+
// optional pieces are omitted when their values are zero. (Note that
|
38
|
+
// the sign is the opposite of that used in a POSIX TZ specification.)
|
39
|
+
//
|
40
|
+
// Note: FixedOffsetFromName() fails on syntax errors or when the parsed
|
41
|
+
// offset exceeds 24 hours. FixedOffsetToName() and FixedOffsetToAbbr()
|
42
|
+
// both produce "UTC" when the argument offset exceeds 24 hours.
|
43
|
+
bool FixedOffsetFromName(const std::string& name, seconds* offset);
|
44
|
+
std::string FixedOffsetToName(const seconds& offset);
|
45
|
+
std::string FixedOffsetToAbbr(const seconds& offset);
|
46
|
+
|
47
|
+
} // namespace cctz
|
48
|
+
} // namespace time_internal
|
49
|
+
ABSL_NAMESPACE_END
|
50
|
+
} // namespace absl
|
51
|
+
|
52
|
+
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_
|
@@ -0,0 +1,922 @@
|
|
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
|
+
#if !defined(HAS_STRPTIME)
|
16
|
+
#if !defined(_MSC_VER) && !defined(__MINGW32__)
|
17
|
+
#define HAS_STRPTIME 1 // assume everyone has strptime() except windows
|
18
|
+
#endif
|
19
|
+
#endif
|
20
|
+
|
21
|
+
#if defined(HAS_STRPTIME) && HAS_STRPTIME
|
22
|
+
#if !defined(_XOPEN_SOURCE)
|
23
|
+
#define _XOPEN_SOURCE // Definedness suffices for strptime.
|
24
|
+
#endif
|
25
|
+
#endif
|
26
|
+
|
27
|
+
#include "absl/base/config.h"
|
28
|
+
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
|
29
|
+
|
30
|
+
// Include time.h directly since, by C++ standards, ctime doesn't have to
|
31
|
+
// declare strptime.
|
32
|
+
#include <time.h>
|
33
|
+
|
34
|
+
#include <cctype>
|
35
|
+
#include <chrono>
|
36
|
+
#include <cstddef>
|
37
|
+
#include <cstdint>
|
38
|
+
#include <cstring>
|
39
|
+
#include <ctime>
|
40
|
+
#include <limits>
|
41
|
+
#include <string>
|
42
|
+
#include <vector>
|
43
|
+
#if !HAS_STRPTIME
|
44
|
+
#include <iomanip>
|
45
|
+
#include <sstream>
|
46
|
+
#endif
|
47
|
+
|
48
|
+
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
|
49
|
+
#include "time_zone_if.h"
|
50
|
+
|
51
|
+
namespace absl {
|
52
|
+
ABSL_NAMESPACE_BEGIN
|
53
|
+
namespace time_internal {
|
54
|
+
namespace cctz {
|
55
|
+
namespace detail {
|
56
|
+
|
57
|
+
namespace {
|
58
|
+
|
59
|
+
#if !HAS_STRPTIME
|
60
|
+
// Build a strptime() using C++11's std::get_time().
|
61
|
+
char* strptime(const char* s, const char* fmt, std::tm* tm) {
|
62
|
+
std::istringstream input(s);
|
63
|
+
input >> std::get_time(tm, fmt);
|
64
|
+
if (input.fail()) return nullptr;
|
65
|
+
return const_cast<char*>(s) +
|
66
|
+
(input.eof() ? strlen(s) : static_cast<std::size_t>(input.tellg()));
|
67
|
+
}
|
68
|
+
#endif
|
69
|
+
|
70
|
+
std::tm ToTM(const time_zone::absolute_lookup& al) {
|
71
|
+
std::tm tm{};
|
72
|
+
tm.tm_sec = al.cs.second();
|
73
|
+
tm.tm_min = al.cs.minute();
|
74
|
+
tm.tm_hour = al.cs.hour();
|
75
|
+
tm.tm_mday = al.cs.day();
|
76
|
+
tm.tm_mon = al.cs.month() - 1;
|
77
|
+
|
78
|
+
// Saturate tm.tm_year is cases of over/underflow.
|
79
|
+
if (al.cs.year() < std::numeric_limits<int>::min() + 1900) {
|
80
|
+
tm.tm_year = std::numeric_limits<int>::min();
|
81
|
+
} else if (al.cs.year() - 1900 > std::numeric_limits<int>::max()) {
|
82
|
+
tm.tm_year = std::numeric_limits<int>::max();
|
83
|
+
} else {
|
84
|
+
tm.tm_year = static_cast<int>(al.cs.year() - 1900);
|
85
|
+
}
|
86
|
+
|
87
|
+
switch (get_weekday(al.cs)) {
|
88
|
+
case weekday::sunday:
|
89
|
+
tm.tm_wday = 0;
|
90
|
+
break;
|
91
|
+
case weekday::monday:
|
92
|
+
tm.tm_wday = 1;
|
93
|
+
break;
|
94
|
+
case weekday::tuesday:
|
95
|
+
tm.tm_wday = 2;
|
96
|
+
break;
|
97
|
+
case weekday::wednesday:
|
98
|
+
tm.tm_wday = 3;
|
99
|
+
break;
|
100
|
+
case weekday::thursday:
|
101
|
+
tm.tm_wday = 4;
|
102
|
+
break;
|
103
|
+
case weekday::friday:
|
104
|
+
tm.tm_wday = 5;
|
105
|
+
break;
|
106
|
+
case weekday::saturday:
|
107
|
+
tm.tm_wday = 6;
|
108
|
+
break;
|
109
|
+
}
|
110
|
+
tm.tm_yday = get_yearday(al.cs) - 1;
|
111
|
+
tm.tm_isdst = al.is_dst ? 1 : 0;
|
112
|
+
return tm;
|
113
|
+
}
|
114
|
+
|
115
|
+
const char kDigits[] = "0123456789";
|
116
|
+
|
117
|
+
// Formats a 64-bit integer in the given field width. Note that it is up
|
118
|
+
// to the caller of Format64() [and Format02d()/FormatOffset()] to ensure
|
119
|
+
// that there is sufficient space before ep to hold the conversion.
|
120
|
+
char* Format64(char* ep, int width, std::int_fast64_t v) {
|
121
|
+
bool neg = false;
|
122
|
+
if (v < 0) {
|
123
|
+
--width;
|
124
|
+
neg = true;
|
125
|
+
if (v == std::numeric_limits<std::int_fast64_t>::min()) {
|
126
|
+
// Avoid negating minimum value.
|
127
|
+
std::int_fast64_t last_digit = -(v % 10);
|
128
|
+
v /= 10;
|
129
|
+
if (last_digit < 0) {
|
130
|
+
++v;
|
131
|
+
last_digit += 10;
|
132
|
+
}
|
133
|
+
--width;
|
134
|
+
*--ep = kDigits[last_digit];
|
135
|
+
}
|
136
|
+
v = -v;
|
137
|
+
}
|
138
|
+
do {
|
139
|
+
--width;
|
140
|
+
*--ep = kDigits[v % 10];
|
141
|
+
} while (v /= 10);
|
142
|
+
while (--width >= 0) *--ep = '0'; // zero pad
|
143
|
+
if (neg) *--ep = '-';
|
144
|
+
return ep;
|
145
|
+
}
|
146
|
+
|
147
|
+
// Formats [0 .. 99] as %02d.
|
148
|
+
char* Format02d(char* ep, int v) {
|
149
|
+
*--ep = kDigits[v % 10];
|
150
|
+
*--ep = kDigits[(v / 10) % 10];
|
151
|
+
return ep;
|
152
|
+
}
|
153
|
+
|
154
|
+
// Formats a UTC offset, like +00:00.
|
155
|
+
char* FormatOffset(char* ep, int offset, const char* mode) {
|
156
|
+
// TODO: Follow the RFC3339 "Unknown Local Offset Convention" and
|
157
|
+
// generate a "negative zero" when we're formatting a zero offset
|
158
|
+
// as the result of a failed load_time_zone().
|
159
|
+
char sign = '+';
|
160
|
+
if (offset < 0) {
|
161
|
+
offset = -offset; // bounded by 24h so no overflow
|
162
|
+
sign = '-';
|
163
|
+
}
|
164
|
+
const int seconds = offset % 60;
|
165
|
+
const int minutes = (offset /= 60) % 60;
|
166
|
+
const int hours = offset /= 60;
|
167
|
+
const char sep = mode[0];
|
168
|
+
const bool ext = (sep != '\0' && mode[1] == '*');
|
169
|
+
const bool ccc = (ext && mode[2] == ':');
|
170
|
+
if (ext && (!ccc || seconds != 0)) {
|
171
|
+
ep = Format02d(ep, seconds);
|
172
|
+
*--ep = sep;
|
173
|
+
} else {
|
174
|
+
// If we're not rendering seconds, sub-minute negative offsets
|
175
|
+
// should get a positive sign (e.g., offset=-10s => "+00:00").
|
176
|
+
if (hours == 0 && minutes == 0) sign = '+';
|
177
|
+
}
|
178
|
+
if (!ccc || minutes != 0 || seconds != 0) {
|
179
|
+
ep = Format02d(ep, minutes);
|
180
|
+
if (sep != '\0') *--ep = sep;
|
181
|
+
}
|
182
|
+
ep = Format02d(ep, hours);
|
183
|
+
*--ep = sign;
|
184
|
+
return ep;
|
185
|
+
}
|
186
|
+
|
187
|
+
// Formats a std::tm using strftime(3).
|
188
|
+
void FormatTM(std::string* out, const std::string& fmt, const std::tm& tm) {
|
189
|
+
// strftime(3) returns the number of characters placed in the output
|
190
|
+
// array (which may be 0 characters). It also returns 0 to indicate
|
191
|
+
// an error, like the array wasn't large enough. To accommodate this,
|
192
|
+
// the following code grows the buffer size from 2x the format std::string
|
193
|
+
// length up to 32x.
|
194
|
+
for (std::size_t i = 2; i != 32; i *= 2) {
|
195
|
+
std::size_t buf_size = fmt.size() * i;
|
196
|
+
std::vector<char> buf(buf_size);
|
197
|
+
if (std::size_t len = strftime(&buf[0], buf_size, fmt.c_str(), &tm)) {
|
198
|
+
out->append(&buf[0], len);
|
199
|
+
return;
|
200
|
+
}
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
// Used for %E#S/%E#f specifiers and for data values in parse().
|
205
|
+
template <typename T>
|
206
|
+
const char* ParseInt(const char* dp, int width, T min, T max, T* vp) {
|
207
|
+
if (dp != nullptr) {
|
208
|
+
const T kmin = std::numeric_limits<T>::min();
|
209
|
+
bool erange = false;
|
210
|
+
bool neg = false;
|
211
|
+
T value = 0;
|
212
|
+
if (*dp == '-') {
|
213
|
+
neg = true;
|
214
|
+
if (width <= 0 || --width != 0) {
|
215
|
+
++dp;
|
216
|
+
} else {
|
217
|
+
dp = nullptr; // width was 1
|
218
|
+
}
|
219
|
+
}
|
220
|
+
if (const char* const bp = dp) {
|
221
|
+
while (const char* cp = strchr(kDigits, *dp)) {
|
222
|
+
int d = static_cast<int>(cp - kDigits);
|
223
|
+
if (d >= 10) break;
|
224
|
+
if (value < kmin / 10) {
|
225
|
+
erange = true;
|
226
|
+
break;
|
227
|
+
}
|
228
|
+
value *= 10;
|
229
|
+
if (value < kmin + d) {
|
230
|
+
erange = true;
|
231
|
+
break;
|
232
|
+
}
|
233
|
+
value -= d;
|
234
|
+
dp += 1;
|
235
|
+
if (width > 0 && --width == 0) break;
|
236
|
+
}
|
237
|
+
if (dp != bp && !erange && (neg || value != kmin)) {
|
238
|
+
if (!neg || value != 0) {
|
239
|
+
if (!neg) value = -value; // make positive
|
240
|
+
if (min <= value && value <= max) {
|
241
|
+
*vp = value;
|
242
|
+
} else {
|
243
|
+
dp = nullptr;
|
244
|
+
}
|
245
|
+
} else {
|
246
|
+
dp = nullptr;
|
247
|
+
}
|
248
|
+
} else {
|
249
|
+
dp = nullptr;
|
250
|
+
}
|
251
|
+
}
|
252
|
+
}
|
253
|
+
return dp;
|
254
|
+
}
|
255
|
+
|
256
|
+
// The number of base-10 digits that can be represented by a signed 64-bit
|
257
|
+
// integer. That is, 10^kDigits10_64 <= 2^63 - 1 < 10^(kDigits10_64 + 1).
|
258
|
+
const int kDigits10_64 = 18;
|
259
|
+
|
260
|
+
// 10^n for everything that can be represented by a signed 64-bit integer.
|
261
|
+
const std::int_fast64_t kExp10[kDigits10_64 + 1] = {
|
262
|
+
1,
|
263
|
+
10,
|
264
|
+
100,
|
265
|
+
1000,
|
266
|
+
10000,
|
267
|
+
100000,
|
268
|
+
1000000,
|
269
|
+
10000000,
|
270
|
+
100000000,
|
271
|
+
1000000000,
|
272
|
+
10000000000,
|
273
|
+
100000000000,
|
274
|
+
1000000000000,
|
275
|
+
10000000000000,
|
276
|
+
100000000000000,
|
277
|
+
1000000000000000,
|
278
|
+
10000000000000000,
|
279
|
+
100000000000000000,
|
280
|
+
1000000000000000000,
|
281
|
+
};
|
282
|
+
|
283
|
+
} // namespace
|
284
|
+
|
285
|
+
// Uses strftime(3) to format the given Time. The following extended format
|
286
|
+
// specifiers are also supported:
|
287
|
+
//
|
288
|
+
// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)
|
289
|
+
// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)
|
290
|
+
// - %E#S - Seconds with # digits of fractional precision
|
291
|
+
// - %E*S - Seconds with full fractional precision (a literal '*')
|
292
|
+
// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
|
293
|
+
//
|
294
|
+
// The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are
|
295
|
+
// handled internally for performance reasons. strftime(3) is slow due to
|
296
|
+
// a POSIX requirement to respect changes to ${TZ}.
|
297
|
+
//
|
298
|
+
// The TZ/GNU %s extension is handled internally because strftime() has
|
299
|
+
// to use mktime() to generate it, and that assumes the local time zone.
|
300
|
+
//
|
301
|
+
// We also handle the %z and %Z specifiers to accommodate platforms that do
|
302
|
+
// not support the tm_gmtoff and tm_zone extensions to std::tm.
|
303
|
+
//
|
304
|
+
// Requires that zero() <= fs < seconds(1).
|
305
|
+
std::string format(const std::string& format, const time_point<seconds>& tp,
|
306
|
+
const detail::femtoseconds& fs, const time_zone& tz) {
|
307
|
+
std::string result;
|
308
|
+
result.reserve(format.size()); // A reasonable guess for the result size.
|
309
|
+
const time_zone::absolute_lookup al = tz.lookup(tp);
|
310
|
+
const std::tm tm = ToTM(al);
|
311
|
+
|
312
|
+
// Scratch buffer for internal conversions.
|
313
|
+
char buf[3 + kDigits10_64]; // enough for longest conversion
|
314
|
+
char* const ep = buf + sizeof(buf);
|
315
|
+
char* bp; // works back from ep
|
316
|
+
|
317
|
+
// Maintain three, disjoint subsequences that span format.
|
318
|
+
// [format.begin() ... pending) : already formatted into result
|
319
|
+
// [pending ... cur) : formatting pending, but no special cases
|
320
|
+
// [cur ... format.end()) : unexamined
|
321
|
+
// Initially, everything is in the unexamined part.
|
322
|
+
const char* pending = format.c_str(); // NUL terminated
|
323
|
+
const char* cur = pending;
|
324
|
+
const char* end = pending + format.length();
|
325
|
+
|
326
|
+
while (cur != end) { // while something is unexamined
|
327
|
+
// Moves cur to the next percent sign.
|
328
|
+
const char* start = cur;
|
329
|
+
while (cur != end && *cur != '%') ++cur;
|
330
|
+
|
331
|
+
// If the new pending text is all ordinary, copy it out.
|
332
|
+
if (cur != start && pending == start) {
|
333
|
+
result.append(pending, static_cast<std::size_t>(cur - pending));
|
334
|
+
pending = start = cur;
|
335
|
+
}
|
336
|
+
|
337
|
+
// Span the sequential percent signs.
|
338
|
+
const char* percent = cur;
|
339
|
+
while (cur != end && *cur == '%') ++cur;
|
340
|
+
|
341
|
+
// If the new pending text is all percents, copy out one
|
342
|
+
// percent for every matched pair, then skip those pairs.
|
343
|
+
if (cur != start && pending == start) {
|
344
|
+
std::size_t escaped = static_cast<std::size_t>(cur - pending) / 2;
|
345
|
+
result.append(pending, escaped);
|
346
|
+
pending += escaped * 2;
|
347
|
+
// Also copy out a single trailing percent.
|
348
|
+
if (pending != cur && cur == end) {
|
349
|
+
result.push_back(*pending++);
|
350
|
+
}
|
351
|
+
}
|
352
|
+
|
353
|
+
// Loop unless we have an unescaped percent.
|
354
|
+
if (cur == end || (cur - percent) % 2 == 0) continue;
|
355
|
+
|
356
|
+
// Simple specifiers that we handle ourselves.
|
357
|
+
if (strchr("YmdeHMSzZs%", *cur)) {
|
358
|
+
if (cur - 1 != pending) {
|
359
|
+
FormatTM(&result, std::string(pending, cur - 1), tm);
|
360
|
+
}
|
361
|
+
switch (*cur) {
|
362
|
+
case 'Y':
|
363
|
+
// This avoids the tm.tm_year overflow problem for %Y, however
|
364
|
+
// tm.tm_year will still be used by other specifiers like %D.
|
365
|
+
bp = Format64(ep, 0, al.cs.year());
|
366
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
367
|
+
break;
|
368
|
+
case 'm':
|
369
|
+
bp = Format02d(ep, al.cs.month());
|
370
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
371
|
+
break;
|
372
|
+
case 'd':
|
373
|
+
case 'e':
|
374
|
+
bp = Format02d(ep, al.cs.day());
|
375
|
+
if (*cur == 'e' && *bp == '0') *bp = ' '; // for Windows
|
376
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
377
|
+
break;
|
378
|
+
case 'H':
|
379
|
+
bp = Format02d(ep, al.cs.hour());
|
380
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
381
|
+
break;
|
382
|
+
case 'M':
|
383
|
+
bp = Format02d(ep, al.cs.minute());
|
384
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
385
|
+
break;
|
386
|
+
case 'S':
|
387
|
+
bp = Format02d(ep, al.cs.second());
|
388
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
389
|
+
break;
|
390
|
+
case 'z':
|
391
|
+
bp = FormatOffset(ep, al.offset, "");
|
392
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
393
|
+
break;
|
394
|
+
case 'Z':
|
395
|
+
result.append(al.abbr);
|
396
|
+
break;
|
397
|
+
case 's':
|
398
|
+
bp = Format64(ep, 0, ToUnixSeconds(tp));
|
399
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
400
|
+
break;
|
401
|
+
case '%':
|
402
|
+
result.push_back('%');
|
403
|
+
break;
|
404
|
+
}
|
405
|
+
pending = ++cur;
|
406
|
+
continue;
|
407
|
+
}
|
408
|
+
|
409
|
+
// More complex specifiers that we handle ourselves.
|
410
|
+
if (*cur == ':' && cur + 1 != end) {
|
411
|
+
if (*(cur + 1) == 'z') {
|
412
|
+
// Formats %:z.
|
413
|
+
if (cur - 1 != pending) {
|
414
|
+
FormatTM(&result, std::string(pending, cur - 1), tm);
|
415
|
+
}
|
416
|
+
bp = FormatOffset(ep, al.offset, ":");
|
417
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
418
|
+
pending = cur += 2;
|
419
|
+
continue;
|
420
|
+
}
|
421
|
+
if (*(cur + 1) == ':' && cur + 2 != end) {
|
422
|
+
if (*(cur + 2) == 'z') {
|
423
|
+
// Formats %::z.
|
424
|
+
if (cur - 1 != pending) {
|
425
|
+
FormatTM(&result, std::string(pending, cur - 1), tm);
|
426
|
+
}
|
427
|
+
bp = FormatOffset(ep, al.offset, ":*");
|
428
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
429
|
+
pending = cur += 3;
|
430
|
+
continue;
|
431
|
+
}
|
432
|
+
if (*(cur + 2) == ':' && cur + 3 != end) {
|
433
|
+
if (*(cur + 3) == 'z') {
|
434
|
+
// Formats %:::z.
|
435
|
+
if (cur - 1 != pending) {
|
436
|
+
FormatTM(&result, std::string(pending, cur - 1), tm);
|
437
|
+
}
|
438
|
+
bp = FormatOffset(ep, al.offset, ":*:");
|
439
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
440
|
+
pending = cur += 4;
|
441
|
+
continue;
|
442
|
+
}
|
443
|
+
}
|
444
|
+
}
|
445
|
+
}
|
446
|
+
|
447
|
+
// Loop if there is no E modifier.
|
448
|
+
if (*cur != 'E' || ++cur == end) continue;
|
449
|
+
|
450
|
+
// Format our extensions.
|
451
|
+
if (*cur == 'z') {
|
452
|
+
// Formats %Ez.
|
453
|
+
if (cur - 2 != pending) {
|
454
|
+
FormatTM(&result, std::string(pending, cur - 2), tm);
|
455
|
+
}
|
456
|
+
bp = FormatOffset(ep, al.offset, ":");
|
457
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
458
|
+
pending = ++cur;
|
459
|
+
} else if (*cur == '*' && cur + 1 != end && *(cur + 1) == 'z') {
|
460
|
+
// Formats %E*z.
|
461
|
+
if (cur - 2 != pending) {
|
462
|
+
FormatTM(&result, std::string(pending, cur - 2), tm);
|
463
|
+
}
|
464
|
+
bp = FormatOffset(ep, al.offset, ":*");
|
465
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
466
|
+
pending = cur += 2;
|
467
|
+
} else if (*cur == '*' && cur + 1 != end &&
|
468
|
+
(*(cur + 1) == 'S' || *(cur + 1) == 'f')) {
|
469
|
+
// Formats %E*S or %E*F.
|
470
|
+
if (cur - 2 != pending) {
|
471
|
+
FormatTM(&result, std::string(pending, cur - 2), tm);
|
472
|
+
}
|
473
|
+
char* cp = ep;
|
474
|
+
bp = Format64(cp, 15, fs.count());
|
475
|
+
while (cp != bp && cp[-1] == '0') --cp;
|
476
|
+
switch (*(cur + 1)) {
|
477
|
+
case 'S':
|
478
|
+
if (cp != bp) *--bp = '.';
|
479
|
+
bp = Format02d(bp, al.cs.second());
|
480
|
+
break;
|
481
|
+
case 'f':
|
482
|
+
if (cp == bp) *--bp = '0';
|
483
|
+
break;
|
484
|
+
}
|
485
|
+
result.append(bp, static_cast<std::size_t>(cp - bp));
|
486
|
+
pending = cur += 2;
|
487
|
+
} else if (*cur == '4' && cur + 1 != end && *(cur + 1) == 'Y') {
|
488
|
+
// Formats %E4Y.
|
489
|
+
if (cur - 2 != pending) {
|
490
|
+
FormatTM(&result, std::string(pending, cur - 2), tm);
|
491
|
+
}
|
492
|
+
bp = Format64(ep, 4, al.cs.year());
|
493
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
494
|
+
pending = cur += 2;
|
495
|
+
} else if (std::isdigit(*cur)) {
|
496
|
+
// Possibly found %E#S or %E#f.
|
497
|
+
int n = 0;
|
498
|
+
if (const char* np = ParseInt(cur, 0, 0, 1024, &n)) {
|
499
|
+
if (*np == 'S' || *np == 'f') {
|
500
|
+
// Formats %E#S or %E#f.
|
501
|
+
if (cur - 2 != pending) {
|
502
|
+
FormatTM(&result, std::string(pending, cur - 2), tm);
|
503
|
+
}
|
504
|
+
bp = ep;
|
505
|
+
if (n > 0) {
|
506
|
+
if (n > kDigits10_64) n = kDigits10_64;
|
507
|
+
bp = Format64(bp, n,
|
508
|
+
(n > 15) ? fs.count() * kExp10[n - 15]
|
509
|
+
: fs.count() / kExp10[15 - n]);
|
510
|
+
if (*np == 'S') *--bp = '.';
|
511
|
+
}
|
512
|
+
if (*np == 'S') bp = Format02d(bp, al.cs.second());
|
513
|
+
result.append(bp, static_cast<std::size_t>(ep - bp));
|
514
|
+
pending = cur = ++np;
|
515
|
+
}
|
516
|
+
}
|
517
|
+
}
|
518
|
+
}
|
519
|
+
|
520
|
+
// Formats any remaining data.
|
521
|
+
if (end != pending) {
|
522
|
+
FormatTM(&result, std::string(pending, end), tm);
|
523
|
+
}
|
524
|
+
|
525
|
+
return result;
|
526
|
+
}
|
527
|
+
|
528
|
+
namespace {
|
529
|
+
|
530
|
+
const char* ParseOffset(const char* dp, const char* mode, int* offset) {
|
531
|
+
if (dp != nullptr) {
|
532
|
+
const char first = *dp++;
|
533
|
+
if (first == '+' || first == '-') {
|
534
|
+
char sep = mode[0];
|
535
|
+
int hours = 0;
|
536
|
+
int minutes = 0;
|
537
|
+
int seconds = 0;
|
538
|
+
const char* ap = ParseInt(dp, 2, 0, 23, &hours);
|
539
|
+
if (ap != nullptr && ap - dp == 2) {
|
540
|
+
dp = ap;
|
541
|
+
if (sep != '\0' && *ap == sep) ++ap;
|
542
|
+
const char* bp = ParseInt(ap, 2, 0, 59, &minutes);
|
543
|
+
if (bp != nullptr && bp - ap == 2) {
|
544
|
+
dp = bp;
|
545
|
+
if (sep != '\0' && *bp == sep) ++bp;
|
546
|
+
const char* cp = ParseInt(bp, 2, 0, 59, &seconds);
|
547
|
+
if (cp != nullptr && cp - bp == 2) dp = cp;
|
548
|
+
}
|
549
|
+
*offset = ((hours * 60 + minutes) * 60) + seconds;
|
550
|
+
if (first == '-') *offset = -*offset;
|
551
|
+
} else {
|
552
|
+
dp = nullptr;
|
553
|
+
}
|
554
|
+
} else if (first == 'Z') { // Zulu
|
555
|
+
*offset = 0;
|
556
|
+
} else {
|
557
|
+
dp = nullptr;
|
558
|
+
}
|
559
|
+
}
|
560
|
+
return dp;
|
561
|
+
}
|
562
|
+
|
563
|
+
const char* ParseZone(const char* dp, std::string* zone) {
|
564
|
+
zone->clear();
|
565
|
+
if (dp != nullptr) {
|
566
|
+
while (*dp != '\0' && !std::isspace(*dp)) zone->push_back(*dp++);
|
567
|
+
if (zone->empty()) dp = nullptr;
|
568
|
+
}
|
569
|
+
return dp;
|
570
|
+
}
|
571
|
+
|
572
|
+
const char* ParseSubSeconds(const char* dp, detail::femtoseconds* subseconds) {
|
573
|
+
if (dp != nullptr) {
|
574
|
+
std::int_fast64_t v = 0;
|
575
|
+
std::int_fast64_t exp = 0;
|
576
|
+
const char* const bp = dp;
|
577
|
+
while (const char* cp = strchr(kDigits, *dp)) {
|
578
|
+
int d = static_cast<int>(cp - kDigits);
|
579
|
+
if (d >= 10) break;
|
580
|
+
if (exp < 15) {
|
581
|
+
exp += 1;
|
582
|
+
v *= 10;
|
583
|
+
v += d;
|
584
|
+
}
|
585
|
+
++dp;
|
586
|
+
}
|
587
|
+
if (dp != bp) {
|
588
|
+
v *= kExp10[15 - exp];
|
589
|
+
*subseconds = detail::femtoseconds(v);
|
590
|
+
} else {
|
591
|
+
dp = nullptr;
|
592
|
+
}
|
593
|
+
}
|
594
|
+
return dp;
|
595
|
+
}
|
596
|
+
|
597
|
+
// Parses a string into a std::tm using strptime(3).
|
598
|
+
const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) {
|
599
|
+
if (dp != nullptr) {
|
600
|
+
dp = strptime(dp, fmt, tm);
|
601
|
+
}
|
602
|
+
return dp;
|
603
|
+
}
|
604
|
+
|
605
|
+
} // namespace
|
606
|
+
|
607
|
+
// Uses strptime(3) to parse the given input. Supports the same extended
|
608
|
+
// format specifiers as format(), although %E#S and %E*S are treated
|
609
|
+
// identically (and similarly for %E#f and %E*f). %Ez and %E*z also accept
|
610
|
+
// the same inputs.
|
611
|
+
//
|
612
|
+
// The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are
|
613
|
+
// handled internally so that we can normally avoid strptime() altogether
|
614
|
+
// (which is particularly helpful when the native implementation is broken).
|
615
|
+
//
|
616
|
+
// The TZ/GNU %s extension is handled internally because strptime() has to
|
617
|
+
// use localtime_r() to generate it, and that assumes the local time zone.
|
618
|
+
//
|
619
|
+
// We also handle the %z specifier to accommodate platforms that do not
|
620
|
+
// support the tm_gmtoff extension to std::tm. %Z is parsed but ignored.
|
621
|
+
bool parse(const std::string& format, const std::string& input,
|
622
|
+
const time_zone& tz, time_point<seconds>* sec,
|
623
|
+
detail::femtoseconds* fs, std::string* err) {
|
624
|
+
// The unparsed input.
|
625
|
+
const char* data = input.c_str(); // NUL terminated
|
626
|
+
|
627
|
+
// Skips leading whitespace.
|
628
|
+
while (std::isspace(*data)) ++data;
|
629
|
+
|
630
|
+
const year_t kyearmax = std::numeric_limits<year_t>::max();
|
631
|
+
const year_t kyearmin = std::numeric_limits<year_t>::min();
|
632
|
+
|
633
|
+
// Sets default values for unspecified fields.
|
634
|
+
bool saw_year = false;
|
635
|
+
year_t year = 1970;
|
636
|
+
std::tm tm{};
|
637
|
+
tm.tm_year = 1970 - 1900;
|
638
|
+
tm.tm_mon = 1 - 1; // Jan
|
639
|
+
tm.tm_mday = 1;
|
640
|
+
tm.tm_hour = 0;
|
641
|
+
tm.tm_min = 0;
|
642
|
+
tm.tm_sec = 0;
|
643
|
+
tm.tm_wday = 4; // Thu
|
644
|
+
tm.tm_yday = 0;
|
645
|
+
tm.tm_isdst = 0;
|
646
|
+
auto subseconds = detail::femtoseconds::zero();
|
647
|
+
bool saw_offset = false;
|
648
|
+
int offset = 0; // No offset from passed tz.
|
649
|
+
std::string zone = "UTC";
|
650
|
+
|
651
|
+
const char* fmt = format.c_str(); // NUL terminated
|
652
|
+
bool twelve_hour = false;
|
653
|
+
bool afternoon = false;
|
654
|
+
|
655
|
+
bool saw_percent_s = false;
|
656
|
+
std::int_fast64_t percent_s = 0;
|
657
|
+
|
658
|
+
// Steps through format, one specifier at a time.
|
659
|
+
while (data != nullptr && *fmt != '\0') {
|
660
|
+
if (std::isspace(*fmt)) {
|
661
|
+
while (std::isspace(*data)) ++data;
|
662
|
+
while (std::isspace(*++fmt)) continue;
|
663
|
+
continue;
|
664
|
+
}
|
665
|
+
|
666
|
+
if (*fmt != '%') {
|
667
|
+
if (*data == *fmt) {
|
668
|
+
++data;
|
669
|
+
++fmt;
|
670
|
+
} else {
|
671
|
+
data = nullptr;
|
672
|
+
}
|
673
|
+
continue;
|
674
|
+
}
|
675
|
+
|
676
|
+
const char* percent = fmt;
|
677
|
+
if (*++fmt == '\0') {
|
678
|
+
data = nullptr;
|
679
|
+
continue;
|
680
|
+
}
|
681
|
+
switch (*fmt++) {
|
682
|
+
case 'Y':
|
683
|
+
// Symmetrically with FormatTime(), directly handing %Y avoids the
|
684
|
+
// tm.tm_year overflow problem. However, tm.tm_year will still be
|
685
|
+
// used by other specifiers like %D.
|
686
|
+
data = ParseInt(data, 0, kyearmin, kyearmax, &year);
|
687
|
+
if (data != nullptr) saw_year = true;
|
688
|
+
continue;
|
689
|
+
case 'm':
|
690
|
+
data = ParseInt(data, 2, 1, 12, &tm.tm_mon);
|
691
|
+
if (data != nullptr) tm.tm_mon -= 1;
|
692
|
+
continue;
|
693
|
+
case 'd':
|
694
|
+
case 'e':
|
695
|
+
data = ParseInt(data, 2, 1, 31, &tm.tm_mday);
|
696
|
+
continue;
|
697
|
+
case 'H':
|
698
|
+
data = ParseInt(data, 2, 0, 23, &tm.tm_hour);
|
699
|
+
twelve_hour = false;
|
700
|
+
continue;
|
701
|
+
case 'M':
|
702
|
+
data = ParseInt(data, 2, 0, 59, &tm.tm_min);
|
703
|
+
continue;
|
704
|
+
case 'S':
|
705
|
+
data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
|
706
|
+
continue;
|
707
|
+
case 'I':
|
708
|
+
case 'l':
|
709
|
+
case 'r': // probably uses %I
|
710
|
+
twelve_hour = true;
|
711
|
+
break;
|
712
|
+
case 'R': // uses %H
|
713
|
+
case 'T': // uses %H
|
714
|
+
case 'c': // probably uses %H
|
715
|
+
case 'X': // probably uses %H
|
716
|
+
twelve_hour = false;
|
717
|
+
break;
|
718
|
+
case 'z':
|
719
|
+
data = ParseOffset(data, "", &offset);
|
720
|
+
if (data != nullptr) saw_offset = true;
|
721
|
+
continue;
|
722
|
+
case 'Z': // ignored; zone abbreviations are ambiguous
|
723
|
+
data = ParseZone(data, &zone);
|
724
|
+
continue;
|
725
|
+
case 's':
|
726
|
+
data =
|
727
|
+
ParseInt(data, 0, std::numeric_limits<std::int_fast64_t>::min(),
|
728
|
+
std::numeric_limits<std::int_fast64_t>::max(), &percent_s);
|
729
|
+
if (data != nullptr) saw_percent_s = true;
|
730
|
+
continue;
|
731
|
+
case ':':
|
732
|
+
if (fmt[0] == 'z' ||
|
733
|
+
(fmt[0] == ':' &&
|
734
|
+
(fmt[1] == 'z' || (fmt[1] == ':' && fmt[2] == 'z')))) {
|
735
|
+
data = ParseOffset(data, ":", &offset);
|
736
|
+
if (data != nullptr) saw_offset = true;
|
737
|
+
fmt += (fmt[0] == 'z') ? 1 : (fmt[1] == 'z') ? 2 : 3;
|
738
|
+
continue;
|
739
|
+
}
|
740
|
+
break;
|
741
|
+
case '%':
|
742
|
+
data = (*data == '%' ? data + 1 : nullptr);
|
743
|
+
continue;
|
744
|
+
case 'E':
|
745
|
+
if (fmt[0] == 'z' || (fmt[0] == '*' && fmt[1] == 'z')) {
|
746
|
+
data = ParseOffset(data, ":", &offset);
|
747
|
+
if (data != nullptr) saw_offset = true;
|
748
|
+
fmt += (fmt[0] == 'z') ? 1 : 2;
|
749
|
+
continue;
|
750
|
+
}
|
751
|
+
if (fmt[0] == '*' && fmt[1] == 'S') {
|
752
|
+
data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
|
753
|
+
if (data != nullptr && *data == '.') {
|
754
|
+
data = ParseSubSeconds(data + 1, &subseconds);
|
755
|
+
}
|
756
|
+
fmt += 2;
|
757
|
+
continue;
|
758
|
+
}
|
759
|
+
if (fmt[0] == '*' && fmt[1] == 'f') {
|
760
|
+
if (data != nullptr && std::isdigit(*data)) {
|
761
|
+
data = ParseSubSeconds(data, &subseconds);
|
762
|
+
}
|
763
|
+
fmt += 2;
|
764
|
+
continue;
|
765
|
+
}
|
766
|
+
if (fmt[0] == '4' && fmt[1] == 'Y') {
|
767
|
+
const char* bp = data;
|
768
|
+
data = ParseInt(data, 4, year_t{-999}, year_t{9999}, &year);
|
769
|
+
if (data != nullptr) {
|
770
|
+
if (data - bp == 4) {
|
771
|
+
saw_year = true;
|
772
|
+
} else {
|
773
|
+
data = nullptr; // stopped too soon
|
774
|
+
}
|
775
|
+
}
|
776
|
+
fmt += 2;
|
777
|
+
continue;
|
778
|
+
}
|
779
|
+
if (std::isdigit(*fmt)) {
|
780
|
+
int n = 0; // value ignored
|
781
|
+
if (const char* np = ParseInt(fmt, 0, 0, 1024, &n)) {
|
782
|
+
if (*np == 'S') {
|
783
|
+
data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
|
784
|
+
if (data != nullptr && *data == '.') {
|
785
|
+
data = ParseSubSeconds(data + 1, &subseconds);
|
786
|
+
}
|
787
|
+
fmt = ++np;
|
788
|
+
continue;
|
789
|
+
}
|
790
|
+
if (*np == 'f') {
|
791
|
+
if (data != nullptr && std::isdigit(*data)) {
|
792
|
+
data = ParseSubSeconds(data, &subseconds);
|
793
|
+
}
|
794
|
+
fmt = ++np;
|
795
|
+
continue;
|
796
|
+
}
|
797
|
+
}
|
798
|
+
}
|
799
|
+
if (*fmt == 'c') twelve_hour = false; // probably uses %H
|
800
|
+
if (*fmt == 'X') twelve_hour = false; // probably uses %H
|
801
|
+
if (*fmt != '\0') ++fmt;
|
802
|
+
break;
|
803
|
+
case 'O':
|
804
|
+
if (*fmt == 'H') twelve_hour = false;
|
805
|
+
if (*fmt == 'I') twelve_hour = true;
|
806
|
+
if (*fmt != '\0') ++fmt;
|
807
|
+
break;
|
808
|
+
}
|
809
|
+
|
810
|
+
// Parses the current specifier.
|
811
|
+
const char* orig_data = data;
|
812
|
+
std::string spec(percent, static_cast<std::size_t>(fmt - percent));
|
813
|
+
data = ParseTM(data, spec.c_str(), &tm);
|
814
|
+
|
815
|
+
// If we successfully parsed %p we need to remember whether the result
|
816
|
+
// was AM or PM so that we can adjust tm_hour before time_zone::lookup().
|
817
|
+
// So reparse the input with a known AM hour, and check if it is shifted
|
818
|
+
// to a PM hour.
|
819
|
+
if (spec == "%p" && data != nullptr) {
|
820
|
+
std::string test_input = "1";
|
821
|
+
test_input.append(orig_data, static_cast<std::size_t>(data - orig_data));
|
822
|
+
const char* test_data = test_input.c_str();
|
823
|
+
std::tm tmp{};
|
824
|
+
ParseTM(test_data, "%I%p", &tmp);
|
825
|
+
afternoon = (tmp.tm_hour == 13);
|
826
|
+
}
|
827
|
+
}
|
828
|
+
|
829
|
+
// Adjust a 12-hour tm_hour value if it should be in the afternoon.
|
830
|
+
if (twelve_hour && afternoon && tm.tm_hour < 12) {
|
831
|
+
tm.tm_hour += 12;
|
832
|
+
}
|
833
|
+
|
834
|
+
if (data == nullptr) {
|
835
|
+
if (err != nullptr) *err = "Failed to parse input";
|
836
|
+
return false;
|
837
|
+
}
|
838
|
+
|
839
|
+
// Skip any remaining whitespace.
|
840
|
+
while (std::isspace(*data)) ++data;
|
841
|
+
|
842
|
+
// parse() must consume the entire input std::string.
|
843
|
+
if (*data != '\0') {
|
844
|
+
if (err != nullptr) *err = "Illegal trailing data in input string";
|
845
|
+
return false;
|
846
|
+
}
|
847
|
+
|
848
|
+
// If we saw %s then we ignore anything else and return that time.
|
849
|
+
if (saw_percent_s) {
|
850
|
+
*sec = FromUnixSeconds(percent_s);
|
851
|
+
*fs = detail::femtoseconds::zero();
|
852
|
+
return true;
|
853
|
+
}
|
854
|
+
|
855
|
+
// If we saw %z, %Ez, or %E*z then we want to interpret the parsed fields
|
856
|
+
// in UTC and then shift by that offset. Otherwise we want to interpret
|
857
|
+
// the fields directly in the passed time_zone.
|
858
|
+
time_zone ptz = saw_offset ? utc_time_zone() : tz;
|
859
|
+
|
860
|
+
// Allows a leap second of 60 to normalize forward to the following ":00".
|
861
|
+
if (tm.tm_sec == 60) {
|
862
|
+
tm.tm_sec -= 1;
|
863
|
+
offset -= 1;
|
864
|
+
subseconds = detail::femtoseconds::zero();
|
865
|
+
}
|
866
|
+
|
867
|
+
if (!saw_year) {
|
868
|
+
year = year_t{tm.tm_year};
|
869
|
+
if (year > kyearmax - 1900) {
|
870
|
+
// Platform-dependent, maybe unreachable.
|
871
|
+
if (err != nullptr) *err = "Out-of-range year";
|
872
|
+
return false;
|
873
|
+
}
|
874
|
+
year += 1900;
|
875
|
+
}
|
876
|
+
|
877
|
+
const int month = tm.tm_mon + 1;
|
878
|
+
civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
|
879
|
+
|
880
|
+
// parse() should not allow normalization. Due to the restricted field
|
881
|
+
// ranges above (see ParseInt()), the only possibility is for days to roll
|
882
|
+
// into months. That is, parsing "Sep 31" should not produce "Oct 1".
|
883
|
+
if (cs.month() != month || cs.day() != tm.tm_mday) {
|
884
|
+
if (err != nullptr) *err = "Out-of-range field";
|
885
|
+
return false;
|
886
|
+
}
|
887
|
+
|
888
|
+
// Accounts for the offset adjustment before converting to absolute time.
|
889
|
+
if ((offset < 0 && cs > civil_second::max() + offset) ||
|
890
|
+
(offset > 0 && cs < civil_second::min() + offset)) {
|
891
|
+
if (err != nullptr) *err = "Out-of-range field";
|
892
|
+
return false;
|
893
|
+
}
|
894
|
+
cs -= offset;
|
895
|
+
|
896
|
+
const auto tp = ptz.lookup(cs).pre;
|
897
|
+
// Checks for overflow/underflow and returns an error as necessary.
|
898
|
+
if (tp == time_point<seconds>::max()) {
|
899
|
+
const auto al = ptz.lookup(time_point<seconds>::max());
|
900
|
+
if (cs > al.cs) {
|
901
|
+
if (err != nullptr) *err = "Out-of-range field";
|
902
|
+
return false;
|
903
|
+
}
|
904
|
+
}
|
905
|
+
if (tp == time_point<seconds>::min()) {
|
906
|
+
const auto al = ptz.lookup(time_point<seconds>::min());
|
907
|
+
if (cs < al.cs) {
|
908
|
+
if (err != nullptr) *err = "Out-of-range field";
|
909
|
+
return false;
|
910
|
+
}
|
911
|
+
}
|
912
|
+
|
913
|
+
*sec = tp;
|
914
|
+
*fs = subseconds;
|
915
|
+
return true;
|
916
|
+
}
|
917
|
+
|
918
|
+
} // namespace detail
|
919
|
+
} // namespace cctz
|
920
|
+
} // namespace time_internal
|
921
|
+
ABSL_NAMESPACE_END
|
922
|
+
} // namespace absl
|