Export of internal Abseil changes

--
20405fc394419d434d3ea09b2e62e4edcb282421 by Christian Blichmann <cblichmann@google.com>:

Include `status` subdirectory in main `CMakeLists.txt`

PiperOrigin-RevId: 297125966

--
101087af9689612bdda679ee0869e5cde4472244 by Matt Kulukundis <kfm@google.com>:

Fix typo

PiperOrigin-RevId: 296991360

--
55ff5bc6970d46214c0459d3a7a23973c7dc69b9 by Andy Getzendanner <durandal@google.com>:

Extract logging's ErrnoSaver to absl::base_internal and use it in a couple other places.

PiperOrigin-RevId: 296969168

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

Internal change

PiperOrigin-RevId: 296951474

--
8c04c73fc53f9a09c3e2400812b931157f35fe07 by Andy Soffer <asoffer@google.com>:

Auto-generate list of files in the DLL, and add new build targets to the DLL.

PiperOrigin-RevId: 296932061

--
2f77829e196094f1addefd8ac2ac9e398c5b6100 by Andy Soffer <asoffer@google.com>:

Fix bug introduced by DLL where we couldn't build shared libraries on
non-windows platforms.

Fixes #623

PiperOrigin-RevId: 296919347

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

typo: microprosessor

PiperOrigin-RevId: 296904933

--
b185da0dac44c91855373f0723df9242cbfb3db3 by Matthew Brown <matthewbr@google.com>:

Internal cleanup

PiperOrigin-RevId: 296509711
GitOrigin-RevId: 20405fc394419d434d3ea09b2e62e4edcb282421
Change-Id: I55c8eba6f353ceb337455ae144ab743ea21edbef
This commit is contained in:
Abseil Team 2020-02-25 08:48:42 -08:00 committed by CJ Johnson
parent b69c7d880c
commit 0d5ce2797e
20 changed files with 248 additions and 128 deletions

View file

@ -16,6 +16,7 @@ set(ABSL_INTERNAL_DLL_FILES
"base/internal/cycleclock.h"
"base/internal/direct_mmap.h"
"base/internal/endian.h"
"base/internal/errno_saver.h"
"base/internal/exponential_biased.cc"
"base/internal/exponential_biased.h"
"base/internal/hide_ptr.h"
@ -108,6 +109,8 @@ set(ABSL_INTERNAL_DLL_FILES
"debugging/internal/symbolize.h"
"debugging/internal/vdso_support.cc"
"debugging/internal/vdso_support.h"
"functional/internal/front_binder.h"
"functional/bind_front.h"
"functional/function_ref.h"
"functional/internal/function_ref.h"
"hash/hash.h"
@ -169,18 +172,23 @@ set(ABSL_INTERNAL_DLL_FILES
"random/uniform_int_distribution.h"
"random/uniform_real_distribution.h"
"random/zipf_distribution.h"
"status/status.h"
"status/status.cc"
"status/status_payload_printer.h"
"status/status_payload_printer.cc"
"strings/ascii.cc"
"strings/ascii.h"
"strings/charconv.cc"
"strings/charconv.h"
"strings/cord.cc"
"strings/cord.h"
"strings/escaping.cc"
"strings/escaping.h"
"strings/internal/cord_internal.h"
"strings/internal/charconv_bigint.cc"
"strings/internal/charconv_bigint.h"
"strings/internal/charconv_parse.cc"
"strings/internal/charconv_parse.h"
"strings/internal/escaping.cc"
"strings/internal/escaping.h"
"strings/internal/stl_type_traits.h"
"strings/match.cc"
"strings/match.h"
@ -200,6 +208,8 @@ set(ABSL_INTERNAL_DLL_FILES
"strings/substitute.cc"
"strings/substitute.h"
"strings/internal/char_map.h"
"strings/internal/escaping.h"
"strings/internal/escaping.cc"
"strings/internal/memutil.cc"
"strings/internal/memutil.h"
"strings/internal/ostringstream.cc"
@ -308,6 +318,7 @@ set(ABSL_INTERNAL_DLL_TARGETS
"memory"
"strings"
"strings_internal"
"cord"
"str_format"
"str_format_internal"
"pow10_helper"
@ -377,6 +388,7 @@ set(ABSL_INTERNAL_DLL_TARGETS
"random_internal_randen_hwaes"
"random_internal_randen_hwaes_impl"
"random_internal_uniform_helper"
"status"
"time"
"civil_time"
"time_zone"

View file

@ -108,14 +108,16 @@ function(absl_cc_library)
set(ABSL_CC_LIB_IS_INTERFACE 0)
endif()
# Determine this build target's relationship to the DLL. It's one of three things:
# Determine this build target's relationship to the DLL. It's one of four things:
# 1. "dll" -- This target is part of the DLL
# 2. "dll_dep" -- This target is not part of the DLL, but depends on the DLL.
# Note that we assume any target not in the DLL depends on the
# DLL. This is not a technical necessity but a convenience
# which happens to be true, because nearly every target is
# part of the DLL.
# 3. "static" -- This target does not depend on the DLL and should be built
# 3. "shared" -- This is a shared library, perhaps on a non-windows platform
# where DLL doesn't make sense.
# 4. "static" -- This target does not depend on the DLL and should be built
# statically.
if (${ABSL_BUILD_DLL})
absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_dll)
@ -127,6 +129,8 @@ function(absl_cc_library)
# Building a DLL, but this target is not part of the DLL
set(_build_type "dll_dep")
endif()
elseif(BUILD_SHARED_LIBS)
set(_build_type "shared")
else()
set(_build_type "static")
endif()
@ -161,8 +165,8 @@ function(absl_cc_library)
"${_gtest_link_define}"
)
elseif(${_build_type} STREQUAL "static")
add_library(${_NAME} STATIC "")
elseif(${_build_type} STREQUAL "static" OR ${_build_type} STREQUAL "shared")
add_library(${_NAME} "")
target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})
target_link_libraries(${_NAME}
PUBLIC ${ABSL_CC_LIB_DEPS}

View file

@ -25,6 +25,7 @@ add_subdirectory(memory)
add_subdirectory(meta)
add_subdirectory(numeric)
add_subdirectory(random)
add_subdirectory(status)
add_subdirectory(strings)
add_subdirectory(synchronization)
add_subdirectory(time)

View file

@ -40,6 +40,17 @@ cc_library(
],
)
cc_library(
name = "errno_saver",
hdrs = ["internal/errno_saver.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl:__subpackages__",
],
deps = [":config"],
)
cc_library(
name = "log_severity",
srcs = ["log_severity.cc"],
@ -87,6 +98,7 @@ cc_library(
deps = [
":base_internal",
":core_headers",
":errno_saver",
],
)
@ -287,6 +299,18 @@ cc_test(
],
)
cc_test(
name = "errno_saver_test",
size = "small",
srcs = ["internal/errno_saver_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":errno_saver",
"@com_google_googletest//:gtest_main",
],
)
cc_library(
name = "exception_testing",
testonly = 1,

View file

@ -28,6 +28,17 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
)
absl_cc_library(
NAME
errno_saver
HDRS
"internal/errno_saver.h"
DEPS
absl::config
COPTS
${ABSL_DEFAULT_COPTS}
)
absl_cc_library(
NAME
log_severity
@ -73,6 +84,7 @@ absl_cc_library(
DEPS
absl::base_internal
absl::core_headers
absl::errno_saver
)
absl_cc_library(
@ -305,6 +317,19 @@ absl_cc_test(
gtest_main
)
absl_cc_test(
NAME
errno_saver_test
SRCS
"internal/errno_saver_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
absl::errno_saver
gmock
gtest_main
)
absl_cc_test(
NAME
throw_delegate_test

View file

@ -575,7 +575,7 @@
// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the
// natural alignment of structure members not annotated is preserved. Aligned
// member accesses are faster than non-aligned member accesses even if the
// targeted microprosessor supports non-aligned accesses.
// targeted microprocessor supports non-aligned accesses.
#if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__))
#else

View file

@ -0,0 +1,43 @@
// Copyright 2017 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_BASE_INTERNAL_ERRNO_SAVER_H_
#define ABSL_BASE_INTERNAL_ERRNO_SAVER_H_
#include <cerrno>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
// `ErrnoSaver` captures the value of `errno` upon construction and restores it
// upon deletion. It is used in low-level code and must be super fast. Do not
// add instrumentation, even in debug modes.
class ErrnoSaver {
public:
ErrnoSaver() : saved_errno_(errno) {}
~ErrnoSaver() { errno = saved_errno_; }
int operator()() const { return saved_errno_; }
private:
const int saved_errno_;
};
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_ERRNO_SAVER_H_

View file

@ -0,0 +1,44 @@
// Copyright 2018 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/base/internal/errno_saver.h"
#include <cerrno>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace {
using ::testing::Eq;
struct ErrnoPrinter {
int no;
};
std::ostream &operator<<(std::ostream &os, ErrnoPrinter ep) {
return os << strerror(ep.no) << " [" << ep.no << "]";
}
bool operator==(ErrnoPrinter one, ErrnoPrinter two) { return one.no == two.no; }
TEST(ErrnoSaverTest, Works) {
errno = EDOM;
{
absl::base_internal::ErrnoSaver errno_saver;
EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{EDOM}));
errno = ERANGE;
EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{ERANGE}));
EXPECT_THAT(ErrnoPrinter{errno_saver()}, Eq(ErrnoPrinter{EDOM}));
}
EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{EDOM}));
}
} // namespace

View file

@ -19,12 +19,12 @@
#include <unistd.h>
#include <atomic>
#include <cerrno>
#include <climits>
#include <cstdint>
#include <ctime>
#include "absl/base/attributes.h"
#include "absl/base/internal/errno_saver.h"
// The SpinLock lockword is `std::atomic<uint32_t>`. Here we assert that
// `std::atomic<uint32_t>` is bitwise equivalent of the `int` expected
@ -51,12 +51,11 @@ extern "C" {
ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
std::atomic<uint32_t> *w, uint32_t value, int loop,
absl::base_internal::SchedulingMode) {
int save_errno = errno;
absl::base_internal::ErrnoSaver errno_saver;
struct timespec tm;
tm.tv_sec = 0;
tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop);
syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm);
errno = save_errno;
}
ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(std::atomic<uint32_t> *w,

View file

@ -15,10 +15,11 @@
// This file is a Posix-specific part of spinlock_wait.cc
#include <sched.h>
#include <atomic>
#include <ctime>
#include <cerrno>
#include "absl/base/internal/errno_saver.h"
#include "absl/base/internal/scheduling_mode.h"
#include "absl/base/port.h"
@ -27,7 +28,7 @@ extern "C" {
ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, int loop,
absl::base_internal::SchedulingMode /* mode */) {
int save_errno = errno;
absl::base_internal::ErrnoSaver errno_saver;
if (loop == 0) {
} else if (loop == 1) {
sched_yield();
@ -37,7 +38,6 @@ ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop);
nanosleep(&tm, nullptr);
}
errno = save_errno;
}
ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(

View file

@ -134,6 +134,7 @@ cc_library(
"//absl/base",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:errno_saver",
"//absl/base:raw_logging_internal",
],
)
@ -174,6 +175,7 @@ cc_library(
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:dynamic_annotations",
"//absl/base:errno_saver",
"//absl/base:raw_logging_internal",
],
)

View file

@ -118,6 +118,7 @@ absl_cc_library(
absl::base
absl::config
absl::core_headers
absl::errno_saver
absl::raw_logging_internal
PUBLIC
)
@ -156,6 +157,7 @@ absl_cc_library(
absl::core_headers
absl::config
absl::dynamic_annotations
absl::errno_saver
absl::raw_logging_internal
)

View file

@ -41,6 +41,7 @@
#include <ctime>
#include "absl/base/attributes.h"
#include "absl/base/internal/errno_saver.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/sysinfo.h"
#include "absl/debugging/internal/examine_stack.h"
@ -214,9 +215,8 @@ static void InstallOneFailureHandler(FailureSignalData* data,
#endif
static void WriteToStderr(const char* data) {
int old_errno = errno;
absl::base_internal::ErrnoSaver errno_saver;
absl::raw_logging_internal::SafeWriteToStderr(data, strlen(data));
errno = old_errno;
}
static void WriteSignalMessage(int signo, void (*writerfn)(const char*)) {

View file

@ -35,10 +35,12 @@ ABSL_NAMESPACE_END
#include <fcntl.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <atomic>
#include <cerrno>
#include <cstdint>
#include "absl/base/internal/errno_saver.h"
#include "absl/base/internal/raw_logging.h"
namespace absl {
@ -67,7 +69,7 @@ static void Unpack(uint64_t x, int *pid, int *read_fd, int *write_fd) {
// This is a namespace-scoped variable for correct zero-initialization.
static std::atomic<uint64_t> pid_and_fds; // initially 0, an invalid pid.
bool AddressIsReadable(const void *addr) {
int save_errno = errno;
absl::base_internal::ErrnoSaver errno_saver;
// We test whether a byte is readable by using write(). Normally, this would
// be done via a cached file descriptor to /dev/null, but linux fails to
// check whether the byte is readable when the destination is /dev/null, so
@ -126,7 +128,6 @@ bool AddressIsReadable(const void *addr) {
std::memory_order_relaxed);
}
} while (errno == EBADF);
errno = save_errno;
return bytes_written == 1;
}

View file

@ -465,7 +465,7 @@ class FlagImpl {
// Flag initialization called via absl::call_once.
void Init();
// Attempts to parse supplied `value` std::string. If parsing is successful,
// returns new value. Otherwsie returns nullptr.
// returns new value. Otherwise returns nullptr.
std::unique_ptr<void, DynValueDeleter> TryParse(absl::string_view value,
std::string* err) const
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());

View file

@ -1,30 +0,0 @@
// Copyright 2017 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 <iostream>
#include <random>
#include "absl/random/random.h"
// This program is used in integration tests.
int main() {
std::seed_seq seed_seq{1234};
absl::BitGen rng(seed_seq);
constexpr size_t kSequenceLength = 8;
for (size_t i = 0; i < kSequenceLength; i++) {
std::cout << rng() << "\n";
}
return 0;
}

View file

@ -1,30 +0,0 @@
// Copyright 2017 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 <iostream>
#include <random>
#include "absl/random/random.h"
// This program is used in integration tests.
int main() {
std::seed_seq seed_seq{};
absl::BitGen rng(seed_seq);
constexpr size_t kSequenceLength = 8;
for (size_t i = 0; i < kSequenceLength; i++) {
std::cout << rng() << "\n";
}
return 0;
}

View file

@ -41,7 +41,7 @@ absl_cc_library(
absl_cc_test(
NAME
status_test
HDRS
SRCS
"status_test.cc"
COPTS
${ABSL_TEST_COPTS}

View file

@ -13,7 +13,7 @@ std::string ConvToString(Conv conv) {
std::string out;
#define CONV_SET_CASE(c) \
if (Contains(conv, Conv::c)) out += #c;
ABSL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
#undef CONV_SET_CASE
if (Contains(conv, Conv::star)) out += "*";
return out;

View file

@ -137,7 +137,7 @@ struct Flags {
};
// clang-format off
#define ABSL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
#define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
/* text */ \
X_VAL(c) X_SEP X_VAL(C) X_SEP X_VAL(s) X_SEP X_VAL(S) X_SEP \
/* ints */ \
@ -161,11 +161,11 @@ enum class FormatConversionChar : uint8_t {
inline FormatConversionChar FormatConversionCharFromChar(char c) {
switch (c) {
#define X_VAL(id) \
case #id[0]: \
#define ABSL_INTERNAL_X_VAL(id) \
case #id[0]: \
return FormatConversionChar::id;
ABSL_CONVERSION_CHARS_EXPAND_(X_VAL, )
#undef X_VAL
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
#undef ABSL_INTERNAL_X_VAL
}
return FormatConversionChar::kNone;
}
@ -240,15 +240,16 @@ inline bool FormatConversionCharIsFloat(FormatConversionChar c) {
inline char FormatConversionCharToChar(FormatConversionChar c) {
switch (c) {
#define X_VAL(e) \
#define ABSL_INTERNAL_X_VAL(e) \
case FormatConversionChar::e: \
return #e[0];
#define X_SEP
ABSL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP)
#define ABSL_INTERNAL_X_SEP
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL,
ABSL_INTERNAL_X_SEP)
case FormatConversionChar::kNone:
return '\0';
#undef X_VAL
#undef X_SEP
#undef ABSL_INTERNAL_X_VAL
#undef ABSL_INTERNAL_X_SEP
}
return '\0';
}
@ -262,11 +263,8 @@ inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {
struct FormatConversionSpecImplFriend;
class ConversionSpec {
class FormatConversionSpec {
public:
// Deprecated (use has_x_flag() instead).
Flags flags() const { return flags_; }
// Width and precison are not specified, no flags are set.
bool is_basic() const { return flags_.basic; }
bool has_left_flag() const { return flags_.left; }
@ -275,10 +273,10 @@ class ConversionSpec {
bool has_alt_flag() const { return flags_.alt; }
bool has_zero_flag() const { return flags_.zero; }
FormatConversionChar conv() const {
FormatConversionChar conversion_char() const {
// Keep this field first in the struct . It generates better code when
// accessing it when ConversionSpec is passed by value in registers.
static_assert(offsetof(ConversionSpec, conv_) == 0, "");
static_assert(offsetof(FormatConversionSpec, conv_) == 0, "");
return conv_;
}
@ -289,6 +287,11 @@ class ConversionSpec {
// negative value.
int precision() const { return precision_; }
// Deprecated (use has_x_flag() instead).
Flags flags() const { return flags_; }
// Deprecated
FormatConversionChar conv() const { return conversion_char(); }
private:
friend struct str_format_internal::FormatConversionSpecImplFriend;
FormatConversionChar conv_ = FormatConversionChar::kNone;
@ -298,46 +301,57 @@ class ConversionSpec {
};
struct FormatConversionSpecImplFriend final {
static void SetFlags(Flags f, ConversionSpec* conv) { conv->flags_ = f; }
static void SetConversionChar(FormatConversionChar c, ConversionSpec* conv) {
static void SetFlags(Flags f, FormatConversionSpec* conv) {
conv->flags_ = f;
}
static void SetConversionChar(FormatConversionChar c,
FormatConversionSpec* conv) {
conv->conv_ = c;
}
static void SetWidth(int w, ConversionSpec* conv) { conv->width_ = w; }
static void SetPrecision(int p, ConversionSpec* conv) {
static void SetWidth(int w, FormatConversionSpec* conv) { conv->width_ = w; }
static void SetPrecision(int p, FormatConversionSpec* conv) {
conv->precision_ = p;
}
static std::string FlagsToString(const ConversionSpec& spec) {
static std::string FlagsToString(const FormatConversionSpec& spec) {
return spec.flags_.ToString();
}
};
constexpr uint64_t FormatConversionCharToConvValue(char conv) {
return
#define CONV_SET_CASE(c) \
#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
conv == #c[0] \
? (uint64_t{1} << (1 + static_cast<uint8_t>(FormatConversionChar::c))) \
:
ABSL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
#undef CONV_SET_CASE
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
#undef ABSL_INTERNAL_CHAR_SET_CASE
conv == '*'
? 1
: 0;
}
enum class Conv : uint64_t {
#define CONV_SET_CASE(c) c = FormatConversionCharToConvValue(#c[0]),
ABSL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
#undef CONV_SET_CASE
enum class FormatConversionCharSet : uint64_t {
#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
c = FormatConversionCharToConvValue(#c[0]),
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
#undef ABSL_INTERNAL_CHAR_SET_CASE
// Used for width/precision '*' specification.
star = FormatConversionCharToConvValue('*'),
kStar = FormatConversionCharToConvValue('*'),
// Some predefined values:
integral = d | i | u | o | x | X,
floating = a | e | f | g | A | E | F | G,
numeric = integral | floating,
string = s,
pointer = p
kIntegral = d | i | u | o | x | X,
kFloating = a | e | f | g | A | E | F | G,
kNumeric = kIntegral | kFloating,
kString = s,
kPointer = p,
// The following are deprecated
star = kStar,
integral = kIntegral,
floating = kFloating,
numeric = kNumeric,
string = kString,
pointer = kPointer
};
// Type safe OR operator.
@ -345,36 +359,41 @@ enum class Conv : uint64_t {
// 1. operator| on enums makes them decay to integers and the result is an
// integer. We need the result to stay as an enum.
// 2. We use "enum class" which would not work even if we accepted the decay.
constexpr Conv operator|(Conv a, Conv b) {
return Conv(static_cast<uint64_t>(a) | static_cast<uint64_t>(b));
constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
FormatConversionCharSet b) {
return FormatConversionCharSet(static_cast<uint64_t>(a) |
static_cast<uint64_t>(b));
}
// Get a conversion with a single character in it.
constexpr Conv ConversionCharToConv(char c) {
return Conv(FormatConversionCharToConvValue(c));
constexpr FormatConversionCharSet ConversionCharToConv(char c) {
return FormatConversionCharSet(FormatConversionCharToConvValue(c));
}
// Checks whether `c` exists in `set`.
constexpr bool Contains(Conv set, char c) {
constexpr bool Contains(FormatConversionCharSet set, char c) {
return (static_cast<uint64_t>(set) & FormatConversionCharToConvValue(c)) != 0;
}
// Checks whether all the characters in `c` are contained in `set`
constexpr bool Contains(Conv set, Conv c) {
constexpr bool Contains(FormatConversionCharSet set,
FormatConversionCharSet c) {
return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) ==
static_cast<uint64_t>(c);
}
// Return type of the AbslFormatConvert() functions.
// The Conv template parameter is used to inform the framework of what
// conversion characters are supported by that AbslFormatConvert routine.
template <Conv C>
struct ConvertResult {
static constexpr Conv kConv = C;
// The FormatConversionCharSet template parameter is used to inform the
// framework of what conversion characters are supported by that
// AbslFormatConvert routine.
template <FormatConversionCharSet C>
struct FormatConvertResult {
static constexpr FormatConversionCharSet kConv = C;
bool value;
};
template <Conv C>
constexpr Conv ConvertResult<C>::kConv;
template <FormatConversionCharSet C>
constexpr FormatConversionCharSet FormatConvertResult<C>::kConv;
// Return capacity - used, clipped to a minimum of 0.
inline size_t Excess(size_t used, size_t capacity) {
@ -383,6 +402,10 @@ inline size_t Excess(size_t used, size_t capacity) {
// Type alias for use during migration.
using ConversionChar = FormatConversionChar;
using ConversionSpec = FormatConversionSpec;
using Conv = FormatConversionCharSet;
template <FormatConversionCharSet C>
using ConvertResult = FormatConvertResult<C>;
} // namespace str_format_internal