Add 'third_party/abseil_cpp/' from commit '768eb2ca28'
				
					
				
			git-subtree-dir: third_party/abseil_cpp git-subtree-mainline:ffb2ae54begit-subtree-split:768eb2ca28
This commit is contained in:
		
						commit
						fc8dc48020
					
				
					 1276 changed files with 208196 additions and 0 deletions
				
			
		
							
								
								
									
										491
									
								
								third_party/abseil_cpp/absl/flags/BUILD.bazel
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										491
									
								
								third_party/abseil_cpp/absl/flags/BUILD.bazel
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,491 @@ | |||
| # | ||||
| # Copyright 2019 The Abseil Authors. | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #      https://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
| # | ||||
| 
 | ||||
| load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") | ||||
| load( | ||||
|     "//absl:copts/configure_copts.bzl", | ||||
|     "ABSL_DEFAULT_COPTS", | ||||
|     "ABSL_DEFAULT_LINKOPTS", | ||||
|     "ABSL_TEST_COPTS", | ||||
| ) | ||||
| 
 | ||||
| package(default_visibility = ["//visibility:public"]) | ||||
| 
 | ||||
| licenses(["notice"])  # Apache 2.0 | ||||
| 
 | ||||
| cc_library( | ||||
|     name = "flag_internal", | ||||
|     srcs = [ | ||||
|         "internal/flag.cc", | ||||
|     ], | ||||
|     hdrs = [ | ||||
|         "internal/flag.h", | ||||
|     ], | ||||
|     copts = ABSL_DEFAULT_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     visibility = ["//absl/base:__subpackages__"], | ||||
|     deps = [ | ||||
|         ":config", | ||||
|         ":handle", | ||||
|         ":marshalling", | ||||
|         ":registry", | ||||
|         "//absl/base", | ||||
|         "//absl/base:config", | ||||
|         "//absl/base:core_headers", | ||||
|         "//absl/memory", | ||||
|         "//absl/meta:type_traits", | ||||
|         "//absl/strings", | ||||
|         "//absl/synchronization", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_library( | ||||
|     name = "program_name", | ||||
|     srcs = [ | ||||
|         "internal/program_name.cc", | ||||
|     ], | ||||
|     hdrs = [ | ||||
|         "internal/program_name.h", | ||||
|     ], | ||||
|     copts = ABSL_DEFAULT_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     visibility = [ | ||||
|         "//absl/flags:__pkg__", | ||||
|     ], | ||||
|     deps = [ | ||||
|         ":path_util", | ||||
|         "//absl/base:config", | ||||
|         "//absl/base:core_headers", | ||||
|         "//absl/strings", | ||||
|         "//absl/synchronization", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_library( | ||||
|     name = "path_util", | ||||
|     hdrs = [ | ||||
|         "internal/path_util.h", | ||||
|     ], | ||||
|     copts = ABSL_DEFAULT_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     visibility = [ | ||||
|         "//absl/flags:__pkg__", | ||||
|     ], | ||||
|     deps = [ | ||||
|         "//absl/base:config", | ||||
|         "//absl/strings", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_library( | ||||
|     name = "config", | ||||
|     srcs = [ | ||||
|         "usage_config.cc", | ||||
|     ], | ||||
|     hdrs = [ | ||||
|         "config.h", | ||||
|         "usage_config.h", | ||||
|     ], | ||||
|     copts = ABSL_DEFAULT_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":path_util", | ||||
|         ":program_name", | ||||
|         "//absl/base:config", | ||||
|         "//absl/base:core_headers", | ||||
|         "//absl/strings", | ||||
|         "//absl/synchronization", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_library( | ||||
|     name = "marshalling", | ||||
|     srcs = [ | ||||
|         "marshalling.cc", | ||||
|     ], | ||||
|     hdrs = [ | ||||
|         "marshalling.h", | ||||
|     ], | ||||
|     copts = ABSL_DEFAULT_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         "//absl/base:config", | ||||
|         "//absl/base:core_headers", | ||||
|         "//absl/base:log_severity", | ||||
|         "//absl/strings", | ||||
|         "//absl/strings:str_format", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_library( | ||||
|     name = "handle", | ||||
|     srcs = [ | ||||
|         "internal/commandlineflag.cc", | ||||
|     ], | ||||
|     hdrs = [ | ||||
|         "internal/commandlineflag.h", | ||||
|     ], | ||||
|     copts = ABSL_DEFAULT_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     visibility = [ | ||||
|         "//absl/flags:__pkg__", | ||||
|     ], | ||||
|     deps = [ | ||||
|         "//absl/base:config", | ||||
|         "//absl/base:core_headers", | ||||
|         "//absl/base:fast_type_id", | ||||
|         "//absl/strings", | ||||
|         "//absl/types:optional", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_library( | ||||
|     name = "private_handle_accessor", | ||||
|     srcs = [ | ||||
|         "internal/private_handle_accessor.cc", | ||||
|     ], | ||||
|     hdrs = [ | ||||
|         "internal/private_handle_accessor.h", | ||||
|     ], | ||||
|     copts = ABSL_DEFAULT_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     visibility = [ | ||||
|         "//absl/flags:__pkg__", | ||||
|     ], | ||||
|     deps = [":handle"], | ||||
| ) | ||||
| 
 | ||||
| cc_library( | ||||
|     name = "registry", | ||||
|     srcs = [ | ||||
|         "internal/registry.cc", | ||||
|         "internal/type_erased.cc", | ||||
|     ], | ||||
|     hdrs = [ | ||||
|         "internal/registry.h", | ||||
|         "internal/type_erased.h", | ||||
|     ], | ||||
|     copts = ABSL_DEFAULT_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     visibility = [ | ||||
|         "//absl/flags:__pkg__", | ||||
|     ], | ||||
|     deps = [ | ||||
|         ":config", | ||||
|         ":handle", | ||||
|         ":private_handle_accessor", | ||||
|         "//absl/base:config", | ||||
|         "//absl/base:core_headers", | ||||
|         "//absl/base:raw_logging_internal", | ||||
|         "//absl/strings", | ||||
|         "//absl/synchronization", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_library( | ||||
|     name = "flag", | ||||
|     srcs = [ | ||||
|         "flag.cc", | ||||
|     ], | ||||
|     hdrs = [ | ||||
|         "declare.h", | ||||
|         "flag.h", | ||||
|     ], | ||||
|     copts = ABSL_DEFAULT_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":config", | ||||
|         ":flag_internal", | ||||
|         ":handle", | ||||
|         ":marshalling", | ||||
|         ":registry", | ||||
|         "//absl/base", | ||||
|         "//absl/base:config", | ||||
|         "//absl/base:core_headers", | ||||
|         "//absl/strings", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_library( | ||||
|     name = "usage_internal", | ||||
|     srcs = [ | ||||
|         "internal/usage.cc", | ||||
|     ], | ||||
|     hdrs = [ | ||||
|         "internal/usage.h", | ||||
|     ], | ||||
|     copts = ABSL_DEFAULT_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     visibility = [ | ||||
|         "//absl/flags:__pkg__", | ||||
|     ], | ||||
|     deps = [ | ||||
|         ":config", | ||||
|         ":flag", | ||||
|         ":flag_internal", | ||||
|         ":handle", | ||||
|         ":path_util", | ||||
|         ":private_handle_accessor", | ||||
|         ":program_name", | ||||
|         ":registry", | ||||
|         "//absl/base:config", | ||||
|         "//absl/base:core_headers", | ||||
|         "//absl/strings", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_library( | ||||
|     name = "usage", | ||||
|     srcs = [ | ||||
|         "usage.cc", | ||||
|     ], | ||||
|     hdrs = [ | ||||
|         "usage.h", | ||||
|     ], | ||||
|     copts = ABSL_DEFAULT_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":usage_internal", | ||||
|         "//absl/base:config", | ||||
|         "//absl/base:core_headers", | ||||
|         "//absl/strings", | ||||
|         "//absl/synchronization", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_library( | ||||
|     name = "parse", | ||||
|     srcs = ["parse.cc"], | ||||
|     hdrs = [ | ||||
|         "internal/parse.h", | ||||
|         "parse.h", | ||||
|     ], | ||||
|     copts = ABSL_DEFAULT_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":config", | ||||
|         ":flag", | ||||
|         ":flag_internal", | ||||
|         ":handle", | ||||
|         ":private_handle_accessor", | ||||
|         ":program_name", | ||||
|         ":registry", | ||||
|         ":usage", | ||||
|         ":usage_internal", | ||||
|         "//absl/base:config", | ||||
|         "//absl/base:core_headers", | ||||
|         "//absl/strings", | ||||
|         "//absl/synchronization", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| ############################################################################ | ||||
| # Unit tests in alphabetical order. | ||||
| 
 | ||||
| cc_test( | ||||
|     name = "commandlineflag_test", | ||||
|     size = "small", | ||||
|     srcs = [ | ||||
|         "internal/commandlineflag_test.cc", | ||||
|     ], | ||||
|     copts = ABSL_TEST_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":config", | ||||
|         ":flag", | ||||
|         ":handle", | ||||
|         ":private_handle_accessor", | ||||
|         ":registry", | ||||
|         "//absl/memory", | ||||
|         "//absl/strings", | ||||
|         "@com_google_googletest//:gtest_main", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_test( | ||||
|     name = "config_test", | ||||
|     size = "small", | ||||
|     srcs = [ | ||||
|         "config_test.cc", | ||||
|     ], | ||||
|     copts = ABSL_TEST_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":config", | ||||
|         "@com_google_googletest//:gtest_main", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_test( | ||||
|     name = "flag_test", | ||||
|     size = "small", | ||||
|     srcs = [ | ||||
|         "flag_test.cc", | ||||
|         "flag_test_defs.cc", | ||||
|     ], | ||||
|     copts = ABSL_TEST_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":config", | ||||
|         ":flag", | ||||
|         ":flag_internal", | ||||
|         ":handle", | ||||
|         ":registry", | ||||
|         "//absl/base:core_headers", | ||||
|         "//absl/base:malloc_internal", | ||||
|         "//absl/strings", | ||||
|         "//absl/time", | ||||
|         "@com_google_googletest//:gtest_main", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_binary( | ||||
|     name = "flag_benchmark", | ||||
|     testonly = 1, | ||||
|     srcs = [ | ||||
|         "flag_benchmark.cc", | ||||
|     ], | ||||
|     copts = ABSL_TEST_COPTS, | ||||
|     tags = ["benchmark"], | ||||
|     visibility = ["//visibility:private"], | ||||
|     deps = [ | ||||
|         ":flag", | ||||
|         "//absl/time", | ||||
|         "//absl/types:optional", | ||||
|         "@com_github_google_benchmark//:benchmark_main", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_test( | ||||
|     name = "marshalling_test", | ||||
|     size = "small", | ||||
|     srcs = [ | ||||
|         "marshalling_test.cc", | ||||
|     ], | ||||
|     copts = ABSL_TEST_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":marshalling", | ||||
|         "@com_google_googletest//:gtest_main", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_test( | ||||
|     name = "path_util_test", | ||||
|     size = "small", | ||||
|     srcs = [ | ||||
|         "internal/path_util_test.cc", | ||||
|     ], | ||||
|     copts = ABSL_TEST_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":path_util", | ||||
|         "@com_google_googletest//:gtest_main", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_test( | ||||
|     name = "parse_test", | ||||
|     size = "small", | ||||
|     srcs = [ | ||||
|         "parse_test.cc", | ||||
|     ], | ||||
|     copts = ABSL_TEST_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":flag", | ||||
|         ":parse", | ||||
|         ":registry", | ||||
|         "//absl/base:raw_logging_internal", | ||||
|         "//absl/base:scoped_set_env", | ||||
|         "//absl/strings", | ||||
|         "//absl/types:span", | ||||
|         "@com_google_googletest//:gtest_main", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_test( | ||||
|     name = "program_name_test", | ||||
|     size = "small", | ||||
|     srcs = [ | ||||
|         "internal/program_name_test.cc", | ||||
|     ], | ||||
|     copts = ABSL_TEST_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":program_name", | ||||
|         "//absl/strings", | ||||
|         "@com_google_googletest//:gtest_main", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_test( | ||||
|     name = "type_erased_test", | ||||
|     size = "small", | ||||
|     srcs = [ | ||||
|         "internal/type_erased_test.cc", | ||||
|     ], | ||||
|     copts = ABSL_TEST_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":flag", | ||||
|         ":handle", | ||||
|         ":marshalling", | ||||
|         ":registry", | ||||
|         "//absl/memory", | ||||
|         "@com_google_googletest//:gtest_main", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_test( | ||||
|     name = "usage_config_test", | ||||
|     size = "small", | ||||
|     srcs = [ | ||||
|         "usage_config_test.cc", | ||||
|     ], | ||||
|     copts = ABSL_TEST_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":config", | ||||
|         ":path_util", | ||||
|         ":program_name", | ||||
|         "//absl/strings", | ||||
|         "@com_google_googletest//:gtest_main", | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| cc_test( | ||||
|     name = "usage_test", | ||||
|     size = "small", | ||||
|     srcs = [ | ||||
|         "internal/usage_test.cc", | ||||
|     ], | ||||
|     copts = ABSL_TEST_COPTS, | ||||
|     linkopts = ABSL_DEFAULT_LINKOPTS, | ||||
|     deps = [ | ||||
|         ":config", | ||||
|         ":flag", | ||||
|         ":parse", | ||||
|         ":path_util", | ||||
|         ":program_name", | ||||
|         ":registry", | ||||
|         ":usage", | ||||
|         ":usage_internal", | ||||
|         "//absl/memory", | ||||
|         "//absl/strings", | ||||
|         "@com_google_googletest//:gtest", | ||||
|     ], | ||||
| ) | ||||
							
								
								
									
										435
									
								
								third_party/abseil_cpp/absl/flags/CMakeLists.txt
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										435
									
								
								third_party/abseil_cpp/absl/flags/CMakeLists.txt
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,435 @@ | |||
| # | ||||
| # Copyright 2019 The Abseil Authors. | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #      https://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
| # | ||||
| 
 | ||||
| # Internal-only target, do not depend on directly. | ||||
| absl_cc_library( | ||||
|   NAME | ||||
|     flags_internal | ||||
|   SRCS | ||||
|     "internal/flag.cc" | ||||
|   HDRS | ||||
|     "internal/flag.h" | ||||
|   COPTS | ||||
|     ${ABSL_DEFAULT_COPTS} | ||||
|   LINKOPTS | ||||
|     ${ABSL_DEFAULT_LINKOPTS} | ||||
|   DEPS | ||||
|     absl::base | ||||
|     absl::config | ||||
|     absl::flags_config | ||||
|     absl::flags_handle | ||||
|     absl::flags_marshalling | ||||
|     absl::flags_registry | ||||
|     absl::synchronization | ||||
|     absl::meta | ||||
|   PUBLIC | ||||
| ) | ||||
| 
 | ||||
| # Internal-only target, do not depend on directly. | ||||
| absl_cc_library( | ||||
|   NAME | ||||
|     flags_program_name | ||||
|   SRCS | ||||
|     "internal/program_name.cc" | ||||
|   HDRS | ||||
|     "internal/program_name.h" | ||||
|   COPTS | ||||
|     ${ABSL_DEFAULT_COPTS} | ||||
|   LINKOPTS | ||||
|     ${ABSL_DEFAULT_LINKOPTS} | ||||
|   DEPS | ||||
|     absl::config | ||||
|     absl::core_headers | ||||
|     absl::flags_path_util | ||||
|     absl::strings | ||||
|     absl::synchronization | ||||
|   PUBLIC | ||||
| ) | ||||
| 
 | ||||
| # Internal-only target, do not depend on directly. | ||||
| absl_cc_library( | ||||
|   NAME | ||||
|     flags_path_util | ||||
|   HDRS | ||||
|     "internal/path_util.h" | ||||
|   COPTS | ||||
|     ${ABSL_DEFAULT_COPTS} | ||||
|   LINKOPTS | ||||
|     ${ABSL_DEFAULT_LINKOPTS} | ||||
|   DEPS | ||||
|     absl::config | ||||
|     absl::strings | ||||
|   PUBLIC | ||||
| ) | ||||
| 
 | ||||
| absl_cc_library( | ||||
|   NAME | ||||
|     flags_config | ||||
|   SRCS | ||||
|     "usage_config.cc" | ||||
|   HDRS | ||||
|     "config.h" | ||||
|     "usage_config.h" | ||||
|   COPTS | ||||
|     ${ABSL_DEFAULT_COPTS} | ||||
|   LINKOPTS | ||||
|     ${ABSL_DEFAULT_LINKOPTS} | ||||
|   DEPS | ||||
|     absl::config | ||||
|     absl::flags_path_util | ||||
|     absl::flags_program_name | ||||
|     absl::core_headers | ||||
|     absl::strings | ||||
|     absl::synchronization | ||||
| ) | ||||
| 
 | ||||
| absl_cc_library( | ||||
|   NAME | ||||
|     flags_marshalling | ||||
|   SRCS | ||||
|     "marshalling.cc" | ||||
|   HDRS | ||||
|     "marshalling.h" | ||||
|   COPTS | ||||
|     ${ABSL_DEFAULT_COPTS} | ||||
|   LINKOPTS | ||||
|     ${ABSL_DEFAULT_LINKOPTS} | ||||
|   DEPS | ||||
|     absl::config | ||||
|     absl::core_headers | ||||
|     absl::log_severity | ||||
|     absl::strings | ||||
|     absl::str_format | ||||
| ) | ||||
| 
 | ||||
| # Internal-only target, do not depend on directly. | ||||
| absl_cc_library( | ||||
|   NAME | ||||
|     flags_handle | ||||
|   SRCS | ||||
|     "internal/commandlineflag.cc" | ||||
|   HDRS | ||||
|     "internal/commandlineflag.h" | ||||
|   COPTS | ||||
|     ${ABSL_DEFAULT_COPTS} | ||||
|   LINKOPTS | ||||
|     ${ABSL_DEFAULT_LINKOPTS} | ||||
|   DEPS | ||||
|     absl::config | ||||
|     absl::fast_type_id | ||||
|     absl::core_headers | ||||
|     absl::optional | ||||
|     absl::raw_logging_internal | ||||
|     absl::strings | ||||
|     absl::synchronization | ||||
| ) | ||||
| 
 | ||||
| # Internal-only target, do not depend on directly. | ||||
| absl_cc_library( | ||||
|   NAME | ||||
|     flags_private_handle_accessor | ||||
|   SRCS | ||||
|     "internal/private_handle_accessor.cc" | ||||
|   HDRS | ||||
|     "internal/private_handle_accessor.h" | ||||
|   COPTS | ||||
|     ${ABSL_DEFAULT_COPTS} | ||||
|   LINKOPTS | ||||
|     ${ABSL_DEFAULT_LINKOPTS} | ||||
|   DEPS | ||||
|     absl::flags_handle | ||||
| ) | ||||
| 
 | ||||
| # Internal-only target, do not depend on directly. | ||||
| absl_cc_library( | ||||
|   NAME | ||||
|     flags_registry | ||||
|   SRCS | ||||
|     "internal/registry.cc" | ||||
|     "internal/type_erased.cc" | ||||
|   HDRS | ||||
|     "internal/registry.h" | ||||
|     "internal/type_erased.h" | ||||
|   COPTS | ||||
|     ${ABSL_DEFAULT_COPTS} | ||||
|   LINKOPTS | ||||
|     ${ABSL_DEFAULT_LINKOPTS} | ||||
|   DEPS | ||||
|     absl::config | ||||
|     absl::flags_config | ||||
|     absl::flags_handle | ||||
|     absl::flags_private_handle_accessor | ||||
|     absl::core_headers | ||||
|     absl::raw_logging_internal | ||||
|     absl::strings | ||||
|     absl::synchronization | ||||
| ) | ||||
| 
 | ||||
| absl_cc_library( | ||||
|   NAME | ||||
|     flags | ||||
|   SRCS | ||||
|     "flag.cc" | ||||
|   HDRS | ||||
|     "declare.h" | ||||
|     "flag.h" | ||||
|   COPTS | ||||
|     ${ABSL_DEFAULT_COPTS} | ||||
|   LINKOPTS | ||||
|     ${ABSL_DEFAULT_LINKOPTS} | ||||
|   DEPS | ||||
|     absl::config | ||||
|     absl::flags_config | ||||
|     absl::flags_handle | ||||
|     absl::flags_internal | ||||
|     absl::flags_marshalling | ||||
|     absl::flags_registry | ||||
|     absl::base | ||||
|     absl::core_headers | ||||
|     absl::strings | ||||
| ) | ||||
| 
 | ||||
| # Internal-only target, do not depend on directly. | ||||
| absl_cc_library( | ||||
|   NAME | ||||
|     flags_usage_internal | ||||
|   SRCS | ||||
|     "internal/usage.cc" | ||||
|   HDRS | ||||
|     "internal/usage.h" | ||||
|   COPTS | ||||
|     ${ABSL_DEFAULT_COPTS} | ||||
|   LINKOPTS | ||||
|     ${ABSL_DEFAULT_LINKOPTS} | ||||
|   DEPS | ||||
|     absl::config | ||||
|     absl::flags_config | ||||
|     absl::flags | ||||
|     absl::flags_handle | ||||
|     absl::flags_private_handle_accessor | ||||
|     absl::flags_internal | ||||
|     absl::flags_path_util | ||||
|     absl::flags_program_name | ||||
|     absl::flags_registry | ||||
|     absl::strings | ||||
|     absl::synchronization | ||||
| ) | ||||
| 
 | ||||
| absl_cc_library( | ||||
|   NAME | ||||
|     flags_usage | ||||
|   SRCS | ||||
|     "usage.cc" | ||||
|   HDRS | ||||
|     "usage.h" | ||||
|   COPTS | ||||
|     ${ABSL_DEFAULT_COPTS} | ||||
|   LINKOPTS | ||||
|     ${ABSL_DEFAULT_LINKOPTS} | ||||
|   DEPS | ||||
|     absl::config | ||||
|     absl::core_headers | ||||
|     absl::flags_usage_internal | ||||
|     absl::strings | ||||
|     absl::synchronization | ||||
| ) | ||||
| 
 | ||||
| absl_cc_library( | ||||
|   NAME | ||||
|     flags_parse | ||||
|   SRCS | ||||
|     "parse.cc" | ||||
|   HDRS | ||||
|     "internal/parse.h" | ||||
|     "parse.h" | ||||
|   COPTS | ||||
|     ${ABSL_DEFAULT_COPTS} | ||||
|   LINKOPTS | ||||
|     ${ABSL_DEFAULT_LINKOPTS} | ||||
|   DEPS | ||||
|     absl::config | ||||
|     absl::core_headers | ||||
|     absl::flags_config | ||||
|     absl::flags | ||||
|     absl::flags_handle | ||||
|     absl::flags_private_handle_accessor | ||||
|     absl::flags_internal | ||||
|     absl::flags_program_name | ||||
|     absl::flags_registry | ||||
|     absl::flags_usage | ||||
|     absl::strings | ||||
|     absl::synchronization | ||||
| ) | ||||
| 
 | ||||
| ############################################################################ | ||||
| # Unit tests in alpahabetical order. | ||||
| 
 | ||||
| absl_cc_test( | ||||
|   NAME | ||||
|     flags_commandlineflag_test | ||||
|   SRCS | ||||
|     "internal/commandlineflag_test.cc" | ||||
|   COPTS | ||||
|     ${ABSL_TEST_COPTS} | ||||
|   DEPS | ||||
|     absl::flags | ||||
|     absl::flags_config | ||||
|     absl::flags_handle | ||||
|     absl::flags_private_handle_accessor | ||||
|     absl::flags_registry | ||||
|     absl::memory | ||||
|     absl::strings | ||||
|     gtest_main | ||||
| ) | ||||
| 
 | ||||
| absl_cc_test( | ||||
|   NAME | ||||
|     flags_config_test | ||||
|   SRCS | ||||
|     "config_test.cc" | ||||
|   COPTS | ||||
|     ${ABSL_TEST_COPTS} | ||||
|   DEPS | ||||
|     absl::flags_config | ||||
|     gtest_main | ||||
| ) | ||||
| 
 | ||||
| absl_cc_test( | ||||
|   NAME | ||||
|     flags_flag_test | ||||
|   SRCS | ||||
|     "flag_test.cc" | ||||
|     "flag_test_defs.cc" | ||||
|   COPTS | ||||
|     ${ABSL_TEST_COPTS} | ||||
|   DEPS | ||||
|     absl::core_headers | ||||
|     absl::flags | ||||
|     absl::flags_config | ||||
|     absl::flags_handle | ||||
|     absl::flags_internal | ||||
|     absl::flags_registry | ||||
|     absl::strings | ||||
|     absl::time | ||||
|     gtest_main | ||||
| ) | ||||
| 
 | ||||
| absl_cc_test( | ||||
|   NAME | ||||
|     flags_marshalling_test | ||||
|   SRCS | ||||
|     "marshalling_test.cc" | ||||
|   COPTS | ||||
|     ${ABSL_TEST_COPTS} | ||||
|   DEPS | ||||
|     absl::flags_marshalling | ||||
|     gtest_main | ||||
| ) | ||||
| 
 | ||||
| absl_cc_test( | ||||
|   NAME | ||||
|     flags_parse_test | ||||
|   SRCS | ||||
|     "parse_test.cc" | ||||
|   COPTS | ||||
|     ${ABSL_TEST_COPTS} | ||||
|   DEPS | ||||
|     absl::flags | ||||
|     absl::flags_parse | ||||
|     absl::flags_registry | ||||
|     absl::raw_logging_internal | ||||
|     absl::scoped_set_env | ||||
|     absl::span | ||||
|     absl::strings | ||||
|     gmock_main | ||||
| ) | ||||
| 
 | ||||
| absl_cc_test( | ||||
|   NAME | ||||
|     flags_path_util_test | ||||
|   SRCS | ||||
|     "internal/path_util_test.cc" | ||||
|   COPTS | ||||
|     ${ABSL_TEST_COPTS} | ||||
|   DEPS | ||||
|     absl::flags_path_util | ||||
|     gtest_main | ||||
| ) | ||||
| 
 | ||||
| absl_cc_test( | ||||
|   NAME | ||||
|     flags_program_name_test | ||||
|   SRCS | ||||
|     "internal/program_name_test.cc" | ||||
|   COPTS | ||||
|     ${ABSL_TEST_COPTS} | ||||
|   DEPS | ||||
|     absl::flags_program_name | ||||
|     absl::strings | ||||
|     gtest_main | ||||
| ) | ||||
| 
 | ||||
| absl_cc_test( | ||||
|   NAME | ||||
|     flags_type_erased_test | ||||
|   SRCS | ||||
|     "internal/type_erased_test.cc" | ||||
|   COPTS | ||||
|     ${ABSL_TEST_COPTS} | ||||
|   DEPS | ||||
|     absl::flags | ||||
|     absl::flags_handle | ||||
|     absl::flags_marshalling | ||||
|     absl::flags_registry | ||||
|     absl::memory | ||||
|     absl::strings | ||||
|     gtest_main | ||||
| ) | ||||
| 
 | ||||
| absl_cc_test( | ||||
|   NAME | ||||
|     flags_usage_config_test | ||||
|   SRCS | ||||
|     "usage_config_test.cc" | ||||
|   COPTS | ||||
|     ${ABSL_TEST_COPTS} | ||||
|   DEPS | ||||
|     absl::flags_config | ||||
|     absl::flags_path_util | ||||
|     absl::flags_program_name | ||||
|     absl::strings | ||||
|     gtest_main | ||||
| ) | ||||
| 
 | ||||
| absl_cc_test( | ||||
|   NAME | ||||
|     flags_usage_test | ||||
|   SRCS | ||||
|     "internal/usage_test.cc" | ||||
|   COPTS | ||||
|     ${ABSL_TEST_COPTS} | ||||
|   DEPS | ||||
|     absl::flags_config | ||||
|     absl::flags | ||||
|     absl::flags_path_util | ||||
|     absl::flags_program_name | ||||
|     absl::flags_parse | ||||
|     absl::flags_registry | ||||
|     absl::flags_usage | ||||
|     absl::memory | ||||
|     absl::strings | ||||
|     gtest | ||||
| ) | ||||
							
								
								
									
										87
									
								
								third_party/abseil_cpp/absl/flags/config.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								third_party/abseil_cpp/absl/flags/config.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,87 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_CONFIG_H_ | ||||
| #define ABSL_FLAGS_CONFIG_H_ | ||||
| 
 | ||||
| // Determine if we should strip string literals from the Flag objects.
 | ||||
| // By default we strip string literals on mobile platforms.
 | ||||
| #if !defined(ABSL_FLAGS_STRIP_NAMES) | ||||
| 
 | ||||
| #if defined(__ANDROID__) | ||||
| #define ABSL_FLAGS_STRIP_NAMES 1 | ||||
| 
 | ||||
| #elif defined(__APPLE__) | ||||
| #include <TargetConditionals.h> | ||||
| #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE | ||||
| #define ABSL_FLAGS_STRIP_NAMES 1 | ||||
| #elif defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED | ||||
| #define ABSL_FLAGS_STRIP_NAMES 1 | ||||
| #endif  // TARGET_OS_*
 | ||||
| #endif | ||||
| 
 | ||||
| #endif  // !defined(ABSL_FLAGS_STRIP_NAMES)
 | ||||
| 
 | ||||
| #if !defined(ABSL_FLAGS_STRIP_NAMES) | ||||
| // If ABSL_FLAGS_STRIP_NAMES wasn't set on the command line or above,
 | ||||
| // the default is not to strip.
 | ||||
| #define ABSL_FLAGS_STRIP_NAMES 0 | ||||
| #endif | ||||
| 
 | ||||
| #if !defined(ABSL_FLAGS_STRIP_HELP) | ||||
| // By default, if we strip names, we also strip help.
 | ||||
| #define ABSL_FLAGS_STRIP_HELP ABSL_FLAGS_STRIP_NAMES | ||||
| #endif | ||||
| 
 | ||||
| // ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD macro is used for using atomics with
 | ||||
| // double words, e.g. absl::Duration.
 | ||||
| // For reasons in bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80878, modern
 | ||||
| // versions of GCC do not support cmpxchg16b instruction in standard atomics.
 | ||||
| #ifdef ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD | ||||
| #error "ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD should not be defined." | ||||
| #elif defined(__clang__) && defined(__x86_64__) && \ | ||||
|     defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) | ||||
| #define ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD 1 | ||||
| #endif | ||||
| 
 | ||||
| // ABSL_FLAGS_INTERNAL_HAS_RTTI macro is used for selecting if we can use RTTI
 | ||||
| // for flag type identification.
 | ||||
| #ifdef ABSL_FLAGS_INTERNAL_HAS_RTTI | ||||
| #error ABSL_FLAGS_INTERNAL_HAS_RTTI cannot be directly set | ||||
| #elif !defined(__GNUC__) || defined(__GXX_RTTI) | ||||
| #define ABSL_FLAGS_INTERNAL_HAS_RTTI 1 | ||||
| #endif  // !defined(__GNUC__) || defined(__GXX_RTTI)
 | ||||
| 
 | ||||
| // These macros represent the "source of truth" for the list of supported
 | ||||
| // built-in types.
 | ||||
| #define ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \ | ||||
|   A(bool, bool)                              \ | ||||
|   A(short, short)                            \ | ||||
|   A(unsigned short, unsigned_short)          \ | ||||
|   A(int, int)                                \ | ||||
|   A(unsigned int, unsigned_int)              \ | ||||
|   A(long, long)                              \ | ||||
|   A(unsigned long, unsigned_long)            \ | ||||
|   A(long long, long_long)                    \ | ||||
|   A(unsigned long long, unsigned_long_long)  \ | ||||
|   A(double, double)                          \ | ||||
|   A(float, float) | ||||
| 
 | ||||
| #define ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(A) \ | ||||
|   ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A)         \ | ||||
|   A(std::string, std_string)                   \ | ||||
|   A(std::vector<std::string>, std_vector_of_string) | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_CONFIG_H_
 | ||||
							
								
								
									
										61
									
								
								third_party/abseil_cpp/absl/flags/config_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								third_party/abseil_cpp/absl/flags/config_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | |||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/config.h" | ||||
| 
 | ||||
| #ifdef __APPLE__ | ||||
| #include <TargetConditionals.h> | ||||
| #endif | ||||
| 
 | ||||
| #include "gtest/gtest.h" | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_STRIP_NAMES | ||||
| #error ABSL_FLAGS_STRIP_NAMES is not defined | ||||
| #endif | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_STRIP_HELP | ||||
| #error ABSL_FLAGS_STRIP_HELP is not defined | ||||
| #endif | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| // Test that ABSL_FLAGS_STRIP_NAMES and ABSL_FLAGS_STRIP_HELP are configured how
 | ||||
| // we expect them to be configured by default. If you override this
 | ||||
| // configuration, this test will fail, but the code should still be safe to use.
 | ||||
| TEST(FlagsConfigTest, Test) { | ||||
| #if defined(__ANDROID__) | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1); | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1); | ||||
| #elif defined(__myriad2__) | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0); | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0); | ||||
| #elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1); | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1); | ||||
| #elif defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1); | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1); | ||||
| #elif defined(__APPLE__) | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0); | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0); | ||||
| #elif defined(_WIN32) | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0); | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0); | ||||
| #elif defined(__linux__) | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0); | ||||
|   EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
							
								
								
									
										66
									
								
								third_party/abseil_cpp/absl/flags/declare.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								third_party/abseil_cpp/absl/flags/declare.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| //
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| // File: declare.h
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| //
 | ||||
| // This file defines the ABSL_DECLARE_FLAG macro, allowing you to declare an
 | ||||
| // `absl::Flag` for use within a translation unit. You should place this
 | ||||
| // declaration within the header file associated with the .cc file that defines
 | ||||
| // and owns the `Flag`.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_DECLARE_H_ | ||||
| #define ABSL_FLAGS_DECLARE_H_ | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| // absl::Flag<T> represents a flag of type 'T' created by ABSL_FLAG.
 | ||||
| template <typename T> | ||||
| class Flag; | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| 
 | ||||
| // Flag
 | ||||
| //
 | ||||
| // Forward declaration of the `absl::Flag` type for use in defining the macro.
 | ||||
| #if defined(_MSC_VER) && !defined(__clang__) | ||||
| template <typename T> | ||||
| class Flag; | ||||
| #else | ||||
| template <typename T> | ||||
| using Flag = flags_internal::Flag<T>; | ||||
| #endif | ||||
| 
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| // ABSL_DECLARE_FLAG()
 | ||||
| //
 | ||||
| // This macro is a convenience for declaring use of an `absl::Flag` within a
 | ||||
| // translation unit. This macro should be used within a header file to
 | ||||
| // declare usage of the flag within any .cc file including that header file.
 | ||||
| //
 | ||||
| // The ABSL_DECLARE_FLAG(type, name) macro expands to:
 | ||||
| //
 | ||||
| //   extern absl::Flag<type> FLAGS_name;
 | ||||
| #define ABSL_DECLARE_FLAG(type, name) extern ::absl::Flag<type> FLAGS_##name | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_DECLARE_H_
 | ||||
							
								
								
									
										40
									
								
								third_party/abseil_cpp/absl/flags/flag.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								third_party/abseil_cpp/absl/flags/flag.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/flag.h" | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| #include "absl/flags/internal/flag.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| 
 | ||||
| // This global mutex protects on-demand construction of flag objects in MSVC
 | ||||
| // builds.
 | ||||
| #if defined(_MSC_VER) && !defined(__clang__) | ||||
| 
 | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| ABSL_CONST_INIT static absl::Mutex construction_guard(absl::kConstInit); | ||||
| 
 | ||||
| absl::Mutex* GetGlobalConstructionGuard() { return &construction_guard; } | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
							
								
								
									
										381
									
								
								third_party/abseil_cpp/absl/flags/flag.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										381
									
								
								third_party/abseil_cpp/absl/flags/flag.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,381 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| //
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| // File: flag.h
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| //
 | ||||
| // This header file defines the `absl::Flag<T>` type for holding command-line
 | ||||
| // flag data, and abstractions to create, get and set such flag data.
 | ||||
| //
 | ||||
| // It is important to note that this type is **unspecified** (an implementation
 | ||||
| // detail) and you do not construct or manipulate actual `absl::Flag<T>`
 | ||||
| // instances. Instead, you define and declare flags using the
 | ||||
| // `ABSL_FLAG()` and `ABSL_DECLARE_FLAG()` macros, and get and set flag values
 | ||||
| // using the `absl::GetFlag()` and `absl::SetFlag()` functions.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_FLAG_H_ | ||||
| #define ABSL_FLAGS_FLAG_H_ | ||||
| 
 | ||||
| #include <string> | ||||
| #include <type_traits> | ||||
| 
 | ||||
| #include "absl/base/attributes.h" | ||||
| #include "absl/base/casts.h" | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/flags/config.h" | ||||
| #include "absl/flags/declare.h" | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| #include "absl/flags/internal/flag.h" | ||||
| #include "absl/flags/internal/registry.h" | ||||
| #include "absl/flags/marshalling.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| 
 | ||||
| // Flag
 | ||||
| //
 | ||||
| // An `absl::Flag` holds a command-line flag value, providing a runtime
 | ||||
| // parameter to a binary. Such flags should be defined in the global namespace
 | ||||
| // and (preferably) in the module containing the binary's `main()` function.
 | ||||
| //
 | ||||
| // You should not construct and cannot use the `absl::Flag` type directly;
 | ||||
| // instead, you should declare flags using the `ABSL_DECLARE_FLAG()` macro
 | ||||
| // within a header file, and define your flag using `ABSL_FLAG()` within your
 | ||||
| // header's associated `.cc` file. Such flags will be named `FLAGS_name`.
 | ||||
| //
 | ||||
| // Example:
 | ||||
| //
 | ||||
| //    .h file
 | ||||
| //
 | ||||
| //      // Declares usage of a flag named "FLAGS_count"
 | ||||
| //      ABSL_DECLARE_FLAG(int, count);
 | ||||
| //
 | ||||
| //    .cc file
 | ||||
| //
 | ||||
| //      // Defines a flag named "FLAGS_count" with a default `int` value of 0.
 | ||||
| //      ABSL_FLAG(int, count, 0, "Count of items to process");
 | ||||
| //
 | ||||
| // No public methods of `absl::Flag<T>` are part of the Abseil Flags API.
 | ||||
| #if !defined(_MSC_VER) || defined(__clang__) | ||||
| template <typename T> | ||||
| using Flag = flags_internal::Flag<T>; | ||||
| #else | ||||
| // MSVC debug builds do not implement initialization with constexpr constructors
 | ||||
| // correctly. To work around this we add a level of indirection, so that the
 | ||||
| // class `absl::Flag` contains an `internal::Flag*` (instead of being an alias
 | ||||
| // to that class) and dynamically allocates an instance when necessary. We also
 | ||||
| // forward all calls to internal::Flag methods via trampoline methods. In this
 | ||||
| // setup the `absl::Flag` class does not have constructor and virtual methods,
 | ||||
| // all the data members are public and thus MSVC is able to initialize it at
 | ||||
| // link time. To deal with multiple threads accessing the flag for the first
 | ||||
| // time concurrently we use an atomic boolean indicating if flag object is
 | ||||
| // initialized. We also employ the double-checked locking pattern where the
 | ||||
| // second level of protection is a global Mutex, so if two threads attempt to
 | ||||
| // construct the flag concurrently only one wins.
 | ||||
| // This solution is based on a recomendation here:
 | ||||
| // https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html?childToView=648454#comment-648454
 | ||||
| 
 | ||||
| namespace flags_internal { | ||||
| absl::Mutex* GetGlobalConstructionGuard(); | ||||
| }  // namespace flags_internal
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class Flag { | ||||
|  public: | ||||
|   // No constructor and destructor to ensure this is an aggregate type.
 | ||||
|   // Visual Studio 2015 still requires the constructor for class to be
 | ||||
|   // constexpr initializable.
 | ||||
| #if _MSC_VER <= 1900 | ||||
|   constexpr Flag(const char* name, const char* filename, | ||||
|                  const flags_internal::HelpGenFunc help_gen, | ||||
|                  const flags_internal::FlagDfltGenFunc default_value_gen) | ||||
|       : name_(name), | ||||
|         filename_(filename), | ||||
|         help_gen_(help_gen), | ||||
|         default_value_gen_(default_value_gen), | ||||
|         inited_(false), | ||||
|         impl_(nullptr) {} | ||||
| #endif | ||||
| 
 | ||||
|   flags_internal::Flag<T>* GetImpl() const { | ||||
|     if (!inited_.load(std::memory_order_acquire)) { | ||||
|       absl::MutexLock l(flags_internal::GetGlobalConstructionGuard()); | ||||
| 
 | ||||
|       if (inited_.load(std::memory_order_acquire)) { | ||||
|         return impl_; | ||||
|       } | ||||
| 
 | ||||
|       impl_ = new flags_internal::Flag<T>( | ||||
|           name_, filename_, | ||||
|           {flags_internal::FlagHelpMsg(help_gen_), | ||||
|            flags_internal::FlagHelpKind::kGenFunc}, | ||||
|           {flags_internal::FlagDefaultSrc(default_value_gen_), | ||||
|            flags_internal::FlagDefaultKind::kGenFunc}); | ||||
|       inited_.store(true, std::memory_order_release); | ||||
|     } | ||||
| 
 | ||||
|     return impl_; | ||||
|   } | ||||
| 
 | ||||
|   // Public methods of `absl::Flag<T>` are NOT part of the Abseil Flags API.
 | ||||
|   // See https://abseil.io/docs/cpp/guides/flags
 | ||||
|   bool IsRetired() const { return GetImpl()->IsRetired(); } | ||||
|   absl::string_view Name() const { return GetImpl()->Name(); } | ||||
|   std::string Help() const { return GetImpl()->Help(); } | ||||
|   bool IsModified() const { return GetImpl()->IsModified(); } | ||||
|   bool IsSpecifiedOnCommandLine() const { | ||||
|     return GetImpl()->IsSpecifiedOnCommandLine(); | ||||
|   } | ||||
|   std::string Filename() const { return GetImpl()->Filename(); } | ||||
|   std::string DefaultValue() const { return GetImpl()->DefaultValue(); } | ||||
|   std::string CurrentValue() const { return GetImpl()->CurrentValue(); } | ||||
|   template <typename U> | ||||
|   inline bool IsOfType() const { | ||||
|     return GetImpl()->template IsOfType<U>(); | ||||
|   } | ||||
|   T Get() const { return GetImpl()->Get(); } | ||||
|   void Set(const T& v) { GetImpl()->Set(v); } | ||||
|   void InvokeCallback() { GetImpl()->InvokeCallback(); } | ||||
| 
 | ||||
|   // The data members are logically private, but they need to be public for
 | ||||
|   // this to be an aggregate type.
 | ||||
|   const char* name_; | ||||
|   const char* filename_; | ||||
|   const flags_internal::HelpGenFunc help_gen_; | ||||
|   const flags_internal::FlagDfltGenFunc default_value_gen_; | ||||
| 
 | ||||
|   mutable std::atomic<bool> inited_; | ||||
|   mutable flags_internal::Flag<T>* impl_; | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| // GetFlag()
 | ||||
| //
 | ||||
| // Returns the value (of type `T`) of an `absl::Flag<T>` instance, by value. Do
 | ||||
| // not construct an `absl::Flag<T>` directly and call `absl::GetFlag()`;
 | ||||
| // instead, refer to flag's constructed variable name (e.g. `FLAGS_name`).
 | ||||
| // Because this function returns by value and not by reference, it is
 | ||||
| // thread-safe, but note that the operation may be expensive; as a result, avoid
 | ||||
| // `absl::GetFlag()` within any tight loops.
 | ||||
| //
 | ||||
| // Example:
 | ||||
| //
 | ||||
| //   // FLAGS_count is a Flag of type `int`
 | ||||
| //   int my_count = absl::GetFlag(FLAGS_count);
 | ||||
| //
 | ||||
| //   // FLAGS_firstname is a Flag of type `std::string`
 | ||||
| //   std::string first_name = absl::GetFlag(FLAGS_firstname);
 | ||||
| template <typename T> | ||||
| ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) { | ||||
|   return flag.Get(); | ||||
| } | ||||
| 
 | ||||
| // SetFlag()
 | ||||
| //
 | ||||
| // Sets the value of an `absl::Flag` to the value `v`. Do not construct an
 | ||||
| // `absl::Flag<T>` directly and call `absl::SetFlag()`; instead, use the
 | ||||
| // flag's variable name (e.g. `FLAGS_name`). This function is
 | ||||
| // thread-safe, but is potentially expensive. Avoid setting flags in general,
 | ||||
| // but especially within performance-critical code.
 | ||||
| template <typename T> | ||||
| void SetFlag(absl::Flag<T>* flag, const T& v) { | ||||
|   flag->Set(v); | ||||
| } | ||||
| 
 | ||||
| // Overload of `SetFlag()` to allow callers to pass in a value that is
 | ||||
| // convertible to `T`. E.g., use this overload to pass a "const char*" when `T`
 | ||||
| // is `std::string`.
 | ||||
| template <typename T, typename V> | ||||
| void SetFlag(absl::Flag<T>* flag, const V& v) { | ||||
|   T value(v); | ||||
|   flag->Set(value); | ||||
| } | ||||
| 
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| 
 | ||||
| // ABSL_FLAG()
 | ||||
| //
 | ||||
| // This macro defines an `absl::Flag<T>` instance of a specified type `T`:
 | ||||
| //
 | ||||
| //   ABSL_FLAG(T, name, default_value, help);
 | ||||
| //
 | ||||
| // where:
 | ||||
| //
 | ||||
| //   * `T` is a supported flag type (see the list of types in `marshalling.h`),
 | ||||
| //   * `name` designates the name of the flag (as a global variable
 | ||||
| //     `FLAGS_name`),
 | ||||
| //   * `default_value` is an expression holding the default value for this flag
 | ||||
| //     (which must be implicitly convertible to `T`),
 | ||||
| //   * `help` is the help text, which can also be an expression.
 | ||||
| //
 | ||||
| // This macro expands to a flag named 'FLAGS_name' of type 'T':
 | ||||
| //
 | ||||
| //   absl::Flag<T> FLAGS_name = ...;
 | ||||
| //
 | ||||
| // Note that all such instances are created as global variables.
 | ||||
| //
 | ||||
| // For `ABSL_FLAG()` values that you wish to expose to other translation units,
 | ||||
| // it is recommended to define those flags within the `.cc` file associated with
 | ||||
| // the header where the flag is declared.
 | ||||
| //
 | ||||
| // Note: do not construct objects of type `absl::Flag<T>` directly. Only use the
 | ||||
| // `ABSL_FLAG()` macro for such construction.
 | ||||
| #define ABSL_FLAG(Type, name, default_value, help) \ | ||||
|   ABSL_FLAG_IMPL(Type, name, default_value, help) | ||||
| 
 | ||||
| // ABSL_FLAG().OnUpdate()
 | ||||
| //
 | ||||
| // Defines a flag of type `T` with a callback attached:
 | ||||
| //
 | ||||
| //   ABSL_FLAG(T, name, default_value, help).OnUpdate(callback);
 | ||||
| //
 | ||||
| // After any setting of the flag value, the callback will be called at least
 | ||||
| // once. A rapid sequence of changes may be merged together into the same
 | ||||
| // callback. No concurrent calls to the callback will be made for the same
 | ||||
| // flag. Callbacks are allowed to read the current value of the flag but must
 | ||||
| // not mutate that flag.
 | ||||
| //
 | ||||
| // The update mechanism guarantees "eventual consistency"; if the callback
 | ||||
| // derives an auxiliary data structure from the flag value, it is guaranteed
 | ||||
| // that eventually the flag value and the derived data structure will be
 | ||||
| // consistent.
 | ||||
| //
 | ||||
| // Note: ABSL_FLAG.OnUpdate() does not have a public definition. Hence, this
 | ||||
| // comment serves as its API documentation.
 | ||||
| 
 | ||||
| 
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| // Implementation details below this section
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_NAMES
 | ||||
| 
 | ||||
| #if ABSL_FLAGS_STRIP_NAMES | ||||
| #define ABSL_FLAG_IMPL_FLAGNAME(txt) "" | ||||
| #define ABSL_FLAG_IMPL_FILENAME() "" | ||||
| #if !defined(_MSC_VER) || defined(__clang__) | ||||
| #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \ | ||||
|   absl::flags_internal::FlagRegistrar<T, false>(&flag) | ||||
| #else | ||||
| #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \ | ||||
|   absl::flags_internal::FlagRegistrar<T, false>(flag.GetImpl()) | ||||
| #endif | ||||
| #else | ||||
| #define ABSL_FLAG_IMPL_FLAGNAME(txt) txt | ||||
| #define ABSL_FLAG_IMPL_FILENAME() __FILE__ | ||||
| #if !defined(_MSC_VER) || defined(__clang__) | ||||
| #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \ | ||||
|   absl::flags_internal::FlagRegistrar<T, true>(&flag) | ||||
| #else | ||||
| #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \ | ||||
|   absl::flags_internal::FlagRegistrar<T, true>(flag.GetImpl()) | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP
 | ||||
| 
 | ||||
| #if ABSL_FLAGS_STRIP_HELP | ||||
| #define ABSL_FLAG_IMPL_FLAGHELP(txt) absl::flags_internal::kStrippedFlagHelp | ||||
| #else | ||||
| #define ABSL_FLAG_IMPL_FLAGHELP(txt) txt | ||||
| #endif | ||||
| 
 | ||||
| // AbslFlagHelpGenFor##name is used to encapsulate both immediate (method Const)
 | ||||
| // and lazy (method NonConst) evaluation of help message expression. We choose
 | ||||
| // between the two via the call to HelpArg in absl::Flag instantiation below.
 | ||||
| // If help message expression is constexpr evaluable compiler will optimize
 | ||||
| // away this whole struct.
 | ||||
| #define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt)                     \ | ||||
|   struct AbslFlagHelpGenFor##name {                                        \ | ||||
|     template <typename T = void>                                           \ | ||||
|     static constexpr const char* Const() {                                 \ | ||||
|       return absl::flags_internal::HelpConstexprWrap(                      \ | ||||
|           ABSL_FLAG_IMPL_FLAGHELP(txt));                                   \ | ||||
|     }                                                                      \ | ||||
|     static std::string NonConst() { return ABSL_FLAG_IMPL_FLAGHELP(txt); } \ | ||||
|   } | ||||
| 
 | ||||
| #define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)     \ | ||||
|   struct AbslFlagDefaultGenFor##name {                                        \ | ||||
|     Type value = absl::flags_internal::InitDefaultValue<Type>(default_value); \ | ||||
|     static void Gen(void* p) {                                                \ | ||||
|       new (p) Type(AbslFlagDefaultGenFor##name{}.value);                      \ | ||||
|     }                                                                         \ | ||||
|   } | ||||
| 
 | ||||
| // ABSL_FLAG_IMPL
 | ||||
| //
 | ||||
| // Note: Name of registrar object is not arbitrary. It is used to "grab"
 | ||||
| // global name for FLAGS_no<flag_name> symbol, thus preventing the possibility
 | ||||
| // of defining two flags with names foo and nofoo.
 | ||||
| #if !defined(_MSC_VER) || defined(__clang__) | ||||
| 
 | ||||
| #define ABSL_FLAG_IMPL(Type, name, default_value, help)                        \ | ||||
|   namespace absl /* block flags in namespaces */ {}                            \ | ||||
|   ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value);           \ | ||||
|   ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help);                             \ | ||||
|   ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{                               \ | ||||
|       ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(),               \ | ||||
|       absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>(0),              \ | ||||
|       absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0)}; \ | ||||
|   extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name;              \ | ||||
|   absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name =                    \ | ||||
|       ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name) | ||||
| #else | ||||
| // MSVC version uses aggregate initialization. We also do not try to
 | ||||
| // optimize away help wrapper.
 | ||||
| #define ABSL_FLAG_IMPL(Type, name, default_value, help)                        \ | ||||
|   namespace absl /* block flags in namespaces */ {}                            \ | ||||
|   ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value);           \ | ||||
|   ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help);                             \ | ||||
|   ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{                               \ | ||||
|       ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(),               \ | ||||
|       &AbslFlagHelpGenFor##name::NonConst, &AbslFlagDefaultGenFor##name::Gen}; \ | ||||
|   extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name;              \ | ||||
|   absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name =                    \ | ||||
|       ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name) | ||||
| #endif | ||||
| 
 | ||||
| // ABSL_RETIRED_FLAG
 | ||||
| //
 | ||||
| // Designates the flag (which is usually pre-existing) as "retired." A retired
 | ||||
| // flag is a flag that is now unused by the program, but may still be passed on
 | ||||
| // the command line, usually by production scripts. A retired flag is ignored
 | ||||
| // and code can't access it at runtime.
 | ||||
| //
 | ||||
| // This macro registers a retired flag with given name and type, with a name
 | ||||
| // identical to the name of the original flag you are retiring. The retired
 | ||||
| // flag's type can change over time, so that you can retire code to support a
 | ||||
| // custom flag type.
 | ||||
| //
 | ||||
| // This macro has the same signature as `ABSL_FLAG`. To retire a flag, simply
 | ||||
| // replace an `ABSL_FLAG` definition with `ABSL_RETIRED_FLAG`, leaving the
 | ||||
| // arguments unchanged (unless of course you actually want to retire the flag
 | ||||
| // type at this time as well).
 | ||||
| //
 | ||||
| // `default_value` is only used as a double check on the type. `explanation` is
 | ||||
| // unused.
 | ||||
| // TODO(rogeeff): Return an anonymous struct instead of bool, and place it into
 | ||||
| // the unnamed namespace.
 | ||||
| #define ABSL_RETIRED_FLAG(type, flagname, default_value, explanation) \ | ||||
|   ABSL_ATTRIBUTE_UNUSED static const bool ignored_##flagname =        \ | ||||
|       ([] { return type(default_value); },                            \ | ||||
|        absl::flags_internal::RetiredFlag<type>(#flagname)) | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_FLAG_H_
 | ||||
							
								
								
									
										119
									
								
								third_party/abseil_cpp/absl/flags/flag_benchmark.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								third_party/abseil_cpp/absl/flags/flag_benchmark.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,119 @@ | |||
| //
 | ||||
| // Copyright 2020 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/flag.h" | ||||
| #include "absl/time/time.h" | ||||
| #include "absl/types/optional.h" | ||||
| #include "benchmark/benchmark.h" | ||||
| 
 | ||||
| namespace { | ||||
| using String = std::string; | ||||
| using VectorOfStrings = std::vector<std::string>; | ||||
| using AbslDuration = absl::Duration; | ||||
| 
 | ||||
| // We do not want to take over marshalling for the types absl::optional<int>,
 | ||||
| // absl::optional<std::string> which we do not own. Instead we introduce unique
 | ||||
| // "aliases" to these types, which we do.
 | ||||
| using AbslOptionalInt = absl::optional<int>; | ||||
| struct OptionalInt : AbslOptionalInt { | ||||
|   using AbslOptionalInt::AbslOptionalInt; | ||||
| }; | ||||
| // Next two functions represent Abseil Flags marshalling for OptionalInt.
 | ||||
| bool AbslParseFlag(absl::string_view src, OptionalInt* flag, | ||||
|                    std::string* error) { | ||||
|   int val; | ||||
|   if (src.empty()) | ||||
|     flag->reset(); | ||||
|   else if (!absl::ParseFlag(src, &val, error)) | ||||
|     return false; | ||||
|   *flag = val; | ||||
|   return true; | ||||
| } | ||||
| std::string AbslUnparseFlag(const OptionalInt& flag) { | ||||
|   return !flag ? "" : absl::UnparseFlag(*flag); | ||||
| } | ||||
| 
 | ||||
| using AbslOptionalString = absl::optional<std::string>; | ||||
| struct OptionalString : AbslOptionalString { | ||||
|   using AbslOptionalString::AbslOptionalString; | ||||
| }; | ||||
| // Next two functions represent Abseil Flags marshalling for OptionalString.
 | ||||
| bool AbslParseFlag(absl::string_view src, OptionalString* flag, | ||||
|                    std::string* error) { | ||||
|   std::string val; | ||||
|   if (src.empty()) | ||||
|     flag->reset(); | ||||
|   else if (!absl::ParseFlag(src, &val, error)) | ||||
|     return false; | ||||
|   *flag = val; | ||||
|   return true; | ||||
| } | ||||
| std::string AbslUnparseFlag(const OptionalString& flag) { | ||||
|   return !flag ? "" : absl::UnparseFlag(*flag); | ||||
| } | ||||
| 
 | ||||
| struct UDT { | ||||
|   UDT() = default; | ||||
|   UDT(const UDT&) {} | ||||
|   UDT& operator=(const UDT&) { return *this; } | ||||
| }; | ||||
| // Next two functions represent Abseil Flags marshalling for UDT.
 | ||||
| bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; } | ||||
| std::string AbslUnparseFlag(const UDT&) { return ""; } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| #define BENCHMARKED_TYPES(A) \ | ||||
|   A(bool)                    \ | ||||
|   A(int16_t)                 \ | ||||
|   A(uint16_t)                \ | ||||
|   A(int32_t)                 \ | ||||
|   A(uint32_t)                \ | ||||
|   A(int64_t)                 \ | ||||
|   A(uint64_t)                \ | ||||
|   A(double)                  \ | ||||
|   A(float)                   \ | ||||
|   A(String)                  \ | ||||
|   A(VectorOfStrings)         \ | ||||
|   A(OptionalInt)             \ | ||||
|   A(OptionalString)          \ | ||||
|   A(AbslDuration)            \ | ||||
|   A(UDT) | ||||
| 
 | ||||
| #define FLAG_DEF(T) ABSL_FLAG(T, T##_flag, {}, ""); | ||||
| 
 | ||||
| BENCHMARKED_TYPES(FLAG_DEF) | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| #define BM_GetFlag(T)                                            \ | ||||
|   void BM_GetFlag_##T(benchmark::State& state) {                 \ | ||||
|     for (auto _ : state) {                                       \ | ||||
|       benchmark::DoNotOptimize(absl::GetFlag(FLAGS_##T##_flag)); \ | ||||
|     }                                                            \ | ||||
|   }                                                              \ | ||||
|   BENCHMARK(BM_GetFlag_##T); | ||||
| 
 | ||||
| BENCHMARKED_TYPES(BM_GetFlag) | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| #define InvokeGetFlag(T)                                               \ | ||||
|   T AbslInvokeGetFlag##T() { return absl::GetFlag(FLAGS_##T##_flag); } \ | ||||
|   int odr##T = (benchmark::DoNotOptimize(AbslInvokeGetFlag##T), 1); | ||||
| 
 | ||||
| BENCHMARKED_TYPES(InvokeGetFlag) | ||||
| 
 | ||||
| // To veiw disassembly use: gdb ${BINARY}  -batch -ex "disassemble /s $FUNC"
 | ||||
							
								
								
									
										783
									
								
								third_party/abseil_cpp/absl/flags/flag_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										783
									
								
								third_party/abseil_cpp/absl/flags/flag_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,783 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/flag.h" | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| #include <cmath> | ||||
| #include <string> | ||||
| #include <thread>  // NOLINT
 | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "gtest/gtest.h" | ||||
| #include "absl/base/attributes.h" | ||||
| #include "absl/flags/config.h" | ||||
| #include "absl/flags/declare.h" | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| #include "absl/flags/internal/flag.h" | ||||
| #include "absl/flags/internal/registry.h" | ||||
| #include "absl/flags/usage_config.h" | ||||
| #include "absl/strings/match.h" | ||||
| #include "absl/strings/numbers.h" | ||||
| #include "absl/strings/str_cat.h" | ||||
| #include "absl/strings/str_split.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| #include "absl/time/time.h" | ||||
| 
 | ||||
| ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag); | ||||
| ABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| namespace flags = absl::flags_internal; | ||||
| 
 | ||||
| std::string TestHelpMsg() { return "dynamic help"; } | ||||
| template <typename T> | ||||
| void TestMakeDflt(void* dst) { | ||||
|   new (dst) T{}; | ||||
| } | ||||
| void TestCallback() {} | ||||
| 
 | ||||
| struct UDT { | ||||
|   UDT() = default; | ||||
|   UDT(const UDT&) = default; | ||||
| }; | ||||
| bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; } | ||||
| std::string AbslUnparseFlag(const UDT&) { return ""; } | ||||
| 
 | ||||
| class FlagTest : public testing::Test { | ||||
|  protected: | ||||
|   static void SetUpTestSuite() { | ||||
|     // Install a function to normalize filenames before this test is run.
 | ||||
|     absl::FlagsUsageConfig default_config; | ||||
|     default_config.normalize_filename = &FlagTest::NormalizeFileName; | ||||
|     absl::SetFlagsUsageConfig(default_config); | ||||
|   } | ||||
| 
 | ||||
|  private: | ||||
|   static std::string NormalizeFileName(absl::string_view fname) { | ||||
| #ifdef _WIN32 | ||||
|     std::string normalized(fname); | ||||
|     std::replace(normalized.begin(), normalized.end(), '\\', '/'); | ||||
|     fname = normalized; | ||||
| #endif | ||||
|     return std::string(fname); | ||||
|   } | ||||
|   flags::FlagSaver flag_saver_; | ||||
| }; | ||||
| 
 | ||||
| struct S1 { | ||||
|   S1() = default; | ||||
|   S1(const S1&) = default; | ||||
|   int32_t f1; | ||||
|   int64_t f2; | ||||
| }; | ||||
| 
 | ||||
| struct S2 { | ||||
|   S2() = default; | ||||
|   S2(const S2&) = default; | ||||
|   int64_t f1; | ||||
|   double f2; | ||||
| }; | ||||
| 
 | ||||
| TEST_F(FlagTest, Traits) { | ||||
|   EXPECT_EQ(flags::StorageKind<int>(), | ||||
|             flags::FlagValueStorageKind::kOneWordAtomic); | ||||
|   EXPECT_EQ(flags::StorageKind<bool>(), | ||||
|             flags::FlagValueStorageKind::kOneWordAtomic); | ||||
|   EXPECT_EQ(flags::StorageKind<double>(), | ||||
|             flags::FlagValueStorageKind::kOneWordAtomic); | ||||
|   EXPECT_EQ(flags::StorageKind<int64_t>(), | ||||
|             flags::FlagValueStorageKind::kOneWordAtomic); | ||||
| 
 | ||||
| #if defined(ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD) | ||||
|   EXPECT_EQ(flags::StorageKind<S1>(), | ||||
|             flags::FlagValueStorageKind::kTwoWordsAtomic); | ||||
|   EXPECT_EQ(flags::StorageKind<S2>(), | ||||
|             flags::FlagValueStorageKind::kTwoWordsAtomic); | ||||
| #else | ||||
|   EXPECT_EQ(flags::StorageKind<S1>(), | ||||
|             flags::FlagValueStorageKind::kAlignedBuffer); | ||||
|   EXPECT_EQ(flags::StorageKind<S2>(), | ||||
|             flags::FlagValueStorageKind::kAlignedBuffer); | ||||
| #endif | ||||
| 
 | ||||
|   EXPECT_EQ(flags::StorageKind<std::string>(), | ||||
|             flags::FlagValueStorageKind::kAlignedBuffer); | ||||
|   EXPECT_EQ(flags::StorageKind<std::vector<std::string>>(), | ||||
|             flags::FlagValueStorageKind::kAlignedBuffer); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| constexpr flags::FlagHelpArg help_arg{flags::FlagHelpMsg("literal help"), | ||||
|                                       flags::FlagHelpKind::kLiteral}; | ||||
| 
 | ||||
| using String = std::string; | ||||
| 
 | ||||
| #define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind)                      \ | ||||
|   constexpr flags::FlagDefaultArg f1default##T{                          \ | ||||
|       flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind};   \ | ||||
|   constexpr flags::Flag<T> f1##T("f1", "file", help_arg, f1default##T);  \ | ||||
|   ABSL_CONST_INIT flags::Flag<T> f2##T(                                  \ | ||||
|       "f2", "file",                                                      \ | ||||
|       {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \ | ||||
|       flags::FlagDefaultArg{flags::FlagDefaultSrc(&TestMakeDflt<T>),     \ | ||||
|                             flags::FlagDefaultKind::kGenFunc}) | ||||
| 
 | ||||
| DEFINE_CONSTRUCTED_FLAG(bool, true, kOneWord); | ||||
| DEFINE_CONSTRUCTED_FLAG(int16_t, 1, kOneWord); | ||||
| DEFINE_CONSTRUCTED_FLAG(uint16_t, 2, kOneWord); | ||||
| DEFINE_CONSTRUCTED_FLAG(int32_t, 3, kOneWord); | ||||
| DEFINE_CONSTRUCTED_FLAG(uint32_t, 4, kOneWord); | ||||
| DEFINE_CONSTRUCTED_FLAG(int64_t, 5, kOneWord); | ||||
| DEFINE_CONSTRUCTED_FLAG(uint64_t, 6, kOneWord); | ||||
| DEFINE_CONSTRUCTED_FLAG(float, 7.8, kOneWord); | ||||
| DEFINE_CONSTRUCTED_FLAG(double, 9.10, kOneWord); | ||||
| DEFINE_CONSTRUCTED_FLAG(String, &TestMakeDflt<String>, kGenFunc); | ||||
| DEFINE_CONSTRUCTED_FLAG(UDT, &TestMakeDflt<UDT>, kGenFunc); | ||||
| 
 | ||||
| template <typename T> | ||||
| bool TestConstructionFor(const flags::Flag<T>& f1, flags::Flag<T>* f2) { | ||||
|   EXPECT_EQ(f1.Name(), "f1"); | ||||
|   EXPECT_EQ(f1.Help(), "literal help"); | ||||
|   EXPECT_EQ(f1.Filename(), "file"); | ||||
| 
 | ||||
|   flags::FlagRegistrar<T, false>(f2).OnUpdate(TestCallback); | ||||
| 
 | ||||
|   EXPECT_EQ(f2->Name(), "f2"); | ||||
|   EXPECT_EQ(f2->Help(), "dynamic help"); | ||||
|   EXPECT_EQ(f2->Filename(), "file"); | ||||
| 
 | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| #define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, &f2##T); | ||||
| 
 | ||||
| TEST_F(FlagTest, TestConstruction) { | ||||
|   TEST_CONSTRUCTED_FLAG(bool); | ||||
|   TEST_CONSTRUCTED_FLAG(int16_t); | ||||
|   TEST_CONSTRUCTED_FLAG(uint16_t); | ||||
|   TEST_CONSTRUCTED_FLAG(int32_t); | ||||
|   TEST_CONSTRUCTED_FLAG(uint32_t); | ||||
|   TEST_CONSTRUCTED_FLAG(int64_t); | ||||
|   TEST_CONSTRUCTED_FLAG(uint64_t); | ||||
|   TEST_CONSTRUCTED_FLAG(float); | ||||
|   TEST_CONSTRUCTED_FLAG(double); | ||||
|   TEST_CONSTRUCTED_FLAG(String); | ||||
|   TEST_CONSTRUCTED_FLAG(UDT); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| ABSL_DECLARE_FLAG(bool, test_flag_01); | ||||
| ABSL_DECLARE_FLAG(int, test_flag_02); | ||||
| ABSL_DECLARE_FLAG(int16_t, test_flag_03); | ||||
| ABSL_DECLARE_FLAG(uint16_t, test_flag_04); | ||||
| ABSL_DECLARE_FLAG(int32_t, test_flag_05); | ||||
| ABSL_DECLARE_FLAG(uint32_t, test_flag_06); | ||||
| ABSL_DECLARE_FLAG(int64_t, test_flag_07); | ||||
| ABSL_DECLARE_FLAG(uint64_t, test_flag_08); | ||||
| ABSL_DECLARE_FLAG(double, test_flag_09); | ||||
| ABSL_DECLARE_FLAG(float, test_flag_10); | ||||
| ABSL_DECLARE_FLAG(std::string, test_flag_11); | ||||
| ABSL_DECLARE_FLAG(absl::Duration, test_flag_12); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| #if !ABSL_FLAGS_STRIP_NAMES | ||||
| 
 | ||||
| TEST_F(FlagTest, TestFlagDeclaration) { | ||||
|   // test that we can access flag objects.
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_12.Name(), "test_flag_12"); | ||||
| } | ||||
| #endif  // !ABSL_FLAGS_STRIP_NAMES
 | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| ABSL_FLAG(bool, test_flag_01, true, "test flag 01"); | ||||
| ABSL_FLAG(int, test_flag_02, 1234, "test flag 02"); | ||||
| ABSL_FLAG(int16_t, test_flag_03, -34, "test flag 03"); | ||||
| ABSL_FLAG(uint16_t, test_flag_04, 189, "test flag 04"); | ||||
| ABSL_FLAG(int32_t, test_flag_05, 10765, "test flag 05"); | ||||
| ABSL_FLAG(uint32_t, test_flag_06, 40000, "test flag 06"); | ||||
| ABSL_FLAG(int64_t, test_flag_07, -1234567, "test flag 07"); | ||||
| ABSL_FLAG(uint64_t, test_flag_08, 9876543, "test flag 08"); | ||||
| ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09"); | ||||
| ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10"); | ||||
| ABSL_FLAG(std::string, test_flag_11, "", "test flag 11"); | ||||
| ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "test flag 12"); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| #if !ABSL_FLAGS_STRIP_NAMES | ||||
| TEST_F(FlagTest, TestFlagDefinition) { | ||||
|   absl::string_view expected_file_name = "absl/flags/flag_test.cc"; | ||||
| 
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_01.Help(), "test flag 01"); | ||||
|   EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_01.Filename(), expected_file_name)) | ||||
|       << FLAGS_test_flag_01.Filename(); | ||||
| 
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_02.Help(), "test flag 02"); | ||||
|   EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_02.Filename(), expected_file_name)) | ||||
|       << FLAGS_test_flag_02.Filename(); | ||||
| 
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_03.Help(), "test flag 03"); | ||||
|   EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_03.Filename(), expected_file_name)) | ||||
|       << FLAGS_test_flag_03.Filename(); | ||||
| 
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_04.Help(), "test flag 04"); | ||||
|   EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_04.Filename(), expected_file_name)) | ||||
|       << FLAGS_test_flag_04.Filename(); | ||||
| 
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_05.Help(), "test flag 05"); | ||||
|   EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_05.Filename(), expected_file_name)) | ||||
|       << FLAGS_test_flag_05.Filename(); | ||||
| 
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_06.Help(), "test flag 06"); | ||||
|   EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_06.Filename(), expected_file_name)) | ||||
|       << FLAGS_test_flag_06.Filename(); | ||||
| 
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_07.Help(), "test flag 07"); | ||||
|   EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_07.Filename(), expected_file_name)) | ||||
|       << FLAGS_test_flag_07.Filename(); | ||||
| 
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_08.Help(), "test flag 08"); | ||||
|   EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_08.Filename(), expected_file_name)) | ||||
|       << FLAGS_test_flag_08.Filename(); | ||||
| 
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_09.Help(), "test flag 09"); | ||||
|   EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_09.Filename(), expected_file_name)) | ||||
|       << FLAGS_test_flag_09.Filename(); | ||||
| 
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_10.Help(), "test flag 10"); | ||||
|   EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_10.Filename(), expected_file_name)) | ||||
|       << FLAGS_test_flag_10.Filename(); | ||||
| 
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_11.Help(), "test flag 11"); | ||||
|   EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_11.Filename(), expected_file_name)) | ||||
|       << FLAGS_test_flag_11.Filename(); | ||||
| 
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_12.Name(), "test_flag_12"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_12.Help(), "test flag 12"); | ||||
|   EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_12.Filename(), expected_file_name)) | ||||
|       << FLAGS_test_flag_12.Filename(); | ||||
| } | ||||
| #endif  // !ABSL_FLAGS_STRIP_NAMES
 | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(FlagTest, TestDefault) { | ||||
|   EXPECT_EQ(FLAGS_test_flag_01.DefaultValue(), "true"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_02.DefaultValue(), "1234"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_03.DefaultValue(), "-34"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_04.DefaultValue(), "189"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_05.DefaultValue(), "10765"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_06.DefaultValue(), "40000"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_07.DefaultValue(), "-1234567"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_08.DefaultValue(), "9876543"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_09.DefaultValue(), "-9.876e-50"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_10.DefaultValue(), "1.234e+12"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_11.DefaultValue(), ""); | ||||
|   EXPECT_EQ(FLAGS_test_flag_12.DefaultValue(), "10m"); | ||||
| 
 | ||||
|   EXPECT_EQ(FLAGS_test_flag_01.CurrentValue(), "true"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_02.CurrentValue(), "1234"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_03.CurrentValue(), "-34"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_04.CurrentValue(), "189"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_05.CurrentValue(), "10765"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_06.CurrentValue(), "40000"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_07.CurrentValue(), "-1234567"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_08.CurrentValue(), "9876543"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_09.CurrentValue(), "-9.876e-50"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_10.CurrentValue(), "1.234e+12"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_11.CurrentValue(), ""); | ||||
|   EXPECT_EQ(FLAGS_test_flag_12.CurrentValue(), "10m"); | ||||
| 
 | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543); | ||||
|   EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55); | ||||
|   EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), ""); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| struct NonTriviallyCopyableAggregate { | ||||
|   NonTriviallyCopyableAggregate() = default; | ||||
|   NonTriviallyCopyableAggregate(const NonTriviallyCopyableAggregate& rhs) | ||||
|       : value(rhs.value) {} | ||||
|   NonTriviallyCopyableAggregate& operator=( | ||||
|       const NonTriviallyCopyableAggregate& rhs) { | ||||
|     value = rhs.value; | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   int value; | ||||
| }; | ||||
| bool AbslParseFlag(absl::string_view src, NonTriviallyCopyableAggregate* f, | ||||
|                    std::string* e) { | ||||
|   return absl::ParseFlag(src, &f->value, e); | ||||
| } | ||||
| std::string AbslUnparseFlag(const NonTriviallyCopyableAggregate& ntc) { | ||||
|   return absl::StrCat(ntc.value); | ||||
| } | ||||
| 
 | ||||
| bool operator==(const NonTriviallyCopyableAggregate& ntc1, | ||||
|                 const NonTriviallyCopyableAggregate& ntc2) { | ||||
|   return ntc1.value == ntc2.value; | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| ABSL_FLAG(bool, test_flag_eb_01, {}, ""); | ||||
| ABSL_FLAG(int32_t, test_flag_eb_02, {}, ""); | ||||
| ABSL_FLAG(int64_t, test_flag_eb_03, {}, ""); | ||||
| ABSL_FLAG(double, test_flag_eb_04, {}, ""); | ||||
| ABSL_FLAG(std::string, test_flag_eb_05, {}, ""); | ||||
| ABSL_FLAG(NonTriviallyCopyableAggregate, test_flag_eb_06, {}, ""); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| TEST_F(FlagTest, TestEmptyBracesDefault) { | ||||
|   EXPECT_EQ(FLAGS_test_flag_eb_01.DefaultValue(), "false"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_eb_02.DefaultValue(), "0"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_eb_03.DefaultValue(), "0"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_eb_04.DefaultValue(), "0"); | ||||
|   EXPECT_EQ(FLAGS_test_flag_eb_05.DefaultValue(), ""); | ||||
|   EXPECT_EQ(FLAGS_test_flag_eb_06.DefaultValue(), "0"); | ||||
| 
 | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_01), false); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_02), 0); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_03), 0); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_04), 0.0); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_05), ""); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_06), | ||||
|             NonTriviallyCopyableAggregate{}); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(FlagTest, TestGetSet) { | ||||
|   absl::SetFlag(&FLAGS_test_flag_01, false); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), false); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_test_flag_02, 321); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 321); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_test_flag_03, 67); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), 67); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_test_flag_04, 1); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 1); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_test_flag_05, -908); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), -908); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_test_flag_06, 4001); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 4001); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_test_flag_07, -23456); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -23456); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_test_flag_08, 975310); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 975310); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_test_flag_09, 1.00001); | ||||
|   EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), 1.00001, 1e-10); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_test_flag_10, -3.54f); | ||||
|   EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), -3.54f, 1e-6f); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_test_flag_11, "asdf"); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf"); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_test_flag_12, absl::Seconds(110)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Seconds(110)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(FlagTest, TestGetViaReflection) { | ||||
|   auto* handle = flags::FindCommandLineFlag("test_flag_01"); | ||||
|   EXPECT_EQ(*handle->TryGet<bool>(), true); | ||||
|   handle = flags::FindCommandLineFlag("test_flag_02"); | ||||
|   EXPECT_EQ(*handle->TryGet<int>(), 1234); | ||||
|   handle = flags::FindCommandLineFlag("test_flag_03"); | ||||
|   EXPECT_EQ(*handle->TryGet<int16_t>(), -34); | ||||
|   handle = flags::FindCommandLineFlag("test_flag_04"); | ||||
|   EXPECT_EQ(*handle->TryGet<uint16_t>(), 189); | ||||
|   handle = flags::FindCommandLineFlag("test_flag_05"); | ||||
|   EXPECT_EQ(*handle->TryGet<int32_t>(), 10765); | ||||
|   handle = flags::FindCommandLineFlag("test_flag_06"); | ||||
|   EXPECT_EQ(*handle->TryGet<uint32_t>(), 40000); | ||||
|   handle = flags::FindCommandLineFlag("test_flag_07"); | ||||
|   EXPECT_EQ(*handle->TryGet<int64_t>(), -1234567); | ||||
|   handle = flags::FindCommandLineFlag("test_flag_08"); | ||||
|   EXPECT_EQ(*handle->TryGet<uint64_t>(), 9876543); | ||||
|   handle = flags::FindCommandLineFlag("test_flag_09"); | ||||
|   EXPECT_NEAR(*handle->TryGet<double>(), -9.876e-50, 1e-55); | ||||
|   handle = flags::FindCommandLineFlag("test_flag_10"); | ||||
|   EXPECT_NEAR(*handle->TryGet<float>(), 1.234e12f, 1e5f); | ||||
|   handle = flags::FindCommandLineFlag("test_flag_11"); | ||||
|   EXPECT_EQ(*handle->TryGet<std::string>(), ""); | ||||
|   handle = flags::FindCommandLineFlag("test_flag_12"); | ||||
|   EXPECT_EQ(*handle->TryGet<absl::Duration>(), absl::Minutes(10)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| int GetDflt1() { return 1; } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| ABSL_FLAG(int, test_int_flag_with_non_const_default, GetDflt1(), | ||||
|           "test int flag non const default"); | ||||
| ABSL_FLAG(std::string, test_string_flag_with_non_const_default, | ||||
|           absl::StrCat("AAA", "BBB"), "test string flag non const default"); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| TEST_F(FlagTest, TestNonConstexprDefault) { | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_int_flag_with_non_const_default), 1); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_string_flag_with_non_const_default), | ||||
|             "AAABBB"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| ABSL_FLAG(bool, test_flag_with_non_const_help, true, | ||||
|           absl::StrCat("test ", "flag ", "non const help")); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| #if !ABSL_FLAGS_STRIP_HELP | ||||
| TEST_F(FlagTest, TestNonConstexprHelp) { | ||||
|   EXPECT_EQ(FLAGS_test_flag_with_non_const_help.Help(), | ||||
|             "test flag non const help"); | ||||
| } | ||||
| #endif  //! ABSL_FLAGS_STRIP_HELP
 | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| int cb_test_value = -1; | ||||
| void TestFlagCB(); | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| ABSL_FLAG(int, test_flag_with_cb, 100, "").OnUpdate(TestFlagCB); | ||||
| 
 | ||||
| ABSL_FLAG(int, test_flag_with_lambda_cb, 200, "").OnUpdate([]() { | ||||
|   cb_test_value = absl::GetFlag(FLAGS_test_flag_with_lambda_cb) + | ||||
|                   absl::GetFlag(FLAGS_test_flag_with_cb); | ||||
| }); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| void TestFlagCB() { cb_test_value = absl::GetFlag(FLAGS_test_flag_with_cb); } | ||||
| 
 | ||||
| // Tests side-effects of callback invocation.
 | ||||
| TEST_F(FlagTest, CallbackInvocation) { | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_cb), 100); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_lambda_cb), 200); | ||||
|   EXPECT_EQ(cb_test_value, 300); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_test_flag_with_cb, 1); | ||||
|   EXPECT_EQ(cb_test_value, 1); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_test_flag_with_lambda_cb, 3); | ||||
|   EXPECT_EQ(cb_test_value, 4); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| struct CustomUDT { | ||||
|   CustomUDT() : a(1), b(1) {} | ||||
|   CustomUDT(int a_, int b_) : a(a_), b(b_) {} | ||||
| 
 | ||||
|   friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) { | ||||
|     return f1.a == f2.a && f1.b == f2.b; | ||||
|   } | ||||
| 
 | ||||
|   int a; | ||||
|   int b; | ||||
| }; | ||||
| bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) { | ||||
|   std::vector<absl::string_view> parts = | ||||
|       absl::StrSplit(in, ':', absl::SkipWhitespace()); | ||||
| 
 | ||||
|   if (parts.size() != 2) return false; | ||||
| 
 | ||||
|   if (!absl::SimpleAtoi(parts[0], &f->a)) return false; | ||||
| 
 | ||||
|   if (!absl::SimpleAtoi(parts[1], &f->b)) return false; | ||||
| 
 | ||||
|   return true; | ||||
| } | ||||
| std::string AbslUnparseFlag(const CustomUDT& f) { | ||||
|   return absl::StrCat(f.a, ":", f.b); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| ABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(), "test flag custom UDT"); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| TEST_F(FlagTest, TestCustomUDT) { | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(1, 1)); | ||||
|   absl::SetFlag(&FLAGS_test_flag_custom_udt, CustomUDT(2, 3)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(2, 3)); | ||||
| } | ||||
| 
 | ||||
| // MSVC produces link error on the type mismatch.
 | ||||
| // Linux does not have build errors and validations work as expected.
 | ||||
| #if !defined(_WIN32) && GTEST_HAS_DEATH_TEST | ||||
| 
 | ||||
| using FlagDeathTest = FlagTest; | ||||
| 
 | ||||
| TEST_F(FlagDeathTest, TestTypeMismatchValidations) { | ||||
| #if !defined(NDEBUG) | ||||
|   EXPECT_DEATH_IF_SUPPORTED( | ||||
|       static_cast<void>(absl::GetFlag(FLAGS_mistyped_int_flag)), | ||||
|       "Flag 'mistyped_int_flag' is defined as one type and declared " | ||||
|       "as another"); | ||||
|   EXPECT_DEATH_IF_SUPPORTED( | ||||
|       static_cast<void>(absl::GetFlag(FLAGS_mistyped_string_flag)), | ||||
|       "Flag 'mistyped_string_flag' is defined as one type and " | ||||
|       "declared as another"); | ||||
| #endif | ||||
| 
 | ||||
|   EXPECT_DEATH_IF_SUPPORTED( | ||||
|       absl::SetFlag(&FLAGS_mistyped_int_flag, 1), | ||||
|       "Flag 'mistyped_int_flag' is defined as one type and declared " | ||||
|       "as another"); | ||||
|   EXPECT_DEATH_IF_SUPPORTED( | ||||
|       absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}), | ||||
|       "Flag 'mistyped_string_flag' is defined as one type and declared as " | ||||
|       "another"); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| // A contrived type that offers implicit and explicit conversion from specific
 | ||||
| // source types.
 | ||||
| struct ConversionTestVal { | ||||
|   ConversionTestVal() = default; | ||||
|   explicit ConversionTestVal(int a_in) : a(a_in) {} | ||||
| 
 | ||||
|   enum class ViaImplicitConv { kTen = 10, kEleven }; | ||||
|   // NOLINTNEXTLINE
 | ||||
|   ConversionTestVal(ViaImplicitConv from) : a(static_cast<int>(from)) {} | ||||
| 
 | ||||
|   int a; | ||||
| }; | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view in, ConversionTestVal* val_out, | ||||
|                    std::string*) { | ||||
|   if (!absl::SimpleAtoi(in, &val_out->a)) { | ||||
|     return false; | ||||
|   } | ||||
|   return true; | ||||
| } | ||||
| std::string AbslUnparseFlag(const ConversionTestVal& val) { | ||||
|   return absl::StrCat(val.a); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| // Flag default values can be specified with a value that converts to the flag
 | ||||
| // value type implicitly.
 | ||||
| ABSL_FLAG(ConversionTestVal, test_flag_implicit_conv, | ||||
|           ConversionTestVal::ViaImplicitConv::kTen, | ||||
|           "test flag init via implicit conversion"); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| TEST_F(FlagTest, CanSetViaImplicitConversion) { | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 10); | ||||
|   absl::SetFlag(&FLAGS_test_flag_implicit_conv, | ||||
|                 ConversionTestVal::ViaImplicitConv::kEleven); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 11); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| struct NonDfltConstructible { | ||||
|  public: | ||||
|   // This constructor tests that we can initialize the flag with int value
 | ||||
|   NonDfltConstructible(int i) : value(i) {}  // NOLINT
 | ||||
| 
 | ||||
|   // This constructor tests that we can't initialize the flag with char value
 | ||||
|   // but can with explicitly constructed NonDfltConstructible.
 | ||||
|   explicit NonDfltConstructible(char c) : value(100 + static_cast<int>(c)) {} | ||||
| 
 | ||||
|   int value; | ||||
| }; | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view in, NonDfltConstructible* ndc_out, | ||||
|                    std::string*) { | ||||
|   return absl::SimpleAtoi(in, &ndc_out->value); | ||||
| } | ||||
| std::string AbslUnparseFlag(const NonDfltConstructible& ndc) { | ||||
|   return absl::StrCat(ndc.value); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| ABSL_FLAG(NonDfltConstructible, ndc_flag1, NonDfltConstructible('1'), | ||||
|           "Flag with non default constructible type"); | ||||
| ABSL_FLAG(NonDfltConstructible, ndc_flag2, 0, | ||||
|           "Flag with non default constructible type"); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| TEST_F(FlagTest, TestNonDefaultConstructibleType) { | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, '1' + 100); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 0); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_ndc_flag1, NonDfltConstructible('A')); | ||||
|   absl::SetFlag(&FLAGS_ndc_flag2, 25); | ||||
| 
 | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, 'A' + 100); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 25); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr"); | ||||
| ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr"); | ||||
| ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr")); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| TEST_F(FlagTest, TestRetiredFlagRegistration) { | ||||
|   bool is_bool = false; | ||||
|   EXPECT_TRUE(flags::IsRetiredFlag("old_bool_flag", &is_bool)); | ||||
|   EXPECT_TRUE(is_bool); | ||||
|   EXPECT_TRUE(flags::IsRetiredFlag("old_int_flag", &is_bool)); | ||||
|   EXPECT_FALSE(is_bool); | ||||
|   EXPECT_TRUE(flags::IsRetiredFlag("old_str_flag", &is_bool)); | ||||
|   EXPECT_FALSE(is_bool); | ||||
|   EXPECT_FALSE(flags::IsRetiredFlag("some_other_flag", &is_bool)); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| // User-defined type with small alignment, but size exceeding 16.
 | ||||
| struct SmallAlignUDT { | ||||
|   SmallAlignUDT() : c('A'), s(12) {} | ||||
|   char c; | ||||
|   int16_t s; | ||||
|   char bytes[14]; | ||||
| }; | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view, SmallAlignUDT*, std::string*) { | ||||
|   return true; | ||||
| } | ||||
| std::string AbslUnparseFlag(const SmallAlignUDT&) { return ""; } | ||||
| 
 | ||||
| // User-defined type with small size, but not trivially copyable.
 | ||||
| struct NonTriviallyCopyableUDT { | ||||
|   NonTriviallyCopyableUDT() : c('A') {} | ||||
|   NonTriviallyCopyableUDT(const NonTriviallyCopyableUDT& rhs) : c(rhs.c) {} | ||||
|   NonTriviallyCopyableUDT& operator=(const NonTriviallyCopyableUDT& rhs) { | ||||
|     c = rhs.c; | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   char c; | ||||
| }; | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view, NonTriviallyCopyableUDT*, std::string*) { | ||||
|   return true; | ||||
| } | ||||
| std::string AbslUnparseFlag(const NonTriviallyCopyableUDT&) { return ""; } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| ABSL_FLAG(SmallAlignUDT, test_flag_sa_udt, {}, "help"); | ||||
| ABSL_FLAG(NonTriviallyCopyableUDT, test_flag_ntc_udt, {}, "help"); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| TEST_F(FlagTest, TestSmallAlignUDT) { | ||||
|   SmallAlignUDT value = absl::GetFlag(FLAGS_test_flag_sa_udt); | ||||
|   EXPECT_EQ(value.c, 'A'); | ||||
|   EXPECT_EQ(value.s, 12); | ||||
| 
 | ||||
|   value.c = 'B'; | ||||
|   value.s = 45; | ||||
|   absl::SetFlag(&FLAGS_test_flag_sa_udt, value); | ||||
|   value = absl::GetFlag(FLAGS_test_flag_sa_udt); | ||||
|   EXPECT_EQ(value.c, 'B'); | ||||
|   EXPECT_EQ(value.s, 45); | ||||
| } | ||||
| 
 | ||||
| TEST_F(FlagTest, TestNonTriviallyCopyableUDT) { | ||||
|   NonTriviallyCopyableUDT value = absl::GetFlag(FLAGS_test_flag_ntc_udt); | ||||
|   EXPECT_EQ(value.c, 'A'); | ||||
| 
 | ||||
|   value.c = 'B'; | ||||
|   absl::SetFlag(&FLAGS_test_flag_ntc_udt, value); | ||||
|   value = absl::GetFlag(FLAGS_test_flag_ntc_udt); | ||||
|   EXPECT_EQ(value.c, 'B'); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
							
								
								
									
										24
									
								
								third_party/abseil_cpp/absl/flags/flag_test_defs.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								third_party/abseil_cpp/absl/flags/flag_test_defs.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| // This file is used to test the mismatch of the flag type between definition
 | ||||
| // and declaration. These are definitions. flag_test.cc contains declarations.
 | ||||
| #include <string> | ||||
| #include "absl/flags/flag.h" | ||||
| 
 | ||||
| ABSL_FLAG(int, mistyped_int_flag, 0, ""); | ||||
| ABSL_FLAG(std::string, mistyped_string_flag, "", ""); | ||||
| ABSL_RETIRED_FLAG(bool, old_bool_flag, true, | ||||
|                   "repetition of retired flag definition"); | ||||
							
								
								
									
										34
									
								
								third_party/abseil_cpp/absl/flags/internal/commandlineflag.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								third_party/abseil_cpp/absl/flags/internal/commandlineflag.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| //
 | ||||
| // Copyright 2020 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| FlagStateInterface::~FlagStateInterface() {} | ||||
| 
 | ||||
| bool CommandLineFlag::IsRetired() const { return false; } | ||||
| 
 | ||||
| bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) { | ||||
|   return ParseFrom(value, flags_internal::SET_FLAGS_VALUE, | ||||
|                    flags_internal::kProgrammaticChange, error); | ||||
| } | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
							
								
								
									
										185
									
								
								third_party/abseil_cpp/absl/flags/internal/commandlineflag.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								third_party/abseil_cpp/absl/flags/internal/commandlineflag.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,185 @@ | |||
| //
 | ||||
| // Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_ | ||||
| #define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_ | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <string> | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/base/internal/fast_type_id.h" | ||||
| #include "absl/base/macros.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| #include "absl/types/optional.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| // An alias for flag fast type id. This value identifies the flag value type
 | ||||
| // simialarly to typeid(T), without relying on RTTI being available. In most
 | ||||
| // cases this id is enough to uniquely identify the flag's value type. In a few
 | ||||
| // cases we'll have to resort to using actual RTTI implementation if it is
 | ||||
| // available.
 | ||||
| using FlagFastTypeId = base_internal::FastTypeIdType; | ||||
| 
 | ||||
| // Options that control SetCommandLineOptionWithMode.
 | ||||
| enum FlagSettingMode { | ||||
|   // update the flag's value unconditionally (can call this multiple times).
 | ||||
|   SET_FLAGS_VALUE, | ||||
|   // update the flag's value, but *only if* it has not yet been updated
 | ||||
|   // with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef".
 | ||||
|   SET_FLAG_IF_DEFAULT, | ||||
|   // set the flag's default value to this.  If the flag has not been updated
 | ||||
|   // yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef")
 | ||||
|   // change the flag's current value to the new default value as well.
 | ||||
|   SET_FLAGS_DEFAULT | ||||
| }; | ||||
| 
 | ||||
| // Options that control ParseFrom: Source of a value.
 | ||||
| enum ValueSource { | ||||
|   // Flag is being set by value specified on a command line.
 | ||||
|   kCommandLine, | ||||
|   // Flag is being set by value specified in the code.
 | ||||
|   kProgrammaticChange, | ||||
| }; | ||||
| 
 | ||||
| // Handle to FlagState objects. Specific flag state objects will restore state
 | ||||
| // of a flag produced this flag state from method CommandLineFlag::SaveState().
 | ||||
| class FlagStateInterface { | ||||
|  public: | ||||
|   virtual ~FlagStateInterface(); | ||||
| 
 | ||||
|   // Restores the flag originated this object to the saved state.
 | ||||
|   virtual void Restore() const = 0; | ||||
| }; | ||||
| 
 | ||||
| // Holds all information for a flag.
 | ||||
| class CommandLineFlag { | ||||
|  public: | ||||
|   constexpr CommandLineFlag() = default; | ||||
| 
 | ||||
|   // Not copyable/assignable.
 | ||||
|   CommandLineFlag(const CommandLineFlag&) = delete; | ||||
|   CommandLineFlag& operator=(const CommandLineFlag&) = delete; | ||||
| 
 | ||||
|   // Non-polymorphic access methods.
 | ||||
| 
 | ||||
|   // Return true iff flag has type T.
 | ||||
|   template <typename T> | ||||
|   inline bool IsOfType() const { | ||||
|     return TypeId() == base_internal::FastTypeId<T>(); | ||||
|   } | ||||
| 
 | ||||
|   // Attempts to retrieve the flag value. Returns value on success,
 | ||||
|   // absl::nullopt otherwise.
 | ||||
|   template <typename T> | ||||
|   absl::optional<T> TryGet() const { | ||||
|     if (IsRetired() || !IsOfType<T>()) { | ||||
|       return absl::nullopt; | ||||
|     } | ||||
| 
 | ||||
|     // Implementation notes:
 | ||||
|     //
 | ||||
|     // We are wrapping a union around the value of `T` to serve three purposes:
 | ||||
|     //
 | ||||
|     //  1. `U.value` has correct size and alignment for a value of type `T`
 | ||||
|     //  2. The `U.value` constructor is not invoked since U's constructor does
 | ||||
|     //     not do it explicitly.
 | ||||
|     //  3. The `U.value` destructor is invoked since U's destructor does it
 | ||||
|     //     explicitly. This makes `U` a kind of RAII wrapper around non default
 | ||||
|     //     constructible value of T, which is destructed when we leave the
 | ||||
|     //     scope. We do need to destroy U.value, which is constructed by
 | ||||
|     //     CommandLineFlag::Read even though we left it in a moved-from state
 | ||||
|     //     after std::move.
 | ||||
|     //
 | ||||
|     // All of this serves to avoid requiring `T` being default constructible.
 | ||||
|     union U { | ||||
|       T value; | ||||
|       U() {} | ||||
|       ~U() { value.~T(); } | ||||
|     }; | ||||
|     U u; | ||||
| 
 | ||||
|     Read(&u.value); | ||||
|     return std::move(u.value); | ||||
|   } | ||||
| 
 | ||||
|   // Polymorphic access methods
 | ||||
| 
 | ||||
|   // Returns name of this flag.
 | ||||
|   virtual absl::string_view Name() const = 0; | ||||
|   // Returns name of the file where this flag is defined.
 | ||||
|   virtual std::string Filename() const = 0; | ||||
|   // Returns help message associated with this flag.
 | ||||
|   virtual std::string Help() const = 0; | ||||
|   // Returns true iff this object corresponds to retired flag.
 | ||||
|   virtual bool IsRetired() const; | ||||
|   virtual std::string DefaultValue() const = 0; | ||||
|   virtual std::string CurrentValue() const = 0; | ||||
| 
 | ||||
|   // Sets the value of the flag based on specified string `value`. If the flag
 | ||||
|   // was successfully set to new value, it returns true. Otherwise, sets `error`
 | ||||
|   // to indicate the error, leaves the flag unchanged, and returns false.
 | ||||
|   bool ParseFrom(absl::string_view value, std::string* error); | ||||
| 
 | ||||
|  protected: | ||||
|   ~CommandLineFlag() = default; | ||||
| 
 | ||||
|  private: | ||||
|   friend class PrivateHandleAccessor; | ||||
| 
 | ||||
|   // Sets the value of the flag based on specified string `value`. If the flag
 | ||||
|   // was successfully set to new value, it returns true. Otherwise, sets `error`
 | ||||
|   // to indicate the error, leaves the flag unchanged, and returns false. There
 | ||||
|   // are three ways to set the flag's value:
 | ||||
|   //  * Update the current flag value
 | ||||
|   //  * Update the flag's default value
 | ||||
|   //  * Update the current flag value if it was never set before
 | ||||
|   // The mode is selected based on `set_mode` parameter.
 | ||||
|   virtual bool ParseFrom(absl::string_view value, | ||||
|                          flags_internal::FlagSettingMode set_mode, | ||||
|                          flags_internal::ValueSource source, | ||||
|                          std::string* error) = 0; | ||||
| 
 | ||||
|   // Returns id of the flag's value type.
 | ||||
|   virtual FlagFastTypeId TypeId() const = 0; | ||||
| 
 | ||||
|   // Interface to save flag to some persistent state. Returns current flag state
 | ||||
|   // or nullptr if flag does not support saving and restoring a state.
 | ||||
|   virtual std::unique_ptr<FlagStateInterface> SaveState() = 0; | ||||
| 
 | ||||
|   // Copy-construct a new value of the flag's type in a memory referenced by
 | ||||
|   // the dst based on the current flag's value.
 | ||||
|   virtual void Read(void* dst) const = 0; | ||||
| 
 | ||||
|   // To be deleted. Used to return true if flag's current value originated from
 | ||||
|   // command line.
 | ||||
|   virtual bool IsSpecifiedOnCommandLine() const = 0; | ||||
| 
 | ||||
|   // Validates supplied value usign validator or parseflag routine
 | ||||
|   virtual bool ValidateInputValue(absl::string_view value) const = 0; | ||||
| 
 | ||||
|   // Checks that flags default value can be converted to string and back to the
 | ||||
|   // flag's value type.
 | ||||
|   virtual void CheckDefaultValueParsingRoundtrip() const = 0; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
 | ||||
							
								
								
									
										233
									
								
								third_party/abseil_cpp/absl/flags/internal/commandlineflag_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								third_party/abseil_cpp/absl/flags/internal/commandlineflag_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,233 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <string> | ||||
| 
 | ||||
| #include "gtest/gtest.h" | ||||
| #include "absl/flags/flag.h" | ||||
| #include "absl/flags/internal/private_handle_accessor.h" | ||||
| #include "absl/flags/internal/registry.h" | ||||
| #include "absl/flags/usage_config.h" | ||||
| #include "absl/memory/memory.h" | ||||
| #include "absl/strings/match.h" | ||||
| #include "absl/strings/str_cat.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| ABSL_FLAG(int, int_flag, 201, "int_flag help"); | ||||
| ABSL_FLAG(std::string, string_flag, "dflt", | ||||
|           absl::StrCat("string_flag", " help")); | ||||
| ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help"); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| namespace flags = absl::flags_internal; | ||||
| 
 | ||||
| class CommandLineFlagTest : public testing::Test { | ||||
|  protected: | ||||
|   static void SetUpTestSuite() { | ||||
|     // Install a function to normalize filenames before this test is run.
 | ||||
|     absl::FlagsUsageConfig default_config; | ||||
|     default_config.normalize_filename = &CommandLineFlagTest::NormalizeFileName; | ||||
|     absl::SetFlagsUsageConfig(default_config); | ||||
|   } | ||||
| 
 | ||||
|   void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); } | ||||
|   void TearDown() override { flag_saver_.reset(); } | ||||
| 
 | ||||
|  private: | ||||
|   static std::string NormalizeFileName(absl::string_view fname) { | ||||
| #ifdef _WIN32 | ||||
|     std::string normalized(fname); | ||||
|     std::replace(normalized.begin(), normalized.end(), '\\', '/'); | ||||
|     fname = normalized; | ||||
| #endif | ||||
|     return std::string(fname); | ||||
|   } | ||||
| 
 | ||||
|   std::unique_ptr<flags::FlagSaver> flag_saver_; | ||||
| }; | ||||
| 
 | ||||
| TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) { | ||||
|   auto* flag_01 = flags::FindCommandLineFlag("int_flag"); | ||||
| 
 | ||||
|   ASSERT_TRUE(flag_01); | ||||
|   EXPECT_EQ(flag_01->Name(), "int_flag"); | ||||
|   EXPECT_EQ(flag_01->Help(), "int_flag help"); | ||||
|   EXPECT_TRUE(!flag_01->IsRetired()); | ||||
|   EXPECT_TRUE(flag_01->IsOfType<int>()); | ||||
|   EXPECT_TRUE( | ||||
|       absl::EndsWith(flag_01->Filename(), | ||||
|                      "absl/flags/internal/commandlineflag_test.cc")) | ||||
|       << flag_01->Filename(); | ||||
| 
 | ||||
|   auto* flag_02 = flags::FindCommandLineFlag("string_flag"); | ||||
| 
 | ||||
|   ASSERT_TRUE(flag_02); | ||||
|   EXPECT_EQ(flag_02->Name(), "string_flag"); | ||||
|   EXPECT_EQ(flag_02->Help(), "string_flag help"); | ||||
|   EXPECT_TRUE(!flag_02->IsRetired()); | ||||
|   EXPECT_TRUE(flag_02->IsOfType<std::string>()); | ||||
|   EXPECT_TRUE( | ||||
|       absl::EndsWith(flag_02->Filename(), | ||||
|                      "absl/flags/internal/commandlineflag_test.cc")) | ||||
|       << flag_02->Filename(); | ||||
| 
 | ||||
|   auto* flag_03 = flags::FindRetiredFlag("bool_retired_flag"); | ||||
| 
 | ||||
|   ASSERT_TRUE(flag_03); | ||||
|   EXPECT_EQ(flag_03->Name(), "bool_retired_flag"); | ||||
|   EXPECT_EQ(flag_03->Help(), ""); | ||||
|   EXPECT_TRUE(flag_03->IsRetired()); | ||||
|   EXPECT_TRUE(flag_03->IsOfType<bool>()); | ||||
|   EXPECT_EQ(flag_03->Filename(), "RETIRED"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(CommandLineFlagTest, TestValueAccessMethods) { | ||||
|   absl::SetFlag(&FLAGS_int_flag, 301); | ||||
|   auto* flag_01 = flags::FindCommandLineFlag("int_flag"); | ||||
| 
 | ||||
|   ASSERT_TRUE(flag_01); | ||||
|   EXPECT_EQ(flag_01->CurrentValue(), "301"); | ||||
|   EXPECT_EQ(flag_01->DefaultValue(), "201"); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_string_flag, "new_str_value"); | ||||
|   auto* flag_02 = flags::FindCommandLineFlag("string_flag"); | ||||
| 
 | ||||
|   ASSERT_TRUE(flag_02); | ||||
|   EXPECT_EQ(flag_02->CurrentValue(), "new_str_value"); | ||||
|   EXPECT_EQ(flag_02->DefaultValue(), "dflt"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) { | ||||
|   std::string err; | ||||
| 
 | ||||
|   auto* flag_01 = flags::FindCommandLineFlag("int_flag"); | ||||
|   EXPECT_FALSE( | ||||
|       flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01)); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_01, "11", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11); | ||||
|   EXPECT_FALSE( | ||||
|       flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01)); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_01, "-123", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, | ||||
|       &err)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123); | ||||
|   EXPECT_FALSE( | ||||
|       flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01)); | ||||
| 
 | ||||
|   EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_01, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, | ||||
|       &err)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123); | ||||
|   EXPECT_EQ(err, "Illegal value 'xyz' specified for flag 'int_flag'"); | ||||
|   EXPECT_FALSE( | ||||
|       flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01)); | ||||
| 
 | ||||
|   EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_01, "A1", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123); | ||||
|   EXPECT_EQ(err, "Illegal value 'A1' specified for flag 'int_flag'"); | ||||
|   EXPECT_FALSE( | ||||
|       flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01)); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_01, "0x10", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, | ||||
|       &err)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16); | ||||
|   EXPECT_FALSE( | ||||
|       flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01)); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_01, "011", flags::SET_FLAGS_VALUE, flags::kCommandLine, &err)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11); | ||||
|   EXPECT_TRUE(flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01)); | ||||
| 
 | ||||
|   EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_01, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err)); | ||||
|   EXPECT_EQ(err, "Illegal value '' specified for flag 'int_flag'"); | ||||
| 
 | ||||
|   auto* flag_02 = flags::FindCommandLineFlag("string_flag"); | ||||
|   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_02, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, | ||||
|       &err)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "xyz"); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_02, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), ""); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(CommandLineFlagTest, TestParseFromDefaultValue) { | ||||
|   std::string err; | ||||
| 
 | ||||
|   auto* flag_01 = flags::FindCommandLineFlag("int_flag"); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_01, "111", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange, | ||||
|       &err)); | ||||
|   EXPECT_EQ(flag_01->DefaultValue(), "111"); | ||||
| 
 | ||||
|   auto* flag_02 = flags::FindCommandLineFlag("string_flag"); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_02, "abc", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange, | ||||
|       &err)); | ||||
|   EXPECT_EQ(flag_02->DefaultValue(), "abc"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(CommandLineFlagTest, TestParseFromIfDefault) { | ||||
|   std::string err; | ||||
| 
 | ||||
|   auto* flag_01 = flags::FindCommandLineFlag("int_flag"); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_01, "22", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange, | ||||
|       &err)) | ||||
|       << err; | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange, | ||||
|       &err)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22); | ||||
|   // EXPECT_EQ(err, "ERROR: int_flag is already set to 22");
 | ||||
| 
 | ||||
|   // Reset back to default value
 | ||||
|   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_01, "201", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, | ||||
|       &err)); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( | ||||
|       flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange, | ||||
|       &err)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 201); | ||||
|   // EXPECT_EQ(err, "ERROR: int_flag is already set to 201");
 | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
							
								
								
									
										564
									
								
								third_party/abseil_cpp/absl/flags/internal/flag.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										564
									
								
								third_party/abseil_cpp/absl/flags/internal/flag.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,564 @@ | |||
| //
 | ||||
| // Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/internal/flag.h" | ||||
| 
 | ||||
| #include <stddef.h> | ||||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include <atomic> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "absl/base/attributes.h" | ||||
| #include "absl/base/casts.h" | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/base/const_init.h" | ||||
| #include "absl/base/optimization.h" | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| #include "absl/flags/usage_config.h" | ||||
| #include "absl/strings/str_cat.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| #include "absl/synchronization/mutex.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| // The help message indicating that the commandline flag has been
 | ||||
| // 'stripped'. It will not show up when doing "-help" and its
 | ||||
| // variants. The flag is stripped if ABSL_FLAGS_STRIP_HELP is set to 1
 | ||||
| // before including absl/flags/flag.h
 | ||||
| const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001"; | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| // Currently we only validate flag values for user-defined flag types.
 | ||||
| bool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) { | ||||
| #define DONT_VALIDATE(T, _) \ | ||||
|   if (flag_type_id == base_internal::FastTypeId<T>()) return false; | ||||
|   ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(DONT_VALIDATE) | ||||
| #undef DONT_VALIDATE | ||||
| 
 | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| // RAII helper used to temporarily unlock and relock `absl::Mutex`.
 | ||||
| // This is used when we need to ensure that locks are released while
 | ||||
| // invoking user supplied callbacks and then reacquired, since callbacks may
 | ||||
| // need to acquire these locks themselves.
 | ||||
| class MutexRelock { | ||||
|  public: | ||||
|   explicit MutexRelock(absl::Mutex* mu) : mu_(mu) { mu_->Unlock(); } | ||||
|   ~MutexRelock() { mu_->Lock(); } | ||||
| 
 | ||||
|   MutexRelock(const MutexRelock&) = delete; | ||||
|   MutexRelock& operator=(const MutexRelock&) = delete; | ||||
| 
 | ||||
|  private: | ||||
|   absl::Mutex* mu_; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| // Persistent state of the flag data.
 | ||||
| 
 | ||||
| class FlagImpl; | ||||
| 
 | ||||
| class FlagState : public flags_internal::FlagStateInterface { | ||||
|  public: | ||||
|   template <typename V> | ||||
|   FlagState(FlagImpl* flag_impl, const V& v, bool modified, | ||||
|             bool on_command_line, int64_t counter) | ||||
|       : flag_impl_(flag_impl), | ||||
|         value_(v), | ||||
|         modified_(modified), | ||||
|         on_command_line_(on_command_line), | ||||
|         counter_(counter) {} | ||||
| 
 | ||||
|   ~FlagState() override { | ||||
|     if (flag_impl_->ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer) | ||||
|       return; | ||||
|     flags_internal::Delete(flag_impl_->op_, value_.heap_allocated); | ||||
|   } | ||||
| 
 | ||||
|  private: | ||||
|   friend class FlagImpl; | ||||
| 
 | ||||
|   // Restores the flag to the saved state.
 | ||||
|   void Restore() const override { | ||||
|     if (!flag_impl_->RestoreState(*this)) return; | ||||
| 
 | ||||
|     ABSL_INTERNAL_LOG( | ||||
|         INFO, absl::StrCat("Restore saved value of ", flag_impl_->Name(), | ||||
|                            " to: ", flag_impl_->CurrentValue())); | ||||
|   } | ||||
| 
 | ||||
|   // Flag and saved flag data.
 | ||||
|   FlagImpl* flag_impl_; | ||||
|   union SavedValue { | ||||
|     explicit SavedValue(void* v) : heap_allocated(v) {} | ||||
|     explicit SavedValue(int64_t v) : one_word(v) {} | ||||
|     explicit SavedValue(flags_internal::AlignedTwoWords v) : two_words(v) {} | ||||
| 
 | ||||
|     void* heap_allocated; | ||||
|     int64_t one_word; | ||||
|     flags_internal::AlignedTwoWords two_words; | ||||
|   } value_; | ||||
|   bool modified_; | ||||
|   bool on_command_line_; | ||||
|   int64_t counter_; | ||||
| }; | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| // Flag implementation, which does not depend on flag value type.
 | ||||
| 
 | ||||
| DynValueDeleter::DynValueDeleter(FlagOpFn op_arg) : op(op_arg) {} | ||||
| 
 | ||||
| void DynValueDeleter::operator()(void* ptr) const { | ||||
|   if (op == nullptr) return; | ||||
| 
 | ||||
|   Delete(op, ptr); | ||||
| } | ||||
| 
 | ||||
| void FlagImpl::Init() { | ||||
|   new (&data_guard_) absl::Mutex; | ||||
| 
 | ||||
|   auto def_kind = static_cast<FlagDefaultKind>(def_kind_); | ||||
| 
 | ||||
|   switch (ValueStorageKind()) { | ||||
|     case FlagValueStorageKind::kAlignedBuffer: | ||||
|       // For this storage kind the default_value_ always points to gen_func
 | ||||
|       // during initialization.
 | ||||
|       assert(def_kind == FlagDefaultKind::kGenFunc); | ||||
|       (*default_value_.gen_func)(AlignedBufferValue()); | ||||
|       break; | ||||
|     case FlagValueStorageKind::kOneWordAtomic: { | ||||
|       alignas(int64_t) std::array<char, sizeof(int64_t)> buf{}; | ||||
|       if (def_kind == FlagDefaultKind::kGenFunc) { | ||||
|         (*default_value_.gen_func)(buf.data()); | ||||
|       } else { | ||||
|         assert(def_kind != FlagDefaultKind::kDynamicValue); | ||||
|         std::memcpy(buf.data(), &default_value_, Sizeof(op_)); | ||||
|       } | ||||
|       OneWordValue().store(absl::bit_cast<int64_t>(buf), | ||||
|                            std::memory_order_release); | ||||
|       break; | ||||
|     } | ||||
|     case FlagValueStorageKind::kTwoWordsAtomic: { | ||||
|       // For this storage kind the default_value_ always points to gen_func
 | ||||
|       // during initialization.
 | ||||
|       assert(def_kind == FlagDefaultKind::kGenFunc); | ||||
|       alignas(AlignedTwoWords) std::array<char, sizeof(AlignedTwoWords)> buf{}; | ||||
|       (*default_value_.gen_func)(buf.data()); | ||||
|       auto atomic_value = absl::bit_cast<AlignedTwoWords>(buf); | ||||
|       TwoWordsValue().store(atomic_value, std::memory_order_release); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| absl::Mutex* FlagImpl::DataGuard() const { | ||||
|   absl::call_once(const_cast<FlagImpl*>(this)->init_control_, &FlagImpl::Init, | ||||
|                   const_cast<FlagImpl*>(this)); | ||||
| 
 | ||||
|   // data_guard_ is initialized inside Init.
 | ||||
|   return reinterpret_cast<absl::Mutex*>(&data_guard_); | ||||
| } | ||||
| 
 | ||||
| void FlagImpl::AssertValidType(FlagFastTypeId rhs_type_id, | ||||
|                                const std::type_info* (*gen_rtti)()) const { | ||||
|   FlagFastTypeId lhs_type_id = flags_internal::FastTypeId(op_); | ||||
| 
 | ||||
|   // `rhs_type_id` is the fast type id corresponding to the declaration
 | ||||
|   // visibile at the call site. `lhs_type_id` is the fast type id
 | ||||
|   // corresponding to the type specified in flag definition. They must match
 | ||||
|   //  for this operation to be well-defined.
 | ||||
|   if (ABSL_PREDICT_TRUE(lhs_type_id == rhs_type_id)) return; | ||||
| 
 | ||||
|   const std::type_info* lhs_runtime_type_id = | ||||
|       flags_internal::RuntimeTypeId(op_); | ||||
|   const std::type_info* rhs_runtime_type_id = (*gen_rtti)(); | ||||
| 
 | ||||
|   if (lhs_runtime_type_id == rhs_runtime_type_id) return; | ||||
| 
 | ||||
| #if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI) | ||||
|   if (*lhs_runtime_type_id == *rhs_runtime_type_id) return; | ||||
| #endif | ||||
| 
 | ||||
|   ABSL_INTERNAL_LOG( | ||||
|       FATAL, absl::StrCat("Flag '", Name(), | ||||
|                           "' is defined as one type and declared as another")); | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const { | ||||
|   void* res = nullptr; | ||||
|   switch (DefaultKind()) { | ||||
|     case FlagDefaultKind::kDynamicValue: | ||||
|       res = flags_internal::Clone(op_, default_value_.dynamic_value); | ||||
|       break; | ||||
|     case FlagDefaultKind::kGenFunc: | ||||
|       res = flags_internal::Alloc(op_); | ||||
|       (*default_value_.gen_func)(res); | ||||
|       break; | ||||
|     default: | ||||
|       res = flags_internal::Clone(op_, &default_value_); | ||||
|       break; | ||||
|   } | ||||
|   return {res, DynValueDeleter{op_}}; | ||||
| } | ||||
| 
 | ||||
| void FlagImpl::StoreValue(const void* src) { | ||||
|   switch (ValueStorageKind()) { | ||||
|     case FlagValueStorageKind::kAlignedBuffer: | ||||
|       Copy(op_, src, AlignedBufferValue()); | ||||
|       break; | ||||
|     case FlagValueStorageKind::kOneWordAtomic: { | ||||
|       int64_t one_word_val = 0; | ||||
|       std::memcpy(&one_word_val, src, Sizeof(op_)); | ||||
|       OneWordValue().store(one_word_val, std::memory_order_release); | ||||
|       break; | ||||
|     } | ||||
|     case FlagValueStorageKind::kTwoWordsAtomic: { | ||||
|       AlignedTwoWords two_words_val{0, 0}; | ||||
|       std::memcpy(&two_words_val, src, Sizeof(op_)); | ||||
|       TwoWordsValue().store(two_words_val, std::memory_order_release); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   modified_ = true; | ||||
|   ++counter_; | ||||
|   InvokeCallback(); | ||||
| } | ||||
| 
 | ||||
| absl::string_view FlagImpl::Name() const { return name_; } | ||||
| 
 | ||||
| std::string FlagImpl::Filename() const { | ||||
|   return flags_internal::GetUsageConfig().normalize_filename(filename_); | ||||
| } | ||||
| 
 | ||||
| std::string FlagImpl::Help() const { | ||||
|   return HelpSourceKind() == FlagHelpKind::kLiteral ? help_.literal | ||||
|                                                     : help_.gen_func(); | ||||
| } | ||||
| 
 | ||||
| FlagFastTypeId FlagImpl::TypeId() const { | ||||
|   return flags_internal::FastTypeId(op_); | ||||
| } | ||||
| 
 | ||||
| bool FlagImpl::IsSpecifiedOnCommandLine() const { | ||||
|   absl::MutexLock l(DataGuard()); | ||||
|   return on_command_line_; | ||||
| } | ||||
| 
 | ||||
| std::string FlagImpl::DefaultValue() const { | ||||
|   absl::MutexLock l(DataGuard()); | ||||
| 
 | ||||
|   auto obj = MakeInitValue(); | ||||
|   return flags_internal::Unparse(op_, obj.get()); | ||||
| } | ||||
| 
 | ||||
| std::string FlagImpl::CurrentValue() const { | ||||
|   auto* guard = DataGuard();  // Make sure flag initialized
 | ||||
|   switch (ValueStorageKind()) { | ||||
|     case FlagValueStorageKind::kAlignedBuffer: { | ||||
|       absl::MutexLock l(guard); | ||||
|       return flags_internal::Unparse(op_, AlignedBufferValue()); | ||||
|     } | ||||
|     case FlagValueStorageKind::kOneWordAtomic: { | ||||
|       const auto one_word_val = | ||||
|           absl::bit_cast<std::array<char, sizeof(int64_t)>>( | ||||
|               OneWordValue().load(std::memory_order_acquire)); | ||||
|       return flags_internal::Unparse(op_, one_word_val.data()); | ||||
|     } | ||||
|     case FlagValueStorageKind::kTwoWordsAtomic: { | ||||
|       const auto two_words_val = | ||||
|           absl::bit_cast<std::array<char, sizeof(AlignedTwoWords)>>( | ||||
|               TwoWordsValue().load(std::memory_order_acquire)); | ||||
|       return flags_internal::Unparse(op_, two_words_val.data()); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return ""; | ||||
| } | ||||
| 
 | ||||
| void FlagImpl::SetCallback(const FlagCallbackFunc mutation_callback) { | ||||
|   absl::MutexLock l(DataGuard()); | ||||
| 
 | ||||
|   if (callback_ == nullptr) { | ||||
|     callback_ = new FlagCallback; | ||||
|   } | ||||
|   callback_->func = mutation_callback; | ||||
| 
 | ||||
|   InvokeCallback(); | ||||
| } | ||||
| 
 | ||||
| void FlagImpl::InvokeCallback() const { | ||||
|   if (!callback_) return; | ||||
| 
 | ||||
|   // Make a copy of the C-style function pointer that we are about to invoke
 | ||||
|   // before we release the lock guarding it.
 | ||||
|   FlagCallbackFunc cb = callback_->func; | ||||
| 
 | ||||
|   // If the flag has a mutation callback this function invokes it. While the
 | ||||
|   // callback is being invoked the primary flag's mutex is unlocked and it is
 | ||||
|   // re-locked back after call to callback is completed. Callback invocation is
 | ||||
|   // guarded by flag's secondary mutex instead which prevents concurrent
 | ||||
|   // callback invocation. Note that it is possible for other thread to grab the
 | ||||
|   // primary lock and update flag's value at any time during the callback
 | ||||
|   // invocation. This is by design. Callback can get a value of the flag if
 | ||||
|   // necessary, but it might be different from the value initiated the callback
 | ||||
|   // and it also can be different by the time the callback invocation is
 | ||||
|   // completed. Requires that *primary_lock be held in exclusive mode; it may be
 | ||||
|   // released and reacquired by the implementation.
 | ||||
|   MutexRelock relock(DataGuard()); | ||||
|   absl::MutexLock lock(&callback_->guard); | ||||
|   cb(); | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() { | ||||
|   absl::MutexLock l(DataGuard()); | ||||
| 
 | ||||
|   bool modified = modified_; | ||||
|   bool on_command_line = on_command_line_; | ||||
|   switch (ValueStorageKind()) { | ||||
|     case FlagValueStorageKind::kAlignedBuffer: { | ||||
|       return absl::make_unique<FlagState>( | ||||
|           this, flags_internal::Clone(op_, AlignedBufferValue()), modified, | ||||
|           on_command_line, counter_); | ||||
|     } | ||||
|     case FlagValueStorageKind::kOneWordAtomic: { | ||||
|       return absl::make_unique<FlagState>( | ||||
|           this, OneWordValue().load(std::memory_order_acquire), modified, | ||||
|           on_command_line, counter_); | ||||
|     } | ||||
|     case FlagValueStorageKind::kTwoWordsAtomic: { | ||||
|       return absl::make_unique<FlagState>( | ||||
|           this, TwoWordsValue().load(std::memory_order_acquire), modified, | ||||
|           on_command_line, counter_); | ||||
|     } | ||||
|   } | ||||
|   return nullptr; | ||||
| } | ||||
| 
 | ||||
| bool FlagImpl::RestoreState(const FlagState& flag_state) { | ||||
|   absl::MutexLock l(DataGuard()); | ||||
| 
 | ||||
|   if (flag_state.counter_ == counter_) { | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   switch (ValueStorageKind()) { | ||||
|     case FlagValueStorageKind::kAlignedBuffer: | ||||
|       StoreValue(flag_state.value_.heap_allocated); | ||||
|       break; | ||||
|     case FlagValueStorageKind::kOneWordAtomic: | ||||
|       StoreValue(&flag_state.value_.one_word); | ||||
|       break; | ||||
|     case FlagValueStorageKind::kTwoWordsAtomic: | ||||
|       StoreValue(&flag_state.value_.two_words); | ||||
|       break; | ||||
|   } | ||||
| 
 | ||||
|   modified_ = flag_state.modified_; | ||||
|   on_command_line_ = flag_state.on_command_line_; | ||||
| 
 | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| template <typename StorageT> | ||||
| StorageT* FlagImpl::OffsetValue() const { | ||||
|   char* p = reinterpret_cast<char*>(const_cast<FlagImpl*>(this)); | ||||
|   // The offset is deduced via Flag value type specific op_.
 | ||||
|   size_t offset = flags_internal::ValueOffset(op_); | ||||
| 
 | ||||
|   return reinterpret_cast<StorageT*>(p + offset); | ||||
| } | ||||
| 
 | ||||
| void* FlagImpl::AlignedBufferValue() const { | ||||
|   assert(ValueStorageKind() == FlagValueStorageKind::kAlignedBuffer); | ||||
|   return OffsetValue<void>(); | ||||
| } | ||||
| 
 | ||||
| std::atomic<int64_t>& FlagImpl::OneWordValue() const { | ||||
|   assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic); | ||||
|   return OffsetValue<FlagOneWordValue>()->value; | ||||
| } | ||||
| 
 | ||||
| std::atomic<AlignedTwoWords>& FlagImpl::TwoWordsValue() const { | ||||
|   assert(ValueStorageKind() == FlagValueStorageKind::kTwoWordsAtomic); | ||||
|   return OffsetValue<FlagTwoWordsValue>()->value; | ||||
| } | ||||
| 
 | ||||
| // Attempts to parse supplied `value` string using parsing routine in the `flag`
 | ||||
| // argument. If parsing successful, this function replaces the dst with newly
 | ||||
| // parsed value. In case if any error is encountered in either step, the error
 | ||||
| // message is stored in 'err'
 | ||||
| std::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse( | ||||
|     absl::string_view value, std::string* err) const { | ||||
|   std::unique_ptr<void, DynValueDeleter> tentative_value = MakeInitValue(); | ||||
| 
 | ||||
|   std::string parse_err; | ||||
|   if (!flags_internal::Parse(op_, value, tentative_value.get(), &parse_err)) { | ||||
|     absl::string_view err_sep = parse_err.empty() ? "" : "; "; | ||||
|     *err = absl::StrCat("Illegal value '", value, "' specified for flag '", | ||||
|                         Name(), "'", err_sep, parse_err); | ||||
|     return nullptr; | ||||
|   } | ||||
| 
 | ||||
|   return tentative_value; | ||||
| } | ||||
| 
 | ||||
| void FlagImpl::Read(void* dst) const { | ||||
|   auto* guard = DataGuard();  // Make sure flag initialized
 | ||||
|   switch (ValueStorageKind()) { | ||||
|     case FlagValueStorageKind::kAlignedBuffer: { | ||||
|       absl::MutexLock l(guard); | ||||
|       flags_internal::CopyConstruct(op_, AlignedBufferValue(), dst); | ||||
|       break; | ||||
|     } | ||||
|     case FlagValueStorageKind::kOneWordAtomic: { | ||||
|       const int64_t one_word_val = | ||||
|           OneWordValue().load(std::memory_order_acquire); | ||||
|       std::memcpy(dst, &one_word_val, Sizeof(op_)); | ||||
|       break; | ||||
|     } | ||||
|     case FlagValueStorageKind::kTwoWordsAtomic: { | ||||
|       const AlignedTwoWords two_words_val = | ||||
|           TwoWordsValue().load(std::memory_order_acquire); | ||||
|       std::memcpy(dst, &two_words_val, Sizeof(op_)); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void FlagImpl::Write(const void* src) { | ||||
|   absl::MutexLock l(DataGuard()); | ||||
| 
 | ||||
|   if (ShouldValidateFlagValue(flags_internal::FastTypeId(op_))) { | ||||
|     std::unique_ptr<void, DynValueDeleter> obj{flags_internal::Clone(op_, src), | ||||
|                                                DynValueDeleter{op_}}; | ||||
|     std::string ignored_error; | ||||
|     std::string src_as_str = flags_internal::Unparse(op_, src); | ||||
|     if (!flags_internal::Parse(op_, src_as_str, obj.get(), &ignored_error)) { | ||||
|       ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", Name(), | ||||
|                                             "' to invalid value ", src_as_str)); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   StoreValue(src); | ||||
| } | ||||
| 
 | ||||
| // Sets the value of the flag based on specified string `value`. If the flag
 | ||||
| // was successfully set to new value, it returns true. Otherwise, sets `err`
 | ||||
| // to indicate the error, leaves the flag unchanged, and returns false. There
 | ||||
| // are three ways to set the flag's value:
 | ||||
| //  * Update the current flag value
 | ||||
| //  * Update the flag's default value
 | ||||
| //  * Update the current flag value if it was never set before
 | ||||
| // The mode is selected based on 'set_mode' parameter.
 | ||||
| bool FlagImpl::ParseFrom(absl::string_view value, FlagSettingMode set_mode, | ||||
|                          ValueSource source, std::string* err) { | ||||
|   absl::MutexLock l(DataGuard()); | ||||
| 
 | ||||
|   switch (set_mode) { | ||||
|     case SET_FLAGS_VALUE: { | ||||
|       // set or modify the flag's value
 | ||||
|       auto tentative_value = TryParse(value, err); | ||||
|       if (!tentative_value) return false; | ||||
| 
 | ||||
|       StoreValue(tentative_value.get()); | ||||
| 
 | ||||
|       if (source == kCommandLine) { | ||||
|         on_command_line_ = true; | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
|     case SET_FLAG_IF_DEFAULT: { | ||||
|       // set the flag's value, but only if it hasn't been set by someone else
 | ||||
|       if (modified_) { | ||||
|         // TODO(rogeeff): review and fix this semantic. Currently we do not fail
 | ||||
|         // in this case if flag is modified. This is misleading since the flag's
 | ||||
|         // value is not updated even though we return true.
 | ||||
|         // *err = absl::StrCat(Name(), " is already set to ",
 | ||||
|         //                     CurrentValue(), "\n");
 | ||||
|         // return false;
 | ||||
|         return true; | ||||
|       } | ||||
|       auto tentative_value = TryParse(value, err); | ||||
|       if (!tentative_value) return false; | ||||
| 
 | ||||
|       StoreValue(tentative_value.get()); | ||||
|       break; | ||||
|     } | ||||
|     case SET_FLAGS_DEFAULT: { | ||||
|       auto tentative_value = TryParse(value, err); | ||||
|       if (!tentative_value) return false; | ||||
| 
 | ||||
|       if (DefaultKind() == FlagDefaultKind::kDynamicValue) { | ||||
|         void* old_value = default_value_.dynamic_value; | ||||
|         default_value_.dynamic_value = tentative_value.release(); | ||||
|         tentative_value.reset(old_value); | ||||
|       } else { | ||||
|         default_value_.dynamic_value = tentative_value.release(); | ||||
|         def_kind_ = static_cast<uint8_t>(FlagDefaultKind::kDynamicValue); | ||||
|       } | ||||
| 
 | ||||
|       if (!modified_) { | ||||
|         // Need to set both default value *and* current, in this case.
 | ||||
|         StoreValue(default_value_.dynamic_value); | ||||
|         modified_ = false; | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| void FlagImpl::CheckDefaultValueParsingRoundtrip() const { | ||||
|   std::string v = DefaultValue(); | ||||
| 
 | ||||
|   absl::MutexLock lock(DataGuard()); | ||||
| 
 | ||||
|   auto dst = MakeInitValue(); | ||||
|   std::string error; | ||||
|   if (!flags_internal::Parse(op_, v, dst.get(), &error)) { | ||||
|     ABSL_INTERNAL_LOG( | ||||
|         FATAL, | ||||
|         absl::StrCat("Flag ", Name(), " (from ", Filename(), | ||||
|                      "): string form of default value '", v, | ||||
|                      "' could not be parsed; error=", error)); | ||||
|   } | ||||
| 
 | ||||
|   // We do not compare dst to def since parsing/unparsing may make
 | ||||
|   // small changes, e.g., precision loss for floating point types.
 | ||||
| } | ||||
| 
 | ||||
| bool FlagImpl::ValidateInputValue(absl::string_view value) const { | ||||
|   absl::MutexLock l(DataGuard()); | ||||
| 
 | ||||
|   auto obj = MakeInitValue(); | ||||
|   std::string ignored_error; | ||||
|   return flags_internal::Parse(op_, value, obj.get(), &ignored_error); | ||||
| } | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
							
								
								
									
										745
									
								
								third_party/abseil_cpp/absl/flags/internal/flag.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										745
									
								
								third_party/abseil_cpp/absl/flags/internal/flag.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,745 @@ | |||
| //
 | ||||
| // Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_INTERNAL_FLAG_H_ | ||||
| #define ABSL_FLAGS_INTERNAL_FLAG_H_ | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| #include <atomic> | ||||
| #include <cstring> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <type_traits> | ||||
| #include <typeinfo> | ||||
| 
 | ||||
| #include "absl/base/call_once.h" | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/base/thread_annotations.h" | ||||
| #include "absl/flags/config.h" | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| #include "absl/flags/internal/registry.h" | ||||
| #include "absl/flags/marshalling.h" | ||||
| #include "absl/memory/memory.h" | ||||
| #include "absl/meta/type_traits.h" | ||||
| #include "absl/strings/str_cat.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| #include "absl/synchronization/mutex.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| 
 | ||||
| // Forward declaration of absl::Flag<T> public API.
 | ||||
| namespace flags_internal { | ||||
| template <typename T> | ||||
| class Flag; | ||||
| }  // namespace flags_internal
 | ||||
| 
 | ||||
| #if defined(_MSC_VER) && !defined(__clang__) | ||||
| template <typename T> | ||||
| class Flag; | ||||
| #else | ||||
| template <typename T> | ||||
| using Flag = flags_internal::Flag<T>; | ||||
| #endif | ||||
| 
 | ||||
| template <typename T> | ||||
| ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag); | ||||
| 
 | ||||
| template <typename T> | ||||
| void SetFlag(absl::Flag<T>* flag, const T& v); | ||||
| 
 | ||||
| template <typename T, typename V> | ||||
| void SetFlag(absl::Flag<T>* flag, const V& v); | ||||
| 
 | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| // Flag value type operations, eg., parsing, copying, etc. are provided
 | ||||
| // by function specific to that type with a signature matching FlagOpFn.
 | ||||
| 
 | ||||
| enum class FlagOp { | ||||
|   kAlloc, | ||||
|   kDelete, | ||||
|   kCopy, | ||||
|   kCopyConstruct, | ||||
|   kSizeof, | ||||
|   kFastTypeId, | ||||
|   kRuntimeTypeId, | ||||
|   kParse, | ||||
|   kUnparse, | ||||
|   kValueOffset, | ||||
| }; | ||||
| using FlagOpFn = void* (*)(FlagOp, const void*, void*, void*); | ||||
| 
 | ||||
| // Forward declaration for Flag value specific operations.
 | ||||
| template <typename T> | ||||
| void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3); | ||||
| 
 | ||||
| // Allocate aligned memory for a flag value.
 | ||||
| inline void* Alloc(FlagOpFn op) { | ||||
|   return op(FlagOp::kAlloc, nullptr, nullptr, nullptr); | ||||
| } | ||||
| // Deletes memory interpreting obj as flag value type pointer.
 | ||||
| inline void Delete(FlagOpFn op, void* obj) { | ||||
|   op(FlagOp::kDelete, nullptr, obj, nullptr); | ||||
| } | ||||
| // Copies src to dst interpreting as flag value type pointers.
 | ||||
| inline void Copy(FlagOpFn op, const void* src, void* dst) { | ||||
|   op(FlagOp::kCopy, src, dst, nullptr); | ||||
| } | ||||
| // Construct a copy of flag value in a location pointed by dst
 | ||||
| // based on src - pointer to the flag's value.
 | ||||
| inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) { | ||||
|   op(FlagOp::kCopyConstruct, src, dst, nullptr); | ||||
| } | ||||
| // Makes a copy of flag value pointed by obj.
 | ||||
| inline void* Clone(FlagOpFn op, const void* obj) { | ||||
|   void* res = flags_internal::Alloc(op); | ||||
|   flags_internal::CopyConstruct(op, obj, res); | ||||
|   return res; | ||||
| } | ||||
| // Returns true if parsing of input text is successfull.
 | ||||
| inline bool Parse(FlagOpFn op, absl::string_view text, void* dst, | ||||
|                   std::string* error) { | ||||
|   return op(FlagOp::kParse, &text, dst, error) != nullptr; | ||||
| } | ||||
| // Returns string representing supplied value.
 | ||||
| inline std::string Unparse(FlagOpFn op, const void* val) { | ||||
|   std::string result; | ||||
|   op(FlagOp::kUnparse, val, &result, nullptr); | ||||
|   return result; | ||||
| } | ||||
| // Returns size of flag value type.
 | ||||
| inline size_t Sizeof(FlagOpFn op) { | ||||
|   // This sequence of casts reverses the sequence from
 | ||||
|   // `flags_internal::FlagOps()`
 | ||||
|   return static_cast<size_t>(reinterpret_cast<intptr_t>( | ||||
|       op(FlagOp::kSizeof, nullptr, nullptr, nullptr))); | ||||
| } | ||||
| // Returns fast type id coresponding to the value type.
 | ||||
| inline FlagFastTypeId FastTypeId(FlagOpFn op) { | ||||
|   return reinterpret_cast<FlagFastTypeId>( | ||||
|       op(FlagOp::kFastTypeId, nullptr, nullptr, nullptr)); | ||||
| } | ||||
| // Returns fast type id coresponding to the value type.
 | ||||
| inline const std::type_info* RuntimeTypeId(FlagOpFn op) { | ||||
|   return reinterpret_cast<const std::type_info*>( | ||||
|       op(FlagOp::kRuntimeTypeId, nullptr, nullptr, nullptr)); | ||||
| } | ||||
| // Returns offset of the field value_ from the field impl_ inside of
 | ||||
| // absl::Flag<T> data. Given FlagImpl pointer p you can get the
 | ||||
| // location of the corresponding value as:
 | ||||
| //      reinterpret_cast<char*>(p) + ValueOffset().
 | ||||
| inline ptrdiff_t ValueOffset(FlagOpFn op) { | ||||
|   // This sequence of casts reverses the sequence from
 | ||||
|   // `flags_internal::FlagOps()`
 | ||||
|   return static_cast<ptrdiff_t>(reinterpret_cast<intptr_t>( | ||||
|       op(FlagOp::kValueOffset, nullptr, nullptr, nullptr))); | ||||
| } | ||||
| 
 | ||||
| // Returns an address of RTTI's typeid(T).
 | ||||
| template <typename T> | ||||
| inline const std::type_info* GenRuntimeTypeId() { | ||||
| #if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI) | ||||
|   return &typeid(T); | ||||
| #else | ||||
|   return nullptr; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| // Flag help auxiliary structs.
 | ||||
| 
 | ||||
| // This is help argument for absl::Flag encapsulating the string literal pointer
 | ||||
| // or pointer to function generating it as well as enum descriminating two
 | ||||
| // cases.
 | ||||
| using HelpGenFunc = std::string (*)(); | ||||
| 
 | ||||
| union FlagHelpMsg { | ||||
|   constexpr explicit FlagHelpMsg(const char* help_msg) : literal(help_msg) {} | ||||
|   constexpr explicit FlagHelpMsg(HelpGenFunc help_gen) : gen_func(help_gen) {} | ||||
| 
 | ||||
|   const char* literal; | ||||
|   HelpGenFunc gen_func; | ||||
| }; | ||||
| 
 | ||||
| enum class FlagHelpKind : uint8_t { kLiteral = 0, kGenFunc = 1 }; | ||||
| 
 | ||||
| struct FlagHelpArg { | ||||
|   FlagHelpMsg source; | ||||
|   FlagHelpKind kind; | ||||
| }; | ||||
| 
 | ||||
| extern const char kStrippedFlagHelp[]; | ||||
| 
 | ||||
| // HelpConstexprWrap is used by struct AbslFlagHelpGenFor##name generated by
 | ||||
| // ABSL_FLAG macro. It is only used to silence the compiler in the case where
 | ||||
| // help message expression is not constexpr and does not have type const char*.
 | ||||
| // If help message expression is indeed constexpr const char* HelpConstexprWrap
 | ||||
| // is just a trivial identity function.
 | ||||
| template <typename T> | ||||
| const char* HelpConstexprWrap(const T&) { | ||||
|   return nullptr; | ||||
| } | ||||
| constexpr const char* HelpConstexprWrap(const char* p) { return p; } | ||||
| constexpr const char* HelpConstexprWrap(char* p) { return p; } | ||||
| 
 | ||||
| // These two HelpArg overloads allows us to select at compile time one of two
 | ||||
| // way to pass Help argument to absl::Flag. We'll be passing
 | ||||
| // AbslFlagHelpGenFor##name as T and integer 0 as a single argument to prefer
 | ||||
| // first overload if possible. If T::Const is evaluatable on constexpr
 | ||||
| // context (see non template int parameter below) we'll choose first overload.
 | ||||
| // In this case the help message expression is immediately evaluated and is used
 | ||||
| // to construct the absl::Flag. No additionl code is generated by ABSL_FLAG.
 | ||||
| // Otherwise SFINAE kicks in and first overload is dropped from the
 | ||||
| // consideration, in which case the second overload will be used. The second
 | ||||
| // overload does not attempt to evaluate the help message expression
 | ||||
| // immediately and instead delays the evaluation by returing the function
 | ||||
| // pointer (&T::NonConst) genering the help message when necessary. This is
 | ||||
| // evaluatable in constexpr context, but the cost is an extra function being
 | ||||
| // generated in the ABSL_FLAG code.
 | ||||
| template <typename T, int = (T::Const(), 1)> | ||||
| constexpr FlagHelpArg HelpArg(int) { | ||||
|   return {FlagHelpMsg(T::Const()), FlagHelpKind::kLiteral}; | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| constexpr FlagHelpArg HelpArg(char) { | ||||
|   return {FlagHelpMsg(&T::NonConst), FlagHelpKind::kGenFunc}; | ||||
| } | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| // Flag default value auxiliary structs.
 | ||||
| 
 | ||||
| // Signature for the function generating the initial flag value (usually
 | ||||
| // based on default value supplied in flag's definition)
 | ||||
| using FlagDfltGenFunc = void (*)(void*); | ||||
| 
 | ||||
| union FlagDefaultSrc { | ||||
|   constexpr explicit FlagDefaultSrc(FlagDfltGenFunc gen_func_arg) | ||||
|       : gen_func(gen_func_arg) {} | ||||
| 
 | ||||
| #define ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE(T, name) \ | ||||
|   T name##_value;                                  \ | ||||
|   constexpr explicit FlagDefaultSrc(T value) : name##_value(value) {}  // NOLINT
 | ||||
|   ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE) | ||||
| #undef ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE | ||||
| 
 | ||||
|   void* dynamic_value; | ||||
|   FlagDfltGenFunc gen_func; | ||||
| }; | ||||
| 
 | ||||
| enum class FlagDefaultKind : uint8_t { | ||||
|   kDynamicValue = 0, | ||||
|   kGenFunc = 1, | ||||
|   kOneWord = 2  // for default values UP to one word in size
 | ||||
| }; | ||||
| 
 | ||||
| struct FlagDefaultArg { | ||||
|   FlagDefaultSrc source; | ||||
|   FlagDefaultKind kind; | ||||
| }; | ||||
| 
 | ||||
| // This struct and corresponding overload to InitDefaultValue are used to
 | ||||
| // facilitate usage of {} as default value in ABSL_FLAG macro.
 | ||||
| // TODO(rogeeff): Fix handling types with explicit constructors.
 | ||||
| struct EmptyBraces {}; | ||||
| 
 | ||||
| template <typename T> | ||||
| constexpr T InitDefaultValue(T t) { | ||||
|   return t; | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| constexpr T InitDefaultValue(EmptyBraces) { | ||||
|   return T{}; | ||||
| } | ||||
| 
 | ||||
| template <typename ValueT, typename GenT, | ||||
|           typename std::enable_if<std::is_integral<ValueT>::value, int>::type = | ||||
|               (GenT{}, 0)> | ||||
| constexpr FlagDefaultArg DefaultArg(int) { | ||||
|   return {FlagDefaultSrc(GenT{}.value), FlagDefaultKind::kOneWord}; | ||||
| } | ||||
| 
 | ||||
| template <typename ValueT, typename GenT> | ||||
| constexpr FlagDefaultArg DefaultArg(char) { | ||||
|   return {FlagDefaultSrc(&GenT::Gen), FlagDefaultKind::kGenFunc}; | ||||
| } | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| // Flag current value auxiliary structs.
 | ||||
| 
 | ||||
| constexpr int64_t UninitializedFlagValue() { return 0xababababababababll; } | ||||
| 
 | ||||
| template <typename T> | ||||
| using FlagUseOneWordStorage = std::integral_constant< | ||||
|     bool, absl::type_traits_internal::is_trivially_copyable<T>::value && | ||||
|               (sizeof(T) <= 8)>; | ||||
| 
 | ||||
| #if defined(ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD) | ||||
| // Clang does not always produce cmpxchg16b instruction when alignment of a 16
 | ||||
| // bytes type is not 16.
 | ||||
| struct alignas(16) AlignedTwoWords { | ||||
|   int64_t first; | ||||
|   int64_t second; | ||||
| 
 | ||||
|   bool IsInitialized() const { | ||||
|     return first != flags_internal::UninitializedFlagValue(); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| using FlagUseTwoWordsStorage = std::integral_constant< | ||||
|     bool, absl::type_traits_internal::is_trivially_copyable<T>::value && | ||||
|               (sizeof(T) > 8) && (sizeof(T) <= 16)>; | ||||
| #else | ||||
| // This is actually unused and only here to avoid ifdefs in other palces.
 | ||||
| struct AlignedTwoWords { | ||||
|   constexpr AlignedTwoWords() noexcept : dummy() {} | ||||
|   constexpr AlignedTwoWords(int64_t, int64_t) noexcept : dummy() {} | ||||
|   char dummy; | ||||
| 
 | ||||
|   bool IsInitialized() const { | ||||
|     std::abort(); | ||||
|     return true; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| // This trait should be type dependent, otherwise SFINAE below will fail
 | ||||
| template <typename T> | ||||
| using FlagUseTwoWordsStorage = | ||||
|     std::integral_constant<bool, sizeof(T) != sizeof(T)>; | ||||
| #endif | ||||
| 
 | ||||
| template <typename T> | ||||
| using FlagUseBufferStorage = | ||||
|     std::integral_constant<bool, !FlagUseOneWordStorage<T>::value && | ||||
|                                      !FlagUseTwoWordsStorage<T>::value>; | ||||
| 
 | ||||
| enum class FlagValueStorageKind : uint8_t { | ||||
|   kAlignedBuffer = 0, | ||||
|   kOneWordAtomic = 1, | ||||
|   kTwoWordsAtomic = 2 | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| static constexpr FlagValueStorageKind StorageKind() { | ||||
|   return FlagUseBufferStorage<T>::value | ||||
|              ? FlagValueStorageKind::kAlignedBuffer | ||||
|              : FlagUseOneWordStorage<T>::value | ||||
|                    ? FlagValueStorageKind::kOneWordAtomic | ||||
|                    : FlagValueStorageKind::kTwoWordsAtomic; | ||||
| } | ||||
| 
 | ||||
| struct FlagOneWordValue { | ||||
|   constexpr FlagOneWordValue() : value(UninitializedFlagValue()) {} | ||||
| 
 | ||||
|   std::atomic<int64_t> value; | ||||
| }; | ||||
| 
 | ||||
| struct FlagTwoWordsValue { | ||||
|   constexpr FlagTwoWordsValue() | ||||
|       : value(AlignedTwoWords{UninitializedFlagValue(), 0}) {} | ||||
| 
 | ||||
|   std::atomic<AlignedTwoWords> value; | ||||
| }; | ||||
| 
 | ||||
| template <typename T, | ||||
|           FlagValueStorageKind Kind = flags_internal::StorageKind<T>()> | ||||
| struct FlagValue; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct FlagValue<T, FlagValueStorageKind::kAlignedBuffer> { | ||||
|   bool Get(T*) const { return false; } | ||||
| 
 | ||||
|   alignas(T) char value[sizeof(T)]; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct FlagValue<T, FlagValueStorageKind::kOneWordAtomic> : FlagOneWordValue { | ||||
|   bool Get(T* dst) const { | ||||
|     int64_t one_word_val = value.load(std::memory_order_acquire); | ||||
|     if (ABSL_PREDICT_FALSE(one_word_val == UninitializedFlagValue())) { | ||||
|       return false; | ||||
|     } | ||||
|     std::memcpy(dst, static_cast<const void*>(&one_word_val), sizeof(T)); | ||||
|     return true; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct FlagValue<T, FlagValueStorageKind::kTwoWordsAtomic> : FlagTwoWordsValue { | ||||
|   bool Get(T* dst) const { | ||||
|     AlignedTwoWords two_words_val = value.load(std::memory_order_acquire); | ||||
|     if (ABSL_PREDICT_FALSE(!two_words_val.IsInitialized())) { | ||||
|       return false; | ||||
|     } | ||||
|     std::memcpy(dst, static_cast<const void*>(&two_words_val), sizeof(T)); | ||||
|     return true; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| // Flag callback auxiliary structs.
 | ||||
| 
 | ||||
| // Signature for the mutation callback used by watched Flags
 | ||||
| // The callback is noexcept.
 | ||||
| // TODO(rogeeff): add noexcept after C++17 support is added.
 | ||||
| using FlagCallbackFunc = void (*)(); | ||||
| 
 | ||||
| struct FlagCallback { | ||||
|   FlagCallbackFunc func; | ||||
|   absl::Mutex guard;  // Guard for concurrent callback invocations.
 | ||||
| }; | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| // Flag implementation, which does not depend on flag value type.
 | ||||
| // The class encapsulates the Flag's data and access to it.
 | ||||
| 
 | ||||
| struct DynValueDeleter { | ||||
|   explicit DynValueDeleter(FlagOpFn op_arg = nullptr); | ||||
|   void operator()(void* ptr) const; | ||||
| 
 | ||||
|   FlagOpFn op; | ||||
| }; | ||||
| 
 | ||||
| class FlagState; | ||||
| 
 | ||||
| class FlagImpl final : public flags_internal::CommandLineFlag { | ||||
|  public: | ||||
|   constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op, | ||||
|                      FlagHelpArg help, FlagValueStorageKind value_kind, | ||||
|                      FlagDefaultArg default_arg) | ||||
|       : name_(name), | ||||
|         filename_(filename), | ||||
|         op_(op), | ||||
|         help_(help.source), | ||||
|         help_source_kind_(static_cast<uint8_t>(help.kind)), | ||||
|         value_storage_kind_(static_cast<uint8_t>(value_kind)), | ||||
|         def_kind_(static_cast<uint8_t>(default_arg.kind)), | ||||
|         modified_(false), | ||||
|         on_command_line_(false), | ||||
|         counter_(0), | ||||
|         callback_(nullptr), | ||||
|         default_value_(default_arg.source), | ||||
|         data_guard_{} {} | ||||
| 
 | ||||
|   // Constant access methods
 | ||||
|   void Read(void* dst) const override ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||
| 
 | ||||
|   // Mutating access methods
 | ||||
|   void Write(const void* src) ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||
| 
 | ||||
|   // Interfaces to operate on callbacks.
 | ||||
|   void SetCallback(const FlagCallbackFunc mutation_callback) | ||||
|       ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||
|   void InvokeCallback() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); | ||||
| 
 | ||||
|   // Used in read/write operations to validate source/target has correct type.
 | ||||
|   // For example if flag is declared as absl::Flag<int> FLAGS_foo, a call to
 | ||||
|   // absl::GetFlag(FLAGS_foo) validates that the type of FLAGS_foo is indeed
 | ||||
|   // int. To do that we pass the "assumed" type id (which is deduced from type
 | ||||
|   // int) as an argument `type_id`, which is in turn is validated against the
 | ||||
|   // type id stored in flag object by flag definition statement.
 | ||||
|   void AssertValidType(FlagFastTypeId type_id, | ||||
|                        const std::type_info* (*gen_rtti)()) const; | ||||
| 
 | ||||
|  private: | ||||
|   template <typename T> | ||||
|   friend class Flag; | ||||
|   friend class FlagState; | ||||
| 
 | ||||
|   // Ensures that `data_guard_` is initialized and returns it.
 | ||||
|   absl::Mutex* DataGuard() const ABSL_LOCK_RETURNED((absl::Mutex*)&data_guard_); | ||||
|   // Returns heap allocated value of type T initialized with default value.
 | ||||
|   std::unique_ptr<void, DynValueDeleter> MakeInitValue() const | ||||
|       ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); | ||||
|   // Flag initialization called via absl::call_once.
 | ||||
|   void Init(); | ||||
| 
 | ||||
|   // Offset value access methods. One per storage kind. These methods to not
 | ||||
|   // respect const correctness, so be very carefull using them.
 | ||||
| 
 | ||||
|   // This is a shared helper routine which encapsulates most of the magic. Since
 | ||||
|   // it is only used inside the three routines below, which are defined in
 | ||||
|   // flag.cc, we can define it in that file as well.
 | ||||
|   template <typename StorageT> | ||||
|   StorageT* OffsetValue() const; | ||||
|   // This is an accessor for a value stored in an aligned buffer storage.
 | ||||
|   // Returns a mutable pointer to the start of a buffer.
 | ||||
|   void* AlignedBufferValue() const; | ||||
|   // This is an accessor for a value stored as one word atomic. Returns a
 | ||||
|   // mutable reference to an atomic value.
 | ||||
|   std::atomic<int64_t>& OneWordValue() const; | ||||
|   // This is an accessor for a value stored as two words atomic. Returns a
 | ||||
|   // mutable reference to an atomic value.
 | ||||
|   std::atomic<AlignedTwoWords>& TwoWordsValue() const; | ||||
| 
 | ||||
|   // Attempts to parse supplied `value` string. If parsing is successful,
 | ||||
|   // returns new value. Otherwise returns nullptr.
 | ||||
|   std::unique_ptr<void, DynValueDeleter> TryParse(absl::string_view value, | ||||
|                                                   std::string* err) const | ||||
|       ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); | ||||
|   // Stores the flag value based on the pointer to the source.
 | ||||
|   void StoreValue(const void* src) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); | ||||
| 
 | ||||
|   FlagHelpKind HelpSourceKind() const { | ||||
|     return static_cast<FlagHelpKind>(help_source_kind_); | ||||
|   } | ||||
|   FlagValueStorageKind ValueStorageKind() const { | ||||
|     return static_cast<FlagValueStorageKind>(value_storage_kind_); | ||||
|   } | ||||
|   FlagDefaultKind DefaultKind() const | ||||
|       ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()) { | ||||
|     return static_cast<FlagDefaultKind>(def_kind_); | ||||
|   } | ||||
| 
 | ||||
|   // CommandLineFlag interface implementation
 | ||||
|   absl::string_view Name() const override; | ||||
|   std::string Filename() const override; | ||||
|   std::string Help() const override; | ||||
|   FlagFastTypeId TypeId() const override; | ||||
|   bool IsSpecifiedOnCommandLine() const override | ||||
|       ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||
|   std::string DefaultValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||
|   std::string CurrentValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||
|   bool ValidateInputValue(absl::string_view value) const override | ||||
|       ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||
|   void CheckDefaultValueParsingRoundtrip() const override | ||||
|       ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||
| 
 | ||||
|   // Interfaces to save and restore flags to/from persistent state.
 | ||||
|   // Returns current flag state or nullptr if flag does not support
 | ||||
|   // saving and restoring a state.
 | ||||
|   std::unique_ptr<FlagStateInterface> SaveState() override | ||||
|       ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||
| 
 | ||||
|   // Restores the flag state to the supplied state object. If there is
 | ||||
|   // nothing to restore returns false. Otherwise returns true.
 | ||||
|   bool RestoreState(const FlagState& flag_state) | ||||
|       ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||
| 
 | ||||
|   bool ParseFrom(absl::string_view value, FlagSettingMode set_mode, | ||||
|                  ValueSource source, std::string* error) override | ||||
|       ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||
| 
 | ||||
|   // Immutable flag's state.
 | ||||
| 
 | ||||
|   // Flags name passed to ABSL_FLAG as second arg.
 | ||||
|   const char* const name_; | ||||
|   // The file name where ABSL_FLAG resides.
 | ||||
|   const char* const filename_; | ||||
|   // Type-specific operations "vtable".
 | ||||
|   const FlagOpFn op_; | ||||
|   // Help message literal or function to generate it.
 | ||||
|   const FlagHelpMsg help_; | ||||
|   // Indicates if help message was supplied as literal or generator func.
 | ||||
|   const uint8_t help_source_kind_ : 1; | ||||
|   // Kind of storage this flag is using for the flag's value.
 | ||||
|   const uint8_t value_storage_kind_ : 2; | ||||
| 
 | ||||
|   uint8_t : 0;  // The bytes containing the const bitfields must not be
 | ||||
|                 // shared with bytes containing the mutable bitfields.
 | ||||
| 
 | ||||
|   // Mutable flag's state (guarded by `data_guard_`).
 | ||||
| 
 | ||||
|   // def_kind_ is not guard by DataGuard() since it is accessed in Init without
 | ||||
|   // locks.
 | ||||
|   uint8_t def_kind_ : 2; | ||||
|   // Has this flag's value been modified?
 | ||||
|   bool modified_ : 1 ABSL_GUARDED_BY(*DataGuard()); | ||||
|   // Has this flag been specified on command line.
 | ||||
|   bool on_command_line_ : 1 ABSL_GUARDED_BY(*DataGuard()); | ||||
| 
 | ||||
|   // Unique tag for absl::call_once call to initialize this flag.
 | ||||
|   absl::once_flag init_control_; | ||||
| 
 | ||||
|   // Mutation counter
 | ||||
|   int64_t counter_ ABSL_GUARDED_BY(*DataGuard()); | ||||
|   // Optional flag's callback and absl::Mutex to guard the invocations.
 | ||||
|   FlagCallback* callback_ ABSL_GUARDED_BY(*DataGuard()); | ||||
|   // Either a pointer to the function generating the default value based on the
 | ||||
|   // value specified in ABSL_FLAG or pointer to the dynamically set default
 | ||||
|   // value via SetCommandLineOptionWithMode. def_kind_ is used to distinguish
 | ||||
|   // these two cases.
 | ||||
|   FlagDefaultSrc default_value_; | ||||
| 
 | ||||
|   // This is reserved space for an absl::Mutex to guard flag data. It will be
 | ||||
|   // initialized in FlagImpl::Init via placement new.
 | ||||
|   // We can't use "absl::Mutex data_guard_", since this class is not literal.
 | ||||
|   // We do not want to use "absl::Mutex* data_guard_", since this would require
 | ||||
|   // heap allocation during initialization, which is both slows program startup
 | ||||
|   // and can fail. Using reserved space + placement new allows us to avoid both
 | ||||
|   // problems.
 | ||||
|   alignas(absl::Mutex) mutable char data_guard_[sizeof(absl::Mutex)]; | ||||
| }; | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| // The Flag object parameterized by the flag's value type. This class implements
 | ||||
| // flag reflection handle interface.
 | ||||
| 
 | ||||
| template <typename T> | ||||
| class Flag { | ||||
|  public: | ||||
|   constexpr Flag(const char* name, const char* filename, FlagHelpArg help, | ||||
|                  const FlagDefaultArg default_arg) | ||||
|       : impl_(name, filename, &FlagOps<T>, help, | ||||
|               flags_internal::StorageKind<T>(), default_arg), | ||||
|         value_() {} | ||||
| 
 | ||||
|   // CommandLineFlag interface
 | ||||
|   absl::string_view Name() const { return impl_.Name(); } | ||||
|   std::string Filename() const { return impl_.Filename(); } | ||||
|   std::string Help() const { return impl_.Help(); } | ||||
|   // Do not use. To be removed.
 | ||||
|   bool IsSpecifiedOnCommandLine() const { | ||||
|     return impl_.IsSpecifiedOnCommandLine(); | ||||
|   } | ||||
|   std::string DefaultValue() const { return impl_.DefaultValue(); } | ||||
|   std::string CurrentValue() const { return impl_.CurrentValue(); } | ||||
| 
 | ||||
|  private: | ||||
|   template <typename U, bool do_register> | ||||
|   friend class FlagRegistrar; | ||||
| 
 | ||||
| #if !defined(_MSC_VER) || defined(__clang__) | ||||
|   template <typename U> | ||||
|   friend U absl::GetFlag(const flags_internal::Flag<U>& flag); | ||||
|   template <typename U> | ||||
|   friend void absl::SetFlag(flags_internal::Flag<U>* flag, const U& v); | ||||
|   template <typename U, typename V> | ||||
|   friend void absl::SetFlag(flags_internal::Flag<U>* flag, const V& v); | ||||
| #else | ||||
|   template <typename U> | ||||
|   friend class absl::Flag; | ||||
| #endif | ||||
| 
 | ||||
|   T Get() const { | ||||
|     // See implementation notes in CommandLineFlag::Get().
 | ||||
|     union U { | ||||
|       T value; | ||||
|       U() {} | ||||
|       ~U() { value.~T(); } | ||||
|     }; | ||||
|     U u; | ||||
| 
 | ||||
| #if !defined(NDEBUG) | ||||
|     impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>); | ||||
| #endif | ||||
| 
 | ||||
|     if (!value_.Get(&u.value)) impl_.Read(&u.value); | ||||
|     return std::move(u.value); | ||||
|   } | ||||
|   void Set(const T& v) { | ||||
|     impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>); | ||||
|     impl_.Write(&v); | ||||
|   } | ||||
| 
 | ||||
|   // Flag's data
 | ||||
|   // The implementation depends on value_ field to be placed exactly after the
 | ||||
|   // impl_ field, so that impl_ can figure out the offset to the value and
 | ||||
|   // access it.
 | ||||
|   FlagImpl impl_; | ||||
|   FlagValue<T> value_; | ||||
| }; | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| // Implementation of Flag value specific operations routine.
 | ||||
| template <typename T> | ||||
| void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) { | ||||
|   switch (op) { | ||||
|     case FlagOp::kAlloc: { | ||||
|       std::allocator<T> alloc; | ||||
|       return std::allocator_traits<std::allocator<T>>::allocate(alloc, 1); | ||||
|     } | ||||
|     case FlagOp::kDelete: { | ||||
|       T* p = static_cast<T*>(v2); | ||||
|       p->~T(); | ||||
|       std::allocator<T> alloc; | ||||
|       std::allocator_traits<std::allocator<T>>::deallocate(alloc, p, 1); | ||||
|       return nullptr; | ||||
|     } | ||||
|     case FlagOp::kCopy: | ||||
|       *static_cast<T*>(v2) = *static_cast<const T*>(v1); | ||||
|       return nullptr; | ||||
|     case FlagOp::kCopyConstruct: | ||||
|       new (v2) T(*static_cast<const T*>(v1)); | ||||
|       return nullptr; | ||||
|     case FlagOp::kSizeof: | ||||
|       return reinterpret_cast<void*>(static_cast<uintptr_t>(sizeof(T))); | ||||
|     case FlagOp::kFastTypeId: | ||||
|       return const_cast<void*>(base_internal::FastTypeId<T>()); | ||||
|     case FlagOp::kRuntimeTypeId: | ||||
|       return const_cast<std::type_info*>(GenRuntimeTypeId<T>()); | ||||
|     case FlagOp::kParse: { | ||||
|       // Initialize the temporary instance of type T based on current value in
 | ||||
|       // destination (which is going to be flag's default value).
 | ||||
|       T temp(*static_cast<T*>(v2)); | ||||
|       if (!absl::ParseFlag<T>(*static_cast<const absl::string_view*>(v1), &temp, | ||||
|                               static_cast<std::string*>(v3))) { | ||||
|         return nullptr; | ||||
|       } | ||||
|       *static_cast<T*>(v2) = std::move(temp); | ||||
|       return v2; | ||||
|     } | ||||
|     case FlagOp::kUnparse: | ||||
|       *static_cast<std::string*>(v2) = | ||||
|           absl::UnparseFlag<T>(*static_cast<const T*>(v1)); | ||||
|       return nullptr; | ||||
|     case FlagOp::kValueOffset: { | ||||
|       // Round sizeof(FlagImp) to a multiple of alignof(FlagValue<T>) to get the
 | ||||
|       // offset of the data.
 | ||||
|       ptrdiff_t round_to = alignof(FlagValue<T>); | ||||
|       ptrdiff_t offset = | ||||
|           (sizeof(FlagImpl) + round_to - 1) / round_to * round_to; | ||||
|       return reinterpret_cast<void*>(offset); | ||||
|     } | ||||
|   } | ||||
|   return nullptr; | ||||
| } | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| // This class facilitates Flag object registration and tail expression-based
 | ||||
| // flag definition, for example:
 | ||||
| // ABSL_FLAG(int, foo, 42, "Foo help").OnUpdate(NotifyFooWatcher);
 | ||||
| struct FlagRegistrarEmpty {}; | ||||
| template <typename T, bool do_register> | ||||
| class FlagRegistrar { | ||||
|  public: | ||||
|   explicit FlagRegistrar(Flag<T>* flag) : flag_(flag) { | ||||
|     if (do_register) flags_internal::RegisterCommandLineFlag(&flag_->impl_); | ||||
|   } | ||||
| 
 | ||||
|   FlagRegistrar OnUpdate(FlagCallbackFunc cb) && { | ||||
|     flag_->impl_.SetCallback(cb); | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   // Make the registrar "die" gracefully as an empty struct on a line where
 | ||||
|   // registration happens. Registrar objects are intended to live only as
 | ||||
|   // temporary.
 | ||||
|   operator FlagRegistrarEmpty() const { return {}; }  // NOLINT
 | ||||
| 
 | ||||
|  private: | ||||
|   Flag<T>* flag_;  // Flag being registered (not owned).
 | ||||
| }; | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_INTERNAL_FLAG_H_
 | ||||
							
								
								
									
										58
									
								
								third_party/abseil_cpp/absl/flags/internal/parse.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								third_party/abseil_cpp/absl/flags/internal/parse.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | |||
| //
 | ||||
| // Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_INTERNAL_PARSE_H_ | ||||
| #define ABSL_FLAGS_INTERNAL_PARSE_H_ | ||||
| 
 | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/flags/declare.h" | ||||
| 
 | ||||
| ABSL_DECLARE_FLAG(std::vector<std::string>, flagfile); | ||||
| ABSL_DECLARE_FLAG(std::vector<std::string>, fromenv); | ||||
| ABSL_DECLARE_FLAG(std::vector<std::string>, tryfromenv); | ||||
| ABSL_DECLARE_FLAG(std::vector<std::string>, undefok); | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| enum class ArgvListAction { kRemoveParsedArgs, kKeepParsedArgs }; | ||||
| enum class UsageFlagsAction { kHandleUsage, kIgnoreUsage }; | ||||
| enum class OnUndefinedFlag { | ||||
|   kIgnoreUndefined, | ||||
|   kReportUndefined, | ||||
|   kAbortIfUndefined | ||||
| }; | ||||
| 
 | ||||
| std::vector<char*> ParseCommandLineImpl(int argc, char* argv[], | ||||
|                                         ArgvListAction arg_list_act, | ||||
|                                         UsageFlagsAction usage_flag_act, | ||||
|                                         OnUndefinedFlag on_undef_flag); | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Inspect original command line
 | ||||
| 
 | ||||
| // Returns true if flag with specified name was either present on the original
 | ||||
| // command line or specified in flag file present on the original command line.
 | ||||
| bool WasPresentOnCommandLine(absl::string_view flag_name); | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_INTERNAL_PARSE_H_
 | ||||
							
								
								
									
										63
									
								
								third_party/abseil_cpp/absl/flags/internal/path_util.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								third_party/abseil_cpp/absl/flags/internal/path_util.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_INTERNAL_PATH_UTIL_H_ | ||||
| #define ABSL_FLAGS_INTERNAL_PATH_UTIL_H_ | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/strings/match.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| // A portable interface that returns the basename of the filename passed as an
 | ||||
| // argument. It is similar to basename(3)
 | ||||
| // <https://linux.die.net/man/3/basename>.
 | ||||
| // For example:
 | ||||
| //     flags_internal::Basename("a/b/prog/file.cc")
 | ||||
| // returns "file.cc"
 | ||||
| //     flags_internal::Basename("file.cc")
 | ||||
| // returns "file.cc"
 | ||||
| inline absl::string_view Basename(absl::string_view filename) { | ||||
|   auto last_slash_pos = filename.find_last_of("/\\"); | ||||
| 
 | ||||
|   return last_slash_pos == absl::string_view::npos | ||||
|              ? filename | ||||
|              : filename.substr(last_slash_pos + 1); | ||||
| } | ||||
| 
 | ||||
| // A portable interface that returns the directory name of the filename
 | ||||
| // passed as an argument, including the trailing slash.
 | ||||
| // Returns the empty string if a slash is not found in the input file name.
 | ||||
| // For example:
 | ||||
| //      flags_internal::Package("a/b/prog/file.cc")
 | ||||
| // returns "a/b/prog/"
 | ||||
| //      flags_internal::Package("file.cc")
 | ||||
| // returns ""
 | ||||
| inline absl::string_view Package(absl::string_view filename) { | ||||
|   auto last_slash_pos = filename.find_last_of("/\\"); | ||||
| 
 | ||||
|   return last_slash_pos == absl::string_view::npos | ||||
|              ? absl::string_view() | ||||
|              : filename.substr(0, last_slash_pos + 1); | ||||
| } | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
 | ||||
							
								
								
									
										46
									
								
								third_party/abseil_cpp/absl/flags/internal/path_util_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								third_party/abseil_cpp/absl/flags/internal/path_util_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/internal/path_util.h" | ||||
| 
 | ||||
| #include "gtest/gtest.h" | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| namespace flags = absl::flags_internal; | ||||
| 
 | ||||
| TEST(FlagsPathUtilTest, TestBasename) { | ||||
|   EXPECT_EQ(flags::Basename(""), ""); | ||||
|   EXPECT_EQ(flags::Basename("a.cc"), "a.cc"); | ||||
|   EXPECT_EQ(flags::Basename("dir/a.cc"), "a.cc"); | ||||
|   EXPECT_EQ(flags::Basename("dir1/dir2/a.cc"), "a.cc"); | ||||
|   EXPECT_EQ(flags::Basename("../dir1/dir2/a.cc"), "a.cc"); | ||||
|   EXPECT_EQ(flags::Basename("/dir1/dir2/a.cc"), "a.cc"); | ||||
|   EXPECT_EQ(flags::Basename("/dir1/dir2/../dir3/a.cc"), "a.cc"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(FlagsPathUtilTest, TestPackage) { | ||||
|   EXPECT_EQ(flags::Package(""), ""); | ||||
|   EXPECT_EQ(flags::Package("a.cc"), ""); | ||||
|   EXPECT_EQ(flags::Package("dir/a.cc"), "dir/"); | ||||
|   EXPECT_EQ(flags::Package("dir1/dir2/a.cc"), "dir1/dir2/"); | ||||
|   EXPECT_EQ(flags::Package("../dir1/dir2/a.cc"), "../dir1/dir2/"); | ||||
|   EXPECT_EQ(flags::Package("/dir1/dir2/a.cc"), "/dir1/dir2/"); | ||||
|   EXPECT_EQ(flags::Package("/dir1/dir2/../dir3/a.cc"), "/dir1/dir2/../dir3/"); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
							
								
								
									
										57
									
								
								third_party/abseil_cpp/absl/flags/internal/private_handle_accessor.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								third_party/abseil_cpp/absl/flags/internal/private_handle_accessor.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,57 @@ | |||
| //
 | ||||
| // Copyright 2020 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/internal/private_handle_accessor.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| FlagFastTypeId PrivateHandleAccessor::TypeId(const CommandLineFlag& flag) { | ||||
|   return flag.TypeId(); | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<FlagStateInterface> PrivateHandleAccessor::SaveState( | ||||
|     CommandLineFlag* flag) { | ||||
|   return flag->SaveState(); | ||||
| } | ||||
| 
 | ||||
| bool PrivateHandleAccessor::IsSpecifiedOnCommandLine( | ||||
|     const CommandLineFlag& flag) { | ||||
|   return flag.IsSpecifiedOnCommandLine(); | ||||
| } | ||||
| 
 | ||||
| bool PrivateHandleAccessor::ValidateInputValue(const CommandLineFlag& flag, | ||||
|                                                absl::string_view value) { | ||||
|   return flag.ValidateInputValue(value); | ||||
| } | ||||
| 
 | ||||
| void PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip( | ||||
|     const CommandLineFlag& flag) { | ||||
|   flag.CheckDefaultValueParsingRoundtrip(); | ||||
| } | ||||
| 
 | ||||
| bool PrivateHandleAccessor::ParseFrom(CommandLineFlag* flag, | ||||
|                                       absl::string_view value, | ||||
|                                       flags_internal::FlagSettingMode set_mode, | ||||
|                                       flags_internal::ValueSource source, | ||||
|                                       std::string* error) { | ||||
|   return flag->ParseFrom(value, set_mode, source, error); | ||||
| } | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
							
								
								
									
										55
									
								
								third_party/abseil_cpp/absl/flags/internal/private_handle_accessor.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								third_party/abseil_cpp/absl/flags/internal/private_handle_accessor.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | |||
| //
 | ||||
| // Copyright 2020 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_ | ||||
| #define ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_ | ||||
| 
 | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| // This class serves as a trampoline to access private methods of
 | ||||
| // CommandLineFlag. This class is intended for use exclusively internally inside
 | ||||
| // of the Abseil Flags implementation.
 | ||||
| class PrivateHandleAccessor { | ||||
|  public: | ||||
|   // Access to CommandLineFlag::TypeId.
 | ||||
|   static FlagFastTypeId TypeId(const CommandLineFlag& flag); | ||||
| 
 | ||||
|   // Access to CommandLineFlag::SaveState.
 | ||||
|   static std::unique_ptr<FlagStateInterface> SaveState(CommandLineFlag* flag); | ||||
| 
 | ||||
|   // Access to CommandLineFlag::IsSpecifiedOnCommandLine.
 | ||||
|   static bool IsSpecifiedOnCommandLine(const CommandLineFlag& flag); | ||||
| 
 | ||||
|   // Access to CommandLineFlag::ValidateInputValue.
 | ||||
|   static bool ValidateInputValue(const CommandLineFlag& flag, | ||||
|                                  absl::string_view value); | ||||
| 
 | ||||
|   // Access to CommandLineFlag::CheckDefaultValueParsingRoundtrip.
 | ||||
|   static void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag); | ||||
| 
 | ||||
|   static bool ParseFrom(CommandLineFlag* flag, absl::string_view value, | ||||
|                         flags_internal::FlagSettingMode set_mode, | ||||
|                         flags_internal::ValueSource source, std::string* error); | ||||
| }; | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
 | ||||
							
								
								
									
										60
									
								
								third_party/abseil_cpp/absl/flags/internal/program_name.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								third_party/abseil_cpp/absl/flags/internal/program_name.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/internal/program_name.h" | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| #include "absl/base/attributes.h" | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/base/const_init.h" | ||||
| #include "absl/base/thread_annotations.h" | ||||
| #include "absl/flags/internal/path_util.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| #include "absl/synchronization/mutex.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| ABSL_CONST_INIT static absl::Mutex program_name_guard(absl::kConstInit); | ||||
| ABSL_CONST_INIT static std::string* program_name | ||||
|     ABSL_GUARDED_BY(program_name_guard) = nullptr; | ||||
| 
 | ||||
| std::string ProgramInvocationName() { | ||||
|   absl::MutexLock l(&program_name_guard); | ||||
| 
 | ||||
|   return program_name ? *program_name : "UNKNOWN"; | ||||
| } | ||||
| 
 | ||||
| std::string ShortProgramInvocationName() { | ||||
|   absl::MutexLock l(&program_name_guard); | ||||
| 
 | ||||
|   return program_name ? std::string(flags_internal::Basename(*program_name)) | ||||
|                       : "UNKNOWN"; | ||||
| } | ||||
| 
 | ||||
| void SetProgramInvocationName(absl::string_view prog_name_str) { | ||||
|   absl::MutexLock l(&program_name_guard); | ||||
| 
 | ||||
|   if (!program_name) | ||||
|     program_name = new std::string(prog_name_str); | ||||
|   else | ||||
|     program_name->assign(prog_name_str.data(), prog_name_str.size()); | ||||
| } | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
							
								
								
									
										50
									
								
								third_party/abseil_cpp/absl/flags/internal/program_name.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								third_party/abseil_cpp/absl/flags/internal/program_name.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_ | ||||
| #define ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_ | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Program name
 | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| // Returns program invocation name or "UNKNOWN" if `SetProgramInvocationName()`
 | ||||
| // is never called. At the moment this is always set to argv[0] as part of
 | ||||
| // library initialization.
 | ||||
| std::string ProgramInvocationName(); | ||||
| 
 | ||||
| // Returns base name for program invocation name. For example, if
 | ||||
| //   ProgramInvocationName() == "a/b/mybinary"
 | ||||
| // then
 | ||||
| //   ShortProgramInvocationName() == "mybinary"
 | ||||
| std::string ShortProgramInvocationName(); | ||||
| 
 | ||||
| // Sets program invocation name to a new value. Should only be called once
 | ||||
| // during program initialization, before any threads are spawned.
 | ||||
| void SetProgramInvocationName(absl::string_view prog_name_str); | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_
 | ||||
							
								
								
									
										63
									
								
								third_party/abseil_cpp/absl/flags/internal/program_name_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								third_party/abseil_cpp/absl/flags/internal/program_name_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/internal/program_name.h" | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| #include "gtest/gtest.h" | ||||
| #include "absl/strings/match.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| namespace flags = absl::flags_internal; | ||||
| 
 | ||||
| TEST(FlagsPathUtilTest, TestInitialProgamName) { | ||||
|   flags::SetProgramInvocationName("absl/flags/program_name_test"); | ||||
|   std::string program_name = flags::ProgramInvocationName(); | ||||
|   for (char& c : program_name) | ||||
|     if (c == '\\') c = '/'; | ||||
| 
 | ||||
| #if !defined(__wasm__) && !defined(__asmjs__) | ||||
|   const std::string expect_name = "absl/flags/program_name_test"; | ||||
|   const std::string expect_basename = "program_name_test"; | ||||
| #else | ||||
|   // For targets that generate javascript or webassembly the invocation name
 | ||||
|   // has the special value below.
 | ||||
|   const std::string expect_name = "this.program"; | ||||
|   const std::string expect_basename = "this.program"; | ||||
| #endif | ||||
| 
 | ||||
|   EXPECT_TRUE(absl::EndsWith(program_name, expect_name)) << program_name; | ||||
|   EXPECT_EQ(flags::ShortProgramInvocationName(), expect_basename); | ||||
| } | ||||
| 
 | ||||
| TEST(FlagsPathUtilTest, TestProgamNameInterfaces) { | ||||
|   flags::SetProgramInvocationName("a/my_test"); | ||||
| 
 | ||||
|   EXPECT_EQ(flags::ProgramInvocationName(), "a/my_test"); | ||||
|   EXPECT_EQ(flags::ShortProgramInvocationName(), "my_test"); | ||||
| 
 | ||||
|   absl::string_view not_null_terminated("absl/aaa/bbb"); | ||||
|   not_null_terminated = not_null_terminated.substr(1, 10); | ||||
| 
 | ||||
|   flags::SetProgramInvocationName(not_null_terminated); | ||||
| 
 | ||||
|   EXPECT_EQ(flags::ProgramInvocationName(), "bsl/aaa/bb"); | ||||
|   EXPECT_EQ(flags::ShortProgramInvocationName(), "bb"); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
							
								
								
									
										350
									
								
								third_party/abseil_cpp/absl/flags/internal/registry.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										350
									
								
								third_party/abseil_cpp/absl/flags/internal/registry.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,350 @@ | |||
| //
 | ||||
| // Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/internal/registry.h" | ||||
| 
 | ||||
| #include <assert.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include <functional> | ||||
| #include <map> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <utility> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/base/internal/raw_logging.h" | ||||
| #include "absl/base/thread_annotations.h" | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| #include "absl/flags/internal/private_handle_accessor.h" | ||||
| #include "absl/flags/usage_config.h" | ||||
| #include "absl/strings/str_cat.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| #include "absl/synchronization/mutex.h" | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // FlagRegistry implementation
 | ||||
| //    A FlagRegistry holds all flag objects indexed
 | ||||
| //    by their names so that if you know a flag's name you can access or
 | ||||
| //    set it.
 | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // FlagRegistry
 | ||||
| //    A FlagRegistry singleton object holds all flag objects indexed
 | ||||
| //    by their names so that if you know a flag's name (as a C
 | ||||
| //    string), you can access or set it.  If the function is named
 | ||||
| //    FooLocked(), you must own the registry lock before calling
 | ||||
| //    the function; otherwise, you should *not* hold the lock, and
 | ||||
| //    the function will acquire it itself if needed.
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| class FlagRegistry { | ||||
|  public: | ||||
|   FlagRegistry() = default; | ||||
|   ~FlagRegistry() = default; | ||||
| 
 | ||||
|   // Store a flag in this registry.  Takes ownership of *flag.
 | ||||
|   void RegisterFlag(CommandLineFlag* flag); | ||||
| 
 | ||||
|   void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.Lock(); } | ||||
|   void Unlock() ABSL_UNLOCK_FUNCTION(lock_) { lock_.Unlock(); } | ||||
| 
 | ||||
|   // Returns the flag object for the specified name, or nullptr if not found.
 | ||||
|   // Will emit a warning if a 'retired' flag is specified.
 | ||||
|   CommandLineFlag* FindFlagLocked(absl::string_view name); | ||||
| 
 | ||||
|   // Returns the retired flag object for the specified name, or nullptr if not
 | ||||
|   // found or not retired.  Does not emit a warning.
 | ||||
|   CommandLineFlag* FindRetiredFlagLocked(absl::string_view name); | ||||
| 
 | ||||
|   static FlagRegistry* GlobalRegistry();  // returns a singleton registry
 | ||||
| 
 | ||||
|  private: | ||||
|   friend class FlagSaverImpl;  // reads all the flags in order to copy them
 | ||||
|   friend void ForEachFlagUnlocked( | ||||
|       std::function<void(CommandLineFlag*)> visitor); | ||||
| 
 | ||||
|   // The map from name to flag, for FindFlagLocked().
 | ||||
|   using FlagMap = std::map<absl::string_view, CommandLineFlag*>; | ||||
|   using FlagIterator = FlagMap::iterator; | ||||
|   using FlagConstIterator = FlagMap::const_iterator; | ||||
|   FlagMap flags_; | ||||
| 
 | ||||
|   absl::Mutex lock_; | ||||
| 
 | ||||
|   // Disallow
 | ||||
|   FlagRegistry(const FlagRegistry&); | ||||
|   FlagRegistry& operator=(const FlagRegistry&); | ||||
| }; | ||||
| 
 | ||||
| FlagRegistry* FlagRegistry::GlobalRegistry() { | ||||
|   static FlagRegistry* global_registry = new FlagRegistry; | ||||
|   return global_registry; | ||||
| } | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| class FlagRegistryLock { | ||||
|  public: | ||||
|   explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); } | ||||
|   ~FlagRegistryLock() { fr_->Unlock(); } | ||||
| 
 | ||||
|  private: | ||||
|   FlagRegistry* const fr_; | ||||
| }; | ||||
| 
 | ||||
| void DestroyRetiredFlag(CommandLineFlag* flag); | ||||
| }  // namespace
 | ||||
| 
 | ||||
| void FlagRegistry::RegisterFlag(CommandLineFlag* flag) { | ||||
|   FlagRegistryLock registry_lock(this); | ||||
|   std::pair<FlagIterator, bool> ins = | ||||
|       flags_.insert(FlagMap::value_type(flag->Name(), flag)); | ||||
|   if (ins.second == false) {  // means the name was already in the map
 | ||||
|     CommandLineFlag* old_flag = ins.first->second; | ||||
|     if (flag->IsRetired() != old_flag->IsRetired()) { | ||||
|       // All registrations must agree on the 'retired' flag.
 | ||||
|       flags_internal::ReportUsageError( | ||||
|           absl::StrCat( | ||||
|               "Retired flag '", flag->Name(), | ||||
|               "' was defined normally in file '", | ||||
|               (flag->IsRetired() ? old_flag->Filename() : flag->Filename()), | ||||
|               "'."), | ||||
|           true); | ||||
|     } else if (flags_internal::PrivateHandleAccessor::TypeId(*flag) != | ||||
|                flags_internal::PrivateHandleAccessor::TypeId(*old_flag)) { | ||||
|       flags_internal::ReportUsageError( | ||||
|           absl::StrCat("Flag '", flag->Name(), | ||||
|                        "' was defined more than once but with " | ||||
|                        "differing types. Defined in files '", | ||||
|                        old_flag->Filename(), "' and '", flag->Filename(), "'."), | ||||
|           true); | ||||
|     } else if (old_flag->IsRetired()) { | ||||
|       // Retired flag can just be deleted.
 | ||||
|       DestroyRetiredFlag(flag); | ||||
|       return; | ||||
|     } else if (old_flag->Filename() != flag->Filename()) { | ||||
|       flags_internal::ReportUsageError( | ||||
|           absl::StrCat("Flag '", flag->Name(), | ||||
|                        "' was defined more than once (in files '", | ||||
|                        old_flag->Filename(), "' and '", flag->Filename(), | ||||
|                        "')."), | ||||
|           true); | ||||
|     } else { | ||||
|       flags_internal::ReportUsageError( | ||||
|           absl::StrCat( | ||||
|               "Something wrong with flag '", flag->Name(), "' in file '", | ||||
|               flag->Filename(), "'. One possibility: file '", flag->Filename(), | ||||
|               "' is being linked both statically and dynamically into this " | ||||
|               "executable. e.g. some files listed as srcs to a test and also " | ||||
|               "listed as srcs of some shared lib deps of the same test."), | ||||
|           true); | ||||
|     } | ||||
|     // All cases above are fatal, except for the retired flags.
 | ||||
|     std::exit(1); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) { | ||||
|   FlagConstIterator i = flags_.find(name); | ||||
|   if (i == flags_.end()) { | ||||
|     return nullptr; | ||||
|   } | ||||
| 
 | ||||
|   if (i->second->IsRetired()) { | ||||
|     flags_internal::ReportUsageError( | ||||
|         absl::StrCat("Accessing retired flag '", name, "'"), false); | ||||
|   } | ||||
| 
 | ||||
|   return i->second; | ||||
| } | ||||
| 
 | ||||
| CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) { | ||||
|   FlagConstIterator i = flags_.find(name); | ||||
|   if (i == flags_.end() || !i->second->IsRetired()) { | ||||
|     return nullptr; | ||||
|   } | ||||
| 
 | ||||
|   return i->second; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // FlagSaver
 | ||||
| // FlagSaverImpl
 | ||||
| //    This class stores the states of all flags at construct time,
 | ||||
| //    and restores all flags to that state at destruct time.
 | ||||
| //    Its major implementation challenge is that it never modifies
 | ||||
| //    pointers in the 'main' registry, so global FLAG_* vars always
 | ||||
| //    point to the right place.
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| class FlagSaverImpl { | ||||
|  public: | ||||
|   FlagSaverImpl() = default; | ||||
|   FlagSaverImpl(const FlagSaverImpl&) = delete; | ||||
|   void operator=(const FlagSaverImpl&) = delete; | ||||
| 
 | ||||
|   // Saves the flag states from the flag registry into this object.
 | ||||
|   // It's an error to call this more than once.
 | ||||
|   void SaveFromRegistry() { | ||||
|     assert(backup_registry_.empty());  // call only once!
 | ||||
|     flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) { | ||||
|       if (auto flag_state = | ||||
|               flags_internal::PrivateHandleAccessor::SaveState(flag)) { | ||||
|         backup_registry_.emplace_back(std::move(flag_state)); | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   // Restores the saved flag states into the flag registry.
 | ||||
|   void RestoreToRegistry() { | ||||
|     for (const auto& flag_state : backup_registry_) { | ||||
|       flag_state->Restore(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  private: | ||||
|   std::vector<std::unique_ptr<flags_internal::FlagStateInterface>> | ||||
|       backup_registry_; | ||||
| }; | ||||
| 
 | ||||
| FlagSaver::FlagSaver() : impl_(new FlagSaverImpl) { impl_->SaveFromRegistry(); } | ||||
| 
 | ||||
| void FlagSaver::Ignore() { | ||||
|   delete impl_; | ||||
|   impl_ = nullptr; | ||||
| } | ||||
| 
 | ||||
| FlagSaver::~FlagSaver() { | ||||
|   if (!impl_) return; | ||||
| 
 | ||||
|   impl_->RestoreToRegistry(); | ||||
|   delete impl_; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| CommandLineFlag* FindCommandLineFlag(absl::string_view name) { | ||||
|   if (name.empty()) return nullptr; | ||||
|   FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); | ||||
|   FlagRegistryLock frl(registry); | ||||
| 
 | ||||
|   return registry->FindFlagLocked(name); | ||||
| } | ||||
| 
 | ||||
| CommandLineFlag* FindRetiredFlag(absl::string_view name) { | ||||
|   FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); | ||||
|   FlagRegistryLock frl(registry); | ||||
| 
 | ||||
|   return registry->FindRetiredFlagLocked(name); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor) { | ||||
|   FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); | ||||
|   for (FlagRegistry::FlagConstIterator i = registry->flags_.begin(); | ||||
|        i != registry->flags_.end(); ++i) { | ||||
|     visitor(i->second); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void ForEachFlag(std::function<void(CommandLineFlag*)> visitor) { | ||||
|   FlagRegistry* const registry = FlagRegistry::GlobalRegistry(); | ||||
|   FlagRegistryLock frl(registry); | ||||
|   ForEachFlagUnlocked(visitor); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| bool RegisterCommandLineFlag(CommandLineFlag* flag) { | ||||
|   FlagRegistry::GlobalRegistry()->RegisterFlag(flag); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| class RetiredFlagObj final : public flags_internal::CommandLineFlag { | ||||
|  public: | ||||
|   constexpr RetiredFlagObj(const char* name, FlagFastTypeId type_id) | ||||
|       : name_(name), type_id_(type_id) {} | ||||
| 
 | ||||
|  private: | ||||
|   absl::string_view Name() const override { return name_; } | ||||
|   std::string Filename() const override { return "RETIRED"; } | ||||
|   FlagFastTypeId TypeId() const override { return type_id_; } | ||||
|   std::string Help() const override { return ""; } | ||||
|   bool IsRetired() const override { return true; } | ||||
|   bool IsSpecifiedOnCommandLine() const override { return false; } | ||||
|   std::string DefaultValue() const override { return ""; } | ||||
|   std::string CurrentValue() const override { return ""; } | ||||
| 
 | ||||
|   // Any input is valid
 | ||||
|   bool ValidateInputValue(absl::string_view) const override { return true; } | ||||
| 
 | ||||
|   std::unique_ptr<flags_internal::FlagStateInterface> SaveState() override { | ||||
|     return nullptr; | ||||
|   } | ||||
| 
 | ||||
|   bool ParseFrom(absl::string_view, flags_internal::FlagSettingMode, | ||||
|                  flags_internal::ValueSource, std::string*) override { | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   void CheckDefaultValueParsingRoundtrip() const override {} | ||||
| 
 | ||||
|   void Read(void*) const override {} | ||||
| 
 | ||||
|   // Data members
 | ||||
|   const char* const name_; | ||||
|   const FlagFastTypeId type_id_; | ||||
| }; | ||||
| 
 | ||||
| void DestroyRetiredFlag(flags_internal::CommandLineFlag* flag) { | ||||
|   assert(flag->IsRetired()); | ||||
|   delete static_cast<RetiredFlagObj*>(flag); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| bool Retire(const char* name, FlagFastTypeId type_id) { | ||||
|   auto* flag = new flags_internal::RetiredFlagObj(name, type_id); | ||||
|   FlagRegistry::GlobalRegistry()->RegisterFlag(flag); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| bool IsRetiredFlag(absl::string_view name, bool* type_is_bool) { | ||||
|   assert(!name.empty()); | ||||
|   CommandLineFlag* flag = flags_internal::FindRetiredFlag(name); | ||||
|   if (flag == nullptr) { | ||||
|     return false; | ||||
|   } | ||||
|   assert(type_is_bool); | ||||
|   *type_is_bool = flag->IsOfType<bool>(); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
							
								
								
									
										124
									
								
								third_party/abseil_cpp/absl/flags/internal/registry.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								third_party/abseil_cpp/absl/flags/internal/registry.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,124 @@ | |||
| //
 | ||||
| // Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_INTERNAL_REGISTRY_H_ | ||||
| #define ABSL_FLAGS_INTERNAL_REGISTRY_H_ | ||||
| 
 | ||||
| #include <functional> | ||||
| #include <map> | ||||
| #include <string> | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/base/macros.h" | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Global flags registry API.
 | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| CommandLineFlag* FindCommandLineFlag(absl::string_view name); | ||||
| CommandLineFlag* FindRetiredFlag(absl::string_view name); | ||||
| 
 | ||||
| // Executes specified visitor for each non-retired flag in the registry.
 | ||||
| // Requires the caller hold the registry lock.
 | ||||
| void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor); | ||||
| // Executes specified visitor for each non-retired flag in the registry. While
 | ||||
| // callback are executed, the registry is locked and can't be changed.
 | ||||
| void ForEachFlag(std::function<void(CommandLineFlag*)> visitor); | ||||
| 
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| bool RegisterCommandLineFlag(CommandLineFlag*); | ||||
| 
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| // Retired registrations:
 | ||||
| //
 | ||||
| // Retired flag registrations are treated specially. A 'retired' flag is
 | ||||
| // provided only for compatibility with automated invocations that still
 | ||||
| // name it.  A 'retired' flag:
 | ||||
| //   - is not bound to a C++ FLAGS_ reference.
 | ||||
| //   - has a type and a value, but that value is intentionally inaccessible.
 | ||||
| //   - does not appear in --help messages.
 | ||||
| //   - is fully supported by _all_ flag parsing routines.
 | ||||
| //   - consumes args normally, and complains about type mismatches in its
 | ||||
| //     argument.
 | ||||
| //   - emits a complaint but does not die (e.g. LOG(ERROR)) if it is
 | ||||
| //     accessed by name through the flags API for parsing or otherwise.
 | ||||
| //
 | ||||
| // The registrations for a flag happen in an unspecified order as the
 | ||||
| // initializers for the namespace-scope objects of a program are run.
 | ||||
| // Any number of weak registrations for a flag can weakly define the flag.
 | ||||
| // One non-weak registration will upgrade the flag from weak to non-weak.
 | ||||
| // Further weak registrations of a non-weak flag are ignored.
 | ||||
| //
 | ||||
| // This mechanism is designed to support moving dead flags into a
 | ||||
| // 'graveyard' library.  An example migration:
 | ||||
| //
 | ||||
| //   0: Remove references to this FLAGS_flagname in the C++ codebase.
 | ||||
| //   1: Register as 'retired' in old_lib.
 | ||||
| //   2: Make old_lib depend on graveyard.
 | ||||
| //   3: Add a redundant 'retired' registration to graveyard.
 | ||||
| //   4: Remove the old_lib 'retired' registration.
 | ||||
| //   5: Eventually delete the graveyard registration entirely.
 | ||||
| //
 | ||||
| 
 | ||||
| // Retire flag with name "name" and type indicated by ops.
 | ||||
| bool Retire(const char* name, FlagFastTypeId type_id); | ||||
| 
 | ||||
| // Registered a retired flag with name 'flag_name' and type 'T'.
 | ||||
| template <typename T> | ||||
| inline bool RetiredFlag(const char* flag_name) { | ||||
|   return flags_internal::Retire(flag_name, base_internal::FastTypeId<T>()); | ||||
| } | ||||
| 
 | ||||
| // If the flag is retired, returns true and indicates in |*type_is_bool|
 | ||||
| // whether the type of the retired flag is a bool.
 | ||||
| // Only to be called by code that needs to explicitly ignore retired flags.
 | ||||
| bool IsRetiredFlag(absl::string_view name, bool* type_is_bool); | ||||
| 
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| // Saves the states (value, default value, whether the user has set
 | ||||
| // the flag, registered validators, etc) of all flags, and restores
 | ||||
| // them when the FlagSaver is destroyed.
 | ||||
| //
 | ||||
| // This class is thread-safe.  However, its destructor writes to
 | ||||
| // exactly the set of flags that have changed value during its
 | ||||
| // lifetime, so concurrent _direct_ access to those flags
 | ||||
| // (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe.
 | ||||
| 
 | ||||
| class FlagSaver { | ||||
|  public: | ||||
|   FlagSaver(); | ||||
|   ~FlagSaver(); | ||||
| 
 | ||||
|   FlagSaver(const FlagSaver&) = delete; | ||||
|   void operator=(const FlagSaver&) = delete; | ||||
| 
 | ||||
|   // Prevents saver from restoring the saved state of flags.
 | ||||
|   void Ignore(); | ||||
| 
 | ||||
|  private: | ||||
|   class FlagSaverImpl* impl_;  // we use pimpl here to keep API steady
 | ||||
| }; | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_INTERNAL_REGISTRY_H_
 | ||||
							
								
								
									
										86
									
								
								third_party/abseil_cpp/absl/flags/internal/type_erased.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								third_party/abseil_cpp/absl/flags/internal/type_erased.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,86 @@ | |||
| //
 | ||||
| // Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/internal/type_erased.h" | ||||
| 
 | ||||
| #include <assert.h> | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/base/internal/raw_logging.h" | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| #include "absl/flags/internal/private_handle_accessor.h" | ||||
| #include "absl/flags/internal/registry.h" | ||||
| #include "absl/flags/usage_config.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| bool GetCommandLineOption(absl::string_view name, std::string* value) { | ||||
|   if (name.empty()) return false; | ||||
|   assert(value); | ||||
| 
 | ||||
|   CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name); | ||||
|   if (flag == nullptr || flag->IsRetired()) { | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   *value = flag->CurrentValue(); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool SetCommandLineOption(absl::string_view name, absl::string_view value) { | ||||
|   return SetCommandLineOptionWithMode(name, value, | ||||
|                                       flags_internal::SET_FLAGS_VALUE); | ||||
| } | ||||
| 
 | ||||
| bool SetCommandLineOptionWithMode(absl::string_view name, | ||||
|                                   absl::string_view value, | ||||
|                                   FlagSettingMode set_mode) { | ||||
|   CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name); | ||||
| 
 | ||||
|   if (!flag || flag->IsRetired()) return false; | ||||
| 
 | ||||
|   std::string error; | ||||
|   if (!flags_internal::PrivateHandleAccessor::ParseFrom( | ||||
|           flag, value, set_mode, kProgrammaticChange, &error)) { | ||||
|     // Errors here are all of the form: the provided name was a recognized
 | ||||
|     // flag, but the value was invalid (bad type, or validation failed).
 | ||||
|     flags_internal::ReportUsageError(error, false); | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| bool IsValidFlagValue(absl::string_view name, absl::string_view value) { | ||||
|   CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name); | ||||
| 
 | ||||
|   return flag != nullptr && | ||||
|          (flag->IsRetired() || | ||||
|           flags_internal::PrivateHandleAccessor::ValidateInputValue(*flag, | ||||
|                                                                     value)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
							
								
								
									
										79
									
								
								third_party/abseil_cpp/absl/flags/internal/type_erased.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								third_party/abseil_cpp/absl/flags/internal/type_erased.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,79 @@ | |||
| //
 | ||||
| // Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_ | ||||
| #define ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_ | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| #include "absl/flags/internal/registry.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Registry interfaces operating on type erased handles.
 | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| // If a flag named "name" exists, store its current value in *OUTPUT
 | ||||
| // and return true.  Else return false without changing *OUTPUT.
 | ||||
| // Thread-safe.
 | ||||
| bool GetCommandLineOption(absl::string_view name, std::string* value); | ||||
| 
 | ||||
| // Set the value of the flag named "name" to value.  If successful,
 | ||||
| // returns true.  If not successful (e.g., the flag was not found or
 | ||||
| // the value is not a valid value), returns false.
 | ||||
| // Thread-safe.
 | ||||
| bool SetCommandLineOption(absl::string_view name, absl::string_view value); | ||||
| 
 | ||||
| bool SetCommandLineOptionWithMode(absl::string_view name, | ||||
|                                   absl::string_view value, | ||||
|                                   FlagSettingMode set_mode); | ||||
| 
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| // Returns true iff all of the following conditions are true:
 | ||||
| // (a) "name" names a registered flag
 | ||||
| // (b) "value" can be parsed succesfully according to the type of the flag
 | ||||
| // (c) parsed value passes any validator associated with the flag
 | ||||
| bool IsValidFlagValue(absl::string_view name, absl::string_view value); | ||||
| 
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| // If a flag with specified "name" exists and has type T, store
 | ||||
| // its current value in *dst and return true.  Else return false
 | ||||
| // without touching *dst.  T must obey all of the requirements for
 | ||||
| // types passed to DEFINE_FLAG.
 | ||||
| template <typename T> | ||||
| inline bool GetByName(absl::string_view name, T* dst) { | ||||
|   CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name); | ||||
|   if (!flag) return false; | ||||
| 
 | ||||
|   if (auto val = flag->TryGet<T>()) { | ||||
|     *dst = *val; | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
 | ||||
							
								
								
									
										157
									
								
								third_party/abseil_cpp/absl/flags/internal/type_erased_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								third_party/abseil_cpp/absl/flags/internal/type_erased_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,157 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/internal/type_erased.h" | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <string> | ||||
| 
 | ||||
| #include "gtest/gtest.h" | ||||
| #include "absl/flags/flag.h" | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| #include "absl/flags/internal/registry.h" | ||||
| #include "absl/flags/marshalling.h" | ||||
| #include "absl/memory/memory.h" | ||||
| 
 | ||||
| ABSL_FLAG(int, int_flag, 1, "int_flag help"); | ||||
| ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help"); | ||||
| ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help"); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| namespace flags = absl::flags_internal; | ||||
| 
 | ||||
| class TypeErasedTest : public testing::Test { | ||||
|  protected: | ||||
|   void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); } | ||||
|   void TearDown() override { flag_saver_.reset(); } | ||||
| 
 | ||||
|  private: | ||||
|   std::unique_ptr<flags::FlagSaver> flag_saver_; | ||||
| }; | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(TypeErasedTest, TestGetCommandLineOption) { | ||||
|   std::string value; | ||||
|   EXPECT_TRUE(flags::GetCommandLineOption("int_flag", &value)); | ||||
|   EXPECT_EQ(value, "1"); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::GetCommandLineOption("string_flag", &value)); | ||||
|   EXPECT_EQ(value, "dflt"); | ||||
| 
 | ||||
|   EXPECT_FALSE(flags::GetCommandLineOption("bool_retired_flag", &value)); | ||||
| 
 | ||||
|   EXPECT_FALSE(flags::GetCommandLineOption("unknown_flag", &value)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(TypeErasedTest, TestSetCommandLineOption) { | ||||
|   EXPECT_TRUE(flags::SetCommandLineOption("int_flag", "101")); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::SetCommandLineOption("string_flag", "asdfgh")); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh"); | ||||
| 
 | ||||
|   EXPECT_FALSE(flags::SetCommandLineOption("bool_retired_flag", "true")); | ||||
| 
 | ||||
|   EXPECT_FALSE(flags::SetCommandLineOption("unknown_flag", "true")); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAGS_VALUE) { | ||||
|   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101", | ||||
|                                                   flags::SET_FLAGS_VALUE)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh", | ||||
|                                                   flags::SET_FLAGS_VALUE)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh"); | ||||
| 
 | ||||
|   EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true", | ||||
|                                                    flags::SET_FLAGS_VALUE)); | ||||
| 
 | ||||
|   EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true", | ||||
|                                                    flags::SET_FLAGS_VALUE)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAG_IF_DEFAULT) { | ||||
|   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101", | ||||
|                                                   flags::SET_FLAG_IF_DEFAULT)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101); | ||||
| 
 | ||||
|   // This semantic is broken. We return true instead of false. Value is not
 | ||||
|   // updated.
 | ||||
|   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "202", | ||||
|                                                   flags::SET_FLAG_IF_DEFAULT)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh", | ||||
|                                                   flags::SET_FLAG_IF_DEFAULT)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh"); | ||||
| 
 | ||||
|   EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true", | ||||
|                                                    flags::SET_FLAG_IF_DEFAULT)); | ||||
| 
 | ||||
|   EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true", | ||||
|                                                    flags::SET_FLAG_IF_DEFAULT)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAGS_DEFAULT) { | ||||
|   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101", | ||||
|                                                   flags::SET_FLAGS_DEFAULT)); | ||||
| 
 | ||||
|   // Set it again to ensure that resetting logic is covered.
 | ||||
|   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "102", | ||||
|                                                   flags::SET_FLAGS_DEFAULT)); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "103", | ||||
|                                                   flags::SET_FLAGS_DEFAULT)); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh", | ||||
|                                                   flags::SET_FLAGS_DEFAULT)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh"); | ||||
| 
 | ||||
|   EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true", | ||||
|                                                    flags::SET_FLAGS_DEFAULT)); | ||||
| 
 | ||||
|   EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true", | ||||
|                                                    flags::SET_FLAGS_DEFAULT)); | ||||
| 
 | ||||
|   // This should be successfull, since flag is still is not set
 | ||||
|   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "202", | ||||
|                                                   flags::SET_FLAG_IF_DEFAULT)); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 202); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(TypeErasedTest, TestIsValidFlagValue) { | ||||
|   EXPECT_TRUE(flags::IsValidFlagValue("int_flag", "57")); | ||||
|   EXPECT_TRUE(flags::IsValidFlagValue("int_flag", "-101")); | ||||
|   EXPECT_FALSE(flags::IsValidFlagValue("int_flag", "1.1")); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::IsValidFlagValue("string_flag", "#%^#%^$%DGHDG$W%adsf")); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::IsValidFlagValue("bool_retired_flag", "true")); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
							
								
								
									
										392
									
								
								third_party/abseil_cpp/absl/flags/internal/usage.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										392
									
								
								third_party/abseil_cpp/absl/flags/internal/usage.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,392 @@ | |||
| //
 | ||||
| // Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/internal/usage.h" | ||||
| 
 | ||||
| #include <functional> | ||||
| #include <map> | ||||
| #include <ostream> | ||||
| #include <string> | ||||
| #include <utility> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/flags/flag.h" | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| #include "absl/flags/internal/flag.h" | ||||
| #include "absl/flags/internal/path_util.h" | ||||
| #include "absl/flags/internal/private_handle_accessor.h" | ||||
| #include "absl/flags/internal/program_name.h" | ||||
| #include "absl/flags/internal/registry.h" | ||||
| #include "absl/flags/usage_config.h" | ||||
| #include "absl/strings/str_cat.h" | ||||
| #include "absl/strings/str_split.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| ABSL_FLAG(bool, help, false, | ||||
|           "show help on important flags for this binary [tip: all flags can " | ||||
|           "have two dashes]"); | ||||
| ABSL_FLAG(bool, helpfull, false, "show help on all flags"); | ||||
| ABSL_FLAG(bool, helpshort, false, | ||||
|           "show help on only the main module for this program"); | ||||
| ABSL_FLAG(bool, helppackage, false, | ||||
|           "show help on all modules in the main package"); | ||||
| ABSL_FLAG(bool, version, false, "show version and build info and exit"); | ||||
| ABSL_FLAG(bool, only_check_args, false, "exit after checking all flags"); | ||||
| ABSL_FLAG(std::string, helpon, "", | ||||
|           "show help on the modules named by this flag value"); | ||||
| ABSL_FLAG(std::string, helpmatch, "", | ||||
|           "show help on modules whose name contains the specified substr"); | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| namespace { | ||||
| 
 | ||||
| // This class is used to emit an XML element with `tag` and `text`.
 | ||||
| // It adds opening and closing tags and escapes special characters in the text.
 | ||||
| // For example:
 | ||||
| // std::cout << XMLElement("title", "Milk & Cookies");
 | ||||
| // prints "<title>Milk & Cookies</title>"
 | ||||
| class XMLElement { | ||||
|  public: | ||||
|   XMLElement(absl::string_view tag, absl::string_view txt) | ||||
|       : tag_(tag), txt_(txt) {} | ||||
| 
 | ||||
|   friend std::ostream& operator<<(std::ostream& out, | ||||
|                                   const XMLElement& xml_elem) { | ||||
|     out << "<" << xml_elem.tag_ << ">"; | ||||
| 
 | ||||
|     for (auto c : xml_elem.txt_) { | ||||
|       switch (c) { | ||||
|         case '"': | ||||
|           out << """; | ||||
|           break; | ||||
|         case '\'': | ||||
|           out << "'"; | ||||
|           break; | ||||
|         case '&': | ||||
|           out << "&"; | ||||
|           break; | ||||
|         case '<': | ||||
|           out << "<"; | ||||
|           break; | ||||
|         case '>': | ||||
|           out << ">"; | ||||
|           break; | ||||
|         default: | ||||
|           out << c; | ||||
|           break; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     return out << "</" << xml_elem.tag_ << ">"; | ||||
|   } | ||||
| 
 | ||||
|  private: | ||||
|   absl::string_view tag_; | ||||
|   absl::string_view txt_; | ||||
| }; | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Helper class to pretty-print info about a flag.
 | ||||
| 
 | ||||
| class FlagHelpPrettyPrinter { | ||||
|  public: | ||||
|   // Pretty printer holds on to the std::ostream& reference to direct an output
 | ||||
|   // to that stream.
 | ||||
|   FlagHelpPrettyPrinter(int max_line_len, std::ostream* out) | ||||
|       : out_(*out), | ||||
|         max_line_len_(max_line_len), | ||||
|         line_len_(0), | ||||
|         first_line_(true) {} | ||||
| 
 | ||||
|   void Write(absl::string_view str, bool wrap_line = false) { | ||||
|     // Empty string - do nothing.
 | ||||
|     if (str.empty()) return; | ||||
| 
 | ||||
|     std::vector<absl::string_view> tokens; | ||||
|     if (wrap_line) { | ||||
|       for (auto line : absl::StrSplit(str, absl::ByAnyChar("\n\r"))) { | ||||
|         if (!tokens.empty()) { | ||||
|           // Keep line separators in the input string.
 | ||||
|           tokens.push_back("\n"); | ||||
|         } | ||||
|         for (auto token : | ||||
|              absl::StrSplit(line, absl::ByAnyChar(" \t"), absl::SkipEmpty())) { | ||||
|           tokens.push_back(token); | ||||
|         } | ||||
|       } | ||||
|     } else { | ||||
|       tokens.push_back(str); | ||||
|     } | ||||
| 
 | ||||
|     for (auto token : tokens) { | ||||
|       bool new_line = (line_len_ == 0); | ||||
| 
 | ||||
|       // Respect line separators in the input string.
 | ||||
|       if (token == "\n") { | ||||
|         EndLine(); | ||||
|         continue; | ||||
|       } | ||||
| 
 | ||||
|       // Write the token, ending the string first if necessary/possible.
 | ||||
|       if (!new_line && (line_len_ + token.size() >= max_line_len_)) { | ||||
|         EndLine(); | ||||
|         new_line = true; | ||||
|       } | ||||
| 
 | ||||
|       if (new_line) { | ||||
|         StartLine(); | ||||
|       } else { | ||||
|         out_ << ' '; | ||||
|         ++line_len_; | ||||
|       } | ||||
| 
 | ||||
|       out_ << token; | ||||
|       line_len_ += token.size(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   void StartLine() { | ||||
|     if (first_line_) { | ||||
|       out_ << "    "; | ||||
|       line_len_ = 4; | ||||
|       first_line_ = false; | ||||
|     } else { | ||||
|       out_ << "      "; | ||||
|       line_len_ = 6; | ||||
|     } | ||||
|   } | ||||
|   void EndLine() { | ||||
|     out_ << '\n'; | ||||
|     line_len_ = 0; | ||||
|   } | ||||
| 
 | ||||
|  private: | ||||
|   std::ostream& out_; | ||||
|   const int max_line_len_; | ||||
|   int line_len_; | ||||
|   bool first_line_; | ||||
| }; | ||||
| 
 | ||||
| void FlagHelpHumanReadable(const flags_internal::CommandLineFlag& flag, | ||||
|                            std::ostream* out) { | ||||
|   FlagHelpPrettyPrinter printer(80, out);  // Max line length is 80.
 | ||||
| 
 | ||||
|   // Flag name.
 | ||||
|   printer.Write(absl::StrCat("--", flag.Name())); | ||||
| 
 | ||||
|   // Flag help.
 | ||||
|   printer.Write(absl::StrCat("(", flag.Help(), ");"), /*wrap_line=*/true); | ||||
| 
 | ||||
|   // The listed default value will be the actual default from the flag
 | ||||
|   // definition in the originating source file, unless the value has
 | ||||
|   // subsequently been modified using SetCommandLineOption() with mode
 | ||||
|   // SET_FLAGS_DEFAULT.
 | ||||
|   std::string dflt_val = flag.DefaultValue(); | ||||
|   std::string curr_val = flag.CurrentValue(); | ||||
|   bool is_modified = curr_val != dflt_val; | ||||
| 
 | ||||
|   if (flag.IsOfType<std::string>()) { | ||||
|     dflt_val = absl::StrCat("\"", dflt_val, "\""); | ||||
|   } | ||||
|   printer.Write(absl::StrCat("default: ", dflt_val, ";")); | ||||
| 
 | ||||
|   if (is_modified) { | ||||
|     if (flag.IsOfType<std::string>()) { | ||||
|       curr_val = absl::StrCat("\"", curr_val, "\""); | ||||
|     } | ||||
|     printer.Write(absl::StrCat("currently: ", curr_val, ";")); | ||||
|   } | ||||
| 
 | ||||
|   printer.EndLine(); | ||||
| } | ||||
| 
 | ||||
| // Shows help for every filename which matches any of the filters
 | ||||
| // If filters are empty, shows help for every file.
 | ||||
| // If a flag's help message has been stripped (e.g. by adding '#define
 | ||||
| // STRIP_FLAG_HELP 1' then this flag will not be displayed by '--help'
 | ||||
| // and its variants.
 | ||||
| void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb, | ||||
|                    HelpFormat format, absl::string_view program_usage_message) { | ||||
|   if (format == HelpFormat::kHumanReadable) { | ||||
|     out << flags_internal::ShortProgramInvocationName() << ": " | ||||
|         << program_usage_message << "\n\n"; | ||||
|   } else { | ||||
|     // XML schema is not a part of our public API for now.
 | ||||
|     out << "<?xml version=\"1.0\"?>\n" | ||||
|         << "<!-- This output should be used with care. We do not report type " | ||||
|            "names for flags with user defined types -->\n" | ||||
|         << "<!-- Prefer flag only_check_args for validating flag inputs -->\n" | ||||
|         // The document.
 | ||||
|         << "<AllFlags>\n" | ||||
|         // The program name and usage.
 | ||||
|         << XMLElement("program", flags_internal::ShortProgramInvocationName()) | ||||
|         << '\n' | ||||
|         << XMLElement("usage", program_usage_message) << '\n'; | ||||
|   } | ||||
| 
 | ||||
|   // Map of package name to
 | ||||
|   //   map of file name to
 | ||||
|   //     vector of flags in the file.
 | ||||
|   // This map is used to output matching flags grouped by package and file
 | ||||
|   // name.
 | ||||
|   std::map<std::string, | ||||
|            std::map<std::string, | ||||
|                     std::vector<const flags_internal::CommandLineFlag*>>> | ||||
|       matching_flags; | ||||
| 
 | ||||
|   flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) { | ||||
|     std::string flag_filename = flag->Filename(); | ||||
| 
 | ||||
|     // Ignore retired flags.
 | ||||
|     if (flag->IsRetired()) return; | ||||
| 
 | ||||
|     // If the flag has been stripped, pretend that it doesn't exist.
 | ||||
|     if (flag->Help() == flags_internal::kStrippedFlagHelp) return; | ||||
| 
 | ||||
|     // Make sure flag satisfies the filter
 | ||||
|     if (!filter_cb || !filter_cb(flag_filename)) return; | ||||
| 
 | ||||
|     matching_flags[std::string(flags_internal::Package(flag_filename))] | ||||
|                   [flag_filename] | ||||
|                       .push_back(flag); | ||||
|   }); | ||||
| 
 | ||||
|   absl::string_view | ||||
|       package_separator;             // controls blank lines between packages.
 | ||||
|   absl::string_view file_separator;  // controls blank lines between files.
 | ||||
|   for (const auto& package : matching_flags) { | ||||
|     if (format == HelpFormat::kHumanReadable) { | ||||
|       out << package_separator; | ||||
|       package_separator = "\n\n"; | ||||
|     } | ||||
| 
 | ||||
|     file_separator = ""; | ||||
|     for (const auto& flags_in_file : package.second) { | ||||
|       if (format == HelpFormat::kHumanReadable) { | ||||
|         out << file_separator << "  Flags from " << flags_in_file.first | ||||
|             << ":\n"; | ||||
|         file_separator = "\n"; | ||||
|       } | ||||
| 
 | ||||
|       for (const auto* flag : flags_in_file.second) { | ||||
|         flags_internal::FlagHelp(out, *flag, format); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (format == HelpFormat::kHumanReadable) { | ||||
|     if (filter_cb && matching_flags.empty()) { | ||||
|       out << "  No modules matched: use -helpfull\n"; | ||||
|     } | ||||
|   } else { | ||||
|     // The end of the document.
 | ||||
|     out << "</AllFlags>\n"; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Produces the help message describing specific flag.
 | ||||
| void FlagHelp(std::ostream& out, const flags_internal::CommandLineFlag& flag, | ||||
|               HelpFormat format) { | ||||
|   if (format == HelpFormat::kHumanReadable) | ||||
|     flags_internal::FlagHelpHumanReadable(flag, &out); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Produces the help messages for all flags matching the filter.
 | ||||
| // If filter is empty produces help messages for all flags.
 | ||||
| void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format, | ||||
|                absl::string_view program_usage_message) { | ||||
|   flags_internal::FlagKindFilter filter_cb = [&](absl::string_view filename) { | ||||
|     return filter.empty() || filename.find(filter) != absl::string_view::npos; | ||||
|   }; | ||||
|   flags_internal::FlagsHelpImpl(out, filter_cb, format, program_usage_message); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Checks all the 'usage' command line flags to see if any have been set.
 | ||||
| // If so, handles them appropriately.
 | ||||
| int HandleUsageFlags(std::ostream& out, | ||||
|                      absl::string_view program_usage_message) { | ||||
|   if (absl::GetFlag(FLAGS_helpshort)) { | ||||
|     flags_internal::FlagsHelpImpl( | ||||
|         out, flags_internal::GetUsageConfig().contains_helpshort_flags, | ||||
|         HelpFormat::kHumanReadable, program_usage_message); | ||||
|     return 1; | ||||
|   } | ||||
| 
 | ||||
|   if (absl::GetFlag(FLAGS_helpfull)) { | ||||
|     // show all options
 | ||||
|     flags_internal::FlagsHelp(out, "", HelpFormat::kHumanReadable, | ||||
|                               program_usage_message); | ||||
|     return 1; | ||||
|   } | ||||
| 
 | ||||
|   if (!absl::GetFlag(FLAGS_helpon).empty()) { | ||||
|     flags_internal::FlagsHelp( | ||||
|         out, absl::StrCat("/", absl::GetFlag(FLAGS_helpon), "."), | ||||
|         HelpFormat::kHumanReadable, program_usage_message); | ||||
|     return 1; | ||||
|   } | ||||
| 
 | ||||
|   if (!absl::GetFlag(FLAGS_helpmatch).empty()) { | ||||
|     flags_internal::FlagsHelp(out, absl::GetFlag(FLAGS_helpmatch), | ||||
|                               HelpFormat::kHumanReadable, | ||||
|                               program_usage_message); | ||||
|     return 1; | ||||
|   } | ||||
| 
 | ||||
|   if (absl::GetFlag(FLAGS_help)) { | ||||
|     flags_internal::FlagsHelpImpl( | ||||
|         out, flags_internal::GetUsageConfig().contains_help_flags, | ||||
|         HelpFormat::kHumanReadable, program_usage_message); | ||||
| 
 | ||||
|     out << "\nTry --helpfull to get a list of all flags.\n"; | ||||
| 
 | ||||
|     return 1; | ||||
|   } | ||||
| 
 | ||||
|   if (absl::GetFlag(FLAGS_helppackage)) { | ||||
|     flags_internal::FlagsHelpImpl( | ||||
|         out, flags_internal::GetUsageConfig().contains_helppackage_flags, | ||||
|         HelpFormat::kHumanReadable, program_usage_message); | ||||
| 
 | ||||
|     out << "\nTry --helpfull to get a list of all flags.\n"; | ||||
| 
 | ||||
|     return 1; | ||||
|   } | ||||
| 
 | ||||
|   if (absl::GetFlag(FLAGS_version)) { | ||||
|     if (flags_internal::GetUsageConfig().version_string) | ||||
|       out << flags_internal::GetUsageConfig().version_string(); | ||||
|     // Unlike help, we may be asking for version in a script, so return 0
 | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   if (absl::GetFlag(FLAGS_only_check_args)) { | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   return -1; | ||||
| } | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
							
								
								
									
										81
									
								
								third_party/abseil_cpp/absl/flags/internal/usage.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								third_party/abseil_cpp/absl/flags/internal/usage.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,81 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_INTERNAL_USAGE_H_ | ||||
| #define ABSL_FLAGS_INTERNAL_USAGE_H_ | ||||
| 
 | ||||
| #include <iosfwd> | ||||
| #include <string> | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/flags/declare.h" | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Usage reporting interfaces
 | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| // The format to report the help messages in.
 | ||||
| enum class HelpFormat { | ||||
|   kHumanReadable, | ||||
| }; | ||||
| 
 | ||||
| // Outputs the help message describing specific flag.
 | ||||
| void FlagHelp(std::ostream& out, const flags_internal::CommandLineFlag& flag, | ||||
|               HelpFormat format = HelpFormat::kHumanReadable); | ||||
| 
 | ||||
| // Produces the help messages for all flags matching the filter. A flag matches
 | ||||
| // the filter if it is defined in a file with a filename which includes
 | ||||
| // filter string as a substring. You can use '/' and '.' to restrict the
 | ||||
| // matching to a specific file names. For example:
 | ||||
| //   FlagsHelp(out, "/path/to/file.");
 | ||||
| // restricts help to only flags which resides in files named like:
 | ||||
| //  .../path/to/file.<ext>
 | ||||
| // for any extension 'ext'. If the filter is empty this function produces help
 | ||||
| // messages for all flags.
 | ||||
| void FlagsHelp(std::ostream& out, absl::string_view filter, | ||||
|                HelpFormat format, absl::string_view program_usage_message); | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| // If any of the 'usage' related command line flags (listed on the bottom of
 | ||||
| // this file) has been set this routine produces corresponding help message in
 | ||||
| // the specified output stream and returns:
 | ||||
| //  0 - if "version" or "only_check_flags" flags were set and handled.
 | ||||
| //  1 - if some other 'usage' related flag was set and handled.
 | ||||
| // -1 - if no usage flags were set on a commmand line.
 | ||||
| // Non negative return values are expected to be used as an exit code for a
 | ||||
| // binary.
 | ||||
| int HandleUsageFlags(std::ostream& out, | ||||
|                      absl::string_view program_usage_message); | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| ABSL_DECLARE_FLAG(bool, help); | ||||
| ABSL_DECLARE_FLAG(bool, helpfull); | ||||
| ABSL_DECLARE_FLAG(bool, helpshort); | ||||
| ABSL_DECLARE_FLAG(bool, helppackage); | ||||
| ABSL_DECLARE_FLAG(bool, version); | ||||
| ABSL_DECLARE_FLAG(bool, only_check_args); | ||||
| ABSL_DECLARE_FLAG(std::string, helpon); | ||||
| ABSL_DECLARE_FLAG(std::string, helpmatch); | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_INTERNAL_USAGE_H_
 | ||||
							
								
								
									
										411
									
								
								third_party/abseil_cpp/absl/flags/internal/usage_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										411
									
								
								third_party/abseil_cpp/absl/flags/internal/usage_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,411 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/internal/usage.h" | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| #include <sstream> | ||||
| #include <string> | ||||
| 
 | ||||
| #include "gtest/gtest.h" | ||||
| #include "absl/flags/declare.h" | ||||
| #include "absl/flags/flag.h" | ||||
| #include "absl/flags/internal/parse.h" | ||||
| #include "absl/flags/internal/path_util.h" | ||||
| #include "absl/flags/internal/program_name.h" | ||||
| #include "absl/flags/internal/registry.h" | ||||
| #include "absl/flags/usage.h" | ||||
| #include "absl/flags/usage_config.h" | ||||
| #include "absl/memory/memory.h" | ||||
| #include "absl/strings/match.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| ABSL_FLAG(int, usage_reporting_test_flag_01, 101, | ||||
|           "usage_reporting_test_flag_01 help message"); | ||||
| ABSL_FLAG(bool, usage_reporting_test_flag_02, false, | ||||
|           "usage_reporting_test_flag_02 help message"); | ||||
| ABSL_FLAG(double, usage_reporting_test_flag_03, 1.03, | ||||
|           "usage_reporting_test_flag_03 help message"); | ||||
| ABSL_FLAG(int64_t, usage_reporting_test_flag_04, 1000000000000004L, | ||||
|           "usage_reporting_test_flag_04 help message"); | ||||
| 
 | ||||
| static const char kTestUsageMessage[] = "Custom usage message"; | ||||
| 
 | ||||
| struct UDT { | ||||
|   UDT() = default; | ||||
|   UDT(const UDT&) = default; | ||||
| }; | ||||
| bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; } | ||||
| std::string AbslUnparseFlag(const UDT&) { return "UDT{}"; } | ||||
| 
 | ||||
| ABSL_FLAG(UDT, usage_reporting_test_flag_05, {}, | ||||
|           "usage_reporting_test_flag_05 help message"); | ||||
| 
 | ||||
| ABSL_FLAG( | ||||
|     std::string, usage_reporting_test_flag_06, {}, | ||||
|     "usage_reporting_test_flag_06 help message.\n" | ||||
|     "\n" | ||||
|     "Some more help.\n" | ||||
|     "Even more long long long long long long long long long long long long " | ||||
|     "help message."); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| namespace flags = absl::flags_internal; | ||||
| 
 | ||||
| static std::string NormalizeFileName(absl::string_view fname) { | ||||
| #ifdef _WIN32 | ||||
|   std::string normalized(fname); | ||||
|   std::replace(normalized.begin(), normalized.end(), '\\', '/'); | ||||
|   fname = normalized; | ||||
| #endif | ||||
| 
 | ||||
|   auto absl_pos = fname.rfind("absl/"); | ||||
|   if (absl_pos != absl::string_view::npos) { | ||||
|     fname = fname.substr(absl_pos); | ||||
|   } | ||||
|   return std::string(fname); | ||||
| } | ||||
| 
 | ||||
| class UsageReportingTest : public testing::Test { | ||||
|  protected: | ||||
|   UsageReportingTest() { | ||||
|     // Install default config for the use on this unit test.
 | ||||
|     // Binary may install a custom config before tests are run.
 | ||||
|     absl::FlagsUsageConfig default_config; | ||||
|     default_config.normalize_filename = &NormalizeFileName; | ||||
|     absl::SetFlagsUsageConfig(default_config); | ||||
|   } | ||||
| 
 | ||||
|  private: | ||||
|   flags::FlagSaver flag_saver_; | ||||
| }; | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| using UsageReportingDeathTest = UsageReportingTest; | ||||
| 
 | ||||
| TEST_F(UsageReportingDeathTest, TestSetProgramUsageMessage) { | ||||
|   EXPECT_EQ(absl::ProgramUsageMessage(), kTestUsageMessage); | ||||
| 
 | ||||
| #ifndef _WIN32 | ||||
|   // TODO(rogeeff): figure out why this does not work on Windows.
 | ||||
|   EXPECT_DEATH_IF_SUPPORTED( | ||||
|       absl::SetProgramUsageMessage("custom usage message"), | ||||
|       ".*SetProgramUsageMessage\\(\\) called twice.*"); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) { | ||||
|   const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_01"); | ||||
|   std::stringstream test_buf; | ||||
| 
 | ||||
|   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); | ||||
|   EXPECT_EQ( | ||||
|       test_buf.str(), | ||||
|       R"(    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); | ||||
|       default: 101; | ||||
| )"); | ||||
| } | ||||
| 
 | ||||
| TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) { | ||||
|   const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_02"); | ||||
|   std::stringstream test_buf; | ||||
| 
 | ||||
|   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); | ||||
|   EXPECT_EQ( | ||||
|       test_buf.str(), | ||||
|       R"(    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); | ||||
|       default: false; | ||||
| )"); | ||||
| } | ||||
| 
 | ||||
| TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) { | ||||
|   const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_03"); | ||||
|   std::stringstream test_buf; | ||||
| 
 | ||||
|   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); | ||||
|   EXPECT_EQ( | ||||
|       test_buf.str(), | ||||
|       R"(    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); | ||||
|       default: 1.03; | ||||
| )"); | ||||
| } | ||||
| 
 | ||||
| TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) { | ||||
|   const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_04"); | ||||
|   std::stringstream test_buf; | ||||
| 
 | ||||
|   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); | ||||
|   EXPECT_EQ( | ||||
|       test_buf.str(), | ||||
|       R"(    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); | ||||
|       default: 1000000000000004; | ||||
| )"); | ||||
| } | ||||
| 
 | ||||
| TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_05) { | ||||
|   const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_05"); | ||||
|   std::stringstream test_buf; | ||||
| 
 | ||||
|   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); | ||||
|   EXPECT_EQ( | ||||
|       test_buf.str(), | ||||
|       R"(    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); | ||||
|       default: UDT{}; | ||||
| )"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(UsageReportingTest, TestFlagsHelpHRF) { | ||||
|   std::string usage_test_flags_out = | ||||
|       R"(usage_test: Custom usage message | ||||
| 
 | ||||
|   Flags from absl/flags/internal/usage_test.cc: | ||||
|     --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); | ||||
|       default: 101; | ||||
|     --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); | ||||
|       default: false; | ||||
|     --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); | ||||
|       default: 1.03; | ||||
|     --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); | ||||
|       default: 1000000000000004; | ||||
|     --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); | ||||
|       default: UDT{}; | ||||
|     --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. | ||||
| 
 | ||||
|       Some more help. | ||||
|       Even more long long long long long long long long long long long long help | ||||
|       message.); default: ""; | ||||
| )"; | ||||
| 
 | ||||
|   std::stringstream test_buf_01; | ||||
|   flags::FlagsHelp(test_buf_01, "usage_test.cc", | ||||
|                    flags::HelpFormat::kHumanReadable, kTestUsageMessage); | ||||
|   EXPECT_EQ(test_buf_01.str(), usage_test_flags_out); | ||||
| 
 | ||||
|   std::stringstream test_buf_02; | ||||
|   flags::FlagsHelp(test_buf_02, "flags/internal/usage_test.cc", | ||||
|                    flags::HelpFormat::kHumanReadable, kTestUsageMessage); | ||||
|   EXPECT_EQ(test_buf_02.str(), usage_test_flags_out); | ||||
| 
 | ||||
|   std::stringstream test_buf_03; | ||||
|   flags::FlagsHelp(test_buf_03, "usage_test", flags::HelpFormat::kHumanReadable, | ||||
|                    kTestUsageMessage); | ||||
|   EXPECT_EQ(test_buf_03.str(), usage_test_flags_out); | ||||
| 
 | ||||
|   std::stringstream test_buf_04; | ||||
|   flags::FlagsHelp(test_buf_04, "flags/invalid_file_name.cc", | ||||
|                    flags::HelpFormat::kHumanReadable, kTestUsageMessage); | ||||
|   EXPECT_EQ(test_buf_04.str(), | ||||
|             R"(usage_test: Custom usage message | ||||
| 
 | ||||
|   No modules matched: use -helpfull | ||||
| )"); | ||||
| 
 | ||||
|   std::stringstream test_buf_05; | ||||
|   flags::FlagsHelp(test_buf_05, "", flags::HelpFormat::kHumanReadable, | ||||
|                    kTestUsageMessage); | ||||
|   std::string test_out = test_buf_05.str(); | ||||
|   absl::string_view test_out_str(test_out); | ||||
|   EXPECT_TRUE( | ||||
|       absl::StartsWith(test_out_str, "usage_test: Custom usage message")); | ||||
|   EXPECT_TRUE(absl::StrContains( | ||||
|       test_out_str, "Flags from absl/flags/internal/usage_test.cc:")); | ||||
|   EXPECT_TRUE(absl::StrContains(test_out_str, | ||||
|                                 "Flags from absl/flags/internal/usage.cc:")); | ||||
|   EXPECT_TRUE( | ||||
|       absl::StrContains(test_out_str, "-usage_reporting_test_flag_01 ")); | ||||
|   EXPECT_TRUE(absl::StrContains(test_out_str, "-help (show help")) | ||||
|       << test_out_str; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(UsageReportingTest, TestNoUsageFlags) { | ||||
|   std::stringstream test_buf; | ||||
|   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), -1); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(UsageReportingTest, TestUsageFlag_helpshort) { | ||||
|   absl::SetFlag(&FLAGS_helpshort, true); | ||||
| 
 | ||||
|   std::stringstream test_buf; | ||||
|   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1); | ||||
|   EXPECT_EQ(test_buf.str(), | ||||
|             R"(usage_test: Custom usage message | ||||
| 
 | ||||
|   Flags from absl/flags/internal/usage_test.cc: | ||||
|     --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); | ||||
|       default: 101; | ||||
|     --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); | ||||
|       default: false; | ||||
|     --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); | ||||
|       default: 1.03; | ||||
|     --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); | ||||
|       default: 1000000000000004; | ||||
|     --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); | ||||
|       default: UDT{}; | ||||
|     --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. | ||||
| 
 | ||||
|       Some more help. | ||||
|       Even more long long long long long long long long long long long long help | ||||
|       message.); default: ""; | ||||
| )"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(UsageReportingTest, TestUsageFlag_help) { | ||||
|   absl::SetFlag(&FLAGS_help, true); | ||||
| 
 | ||||
|   std::stringstream test_buf; | ||||
|   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1); | ||||
|   EXPECT_EQ(test_buf.str(), | ||||
|             R"(usage_test: Custom usage message | ||||
| 
 | ||||
|   Flags from absl/flags/internal/usage_test.cc: | ||||
|     --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); | ||||
|       default: 101; | ||||
|     --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); | ||||
|       default: false; | ||||
|     --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); | ||||
|       default: 1.03; | ||||
|     --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); | ||||
|       default: 1000000000000004; | ||||
|     --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); | ||||
|       default: UDT{}; | ||||
|     --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. | ||||
| 
 | ||||
|       Some more help. | ||||
|       Even more long long long long long long long long long long long long help | ||||
|       message.); default: ""; | ||||
| 
 | ||||
| Try --helpfull to get a list of all flags. | ||||
| )"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(UsageReportingTest, TestUsageFlag_helppackage) { | ||||
|   absl::SetFlag(&FLAGS_helppackage, true); | ||||
| 
 | ||||
|   std::stringstream test_buf; | ||||
|   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1); | ||||
|   EXPECT_EQ(test_buf.str(), | ||||
|             R"(usage_test: Custom usage message | ||||
| 
 | ||||
|   Flags from absl/flags/internal/usage_test.cc: | ||||
|     --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); | ||||
|       default: 101; | ||||
|     --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); | ||||
|       default: false; | ||||
|     --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); | ||||
|       default: 1.03; | ||||
|     --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); | ||||
|       default: 1000000000000004; | ||||
|     --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); | ||||
|       default: UDT{}; | ||||
|     --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. | ||||
| 
 | ||||
|       Some more help. | ||||
|       Even more long long long long long long long long long long long long help | ||||
|       message.); default: ""; | ||||
| 
 | ||||
| Try --helpfull to get a list of all flags. | ||||
| )"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(UsageReportingTest, TestUsageFlag_version) { | ||||
|   absl::SetFlag(&FLAGS_version, true); | ||||
| 
 | ||||
|   std::stringstream test_buf; | ||||
|   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0); | ||||
| #ifndef NDEBUG | ||||
|   EXPECT_EQ(test_buf.str(), "usage_test\nDebug build (NDEBUG not #defined)\n"); | ||||
| #else | ||||
|   EXPECT_EQ(test_buf.str(), "usage_test\n"); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) { | ||||
|   absl::SetFlag(&FLAGS_only_check_args, true); | ||||
| 
 | ||||
|   std::stringstream test_buf; | ||||
|   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0); | ||||
|   EXPECT_EQ(test_buf.str(), ""); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(UsageReportingTest, TestUsageFlag_helpon) { | ||||
|   absl::SetFlag(&FLAGS_helpon, "bla-bla"); | ||||
| 
 | ||||
|   std::stringstream test_buf_01; | ||||
|   EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage), 1); | ||||
|   EXPECT_EQ(test_buf_01.str(), | ||||
|             R"(usage_test: Custom usage message | ||||
| 
 | ||||
|   No modules matched: use -helpfull | ||||
| )"); | ||||
| 
 | ||||
|   absl::SetFlag(&FLAGS_helpon, "usage_test"); | ||||
| 
 | ||||
|   std::stringstream test_buf_02; | ||||
|   EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), 1); | ||||
|   EXPECT_EQ(test_buf_02.str(), | ||||
|             R"(usage_test: Custom usage message | ||||
| 
 | ||||
|   Flags from absl/flags/internal/usage_test.cc: | ||||
|     --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); | ||||
|       default: 101; | ||||
|     --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); | ||||
|       default: false; | ||||
|     --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); | ||||
|       default: 1.03; | ||||
|     --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); | ||||
|       default: 1000000000000004; | ||||
|     --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); | ||||
|       default: UDT{}; | ||||
|     --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. | ||||
| 
 | ||||
|       Some more help. | ||||
|       Even more long long long long long long long long long long long long help | ||||
|       message.); default: ""; | ||||
| )"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| int main(int argc, char* argv[]) { | ||||
|   (void)absl::GetFlag(FLAGS_undefok);  // Force linking of parse.cc
 | ||||
|   flags::SetProgramInvocationName("usage_test"); | ||||
|   absl::SetProgramUsageMessage(kTestUsageMessage); | ||||
|   ::testing::InitGoogleTest(&argc, argv); | ||||
| 
 | ||||
|   return RUN_ALL_TESTS(); | ||||
| } | ||||
							
								
								
									
										240
									
								
								third_party/abseil_cpp/absl/flags/marshalling.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								third_party/abseil_cpp/absl/flags/marshalling.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,240 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/marshalling.h" | ||||
| 
 | ||||
| #include <stddef.h> | ||||
| 
 | ||||
| #include <cmath> | ||||
| #include <limits> | ||||
| #include <string> | ||||
| #include <type_traits> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/base/log_severity.h" | ||||
| #include "absl/base/macros.h" | ||||
| #include "absl/strings/ascii.h" | ||||
| #include "absl/strings/match.h" | ||||
| #include "absl/strings/numbers.h" | ||||
| #include "absl/strings/str_cat.h" | ||||
| #include "absl/strings/str_format.h" | ||||
| #include "absl/strings/str_join.h" | ||||
| #include "absl/strings/str_split.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // AbslParseFlag specializations for boolean type.
 | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, bool* dst, std::string*) { | ||||
|   const char* kTrue[] = {"1", "t", "true", "y", "yes"}; | ||||
|   const char* kFalse[] = {"0", "f", "false", "n", "no"}; | ||||
|   static_assert(sizeof(kTrue) == sizeof(kFalse), "true_false_equal"); | ||||
| 
 | ||||
|   text = absl::StripAsciiWhitespace(text); | ||||
| 
 | ||||
|   for (size_t i = 0; i < ABSL_ARRAYSIZE(kTrue); ++i) { | ||||
|     if (absl::EqualsIgnoreCase(text, kTrue[i])) { | ||||
|       *dst = true; | ||||
|       return true; | ||||
|     } else if (absl::EqualsIgnoreCase(text, kFalse[i])) { | ||||
|       *dst = false; | ||||
|       return true; | ||||
|     } | ||||
|   } | ||||
|   return false;  // didn't match a legal input
 | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // AbslParseFlag for integral types.
 | ||||
| 
 | ||||
| // Return the base to use for parsing text as an integer.  Leading 0x
 | ||||
| // puts us in base 16.  But leading 0 does not put us in base 8. It
 | ||||
| // caused too many bugs when we had that behavior.
 | ||||
| static int NumericBase(absl::string_view text) { | ||||
|   const bool hex = (text.size() >= 2 && text[0] == '0' && | ||||
|                     (text[1] == 'x' || text[1] == 'X')); | ||||
|   return hex ? 16 : 10; | ||||
| } | ||||
| 
 | ||||
| template <typename IntType> | ||||
| inline bool ParseFlagImpl(absl::string_view text, IntType* dst) { | ||||
|   text = absl::StripAsciiWhitespace(text); | ||||
| 
 | ||||
|   return absl::numbers_internal::safe_strtoi_base(text, dst, NumericBase(text)); | ||||
| } | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, short* dst, std::string*) { | ||||
|   int val; | ||||
|   if (!ParseFlagImpl(text, &val)) return false; | ||||
|   if (static_cast<short>(val) != val)  // worked, but number out of range
 | ||||
|     return false; | ||||
|   *dst = static_cast<short>(val); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) { | ||||
|   unsigned int val; | ||||
|   if (!ParseFlagImpl(text, &val)) return false; | ||||
|   if (static_cast<unsigned short>(val) != | ||||
|       val)  // worked, but number out of range
 | ||||
|     return false; | ||||
|   *dst = static_cast<unsigned short>(val); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, int* dst, std::string*) { | ||||
|   return ParseFlagImpl(text, dst); | ||||
| } | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, unsigned int* dst, std::string*) { | ||||
|   return ParseFlagImpl(text, dst); | ||||
| } | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, long* dst, std::string*) { | ||||
|   return ParseFlagImpl(text, dst); | ||||
| } | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, unsigned long* dst, std::string*) { | ||||
|   return ParseFlagImpl(text, dst); | ||||
| } | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, long long* dst, std::string*) { | ||||
|   return ParseFlagImpl(text, dst); | ||||
| } | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, unsigned long long* dst, | ||||
|                    std::string*) { | ||||
|   return ParseFlagImpl(text, dst); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // AbslParseFlag for floating point types.
 | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, float* dst, std::string*) { | ||||
|   return absl::SimpleAtof(text, dst); | ||||
| } | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, double* dst, std::string*) { | ||||
|   return absl::SimpleAtod(text, dst); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // AbslParseFlag for strings.
 | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, std::string* dst, std::string*) { | ||||
|   dst->assign(text.data(), text.size()); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // AbslParseFlag for vector of strings.
 | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, std::vector<std::string>* dst, | ||||
|                    std::string*) { | ||||
|   // An empty flag value corresponds to an empty vector, not a vector
 | ||||
|   // with a single, empty std::string.
 | ||||
|   if (text.empty()) { | ||||
|     dst->clear(); | ||||
|     return true; | ||||
|   } | ||||
|   *dst = absl::StrSplit(text, ',', absl::AllowEmpty()); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // AbslUnparseFlag specializations for various builtin flag types.
 | ||||
| 
 | ||||
| std::string Unparse(bool v) { return v ? "true" : "false"; } | ||||
| std::string Unparse(short v) { return absl::StrCat(v); } | ||||
| std::string Unparse(unsigned short v) { return absl::StrCat(v); } | ||||
| std::string Unparse(int v) { return absl::StrCat(v); } | ||||
| std::string Unparse(unsigned int v) { return absl::StrCat(v); } | ||||
| std::string Unparse(long v) { return absl::StrCat(v); } | ||||
| std::string Unparse(unsigned long v) { return absl::StrCat(v); } | ||||
| std::string Unparse(long long v) { return absl::StrCat(v); } | ||||
| std::string Unparse(unsigned long long v) { return absl::StrCat(v); } | ||||
| template <typename T> | ||||
| std::string UnparseFloatingPointVal(T v) { | ||||
|   // digits10 is guaranteed to roundtrip correctly in string -> value -> string
 | ||||
|   // conversions, but may not be enough to represent all the values correctly.
 | ||||
|   std::string digit10_str = | ||||
|       absl::StrFormat("%.*g", std::numeric_limits<T>::digits10, v); | ||||
|   if (std::isnan(v) || std::isinf(v)) return digit10_str; | ||||
| 
 | ||||
|   T roundtrip_val = 0; | ||||
|   std::string err; | ||||
|   if (absl::ParseFlag(digit10_str, &roundtrip_val, &err) && | ||||
|       roundtrip_val == v) { | ||||
|     return digit10_str; | ||||
|   } | ||||
| 
 | ||||
|   // max_digits10 is the number of base-10 digits that are necessary to uniquely
 | ||||
|   // represent all distinct values.
 | ||||
|   return absl::StrFormat("%.*g", std::numeric_limits<T>::max_digits10, v); | ||||
| } | ||||
| std::string Unparse(float v) { return UnparseFloatingPointVal(v); } | ||||
| std::string Unparse(double v) { return UnparseFloatingPointVal(v); } | ||||
| std::string AbslUnparseFlag(absl::string_view v) { return std::string(v); } | ||||
| std::string AbslUnparseFlag(const std::vector<std::string>& v) { | ||||
|   return absl::StrJoin(v, ","); | ||||
| } | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view text, absl::LogSeverity* dst, | ||||
|                    std::string* err) { | ||||
|   text = absl::StripAsciiWhitespace(text); | ||||
|   if (text.empty()) { | ||||
|     *err = "no value provided"; | ||||
|     return false; | ||||
|   } | ||||
|   if (text.front() == 'k' || text.front() == 'K') text.remove_prefix(1); | ||||
|   if (absl::EqualsIgnoreCase(text, "info")) { | ||||
|     *dst = absl::LogSeverity::kInfo; | ||||
|     return true; | ||||
|   } | ||||
|   if (absl::EqualsIgnoreCase(text, "warning")) { | ||||
|     *dst = absl::LogSeverity::kWarning; | ||||
|     return true; | ||||
|   } | ||||
|   if (absl::EqualsIgnoreCase(text, "error")) { | ||||
|     *dst = absl::LogSeverity::kError; | ||||
|     return true; | ||||
|   } | ||||
|   if (absl::EqualsIgnoreCase(text, "fatal")) { | ||||
|     *dst = absl::LogSeverity::kFatal; | ||||
|     return true; | ||||
|   } | ||||
|   std::underlying_type<absl::LogSeverity>::type numeric_value; | ||||
|   if (absl::ParseFlag(text, &numeric_value, err)) { | ||||
|     *dst = static_cast<absl::LogSeverity>(numeric_value); | ||||
|     return true; | ||||
|   } | ||||
|   *err = "only integers and absl::LogSeverity enumerators are accepted"; | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| std::string AbslUnparseFlag(absl::LogSeverity v) { | ||||
|   if (v == absl::NormalizeLogSeverity(v)) return absl::LogSeverityName(v); | ||||
|   return absl::UnparseFlag(static_cast<int>(v)); | ||||
| } | ||||
| 
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
							
								
								
									
										264
									
								
								third_party/abseil_cpp/absl/flags/marshalling.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								third_party/abseil_cpp/absl/flags/marshalling.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,264 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| //
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| // File: marshalling.h
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| //
 | ||||
| // This header file defines the API for extending Abseil flag support to
 | ||||
| // custom types, and defines the set of overloads for fundamental types.
 | ||||
| //
 | ||||
| // Out of the box, the Abseil flags library supports the following types:
 | ||||
| //
 | ||||
| // * `bool`
 | ||||
| // * `int16_t`
 | ||||
| // * `uint16_t`
 | ||||
| // * `int32_t`
 | ||||
| // * `uint32_t`
 | ||||
| // * `int64_t`
 | ||||
| // * `uint64_t`
 | ||||
| // * `float`
 | ||||
| // * `double`
 | ||||
| // * `std::string`
 | ||||
| // * `std::vector<std::string>`
 | ||||
| // * `absl::LogSeverity` (provided natively for layering reasons)
 | ||||
| //
 | ||||
| // Note that support for integral types is implemented using overloads for
 | ||||
| // variable-width fundamental types (`short`, `int`, `long`, etc.). However,
 | ||||
| // you should prefer the fixed-width integral types (`int32_t`, `uint64_t`,
 | ||||
| // etc.) we've noted above within flag definitions.
 | ||||
| //
 | ||||
| // In addition, several Abseil libraries provide their own custom support for
 | ||||
| // Abseil flags. Documentation for these formats is provided in the type's
 | ||||
| // `AbslParseFlag()` definition.
 | ||||
| //
 | ||||
| // The Abseil time library provides the following support for civil time values:
 | ||||
| //
 | ||||
| // * `absl::CivilSecond`
 | ||||
| // * `absl::CivilMinute`
 | ||||
| // * `absl::CivilHour`
 | ||||
| // * `absl::CivilDay`
 | ||||
| // * `absl::CivilMonth`
 | ||||
| // * `absl::CivilYear`
 | ||||
| //
 | ||||
| // and also provides support for the following absolute time values:
 | ||||
| //
 | ||||
| // * `absl::Duration`
 | ||||
| // * `absl::Time`
 | ||||
| //
 | ||||
| // Additional support for Abseil types will be noted here as it is added.
 | ||||
| //
 | ||||
| // You can also provide your own custom flags by adding overloads for
 | ||||
| // `AbslParseFlag()` and `AbslUnparseFlag()` to your type definitions. (See
 | ||||
| // below.)
 | ||||
| //
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| // Adding Type Support for Abseil Flags
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| //
 | ||||
| // To add support for your user-defined type, add overloads of `AbslParseFlag()`
 | ||||
| // and `AbslUnparseFlag()` as free (non-member) functions to your type. If `T`
 | ||||
| // is a class type, these functions can be friend function definitions. These
 | ||||
| // overloads must be added to the same namespace where the type is defined, so
 | ||||
| // that they can be discovered by Argument-Dependent Lookup (ADL).
 | ||||
| //
 | ||||
| // Example:
 | ||||
| //
 | ||||
| //   namespace foo {
 | ||||
| //
 | ||||
| //   enum OutputMode { kPlainText, kHtml };
 | ||||
| //
 | ||||
| //   // AbslParseFlag converts from a string to OutputMode.
 | ||||
| //   // Must be in same namespace as OutputMode.
 | ||||
| //
 | ||||
| //   // Parses an OutputMode from the command line flag value `text. Returns
 | ||||
| //   // `true` and sets `*mode` on success; returns `false` and sets `*error`
 | ||||
| //   // on failure.
 | ||||
| //   bool AbslParseFlag(absl::string_view text,
 | ||||
| //                      OutputMode* mode,
 | ||||
| //                      std::string* error) {
 | ||||
| //     if (text == "plaintext") {
 | ||||
| //       *mode = kPlainText;
 | ||||
| //       return true;
 | ||||
| //     }
 | ||||
| //     if (text == "html") {
 | ||||
| //       *mode = kHtml;
 | ||||
| //      return true;
 | ||||
| //     }
 | ||||
| //     *error = "unknown value for enumeration";
 | ||||
| //     return false;
 | ||||
| //  }
 | ||||
| //
 | ||||
| //  // AbslUnparseFlag converts from an OutputMode to a string.
 | ||||
| //  // Must be in same namespace as OutputMode.
 | ||||
| //
 | ||||
| //  // Returns a textual flag value corresponding to the OutputMode `mode`.
 | ||||
| //  std::string AbslUnparseFlag(OutputMode mode) {
 | ||||
| //    switch (mode) {
 | ||||
| //      case kPlainText: return "plaintext";
 | ||||
| //      case kHtml: return "html";
 | ||||
| //    }
 | ||||
| //    return absl::StrCat(mode);
 | ||||
| //  }
 | ||||
| //
 | ||||
| // Notice that neither `AbslParseFlag()` nor `AbslUnparseFlag()` are class
 | ||||
| // members, but free functions. `AbslParseFlag/AbslUnparseFlag()` overloads
 | ||||
| // for a type should only be declared in the same file and namespace as said
 | ||||
| // type. The proper `AbslParseFlag/AbslUnparseFlag()` implementations for a
 | ||||
| // given type will be discovered via Argument-Dependent Lookup (ADL).
 | ||||
| //
 | ||||
| // `AbslParseFlag()` may need, in turn, to parse simpler constituent types
 | ||||
| // using `absl::ParseFlag()`. For example, a custom struct `MyFlagType`
 | ||||
| // consisting of a `std::pair<int, std::string>` would add an `AbslParseFlag()`
 | ||||
| // overload for its `MyFlagType` like so:
 | ||||
| //
 | ||||
| // Example:
 | ||||
| //
 | ||||
| //   namespace my_flag_type {
 | ||||
| //
 | ||||
| //   struct MyFlagType {
 | ||||
| //     std::pair<int, std::string> my_flag_data;
 | ||||
| //   };
 | ||||
| //
 | ||||
| //   bool AbslParseFlag(absl::string_view text, MyFlagType* flag,
 | ||||
| //                      std::string* err);
 | ||||
| //
 | ||||
| //   std::string AbslUnparseFlag(const MyFlagType&);
 | ||||
| //
 | ||||
| //   // Within the implementation, `AbslParseFlag()` will, in turn invoke
 | ||||
| //   // `absl::ParseFlag()` on its constituent `int` and `std::string` types
 | ||||
| //   // (which have built-in Abseil flag support.
 | ||||
| //
 | ||||
| //   bool AbslParseFlag(absl::string_view text, MyFlagType* flag,
 | ||||
| //                      std::string* err) {
 | ||||
| //     std::pair<absl::string_view, absl::string_view> tokens =
 | ||||
| //         absl::StrSplit(text, ',');
 | ||||
| //     if (!absl::ParseFlag(tokens.first, &flag->my_flag_data.first, err))
 | ||||
| //         return false;
 | ||||
| //     if (!absl::ParseFlag(tokens.second, &flag->my_flag_data.second, err))
 | ||||
| //         return false;
 | ||||
| //     return true;
 | ||||
| //   }
 | ||||
| //
 | ||||
| //   // Similarly, for unparsing, we can simply invoke `absl::UnparseFlag()` on
 | ||||
| //   // the constituent types.
 | ||||
| //   std::string AbslUnparseFlag(const MyFlagType& flag) {
 | ||||
| //     return absl::StrCat(absl::UnparseFlag(flag.my_flag_data.first),
 | ||||
| //                         ",",
 | ||||
| //                         absl::UnparseFlag(flag.my_flag_data.second));
 | ||||
| //   }
 | ||||
| #ifndef ABSL_FLAGS_MARSHALLING_H_ | ||||
| #define ABSL_FLAGS_MARSHALLING_H_ | ||||
| 
 | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| // Overloads of `AbslParseFlag()` and `AbslUnparseFlag()` for fundamental types.
 | ||||
| bool AbslParseFlag(absl::string_view, bool*, std::string*); | ||||
| bool AbslParseFlag(absl::string_view, short*, std::string*);           // NOLINT
 | ||||
| bool AbslParseFlag(absl::string_view, unsigned short*, std::string*);  // NOLINT
 | ||||
| bool AbslParseFlag(absl::string_view, int*, std::string*);             // NOLINT
 | ||||
| bool AbslParseFlag(absl::string_view, unsigned int*, std::string*);    // NOLINT
 | ||||
| bool AbslParseFlag(absl::string_view, long*, std::string*);            // NOLINT
 | ||||
| bool AbslParseFlag(absl::string_view, unsigned long*, std::string*);   // NOLINT
 | ||||
| bool AbslParseFlag(absl::string_view, long long*, std::string*);       // NOLINT
 | ||||
| bool AbslParseFlag(absl::string_view, unsigned long long*,             // NOLINT
 | ||||
|                    std::string*); | ||||
| bool AbslParseFlag(absl::string_view, float*, std::string*); | ||||
| bool AbslParseFlag(absl::string_view, double*, std::string*); | ||||
| bool AbslParseFlag(absl::string_view, std::string*, std::string*); | ||||
| bool AbslParseFlag(absl::string_view, std::vector<std::string>*, std::string*); | ||||
| 
 | ||||
| template <typename T> | ||||
| bool InvokeParseFlag(absl::string_view input, T* dst, std::string* err) { | ||||
|   // Comment on next line provides a good compiler error message if T
 | ||||
|   // does not have AbslParseFlag(absl::string_view, T*, std::string*).
 | ||||
|   return AbslParseFlag(input, dst, err);  // Is T missing AbslParseFlag?
 | ||||
| } | ||||
| 
 | ||||
| // Strings and std:: containers do not have the same overload resolution
 | ||||
| // considerations as fundamental types. Naming these 'AbslUnparseFlag' means we
 | ||||
| // can avoid the need for additional specializations of Unparse (below).
 | ||||
| std::string AbslUnparseFlag(absl::string_view v); | ||||
| std::string AbslUnparseFlag(const std::vector<std::string>&); | ||||
| 
 | ||||
| template <typename T> | ||||
| std::string Unparse(const T& v) { | ||||
|   // Comment on next line provides a good compiler error message if T does not
 | ||||
|   // have UnparseFlag.
 | ||||
|   return AbslUnparseFlag(v);  // Is T missing AbslUnparseFlag?
 | ||||
| } | ||||
| 
 | ||||
| // Overloads for builtin types.
 | ||||
| std::string Unparse(bool v); | ||||
| std::string Unparse(short v);               // NOLINT
 | ||||
| std::string Unparse(unsigned short v);      // NOLINT
 | ||||
| std::string Unparse(int v);                 // NOLINT
 | ||||
| std::string Unparse(unsigned int v);        // NOLINT
 | ||||
| std::string Unparse(long v);                // NOLINT
 | ||||
| std::string Unparse(unsigned long v);       // NOLINT
 | ||||
| std::string Unparse(long long v);           // NOLINT
 | ||||
| std::string Unparse(unsigned long long v);  // NOLINT
 | ||||
| std::string Unparse(float v); | ||||
| std::string Unparse(double v); | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| 
 | ||||
| // ParseFlag()
 | ||||
| //
 | ||||
| // Parses a string value into a flag value of type `T`. Do not add overloads of
 | ||||
| // this function for your type directly; instead, add an `AbslParseFlag()`
 | ||||
| // free function as documented above.
 | ||||
| //
 | ||||
| // Some implementations of `AbslParseFlag()` for types which consist of other,
 | ||||
| // constituent types which already have Abseil flag support, may need to call
 | ||||
| // `absl::ParseFlag()` on those consituent string values. (See above.)
 | ||||
| template <typename T> | ||||
| inline bool ParseFlag(absl::string_view input, T* dst, std::string* error) { | ||||
|   return flags_internal::InvokeParseFlag(input, dst, error); | ||||
| } | ||||
| 
 | ||||
| // UnparseFlag()
 | ||||
| //
 | ||||
| // Unparses a flag value of type `T` into a string value. Do not add overloads
 | ||||
| // of this function for your type directly; instead, add an `AbslUnparseFlag()`
 | ||||
| // free function as documented above.
 | ||||
| //
 | ||||
| // Some implementations of `AbslUnparseFlag()` for types which consist of other,
 | ||||
| // constituent types which already have Abseil flag support, may want to call
 | ||||
| // `absl::UnparseFlag()` on those constituent types. (See above.)
 | ||||
| template <typename T> | ||||
| inline std::string UnparseFlag(const T& v) { | ||||
|   return flags_internal::Unparse(v); | ||||
| } | ||||
| 
 | ||||
| // Overloads for `absl::LogSeverity` can't (easily) appear alongside that type's
 | ||||
| // definition because it is layered below flags.  See proper documentation in
 | ||||
| // base/log_severity.h.
 | ||||
| enum class LogSeverity : int; | ||||
| bool AbslParseFlag(absl::string_view, absl::LogSeverity*, std::string*); | ||||
| std::string AbslUnparseFlag(absl::LogSeverity); | ||||
| 
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_MARSHALLING_H_
 | ||||
							
								
								
									
										904
									
								
								third_party/abseil_cpp/absl/flags/marshalling_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										904
									
								
								third_party/abseil_cpp/absl/flags/marshalling_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,904 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/marshalling.h" | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| #include <cmath> | ||||
| #include <limits> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "gtest/gtest.h" | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| TEST(MarshallingTest, TestBoolParsing) { | ||||
|   std::string err; | ||||
|   bool value; | ||||
| 
 | ||||
|   // True values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("True", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("true", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("TRUE", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
| 
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("Yes", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("yes", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("YES", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
| 
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("t", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("T", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
| 
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("y", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("Y", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
| 
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
| 
 | ||||
|   // False values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("False", &value, &err)); | ||||
|   EXPECT_FALSE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("false", &value, &err)); | ||||
|   EXPECT_FALSE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("FALSE", &value, &err)); | ||||
|   EXPECT_FALSE(value); | ||||
| 
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("No", &value, &err)); | ||||
|   EXPECT_FALSE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("no", &value, &err)); | ||||
|   EXPECT_FALSE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("NO", &value, &err)); | ||||
|   EXPECT_FALSE(value); | ||||
| 
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("f", &value, &err)); | ||||
|   EXPECT_FALSE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("F", &value, &err)); | ||||
|   EXPECT_FALSE(value); | ||||
| 
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("n", &value, &err)); | ||||
|   EXPECT_FALSE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("N", &value, &err)); | ||||
|   EXPECT_FALSE(value); | ||||
| 
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); | ||||
|   EXPECT_FALSE(value); | ||||
| 
 | ||||
|   // Whitespace handling.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("  true", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("true  ", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  true   ", &value, &err)); | ||||
|   EXPECT_TRUE(value); | ||||
| 
 | ||||
|   // Invalid input.
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("  ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("2", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("11", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("tt", &value, &err)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestInt16Parsing) { | ||||
|   std::string err; | ||||
|   int16_t value; | ||||
| 
 | ||||
|   // Decimal values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); | ||||
|   EXPECT_EQ(value, 0); | ||||
|   EXPECT_TRUE(absl::ParseFlag("-1", &value, &err)); | ||||
|   EXPECT_EQ(value, -1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("123", &value, &err)); | ||||
|   EXPECT_EQ(value, 123); | ||||
|   EXPECT_TRUE(absl::ParseFlag("-18765", &value, &err)); | ||||
|   EXPECT_EQ(value, -18765); | ||||
|   EXPECT_TRUE(absl::ParseFlag("+3", &value, &err)); | ||||
|   EXPECT_EQ(value, 3); | ||||
| 
 | ||||
|   // Leading zero values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("01", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("-001", &value, &err)); | ||||
|   EXPECT_EQ(value, -1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err)); | ||||
|   EXPECT_EQ(value, 100); | ||||
| 
 | ||||
|   // Hex values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err)); | ||||
|   EXPECT_EQ(value, 16); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err)); | ||||
|   EXPECT_EQ(value, 564); | ||||
|   // TODO(rogeeff): fix below validations
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("-0x7FFD", &value, &err)); | ||||
|   EXPECT_NE(value, -3); | ||||
|   EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err)); | ||||
|   EXPECT_NE(value, 49); | ||||
| 
 | ||||
|   // Whitespace handling
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("10  ", &value, &err)); | ||||
|   EXPECT_EQ(value, 10); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  11", &value, &err)); | ||||
|   EXPECT_EQ(value, 11); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  012  ", &value, &err)); | ||||
|   EXPECT_EQ(value, 12); | ||||
|   EXPECT_TRUE(absl::ParseFlag(" 0x22    ", &value, &err)); | ||||
|   EXPECT_EQ(value, 34); | ||||
| 
 | ||||
|   // Invalid values.
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("  ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("40000", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("2U", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestUint16Parsing) { | ||||
|   std::string err; | ||||
|   uint16_t value; | ||||
| 
 | ||||
|   // Decimal values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); | ||||
|   EXPECT_EQ(value, 0); | ||||
|   EXPECT_TRUE(absl::ParseFlag("123", &value, &err)); | ||||
|   EXPECT_EQ(value, 123); | ||||
|   EXPECT_TRUE(absl::ParseFlag("+3", &value, &err)); | ||||
|   EXPECT_EQ(value, 3); | ||||
| 
 | ||||
|   // Leading zero values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("01", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("001", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err)); | ||||
|   EXPECT_EQ(value, 100); | ||||
| 
 | ||||
|   // Hex values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err)); | ||||
|   EXPECT_EQ(value, 16); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err)); | ||||
|   EXPECT_EQ(value, 564); | ||||
|   // TODO(rogeeff): fix below validations
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err)); | ||||
|   EXPECT_NE(value, 49); | ||||
| 
 | ||||
|   // Whitespace handling
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("10  ", &value, &err)); | ||||
|   EXPECT_EQ(value, 10); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  11", &value, &err)); | ||||
|   EXPECT_EQ(value, 11); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  012  ", &value, &err)); | ||||
|   EXPECT_EQ(value, 12); | ||||
|   EXPECT_TRUE(absl::ParseFlag(" 0x22    ", &value, &err)); | ||||
|   EXPECT_EQ(value, 34); | ||||
| 
 | ||||
|   // Invalid values.
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("  ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("70000", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("-1", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("2U", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestInt32Parsing) { | ||||
|   std::string err; | ||||
|   int32_t value; | ||||
| 
 | ||||
|   // Decimal values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); | ||||
|   EXPECT_EQ(value, 0); | ||||
|   EXPECT_TRUE(absl::ParseFlag("-1", &value, &err)); | ||||
|   EXPECT_EQ(value, -1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("123", &value, &err)); | ||||
|   EXPECT_EQ(value, 123); | ||||
|   EXPECT_TRUE(absl::ParseFlag("-98765", &value, &err)); | ||||
|   EXPECT_EQ(value, -98765); | ||||
|   EXPECT_TRUE(absl::ParseFlag("+3", &value, &err)); | ||||
|   EXPECT_EQ(value, 3); | ||||
| 
 | ||||
|   // Leading zero values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("01", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("-001", &value, &err)); | ||||
|   EXPECT_EQ(value, -1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err)); | ||||
|   EXPECT_EQ(value, 100); | ||||
| 
 | ||||
|   // Hex values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err)); | ||||
|   EXPECT_EQ(value, 16); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err)); | ||||
|   EXPECT_EQ(value, 564); | ||||
|   // TODO(rogeeff): fix below validations
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("-0x7FFFFFFD", &value, &err)); | ||||
|   EXPECT_NE(value, -3); | ||||
|   EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err)); | ||||
|   EXPECT_NE(value, 49); | ||||
| 
 | ||||
|   // Whitespace handling
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("10  ", &value, &err)); | ||||
|   EXPECT_EQ(value, 10); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  11", &value, &err)); | ||||
|   EXPECT_EQ(value, 11); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  012  ", &value, &err)); | ||||
|   EXPECT_EQ(value, 12); | ||||
|   EXPECT_TRUE(absl::ParseFlag(" 0x22    ", &value, &err)); | ||||
|   EXPECT_EQ(value, 34); | ||||
| 
 | ||||
|   // Invalid values.
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("  ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("70000000000", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("2U", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestUint32Parsing) { | ||||
|   std::string err; | ||||
|   uint32_t value; | ||||
| 
 | ||||
|   // Decimal values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); | ||||
|   EXPECT_EQ(value, 0); | ||||
|   EXPECT_TRUE(absl::ParseFlag("123", &value, &err)); | ||||
|   EXPECT_EQ(value, 123); | ||||
|   EXPECT_TRUE(absl::ParseFlag("+3", &value, &err)); | ||||
|   EXPECT_EQ(value, 3); | ||||
| 
 | ||||
|   // Leading zero values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("01", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err)); | ||||
|   EXPECT_EQ(value, 100); | ||||
| 
 | ||||
|   // Hex values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err)); | ||||
|   EXPECT_EQ(value, 16); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err)); | ||||
|   EXPECT_EQ(value, 564); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0xFFFFFFFD", &value, &err)); | ||||
|   EXPECT_EQ(value, 4294967293); | ||||
|   // TODO(rogeeff): fix below validations
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err)); | ||||
|   EXPECT_NE(value, 49); | ||||
| 
 | ||||
|   // Whitespace handling
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("10  ", &value, &err)); | ||||
|   EXPECT_EQ(value, 10); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  11", &value, &err)); | ||||
|   EXPECT_EQ(value, 11); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  012  ", &value, &err)); | ||||
|   EXPECT_EQ(value, 12); | ||||
|   EXPECT_TRUE(absl::ParseFlag(" 0x22    ", &value, &err)); | ||||
|   EXPECT_EQ(value, 34); | ||||
| 
 | ||||
|   // Invalid values.
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("  ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("140000000000", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("-1", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("2U", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestInt64Parsing) { | ||||
|   std::string err; | ||||
|   int64_t value; | ||||
| 
 | ||||
|   // Decimal values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); | ||||
|   EXPECT_EQ(value, 0); | ||||
|   EXPECT_TRUE(absl::ParseFlag("-1", &value, &err)); | ||||
|   EXPECT_EQ(value, -1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("123", &value, &err)); | ||||
|   EXPECT_EQ(value, 123); | ||||
|   EXPECT_TRUE(absl::ParseFlag("-98765", &value, &err)); | ||||
|   EXPECT_EQ(value, -98765); | ||||
|   EXPECT_TRUE(absl::ParseFlag("+3", &value, &err)); | ||||
|   EXPECT_EQ(value, 3); | ||||
| 
 | ||||
|   // Leading zero values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("01", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("001", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err)); | ||||
|   EXPECT_EQ(value, 100); | ||||
| 
 | ||||
|   // Hex values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err)); | ||||
|   EXPECT_EQ(value, 16); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0XFFFAAABBBCCCDDD", &value, &err)); | ||||
|   EXPECT_EQ(value, 1152827684197027293); | ||||
|   // TODO(rogeeff): fix below validation
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("-0x7FFFFFFFFFFFFFFE", &value, &err)); | ||||
|   EXPECT_NE(value, -2); | ||||
|   EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err)); | ||||
|   EXPECT_NE(value, 49); | ||||
| 
 | ||||
|   // Whitespace handling
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("10  ", &value, &err)); | ||||
|   EXPECT_EQ(value, 10); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  11", &value, &err)); | ||||
|   EXPECT_EQ(value, 11); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  012  ", &value, &err)); | ||||
|   EXPECT_EQ(value, 12); | ||||
|   EXPECT_TRUE(absl::ParseFlag(" 0x7F    ", &value, &err)); | ||||
|   EXPECT_EQ(value, 127); | ||||
| 
 | ||||
|   // Invalid values.
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("  ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("0xFFFFFFFFFFFFFFFFFF", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("2U", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestUInt64Parsing) { | ||||
|   std::string err; | ||||
|   uint64_t value; | ||||
| 
 | ||||
|   // Decimal values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); | ||||
|   EXPECT_EQ(value, 0); | ||||
|   EXPECT_TRUE(absl::ParseFlag("123", &value, &err)); | ||||
|   EXPECT_EQ(value, 123); | ||||
|   EXPECT_TRUE(absl::ParseFlag("+13", &value, &err)); | ||||
|   EXPECT_EQ(value, 13); | ||||
| 
 | ||||
|   // Leading zero values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("01", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("001", &value, &err)); | ||||
|   EXPECT_EQ(value, 1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0000300", &value, &err)); | ||||
|   EXPECT_EQ(value, 300); | ||||
| 
 | ||||
|   // Hex values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err)); | ||||
|   EXPECT_EQ(value, 16); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0XFFFF", &value, &err)); | ||||
|   EXPECT_EQ(value, 65535); | ||||
|   // TODO(rogeeff): fix below validation
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err)); | ||||
|   EXPECT_NE(value, 49); | ||||
| 
 | ||||
|   // Whitespace handling
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("10  ", &value, &err)); | ||||
|   EXPECT_EQ(value, 10); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  11", &value, &err)); | ||||
|   EXPECT_EQ(value, 11); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  012  ", &value, &err)); | ||||
|   EXPECT_EQ(value, 12); | ||||
| 
 | ||||
|   // Invalid values.
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("  ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("0xFFFFFFFFFFFFFFFFFF", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("-1", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("2U", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestFloatParsing) { | ||||
|   std::string err; | ||||
|   float value; | ||||
| 
 | ||||
|   // Ordinary values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("1.3", &value, &err)); | ||||
|   EXPECT_FLOAT_EQ(value, 1.3f); | ||||
|   EXPECT_TRUE(absl::ParseFlag("-0.1", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, -0.1f); | ||||
|   EXPECT_TRUE(absl::ParseFlag("+0.01", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 0.01f); | ||||
| 
 | ||||
|   // Scientific values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("1.2e3", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 1.2e3f); | ||||
|   EXPECT_TRUE(absl::ParseFlag("9.8765402e-37", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 9.8765402e-37f); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0.11e+3", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 0.11e+3f); | ||||
|   EXPECT_TRUE(absl::ParseFlag("1.e-2300", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 0.f); | ||||
|   EXPECT_TRUE(absl::ParseFlag("1.e+2300", &value, &err)); | ||||
|   EXPECT_TRUE(std::isinf(value)); | ||||
| 
 | ||||
|   // Leading zero values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("01.6", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 1.6f); | ||||
|   EXPECT_TRUE(absl::ParseFlag("000.0001", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 0.0001f); | ||||
| 
 | ||||
|   // Trailing zero values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("-5.1000", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, -5.1f); | ||||
| 
 | ||||
|   // Exceptional values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("NaN", &value, &err)); | ||||
|   EXPECT_TRUE(std::isnan(value)); | ||||
|   EXPECT_TRUE(absl::ParseFlag("Inf", &value, &err)); | ||||
|   EXPECT_TRUE(std::isinf(value)); | ||||
| 
 | ||||
|   // Hex values
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("0x10.23p12", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 66096.f); | ||||
|   EXPECT_TRUE(absl::ParseFlag("-0xF1.A3p-2", &value, &err)); | ||||
|   EXPECT_NEAR(value, -60.4092f, 5e-5f); | ||||
|   EXPECT_TRUE(absl::ParseFlag("+0x0.0AAp-12", &value, &err)); | ||||
|   EXPECT_NEAR(value, 1.01328e-05f, 5e-11f); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0x.01p1", &value, &err)); | ||||
|   EXPECT_NEAR(value, 0.0078125f, 5e-8f); | ||||
| 
 | ||||
|   // Whitespace handling
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("10.1  ", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 10.1f); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  2.34", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 2.34f); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  5.7  ", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 5.7f); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  -0xE0.F3p01  ", &value, &err)); | ||||
|   EXPECT_NEAR(value, -449.8984375f, 5e-8f); | ||||
| 
 | ||||
|   // Invalid values.
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("  ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("2.3xxx", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("0x0.1pAA", &value, &err)); | ||||
|   // TODO(rogeeff): below assertion should fail
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("0x0.1", &value, &err)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestDoubleParsing) { | ||||
|   std::string err; | ||||
|   double value; | ||||
| 
 | ||||
|   // Ordinary values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("1.3", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 1.3); | ||||
|   EXPECT_TRUE(absl::ParseFlag("-0.1", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, -0.1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("+0.01", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 0.01); | ||||
| 
 | ||||
|   // Scientific values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("1.2e3", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 1.2e3); | ||||
|   EXPECT_TRUE(absl::ParseFlag("9.00000002e-123", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 9.00000002e-123); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0.11e+3", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 0.11e+3); | ||||
|   EXPECT_TRUE(absl::ParseFlag("1.e-2300", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 0); | ||||
|   EXPECT_TRUE(absl::ParseFlag("1.e+2300", &value, &err)); | ||||
|   EXPECT_TRUE(std::isinf(value)); | ||||
| 
 | ||||
|   // Leading zero values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("01.6", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 1.6); | ||||
|   EXPECT_TRUE(absl::ParseFlag("000.0001", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 0.0001); | ||||
| 
 | ||||
|   // Trailing zero values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("-5.1000", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, -5.1); | ||||
| 
 | ||||
|   // Exceptional values.
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("NaN", &value, &err)); | ||||
|   EXPECT_TRUE(std::isnan(value)); | ||||
|   EXPECT_TRUE(absl::ParseFlag("nan", &value, &err)); | ||||
|   EXPECT_TRUE(std::isnan(value)); | ||||
|   EXPECT_TRUE(absl::ParseFlag("Inf", &value, &err)); | ||||
|   EXPECT_TRUE(std::isinf(value)); | ||||
|   EXPECT_TRUE(absl::ParseFlag("inf", &value, &err)); | ||||
|   EXPECT_TRUE(std::isinf(value)); | ||||
| 
 | ||||
|   // Hex values
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("0x10.23p12", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 66096); | ||||
|   EXPECT_TRUE(absl::ParseFlag("-0xF1.A3p-2", &value, &err)); | ||||
|   EXPECT_NEAR(value, -60.4092, 5e-5); | ||||
|   EXPECT_TRUE(absl::ParseFlag("+0x0.0AAp-12", &value, &err)); | ||||
|   EXPECT_NEAR(value, 1.01328e-05, 5e-11); | ||||
|   EXPECT_TRUE(absl::ParseFlag("0x.01p1", &value, &err)); | ||||
|   EXPECT_NEAR(value, 0.0078125, 5e-8); | ||||
| 
 | ||||
|   // Whitespace handling
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("10.1  ", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 10.1); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  2.34", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 2.34); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  5.7  ", &value, &err)); | ||||
|   EXPECT_DOUBLE_EQ(value, 5.7); | ||||
|   EXPECT_TRUE(absl::ParseFlag("  -0xE0.F3p01  ", &value, &err)); | ||||
|   EXPECT_NEAR(value, -449.8984375, 5e-8); | ||||
| 
 | ||||
|   // Invalid values.
 | ||||
|   EXPECT_FALSE(absl::ParseFlag("", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("  ", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("2.3xxx", &value, &err)); | ||||
|   EXPECT_FALSE(absl::ParseFlag("0x0.1pAA", &value, &err)); | ||||
|   // TODO(rogeeff): below assertion should fail
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("0x0.1", &value, &err)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestStringParsing) { | ||||
|   std::string err; | ||||
|   std::string value; | ||||
| 
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("", &value, &err)); | ||||
|   EXPECT_EQ(value, ""); | ||||
|   EXPECT_TRUE(absl::ParseFlag(" ", &value, &err)); | ||||
|   EXPECT_EQ(value, " "); | ||||
|   EXPECT_TRUE(absl::ParseFlag("   ", &value, &err)); | ||||
|   EXPECT_EQ(value, "   "); | ||||
|   EXPECT_TRUE(absl::ParseFlag("\n", &value, &err)); | ||||
|   EXPECT_EQ(value, "\n"); | ||||
|   EXPECT_TRUE(absl::ParseFlag("\t", &value, &err)); | ||||
|   EXPECT_EQ(value, "\t"); | ||||
|   EXPECT_TRUE(absl::ParseFlag("asdfg", &value, &err)); | ||||
|   EXPECT_EQ(value, "asdfg"); | ||||
|   EXPECT_TRUE(absl::ParseFlag("asdf ghjk", &value, &err)); | ||||
|   EXPECT_EQ(value, "asdf ghjk"); | ||||
|   EXPECT_TRUE(absl::ParseFlag("a\nb\nc", &value, &err)); | ||||
|   EXPECT_EQ(value, "a\nb\nc"); | ||||
|   EXPECT_TRUE(absl::ParseFlag("asd\0fgh", &value, &err)); | ||||
|   EXPECT_EQ(value, "asd"); | ||||
|   EXPECT_TRUE(absl::ParseFlag("\\\\", &value, &err)); | ||||
|   EXPECT_EQ(value, "\\\\"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestVectorOfStringParsing) { | ||||
|   std::string err; | ||||
|   std::vector<std::string> value; | ||||
| 
 | ||||
|   EXPECT_TRUE(absl::ParseFlag("", &value, &err)); | ||||
|   EXPECT_EQ(value, std::vector<std::string>{}); | ||||
|   EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); | ||||
|   EXPECT_EQ(value, std::vector<std::string>({"1"})); | ||||
|   EXPECT_TRUE(absl::ParseFlag("a,b", &value, &err)); | ||||
|   EXPECT_EQ(value, std::vector<std::string>({"a", "b"})); | ||||
|   EXPECT_TRUE(absl::ParseFlag("a,b,c,", &value, &err)); | ||||
|   EXPECT_EQ(value, std::vector<std::string>({"a", "b", "c", ""})); | ||||
|   EXPECT_TRUE(absl::ParseFlag("a,,", &value, &err)); | ||||
|   EXPECT_EQ(value, std::vector<std::string>({"a", "", ""})); | ||||
|   EXPECT_TRUE(absl::ParseFlag(",", &value, &err)); | ||||
|   EXPECT_EQ(value, std::vector<std::string>({"", ""})); | ||||
|   EXPECT_TRUE(absl::ParseFlag("a, b,c ", &value, &err)); | ||||
|   EXPECT_EQ(value, std::vector<std::string>({"a", " b", "c "})); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestBoolUnparsing) { | ||||
|   EXPECT_EQ(absl::UnparseFlag(true), "true"); | ||||
|   EXPECT_EQ(absl::UnparseFlag(false), "false"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestInt16Unparsing) { | ||||
|   int16_t value; | ||||
| 
 | ||||
|   value = 1; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "1"); | ||||
|   value = 0; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "0"); | ||||
|   value = -1; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "-1"); | ||||
|   value = 9876; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "9876"); | ||||
|   value = -987; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "-987"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestUint16Unparsing) { | ||||
|   uint16_t value; | ||||
| 
 | ||||
|   value = 1; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "1"); | ||||
|   value = 0; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "0"); | ||||
|   value = 19876; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "19876"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestInt32Unparsing) { | ||||
|   int32_t value; | ||||
| 
 | ||||
|   value = 1; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "1"); | ||||
|   value = 0; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "0"); | ||||
|   value = -1; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "-1"); | ||||
|   value = 12345; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "12345"); | ||||
|   value = -987; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "-987"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestUint32Unparsing) { | ||||
|   uint32_t value; | ||||
| 
 | ||||
|   value = 1; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "1"); | ||||
|   value = 0; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "0"); | ||||
|   value = 1234500; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "1234500"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestInt64Unparsing) { | ||||
|   int64_t value; | ||||
| 
 | ||||
|   value = 1; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "1"); | ||||
|   value = 0; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "0"); | ||||
|   value = -1; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "-1"); | ||||
|   value = 123456789L; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "123456789"); | ||||
|   value = -987654321L; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "-987654321"); | ||||
|   value = 0x7FFFFFFFFFFFFFFF; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "9223372036854775807"); | ||||
|   value = 0xFFFFFFFFFFFFFFFF; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "-1"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestUint64Unparsing) { | ||||
|   uint64_t value; | ||||
| 
 | ||||
|   value = 1; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "1"); | ||||
|   value = 0; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "0"); | ||||
|   value = 123456789L; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "123456789"); | ||||
|   value = 0xFFFFFFFFFFFFFFFF; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "18446744073709551615"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestFloatUnparsing) { | ||||
|   float value; | ||||
| 
 | ||||
|   value = 1.1f; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "1.1"); | ||||
|   value = 0.01f; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "0.01"); | ||||
|   value = 1.23e-2f; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "0.0123"); | ||||
|   value = -0.71f; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "-0.71"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestDoubleUnparsing) { | ||||
|   double value; | ||||
| 
 | ||||
|   value = 1.1; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "1.1"); | ||||
|   value = 0.01; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "0.01"); | ||||
|   value = 1.23e-2; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "0.0123"); | ||||
|   value = -0.71; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "-0.71"); | ||||
|   value = -0; | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "0"); | ||||
|   value = std::nan(""); | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "nan"); | ||||
|   value = std::numeric_limits<double>::infinity(); | ||||
|   EXPECT_EQ(absl::UnparseFlag(value), "inf"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST(MarshallingTest, TestStringUnparsing) { | ||||
|   EXPECT_EQ(absl::UnparseFlag(""), ""); | ||||
|   EXPECT_EQ(absl::UnparseFlag(" "), " "); | ||||
|   EXPECT_EQ(absl::UnparseFlag("qwerty"), "qwerty"); | ||||
|   EXPECT_EQ(absl::UnparseFlag("ASDFGH"), "ASDFGH"); | ||||
|   EXPECT_EQ(absl::UnparseFlag("\n\t  "), "\n\t  "); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| template <typename T> | ||||
| void TestRoundtrip(T v) { | ||||
|   T new_v; | ||||
|   std::string err; | ||||
|   EXPECT_TRUE(absl::ParseFlag(absl::UnparseFlag(v), &new_v, &err)); | ||||
|   EXPECT_EQ(new_v, v); | ||||
| } | ||||
| 
 | ||||
| TEST(MarshallingTest, TestFloatRoundTrip) { | ||||
|   TestRoundtrip(0.1f); | ||||
|   TestRoundtrip(0.12f); | ||||
|   TestRoundtrip(0.123f); | ||||
|   TestRoundtrip(0.1234f); | ||||
|   TestRoundtrip(0.12345f); | ||||
|   TestRoundtrip(0.123456f); | ||||
|   TestRoundtrip(0.1234567f); | ||||
|   TestRoundtrip(0.12345678f); | ||||
| 
 | ||||
|   TestRoundtrip(0.1e20f); | ||||
|   TestRoundtrip(0.12e20f); | ||||
|   TestRoundtrip(0.123e20f); | ||||
|   TestRoundtrip(0.1234e20f); | ||||
|   TestRoundtrip(0.12345e20f); | ||||
|   TestRoundtrip(0.123456e20f); | ||||
|   TestRoundtrip(0.1234567e20f); | ||||
|   TestRoundtrip(0.12345678e20f); | ||||
| 
 | ||||
|   TestRoundtrip(0.1e-20f); | ||||
|   TestRoundtrip(0.12e-20f); | ||||
|   TestRoundtrip(0.123e-20f); | ||||
|   TestRoundtrip(0.1234e-20f); | ||||
|   TestRoundtrip(0.12345e-20f); | ||||
|   TestRoundtrip(0.123456e-20f); | ||||
|   TestRoundtrip(0.1234567e-20f); | ||||
|   TestRoundtrip(0.12345678e-20f); | ||||
| } | ||||
| 
 | ||||
| TEST(MarshallingTest, TestDoubleRoundTrip) { | ||||
|   TestRoundtrip(0.1); | ||||
|   TestRoundtrip(0.12); | ||||
|   TestRoundtrip(0.123); | ||||
|   TestRoundtrip(0.1234); | ||||
|   TestRoundtrip(0.12345); | ||||
|   TestRoundtrip(0.123456); | ||||
|   TestRoundtrip(0.1234567); | ||||
|   TestRoundtrip(0.12345678); | ||||
|   TestRoundtrip(0.123456789); | ||||
|   TestRoundtrip(0.1234567891); | ||||
|   TestRoundtrip(0.12345678912); | ||||
|   TestRoundtrip(0.123456789123); | ||||
|   TestRoundtrip(0.1234567891234); | ||||
|   TestRoundtrip(0.12345678912345); | ||||
|   TestRoundtrip(0.123456789123456); | ||||
|   TestRoundtrip(0.1234567891234567); | ||||
|   TestRoundtrip(0.12345678912345678); | ||||
| 
 | ||||
|   TestRoundtrip(0.1e50); | ||||
|   TestRoundtrip(0.12e50); | ||||
|   TestRoundtrip(0.123e50); | ||||
|   TestRoundtrip(0.1234e50); | ||||
|   TestRoundtrip(0.12345e50); | ||||
|   TestRoundtrip(0.123456e50); | ||||
|   TestRoundtrip(0.1234567e50); | ||||
|   TestRoundtrip(0.12345678e50); | ||||
|   TestRoundtrip(0.123456789e50); | ||||
|   TestRoundtrip(0.1234567891e50); | ||||
|   TestRoundtrip(0.12345678912e50); | ||||
|   TestRoundtrip(0.123456789123e50); | ||||
|   TestRoundtrip(0.1234567891234e50); | ||||
|   TestRoundtrip(0.12345678912345e50); | ||||
|   TestRoundtrip(0.123456789123456e50); | ||||
|   TestRoundtrip(0.1234567891234567e50); | ||||
|   TestRoundtrip(0.12345678912345678e50); | ||||
| 
 | ||||
|   TestRoundtrip(0.1e-50); | ||||
|   TestRoundtrip(0.12e-50); | ||||
|   TestRoundtrip(0.123e-50); | ||||
|   TestRoundtrip(0.1234e-50); | ||||
|   TestRoundtrip(0.12345e-50); | ||||
|   TestRoundtrip(0.123456e-50); | ||||
|   TestRoundtrip(0.1234567e-50); | ||||
|   TestRoundtrip(0.12345678e-50); | ||||
|   TestRoundtrip(0.123456789e-50); | ||||
|   TestRoundtrip(0.1234567891e-50); | ||||
|   TestRoundtrip(0.12345678912e-50); | ||||
|   TestRoundtrip(0.123456789123e-50); | ||||
|   TestRoundtrip(0.1234567891234e-50); | ||||
|   TestRoundtrip(0.12345678912345e-50); | ||||
|   TestRoundtrip(0.123456789123456e-50); | ||||
|   TestRoundtrip(0.1234567891234567e-50); | ||||
|   TestRoundtrip(0.12345678912345678e-50); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
							
								
								
									
										811
									
								
								third_party/abseil_cpp/absl/flags/parse.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										811
									
								
								third_party/abseil_cpp/absl/flags/parse.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,811 @@ | |||
| //
 | ||||
| // Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/parse.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <iterator> | ||||
| #include <string> | ||||
| #include <tuple> | ||||
| #include <utility> | ||||
| #include <vector> | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #include <windows.h> | ||||
| #endif | ||||
| 
 | ||||
| #include "absl/base/attributes.h" | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/base/const_init.h" | ||||
| #include "absl/base/thread_annotations.h" | ||||
| #include "absl/flags/config.h" | ||||
| #include "absl/flags/flag.h" | ||||
| #include "absl/flags/internal/commandlineflag.h" | ||||
| #include "absl/flags/internal/flag.h" | ||||
| #include "absl/flags/internal/parse.h" | ||||
| #include "absl/flags/internal/private_handle_accessor.h" | ||||
| #include "absl/flags/internal/program_name.h" | ||||
| #include "absl/flags/internal/registry.h" | ||||
| #include "absl/flags/internal/usage.h" | ||||
| #include "absl/flags/usage.h" | ||||
| #include "absl/flags/usage_config.h" | ||||
| #include "absl/strings/ascii.h" | ||||
| #include "absl/strings/str_cat.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| #include "absl/strings/strip.h" | ||||
| #include "absl/synchronization/mutex.h" | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| namespace { | ||||
| 
 | ||||
| ABSL_CONST_INIT absl::Mutex processing_checks_guard(absl::kConstInit); | ||||
| 
 | ||||
| ABSL_CONST_INIT bool flagfile_needs_processing | ||||
|     ABSL_GUARDED_BY(processing_checks_guard) = false; | ||||
| ABSL_CONST_INIT bool fromenv_needs_processing | ||||
|     ABSL_GUARDED_BY(processing_checks_guard) = false; | ||||
| ABSL_CONST_INIT bool tryfromenv_needs_processing | ||||
|     ABSL_GUARDED_BY(processing_checks_guard) = false; | ||||
| 
 | ||||
| ABSL_CONST_INIT absl::Mutex specified_flags_guard(absl::kConstInit); | ||||
| ABSL_CONST_INIT std::vector<const CommandLineFlag*>* specified_flags | ||||
|     ABSL_GUARDED_BY(specified_flags_guard) = nullptr; | ||||
| 
 | ||||
| struct SpecifiedFlagsCompare { | ||||
|   bool operator()(const CommandLineFlag* a, const CommandLineFlag* b) const { | ||||
|     return a->Name() < b->Name(); | ||||
|   } | ||||
|   bool operator()(const CommandLineFlag* a, absl::string_view b) const { | ||||
|     return a->Name() < b; | ||||
|   } | ||||
|   bool operator()(absl::string_view a, const CommandLineFlag* b) const { | ||||
|     return a < b->Name(); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| }  // namespace
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| ABSL_FLAG(std::vector<std::string>, flagfile, {}, | ||||
|           "comma-separated list of files to load flags from") | ||||
|     .OnUpdate([]() { | ||||
|       if (absl::GetFlag(FLAGS_flagfile).empty()) return; | ||||
| 
 | ||||
|       absl::MutexLock l(&absl::flags_internal::processing_checks_guard); | ||||
| 
 | ||||
|       // Setting this flag twice before it is handled most likely an internal
 | ||||
|       // error and should be reviewed by developers.
 | ||||
|       if (absl::flags_internal::flagfile_needs_processing) { | ||||
|         ABSL_INTERNAL_LOG(WARNING, "flagfile set twice before it is handled"); | ||||
|       } | ||||
| 
 | ||||
|       absl::flags_internal::flagfile_needs_processing = true; | ||||
|     }); | ||||
| ABSL_FLAG(std::vector<std::string>, fromenv, {}, | ||||
|           "comma-separated list of flags to set from the environment" | ||||
|           " [use 'export FLAGS_flag1=value']") | ||||
|     .OnUpdate([]() { | ||||
|       if (absl::GetFlag(FLAGS_fromenv).empty()) return; | ||||
| 
 | ||||
|       absl::MutexLock l(&absl::flags_internal::processing_checks_guard); | ||||
| 
 | ||||
|       // Setting this flag twice before it is handled most likely an internal
 | ||||
|       // error and should be reviewed by developers.
 | ||||
|       if (absl::flags_internal::fromenv_needs_processing) { | ||||
|         ABSL_INTERNAL_LOG(WARNING, "fromenv set twice before it is handled."); | ||||
|       } | ||||
| 
 | ||||
|       absl::flags_internal::fromenv_needs_processing = true; | ||||
|     }); | ||||
| ABSL_FLAG(std::vector<std::string>, tryfromenv, {}, | ||||
|           "comma-separated list of flags to try to set from the environment if " | ||||
|           "present") | ||||
|     .OnUpdate([]() { | ||||
|       if (absl::GetFlag(FLAGS_tryfromenv).empty()) return; | ||||
| 
 | ||||
|       absl::MutexLock l(&absl::flags_internal::processing_checks_guard); | ||||
| 
 | ||||
|       // Setting this flag twice before it is handled most likely an internal
 | ||||
|       // error and should be reviewed by developers.
 | ||||
|       if (absl::flags_internal::tryfromenv_needs_processing) { | ||||
|         ABSL_INTERNAL_LOG(WARNING, | ||||
|                           "tryfromenv set twice before it is handled."); | ||||
|       } | ||||
| 
 | ||||
|       absl::flags_internal::tryfromenv_needs_processing = true; | ||||
|     }); | ||||
| 
 | ||||
| ABSL_FLAG(std::vector<std::string>, undefok, {}, | ||||
|           "comma-separated list of flag names that it is okay to specify " | ||||
|           "on the command line even if the program does not define a flag " | ||||
|           "with that name"); | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| class ArgsList { | ||||
|  public: | ||||
|   ArgsList() : next_arg_(0) {} | ||||
|   ArgsList(int argc, char* argv[]) : args_(argv, argv + argc), next_arg_(0) {} | ||||
|   explicit ArgsList(const std::vector<std::string>& args) | ||||
|       : args_(args), next_arg_(0) {} | ||||
| 
 | ||||
|   // Returns success status: true if parsing successful, false otherwise.
 | ||||
|   bool ReadFromFlagfile(const std::string& flag_file_name); | ||||
| 
 | ||||
|   int Size() const { return args_.size() - next_arg_; } | ||||
|   int FrontIndex() const { return next_arg_; } | ||||
|   absl::string_view Front() const { return args_[next_arg_]; } | ||||
|   void PopFront() { next_arg_++; } | ||||
| 
 | ||||
|  private: | ||||
|   std::vector<std::string> args_; | ||||
|   int next_arg_; | ||||
| }; | ||||
| 
 | ||||
| bool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) { | ||||
|   std::ifstream flag_file(flag_file_name); | ||||
| 
 | ||||
|   if (!flag_file) { | ||||
|     flags_internal::ReportUsageError( | ||||
|         absl::StrCat("Can't open flagfile ", flag_file_name), true); | ||||
| 
 | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   // This argument represents fake argv[0], which should be present in all arg
 | ||||
|   // lists.
 | ||||
|   args_.push_back(""); | ||||
| 
 | ||||
|   std::string line; | ||||
|   bool success = true; | ||||
| 
 | ||||
|   while (std::getline(flag_file, line)) { | ||||
|     absl::string_view stripped = absl::StripLeadingAsciiWhitespace(line); | ||||
| 
 | ||||
|     if (stripped.empty() || stripped[0] == '#') { | ||||
|       // Comment or empty line; just ignore.
 | ||||
|       continue; | ||||
|     } | ||||
| 
 | ||||
|     if (stripped[0] == '-') { | ||||
|       if (stripped == "--") { | ||||
|         flags_internal::ReportUsageError( | ||||
|             "Flagfile can't contain position arguments or --", true); | ||||
| 
 | ||||
|         success = false; | ||||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       args_.push_back(std::string(stripped)); | ||||
|       continue; | ||||
|     } | ||||
| 
 | ||||
|     flags_internal::ReportUsageError( | ||||
|         absl::StrCat("Unexpected line in the flagfile ", flag_file_name, ": ", | ||||
|                      line), | ||||
|         true); | ||||
| 
 | ||||
|     success = false; | ||||
|   } | ||||
| 
 | ||||
|   return success; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| // Reads the environment variable with name `name` and stores results in
 | ||||
| // `value`. If variable is not present in environment returns false, otherwise
 | ||||
| // returns true.
 | ||||
| bool GetEnvVar(const char* var_name, std::string* var_value) { | ||||
| #ifdef _WIN32 | ||||
|   char buf[1024]; | ||||
|   auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf)); | ||||
|   if (get_res >= sizeof(buf)) { | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   if (get_res == 0) { | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   *var_value = std::string(buf, get_res); | ||||
| #else | ||||
|   const char* val = ::getenv(var_name); | ||||
|   if (val == nullptr) { | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   *var_value = val; | ||||
| #endif | ||||
| 
 | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| // Returns:
 | ||||
| //  Flag name or empty if arg= --
 | ||||
| //  Flag value after = in --flag=value (empty if --foo)
 | ||||
| //  "Is empty value" status. True if arg= --foo=, false otherwise. This is
 | ||||
| //  required to separate --foo from --foo=.
 | ||||
| // For example:
 | ||||
| //      arg           return values
 | ||||
| //   "--foo=bar" -> {"foo", "bar", false}.
 | ||||
| //   "--foo"     -> {"foo", "", false}.
 | ||||
| //   "--foo="    -> {"foo", "", true}.
 | ||||
| std::tuple<absl::string_view, absl::string_view, bool> SplitNameAndValue( | ||||
|     absl::string_view arg) { | ||||
|   // Allow -foo and --foo
 | ||||
|   absl::ConsumePrefix(&arg, "-"); | ||||
| 
 | ||||
|   if (arg.empty()) { | ||||
|     return std::make_tuple("", "", false); | ||||
|   } | ||||
| 
 | ||||
|   auto equal_sign_pos = arg.find("="); | ||||
| 
 | ||||
|   absl::string_view flag_name = arg.substr(0, equal_sign_pos); | ||||
| 
 | ||||
|   absl::string_view value; | ||||
|   bool is_empty_value = false; | ||||
| 
 | ||||
|   if (equal_sign_pos != absl::string_view::npos) { | ||||
|     value = arg.substr(equal_sign_pos + 1); | ||||
|     is_empty_value = value.empty(); | ||||
|   } | ||||
| 
 | ||||
|   return std::make_tuple(flag_name, value, is_empty_value); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| // Returns:
 | ||||
| //  found flag or nullptr
 | ||||
| //  is negative in case of --nofoo
 | ||||
| std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) { | ||||
|   CommandLineFlag* flag = flags_internal::FindCommandLineFlag(flag_name); | ||||
|   bool is_negative = false; | ||||
| 
 | ||||
|   if (!flag && absl::ConsumePrefix(&flag_name, "no")) { | ||||
|     flag = flags_internal::FindCommandLineFlag(flag_name); | ||||
|     is_negative = true; | ||||
|   } | ||||
| 
 | ||||
|   return std::make_tuple(flag, is_negative); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| // Verify that default values of typed flags must be convertible to string and
 | ||||
| // back.
 | ||||
| void CheckDefaultValuesParsingRoundtrip() { | ||||
| #ifndef NDEBUG | ||||
|   flags_internal::ForEachFlag([&](CommandLineFlag* flag) { | ||||
|     if (flag->IsRetired()) return; | ||||
| 
 | ||||
| #define ABSL_FLAGS_INTERNAL_IGNORE_TYPE(T, _) \ | ||||
|   if (flag->IsOfType<T>()) return; | ||||
| 
 | ||||
|     ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(ABSL_FLAGS_INTERNAL_IGNORE_TYPE) | ||||
| #undef ABSL_FLAGS_INTERNAL_IGNORE_TYPE | ||||
| 
 | ||||
|     flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip( | ||||
|         *flag); | ||||
|   }); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| // Returns success status, which is true if we successfully read all flag files,
 | ||||
| // in which case new ArgLists are appended to the input_args in a reverse order
 | ||||
| // of file names in the input flagfiles list. This order ensures that flags from
 | ||||
| // the first flagfile in the input list are processed before the second flagfile
 | ||||
| // etc.
 | ||||
| bool ReadFlagfiles(const std::vector<std::string>& flagfiles, | ||||
|                    std::vector<ArgsList>* input_args) { | ||||
|   bool success = true; | ||||
|   for (auto it = flagfiles.rbegin(); it != flagfiles.rend(); ++it) { | ||||
|     ArgsList al; | ||||
| 
 | ||||
|     if (al.ReadFromFlagfile(*it)) { | ||||
|       input_args->push_back(al); | ||||
|     } else { | ||||
|       success = false; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return success; | ||||
| } | ||||
| 
 | ||||
| // Returns success status, which is true if were able to locate all environment
 | ||||
| // variables correctly or if fail_on_absent_in_env is false. The environment
 | ||||
| // variable names are expected to be of the form `FLAGS_<flag_name>`, where
 | ||||
| // `flag_name` is a string from the input flag_names list. If successful we
 | ||||
| // append a single ArgList at the end of the input_args.
 | ||||
| bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names, | ||||
|                       std::vector<ArgsList>* input_args, | ||||
|                       bool fail_on_absent_in_env) { | ||||
|   bool success = true; | ||||
|   std::vector<std::string> args; | ||||
| 
 | ||||
|   // This argument represents fake argv[0], which should be present in all arg
 | ||||
|   // lists.
 | ||||
|   args.push_back(""); | ||||
| 
 | ||||
|   for (const auto& flag_name : flag_names) { | ||||
|     // Avoid infinite recursion.
 | ||||
|     if (flag_name == "fromenv" || flag_name == "tryfromenv") { | ||||
|       flags_internal::ReportUsageError( | ||||
|           absl::StrCat("Infinite recursion on flag ", flag_name), true); | ||||
| 
 | ||||
|       success = false; | ||||
|       continue; | ||||
|     } | ||||
| 
 | ||||
|     const std::string envname = absl::StrCat("FLAGS_", flag_name); | ||||
|     std::string envval; | ||||
|     if (!GetEnvVar(envname.c_str(), &envval)) { | ||||
|       if (fail_on_absent_in_env) { | ||||
|         flags_internal::ReportUsageError( | ||||
|             absl::StrCat(envname, " not found in environment"), true); | ||||
| 
 | ||||
|         success = false; | ||||
|       } | ||||
| 
 | ||||
|       continue; | ||||
|     } | ||||
| 
 | ||||
|     args.push_back(absl::StrCat("--", flag_name, "=", envval)); | ||||
|   } | ||||
| 
 | ||||
|   if (success) { | ||||
|     input_args->emplace_back(args); | ||||
|   } | ||||
| 
 | ||||
|   return success; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| // Returns success status, which is true if were able to handle all generator
 | ||||
| // flags (flagfile, fromenv, tryfromemv) successfully.
 | ||||
| bool HandleGeneratorFlags(std::vector<ArgsList>* input_args, | ||||
|                           std::vector<std::string>* flagfile_value) { | ||||
|   bool success = true; | ||||
| 
 | ||||
|   absl::MutexLock l(&flags_internal::processing_checks_guard); | ||||
| 
 | ||||
|   // flagfile could have been set either on a command line or
 | ||||
|   // programmatically before invoking ParseCommandLine. Note that we do not
 | ||||
|   // actually process arguments specified in the flagfile, but instead
 | ||||
|   // create a secondary arguments list to be processed along with the rest
 | ||||
|   // of the comamnd line arguments. Since we always the process most recently
 | ||||
|   // created list of arguments first, this will result in flagfile argument
 | ||||
|   // being processed before any other argument in the command line. If
 | ||||
|   // FLAGS_flagfile contains more than one file name we create multiple new
 | ||||
|   // levels of arguments in a reverse order of file names. Thus we always
 | ||||
|   // process arguments from first file before arguments containing in a
 | ||||
|   // second file, etc. If flagfile contains another
 | ||||
|   // --flagfile inside of it, it will produce new level of arguments and
 | ||||
|   // processed before the rest of the flagfile. We are also collecting all
 | ||||
|   // flagfiles set on original command line. Unlike the rest of the flags,
 | ||||
|   // this flag can be set multiple times and is expected to be handled
 | ||||
|   // multiple times. We are collecting them all into a single list and set
 | ||||
|   // the value of FLAGS_flagfile to that value at the end of the parsing.
 | ||||
|   if (flags_internal::flagfile_needs_processing) { | ||||
|     auto flagfiles = absl::GetFlag(FLAGS_flagfile); | ||||
| 
 | ||||
|     if (input_args->size() == 1) { | ||||
|       flagfile_value->insert(flagfile_value->end(), flagfiles.begin(), | ||||
|                              flagfiles.end()); | ||||
|     } | ||||
| 
 | ||||
|     success &= ReadFlagfiles(flagfiles, input_args); | ||||
| 
 | ||||
|     flags_internal::flagfile_needs_processing = false; | ||||
|   } | ||||
| 
 | ||||
|   // Similar to flagfile fromenv/tryfromemv can be set both
 | ||||
|   // programmatically and at runtime on a command line. Unlike flagfile these
 | ||||
|   // can't be recursive.
 | ||||
|   if (flags_internal::fromenv_needs_processing) { | ||||
|     auto flags_list = absl::GetFlag(FLAGS_fromenv); | ||||
| 
 | ||||
|     success &= ReadFlagsFromEnv(flags_list, input_args, true); | ||||
| 
 | ||||
|     flags_internal::fromenv_needs_processing = false; | ||||
|   } | ||||
| 
 | ||||
|   if (flags_internal::tryfromenv_needs_processing) { | ||||
|     auto flags_list = absl::GetFlag(FLAGS_tryfromenv); | ||||
| 
 | ||||
|     success &= ReadFlagsFromEnv(flags_list, input_args, false); | ||||
| 
 | ||||
|     flags_internal::tryfromenv_needs_processing = false; | ||||
|   } | ||||
| 
 | ||||
|   return success; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| void ResetGeneratorFlags(const std::vector<std::string>& flagfile_value) { | ||||
|   // Setting flagfile to the value which collates all the values set on a
 | ||||
|   // command line and programmatically. So if command line looked like
 | ||||
|   // --flagfile=f1 --flagfile=f2 the final value of the FLAGS_flagfile flag is
 | ||||
|   // going to be {"f1", "f2"}
 | ||||
|   if (!flagfile_value.empty()) { | ||||
|     absl::SetFlag(&FLAGS_flagfile, flagfile_value); | ||||
|     absl::MutexLock l(&flags_internal::processing_checks_guard); | ||||
|     flags_internal::flagfile_needs_processing = false; | ||||
|   } | ||||
| 
 | ||||
|   // fromenv/tryfromenv are set to <undefined> value.
 | ||||
|   if (!absl::GetFlag(FLAGS_fromenv).empty()) { | ||||
|     absl::SetFlag(&FLAGS_fromenv, {}); | ||||
|   } | ||||
|   if (!absl::GetFlag(FLAGS_tryfromenv).empty()) { | ||||
|     absl::SetFlag(&FLAGS_tryfromenv, {}); | ||||
|   } | ||||
| 
 | ||||
|   absl::MutexLock l(&flags_internal::processing_checks_guard); | ||||
|   flags_internal::fromenv_needs_processing = false; | ||||
|   flags_internal::tryfromenv_needs_processing = false; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| // Returns:
 | ||||
| //  success status
 | ||||
| //  deduced value
 | ||||
| // We are also mutating curr_list in case if we need to get a hold of next
 | ||||
| // argument in the input.
 | ||||
| std::tuple<bool, absl::string_view> DeduceFlagValue(const CommandLineFlag& flag, | ||||
|                                                     absl::string_view value, | ||||
|                                                     bool is_negative, | ||||
|                                                     bool is_empty_value, | ||||
|                                                     ArgsList* curr_list) { | ||||
|   // Value is either an argument suffix after `=` in "--foo=<value>"
 | ||||
|   // or separate argument in case of "--foo" "<value>".
 | ||||
| 
 | ||||
|   // boolean flags have these forms:
 | ||||
|   //   --foo
 | ||||
|   //   --nofoo
 | ||||
|   //   --foo=true
 | ||||
|   //   --foo=false
 | ||||
|   //   --nofoo=<value> is not supported
 | ||||
|   //   --foo <value> is not supported
 | ||||
| 
 | ||||
|   // non boolean flags have these forms:
 | ||||
|   // --foo=<value>
 | ||||
|   // --foo <value>
 | ||||
|   // --nofoo is not supported
 | ||||
| 
 | ||||
|   if (flag.IsOfType<bool>()) { | ||||
|     if (value.empty()) { | ||||
|       if (is_empty_value) { | ||||
|         // "--bool_flag=" case
 | ||||
|         flags_internal::ReportUsageError( | ||||
|             absl::StrCat( | ||||
|                 "Missing the value after assignment for the boolean flag '", | ||||
|                 flag.Name(), "'"), | ||||
|             true); | ||||
|         return std::make_tuple(false, ""); | ||||
|       } | ||||
| 
 | ||||
|       // "--bool_flag" case
 | ||||
|       value = is_negative ? "0" : "1"; | ||||
|     } else if (is_negative) { | ||||
|       // "--nobool_flag=Y" case
 | ||||
|       flags_internal::ReportUsageError( | ||||
|           absl::StrCat("Negative form with assignment is not valid for the " | ||||
|                        "boolean flag '", | ||||
|                        flag.Name(), "'"), | ||||
|           true); | ||||
|       return std::make_tuple(false, ""); | ||||
|     } | ||||
|   } else if (is_negative) { | ||||
|     // "--noint_flag=1" case
 | ||||
|     flags_internal::ReportUsageError( | ||||
|         absl::StrCat("Negative form is not valid for the flag '", flag.Name(), | ||||
|                      "'"), | ||||
|         true); | ||||
|     return std::make_tuple(false, ""); | ||||
|   } else if (value.empty() && (!is_empty_value)) { | ||||
|     if (curr_list->Size() == 1) { | ||||
|       // "--int_flag" case
 | ||||
|       flags_internal::ReportUsageError( | ||||
|           absl::StrCat("Missing the value for the flag '", flag.Name(), "'"), | ||||
|           true); | ||||
|       return std::make_tuple(false, ""); | ||||
|     } | ||||
| 
 | ||||
|     // "--int_flag" "10" case
 | ||||
|     curr_list->PopFront(); | ||||
|     value = curr_list->Front(); | ||||
| 
 | ||||
|     // Heuristic to detect the case where someone treats a string arg
 | ||||
|     // like a bool or just forgets to pass a value:
 | ||||
|     // --my_string_var --foo=bar
 | ||||
|     // We look for a flag of string type, whose value begins with a
 | ||||
|     // dash and corresponds to known flag or standalone --.
 | ||||
|     if (!value.empty() && value[0] == '-' && flag.IsOfType<std::string>()) { | ||||
|       auto maybe_flag_name = std::get<0>(SplitNameAndValue(value.substr(1))); | ||||
| 
 | ||||
|       if (maybe_flag_name.empty() || | ||||
|           std::get<0>(LocateFlag(maybe_flag_name)) != nullptr) { | ||||
|         // "--string_flag" "--known_flag" case
 | ||||
|         ABSL_INTERNAL_LOG( | ||||
|             WARNING, | ||||
|             absl::StrCat("Did you really mean to set flag '", flag.Name(), | ||||
|                          "' to the value '", value, "'?")); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return std::make_tuple(true, value); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| bool CanIgnoreUndefinedFlag(absl::string_view flag_name) { | ||||
|   auto undefok = absl::GetFlag(FLAGS_undefok); | ||||
|   if (std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) { | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   if (absl::ConsumePrefix(&flag_name, "no") && | ||||
|       std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) { | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| bool WasPresentOnCommandLine(absl::string_view flag_name) { | ||||
|   absl::MutexLock l(&specified_flags_guard); | ||||
|   ABSL_INTERNAL_CHECK(specified_flags != nullptr, | ||||
|                       "ParseCommandLine is not invoked yet"); | ||||
| 
 | ||||
|   return std::binary_search(specified_flags->begin(), specified_flags->end(), | ||||
|                             flag_name, SpecifiedFlagsCompare{}); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| std::vector<char*> ParseCommandLineImpl(int argc, char* argv[], | ||||
|                                         ArgvListAction arg_list_act, | ||||
|                                         UsageFlagsAction usage_flag_act, | ||||
|                                         OnUndefinedFlag on_undef_flag) { | ||||
|   ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]"); | ||||
| 
 | ||||
|   // This routine does not return anything since we abort on failure.
 | ||||
|   CheckDefaultValuesParsingRoundtrip(); | ||||
| 
 | ||||
|   std::vector<std::string> flagfile_value; | ||||
| 
 | ||||
|   std::vector<ArgsList> input_args; | ||||
|   input_args.push_back(ArgsList(argc, argv)); | ||||
| 
 | ||||
|   std::vector<char*> output_args; | ||||
|   std::vector<char*> positional_args; | ||||
|   output_args.reserve(argc); | ||||
| 
 | ||||
|   // This is the list of undefined flags. The element of the list is the pair
 | ||||
|   // consisting of boolean indicating if flag came from command line (vs from
 | ||||
|   // some flag file we've read) and flag name.
 | ||||
|   // TODO(rogeeff): Eliminate the first element in the pair after cleanup.
 | ||||
|   std::vector<std::pair<bool, std::string>> undefined_flag_names; | ||||
| 
 | ||||
|   // Set program invocation name if it is not set before.
 | ||||
|   if (ProgramInvocationName() == "UNKNOWN") { | ||||
|     flags_internal::SetProgramInvocationName(argv[0]); | ||||
|   } | ||||
|   output_args.push_back(argv[0]); | ||||
| 
 | ||||
|   absl::MutexLock l(&specified_flags_guard); | ||||
|   if (specified_flags == nullptr) { | ||||
|     specified_flags = new std::vector<const CommandLineFlag*>; | ||||
|   } else { | ||||
|     specified_flags->clear(); | ||||
|   } | ||||
| 
 | ||||
|   // Iterate through the list of the input arguments. First level are arguments
 | ||||
|   // originated from argc/argv. Following levels are arguments originated from
 | ||||
|   // recursive parsing of flagfile(s).
 | ||||
|   bool success = true; | ||||
|   while (!input_args.empty()) { | ||||
|     // 10. First we process the built-in generator flags.
 | ||||
|     success &= HandleGeneratorFlags(&input_args, &flagfile_value); | ||||
| 
 | ||||
|     // 30. Select top-most (most recent) arguments list. If it is empty drop it
 | ||||
|     // and re-try.
 | ||||
|     ArgsList& curr_list = input_args.back(); | ||||
| 
 | ||||
|     curr_list.PopFront(); | ||||
| 
 | ||||
|     if (curr_list.Size() == 0) { | ||||
|       input_args.pop_back(); | ||||
|       continue; | ||||
|     } | ||||
| 
 | ||||
|     // 40. Pick up the front remaining argument in the current list. If current
 | ||||
|     // stack of argument lists contains only one element - we are processing an
 | ||||
|     // argument from the original argv.
 | ||||
|     absl::string_view arg(curr_list.Front()); | ||||
|     bool arg_from_argv = input_args.size() == 1; | ||||
| 
 | ||||
|     // 50. If argument does not start with - or is just "-" - this is
 | ||||
|     // positional argument.
 | ||||
|     if (!absl::ConsumePrefix(&arg, "-") || arg.empty()) { | ||||
|       ABSL_INTERNAL_CHECK(arg_from_argv, | ||||
|                           "Flagfile cannot contain positional argument"); | ||||
| 
 | ||||
|       positional_args.push_back(argv[curr_list.FrontIndex()]); | ||||
|       continue; | ||||
|     } | ||||
| 
 | ||||
|     if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs)) { | ||||
|       output_args.push_back(argv[curr_list.FrontIndex()]); | ||||
|     } | ||||
| 
 | ||||
|     // 60. Split the current argument on '=' to figure out the argument
 | ||||
|     // name and value. If flag name is empty it means we've got "--". value
 | ||||
|     // can be empty either if there were no '=' in argument string at all or
 | ||||
|     // an argument looked like "--foo=". In a latter case is_empty_value is
 | ||||
|     // true.
 | ||||
|     absl::string_view flag_name; | ||||
|     absl::string_view value; | ||||
|     bool is_empty_value = false; | ||||
| 
 | ||||
|     std::tie(flag_name, value, is_empty_value) = SplitNameAndValue(arg); | ||||
| 
 | ||||
|     // 70. "--" alone means what it does for GNU: stop flags parsing. We do
 | ||||
|     // not support positional arguments in flagfiles, so we just drop them.
 | ||||
|     if (flag_name.empty()) { | ||||
|       ABSL_INTERNAL_CHECK(arg_from_argv, | ||||
|                           "Flagfile cannot contain positional argument"); | ||||
| 
 | ||||
|       curr_list.PopFront(); | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
|     // 80. Locate the flag based on flag name. Handle both --foo and --nofoo
 | ||||
|     CommandLineFlag* flag = nullptr; | ||||
|     bool is_negative = false; | ||||
|     std::tie(flag, is_negative) = LocateFlag(flag_name); | ||||
| 
 | ||||
|     if (flag == nullptr) { | ||||
|       if (on_undef_flag != OnUndefinedFlag::kIgnoreUndefined) { | ||||
|         undefined_flag_names.emplace_back(arg_from_argv, | ||||
|                                           std::string(flag_name)); | ||||
|       } | ||||
|       continue; | ||||
|     } | ||||
| 
 | ||||
|     // 90. Deduce flag's value (from this or next argument)
 | ||||
|     auto curr_index = curr_list.FrontIndex(); | ||||
|     bool value_success = true; | ||||
|     std::tie(value_success, value) = | ||||
|         DeduceFlagValue(*flag, value, is_negative, is_empty_value, &curr_list); | ||||
|     success &= value_success; | ||||
| 
 | ||||
|     // If above call consumed an argument, it was a standalone value
 | ||||
|     if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs) && | ||||
|         (curr_index != curr_list.FrontIndex())) { | ||||
|       output_args.push_back(argv[curr_list.FrontIndex()]); | ||||
|     } | ||||
| 
 | ||||
|     // 100. Set the located flag to a new new value, unless it is retired.
 | ||||
|     // Setting retired flag fails, but we ignoring it here.
 | ||||
|     if (flag->IsRetired()) continue; | ||||
| 
 | ||||
|     std::string error; | ||||
|     if (!flags_internal::PrivateHandleAccessor::ParseFrom( | ||||
|             flag, value, SET_FLAGS_VALUE, kCommandLine, &error)) { | ||||
|       flags_internal::ReportUsageError(error, true); | ||||
|       success = false; | ||||
|     } else { | ||||
|       specified_flags->push_back(flag); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   for (const auto& flag_name : undefined_flag_names) { | ||||
|     if (CanIgnoreUndefinedFlag(flag_name.second)) continue; | ||||
| 
 | ||||
|     flags_internal::ReportUsageError( | ||||
|         absl::StrCat("Unknown command line flag '", flag_name.second, "'"), | ||||
|         true); | ||||
| 
 | ||||
|     success = false; | ||||
|   } | ||||
| 
 | ||||
| #if ABSL_FLAGS_STRIP_NAMES | ||||
|   if (!success) { | ||||
|     flags_internal::ReportUsageError( | ||||
|         "NOTE: command line flags are disabled in this build", true); | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
|   if (!success) { | ||||
|     flags_internal::HandleUsageFlags(std::cout, | ||||
|                                      ProgramUsageMessage()); | ||||
|     std::exit(1); | ||||
|   } | ||||
| 
 | ||||
|   if (usage_flag_act == UsageFlagsAction::kHandleUsage) { | ||||
|     int exit_code = flags_internal::HandleUsageFlags( | ||||
|         std::cout, ProgramUsageMessage()); | ||||
| 
 | ||||
|     if (exit_code != -1) { | ||||
|       std::exit(exit_code); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ResetGeneratorFlags(flagfile_value); | ||||
| 
 | ||||
|   // Reinstate positional args which were intermixed with flags in the arguments
 | ||||
|   // list.
 | ||||
|   for (auto arg : positional_args) { | ||||
|     output_args.push_back(arg); | ||||
|   } | ||||
| 
 | ||||
|   // All the remaining arguments are positional.
 | ||||
|   if (!input_args.empty()) { | ||||
|     for (int arg_index = input_args.back().FrontIndex(); arg_index < argc; | ||||
|          ++arg_index) { | ||||
|       output_args.push_back(argv[arg_index]); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // Trim and sort the vector.
 | ||||
|   specified_flags->shrink_to_fit(); | ||||
|   std::sort(specified_flags->begin(), specified_flags->end(), | ||||
|             SpecifiedFlagsCompare{}); | ||||
|   return output_args; | ||||
| } | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| std::vector<char*> ParseCommandLine(int argc, char* argv[]) { | ||||
|   return flags_internal::ParseCommandLineImpl( | ||||
|       argc, argv, flags_internal::ArgvListAction::kRemoveParsedArgs, | ||||
|       flags_internal::UsageFlagsAction::kHandleUsage, | ||||
|       flags_internal::OnUndefinedFlag::kAbortIfUndefined); | ||||
| } | ||||
| 
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
							
								
								
									
										61
									
								
								third_party/abseil_cpp/absl/flags/parse.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								third_party/abseil_cpp/absl/flags/parse.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | |||
| //
 | ||||
| // Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| //
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| // File: parse.h
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| //
 | ||||
| // This file defines the main parsing function for Abseil flags:
 | ||||
| // `absl::ParseCommandLine()`.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_PARSE_H_ | ||||
| #define ABSL_FLAGS_PARSE_H_ | ||||
| 
 | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/flags/internal/parse.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| 
 | ||||
| // ParseCommandLine()
 | ||||
| //
 | ||||
| // Parses the set of command-line arguments passed in the `argc` (argument
 | ||||
| // count) and `argv[]` (argument vector) parameters from `main()`, assigning
 | ||||
| // values to any defined Abseil flags. (Any arguments passed after the
 | ||||
| // flag-terminating delimiter (`--`) are treated as positional arguments and
 | ||||
| // ignored.)
 | ||||
| //
 | ||||
| // Any command-line flags (and arguments to those flags) are parsed into Abseil
 | ||||
| // Flag values, if those flags are defined. Any undefined flags will either
 | ||||
| // return an error, or be ignored if that flag is designated using `undefok` to
 | ||||
| // indicate "undefined is OK."
 | ||||
| //
 | ||||
| // Any command-line positional arguments not part of any command-line flag (or
 | ||||
| // arguments to a flag) are returned in a vector, with the program invocation
 | ||||
| // name at position 0 of that vector. (Note that this includes positional
 | ||||
| // arguments after the flag-terminating delimiter `--`.)
 | ||||
| //
 | ||||
| // After all flags and flag arguments are parsed, this function looks for any
 | ||||
| // built-in usage flags (e.g. `--help`), and if any were specified, it reports
 | ||||
| // help messages and then exits the program.
 | ||||
| std::vector<char*> ParseCommandLine(int argc, char* argv[]); | ||||
| 
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_PARSE_H_
 | ||||
							
								
								
									
										894
									
								
								third_party/abseil_cpp/absl/flags/parse_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										894
									
								
								third_party/abseil_cpp/absl/flags/parse_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,894 @@ | |||
| //
 | ||||
| // Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/parse.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include <fstream> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "gmock/gmock.h" | ||||
| #include "gtest/gtest.h" | ||||
| #include "absl/base/internal/raw_logging.h" | ||||
| #include "absl/base/internal/scoped_set_env.h" | ||||
| #include "absl/flags/declare.h" | ||||
| #include "absl/flags/flag.h" | ||||
| #include "absl/flags/internal/parse.h" | ||||
| #include "absl/flags/internal/registry.h" | ||||
| #include "absl/strings/str_cat.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| #include "absl/strings/substitute.h" | ||||
| #include "absl/types/span.h" | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #include <windows.h> | ||||
| #endif | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| using absl::base_internal::ScopedSetEnv; | ||||
| 
 | ||||
| struct UDT { | ||||
|   UDT() = default; | ||||
|   UDT(const UDT&) = default; | ||||
|   UDT(int v) : value(v) {}  // NOLINT
 | ||||
| 
 | ||||
|   int value; | ||||
| }; | ||||
| 
 | ||||
| bool AbslParseFlag(absl::string_view in, UDT* udt, std::string* err) { | ||||
|   if (in == "A") { | ||||
|     udt->value = 1; | ||||
|     return true; | ||||
|   } | ||||
|   if (in == "AAA") { | ||||
|     udt->value = 10; | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   *err = "Use values A, AAA instead"; | ||||
|   return false; | ||||
| } | ||||
| std::string AbslUnparseFlag(const UDT& udt) { | ||||
|   return udt.value == 1 ? "A" : "AAA"; | ||||
| } | ||||
| 
 | ||||
| std::string GetTestTmpDirEnvVar(const char* const env_var_name) { | ||||
| #ifdef _WIN32 | ||||
|   char buf[MAX_PATH]; | ||||
|   auto get_res = GetEnvironmentVariableA(env_var_name, buf, sizeof(buf)); | ||||
|   if (get_res >= sizeof(buf) || get_res == 0) { | ||||
|     return ""; | ||||
|   } | ||||
| 
 | ||||
|   return std::string(buf, get_res); | ||||
| #else | ||||
|   const char* val = ::getenv(env_var_name); | ||||
|   if (val == nullptr) { | ||||
|     return ""; | ||||
|   } | ||||
| 
 | ||||
|   return val; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| const std::string& GetTestTempDir() { | ||||
|   static std::string* temp_dir_name = []() -> std::string* { | ||||
|     std::string* res = new std::string(GetTestTmpDirEnvVar("TEST_TMPDIR")); | ||||
| 
 | ||||
|     if (res->empty()) { | ||||
|       *res = GetTestTmpDirEnvVar("TMPDIR"); | ||||
|     } | ||||
| 
 | ||||
|     if (res->empty()) { | ||||
| #ifdef _WIN32 | ||||
|       char temp_path_buffer[MAX_PATH]; | ||||
| 
 | ||||
|       auto len = GetTempPathA(MAX_PATH, temp_path_buffer); | ||||
|       if (len < MAX_PATH && len != 0) { | ||||
|         std::string temp_dir_name = temp_path_buffer; | ||||
|         if (!absl::EndsWith(temp_dir_name, "\\")) { | ||||
|           temp_dir_name.push_back('\\'); | ||||
|         } | ||||
|         absl::StrAppend(&temp_dir_name, "parse_test.", GetCurrentProcessId()); | ||||
|         if (CreateDirectoryA(temp_dir_name.c_str(), nullptr)) { | ||||
|           *res = temp_dir_name; | ||||
|         } | ||||
|       } | ||||
| #else | ||||
|       char temp_dir_template[] = "/tmp/parse_test.XXXXXX"; | ||||
|       if (auto* unique_name = ::mkdtemp(temp_dir_template)) { | ||||
|         *res = unique_name; | ||||
|       } | ||||
| #endif | ||||
|     } | ||||
| 
 | ||||
|     if (res->empty()) { | ||||
|       ABSL_INTERNAL_LOG(FATAL, | ||||
|                         "Failed to make temporary directory for data files"); | ||||
|     } | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|     *res += "\\"; | ||||
| #else | ||||
|     *res += "/"; | ||||
| #endif | ||||
| 
 | ||||
|     return res; | ||||
|   }(); | ||||
| 
 | ||||
|   return *temp_dir_name; | ||||
| } | ||||
| 
 | ||||
| struct FlagfileData { | ||||
|   const absl::string_view file_name; | ||||
|   const absl::Span<const char* const> file_lines; | ||||
| }; | ||||
| 
 | ||||
| // clang-format off
 | ||||
| constexpr const char* const ff1_data[] = { | ||||
|     "# comment    ", | ||||
|     "  # comment  ", | ||||
|     "", | ||||
|     "     ", | ||||
|     "--int_flag=-1", | ||||
|     "  --string_flag=q2w2  ", | ||||
|     "  ##   ", | ||||
|     "  --double_flag=0.1", | ||||
|     "--bool_flag=Y  " | ||||
| }; | ||||
| 
 | ||||
| constexpr const char* const ff2_data[] = { | ||||
|     "# Setting legacy flag", | ||||
|     "--legacy_int=1111", | ||||
|     "--legacy_bool", | ||||
|     "--nobool_flag", | ||||
|     "--legacy_str=aqsw", | ||||
|     "--int_flag=100", | ||||
|     "   ## =============" | ||||
| }; | ||||
| // clang-format on
 | ||||
| 
 | ||||
| // Builds flagfile flag in the flagfile_flag buffer and returns it. This
 | ||||
| // function also creates a temporary flagfile based on FlagfileData input.
 | ||||
| // We create a flagfile in a temporary directory with the name specified in
 | ||||
| // FlagfileData and populate it with lines specifed in FlagfileData. If $0 is
 | ||||
| // referenced in any of the lines in FlagfileData they are replaced with
 | ||||
| // temporary directory location. This way we can test inclusion of one flagfile
 | ||||
| // from another flagfile.
 | ||||
| const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd, | ||||
|                             std::string* flagfile_flag) { | ||||
|   *flagfile_flag = "--flagfile="; | ||||
|   absl::string_view separator; | ||||
|   for (const auto& flagfile_data : ffd) { | ||||
|     std::string flagfile_name = | ||||
|         absl::StrCat(GetTestTempDir(), flagfile_data.file_name); | ||||
| 
 | ||||
|     std::ofstream flagfile_out(flagfile_name); | ||||
|     for (auto line : flagfile_data.file_lines) { | ||||
|       flagfile_out << absl::Substitute(line, GetTestTempDir()) << "\n"; | ||||
|     } | ||||
| 
 | ||||
|     absl::StrAppend(flagfile_flag, separator, flagfile_name); | ||||
|     separator = ","; | ||||
|   } | ||||
| 
 | ||||
|   return flagfile_flag->c_str(); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| ABSL_FLAG(int, int_flag, 1, ""); | ||||
| ABSL_FLAG(double, double_flag, 1.1, ""); | ||||
| ABSL_FLAG(std::string, string_flag, "a", ""); | ||||
| ABSL_FLAG(bool, bool_flag, false, ""); | ||||
| ABSL_FLAG(UDT, udt_flag, -1, ""); | ||||
| ABSL_RETIRED_FLAG(int, legacy_int, 1, ""); | ||||
| ABSL_RETIRED_FLAG(bool, legacy_bool, false, ""); | ||||
| ABSL_RETIRED_FLAG(std::string, legacy_str, "l", ""); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| namespace flags = absl::flags_internal; | ||||
| using testing::ElementsAreArray; | ||||
| 
 | ||||
| class ParseTest : public testing::Test { | ||||
|  private: | ||||
|   flags::FlagSaver flag_saver_; | ||||
| }; | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| template <int N> | ||||
| std::vector<char*> InvokeParse(const char* (&in_argv)[N]) { | ||||
|   return absl::ParseCommandLine(N, const_cast<char**>(in_argv)); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| template <int N> | ||||
| void TestParse(const char* (&in_argv)[N], int int_flag_value, | ||||
|                double double_flag_val, absl::string_view string_flag_val, | ||||
|                bool bool_flag_val, int exp_position_args = 0) { | ||||
|   auto out_args = InvokeParse(in_argv); | ||||
| 
 | ||||
|   EXPECT_EQ(out_args.size(), 1 + exp_position_args); | ||||
|   EXPECT_STREQ(out_args[0], "testbin"); | ||||
| 
 | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), int_flag_value); | ||||
|   EXPECT_NEAR(absl::GetFlag(FLAGS_double_flag), double_flag_val, 0.0001); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), string_flag_val); | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_bool_flag), bool_flag_val); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestEmptyArgv) { | ||||
|   const char* in_argv[] = {"testbin"}; | ||||
| 
 | ||||
|   auto out_args = InvokeParse(in_argv); | ||||
| 
 | ||||
|   EXPECT_EQ(out_args.size(), 1); | ||||
|   EXPECT_STREQ(out_args[0], "testbin"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestValidIntArg) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "--int_flag=10", | ||||
|   }; | ||||
|   TestParse(in_args1, 10, 1.1, "a", false); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       "-int_flag=020", | ||||
|   }; | ||||
|   TestParse(in_args2, 20, 1.1, "a", false); | ||||
| 
 | ||||
|   const char* in_args3[] = { | ||||
|       "testbin", | ||||
|       "--int_flag", | ||||
|       "-30", | ||||
|   }; | ||||
|   TestParse(in_args3, -30, 1.1, "a", false); | ||||
| 
 | ||||
|   const char* in_args4[] = { | ||||
|       "testbin", | ||||
|       "-int_flag", | ||||
|       "0x21", | ||||
|   }; | ||||
|   TestParse(in_args4, 33, 1.1, "a", false); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestValidDoubleArg) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "--double_flag=2.3", | ||||
|   }; | ||||
|   TestParse(in_args1, 1, 2.3, "a", false); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       "--double_flag=0x1.2", | ||||
|   }; | ||||
|   TestParse(in_args2, 1, 1.125, "a", false); | ||||
| 
 | ||||
|   const char* in_args3[] = { | ||||
|       "testbin", | ||||
|       "--double_flag", | ||||
|       "99.7", | ||||
|   }; | ||||
|   TestParse(in_args3, 1, 99.7, "a", false); | ||||
| 
 | ||||
|   const char* in_args4[] = { | ||||
|       "testbin", | ||||
|       "--double_flag", | ||||
|       "0x20.1", | ||||
|   }; | ||||
|   TestParse(in_args4, 1, 32.0625, "a", false); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestValidStringArg) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "--string_flag=aqswde", | ||||
|   }; | ||||
|   TestParse(in_args1, 1, 1.1, "aqswde", false); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       "-string_flag=a=b=c", | ||||
|   }; | ||||
|   TestParse(in_args2, 1, 1.1, "a=b=c", false); | ||||
| 
 | ||||
|   const char* in_args3[] = { | ||||
|       "testbin", | ||||
|       "--string_flag", | ||||
|       "zaxscd", | ||||
|   }; | ||||
|   TestParse(in_args3, 1, 1.1, "zaxscd", false); | ||||
| 
 | ||||
|   const char* in_args4[] = { | ||||
|       "testbin", | ||||
|       "-string_flag", | ||||
|       "--int_flag", | ||||
|   }; | ||||
|   TestParse(in_args4, 1, 1.1, "--int_flag", false); | ||||
| 
 | ||||
|   const char* in_args5[] = { | ||||
|       "testbin", | ||||
|       "--string_flag", | ||||
|       "--no_a_flag=11", | ||||
|   }; | ||||
|   TestParse(in_args5, 1, 1.1, "--no_a_flag=11", false); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestValidBoolArg) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "--bool_flag", | ||||
|   }; | ||||
|   TestParse(in_args1, 1, 1.1, "a", true); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       "--nobool_flag", | ||||
|   }; | ||||
|   TestParse(in_args2, 1, 1.1, "a", false); | ||||
| 
 | ||||
|   const char* in_args3[] = { | ||||
|       "testbin", | ||||
|       "--bool_flag=true", | ||||
|   }; | ||||
|   TestParse(in_args3, 1, 1.1, "a", true); | ||||
| 
 | ||||
|   const char* in_args4[] = { | ||||
|       "testbin", | ||||
|       "-bool_flag=false", | ||||
|   }; | ||||
|   TestParse(in_args4, 1, 1.1, "a", false); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestValidUDTArg) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "--udt_flag=A", | ||||
|   }; | ||||
|   InvokeParse(in_args1); | ||||
| 
 | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 1); | ||||
| 
 | ||||
|   const char* in_args2[] = {"testbin", "--udt_flag", "AAA"}; | ||||
|   InvokeParse(in_args2); | ||||
| 
 | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 10); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestValidMultipleArg) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin",           "--bool_flag",       "--int_flag=2", | ||||
|       "--double_flag=0.1", "--string_flag=asd", | ||||
|   }; | ||||
|   TestParse(in_args1, 2, 0.1, "asd", true); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", "--string_flag=", "--nobool_flag", "--int_flag", | ||||
|       "-011",    "--double_flag",  "-1e-2", | ||||
|   }; | ||||
|   TestParse(in_args2, -11, -0.01, "", false); | ||||
| 
 | ||||
|   const char* in_args3[] = { | ||||
|       "testbin",          "--int_flag",         "-0", "--string_flag", "\"\"", | ||||
|       "--bool_flag=true", "--double_flag=1e18", | ||||
|   }; | ||||
|   TestParse(in_args3, 0, 1e18, "\"\"", true); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestPositionalArgs) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "p1", | ||||
|       "p2", | ||||
|   }; | ||||
|   TestParse(in_args1, 1, 1.1, "a", false, 2); | ||||
| 
 | ||||
|   auto out_args1 = InvokeParse(in_args1); | ||||
| 
 | ||||
|   EXPECT_STREQ(out_args1[1], "p1"); | ||||
|   EXPECT_STREQ(out_args1[2], "p2"); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       "--int_flag=2", | ||||
|       "p1", | ||||
|   }; | ||||
|   TestParse(in_args2, 2, 1.1, "a", false, 1); | ||||
| 
 | ||||
|   auto out_args2 = InvokeParse(in_args2); | ||||
| 
 | ||||
|   EXPECT_STREQ(out_args2[1], "p1"); | ||||
| 
 | ||||
|   const char* in_args3[] = {"testbin", "p1",          "--int_flag=3", | ||||
|                             "p2",      "--bool_flag", "true"}; | ||||
|   TestParse(in_args3, 3, 1.1, "a", true, 3); | ||||
| 
 | ||||
|   auto out_args3 = InvokeParse(in_args3); | ||||
| 
 | ||||
|   EXPECT_STREQ(out_args3[1], "p1"); | ||||
|   EXPECT_STREQ(out_args3[2], "p2"); | ||||
|   EXPECT_STREQ(out_args3[3], "true"); | ||||
| 
 | ||||
|   const char* in_args4[] = { | ||||
|       "testbin", | ||||
|       "--", | ||||
|       "p1", | ||||
|       "p2", | ||||
|   }; | ||||
|   TestParse(in_args4, 3, 1.1, "a", true, 2); | ||||
| 
 | ||||
|   auto out_args4 = InvokeParse(in_args4); | ||||
| 
 | ||||
|   EXPECT_STREQ(out_args4[1], "p1"); | ||||
|   EXPECT_STREQ(out_args4[2], "p2"); | ||||
| 
 | ||||
|   const char* in_args5[] = { | ||||
|       "testbin", "p1", "--int_flag=4", "--", "--bool_flag", "false", "p2", | ||||
|   }; | ||||
|   TestParse(in_args5, 4, 1.1, "a", true, 4); | ||||
| 
 | ||||
|   auto out_args5 = InvokeParse(in_args5); | ||||
| 
 | ||||
|   EXPECT_STREQ(out_args5[1], "p1"); | ||||
|   EXPECT_STREQ(out_args5[2], "--bool_flag"); | ||||
|   EXPECT_STREQ(out_args5[3], "false"); | ||||
|   EXPECT_STREQ(out_args5[4], "p2"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| using ParseDeathTest = ParseTest; | ||||
| 
 | ||||
| TEST_F(ParseDeathTest, TestUndefinedArg) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "--undefined_flag", | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1), | ||||
|                             "Unknown command line flag 'undefined_flag'"); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       "--noprefixed_flag", | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2), | ||||
|                             "Unknown command line flag 'noprefixed_flag'"); | ||||
| 
 | ||||
|   const char* in_args3[] = { | ||||
|       "testbin", | ||||
|       "--Int_flag=1", | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3), | ||||
|                             "Unknown command line flag 'Int_flag'"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseDeathTest, TestInvalidBoolFlagFormat) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "--bool_flag=", | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED( | ||||
|       InvokeParse(in_args1), | ||||
|       "Missing the value after assignment for the boolean flag 'bool_flag'"); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       "--nobool_flag=true", | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2), | ||||
|                "Negative form with assignment is not valid for the boolean " | ||||
|                "flag 'bool_flag'"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseDeathTest, TestInvalidNonBoolFlagFormat) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "--nostring_flag", | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1), | ||||
|                "Negative form is not valid for the flag 'string_flag'"); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       "--int_flag", | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2), | ||||
|                "Missing the value for the flag 'int_flag'"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseDeathTest, TestInvalidUDTFlagFormat) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "--udt_flag=1", | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1), | ||||
|                "Illegal value '1' specified for flag 'udt_flag'; Use values A, " | ||||
|                "AAA instead"); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       "--udt_flag", | ||||
|       "AA", | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2), | ||||
|                "Illegal value 'AA' specified for flag 'udt_flag'; Use values " | ||||
|                "A, AAA instead"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestLegacyFlags) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "--legacy_int=11", | ||||
|   }; | ||||
|   TestParse(in_args1, 1, 1.1, "a", false); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       "--legacy_bool", | ||||
|   }; | ||||
|   TestParse(in_args2, 1, 1.1, "a", false); | ||||
| 
 | ||||
|   const char* in_args3[] = { | ||||
|       "testbin",       "--legacy_int", "22",           "--int_flag=2", | ||||
|       "--legacy_bool", "true",         "--legacy_str", "--string_flag=qwe", | ||||
|   }; | ||||
|   TestParse(in_args3, 2, 1.1, "a", false, 1); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestSimpleValidFlagfile) { | ||||
|   std::string flagfile_flag; | ||||
| 
 | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}}, | ||||
|                       &flagfile_flag), | ||||
|   }; | ||||
|   TestParse(in_args1, -1, 0.1, "q2w2  ", true); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}}, | ||||
|                       &flagfile_flag), | ||||
|   }; | ||||
|   TestParse(in_args2, 100, 0.1, "q2w2  ", false); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestValidMultiFlagfile) { | ||||
|   std::string flagfile_flag; | ||||
| 
 | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}, | ||||
|                        {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}}, | ||||
|                       &flagfile_flag), | ||||
|   }; | ||||
|   TestParse(in_args1, -1, 0.1, "q2w2  ", true); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestFlagfileMixedWithRegularFlags) { | ||||
|   std::string flagfile_flag; | ||||
| 
 | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", "--int_flag=3", | ||||
|       GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}}, | ||||
|                       &flagfile_flag), | ||||
|       "-double_flag=0.2"}; | ||||
|   TestParse(in_args1, -1, 0.2, "q2w2  ", true); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestFlagfileInFlagfile) { | ||||
|   std::string flagfile_flag; | ||||
| 
 | ||||
|   constexpr const char* const ff3_data[] = { | ||||
|       "--flagfile=$0/parse_test.ff1", | ||||
|       "--flagfile=$0/parse_test.ff2", | ||||
|   }; | ||||
| 
 | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       GetFlagfileFlag({{"parse_test.ff3", absl::MakeConstSpan(ff3_data)}}, | ||||
|                       &flagfile_flag), | ||||
|   }; | ||||
|   TestParse(in_args1, 100, 0.1, "q2w2  ", false); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseDeathTest, TestInvalidFlagfiles) { | ||||
|   std::string flagfile_flag; | ||||
| 
 | ||||
|   constexpr const char* const ff4_data[] = { | ||||
|     "--unknown_flag=10" | ||||
|   }; | ||||
| 
 | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       GetFlagfileFlag({{"parse_test.ff4", | ||||
|                         absl::MakeConstSpan(ff4_data)}}, &flagfile_flag), | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1), | ||||
|                "Unknown command line flag 'unknown_flag'"); | ||||
| 
 | ||||
|   constexpr const char* const ff5_data[] = { | ||||
|     "--int_flag 10", | ||||
|   }; | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       GetFlagfileFlag({{"parse_test.ff5", | ||||
|                         absl::MakeConstSpan(ff5_data)}}, &flagfile_flag), | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2), | ||||
|                "Unknown command line flag 'int_flag 10'"); | ||||
| 
 | ||||
|   constexpr const char* const ff6_data[] = { | ||||
|       "--int_flag=10", "--", "arg1", "arg2", "arg3", | ||||
|   }; | ||||
| 
 | ||||
|   const char* in_args3[] = { | ||||
|       "testbin", | ||||
|       GetFlagfileFlag({{"parse_test.ff6", absl::MakeConstSpan(ff6_data)}}, | ||||
|                       &flagfile_flag), | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3), | ||||
|                "Flagfile can't contain position arguments or --"); | ||||
| 
 | ||||
|   const char* in_args4[] = { | ||||
|       "testbin", | ||||
|       "--flagfile=invalid_flag_file", | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args4), | ||||
|                             "Can't open flagfile invalid_flag_file"); | ||||
| 
 | ||||
|   constexpr const char* const ff7_data[] = { | ||||
|       "--int_flag=10", | ||||
|       "*bin*", | ||||
|       "--str_flag=aqsw", | ||||
|   }; | ||||
| 
 | ||||
|   const char* in_args5[] = { | ||||
|       "testbin", | ||||
|       GetFlagfileFlag({{"parse_test.ff7", absl::MakeConstSpan(ff7_data)}}, | ||||
|                       &flagfile_flag), | ||||
|   }; | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args5), | ||||
|                "Unexpected line in the flagfile .*: \\*bin\\*"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestReadingRequiredFlagsFromEnv) { | ||||
|   const char* in_args1[] = {"testbin", | ||||
|                             "--fromenv=int_flag,bool_flag,string_flag"}; | ||||
| 
 | ||||
|   ScopedSetEnv set_int_flag("FLAGS_int_flag", "33"); | ||||
|   ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "True"); | ||||
|   ScopedSetEnv set_string_flag("FLAGS_string_flag", "AQ12"); | ||||
| 
 | ||||
|   TestParse(in_args1, 33, 1.1, "AQ12", true); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseDeathTest, TestReadingUnsetRequiredFlagsFromEnv) { | ||||
|   const char* in_args1[] = {"testbin", "--fromenv=int_flag"}; | ||||
| 
 | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1), | ||||
|                "FLAGS_int_flag not found in environment"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseDeathTest, TestRecursiveFlagsFromEnv) { | ||||
|   const char* in_args1[] = {"testbin", "--fromenv=tryfromenv"}; | ||||
| 
 | ||||
|   ScopedSetEnv set_tryfromenv("FLAGS_tryfromenv", "int_flag"); | ||||
| 
 | ||||
|   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1), | ||||
|                             "Infinite recursion on flag tryfromenv"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestReadingOptionalFlagsFromEnv) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", "--tryfromenv=int_flag,bool_flag,string_flag,other_flag"}; | ||||
| 
 | ||||
|   ScopedSetEnv set_int_flag("FLAGS_int_flag", "17"); | ||||
|   ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "Y"); | ||||
| 
 | ||||
|   TestParse(in_args1, 17, 1.1, "a", true); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestReadingFlagsFromEnvMoxedWithRegularFlags) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "--bool_flag=T", | ||||
|       "--tryfromenv=int_flag,bool_flag", | ||||
|       "--int_flag=-21", | ||||
|   }; | ||||
| 
 | ||||
|   ScopedSetEnv set_int_flag("FLAGS_int_flag", "-15"); | ||||
|   ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "F"); | ||||
| 
 | ||||
|   TestParse(in_args1, -21, 1.1, "a", false); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestKeepParsedArgs) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin",        "arg1", "--bool_flag", | ||||
|       "--int_flag=211", "arg2", "--double_flag=1.1", | ||||
|       "--string_flag",  "asd",  "--", | ||||
|       "arg3",           "arg4", | ||||
|   }; | ||||
| 
 | ||||
|   auto out_args1 = InvokeParse(in_args1); | ||||
| 
 | ||||
|   EXPECT_THAT( | ||||
|       out_args1, | ||||
|       ElementsAreArray({absl::string_view("testbin"), absl::string_view("arg1"), | ||||
|                         absl::string_view("arg2"), absl::string_view("arg3"), | ||||
|                         absl::string_view("arg4")})); | ||||
| 
 | ||||
|   auto out_args2 = flags::ParseCommandLineImpl( | ||||
|       11, const_cast<char**>(in_args1), flags::ArgvListAction::kKeepParsedArgs, | ||||
|       flags::UsageFlagsAction::kHandleUsage, | ||||
|       flags::OnUndefinedFlag::kAbortIfUndefined); | ||||
| 
 | ||||
|   EXPECT_THAT( | ||||
|       out_args2, | ||||
|       ElementsAreArray({absl::string_view("testbin"), | ||||
|                         absl::string_view("--bool_flag"), | ||||
|                         absl::string_view("--int_flag=211"), | ||||
|                         absl::string_view("--double_flag=1.1"), | ||||
|                         absl::string_view("--string_flag"), | ||||
|                         absl::string_view("asd"), absl::string_view("--"), | ||||
|                         absl::string_view("arg1"), absl::string_view("arg2"), | ||||
|                         absl::string_view("arg3"), absl::string_view("arg4")})); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, TestIgnoreUndefinedFlags) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "arg1", | ||||
|       "--undef_flag=aa", | ||||
|       "--int_flag=21", | ||||
|   }; | ||||
| 
 | ||||
|   auto out_args1 = flags::ParseCommandLineImpl( | ||||
|       4, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs, | ||||
|       flags::UsageFlagsAction::kHandleUsage, | ||||
|       flags::OnUndefinedFlag::kIgnoreUndefined); | ||||
| 
 | ||||
|   EXPECT_THAT(out_args1, ElementsAreArray({absl::string_view("testbin"), | ||||
|                                            absl::string_view("arg1")})); | ||||
| 
 | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 21); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       "arg1", | ||||
|       "--undef_flag=aa", | ||||
|       "--string_flag=AA", | ||||
|   }; | ||||
| 
 | ||||
|   auto out_args2 = flags::ParseCommandLineImpl( | ||||
|       4, const_cast<char**>(in_args2), flags::ArgvListAction::kKeepParsedArgs, | ||||
|       flags::UsageFlagsAction::kHandleUsage, | ||||
|       flags::OnUndefinedFlag::kIgnoreUndefined); | ||||
| 
 | ||||
|   EXPECT_THAT( | ||||
|       out_args2, | ||||
|       ElementsAreArray( | ||||
|           {absl::string_view("testbin"), absl::string_view("--undef_flag=aa"), | ||||
|            absl::string_view("--string_flag=AA"), absl::string_view("arg1")})); | ||||
| 
 | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "AA"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseDeathTest, TestHelpFlagHandling) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin", | ||||
|       "--help", | ||||
|   }; | ||||
| 
 | ||||
|   EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(1), ""); | ||||
| 
 | ||||
|   const char* in_args2[] = { | ||||
|       "testbin", | ||||
|       "--help", | ||||
|       "--int_flag=3", | ||||
|   }; | ||||
| 
 | ||||
|   auto out_args2 = flags::ParseCommandLineImpl( | ||||
|       3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs, | ||||
|       flags::UsageFlagsAction::kIgnoreUsage, | ||||
|       flags::OnUndefinedFlag::kAbortIfUndefined); | ||||
| 
 | ||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(ParseTest, WasPresentOnCommandLine) { | ||||
|   const char* in_args1[] = { | ||||
|       "testbin",        "arg1", "--bool_flag", | ||||
|       "--int_flag=211", "arg2", "--double_flag=1.1", | ||||
|       "--string_flag",  "asd",  "--", | ||||
|       "--some_flag",    "arg4", | ||||
|   }; | ||||
| 
 | ||||
|   InvokeParse(in_args1); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::WasPresentOnCommandLine("bool_flag")); | ||||
|   EXPECT_TRUE(flags::WasPresentOnCommandLine("int_flag")); | ||||
|   EXPECT_TRUE(flags::WasPresentOnCommandLine("double_flag")); | ||||
|   EXPECT_TRUE(flags::WasPresentOnCommandLine("string_flag")); | ||||
|   EXPECT_FALSE(flags::WasPresentOnCommandLine("some_flag")); | ||||
|   EXPECT_FALSE(flags::WasPresentOnCommandLine("another_flag")); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| }  // namespace
 | ||||
							
								
								
									
										65
									
								
								third_party/abseil_cpp/absl/flags/usage.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								third_party/abseil_cpp/absl/flags/usage.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,65 @@ | |||
| //
 | ||||
| // Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| #include "absl/flags/usage.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| #include "absl/base/attributes.h" | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/base/const_init.h" | ||||
| #include "absl/base/thread_annotations.h" | ||||
| #include "absl/flags/internal/usage.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| #include "absl/synchronization/mutex.h" | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| namespace { | ||||
| ABSL_CONST_INIT absl::Mutex usage_message_guard(absl::kConstInit); | ||||
| ABSL_CONST_INIT std::string* program_usage_message | ||||
|     ABSL_GUARDED_BY(usage_message_guard) = nullptr; | ||||
| }  // namespace
 | ||||
| }  // namespace flags_internal
 | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Sets the "usage" message to be used by help reporting routines.
 | ||||
| void SetProgramUsageMessage(absl::string_view new_usage_message) { | ||||
|   absl::MutexLock l(&flags_internal::usage_message_guard); | ||||
| 
 | ||||
|   if (flags_internal::program_usage_message != nullptr) { | ||||
|     ABSL_INTERNAL_LOG(FATAL, "SetProgramUsageMessage() called twice."); | ||||
|     std::exit(1); | ||||
|   } | ||||
| 
 | ||||
|   flags_internal::program_usage_message = new std::string(new_usage_message); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Returns the usage message set by SetProgramUsageMessage().
 | ||||
| // Note: We able to return string_view here only because calling
 | ||||
| // SetProgramUsageMessage twice is prohibited.
 | ||||
| absl::string_view ProgramUsageMessage() { | ||||
|   absl::MutexLock l(&flags_internal::usage_message_guard); | ||||
| 
 | ||||
|   return flags_internal::program_usage_message != nullptr | ||||
|              ? absl::string_view(*flags_internal::program_usage_message) | ||||
|              : "Warning: SetProgramUsageMessage() never called"; | ||||
| } | ||||
| 
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
							
								
								
									
										43
									
								
								third_party/abseil_cpp/absl/flags/usage.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								third_party/abseil_cpp/absl/flags/usage.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #ifndef ABSL_FLAGS_USAGE_H_ | ||||
| #define ABSL_FLAGS_USAGE_H_ | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Usage reporting interfaces
 | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| 
 | ||||
| // Sets the "usage" message to be used by help reporting routines.
 | ||||
| // For example:
 | ||||
| //  absl::SetProgramUsageMessage(
 | ||||
| //      absl::StrCat("This program does nothing.  Sample usage:\n", argv[0],
 | ||||
| //                   " <uselessarg1> <uselessarg2>"));
 | ||||
| // Do not include commandline flags in the usage: we do that for you!
 | ||||
| // Note: Calling SetProgramUsageMessage twice will trigger a call to std::exit.
 | ||||
| void SetProgramUsageMessage(absl::string_view new_usage_message); | ||||
| 
 | ||||
| // Returns the usage message set by SetProgramUsageMessage().
 | ||||
| absl::string_view ProgramUsageMessage(); | ||||
| 
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_USAGE_H_
 | ||||
							
								
								
									
										163
									
								
								third_party/abseil_cpp/absl/flags/usage_config.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								third_party/abseil_cpp/absl/flags/usage_config.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,163 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/usage_config.h" | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <string> | ||||
| 
 | ||||
| #include "absl/base/attributes.h" | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/base/const_init.h" | ||||
| #include "absl/base/thread_annotations.h" | ||||
| #include "absl/flags/internal/path_util.h" | ||||
| #include "absl/flags/internal/program_name.h" | ||||
| #include "absl/strings/match.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| #include "absl/strings/strip.h" | ||||
| #include "absl/synchronization/mutex.h" | ||||
| 
 | ||||
| extern "C" { | ||||
| 
 | ||||
| // Additional report of fatal usage error message before we std::exit. Error is
 | ||||
| // fatal if is_fatal argument to ReportUsageError is true.
 | ||||
| ABSL_ATTRIBUTE_WEAK void AbslInternalReportFatalUsageError(absl::string_view) {} | ||||
| 
 | ||||
| }  // extern "C"
 | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Returns true if flags defined in the filename should be reported with
 | ||||
| // -helpshort flag.
 | ||||
| 
 | ||||
| bool ContainsHelpshortFlags(absl::string_view filename) { | ||||
|   // By default we only want flags in binary's main. We expect the main
 | ||||
|   // routine to reside in <program>.cc or <program>-main.cc or
 | ||||
|   // <program>_main.cc, where the <program> is the name of the binary
 | ||||
|   // (without .exe on Windows).
 | ||||
|   auto suffix = flags_internal::Basename(filename); | ||||
|   auto program_name = flags_internal::ShortProgramInvocationName(); | ||||
|   absl::string_view program_name_ref = program_name; | ||||
| #if defined(_WIN32) | ||||
|   absl::ConsumeSuffix(&program_name_ref, ".exe"); | ||||
| #endif | ||||
|   if (!absl::ConsumePrefix(&suffix, program_name_ref)) | ||||
|     return false; | ||||
|   return absl::StartsWith(suffix, ".") || absl::StartsWith(suffix, "-main.") || | ||||
|          absl::StartsWith(suffix, "_main."); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Returns true if flags defined in the filename should be reported with
 | ||||
| // -helppackage flag.
 | ||||
| 
 | ||||
| bool ContainsHelppackageFlags(absl::string_view filename) { | ||||
|   // TODO(rogeeff): implement properly when registry is available.
 | ||||
|   return ContainsHelpshortFlags(filename); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Generates program version information into supplied output.
 | ||||
| 
 | ||||
| std::string VersionString() { | ||||
|   std::string version_str(flags_internal::ShortProgramInvocationName()); | ||||
| 
 | ||||
|   version_str += "\n"; | ||||
| 
 | ||||
| #if !defined(NDEBUG) | ||||
|   version_str += "Debug build (NDEBUG not #defined)\n"; | ||||
| #endif | ||||
| 
 | ||||
|   return version_str; | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| // Normalizes the filename specific to the build system/filesystem used.
 | ||||
| 
 | ||||
| std::string NormalizeFilename(absl::string_view filename) { | ||||
|   // Skip any leading slashes
 | ||||
|   auto pos = filename.find_first_not_of("\\/"); | ||||
|   if (pos == absl::string_view::npos) return ""; | ||||
| 
 | ||||
|   filename.remove_prefix(pos); | ||||
|   return std::string(filename); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| ABSL_CONST_INIT absl::Mutex custom_usage_config_guard(absl::kConstInit); | ||||
| ABSL_CONST_INIT FlagsUsageConfig* custom_usage_config | ||||
|     ABSL_GUARDED_BY(custom_usage_config_guard) = nullptr; | ||||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| FlagsUsageConfig GetUsageConfig() { | ||||
|   absl::MutexLock l(&custom_usage_config_guard); | ||||
| 
 | ||||
|   if (custom_usage_config) return *custom_usage_config; | ||||
| 
 | ||||
|   FlagsUsageConfig default_config; | ||||
|   default_config.contains_helpshort_flags = &ContainsHelpshortFlags; | ||||
|   default_config.contains_help_flags = &ContainsHelppackageFlags; | ||||
|   default_config.contains_helppackage_flags = &ContainsHelppackageFlags; | ||||
|   default_config.version_string = &VersionString; | ||||
|   default_config.normalize_filename = &NormalizeFilename; | ||||
| 
 | ||||
|   return default_config; | ||||
| } | ||||
| 
 | ||||
| void ReportUsageError(absl::string_view msg, bool is_fatal) { | ||||
|   std::cerr << "ERROR: " << msg << std::endl; | ||||
| 
 | ||||
|   if (is_fatal) { | ||||
|     AbslInternalReportFatalUsageError(msg); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| 
 | ||||
| void SetFlagsUsageConfig(FlagsUsageConfig usage_config) { | ||||
|   absl::MutexLock l(&flags_internal::custom_usage_config_guard); | ||||
| 
 | ||||
|   if (!usage_config.contains_helpshort_flags) | ||||
|     usage_config.contains_helpshort_flags = | ||||
|         flags_internal::ContainsHelpshortFlags; | ||||
| 
 | ||||
|   if (!usage_config.contains_help_flags) | ||||
|     usage_config.contains_help_flags = flags_internal::ContainsHelppackageFlags; | ||||
| 
 | ||||
|   if (!usage_config.contains_helppackage_flags) | ||||
|     usage_config.contains_helppackage_flags = | ||||
|         flags_internal::ContainsHelppackageFlags; | ||||
| 
 | ||||
|   if (!usage_config.version_string) | ||||
|     usage_config.version_string = flags_internal::VersionString; | ||||
| 
 | ||||
|   if (!usage_config.normalize_filename) | ||||
|     usage_config.normalize_filename = flags_internal::NormalizeFilename; | ||||
| 
 | ||||
|   if (flags_internal::custom_usage_config) | ||||
|     *flags_internal::custom_usage_config = usage_config; | ||||
|   else | ||||
|     flags_internal::custom_usage_config = new FlagsUsageConfig(usage_config); | ||||
| } | ||||
| 
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
							
								
								
									
										134
									
								
								third_party/abseil_cpp/absl/flags/usage_config.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								third_party/abseil_cpp/absl/flags/usage_config.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,134 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| //
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| // File: usage_config.h
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| //
 | ||||
| // This file defines the main usage reporting configuration interfaces and
 | ||||
| // documents Abseil's supported built-in usage flags. If these flags are found
 | ||||
| // when parsing a command-line, Abseil will exit the program and display
 | ||||
| // appropriate help messages.
 | ||||
| #ifndef ABSL_FLAGS_USAGE_CONFIG_H_ | ||||
| #define ABSL_FLAGS_USAGE_CONFIG_H_ | ||||
| 
 | ||||
| #include <functional> | ||||
| #include <string> | ||||
| 
 | ||||
| #include "absl/base/config.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| // Built-in Usage Flags
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| //
 | ||||
| // Abseil supports the following built-in usage flags. When passed, these flags
 | ||||
| // exit the program and :
 | ||||
| //
 | ||||
| // * --help
 | ||||
| //     Shows help on important flags for this binary
 | ||||
| // * --helpfull
 | ||||
| //     Shows help on all flags
 | ||||
| // * --helpshort
 | ||||
| //     Shows help on only the main module for this program
 | ||||
| // * --helppackage
 | ||||
| //     Shows help on all modules in the main package
 | ||||
| // * --version
 | ||||
| //     Shows the version and build info for this binary and exits
 | ||||
| // * --only_check_args
 | ||||
| //     Exits after checking all flags
 | ||||
| // * --helpon
 | ||||
| //     Shows help on the modules named by this flag value
 | ||||
| // * --helpmatch
 | ||||
| //     Shows help on modules whose name contains the specified substring
 | ||||
| 
 | ||||
| namespace absl { | ||||
| ABSL_NAMESPACE_BEGIN | ||||
| 
 | ||||
| namespace flags_internal { | ||||
| using FlagKindFilter = std::function<bool (absl::string_view)>; | ||||
| }  // namespace flags_internal
 | ||||
| 
 | ||||
| // FlagsUsageConfig
 | ||||
| //
 | ||||
| // This structure contains the collection of callbacks for changing the behavior
 | ||||
| // of the usage reporting routines in Abseil Flags.
 | ||||
| struct FlagsUsageConfig { | ||||
|   // Returns true if flags defined in the given source code file should be
 | ||||
|   // reported with --helpshort flag. For example, if the file
 | ||||
|   // "path/to/my/code.cc" defines the flag "--my_flag", and
 | ||||
|   // contains_helpshort_flags("path/to/my/code.cc") returns true, invoking the
 | ||||
|   // program with --helpshort will include information about --my_flag in the
 | ||||
|   // program output.
 | ||||
|   flags_internal::FlagKindFilter contains_helpshort_flags; | ||||
| 
 | ||||
|   // Returns true if flags defined in the filename should be reported with
 | ||||
|   // --help flag. For example, if the file
 | ||||
|   // "path/to/my/code.cc" defines the flag "--my_flag", and
 | ||||
|   // contains_help_flags("path/to/my/code.cc") returns true, invoking the
 | ||||
|   // program with --help will include information about --my_flag in the
 | ||||
|   // program output.
 | ||||
|   flags_internal::FlagKindFilter contains_help_flags; | ||||
| 
 | ||||
|   // Returns true if flags defined in the filename should be reported with
 | ||||
|   // --helppackage flag. For example, if the file
 | ||||
|   // "path/to/my/code.cc" defines the flag "--my_flag", and
 | ||||
|   // contains_helppackage_flags("path/to/my/code.cc") returns true, invoking the
 | ||||
|   // program with --helppackage will include information about --my_flag in the
 | ||||
|   // program output.
 | ||||
|   flags_internal::FlagKindFilter contains_helppackage_flags; | ||||
| 
 | ||||
|   // Generates string containing program version. This is the string reported
 | ||||
|   // when user specifies --version in a command line.
 | ||||
|   std::function<std::string()> version_string; | ||||
| 
 | ||||
|   // Normalizes the filename specific to the build system/filesystem used. This
 | ||||
|   // routine is used when we report the information about the flag definition
 | ||||
|   // location. For instance, if your build resides at some location you do not
 | ||||
|   // want to expose in the usage output, you can trim it to show only relevant
 | ||||
|   // part.
 | ||||
|   // For example:
 | ||||
|   //   normalize_filename("/my_company/some_long_path/src/project/file.cc")
 | ||||
|   // might produce
 | ||||
|   //   "project/file.cc".
 | ||||
|   std::function<std::string(absl::string_view)> normalize_filename; | ||||
| }; | ||||
| 
 | ||||
| // SetFlagsUsageConfig()
 | ||||
| //
 | ||||
| // Sets the usage reporting configuration callbacks. If any of the callbacks are
 | ||||
| // not set in usage_config instance, then the default value of the callback is
 | ||||
| // used.
 | ||||
| void SetFlagsUsageConfig(FlagsUsageConfig usage_config); | ||||
| 
 | ||||
| namespace flags_internal { | ||||
| 
 | ||||
| FlagsUsageConfig GetUsageConfig(); | ||||
| 
 | ||||
| void ReportUsageError(absl::string_view msg, bool is_fatal); | ||||
| 
 | ||||
| }  // namespace flags_internal
 | ||||
| ABSL_NAMESPACE_END | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| extern "C" { | ||||
| 
 | ||||
| // Additional report of fatal usage error message before we std::exit. Error is
 | ||||
| // fatal if is_fatal argument to ReportUsageError is true.
 | ||||
| void AbslInternalReportFatalUsageError(absl::string_view); | ||||
| 
 | ||||
| }  // extern "C"
 | ||||
| 
 | ||||
| #endif  // ABSL_FLAGS_USAGE_CONFIG_H_
 | ||||
							
								
								
									
										205
									
								
								third_party/abseil_cpp/absl/flags/usage_config_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								third_party/abseil_cpp/absl/flags/usage_config_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,205 @@ | |||
| //
 | ||||
| //  Copyright 2019 The Abseil Authors.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //      https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "absl/flags/usage_config.h" | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| #include "gtest/gtest.h" | ||||
| #include "absl/flags/internal/path_util.h" | ||||
| #include "absl/flags/internal/program_name.h" | ||||
| #include "absl/strings/match.h" | ||||
| #include "absl/strings/string_view.h" | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| class FlagsUsageConfigTest : public testing::Test { | ||||
|  protected: | ||||
|   void SetUp() override { | ||||
|     // Install Default config for the use on this unit test.
 | ||||
|     // Binary may install a custom config before tests are run.
 | ||||
|     absl::FlagsUsageConfig default_config; | ||||
|     absl::SetFlagsUsageConfig(default_config); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| namespace flags = absl::flags_internal; | ||||
| 
 | ||||
| bool TstContainsHelpshortFlags(absl::string_view f) { | ||||
|   return absl::StartsWith(flags::Basename(f), "progname."); | ||||
| } | ||||
| 
 | ||||
| bool TstContainsHelppackageFlags(absl::string_view f) { | ||||
|   return absl::EndsWith(flags::Package(f), "aaa/"); | ||||
| } | ||||
| 
 | ||||
| bool TstContainsHelpFlags(absl::string_view f) { | ||||
|   return absl::EndsWith(flags::Package(f), "zzz/"); | ||||
| } | ||||
| 
 | ||||
| std::string TstVersionString() { return "program 1.0.0"; } | ||||
| 
 | ||||
| std::string TstNormalizeFilename(absl::string_view filename) { | ||||
|   return std::string(filename.substr(2)); | ||||
| } | ||||
| 
 | ||||
| void TstReportUsageMessage(absl::string_view msg) {} | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(FlagsUsageConfigTest, TestGetSetFlagsUsageConfig) { | ||||
|   EXPECT_TRUE(flags::GetUsageConfig().contains_helpshort_flags); | ||||
|   EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags); | ||||
|   EXPECT_TRUE(flags::GetUsageConfig().contains_helppackage_flags); | ||||
|   EXPECT_TRUE(flags::GetUsageConfig().version_string); | ||||
|   EXPECT_TRUE(flags::GetUsageConfig().normalize_filename); | ||||
| 
 | ||||
|   absl::FlagsUsageConfig empty_config; | ||||
|   empty_config.contains_helpshort_flags = &TstContainsHelpshortFlags; | ||||
|   empty_config.contains_help_flags = &TstContainsHelpFlags; | ||||
|   empty_config.contains_helppackage_flags = &TstContainsHelppackageFlags; | ||||
|   empty_config.version_string = &TstVersionString; | ||||
|   empty_config.normalize_filename = &TstNormalizeFilename; | ||||
|   absl::SetFlagsUsageConfig(empty_config); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::GetUsageConfig().contains_helpshort_flags); | ||||
|   EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags); | ||||
|   EXPECT_TRUE(flags::GetUsageConfig().contains_helppackage_flags); | ||||
|   EXPECT_TRUE(flags::GetUsageConfig().version_string); | ||||
|   EXPECT_TRUE(flags::GetUsageConfig().normalize_filename); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(FlagsUsageConfigTest, TestContainsHelpshortFlags) { | ||||
| #if defined(_WIN32) | ||||
|   flags::SetProgramInvocationName("usage_config_test.exe"); | ||||
| #else | ||||
|   flags::SetProgramInvocationName("usage_config_test"); | ||||
| #endif | ||||
| 
 | ||||
|   auto config = flags::GetUsageConfig(); | ||||
|   EXPECT_TRUE(config.contains_helpshort_flags("adir/cd/usage_config_test.cc")); | ||||
|   EXPECT_TRUE( | ||||
|       config.contains_helpshort_flags("aaaa/usage_config_test-main.cc")); | ||||
|   EXPECT_TRUE(config.contains_helpshort_flags("abc/usage_config_test_main.cc")); | ||||
|   EXPECT_FALSE(config.contains_helpshort_flags("usage_config_main.cc")); | ||||
| 
 | ||||
|   absl::FlagsUsageConfig empty_config; | ||||
|   empty_config.contains_helpshort_flags = &TstContainsHelpshortFlags; | ||||
|   absl::SetFlagsUsageConfig(empty_config); | ||||
| 
 | ||||
|   EXPECT_TRUE( | ||||
|       flags::GetUsageConfig().contains_helpshort_flags("aaa/progname.cpp")); | ||||
|   EXPECT_FALSE( | ||||
|       flags::GetUsageConfig().contains_helpshort_flags("aaa/progmane.cpp")); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(FlagsUsageConfigTest, TestContainsHelpFlags) { | ||||
|   flags::SetProgramInvocationName("usage_config_test"); | ||||
| 
 | ||||
|   auto config = flags::GetUsageConfig(); | ||||
|   EXPECT_TRUE(config.contains_help_flags("zzz/usage_config_test.cc")); | ||||
|   EXPECT_TRUE( | ||||
|       config.contains_help_flags("bdir/a/zzz/usage_config_test-main.cc")); | ||||
|   EXPECT_TRUE( | ||||
|       config.contains_help_flags("//aqse/zzz/usage_config_test_main.cc")); | ||||
|   EXPECT_FALSE(config.contains_help_flags("zzz/aa/usage_config_main.cc")); | ||||
| 
 | ||||
|   absl::FlagsUsageConfig empty_config; | ||||
|   empty_config.contains_help_flags = &TstContainsHelpFlags; | ||||
|   absl::SetFlagsUsageConfig(empty_config); | ||||
| 
 | ||||
|   EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags("zzz/main-body.c")); | ||||
|   EXPECT_FALSE( | ||||
|       flags::GetUsageConfig().contains_help_flags("zzz/dir/main-body.c")); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(FlagsUsageConfigTest, TestContainsHelppackageFlags) { | ||||
|   flags::SetProgramInvocationName("usage_config_test"); | ||||
| 
 | ||||
|   auto config = flags::GetUsageConfig(); | ||||
|   EXPECT_TRUE(config.contains_helppackage_flags("aaa/usage_config_test.cc")); | ||||
|   EXPECT_TRUE( | ||||
|       config.contains_helppackage_flags("bbdir/aaa/usage_config_test-main.cc")); | ||||
|   EXPECT_TRUE(config.contains_helppackage_flags( | ||||
|       "//aqswde/aaa/usage_config_test_main.cc")); | ||||
|   EXPECT_FALSE(config.contains_helppackage_flags("aadir/usage_config_main.cc")); | ||||
| 
 | ||||
|   absl::FlagsUsageConfig empty_config; | ||||
|   empty_config.contains_helppackage_flags = &TstContainsHelppackageFlags; | ||||
|   absl::SetFlagsUsageConfig(empty_config); | ||||
| 
 | ||||
|   EXPECT_TRUE( | ||||
|       flags::GetUsageConfig().contains_helppackage_flags("aaa/main-body.c")); | ||||
|   EXPECT_FALSE( | ||||
|       flags::GetUsageConfig().contains_helppackage_flags("aadir/main-body.c")); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(FlagsUsageConfigTest, TestVersionString) { | ||||
|   flags::SetProgramInvocationName("usage_config_test"); | ||||
| 
 | ||||
| #ifdef NDEBUG | ||||
|   std::string expected_output = "usage_config_test\n"; | ||||
| #else | ||||
|   std::string expected_output = | ||||
|       "usage_config_test\nDebug build (NDEBUG not #defined)\n"; | ||||
| #endif | ||||
| 
 | ||||
|   EXPECT_EQ(flags::GetUsageConfig().version_string(), expected_output); | ||||
| 
 | ||||
|   absl::FlagsUsageConfig empty_config; | ||||
|   empty_config.version_string = &TstVersionString; | ||||
|   absl::SetFlagsUsageConfig(empty_config); | ||||
| 
 | ||||
|   EXPECT_EQ(flags::GetUsageConfig().version_string(), "program 1.0.0"); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------
 | ||||
| 
 | ||||
| TEST_F(FlagsUsageConfigTest, TestNormalizeFilename) { | ||||
|   // This tests the default implementation.
 | ||||
|   EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a/a.cc"); | ||||
|   EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/a/a.cc"), "a/a.cc"); | ||||
|   EXPECT_EQ(flags::GetUsageConfig().normalize_filename("///a/a.cc"), "a/a.cc"); | ||||
|   EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/"), ""); | ||||
| 
 | ||||
|   // This tests that the custom implementation is called.
 | ||||
|   absl::FlagsUsageConfig empty_config; | ||||
|   empty_config.normalize_filename = &TstNormalizeFilename; | ||||
|   absl::SetFlagsUsageConfig(empty_config); | ||||
| 
 | ||||
|   EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a.cc"); | ||||
|   EXPECT_EQ(flags::GetUsageConfig().normalize_filename("aaa/a.cc"), "a/a.cc"); | ||||
| 
 | ||||
|   // This tests that the default implementation is called.
 | ||||
|   empty_config.normalize_filename = nullptr; | ||||
|   absl::SetFlagsUsageConfig(empty_config); | ||||
| 
 | ||||
|   EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a/a.cc"); | ||||
|   EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/a/a.cc"), "a/a.cc"); | ||||
|   EXPECT_EQ(flags::GetUsageConfig().normalize_filename("///a/a.cc"), "a/a.cc"); | ||||
|   EXPECT_EQ(flags::GetUsageConfig().normalize_filename("\\a\\a.cc"), "a\\a.cc"); | ||||
|   EXPECT_EQ(flags::GetUsageConfig().normalize_filename("//"), ""); | ||||
|   EXPECT_EQ(flags::GetUsageConfig().normalize_filename("\\\\"), ""); | ||||
| } | ||||
| 
 | ||||
| }  // namespace
 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue