Commit 159bf2bf by Abseil Team Committed by Xiaoyi Zhang

Export of internal Abseil changes

--
c42a234e2c186bf697ce8d77e85628601fa514a6 by Abseil Team <absl-team@google.com>:

Enable the assertion in the iterator's operator++

PiperOrigin-RevId: 290134813

--
f8c53ba8e9c5bb16bbcc1e412a5c2519c912c83e by Abseil Team <absl-team@google.com>:

Define operator== and operator!= for absl::{weak,strong}_equality and
absl::{partial,weak,strong}_ordering types themselves.

PiperOrigin-RevId: 290111564

--
36bc574090cefad74a451719ce2761982647a51d by Tom Manshreck <shreck@google.com>:

Specify Time library flag formats

PiperOrigin-RevId: 289928010

--
26dd40281add260baab2b60fec05dfb9c5304aaa by Mark Barolak <mbar@google.com>:

Delete an extraneous forward declaration of absl::Cord.

PiperOrigin-RevId: 289708481

--
e60aea7f33554ff66d7699bb70e7af1d26323f1d by Abseil Team <absl-team@google.com>:

Release b-tree benchmarks.

PiperOrigin-RevId: 289654429

--
660aa83fa000d4bae072b2d1c790f81d0939bc7e by Greg Falcon <gfalcon@google.com>:

Use https links.

Import of https://github.com/abseil/abseil-cpp/pull/586

PiperOrigin-RevId: 289479559

--
0611ea4482dcf23d6b0a0389fe041eeb9052449a by Derek Mauro <dmauro@google.com>:

Removes the static initializer for LookupTables<absl::uint128>::kVmaxOverBase

Uses template specialization to hard code the resulting array.

Static initializers are problematic for a number of reasons. Not only
are they responsible for the static initialization order fiasco, but
they are in the critical path during program startup. For these
reasons, the Google C++ style guide strongly discourages them (and
forbids them when they are not trivially destructible), and Chromium
even has a test forbidding them.

https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
https://chromium.googlesource.com/chromium/src.git/+/master/docs/static_initializers.md
http://neugierig.org/software/chromium/notes/2011/08/static-initializers.html

PiperOrigin-RevId: 289458677

--
c869362f6bb7a872314f74750d38d81bdaa73f95 by Greg Falcon <gfalcon@google.com>:

Step 2 of 2 to fix our CCTZ fork to respect inline namespaces.

Re-import of CCTZ from GitHub, applying new changes to honor Abseil's optional inline namespace in MSVC.

PiperOrigin-RevId: 289454407

--
fdb3474d76c2ee0371ccdf7593a78137c03a3f58 by Greg Falcon <gfalcon@google.com>:

Step 1 of 2 to fix our CCTZ fork to respect inline namespaces.

CCTZ uses a linker flag to simulate weak symbol support in MSVC.  This takes the form of a #pragma that includes the mangled names of two types: the symbol to treat as weak, and the symbol to use as its default value if no override is provided.

When Abseil is configured to use inline namespaces, the mangled names of these symbols change, and the pragma should change to reflect that.  Fortunately for us, MSVC name mangling is simple enough that we can generate the needed string literals in the preprocessor.

This CL introduces the new macros; the uses will be introduced in a follow-up CL.

PiperOrigin-RevId: 289435599

--
5f152cc36f008acb9ab78f30b5efa40ebaf2754b by Matt Kulukundis <kfm@google.com>:

Improve documentation for lazy_emplace

PiperOrigin-RevId: 289333112
GitOrigin-RevId: c42a234e2c186bf697ce8d77e85628601fa514a6
Change-Id: I139ce6c7044a70d083af53e428bcb987f0fd88c6
parent a2e6adec
...@@ -66,6 +66,10 @@ ...@@ -66,6 +66,10 @@
#include "absl/base/options.h" #include "absl/base/options.h"
#include "absl/base/policy_checks.h" #include "absl/base/policy_checks.h"
// Helper macro to convert a CPP variable to a string literal.
#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x
#define ABSL_INTERNAL_TOKEN_STR(x) ABSL_INTERNAL_DO_TOKEN_STR(x)
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Abseil namespace annotations // Abseil namespace annotations
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -98,8 +102,6 @@ ...@@ -98,8 +102,6 @@
// Check that ABSL_OPTION_INLINE_NAMESPACE_NAME is neither "head" nor "" // Check that ABSL_OPTION_INLINE_NAMESPACE_NAME is neither "head" nor ""
#if defined(__cplusplus) && ABSL_OPTION_USE_INLINE_NAMESPACE == 1 #if defined(__cplusplus) && ABSL_OPTION_USE_INLINE_NAMESPACE == 1
#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x
#define ABSL_INTERNAL_TOKEN_STR(x) ABSL_INTERNAL_DO_TOKEN_STR(x)
#define ABSL_INTERNAL_INLINE_NAMESPACE_STR \ #define ABSL_INTERNAL_INLINE_NAMESPACE_STR \
ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME)
...@@ -617,6 +619,28 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || ...@@ -617,6 +619,28 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_INTERNAL_MSVC_2017_DBG_MODE #define ABSL_INTERNAL_MSVC_2017_DBG_MODE
#endif #endif
// ABSL_INTERNAL_MANGLED_NS
// ABSL_INTERNAL_MANGLED_BACKREFERENCE
//
// Internal macros for building up mangled names in our internal fork of CCTZ.
// This implementation detail is only needed and provided for the MSVC build.
//
// These macros both expand to string literals. ABSL_INTERNAL_MANGLED_NS is
// the mangled spelling of the `absl` namespace, and
// ABSL_INTERNAL_MANGLED_BACKREFERENCE is a back-reference integer representing
// the proper count to skip past the CCTZ fork namespace names. (This number
// is one larger when there is an inline namespace name to skip.)
#if defined(_MSC_VER)
#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0
#define ABSL_INTERNAL_MANGLED_NS "absl"
#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "5"
#else
#define ABSL_INTERNAL_MANGLED_NS \
ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) "@absl"
#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "6"
#endif
#endif
#undef ABSL_INTERNAL_HAS_KEYWORD #undef ABSL_INTERNAL_HAS_KEYWORD
#endif // ABSL_BASE_CONFIG_H_ #endif // ABSL_BASE_CONFIG_H_
...@@ -874,3 +874,29 @@ cc_test( ...@@ -874,3 +874,29 @@ cc_test(
"@com_google_googletest//:gtest_main", "@com_google_googletest//:gtest_main",
], ],
) )
cc_binary(
name = "btree_benchmark",
testonly = 1,
srcs = [
"btree_benchmark.cc",
],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
tags = ["benchmark"],
visibility = ["//visibility:private"],
deps = [
":btree",
":btree_test_common",
":flat_hash_map",
":flat_hash_set",
":hashtable_debug",
"//absl/base:raw_logging_internal",
"//absl/flags:flag",
"//absl/hash",
"//absl/memory",
"//absl/strings:str_format",
"//absl/time",
"@com_github_google_benchmark//:benchmark_main",
],
)
...@@ -625,7 +625,7 @@ class raw_hash_set { ...@@ -625,7 +625,7 @@ class raw_hash_set {
// PRECONDITION: not an end() iterator. // PRECONDITION: not an end() iterator.
iterator& operator++() { iterator& operator++() {
/* To be enabled: assert_is_full(); */ assert_is_full();
++ctrl_; ++ctrl_;
++slot_; ++slot_;
skip_empty_or_deleted(); skip_empty_or_deleted();
...@@ -1084,10 +1084,15 @@ class raw_hash_set { ...@@ -1084,10 +1084,15 @@ class raw_hash_set {
// Extension API: support for lazy emplace. // Extension API: support for lazy emplace.
// //
// Looks up key in the table. If found, returns the iterator to the element. // Looks up key in the table. If found, returns the iterator to the element.
// Otherwise calls f with one argument of type raw_hash_set::constructor. f // Otherwise calls `f` with one argument of type `raw_hash_set::constructor`.
// MUST call raw_hash_set::constructor with arguments as if a //
// raw_hash_set::value_type is constructed, otherwise the behavior is // `f` must abide by several restrictions:
// undefined. // - it MUST call `raw_hash_set::constructor` with arguments as if a
// `raw_hash_set::value_type` is constructed,
// - it MUST NOT access the container before the call to
// `raw_hash_set::constructor`, and
// - it MUST NOT erase the lazily emplaced element.
// Doing any of these is undefined behavior.
// //
// For example: // For example:
// //
......
...@@ -33,16 +33,16 @@ ...@@ -33,16 +33,16 @@
// * `double` // * `double`
// * `std::string` // * `std::string`
// * `std::vector<std::string>` // * `std::vector<std::string>`
// * `absl::LogSeverity` (provided here due to dependency ordering) // * `absl::LogSeverity` (provided natively for layering reasons)
// //
// Note that support for integral types is implemented using overloads for // Note that support for integral types is implemented using overloads for
// variable-width fundamental types (`short`, `int`, `long`, etc.). However, // variable-width fundamental types (`short`, `int`, `long`, etc.). However,
// you should prefer the fixed-width integral types (`int32_t`, `uint64_t`, // you should prefer the fixed-width integral types (`int32_t`, `uint64_t`,
// etc.) we've noted above within flag definitions. // etc.) we've noted above within flag definitions.
// //
// In addition, several Abseil libraries provide their own custom support for // In addition, several Abseil libraries provide their own custom support for
// Abseil flags. // Abseil flags. Documentation for these formats is provided in the type's
// `AbslParseFlag()` definition.
// //
// The Abseil time library provides the following support for civil time values: // The Abseil time library provides the following support for civil time values:
// //
......
...@@ -27,9 +27,6 @@ ...@@ -27,9 +27,6 @@
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
class Cord;
namespace str_format_internal { namespace str_format_internal {
class FormatRawSinkImpl { class FormatRawSinkImpl {
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "absl/base/attributes.h"
#include "absl/base/internal/bits.h" #include "absl/base/internal/bits.h"
#include "absl/base/internal/raw_logging.h" #include "absl/base/internal/raw_logging.h"
#include "absl/strings/ascii.h" #include "absl/strings/ascii.h"
...@@ -719,8 +720,8 @@ inline bool safe_parse_sign_and_base(absl::string_view* text /*inout*/, ...@@ -719,8 +720,8 @@ inline bool safe_parse_sign_and_base(absl::string_view* text /*inout*/,
// commonly used bases. // commonly used bases.
template <typename IntType> template <typename IntType>
struct LookupTables { struct LookupTables {
static const IntType kVmaxOverBase[]; ABSL_CONST_INIT static const IntType kVmaxOverBase[];
static const IntType kVminOverBase[]; ABSL_CONST_INIT static const IntType kVminOverBase[];
}; };
// An array initializer macro for X/base where base in [0, 36]. // An array initializer macro for X/base where base in [0, 36].
...@@ -735,6 +736,49 @@ struct LookupTables { ...@@ -735,6 +736,49 @@ struct LookupTables {
X / 35, X / 36, \ X / 35, X / 36, \
} }
// uint128& operator/=(uint128) is not constexpr, so hardcode the resulting
// array to avoid a static initializer.
template <>
const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
0,
0,
MakeUint128(9223372036854775807u, 18446744073709551615u),
MakeUint128(6148914691236517205u, 6148914691236517205u),
MakeUint128(4611686018427387903u, 18446744073709551615u),
MakeUint128(3689348814741910323u, 3689348814741910323u),
MakeUint128(3074457345618258602u, 12297829382473034410u),
MakeUint128(2635249153387078802u, 5270498306774157604u),
MakeUint128(2305843009213693951u, 18446744073709551615u),
MakeUint128(2049638230412172401u, 14347467612885206812u),
MakeUint128(1844674407370955161u, 11068046444225730969u),
MakeUint128(1676976733973595601u, 8384883669867978007u),
MakeUint128(1537228672809129301u, 6148914691236517205u),
MakeUint128(1418980313362273201u, 4256940940086819603u),
MakeUint128(1317624576693539401u, 2635249153387078802u),
MakeUint128(1229782938247303441u, 1229782938247303441u),
MakeUint128(1152921504606846975u, 18446744073709551615u),
MakeUint128(1085102592571150095u, 1085102592571150095u),
MakeUint128(1024819115206086200u, 16397105843297379214u),
MakeUint128(970881267037344821u, 16504981539634861972u),
MakeUint128(922337203685477580u, 14757395258967641292u),
MakeUint128(878416384462359600u, 14054662151397753612u),
MakeUint128(838488366986797800u, 13415813871788764811u),
MakeUint128(802032351030850070u, 4812194106185100421u),
MakeUint128(768614336404564650u, 12297829382473034410u),
MakeUint128(737869762948382064u, 11805916207174113034u),
MakeUint128(709490156681136600u, 11351842506898185609u),
MakeUint128(683212743470724133u, 17080318586768103348u),
MakeUint128(658812288346769700u, 10540996613548315209u),
MakeUint128(636094623231363848u, 15266270957552732371u),
MakeUint128(614891469123651720u, 9838263505978427528u),
MakeUint128(595056260442243600u, 9520900167075897608u),
MakeUint128(576460752303423487u, 18446744073709551615u),
MakeUint128(558992244657865200u, 8943875914525843207u),
MakeUint128(542551296285575047u, 9765923333140350855u),
MakeUint128(527049830677415760u, 8432797290838652167u),
MakeUint128(512409557603043100u, 8198552921648689607u),
};
template <typename IntType> template <typename IntType>
const IntType LookupTables<IntType>::kVmaxOverBase[] = const IntType LookupTables<IntType>::kVmaxOverBase[] =
X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max()); X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max());
...@@ -754,6 +798,8 @@ inline bool safe_parse_positive_int(absl::string_view text, int base, ...@@ -754,6 +798,8 @@ inline bool safe_parse_positive_int(absl::string_view text, int base,
assert(base >= 0); assert(base >= 0);
assert(vmax >= static_cast<IntType>(base)); assert(vmax >= static_cast<IntType>(base));
const IntType vmax_over_base = LookupTables<IntType>::kVmaxOverBase[base]; const IntType vmax_over_base = LookupTables<IntType>::kVmaxOverBase[base];
assert(base < 2 ||
std::numeric_limits<IntType>::max() / base == vmax_over_base);
const char* start = text.data(); const char* start = text.data();
const char* end = start + text.size(); const char* end = start + text.size();
// loop over digits // loop over digits
...@@ -787,6 +833,8 @@ inline bool safe_parse_negative_int(absl::string_view text, int base, ...@@ -787,6 +833,8 @@ inline bool safe_parse_negative_int(absl::string_view text, int base,
assert(vmin < 0); assert(vmin < 0);
assert(vmin <= 0 - base); assert(vmin <= 0 - base);
IntType vmin_over_base = LookupTables<IntType>::kVminOverBase[base]; IntType vmin_over_base = LookupTables<IntType>::kVminOverBase[base];
assert(base < 2 ||
std::numeric_limits<IntType>::min() / base == vmin_over_base);
// 2003 c++ standard [expr.mul] // 2003 c++ standard [expr.mul]
// "... the sign of the remainder is implementation-defined." // "... the sign of the remainder is implementation-defined."
// Although (vmin/base)*base + vmin%base is always vmin. // Although (vmin/base)*base + vmin%base is always vmin.
......
...@@ -66,13 +66,41 @@ extern ZoneInfoSourceFactory zone_info_source_factory; ...@@ -66,13 +66,41 @@ extern ZoneInfoSourceFactory zone_info_source_factory;
extern ZoneInfoSourceFactory default_factory; extern ZoneInfoSourceFactory default_factory;
ZoneInfoSourceFactory default_factory = DefaultFactory; ZoneInfoSourceFactory default_factory = DefaultFactory;
#if defined(_M_IX86) #if defined(_M_IX86)
#pragma comment( \ #pragma comment( \
linker, \ linker, \
"/alternatename:?zone_info_source_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZA=?default_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZA") "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
"@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
"@@ZA=?default_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
"@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
"@@ZA")
#elif defined(_M_IA_64) || defined(_M_AMD64) || defined(_M_ARM64) #elif defined(_M_IA_64) || defined(_M_AMD64) || defined(_M_ARM64)
#pragma comment( \ #pragma comment( \
linker, \ linker, \
"/alternatename:?zone_info_source_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA=?default_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA") "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
"@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
"@@ZEA=?default_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
"@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
"@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
"@@ZEA")
#else #else
#error Unsupported MSVC platform #error Unsupported MSVC platform
#endif // _M_<PLATFORM> #endif // _M_<PLATFORM>
......
...@@ -527,30 +527,59 @@ std::chrono::seconds ToChronoSeconds(Duration d); ...@@ -527,30 +527,59 @@ std::chrono::seconds ToChronoSeconds(Duration d);
std::chrono::minutes ToChronoMinutes(Duration d); std::chrono::minutes ToChronoMinutes(Duration d);
std::chrono::hours ToChronoHours(Duration d); std::chrono::hours ToChronoHours(Duration d);
// FormatDuration() // FormatDuration()
// //
// Returns a string representing the duration in the form "72h3m0.5s". // Returns a string represention of the duration in a format consisting of a
// Returns "inf" or "-inf" for +/- `InfiniteDuration()`. // possibly-signed prefix and a sequence of decimal numbers, each with an
// optional fractional part and a unit suffix.
//
// Valid unit suffixes are "ns", "us" "ms", "s", "m", and "h".
//
// Simple examples include "300ms", "-1.5h", and "2h45m". Returns "inf" or
// "-inf" for +/- `InfiniteDuration()` values and "0" for `ZeroDuration()`
// values.
//
// This string format is used both as an input for parsing (when handling
// command-line flags of type `absl::Duration`) and as an output in
// `FormatDuration()`
std::string FormatDuration(Duration d); std::string FormatDuration(Duration d);
// Output stream operator.
inline std::ostream& operator<<(std::ostream& os, Duration d) {
return os << FormatDuration(d);
}
// ParseDuration() // ParseDuration()
// //
// Parses a duration string consisting of a possibly signed sequence of // Parses a `dur_string` of the format noted above into an `absl::Duration`
// decimal numbers, each with an optional fractional part and a unit // value.
// suffix. The valid suffixes are "ns", "us" "ms", "s", "m", and "h". //
// Simple examples include "300ms", "-1.5h", and "2h45m". Parses "0" as // Parses "0" as a zero-length duration value. Parses "-inf" or "+inf" as
// `ZeroDuration()`. Parses "inf" and "-inf" as +/- `InfiniteDuration()`. // infinite durations values.
bool ParseDuration(const std::string& dur_string, Duration* d); bool ParseDuration(const std::string& dur_string, Duration* d);
// Support for flag values of type Duration. Duration flags must be specified // AbslParseFlag()
// in a format that is valid input for absl::ParseDuration(). //
// Parses the command-line flag string representation `text` (using the format
// noted above) into an `absl::Duration` destination, setting `error` on
// failure.
//
// Example:
//
// --timeout=6h30m
// --timeout=inf // Equivalent to `InfiniteDuration()`
// --timeout=0 // Equivalent to `ZeroDuration()`
bool AbslParseFlag(absl::string_view text, Duration* dst, std::string* error); bool AbslParseFlag(absl::string_view text, Duration* dst, std::string* error);
// AbslUnparseFlag()
//
// Unparses an `absl::Duration` into a command-line string representation using
// the format noted above.
std::string AbslUnparseFlag(Duration d); std::string AbslUnparseFlag(Duration d);
// operator<<()
//
// Output stream operator, returning a stream in the format noted above.
inline std::ostream& operator<<(std::ostream& os, Duration d) {
return os << FormatDuration(d);
}
ABSL_DEPRECATED("Use AbslParseFlag() instead.") ABSL_DEPRECATED("Use AbslParseFlag() instead.")
bool ParseFlag(const std::string& text, Duration* dst, std::string* error); bool ParseFlag(const std::string& text, Duration* dst, std::string* error);
ABSL_DEPRECATED("Use AbslUnparseFlag() instead.") ABSL_DEPRECATED("Use AbslUnparseFlag() instead.")
...@@ -813,18 +842,29 @@ Time FromChrono(const std::chrono::system_clock::time_point& tp); ...@@ -813,18 +842,29 @@ Time FromChrono(const std::chrono::system_clock::time_point& tp);
// // tp == std::chrono::system_clock::from_time_t(123); // // tp == std::chrono::system_clock::from_time_t(123);
std::chrono::system_clock::time_point ToChronoTime(Time); std::chrono::system_clock::time_point ToChronoTime(Time);
// Support for flag values of type Time. Time flags must be specified in a // AbslParseFlag()
// format that matches absl::RFC3339_full. For example: //
// Parses the command-line flag string representation `text` into an
// `absl::Time` destination, setting `error` on failure. Time flag string
// representations must be specified in a format that matches
// `absl::RFC3339_full`.
//
// Example:
// //
// --start_time=2016-01-02T03:04:05.678+08:00 // --start_time=2016-01-02T03:04:05.678+08:00
// //
// Note: A UTC offset (or 'Z' indicating a zero-offset from UTC) is required. // Note: A UTC offset (or 'Z' indicating a zero-offset from UTC) is required.
// //
// Additionally, if you'd like to specify a time as a count of // Additionally, if you'd like to specify a time as a count of
// seconds/milliseconds/etc from the Unix epoch, use an absl::Duration flag // seconds/milliseconds/etc from the Unix epoch, use an `absl::Duration` flag
// and add that duration to absl::UnixEpoch() to get an absl::Time. // and add that duration to `absl::UnixEpoch()` to get an `absl::Time`.
bool AbslParseFlag(absl::string_view text, Time* t, std::string* error); bool AbslParseFlag(absl::string_view text, Time* t, std::string* error);
// AbslUnparseFlag()
//
// Unparses an `absl::Time` into a command-line string format as noted above.
std::string AbslUnparseFlag(Time t); std::string AbslUnparseFlag(Time t);
ABSL_DEPRECATED("Use AbslParseFlag() instead.") ABSL_DEPRECATED("Use AbslParseFlag() instead.")
bool ParseFlag(const std::string& text, Time* t, std::string* error); bool ParseFlag(const std::string& text, Time* t, std::string* error);
ABSL_DEPRECATED("Use AbslUnparseFlag() instead.") ABSL_DEPRECATED("Use AbslUnparseFlag() instead.")
......
...@@ -176,6 +176,14 @@ class weak_equality ...@@ -176,6 +176,14 @@ class weak_equality
weak_equality v) noexcept { weak_equality v) noexcept {
return 0 != v.value_; return 0 != v.value_;
} }
friend constexpr bool operator==(weak_equality v1,
weak_equality v2) noexcept {
return v1.value_ == v2.value_;
}
friend constexpr bool operator!=(weak_equality v1,
weak_equality v2) noexcept {
return v1.value_ != v2.value_;
}
private: private:
compare_internal::value_type value_; compare_internal::value_type value_;
...@@ -219,6 +227,14 @@ class strong_equality ...@@ -219,6 +227,14 @@ class strong_equality
strong_equality v) noexcept { strong_equality v) noexcept {
return 0 != v.value_; return 0 != v.value_;
} }
friend constexpr bool operator==(strong_equality v1,
strong_equality v2) noexcept {
return v1.value_ == v2.value_;
}
friend constexpr bool operator!=(strong_equality v1,
strong_equality v2) noexcept {
return v1.value_ != v2.value_;
}
private: private:
compare_internal::value_type value_; compare_internal::value_type value_;
...@@ -306,6 +322,14 @@ class partial_ordering ...@@ -306,6 +322,14 @@ class partial_ordering
partial_ordering v) noexcept { partial_ordering v) noexcept {
return v.is_ordered() && 0 >= v.value_; return v.is_ordered() && 0 >= v.value_;
} }
friend constexpr bool operator==(partial_ordering v1,
partial_ordering v2) noexcept {
return v1.value_ == v2.value_;
}
friend constexpr bool operator!=(partial_ordering v1,
partial_ordering v2) noexcept {
return v1.value_ != v2.value_;
}
private: private:
compare_internal::value_type value_; compare_internal::value_type value_;
...@@ -390,6 +414,14 @@ class weak_ordering ...@@ -390,6 +414,14 @@ class weak_ordering
weak_ordering v) noexcept { weak_ordering v) noexcept {
return 0 >= v.value_; return 0 >= v.value_;
} }
friend constexpr bool operator==(weak_ordering v1,
weak_ordering v2) noexcept {
return v1.value_ == v2.value_;
}
friend constexpr bool operator!=(weak_ordering v1,
weak_ordering v2) noexcept {
return v1.value_ != v2.value_;
}
private: private:
compare_internal::value_type value_; compare_internal::value_type value_;
...@@ -481,6 +513,14 @@ class strong_ordering ...@@ -481,6 +513,14 @@ class strong_ordering
strong_ordering v) noexcept { strong_ordering v) noexcept {
return 0 >= v.value_; return 0 >= v.value_;
} }
friend constexpr bool operator==(strong_ordering v1,
strong_ordering v2) noexcept {
return v1.value_ == v2.value_;
}
friend constexpr bool operator!=(strong_ordering v1,
strong_ordering v2) noexcept {
return v1.value_ != v2.value_;
}
private: private:
compare_internal::value_type value_; compare_internal::value_type value_;
......
...@@ -31,6 +31,15 @@ TEST(Compare, WeakEquality) { ...@@ -31,6 +31,15 @@ TEST(Compare, WeakEquality) {
EXPECT_TRUE(Identity(0 == weak_equality::equivalent)); EXPECT_TRUE(Identity(0 == weak_equality::equivalent));
EXPECT_TRUE(Identity(weak_equality::nonequivalent != 0)); EXPECT_TRUE(Identity(weak_equality::nonequivalent != 0));
EXPECT_TRUE(Identity(0 != weak_equality::nonequivalent)); EXPECT_TRUE(Identity(0 != weak_equality::nonequivalent));
const weak_equality values[] = {weak_equality::equivalent,
weak_equality::nonequivalent};
for (const auto& lhs : values) {
for (const auto& rhs : values) {
const bool are_equal = &lhs == &rhs;
EXPECT_EQ(lhs == rhs, are_equal);
EXPECT_EQ(lhs != rhs, !are_equal);
}
}
} }
TEST(Compare, StrongEquality) { TEST(Compare, StrongEquality) {
...@@ -42,6 +51,18 @@ TEST(Compare, StrongEquality) { ...@@ -42,6 +51,18 @@ TEST(Compare, StrongEquality) {
EXPECT_TRUE(Identity(0 == strong_equality::equivalent)); EXPECT_TRUE(Identity(0 == strong_equality::equivalent));
EXPECT_TRUE(Identity(strong_equality::nonequivalent != 0)); EXPECT_TRUE(Identity(strong_equality::nonequivalent != 0));
EXPECT_TRUE(Identity(0 != strong_equality::nonequivalent)); EXPECT_TRUE(Identity(0 != strong_equality::nonequivalent));
const strong_equality values[] = {strong_equality::equal,
strong_equality::nonequal};
for (const auto& lhs : values) {
for (const auto& rhs : values) {
const bool are_equal = &lhs == &rhs;
EXPECT_EQ(lhs == rhs, are_equal);
EXPECT_EQ(lhs != rhs, !are_equal);
}
}
EXPECT_TRUE(Identity(strong_equality::equivalent == strong_equality::equal));
EXPECT_TRUE(
Identity(strong_equality::nonequivalent == strong_equality::nonequal));
} }
TEST(Compare, PartialOrdering) { TEST(Compare, PartialOrdering) {
...@@ -65,6 +86,16 @@ TEST(Compare, PartialOrdering) { ...@@ -65,6 +86,16 @@ TEST(Compare, PartialOrdering) {
EXPECT_FALSE(Identity(0 > partial_ordering::unordered)); EXPECT_FALSE(Identity(0 > partial_ordering::unordered));
EXPECT_FALSE(Identity(partial_ordering::unordered >= 0)); EXPECT_FALSE(Identity(partial_ordering::unordered >= 0));
EXPECT_FALSE(Identity(0 >= partial_ordering::unordered)); EXPECT_FALSE(Identity(0 >= partial_ordering::unordered));
const partial_ordering values[] = {
partial_ordering::less, partial_ordering::equivalent,
partial_ordering::greater, partial_ordering::unordered};
for (const auto& lhs : values) {
for (const auto& rhs : values) {
const bool are_equal = &lhs == &rhs;
EXPECT_EQ(lhs == rhs, are_equal);
EXPECT_EQ(lhs != rhs, !are_equal);
}
}
} }
TEST(Compare, WeakOrdering) { TEST(Compare, WeakOrdering) {
...@@ -78,6 +109,15 @@ TEST(Compare, WeakOrdering) { ...@@ -78,6 +109,15 @@ TEST(Compare, WeakOrdering) {
EXPECT_TRUE(Identity(0 < weak_ordering::greater)); EXPECT_TRUE(Identity(0 < weak_ordering::greater));
EXPECT_TRUE(Identity(weak_ordering::greater >= 0)); EXPECT_TRUE(Identity(weak_ordering::greater >= 0));
EXPECT_TRUE(Identity(0 <= weak_ordering::greater)); EXPECT_TRUE(Identity(0 <= weak_ordering::greater));
const weak_ordering values[] = {
weak_ordering::less, weak_ordering::equivalent, weak_ordering::greater};
for (const auto& lhs : values) {
for (const auto& rhs : values) {
const bool are_equal = &lhs == &rhs;
EXPECT_EQ(lhs == rhs, are_equal);
EXPECT_EQ(lhs != rhs, !are_equal);
}
}
} }
TEST(Compare, StrongOrdering) { TEST(Compare, StrongOrdering) {
...@@ -93,6 +133,16 @@ TEST(Compare, StrongOrdering) { ...@@ -93,6 +133,16 @@ TEST(Compare, StrongOrdering) {
EXPECT_TRUE(Identity(0 < strong_ordering::greater)); EXPECT_TRUE(Identity(0 < strong_ordering::greater));
EXPECT_TRUE(Identity(strong_ordering::greater >= 0)); EXPECT_TRUE(Identity(strong_ordering::greater >= 0));
EXPECT_TRUE(Identity(0 <= strong_ordering::greater)); EXPECT_TRUE(Identity(0 <= strong_ordering::greater));
const strong_ordering values[] = {
strong_ordering::less, strong_ordering::equal, strong_ordering::greater};
for (const auto& lhs : values) {
for (const auto& rhs : values) {
const bool are_equal = &lhs == &rhs;
EXPECT_EQ(lhs == rhs, are_equal);
EXPECT_EQ(lhs != rhs, !are_equal);
}
}
EXPECT_TRUE(Identity(strong_ordering::equivalent == strong_ordering::equal));
} }
TEST(Compare, Conversions) { TEST(Compare, Conversions) {
...@@ -190,7 +240,7 @@ TEST(Compare, Conversions) { ...@@ -190,7 +240,7 @@ TEST(Compare, Conversions) {
struct WeakOrderingLess { struct WeakOrderingLess {
template <typename T> template <typename T>
absl::weak_ordering operator()(const T &a, const T &b) const { absl::weak_ordering operator()(const T& a, const T& b) const {
return a < b ? absl::weak_ordering::less return a < b ? absl::weak_ordering::less
: a == b ? absl::weak_ordering::equivalent : a == b ? absl::weak_ordering::equivalent
: absl::weak_ordering::greater; : absl::weak_ordering::greater;
...@@ -224,10 +274,10 @@ TEST(DoLessThanComparison, SanityTest) { ...@@ -224,10 +274,10 @@ TEST(DoLessThanComparison, SanityTest) {
} }
TEST(CompareResultAsOrdering, SanityTest) { TEST(CompareResultAsOrdering, SanityTest) {
EXPECT_TRUE(Identity( EXPECT_TRUE(
absl::compare_internal::compare_result_as_ordering(-1) < 0)); Identity(absl::compare_internal::compare_result_as_ordering(-1) < 0));
EXPECT_FALSE(Identity( EXPECT_FALSE(
absl::compare_internal::compare_result_as_ordering(-1) == 0)); Identity(absl::compare_internal::compare_result_as_ordering(-1) == 0));
EXPECT_FALSE( EXPECT_FALSE(
Identity(absl::compare_internal::compare_result_as_ordering(-1) > 0)); Identity(absl::compare_internal::compare_result_as_ordering(-1) > 0));
EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering( EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
...@@ -237,31 +287,31 @@ TEST(CompareResultAsOrdering, SanityTest) { ...@@ -237,31 +287,31 @@ TEST(CompareResultAsOrdering, SanityTest) {
EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
weak_ordering::less) > 0)); weak_ordering::less) > 0));
EXPECT_FALSE(Identity( EXPECT_FALSE(
absl::compare_internal::compare_result_as_ordering(0) < 0)); Identity(absl::compare_internal::compare_result_as_ordering(0) < 0));
EXPECT_TRUE(Identity( EXPECT_TRUE(
absl::compare_internal::compare_result_as_ordering(0) == 0)); Identity(absl::compare_internal::compare_result_as_ordering(0) == 0));
EXPECT_FALSE(Identity( EXPECT_FALSE(
absl::compare_internal::compare_result_as_ordering(0) > 0)); Identity(absl::compare_internal::compare_result_as_ordering(0) > 0));
EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
weak_ordering::equivalent) < 0)); weak_ordering::equivalent) < 0));
EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering( EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
weak_ordering::equivalent) == 0)); weak_ordering::equivalent) == 0));
EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
weak_ordering::equivalent) > 0)); weak_ordering::equivalent) > 0));
EXPECT_FALSE(Identity( EXPECT_FALSE(
absl::compare_internal::compare_result_as_ordering(1) < 0)); Identity(absl::compare_internal::compare_result_as_ordering(1) < 0));
EXPECT_FALSE(Identity( EXPECT_FALSE(
absl::compare_internal::compare_result_as_ordering(1) == 0)); Identity(absl::compare_internal::compare_result_as_ordering(1) == 0));
EXPECT_TRUE(Identity( EXPECT_TRUE(
absl::compare_internal::compare_result_as_ordering(1) > 0)); Identity(absl::compare_internal::compare_result_as_ordering(1) > 0));
EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
weak_ordering::greater) < 0)); weak_ordering::greater) < 0));
EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
weak_ordering::greater) == 0)); weak_ordering::greater) == 0));
EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering( EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
weak_ordering::greater) > 0)); weak_ordering::greater) > 0));
} }
TEST(DoThreeWayComparison, SanityTest) { TEST(DoThreeWayComparison, SanityTest) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment