Squashed 'third_party/abseil_cpp/' changes from 768eb2ca2..ccdbb5941
ccdbb5941 Export of internal Abseil changes 01f5f81f9 Export of internal Abseil changes 2c92bdc7c Export of internal Abseil changes e7ebf9803 Export of internal Abseil changes 2eba343b5 Export of internal Abseil changes a8b03d90e Export of internal Abseil changes 1d31b5c36 Export of internal Abseil changes da3a87690 Export of internal Abseil changes 8faf20461 Exclude empty directories (#697) 2069dc796 Export of internal Abseil changes 4832bf6bf Added a BUILD file in root to expose license. (#695) af8f994af Export of internal Abseil changes 33caf1097 Export of internal Abseil changes cf1a02e2d Export of internal Abseil changes git-subtree-dir: third_party/abseil_cpp git-subtree-split: ccdbb5941f992fabda7eae3ce72f55efc17c826a
This commit is contained in:
parent
768eb2ca28
commit
8f2828c4b4
97 changed files with 3546 additions and 2316 deletions
|
|
@ -27,28 +27,18 @@ package(default_visibility = ["//visibility:public"])
|
|||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
cc_library(
|
||||
name = "flag_internal",
|
||||
srcs = [
|
||||
"internal/flag.cc",
|
||||
],
|
||||
name = "path_util",
|
||||
hdrs = [
|
||||
"internal/flag.h",
|
||||
"internal/path_util.h",
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = ["//absl/base:__subpackages__"],
|
||||
visibility = [
|
||||
"//absl/flags:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
":config",
|
||||
":handle",
|
||||
":marshalling",
|
||||
":registry",
|
||||
"//absl/base",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/memory",
|
||||
"//absl/meta:type_traits",
|
||||
"//absl/strings",
|
||||
"//absl/synchronization",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -74,22 +64,6 @@ cc_library(
|
|||
],
|
||||
)
|
||||
|
||||
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 = [
|
||||
|
|
@ -131,21 +105,32 @@ cc_library(
|
|||
)
|
||||
|
||||
cc_library(
|
||||
name = "handle",
|
||||
srcs = [
|
||||
"internal/commandlineflag.cc",
|
||||
],
|
||||
name = "commandlineflag_internal",
|
||||
hdrs = [
|
||||
"internal/commandlineflag.h",
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = [
|
||||
"//absl/flags:__pkg__",
|
||||
],
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/base:fast_type_id",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "commandlineflag",
|
||||
srcs = [
|
||||
"commandlineflag.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"commandlineflag.h",
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":commandlineflag_internal",
|
||||
"//absl/base:config",
|
||||
"//absl/base:fast_type_id",
|
||||
"//absl/strings",
|
||||
"//absl/types:optional",
|
||||
|
|
@ -165,36 +150,65 @@ cc_library(
|
|||
visibility = [
|
||||
"//absl/flags:__pkg__",
|
||||
],
|
||||
deps = [":handle"],
|
||||
deps = [
|
||||
":commandlineflag",
|
||||
":commandlineflag_internal",
|
||||
"//absl/base:config",
|
||||
"//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "registry",
|
||||
name = "reflection",
|
||||
srcs = [
|
||||
"internal/registry.cc",
|
||||
"internal/type_erased.cc",
|
||||
"reflection.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"internal/registry.h",
|
||||
"internal/type_erased.h",
|
||||
"reflection.h",
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = [
|
||||
"//absl/flags:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
":commandlineflag",
|
||||
":commandlineflag_internal",
|
||||
":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_internal",
|
||||
srcs = [
|
||||
"internal/flag.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"internal/flag.h",
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = ["//absl/base:__subpackages__"],
|
||||
deps = [
|
||||
":commandlineflag",
|
||||
":commandlineflag_internal",
|
||||
":config",
|
||||
":marshalling",
|
||||
":reflection",
|
||||
"//absl/base",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/memory",
|
||||
"//absl/meta:type_traits",
|
||||
"//absl/strings",
|
||||
"//absl/synchronization",
|
||||
"//absl/utility",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "flag",
|
||||
srcs = [
|
||||
|
|
@ -209,9 +223,7 @@ cc_library(
|
|||
deps = [
|
||||
":config",
|
||||
":flag_internal",
|
||||
":handle",
|
||||
":marshalling",
|
||||
":registry",
|
||||
":reflection",
|
||||
"//absl/base",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
|
|
@ -233,14 +245,14 @@ cc_library(
|
|||
"//absl/flags:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
":commandlineflag",
|
||||
":config",
|
||||
":flag",
|
||||
":flag_internal",
|
||||
":handle",
|
||||
":path_util",
|
||||
":private_handle_accessor",
|
||||
":program_name",
|
||||
":registry",
|
||||
":reflection",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/strings",
|
||||
|
|
@ -276,13 +288,14 @@ cc_library(
|
|||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":commandlineflag",
|
||||
":commandlineflag_internal",
|
||||
":config",
|
||||
":flag",
|
||||
":flag_internal",
|
||||
":handle",
|
||||
":private_handle_accessor",
|
||||
":program_name",
|
||||
":registry",
|
||||
":reflection",
|
||||
":usage",
|
||||
":usage_internal",
|
||||
"//absl/base:config",
|
||||
|
|
@ -299,16 +312,17 @@ cc_test(
|
|||
name = "commandlineflag_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"internal/commandlineflag_test.cc",
|
||||
"commandlineflag_test.cc",
|
||||
],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":commandlineflag",
|
||||
":commandlineflag_internal",
|
||||
":config",
|
||||
":flag",
|
||||
":handle",
|
||||
":private_handle_accessor",
|
||||
":registry",
|
||||
":reflection",
|
||||
"//absl/memory",
|
||||
"//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
|
|
@ -342,8 +356,8 @@ cc_test(
|
|||
":config",
|
||||
":flag",
|
||||
":flag_internal",
|
||||
":handle",
|
||||
":registry",
|
||||
":marshalling",
|
||||
":reflection",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/base:malloc_internal",
|
||||
"//absl/strings",
|
||||
|
|
@ -363,6 +377,8 @@ cc_binary(
|
|||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":flag",
|
||||
":marshalling",
|
||||
"//absl/strings",
|
||||
"//absl/time",
|
||||
"//absl/types:optional",
|
||||
"@com_github_google_benchmark//:benchmark_main",
|
||||
|
|
@ -383,20 +399,6 @@ cc_test(
|
|||
],
|
||||
)
|
||||
|
||||
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",
|
||||
|
|
@ -408,7 +410,7 @@ cc_test(
|
|||
deps = [
|
||||
":flag",
|
||||
":parse",
|
||||
":registry",
|
||||
":reflection",
|
||||
"//absl/base:raw_logging_internal",
|
||||
"//absl/base:scoped_set_env",
|
||||
"//absl/strings",
|
||||
|
|
@ -417,6 +419,20 @@ cc_test(
|
|||
],
|
||||
)
|
||||
|
||||
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 = "program_name_test",
|
||||
size = "small",
|
||||
|
|
@ -433,18 +449,18 @@ cc_test(
|
|||
)
|
||||
|
||||
cc_test(
|
||||
name = "type_erased_test",
|
||||
name = "reflection_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"internal/type_erased_test.cc",
|
||||
"reflection_test.cc",
|
||||
],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":commandlineflag_internal",
|
||||
":flag",
|
||||
":handle",
|
||||
":marshalling",
|
||||
":registry",
|
||||
":reflection",
|
||||
"//absl/memory",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
|
|
@ -481,10 +497,9 @@ cc_test(
|
|||
":parse",
|
||||
":path_util",
|
||||
":program_name",
|
||||
":registry",
|
||||
":reflection",
|
||||
":usage",
|
||||
":usage_internal",
|
||||
"//absl/memory",
|
||||
"//absl/strings",
|
||||
"@com_google_googletest//:gtest",
|
||||
],
|
||||
|
|
|
|||
|
|
@ -17,24 +17,16 @@
|
|||
# Internal-only target, do not depend on directly.
|
||||
absl_cc_library(
|
||||
NAME
|
||||
flags_internal
|
||||
SRCS
|
||||
"internal/flag.cc"
|
||||
flags_path_util
|
||||
HDRS
|
||||
"internal/flag.h"
|
||||
"internal/path_util.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
|
||||
absl::strings
|
||||
PUBLIC
|
||||
)
|
||||
|
||||
|
|
@ -59,22 +51,6 @@ absl_cc_library(
|
|||
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
|
||||
|
|
@ -118,9 +94,7 @@ absl_cc_library(
|
|||
# Internal-only target, do not depend on directly.
|
||||
absl_cc_library(
|
||||
NAME
|
||||
flags_handle
|
||||
SRCS
|
||||
"internal/commandlineflag.cc"
|
||||
flags_commandlineflag_internal
|
||||
HDRS
|
||||
"internal/commandlineflag.h"
|
||||
COPTS
|
||||
|
|
@ -130,11 +104,25 @@ absl_cc_library(
|
|||
DEPS
|
||||
absl::config
|
||||
absl::fast_type_id
|
||||
absl::core_headers
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
NAME
|
||||
flags_commandlineflag
|
||||
SRCS
|
||||
"commandlineflag.cc"
|
||||
HDRS
|
||||
"commandlineflag.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
LINKOPTS
|
||||
${ABSL_DEFAULT_LINKOPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::fast_type_id
|
||||
absl::flags_commandlineflag_internal
|
||||
absl::optional
|
||||
absl::raw_logging_internal
|
||||
absl::strings
|
||||
absl::synchronization
|
||||
)
|
||||
|
||||
# Internal-only target, do not depend on directly.
|
||||
|
|
@ -150,34 +138,57 @@ absl_cc_library(
|
|||
LINKOPTS
|
||||
${ABSL_DEFAULT_LINKOPTS}
|
||||
DEPS
|
||||
absl::flags_handle
|
||||
absl::config
|
||||
absl::flags_commandlineflag
|
||||
absl::flags_commandlineflag_internal
|
||||
absl::strings
|
||||
)
|
||||
|
||||
# Internal-only target, do not depend on directly.
|
||||
absl_cc_library(
|
||||
NAME
|
||||
flags_registry
|
||||
flags_reflection
|
||||
SRCS
|
||||
"internal/registry.cc"
|
||||
"internal/type_erased.cc"
|
||||
"reflection.cc"
|
||||
HDRS
|
||||
"reflection.h"
|
||||
"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_commandlineflag
|
||||
absl::flags_private_handle_accessor
|
||||
absl::core_headers
|
||||
absl::raw_logging_internal
|
||||
absl::flags_config
|
||||
absl::strings
|
||||
absl::synchronization
|
||||
)
|
||||
|
||||
# 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_commandlineflag_internal
|
||||
absl::flags_config
|
||||
absl::flags_marshalling
|
||||
absl::synchronization
|
||||
absl::meta
|
||||
absl::utility
|
||||
PUBLIC
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
NAME
|
||||
flags
|
||||
|
|
@ -192,11 +203,10 @@ absl_cc_library(
|
|||
${ABSL_DEFAULT_LINKOPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::flags_commandlineflag
|
||||
absl::flags_config
|
||||
absl::flags_handle
|
||||
absl::flags_internal
|
||||
absl::flags_marshalling
|
||||
absl::flags_registry
|
||||
absl::flags_reflection
|
||||
absl::base
|
||||
absl::core_headers
|
||||
absl::strings
|
||||
|
|
@ -218,12 +228,12 @@ absl_cc_library(
|
|||
absl::config
|
||||
absl::flags_config
|
||||
absl::flags
|
||||
absl::flags_handle
|
||||
absl::flags_private_handle_accessor
|
||||
absl::flags_commandlineflag
|
||||
absl::flags_internal
|
||||
absl::flags_path_util
|
||||
absl::flags_private_handle_accessor
|
||||
absl::flags_program_name
|
||||
absl::flags_registry
|
||||
absl::flags_reflection
|
||||
absl::strings
|
||||
absl::synchronization
|
||||
)
|
||||
|
|
@ -264,11 +274,12 @@ absl_cc_library(
|
|||
absl::core_headers
|
||||
absl::flags_config
|
||||
absl::flags
|
||||
absl::flags_handle
|
||||
absl::flags_private_handle_accessor
|
||||
absl::flags_commandlineflag
|
||||
absl::flags_commandlineflag_internal
|
||||
absl::flags_internal
|
||||
absl::flags_private_handle_accessor
|
||||
absl::flags_program_name
|
||||
absl::flags_registry
|
||||
absl::flags_reflection
|
||||
absl::flags_usage
|
||||
absl::strings
|
||||
absl::synchronization
|
||||
|
|
@ -281,15 +292,16 @@ absl_cc_test(
|
|||
NAME
|
||||
flags_commandlineflag_test
|
||||
SRCS
|
||||
"internal/commandlineflag_test.cc"
|
||||
"commandlineflag_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::flags
|
||||
absl::flags_commandlineflag
|
||||
absl::flags_commandlineflag_internal
|
||||
absl::flags_config
|
||||
absl::flags_handle
|
||||
absl::flags_private_handle_accessor
|
||||
absl::flags_registry
|
||||
absl::flags_reflection
|
||||
absl::memory
|
||||
absl::strings
|
||||
gtest_main
|
||||
|
|
@ -319,9 +331,9 @@ absl_cc_test(
|
|||
absl::core_headers
|
||||
absl::flags
|
||||
absl::flags_config
|
||||
absl::flags_handle
|
||||
absl::flags_internal
|
||||
absl::flags_registry
|
||||
absl::flags_marshalling
|
||||
absl::flags_reflection
|
||||
absl::strings
|
||||
absl::time
|
||||
gtest_main
|
||||
|
|
@ -349,7 +361,7 @@ absl_cc_test(
|
|||
DEPS
|
||||
absl::flags
|
||||
absl::flags_parse
|
||||
absl::flags_registry
|
||||
absl::flags_reflection
|
||||
absl::raw_logging_internal
|
||||
absl::scoped_set_env
|
||||
absl::span
|
||||
|
|
@ -384,16 +396,15 @@ absl_cc_test(
|
|||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
flags_type_erased_test
|
||||
flags_reflection_test
|
||||
SRCS
|
||||
"internal/type_erased_test.cc"
|
||||
"reflection_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::flags_commandlineflag_internal
|
||||
absl::flags
|
||||
absl::flags_handle
|
||||
absl::flags_marshalling
|
||||
absl::flags_registry
|
||||
absl::flags_reflection
|
||||
absl::memory
|
||||
absl::strings
|
||||
gtest_main
|
||||
|
|
@ -427,9 +438,8 @@ absl_cc_test(
|
|||
absl::flags_path_util
|
||||
absl::flags_program_name
|
||||
absl::flags_parse
|
||||
absl::flags_registry
|
||||
absl::flags_reflection
|
||||
absl::flags_usage
|
||||
absl::memory
|
||||
absl::strings
|
||||
gtest
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,21 +13,25 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/flags/commandlineflag.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/flags/internal/commandlineflag.h"
|
||||
#include "absl/strings/string_view.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);
|
||||
flags_internal::kProgrammaticChange, *error);
|
||||
}
|
||||
|
||||
namespace flags_internal {
|
||||
FlagStateInterface::~FlagStateInterface() {}
|
||||
} // namespace flags_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
196
absl/flags/commandlineflag.h
Normal file
196
absl/flags/commandlineflag.h
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: commandlineflag.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// This header file defines the `CommandLineFlag`, which acts as a type-erased
|
||||
// handle for accessing metadata about the Abseil Flag in question.
|
||||
//
|
||||
// Because an actual Abseil flag is of an unspecified type, you should not
|
||||
// manipulate or interact directly with objects of that type. Instead, use the
|
||||
// CommandLineFlag type as an intermediary.
|
||||
#ifndef ABSL_FLAGS_COMMANDLINEFLAG_H_
|
||||
#define ABSL_FLAGS_COMMANDLINEFLAG_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/fast_type_id.h"
|
||||
#include "absl/flags/internal/commandlineflag.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace flags_internal {
|
||||
class PrivateHandleAccessor;
|
||||
} // namespace flags_internal
|
||||
|
||||
// CommandLineFlag
|
||||
//
|
||||
// This type acts as a type-erased handle for an instance of an Abseil Flag and
|
||||
// holds reflection information pertaining to that flag. Use CommandLineFlag to
|
||||
// access a flag's name, location, help string etc.
|
||||
//
|
||||
// To obtain an absl::CommandLineFlag, invoke `absl::FindCommandLineFlag()`
|
||||
// passing it the flag name string.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// // Obtain reflection handle for a flag named "flagname".
|
||||
// const absl::CommandLineFlag* my_flag_data =
|
||||
// absl::FindCommandLineFlag("flagname");
|
||||
//
|
||||
// // Now you can get flag info from that reflection handle.
|
||||
// std::string flag_location = my_flag_data->Filename();
|
||||
// ...
|
||||
class CommandLineFlag {
|
||||
public:
|
||||
constexpr CommandLineFlag() = default;
|
||||
|
||||
// Not copyable/assignable.
|
||||
CommandLineFlag(const CommandLineFlag&) = delete;
|
||||
CommandLineFlag& operator=(const CommandLineFlag&) = delete;
|
||||
|
||||
// absl::CommandLineFlag::IsOfType()
|
||||
//
|
||||
// Return true iff flag has type T.
|
||||
template <typename T>
|
||||
inline bool IsOfType() const {
|
||||
return TypeId() == base_internal::FastTypeId<T>();
|
||||
}
|
||||
|
||||
// absl::CommandLineFlag::TryGet()
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
|
||||
// absl::CommandLineFlag::Name()
|
||||
//
|
||||
// Returns name of this flag.
|
||||
virtual absl::string_view Name() const = 0;
|
||||
|
||||
// absl::CommandLineFlag::Filename()
|
||||
//
|
||||
// Returns name of the file where this flag is defined.
|
||||
virtual std::string Filename() const = 0;
|
||||
|
||||
// absl::CommandLineFlag::Help()
|
||||
//
|
||||
// Returns help message associated with this flag.
|
||||
virtual std::string Help() const = 0;
|
||||
|
||||
// absl::CommandLineFlag::IsRetired()
|
||||
//
|
||||
// Returns true iff this object corresponds to retired flag.
|
||||
virtual bool IsRetired() const;
|
||||
|
||||
// absl::CommandLineFlag::DefaultValue()
|
||||
//
|
||||
// Returns the default value for this flag.
|
||||
virtual std::string DefaultValue() const = 0;
|
||||
|
||||
// absl::CommandLineFlag::CurrentValue()
|
||||
//
|
||||
// Returns the current value for this flag.
|
||||
virtual std::string CurrentValue() const = 0;
|
||||
|
||||
// absl::CommandLineFlag::ParseFrom()
|
||||
//
|
||||
// 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 flags_internal::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 flags_internal::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<flags_internal::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;
|
||||
};
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_FLAGS_COMMANDLINEFLAG_H_
|
||||
|
|
@ -13,15 +13,16 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/flags/internal/commandlineflag.h"
|
||||
#include "absl/flags/commandlineflag.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/flags/internal/commandlineflag.h"
|
||||
#include "absl/flags/internal/private_handle_accessor.h"
|
||||
#include "absl/flags/internal/registry.h"
|
||||
#include "absl/flags/reflection.h"
|
||||
#include "absl/flags/usage_config.h"
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/strings/match.h"
|
||||
|
|
@ -33,6 +34,10 @@ ABSL_FLAG(std::string, string_flag, "dflt",
|
|||
absl::StrCat("string_flag", " help"));
|
||||
ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
|
||||
|
||||
// These are only used to test default values.
|
||||
ABSL_FLAG(int, int_flag2, 201, "");
|
||||
ABSL_FLAG(std::string, string_flag2, "dflt", "");
|
||||
|
||||
namespace {
|
||||
|
||||
namespace flags = absl::flags_internal;
|
||||
|
|
@ -46,7 +51,7 @@ class CommandLineFlagTest : public testing::Test {
|
|||
absl::SetFlagsUsageConfig(default_config);
|
||||
}
|
||||
|
||||
void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); }
|
||||
void SetUp() override { flag_saver_ = absl::make_unique<absl::FlagSaver>(); }
|
||||
void TearDown() override { flag_saver_.reset(); }
|
||||
|
||||
private:
|
||||
|
|
@ -59,56 +64,49 @@ class CommandLineFlagTest : public testing::Test {
|
|||
return std::string(fname);
|
||||
}
|
||||
|
||||
std::unique_ptr<flags::FlagSaver> flag_saver_;
|
||||
std::unique_ptr<absl::FlagSaver> flag_saver_;
|
||||
};
|
||||
|
||||
TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {
|
||||
auto* flag_01 = flags::FindCommandLineFlag("int_flag");
|
||||
auto* flag_01 = absl::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"))
|
||||
EXPECT_TRUE(!flag_01->IsOfType<bool>());
|
||||
EXPECT_TRUE(!flag_01->IsOfType<std::string>());
|
||||
EXPECT_TRUE(absl::EndsWith(flag_01->Filename(),
|
||||
"absl/flags/commandlineflag_test.cc"))
|
||||
<< flag_01->Filename();
|
||||
|
||||
auto* flag_02 = flags::FindCommandLineFlag("string_flag");
|
||||
auto* flag_02 = absl::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"))
|
||||
EXPECT_TRUE(!flag_02->IsOfType<bool>());
|
||||
EXPECT_TRUE(!flag_02->IsOfType<int>());
|
||||
EXPECT_TRUE(absl::EndsWith(flag_02->Filename(),
|
||||
"absl/flags/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");
|
||||
absl::SetFlag(&FLAGS_int_flag2, 301);
|
||||
auto* flag_01 = absl::FindCommandLineFlag("int_flag2");
|
||||
|
||||
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");
|
||||
absl::SetFlag(&FLAGS_string_flag2, "new_str_value");
|
||||
auto* flag_02 = absl::FindCommandLineFlag("string_flag2");
|
||||
|
||||
ASSERT_TRUE(flag_02);
|
||||
EXPECT_EQ(flag_02->CurrentValue(), "new_str_value");
|
||||
|
|
@ -120,62 +118,62 @@ TEST_F(CommandLineFlagTest, TestValueAccessMethods) {
|
|||
TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {
|
||||
std::string err;
|
||||
|
||||
auto* flag_01 = flags::FindCommandLineFlag("int_flag");
|
||||
auto* flag_01 = absl::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));
|
||||
*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));
|
||||
*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));
|
||||
*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));
|
||||
*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));
|
||||
*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));
|
||||
*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));
|
||||
*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");
|
||||
auto* flag_02 = absl::FindCommandLineFlag("string_flag");
|
||||
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
|
||||
flag_02, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
|
||||
&err));
|
||||
*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));
|
||||
*flag_02, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "");
|
||||
}
|
||||
|
||||
|
|
@ -184,18 +182,18 @@ TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {
|
|||
TEST_F(CommandLineFlagTest, TestParseFromDefaultValue) {
|
||||
std::string err;
|
||||
|
||||
auto* flag_01 = flags::FindCommandLineFlag("int_flag");
|
||||
auto* flag_01 = absl::FindCommandLineFlag("int_flag");
|
||||
|
||||
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
|
||||
flag_01, "111", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
|
||||
&err));
|
||||
*flag_01, "111", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
|
||||
err));
|
||||
EXPECT_EQ(flag_01->DefaultValue(), "111");
|
||||
|
||||
auto* flag_02 = flags::FindCommandLineFlag("string_flag");
|
||||
auto* flag_02 = absl::FindCommandLineFlag("string_flag");
|
||||
|
||||
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
|
||||
flag_02, "abc", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
|
||||
&err));
|
||||
*flag_02, "abc", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
|
||||
err));
|
||||
EXPECT_EQ(flag_02->DefaultValue(), "abc");
|
||||
}
|
||||
|
||||
|
|
@ -204,28 +202,28 @@ TEST_F(CommandLineFlagTest, TestParseFromDefaultValue) {
|
|||
TEST_F(CommandLineFlagTest, TestParseFromIfDefault) {
|
||||
std::string err;
|
||||
|
||||
auto* flag_01 = flags::FindCommandLineFlag("int_flag");
|
||||
auto* flag_01 = absl::FindCommandLineFlag("int_flag");
|
||||
|
||||
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
|
||||
flag_01, "22", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
|
||||
&err))
|
||||
*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));
|
||||
*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));
|
||||
*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));
|
||||
*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");
|
||||
}
|
||||
|
|
@ -26,7 +26,6 @@
|
|||
#define ABSL_FLAGS_DECLARE_H_
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
|
|
|||
|
|
@ -16,8 +16,6 @@
|
|||
#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
|
||||
|
|
|
|||
|
|
@ -33,14 +33,11 @@
|
|||
#include <type_traits>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/casts.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/optimization.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 {
|
||||
|
|
@ -111,12 +108,12 @@ class Flag {
|
|||
impl_(nullptr) {}
|
||||
#endif
|
||||
|
||||
flags_internal::Flag<T>* GetImpl() const {
|
||||
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_;
|
||||
return *impl_;
|
||||
}
|
||||
|
||||
impl_ = new flags_internal::Flag<T>(
|
||||
|
|
@ -128,28 +125,30 @@ class Flag {
|
|||
inited_.store(true, std::memory_order_release);
|
||||
}
|
||||
|
||||
return impl_;
|
||||
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 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();
|
||||
return GetImpl().IsSpecifiedOnCommandLine();
|
||||
}
|
||||
std::string Filename() const { return GetImpl()->Filename(); }
|
||||
std::string DefaultValue() const { return GetImpl()->DefaultValue(); }
|
||||
std::string CurrentValue() const { return GetImpl()->CurrentValue(); }
|
||||
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>();
|
||||
return GetImpl().template IsOfType<U>();
|
||||
}
|
||||
T Get() const { return GetImpl()->Get(); }
|
||||
void Set(const T& v) { GetImpl()->Set(v); }
|
||||
void InvokeCallback() { GetImpl()->InvokeCallback(); }
|
||||
T Get() const { return GetImpl().Get(); }
|
||||
void Set(const T& v) { GetImpl().Set(v); }
|
||||
void InvokeCallback() { GetImpl().InvokeCallback(); }
|
||||
|
||||
const CommandLineFlag& Reflect() const { return GetImpl().Reflect(); }
|
||||
|
||||
// The data members are logically private, but they need to be public for
|
||||
// this to be an aggregate type.
|
||||
|
|
@ -205,6 +204,21 @@ void SetFlag(absl::Flag<T>* flag, const V& v) {
|
|||
flag->Set(value);
|
||||
}
|
||||
|
||||
// GetFlagReflectionHandle()
|
||||
//
|
||||
// Returns the reflection handle corresponding to specified Abseil Flag
|
||||
// instance. Use this handle to access flag's reflection information, like name,
|
||||
// location, default value etc.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// std::string = absl::GetFlagReflectionHandle(FLAGS_count).DefaultValue();
|
||||
|
||||
template <typename T>
|
||||
const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) {
|
||||
return f.Reflect();
|
||||
}
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
|
|
@ -265,27 +279,29 @@ ABSL_NAMESPACE_END
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_NAMES
|
||||
#if !defined(_MSC_VER) || defined(__clang__)
|
||||
#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag
|
||||
#define ABSL_FLAG_IMPL_HELP_ARG(name) \
|
||||
absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>( \
|
||||
FLAGS_help_storage_##name)
|
||||
#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) \
|
||||
absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0)
|
||||
#else
|
||||
#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag.GetImpl()
|
||||
#define ABSL_FLAG_IMPL_HELP_ARG(name) &AbslFlagHelpGenFor##name::NonConst
|
||||
#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) &AbslFlagDefaultGenFor##name::Gen
|
||||
#endif
|
||||
|
||||
#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
|
||||
absl::flags_internal::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(flag))
|
||||
#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
|
||||
absl::flags_internal::FlagRegistrar<T, true>(ABSL_FLAG_IMPL_FLAG_PTR(flag))
|
||||
#endif
|
||||
|
||||
// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP
|
||||
|
|
@ -301,15 +317,24 @@ ABSL_NAMESPACE_END
|
|||
// 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); } \
|
||||
}
|
||||
// TODO(rogeeff): place these generated structs into local namespace and apply
|
||||
// ABSL_INTERNAL_UNIQUE_SHORT_NAME.
|
||||
// TODO(rogeeff): Apply __attribute__((nodebug)) to FLAGS_help_storage_##name
|
||||
#define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt) \
|
||||
struct AbslFlagHelpGenFor##name { \
|
||||
/* The expression is run in the caller as part of the */ \
|
||||
/* default value argument. That keeps temporaries alive */ \
|
||||
/* long enough for NonConst to work correctly. */ \
|
||||
static constexpr absl::string_view Value( \
|
||||
absl::string_view v = ABSL_FLAG_IMPL_FLAGHELP(txt)) { \
|
||||
return v; \
|
||||
} \
|
||||
static std::string NonConst() { return std::string(Value()); } \
|
||||
}; \
|
||||
constexpr auto FLAGS_help_storage_##name ABSL_INTERNAL_UNIQUE_SMALL_NAME() \
|
||||
ABSL_ATTRIBUTE_SECTION_VARIABLE(flags_help_cold) = \
|
||||
absl::flags_internal::HelpStringAsArray<AbslFlagHelpGenFor##name>( \
|
||||
0);
|
||||
|
||||
#define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \
|
||||
struct AbslFlagDefaultGenFor##name { \
|
||||
|
|
@ -317,40 +342,23 @@ ABSL_NAMESPACE_END
|
|||
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 = \
|
||||
#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_FLAG_IMPL_HELP_ARG(name), ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)}; \
|
||||
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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -13,7 +13,14 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/flags/marshalling.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
|
|
|
|||
|
|
@ -15,9 +15,11 @@
|
|||
|
||||
#include "absl/flags/flag.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include <thread> // NOLINT
|
||||
#include <vector>
|
||||
|
|
@ -26,9 +28,9 @@
|
|||
#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/marshalling.h"
|
||||
#include "absl/flags/reflection.h"
|
||||
#include "absl/flags/usage_config.h"
|
||||
#include "absl/strings/match.h"
|
||||
#include "absl/strings/numbers.h"
|
||||
|
|
@ -45,6 +47,9 @@ namespace {
|
|||
namespace flags = absl::flags_internal;
|
||||
|
||||
std::string TestHelpMsg() { return "dynamic help"; }
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
std::string TestLiteralHelpMsg() { return "literal help"; }
|
||||
#endif
|
||||
template <typename T>
|
||||
void TestMakeDflt(void* dst) {
|
||||
new (dst) T{};
|
||||
|
|
@ -76,7 +81,7 @@ class FlagTest : public testing::Test {
|
|||
#endif
|
||||
return std::string(fname);
|
||||
}
|
||||
flags::FlagSaver flag_saver_;
|
||||
absl::FlagSaver flag_saver_;
|
||||
};
|
||||
|
||||
struct S1 {
|
||||
|
|
@ -128,15 +133,29 @@ constexpr flags::FlagHelpArg help_arg{flags::FlagHelpMsg("literal help"),
|
|||
|
||||
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})
|
||||
#if !defined(_MSC_VER) || defined(__clang__)
|
||||
#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind) \
|
||||
constexpr flags::FlagDefaultArg f1default##T{ \
|
||||
flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
|
||||
constexpr absl::Flag<T> f1##T{"f1", "file", help_arg, f1default##T}; \
|
||||
ABSL_CONST_INIT absl::Flag<T> f2##T { \
|
||||
"f2", "file", \
|
||||
{flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
|
||||
flags::FlagDefaultArg { \
|
||||
flags::FlagDefaultSrc(&TestMakeDflt<T>), \
|
||||
flags::FlagDefaultKind::kGenFunc \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind) \
|
||||
constexpr flags::FlagDefaultArg f1default##T{ \
|
||||
flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
|
||||
constexpr absl::Flag<T> f1##T{"f1", "file", &TestLiteralHelpMsg, \
|
||||
&TestMakeDflt<T>}; \
|
||||
ABSL_CONST_INIT absl::Flag<T> f2##T { \
|
||||
"f2", "file", &TestHelpMsg, &TestMakeDflt<T> \
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_CONSTRUCTED_FLAG(bool, true, kOneWord);
|
||||
DEFINE_CONSTRUCTED_FLAG(int16_t, 1, kOneWord);
|
||||
|
|
@ -151,21 +170,22 @@ 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");
|
||||
bool TestConstructionFor(const absl::Flag<T>& f1, absl::Flag<T>& f2) {
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Name(), "f1");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Help(), "literal help");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Filename(), "file");
|
||||
|
||||
flags::FlagRegistrar<T, false>(f2).OnUpdate(TestCallback);
|
||||
flags::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(f2))
|
||||
.OnUpdate(TestCallback);
|
||||
|
||||
EXPECT_EQ(f2->Name(), "f2");
|
||||
EXPECT_EQ(f2->Help(), "dynamic help");
|
||||
EXPECT_EQ(f2->Filename(), "file");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Name(), "f2");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Help(), "dynamic help");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Filename(), "file");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, &f2##T);
|
||||
#define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, f2##T);
|
||||
|
||||
TEST_F(FlagTest, TestConstruction) {
|
||||
TEST_CONSTRUCTED_FLAG(bool);
|
||||
|
|
@ -204,18 +224,30 @@ namespace {
|
|||
|
||||
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");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
|
||||
"test_flag_01");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
|
||||
"test_flag_02");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
|
||||
"test_flag_03");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
|
||||
"test_flag_04");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
|
||||
"test_flag_05");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
|
||||
"test_flag_06");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
|
||||
"test_flag_07");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
|
||||
"test_flag_08");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
|
||||
"test_flag_09");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
|
||||
"test_flag_10");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
|
||||
"test_flag_11");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
|
||||
"test_flag_12");
|
||||
}
|
||||
#endif // !ABSL_FLAGS_STRIP_NAMES
|
||||
|
||||
|
|
@ -242,96 +274,168 @@ namespace {
|
|||
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(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
|
||||
"test_flag_01");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Help(),
|
||||
"test flag 01");
|
||||
EXPECT_TRUE(absl::EndsWith(
|
||||
absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename(),
|
||||
expected_file_name))
|
||||
<< absl::GetFlagReflectionHandle(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(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
|
||||
"test_flag_02");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Help(),
|
||||
"test flag 02");
|
||||
EXPECT_TRUE(absl::EndsWith(
|
||||
absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename(),
|
||||
expected_file_name))
|
||||
<< absl::GetFlagReflectionHandle(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(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
|
||||
"test_flag_03");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Help(),
|
||||
"test flag 03");
|
||||
EXPECT_TRUE(absl::EndsWith(
|
||||
absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename(),
|
||||
expected_file_name))
|
||||
<< absl::GetFlagReflectionHandle(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(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
|
||||
"test_flag_04");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Help(),
|
||||
"test flag 04");
|
||||
EXPECT_TRUE(absl::EndsWith(
|
||||
absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename(),
|
||||
expected_file_name))
|
||||
<< absl::GetFlagReflectionHandle(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(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
|
||||
"test_flag_05");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Help(),
|
||||
"test flag 05");
|
||||
EXPECT_TRUE(absl::EndsWith(
|
||||
absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename(),
|
||||
expected_file_name))
|
||||
<< absl::GetFlagReflectionHandle(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(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
|
||||
"test_flag_06");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Help(),
|
||||
"test flag 06");
|
||||
EXPECT_TRUE(absl::EndsWith(
|
||||
absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename(),
|
||||
expected_file_name))
|
||||
<< absl::GetFlagReflectionHandle(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(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
|
||||
"test_flag_07");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Help(),
|
||||
"test flag 07");
|
||||
EXPECT_TRUE(absl::EndsWith(
|
||||
absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename(),
|
||||
expected_file_name))
|
||||
<< absl::GetFlagReflectionHandle(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(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
|
||||
"test_flag_08");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Help(),
|
||||
"test flag 08");
|
||||
EXPECT_TRUE(absl::EndsWith(
|
||||
absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename(),
|
||||
expected_file_name))
|
||||
<< absl::GetFlagReflectionHandle(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(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
|
||||
"test_flag_09");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Help(),
|
||||
"test flag 09");
|
||||
EXPECT_TRUE(absl::EndsWith(
|
||||
absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename(),
|
||||
expected_file_name))
|
||||
<< absl::GetFlagReflectionHandle(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(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
|
||||
"test_flag_10");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Help(),
|
||||
"test flag 10");
|
||||
EXPECT_TRUE(absl::EndsWith(
|
||||
absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename(),
|
||||
expected_file_name))
|
||||
<< absl::GetFlagReflectionHandle(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(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
|
||||
"test_flag_11");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Help(),
|
||||
"test flag 11");
|
||||
EXPECT_TRUE(absl::EndsWith(
|
||||
absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename(),
|
||||
expected_file_name))
|
||||
<< absl::GetFlagReflectionHandle(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();
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
|
||||
"test_flag_12");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Help(),
|
||||
"test flag 12");
|
||||
EXPECT_TRUE(absl::EndsWith(
|
||||
absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename(),
|
||||
expected_file_name))
|
||||
<< absl::GetFlagReflectionHandle(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(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).DefaultValue(),
|
||||
"true");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).DefaultValue(),
|
||||
"1234");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).DefaultValue(),
|
||||
"-34");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).DefaultValue(),
|
||||
"189");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).DefaultValue(),
|
||||
"10765");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).DefaultValue(),
|
||||
"40000");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).DefaultValue(),
|
||||
"-1234567");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).DefaultValue(),
|
||||
"9876543");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).DefaultValue(),
|
||||
"-9.876e-50");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).DefaultValue(),
|
||||
"1.234e+12");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).DefaultValue(),
|
||||
"");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(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::GetFlagReflectionHandle(FLAGS_test_flag_01).CurrentValue(),
|
||||
"true");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).CurrentValue(),
|
||||
"1234");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).CurrentValue(),
|
||||
"-34");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).CurrentValue(),
|
||||
"189");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).CurrentValue(),
|
||||
"10765");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).CurrentValue(),
|
||||
"40000");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).CurrentValue(),
|
||||
"-1234567");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).CurrentValue(),
|
||||
"9876543");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).CurrentValue(),
|
||||
"-9.876e-50");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).CurrentValue(),
|
||||
"1.234e+12");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).CurrentValue(),
|
||||
"");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).CurrentValue(),
|
||||
"10m");
|
||||
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
|
||||
|
|
@ -386,12 +490,18 @@ 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::GetFlagReflectionHandle(FLAGS_test_flag_eb_01).DefaultValue(),
|
||||
"false");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_02).DefaultValue(),
|
||||
"0");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_03).DefaultValue(),
|
||||
"0");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_04).DefaultValue(),
|
||||
"0");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_05).DefaultValue(),
|
||||
"");
|
||||
EXPECT_EQ(absl::GetFlagReflectionHandle(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);
|
||||
|
|
@ -445,29 +555,29 @@ TEST_F(FlagTest, TestGetSet) {
|
|||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(FlagTest, TestGetViaReflection) {
|
||||
auto* handle = flags::FindCommandLineFlag("test_flag_01");
|
||||
auto* handle = absl::FindCommandLineFlag("test_flag_01");
|
||||
EXPECT_EQ(*handle->TryGet<bool>(), true);
|
||||
handle = flags::FindCommandLineFlag("test_flag_02");
|
||||
handle = absl::FindCommandLineFlag("test_flag_02");
|
||||
EXPECT_EQ(*handle->TryGet<int>(), 1234);
|
||||
handle = flags::FindCommandLineFlag("test_flag_03");
|
||||
handle = absl::FindCommandLineFlag("test_flag_03");
|
||||
EXPECT_EQ(*handle->TryGet<int16_t>(), -34);
|
||||
handle = flags::FindCommandLineFlag("test_flag_04");
|
||||
handle = absl::FindCommandLineFlag("test_flag_04");
|
||||
EXPECT_EQ(*handle->TryGet<uint16_t>(), 189);
|
||||
handle = flags::FindCommandLineFlag("test_flag_05");
|
||||
handle = absl::FindCommandLineFlag("test_flag_05");
|
||||
EXPECT_EQ(*handle->TryGet<int32_t>(), 10765);
|
||||
handle = flags::FindCommandLineFlag("test_flag_06");
|
||||
handle = absl::FindCommandLineFlag("test_flag_06");
|
||||
EXPECT_EQ(*handle->TryGet<uint32_t>(), 40000);
|
||||
handle = flags::FindCommandLineFlag("test_flag_07");
|
||||
handle = absl::FindCommandLineFlag("test_flag_07");
|
||||
EXPECT_EQ(*handle->TryGet<int64_t>(), -1234567);
|
||||
handle = flags::FindCommandLineFlag("test_flag_08");
|
||||
handle = absl::FindCommandLineFlag("test_flag_08");
|
||||
EXPECT_EQ(*handle->TryGet<uint64_t>(), 9876543);
|
||||
handle = flags::FindCommandLineFlag("test_flag_09");
|
||||
handle = absl::FindCommandLineFlag("test_flag_09");
|
||||
EXPECT_NEAR(*handle->TryGet<double>(), -9.876e-50, 1e-55);
|
||||
handle = flags::FindCommandLineFlag("test_flag_10");
|
||||
handle = absl::FindCommandLineFlag("test_flag_10");
|
||||
EXPECT_NEAR(*handle->TryGet<float>(), 1.234e12f, 1e5f);
|
||||
handle = flags::FindCommandLineFlag("test_flag_11");
|
||||
handle = absl::FindCommandLineFlag("test_flag_11");
|
||||
EXPECT_EQ(*handle->TryGet<std::string>(), "");
|
||||
handle = flags::FindCommandLineFlag("test_flag_12");
|
||||
handle = absl::FindCommandLineFlag("test_flag_12");
|
||||
EXPECT_EQ(*handle->TryGet<absl::Duration>(), absl::Minutes(10));
|
||||
}
|
||||
|
||||
|
|
@ -501,8 +611,9 @@ 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");
|
||||
EXPECT_EQ(
|
||||
absl::GetFlagReflectionHandle(FLAGS_test_flag_with_non_const_help).Help(),
|
||||
"test flag non const help");
|
||||
}
|
||||
#endif //! ABSL_FLAGS_STRIP_HELP
|
||||
|
||||
|
|
@ -704,14 +815,15 @@ 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));
|
||||
auto* handle = absl::FindCommandLineFlag("old_bool_flag");
|
||||
EXPECT_TRUE(handle->IsOfType<bool>());
|
||||
EXPECT_TRUE(handle->IsRetired());
|
||||
handle = absl::FindCommandLineFlag("old_int_flag");
|
||||
EXPECT_TRUE(handle->IsOfType<int>());
|
||||
EXPECT_TRUE(handle->IsRetired());
|
||||
handle = absl::FindCommandLineFlag("old_str_flag");
|
||||
EXPECT_TRUE(handle->IsOfType<std::string>());
|
||||
EXPECT_TRUE(handle->IsRetired());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -16,14 +16,8 @@
|
|||
#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
|
||||
|
|
@ -34,7 +28,7 @@ namespace flags_internal {
|
|||
// 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;
|
||||
using FlagFastTypeId = absl::base_internal::FastTypeIdType;
|
||||
|
||||
// Options that control SetCommandLineOptionWithMode.
|
||||
enum FlagSettingMode {
|
||||
|
|
@ -67,117 +61,6 @@ class FlagStateInterface {
|
|||
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
|
||||
|
|
|
|||
|
|
@ -15,22 +15,26 @@
|
|||
|
||||
#include "absl/flags/internal/flag.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/call_once.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/config.h"
|
||||
#include "absl/flags/internal/commandlineflag.h"
|
||||
#include "absl/flags/usage_config.h"
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
|
|
@ -63,14 +67,14 @@ bool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) {
|
|||
// need to acquire these locks themselves.
|
||||
class MutexRelock {
|
||||
public:
|
||||
explicit MutexRelock(absl::Mutex* mu) : mu_(mu) { mu_->Unlock(); }
|
||||
~MutexRelock() { mu_->Lock(); }
|
||||
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_;
|
||||
absl::Mutex& mu_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
@ -83,7 +87,7 @@ class FlagImpl;
|
|||
class FlagState : public flags_internal::FlagStateInterface {
|
||||
public:
|
||||
template <typename V>
|
||||
FlagState(FlagImpl* flag_impl, const V& v, bool modified,
|
||||
FlagState(FlagImpl& flag_impl, const V& v, bool modified,
|
||||
bool on_command_line, int64_t counter)
|
||||
: flag_impl_(flag_impl),
|
||||
value_(v),
|
||||
|
|
@ -92,9 +96,9 @@ class FlagState : public flags_internal::FlagStateInterface {
|
|||
counter_(counter) {}
|
||||
|
||||
~FlagState() override {
|
||||
if (flag_impl_->ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer)
|
||||
if (flag_impl_.ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer)
|
||||
return;
|
||||
flags_internal::Delete(flag_impl_->op_, value_.heap_allocated);
|
||||
flags_internal::Delete(flag_impl_.op_, value_.heap_allocated);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -102,15 +106,15 @@ class FlagState : public flags_internal::FlagStateInterface {
|
|||
|
||||
// Restores the flag to the saved state.
|
||||
void Restore() const override {
|
||||
if (!flag_impl_->RestoreState(*this)) return;
|
||||
if (!flag_impl_.RestoreState(*this)) return;
|
||||
|
||||
ABSL_INTERNAL_LOG(
|
||||
INFO, absl::StrCat("Restore saved value of ", flag_impl_->Name(),
|
||||
" to: ", flag_impl_->CurrentValue()));
|
||||
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_;
|
||||
FlagImpl& flag_impl_;
|
||||
union SavedValue {
|
||||
explicit SavedValue(void* v) : heap_allocated(v) {}
|
||||
explicit SavedValue(int64_t v) : one_word(v) {}
|
||||
|
|
@ -327,7 +331,7 @@ void FlagImpl::InvokeCallback() const {
|
|||
// 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());
|
||||
MutexRelock relock(*DataGuard());
|
||||
absl::MutexLock lock(&callback_->guard);
|
||||
cb();
|
||||
}
|
||||
|
|
@ -340,17 +344,17 @@ std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() {
|
|||
switch (ValueStorageKind()) {
|
||||
case FlagValueStorageKind::kAlignedBuffer: {
|
||||
return absl::make_unique<FlagState>(
|
||||
this, flags_internal::Clone(op_, AlignedBufferValue()), modified,
|
||||
*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,
|
||||
*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,
|
||||
*this, TwoWordsValue().load(std::memory_order_acquire), modified,
|
||||
on_command_line, counter_);
|
||||
}
|
||||
}
|
||||
|
|
@ -411,14 +415,14 @@ std::atomic<AlignedTwoWords>& FlagImpl::TwoWordsValue() const {
|
|||
// 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 {
|
||||
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);
|
||||
err = absl::StrCat("Illegal value '", value, "' specified for flag '",
|
||||
Name(), "'", err_sep, parse_err);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -474,7 +478,7 @@ void FlagImpl::Write(const void* src) {
|
|||
// * 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) {
|
||||
ValueSource source, std::string& err) {
|
||||
absl::MutexLock l(DataGuard());
|
||||
|
||||
switch (set_mode) {
|
||||
|
|
|
|||
|
|
@ -16,31 +16,36 @@
|
|||
#ifndef ABSL_FLAGS_INTERNAL_FLAG_H_
|
||||
#define ABSL_FLAGS_INTERNAL_FLAG_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/call_once.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/optimization.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/flags/commandlineflag.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"
|
||||
#include "absl/utility/utility.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declaration of absl::Flag<T> public API.
|
||||
namespace flags_internal {
|
||||
template <typename T>
|
||||
|
|
@ -64,12 +69,15 @@ 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 {
|
||||
template <typename U>
|
||||
const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<U>& f);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Flag value type operations, eg., parsing, copying, etc. are provided
|
||||
// by function specific to that type with a signature matching FlagOpFn.
|
||||
|
||||
namespace flags_internal {
|
||||
|
||||
enum class FlagOp {
|
||||
kAlloc,
|
||||
kDelete,
|
||||
|
|
@ -168,6 +176,28 @@ inline const std::type_info* GenRuntimeTypeId() {
|
|||
// cases.
|
||||
using HelpGenFunc = std::string (*)();
|
||||
|
||||
template <size_t N>
|
||||
struct FixedCharArray {
|
||||
char value[N];
|
||||
|
||||
template <size_t... I>
|
||||
static constexpr FixedCharArray<N> FromLiteralString(
|
||||
absl::string_view str, absl::index_sequence<I...>) {
|
||||
return (void)str, FixedCharArray<N>({{str[I]..., '\0'}});
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Gen, size_t N = Gen::Value().size()>
|
||||
constexpr FixedCharArray<N + 1> HelpStringAsArray(int) {
|
||||
return FixedCharArray<N + 1>::FromLiteralString(
|
||||
Gen::Value(), absl::make_index_sequence<N>{});
|
||||
}
|
||||
|
||||
template <typename Gen>
|
||||
constexpr std::false_type HelpStringAsArray(char) {
|
||||
return std::false_type{};
|
||||
}
|
||||
|
||||
union FlagHelpMsg {
|
||||
constexpr explicit FlagHelpMsg(const char* help_msg) : literal(help_msg) {}
|
||||
constexpr explicit FlagHelpMsg(HelpGenFunc help_gen) : gen_func(help_gen) {}
|
||||
|
|
@ -185,40 +215,28 @@ struct FlagHelpArg {
|
|||
|
||||
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
|
||||
// AbslFlagHelpGenFor##name as Gen and integer 0 as a single argument to prefer
|
||||
// first overload if possible. If help message is evaluatable on constexpr
|
||||
// context We'll be able to make FixedCharArray out of it and 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 Gen, size_t N>
|
||||
constexpr FlagHelpArg HelpArg(const FixedCharArray<N>& value) {
|
||||
return {FlagHelpMsg(value.value), FlagHelpKind::kLiteral};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr FlagHelpArg HelpArg(char) {
|
||||
return {FlagHelpMsg(&T::NonConst), FlagHelpKind::kGenFunc};
|
||||
template <typename Gen>
|
||||
constexpr FlagHelpArg HelpArg(std::false_type) {
|
||||
return {FlagHelpMsg(&Gen::NonConst), FlagHelpKind::kGenFunc};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -364,31 +382,31 @@ struct FlagValue;
|
|||
|
||||
template <typename T>
|
||||
struct FlagValue<T, FlagValueStorageKind::kAlignedBuffer> {
|
||||
bool Get(T*) const { return false; }
|
||||
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 {
|
||||
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));
|
||||
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 {
|
||||
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));
|
||||
std::memcpy(&dst, static_cast<const void*>(&two_words_val), sizeof(T));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
@ -419,7 +437,7 @@ struct DynValueDeleter {
|
|||
|
||||
class FlagState;
|
||||
|
||||
class FlagImpl final : public flags_internal::CommandLineFlag {
|
||||
class FlagImpl final : public CommandLineFlag {
|
||||
public:
|
||||
constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op,
|
||||
FlagHelpArg help, FlagValueStorageKind value_kind,
|
||||
|
|
@ -492,7 +510,7 @@ class FlagImpl final : public flags_internal::CommandLineFlag {
|
|||
// 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
|
||||
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());
|
||||
|
|
@ -534,7 +552,7 @@ class FlagImpl final : public flags_internal::CommandLineFlag {
|
|||
ABSL_LOCKS_EXCLUDED(*DataGuard());
|
||||
|
||||
bool ParseFrom(absl::string_view value, FlagSettingMode set_mode,
|
||||
ValueSource source, std::string* error) override
|
||||
ValueSource source, std::string& error) override
|
||||
ABSL_LOCKS_EXCLUDED(*DataGuard());
|
||||
|
||||
// Immutable flag's state.
|
||||
|
|
@ -641,7 +659,7 @@ class Flag {
|
|||
impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
|
||||
#endif
|
||||
|
||||
if (!value_.Get(&u.value)) impl_.Read(&u.value);
|
||||
if (!value_.Get(u.value)) impl_.Read(&u.value);
|
||||
return std::move(u.value);
|
||||
}
|
||||
void Set(const T& v) {
|
||||
|
|
@ -649,6 +667,13 @@ class Flag {
|
|||
impl_.Write(&v);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
friend const CommandLineFlag& absl::GetFlagReflectionHandle(
|
||||
const absl::Flag<U>& f);
|
||||
|
||||
// Access to the reflection.
|
||||
const CommandLineFlag& Reflect() const { return impl_; }
|
||||
|
||||
// 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
|
||||
|
|
@ -720,12 +745,12 @@ 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_);
|
||||
explicit FlagRegistrar(Flag<T>& flag) : flag_(flag) {
|
||||
if (do_register) flags_internal::RegisterCommandLineFlag(flag_.impl_);
|
||||
}
|
||||
|
||||
FlagRegistrar OnUpdate(FlagCallbackFunc cb) && {
|
||||
flag_->impl_.SetCallback(cb);
|
||||
flag_.impl_.SetCallback(cb);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -735,7 +760,7 @@ class FlagRegistrar {
|
|||
operator FlagRegistrarEmpty() const { return {}; } // NOLINT
|
||||
|
||||
private:
|
||||
Flag<T>* flag_; // Flag being registered (not owned).
|
||||
Flag<T>& flag_; // Flag being registered (not owned).
|
||||
};
|
||||
|
||||
} // namespace flags_internal
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/flags/declare.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
ABSL_DECLARE_FLAG(std::vector<std::string>, flagfile);
|
||||
ABSL_DECLARE_FLAG(std::vector<std::string>, fromenv);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
#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 {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,14 @@
|
|||
|
||||
#include "absl/flags/internal/private_handle_accessor.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/flags/commandlineflag.h"
|
||||
#include "absl/flags/internal/commandlineflag.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace flags_internal {
|
||||
|
|
@ -24,8 +32,8 @@ FlagFastTypeId PrivateHandleAccessor::TypeId(const CommandLineFlag& flag) {
|
|||
}
|
||||
|
||||
std::unique_ptr<FlagStateInterface> PrivateHandleAccessor::SaveState(
|
||||
CommandLineFlag* flag) {
|
||||
return flag->SaveState();
|
||||
CommandLineFlag& flag) {
|
||||
return flag.SaveState();
|
||||
}
|
||||
|
||||
bool PrivateHandleAccessor::IsSpecifiedOnCommandLine(
|
||||
|
|
@ -43,12 +51,12 @@ void PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
|
|||
flag.CheckDefaultValueParsingRoundtrip();
|
||||
}
|
||||
|
||||
bool PrivateHandleAccessor::ParseFrom(CommandLineFlag* flag,
|
||||
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);
|
||||
std::string& error) {
|
||||
return flag.ParseFrom(value, set_mode, source, error);
|
||||
}
|
||||
|
||||
} // namespace flags_internal
|
||||
|
|
|
|||
|
|
@ -16,7 +16,13 @@
|
|||
#ifndef ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
|
||||
#define ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/flags/commandlineflag.h"
|
||||
#include "absl/flags/internal/commandlineflag.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
|
@ -31,7 +37,7 @@ class PrivateHandleAccessor {
|
|||
static FlagFastTypeId TypeId(const CommandLineFlag& flag);
|
||||
|
||||
// Access to CommandLineFlag::SaveState.
|
||||
static std::unique_ptr<FlagStateInterface> SaveState(CommandLineFlag* flag);
|
||||
static std::unique_ptr<FlagStateInterface> SaveState(CommandLineFlag& flag);
|
||||
|
||||
// Access to CommandLineFlag::IsSpecifiedOnCommandLine.
|
||||
static bool IsSpecifiedOnCommandLine(const CommandLineFlag& flag);
|
||||
|
|
@ -43,9 +49,9 @@ class PrivateHandleAccessor {
|
|||
// Access to CommandLineFlag::CheckDefaultValueParsingRoundtrip.
|
||||
static void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag);
|
||||
|
||||
static bool ParseFrom(CommandLineFlag* flag, absl::string_view value,
|
||||
static bool ParseFrom(CommandLineFlag& flag, absl::string_view value,
|
||||
flags_internal::FlagSettingMode set_mode,
|
||||
flags_internal::ValueSource source, std::string* error);
|
||||
flags_internal::ValueSource source, std::string& error);
|
||||
};
|
||||
|
||||
} // namespace flags_internal
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace {
|
|||
|
||||
namespace flags = absl::flags_internal;
|
||||
|
||||
TEST(FlagsPathUtilTest, TestInitialProgamName) {
|
||||
TEST(FlagsPathUtilTest, TestProgamNameInterfaces) {
|
||||
flags::SetProgramInvocationName("absl/flags/program_name_test");
|
||||
std::string program_name = flags::ProgramInvocationName();
|
||||
for (char& c : program_name)
|
||||
|
|
@ -43,9 +43,7 @@ TEST(FlagsPathUtilTest, TestInitialProgamName) {
|
|||
|
||||
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");
|
||||
|
|
|
|||
|
|
@ -17,11 +17,9 @@
|
|||
#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/commandlineflag.h"
|
||||
#include "absl/flags/internal/commandlineflag.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
|
|
@ -32,19 +30,16 @@ 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);
|
||||
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);
|
||||
void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool RegisterCommandLineFlag(CommandLineFlag*);
|
||||
bool RegisterCommandLineFlag(CommandLineFlag&);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Retired registrations:
|
||||
|
|
@ -87,36 +82,6 @@ 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
|
||||
|
|
|
|||
|
|
@ -1,86 +0,0 @@
|
|||
//
|
||||
// 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
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
//
|
||||
// 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_
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
//
|
||||
// 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
|
||||
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
#include "absl/flags/internal/usage.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
|
|
@ -23,8 +25,8 @@
|
|||
#include <vector>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/flags/commandlineflag.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"
|
||||
|
|
@ -107,8 +109,8 @@ 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),
|
||||
FlagHelpPrettyPrinter(int max_line_len, std::ostream& out)
|
||||
: out_(out),
|
||||
max_line_len_(max_line_len),
|
||||
line_len_(0),
|
||||
first_line_(true) {}
|
||||
|
|
@ -182,8 +184,7 @@ class FlagHelpPrettyPrinter {
|
|||
bool first_line_;
|
||||
};
|
||||
|
||||
void FlagHelpHumanReadable(const flags_internal::CommandLineFlag& flag,
|
||||
std::ostream* out) {
|
||||
void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
|
||||
FlagHelpPrettyPrinter printer(80, out); // Max line length is 80.
|
||||
|
||||
// Flag name.
|
||||
|
|
@ -245,30 +246,28 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
|
|||
// 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*>>>
|
||||
std::map<std::string, std::vector<const absl::CommandLineFlag*>>>
|
||||
matching_flags;
|
||||
|
||||
flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) {
|
||||
std::string flag_filename = flag->Filename();
|
||||
flags_internal::ForEachFlag([&](absl::CommandLineFlag& flag) {
|
||||
std::string flag_filename = flag.Filename();
|
||||
|
||||
// Ignore retired flags.
|
||||
if (flag->IsRetired()) return;
|
||||
if (flag.IsRetired()) return;
|
||||
|
||||
// If the flag has been stripped, pretend that it doesn't exist.
|
||||
if (flag->Help() == flags_internal::kStrippedFlagHelp) return;
|
||||
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);
|
||||
.push_back(&flag);
|
||||
});
|
||||
|
||||
absl::string_view
|
||||
package_separator; // controls blank lines between packages.
|
||||
absl::string_view file_separator; // controls blank lines between files.
|
||||
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;
|
||||
|
|
@ -303,10 +302,10 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
|
|||
|
||||
// --------------------------------------------------------------------
|
||||
// Produces the help message describing specific flag.
|
||||
void FlagHelp(std::ostream& out, const flags_internal::CommandLineFlag& flag,
|
||||
void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
|
||||
HelpFormat format) {
|
||||
if (format == HelpFormat::kHumanReadable)
|
||||
flags_internal::FlagHelpHumanReadable(flag, &out);
|
||||
flags_internal::FlagHelpHumanReadable(flag, out);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
#include <string>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/flags/commandlineflag.h"
|
||||
#include "absl/flags/declare.h"
|
||||
#include "absl/flags/internal/commandlineflag.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
|
@ -37,7 +37,7 @@ enum class HelpFormat {
|
|||
};
|
||||
|
||||
// Outputs the help message describing specific flag.
|
||||
void FlagHelp(std::ostream& out, const flags_internal::CommandLineFlag& flag,
|
||||
void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
|
||||
HelpFormat format = HelpFormat::kHumanReadable);
|
||||
|
||||
// Produces the help messages for all flags matching the filter. A flag matches
|
||||
|
|
|
|||
|
|
@ -21,15 +21,13 @@
|
|||
#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/reflection.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"
|
||||
|
||||
|
|
@ -91,7 +89,7 @@ class UsageReportingTest : public testing::Test {
|
|||
}
|
||||
|
||||
private:
|
||||
flags::FlagSaver flag_saver_;
|
||||
absl::FlagSaver flag_saver_;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
|
@ -112,7 +110,7 @@ TEST_F(UsageReportingDeathTest, TestSetProgramUsageMessage) {
|
|||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) {
|
||||
const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_01");
|
||||
const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_01");
|
||||
std::stringstream test_buf;
|
||||
|
||||
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
|
||||
|
|
@ -124,7 +122,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) {
|
|||
}
|
||||
|
||||
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) {
|
||||
const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_02");
|
||||
const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_02");
|
||||
std::stringstream test_buf;
|
||||
|
||||
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
|
||||
|
|
@ -136,7 +134,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) {
|
|||
}
|
||||
|
||||
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) {
|
||||
const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_03");
|
||||
const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_03");
|
||||
std::stringstream test_buf;
|
||||
|
||||
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
|
||||
|
|
@ -148,7 +146,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) {
|
|||
}
|
||||
|
||||
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) {
|
||||
const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_04");
|
||||
const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_04");
|
||||
std::stringstream test_buf;
|
||||
|
||||
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
|
||||
|
|
@ -160,7 +158,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) {
|
|||
}
|
||||
|
||||
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_05) {
|
||||
const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_05");
|
||||
const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_05");
|
||||
std::stringstream test_buf;
|
||||
|
||||
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
|
||||
|
|
|
|||
|
|
@ -74,15 +74,16 @@ static int NumericBase(absl::string_view text) {
|
|||
}
|
||||
|
||||
template <typename IntType>
|
||||
inline bool ParseFlagImpl(absl::string_view text, IntType* dst) {
|
||||
inline bool ParseFlagImpl(absl::string_view text, IntType& dst) {
|
||||
text = absl::StripAsciiWhitespace(text);
|
||||
|
||||
return absl::numbers_internal::safe_strtoi_base(text, dst, NumericBase(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 (!ParseFlagImpl(text, val)) return false;
|
||||
if (static_cast<short>(val) != val) // worked, but number out of range
|
||||
return false;
|
||||
*dst = static_cast<short>(val);
|
||||
|
|
@ -91,7 +92,7 @@ bool AbslParseFlag(absl::string_view text, short* dst, std::string*) {
|
|||
|
||||
bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {
|
||||
unsigned int val;
|
||||
if (!ParseFlagImpl(text, &val)) return false;
|
||||
if (!ParseFlagImpl(text, val)) return false;
|
||||
if (static_cast<unsigned short>(val) !=
|
||||
val) // worked, but number out of range
|
||||
return false;
|
||||
|
|
@ -100,28 +101,28 @@ bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {
|
|||
}
|
||||
|
||||
bool AbslParseFlag(absl::string_view text, int* dst, std::string*) {
|
||||
return ParseFlagImpl(text, dst);
|
||||
return ParseFlagImpl(text, *dst);
|
||||
}
|
||||
|
||||
bool AbslParseFlag(absl::string_view text, unsigned int* dst, std::string*) {
|
||||
return ParseFlagImpl(text, dst);
|
||||
return ParseFlagImpl(text, *dst);
|
||||
}
|
||||
|
||||
bool AbslParseFlag(absl::string_view text, long* dst, std::string*) {
|
||||
return ParseFlagImpl(text, dst);
|
||||
return ParseFlagImpl(text, *dst);
|
||||
}
|
||||
|
||||
bool AbslParseFlag(absl::string_view text, unsigned long* dst, std::string*) {
|
||||
return ParseFlagImpl(text, dst);
|
||||
return ParseFlagImpl(text, *dst);
|
||||
}
|
||||
|
||||
bool AbslParseFlag(absl::string_view text, long long* dst, std::string*) {
|
||||
return ParseFlagImpl(text, dst);
|
||||
return ParseFlagImpl(text, *dst);
|
||||
}
|
||||
|
||||
bool AbslParseFlag(absl::string_view text, unsigned long long* dst,
|
||||
std::string*) {
|
||||
return ParseFlagImpl(text, dst);
|
||||
return ParseFlagImpl(text, *dst);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "absl/base/config.h"
|
||||
#include "absl/base/const_init.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/flags/commandlineflag.h"
|
||||
#include "absl/flags/config.h"
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/flags/internal/commandlineflag.h"
|
||||
|
|
@ -41,8 +42,8 @@
|
|||
#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/reflection.h"
|
||||
#include "absl/flags/usage.h"
|
||||
#include "absl/flags/usage_config.h"
|
||||
#include "absl/strings/ascii.h"
|
||||
|
|
@ -222,7 +223,7 @@ bool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) {
|
|||
// 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) {
|
||||
bool GetEnvVar(const char* var_name, std::string& var_value) {
|
||||
#ifdef _WIN32
|
||||
char buf[1024];
|
||||
auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf));
|
||||
|
|
@ -234,14 +235,14 @@ bool GetEnvVar(const char* var_name, std::string* var_value) {
|
|||
return false;
|
||||
}
|
||||
|
||||
*var_value = std::string(buf, get_res);
|
||||
var_value = std::string(buf, get_res);
|
||||
#else
|
||||
const char* val = ::getenv(var_name);
|
||||
if (val == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*var_value = val;
|
||||
var_value = val;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
|
@ -289,11 +290,11 @@ std::tuple<absl::string_view, absl::string_view, bool> SplitNameAndValue(
|
|||
// 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);
|
||||
CommandLineFlag* flag = absl::FindCommandLineFlag(flag_name);
|
||||
bool is_negative = false;
|
||||
|
||||
if (!flag && absl::ConsumePrefix(&flag_name, "no")) {
|
||||
flag = flags_internal::FindCommandLineFlag(flag_name);
|
||||
flag = absl::FindCommandLineFlag(flag_name);
|
||||
is_negative = true;
|
||||
}
|
||||
|
||||
|
|
@ -306,17 +307,17 @@ std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) {
|
|||
// back.
|
||||
void CheckDefaultValuesParsingRoundtrip() {
|
||||
#ifndef NDEBUG
|
||||
flags_internal::ForEachFlag([&](CommandLineFlag* flag) {
|
||||
if (flag->IsRetired()) return;
|
||||
flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
|
||||
if (flag.IsRetired()) return;
|
||||
|
||||
#define ABSL_FLAGS_INTERNAL_IGNORE_TYPE(T, _) \
|
||||
if (flag->IsOfType<T>()) return;
|
||||
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);
|
||||
flag);
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
|
@ -329,13 +330,13 @@ void CheckDefaultValuesParsingRoundtrip() {
|
|||
// 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) {
|
||||
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);
|
||||
input_args.push_back(al);
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
|
|
@ -350,7 +351,7 @@ bool ReadFlagfiles(const std::vector<std::string>& flagfiles,
|
|||
// `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,
|
||||
std::vector<ArgsList>& input_args,
|
||||
bool fail_on_absent_in_env) {
|
||||
bool success = true;
|
||||
std::vector<std::string> args;
|
||||
|
|
@ -371,7 +372,7 @@ bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
|
|||
|
||||
const std::string envname = absl::StrCat("FLAGS_", flag_name);
|
||||
std::string envval;
|
||||
if (!GetEnvVar(envname.c_str(), &envval)) {
|
||||
if (!GetEnvVar(envname.c_str(), envval)) {
|
||||
if (fail_on_absent_in_env) {
|
||||
flags_internal::ReportUsageError(
|
||||
absl::StrCat(envname, " not found in environment"), true);
|
||||
|
|
@ -386,7 +387,7 @@ bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
|
|||
}
|
||||
|
||||
if (success) {
|
||||
input_args->emplace_back(args);
|
||||
input_args.emplace_back(args);
|
||||
}
|
||||
|
||||
return success;
|
||||
|
|
@ -396,8 +397,8 @@ bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
|
|||
|
||||
// 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 HandleGeneratorFlags(std::vector<ArgsList>& input_args,
|
||||
std::vector<std::string>& flagfile_value) {
|
||||
bool success = true;
|
||||
|
||||
absl::MutexLock l(&flags_internal::processing_checks_guard);
|
||||
|
|
@ -422,9 +423,9 @@ bool HandleGeneratorFlags(std::vector<ArgsList>* input_args,
|
|||
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());
|
||||
if (input_args.size() == 1) {
|
||||
flagfile_value.insert(flagfile_value.end(), flagfiles.begin(),
|
||||
flagfiles.end());
|
||||
}
|
||||
|
||||
success &= ReadFlagfiles(flagfiles, input_args);
|
||||
|
|
@ -647,7 +648,7 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
|
|||
bool success = true;
|
||||
while (!input_args.empty()) {
|
||||
// 10. First we process the built-in generator flags.
|
||||
success &= HandleGeneratorFlags(&input_args, &flagfile_value);
|
||||
success &= HandleGeneratorFlags(input_args, flagfile_value);
|
||||
|
||||
// 30. Select top-most (most recent) arguments list. If it is empty drop it
|
||||
// and re-try.
|
||||
|
|
@ -733,7 +734,7 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
|
|||
|
||||
std::string error;
|
||||
if (!flags_internal::PrivateHandleAccessor::ParseFrom(
|
||||
flag, value, SET_FLAGS_VALUE, kCommandLine, &error)) {
|
||||
*flag, value, SET_FLAGS_VALUE, kCommandLine, error)) {
|
||||
flags_internal::ReportUsageError(error, true);
|
||||
success = false;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#ifndef ABSL_FLAGS_PARSE_H_
|
||||
#define ABSL_FLAGS_PARSE_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#include "absl/flags/declare.h"
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/flags/internal/parse.h"
|
||||
#include "absl/flags/internal/registry.h"
|
||||
#include "absl/flags/reflection.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/strings/substitute.h"
|
||||
|
|
@ -171,8 +171,8 @@ constexpr const char* const ff2_data[] = {
|
|||
// 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=";
|
||||
std::string& flagfile_flag) {
|
||||
flagfile_flag = "--flagfile=";
|
||||
absl::string_view separator;
|
||||
for (const auto& flagfile_data : ffd) {
|
||||
std::string flagfile_name =
|
||||
|
|
@ -183,11 +183,11 @@ const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd,
|
|||
flagfile_out << absl::Substitute(line, GetTestTempDir()) << "\n";
|
||||
}
|
||||
|
||||
absl::StrAppend(flagfile_flag, separator, flagfile_name);
|
||||
absl::StrAppend(&flagfile_flag, separator, flagfile_name);
|
||||
separator = ",";
|
||||
}
|
||||
|
||||
return flagfile_flag->c_str();
|
||||
return flagfile_flag.c_str();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
@ -208,7 +208,7 @@ using testing::ElementsAreArray;
|
|||
|
||||
class ParseTest : public testing::Test {
|
||||
private:
|
||||
flags::FlagSaver flag_saver_;
|
||||
absl::FlagSaver flag_saver_;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
|
@ -588,14 +588,14 @@ TEST_F(ParseTest, TestSimpleValidFlagfile) {
|
|||
const char* in_args1[] = {
|
||||
"testbin",
|
||||
GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
|
||||
&flagfile_flag),
|
||||
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),
|
||||
flagfile_flag),
|
||||
};
|
||||
TestParse(in_args2, 100, 0.1, "q2w2 ", false);
|
||||
}
|
||||
|
|
@ -609,7 +609,7 @@ TEST_F(ParseTest, TestValidMultiFlagfile) {
|
|||
"testbin",
|
||||
GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
|
||||
{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
|
||||
&flagfile_flag),
|
||||
flagfile_flag),
|
||||
};
|
||||
TestParse(in_args1, -1, 0.1, "q2w2 ", true);
|
||||
}
|
||||
|
|
@ -622,7 +622,7 @@ TEST_F(ParseTest, TestFlagfileMixedWithRegularFlags) {
|
|||
const char* in_args1[] = {
|
||||
"testbin", "--int_flag=3",
|
||||
GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
|
||||
&flagfile_flag),
|
||||
flagfile_flag),
|
||||
"-double_flag=0.2"};
|
||||
TestParse(in_args1, -1, 0.2, "q2w2 ", true);
|
||||
}
|
||||
|
|
@ -637,10 +637,14 @@ TEST_F(ParseTest, TestFlagfileInFlagfile) {
|
|||
"--flagfile=$0/parse_test.ff2",
|
||||
};
|
||||
|
||||
GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
|
||||
{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
|
||||
flagfile_flag);
|
||||
|
||||
const char* in_args1[] = {
|
||||
"testbin",
|
||||
GetFlagfileFlag({{"parse_test.ff3", absl::MakeConstSpan(ff3_data)}},
|
||||
&flagfile_flag),
|
||||
flagfile_flag),
|
||||
};
|
||||
TestParse(in_args1, 100, 0.1, "q2w2 ", false);
|
||||
}
|
||||
|
|
@ -657,7 +661,7 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
|
|||
const char* in_args1[] = {
|
||||
"testbin",
|
||||
GetFlagfileFlag({{"parse_test.ff4",
|
||||
absl::MakeConstSpan(ff4_data)}}, &flagfile_flag),
|
||||
absl::MakeConstSpan(ff4_data)}}, flagfile_flag),
|
||||
};
|
||||
EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
|
||||
"Unknown command line flag 'unknown_flag'");
|
||||
|
|
@ -669,7 +673,7 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
|
|||
const char* in_args2[] = {
|
||||
"testbin",
|
||||
GetFlagfileFlag({{"parse_test.ff5",
|
||||
absl::MakeConstSpan(ff5_data)}}, &flagfile_flag),
|
||||
absl::MakeConstSpan(ff5_data)}}, flagfile_flag),
|
||||
};
|
||||
EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
|
||||
"Unknown command line flag 'int_flag 10'");
|
||||
|
|
@ -681,7 +685,7 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
|
|||
const char* in_args3[] = {
|
||||
"testbin",
|
||||
GetFlagfileFlag({{"parse_test.ff6", absl::MakeConstSpan(ff6_data)}},
|
||||
&flagfile_flag),
|
||||
flagfile_flag),
|
||||
};
|
||||
EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
|
||||
"Flagfile can't contain position arguments or --");
|
||||
|
|
@ -702,7 +706,7 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
|
|||
const char* in_args5[] = {
|
||||
"testbin",
|
||||
GetFlagfileFlag({{"parse_test.ff7", absl::MakeConstSpan(ff7_data)}},
|
||||
&flagfile_flag),
|
||||
flagfile_flag),
|
||||
};
|
||||
EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args5),
|
||||
"Unexpected line in the flagfile .*: \\*bin\\*");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright 2019 The Abseil Authors.
|
||||
// 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.
|
||||
|
|
@ -13,46 +13,34 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/flags/internal/registry.h"
|
||||
#include "absl/flags/reflection.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/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/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.
|
||||
// A FlagRegistry singleton object holds all flag objects indexed by their
|
||||
// names so that if you know a flag's name, 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 {
|
||||
|
|
@ -60,8 +48,8 @@ class FlagRegistry {
|
|||
FlagRegistry() = default;
|
||||
~FlagRegistry() = default;
|
||||
|
||||
// Store a flag in this registry. Takes ownership of *flag.
|
||||
void RegisterFlag(CommandLineFlag* flag);
|
||||
// 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(); }
|
||||
|
|
@ -74,12 +62,13 @@ class FlagRegistry {
|
|||
// found or not retired. Does not emit a warning.
|
||||
CommandLineFlag* FindRetiredFlagLocked(absl::string_view name);
|
||||
|
||||
static FlagRegistry* GlobalRegistry(); // returns a singleton registry
|
||||
static FlagRegistry& GlobalRegistry(); // returns a singleton registry
|
||||
|
||||
private:
|
||||
friend class FlagSaverImpl; // reads all the flags in order to copy them
|
||||
friend class flags_internal::FlagSaverImpl; // reads all the flags in order
|
||||
// to copy them
|
||||
friend void ForEachFlagUnlocked(
|
||||
std::function<void(CommandLineFlag*)> visitor);
|
||||
std::function<void(CommandLineFlag&)> visitor);
|
||||
|
||||
// The map from name to flag, for FindFlagLocked().
|
||||
using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
|
||||
|
|
@ -94,74 +83,6 @@ class 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()) {
|
||||
|
|
@ -185,97 +106,92 @@ CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) {
|
|||
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.
|
||||
// --------------------------------------------------------------------
|
||||
namespace {
|
||||
|
||||
class FlagSaverImpl {
|
||||
class FlagRegistryLock {
|
||||
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();
|
||||
}
|
||||
}
|
||||
explicit FlagRegistryLock(FlagRegistry& fr) : fr_(fr) { fr_.Lock(); }
|
||||
~FlagRegistryLock() { fr_.Unlock(); }
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<flags_internal::FlagStateInterface>>
|
||||
backup_registry_;
|
||||
FlagRegistry& fr_;
|
||||
};
|
||||
|
||||
FlagSaver::FlagSaver() : impl_(new FlagSaverImpl) { impl_->SaveFromRegistry(); }
|
||||
void DestroyRetiredFlag(CommandLineFlag& flag);
|
||||
|
||||
void FlagSaver::Ignore() {
|
||||
delete impl_;
|
||||
impl_ = nullptr;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
|
||||
void ForEachFlag(std::function<void(CommandLineFlag*)> visitor) {
|
||||
FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
|
||||
FlagRegistry& FlagRegistry::GlobalRegistry() {
|
||||
static FlagRegistry* global_registry = new FlagRegistry;
|
||||
return *global_registry;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void ForEachFlagUnlocked(std::function<void(CommandLineFlag&)> visitor) {
|
||||
FlagRegistry& 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& registry = FlagRegistry::GlobalRegistry();
|
||||
FlagRegistryLock frl(registry);
|
||||
ForEachFlagUnlocked(visitor);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
bool RegisterCommandLineFlag(CommandLineFlag* flag) {
|
||||
FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
|
||||
bool RegisterCommandLineFlag(CommandLineFlag& flag) {
|
||||
FlagRegistry::GlobalRegistry().RegisterFlag(flag);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -283,7 +199,7 @@ bool RegisterCommandLineFlag(CommandLineFlag* flag) {
|
|||
|
||||
namespace {
|
||||
|
||||
class RetiredFlagObj final : public flags_internal::CommandLineFlag {
|
||||
class RetiredFlagObj final : public CommandLineFlag {
|
||||
public:
|
||||
constexpr RetiredFlagObj(const char* name, FlagFastTypeId type_id)
|
||||
: name_(name), type_id_(type_id) {}
|
||||
|
|
@ -306,7 +222,7 @@ class RetiredFlagObj final : public flags_internal::CommandLineFlag {
|
|||
}
|
||||
|
||||
bool ParseFrom(absl::string_view, flags_internal::FlagSettingMode,
|
||||
flags_internal::ValueSource, std::string*) override {
|
||||
flags_internal::ValueSource, std::string&) override {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -319,32 +235,74 @@ class RetiredFlagObj final : public flags_internal::CommandLineFlag {
|
|||
const FlagFastTypeId type_id_;
|
||||
};
|
||||
|
||||
void DestroyRetiredFlag(flags_internal::CommandLineFlag* flag) {
|
||||
assert(flag->IsRetired());
|
||||
delete static_cast<RetiredFlagObj*>(flag);
|
||||
void DestroyRetiredFlag(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);
|
||||
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;
|
||||
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([&](CommandLineFlag& flag) {
|
||||
if (auto flag_state =
|
||||
flags_internal::PrivateHandleAccessor::SaveState(flag)) {
|
||||
backup_registry_.emplace_back(std::move(flag_state));
|
||||
}
|
||||
});
|
||||
}
|
||||
assert(type_is_bool);
|
||||
*type_is_bool = flag->IsOfType<bool>();
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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_;
|
||||
};
|
||||
|
||||
} // namespace flags_internal
|
||||
|
||||
FlagSaver::FlagSaver() : impl_(new flags_internal::FlagSaverImpl) {
|
||||
impl_->SaveFromRegistry();
|
||||
}
|
||||
|
||||
FlagSaver::~FlagSaver() {
|
||||
if (!impl_) return;
|
||||
|
||||
impl_->RestoreToRegistry();
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
|
||||
if (name.empty()) return nullptr;
|
||||
flags_internal::FlagRegistry& registry =
|
||||
flags_internal::FlagRegistry::GlobalRegistry();
|
||||
flags_internal::FlagRegistryLock frl(registry);
|
||||
|
||||
return registry.FindFlagLocked(name);
|
||||
}
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
85
absl/flags/reflection.h
Normal file
85
absl/flags/reflection.h
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: reflection.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// This file defines the routines to access and operate on an Abseil Flag's
|
||||
// reflection handle.
|
||||
|
||||
#ifndef ABSL_FLAGS_REFLECTION_H_
|
||||
#define ABSL_FLAGS_REFLECTION_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/flags/commandlineflag.h"
|
||||
#include "absl/flags/internal/commandlineflag.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace flags_internal {
|
||||
class FlagSaverImpl;
|
||||
} // namespace flags_internal
|
||||
|
||||
// FindCommandLineFlag()
|
||||
//
|
||||
// Returns the reflection handle of an Abseil flag of the specified name, or
|
||||
// `nullptr` if not found. This function will emit a warning if the name of a
|
||||
// 'retired' flag is specified.
|
||||
CommandLineFlag* FindCommandLineFlag(absl::string_view name);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FlagSaver
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// A FlagSaver object stores the state of flags in the scope where the FlagSaver
|
||||
// is defined, allowing modification of those flags within that scope and
|
||||
// automatic restoration of the flags to their previous state upon leaving the
|
||||
// scope.
|
||||
//
|
||||
// A FlagSaver can be used within tests to temporarily change the test
|
||||
// environment and restore the test case to its previous state.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// void MyFunc() {
|
||||
// absl::FlagSaver fs;
|
||||
// ...
|
||||
// absl::SetFlag(FLAGS_myFlag, otherValue);
|
||||
// ...
|
||||
// } // scope of FlagSaver left, flags return to previous state
|
||||
//
|
||||
// This class is thread-safe.
|
||||
|
||||
class FlagSaver {
|
||||
public:
|
||||
FlagSaver();
|
||||
~FlagSaver();
|
||||
|
||||
FlagSaver(const FlagSaver&) = delete;
|
||||
void operator=(const FlagSaver&) = delete;
|
||||
|
||||
private:
|
||||
flags_internal::FlagSaverImpl* impl_;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_FLAGS_REFLECTION_H_
|
||||
60
absl/flags/reflection_test.cc
Normal file
60
absl/flags/reflection_test.cc
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/reflection.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/flags/internal/commandlineflag.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 ReflectionTest : public testing::Test {
|
||||
protected:
|
||||
void SetUp() override { flag_saver_ = absl::make_unique<absl::FlagSaver>(); }
|
||||
void TearDown() override { flag_saver_.reset(); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<absl::FlagSaver> flag_saver_;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(ReflectionTest, TestFindCommandLineFlag) {
|
||||
auto* handle = absl::FindCommandLineFlag("some_flag");
|
||||
EXPECT_EQ(handle, nullptr);
|
||||
|
||||
handle = absl::FindCommandLineFlag("int_flag");
|
||||
EXPECT_NE(handle, nullptr);
|
||||
|
||||
handle = absl::FindCommandLineFlag("string_flag");
|
||||
EXPECT_NE(handle, nullptr);
|
||||
|
||||
handle = absl::FindCommandLineFlag("bool_retired_flag");
|
||||
EXPECT_NE(handle, nullptr);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "absl/flags/usage_config.h"
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue