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

View file

@ -108,14 +108,16 @@ function(absl_cc_library)
set(ABSL_CC_LIB_IS_INTERFACE 0) set(ABSL_CC_LIB_IS_INTERFACE 0)
endif() 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 # 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. # 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 # Note that we assume any target not in the DLL depends on the
# DLL. This is not a technical necessity but a convenience # DLL. This is not a technical necessity but a convenience
# which happens to be true, because nearly every target is # which happens to be true, because nearly every target is
# part of the DLL. # 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. # statically.
if (${ABSL_BUILD_DLL}) if (${ABSL_BUILD_DLL})
absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_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 # Building a DLL, but this target is not part of the DLL
set(_build_type "dll_dep") set(_build_type "dll_dep")
endif() endif()
elseif(BUILD_SHARED_LIBS)
set(_build_type "shared")
else() else()
set(_build_type "static") set(_build_type "static")
endif() endif()
@ -161,8 +165,8 @@ function(absl_cc_library)
"${_gtest_link_define}" "${_gtest_link_define}"
) )
elseif(${_build_type} STREQUAL "static") elseif(${_build_type} STREQUAL "static" OR ${_build_type} STREQUAL "shared")
add_library(${_NAME} STATIC "") add_library(${_NAME} "")
target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS}) target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})
target_link_libraries(${_NAME} target_link_libraries(${_NAME}
PUBLIC ${ABSL_CC_LIB_DEPS} PUBLIC ${ABSL_CC_LIB_DEPS}

View file

@ -25,6 +25,7 @@ add_subdirectory(memory)
add_subdirectory(meta) add_subdirectory(meta)
add_subdirectory(numeric) add_subdirectory(numeric)
add_subdirectory(random) add_subdirectory(random)
add_subdirectory(status)
add_subdirectory(strings) add_subdirectory(strings)
add_subdirectory(synchronization) add_subdirectory(synchronization)
add_subdirectory(time) 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( cc_library(
name = "log_severity", name = "log_severity",
srcs = ["log_severity.cc"], srcs = ["log_severity.cc"],
@ -87,6 +98,7 @@ cc_library(
deps = [ deps = [
":base_internal", ":base_internal",
":core_headers", ":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( cc_library(
name = "exception_testing", name = "exception_testing",
testonly = 1, testonly = 1,

View file

@ -28,6 +28,17 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS} ${ABSL_DEFAULT_COPTS}
) )
absl_cc_library(
NAME
errno_saver
HDRS
"internal/errno_saver.h"
DEPS
absl::config
COPTS
${ABSL_DEFAULT_COPTS}
)
absl_cc_library( absl_cc_library(
NAME NAME
log_severity log_severity
@ -73,6 +84,7 @@ absl_cc_library(
DEPS DEPS
absl::base_internal absl::base_internal
absl::core_headers absl::core_headers
absl::errno_saver
) )
absl_cc_library( absl_cc_library(
@ -305,6 +317,19 @@ absl_cc_test(
gtest_main 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( absl_cc_test(
NAME NAME
throw_delegate_test throw_delegate_test

View file

@ -575,7 +575,7 @@
// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the // When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the
// natural alignment of structure members not annotated is preserved. Aligned // natural alignment of structure members not annotated is preserved. Aligned
// member accesses are faster than non-aligned member accesses even if the // 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__)) #if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__)) #define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__))
#else #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 <unistd.h>
#include <atomic> #include <atomic>
#include <cerrno>
#include <climits> #include <climits>
#include <cstdint> #include <cstdint>
#include <ctime> #include <ctime>
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/internal/errno_saver.h"
// The SpinLock lockword is `std::atomic<uint32_t>`. Here we assert that // The SpinLock lockword is `std::atomic<uint32_t>`. Here we assert that
// `std::atomic<uint32_t>` is bitwise equivalent of the `int` expected // `std::atomic<uint32_t>` is bitwise equivalent of the `int` expected
@ -51,12 +51,11 @@ extern "C" {
ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay( ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
std::atomic<uint32_t> *w, uint32_t value, int loop, std::atomic<uint32_t> *w, uint32_t value, int loop,
absl::base_internal::SchedulingMode) { absl::base_internal::SchedulingMode) {
int save_errno = errno; absl::base_internal::ErrnoSaver errno_saver;
struct timespec tm; struct timespec tm;
tm.tv_sec = 0; tm.tv_sec = 0;
tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop); tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop);
syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm); syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm);
errno = save_errno;
} }
ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(std::atomic<uint32_t> *w, 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 // This file is a Posix-specific part of spinlock_wait.cc
#include <sched.h> #include <sched.h>
#include <atomic> #include <atomic>
#include <ctime> #include <ctime>
#include <cerrno>
#include "absl/base/internal/errno_saver.h"
#include "absl/base/internal/scheduling_mode.h" #include "absl/base/internal/scheduling_mode.h"
#include "absl/base/port.h" #include "absl/base/port.h"
@ -27,7 +28,7 @@ extern "C" {
ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay( ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, int loop, std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, int loop,
absl::base_internal::SchedulingMode /* mode */) { absl::base_internal::SchedulingMode /* mode */) {
int save_errno = errno; absl::base_internal::ErrnoSaver errno_saver;
if (loop == 0) { if (loop == 0) {
} else if (loop == 1) { } else if (loop == 1) {
sched_yield(); sched_yield();
@ -37,7 +38,6 @@ ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop); tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop);
nanosleep(&tm, nullptr); nanosleep(&tm, nullptr);
} }
errno = save_errno;
} }
ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake( ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(

View file

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

View file

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

View file

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

View file

@ -35,10 +35,12 @@ ABSL_NAMESPACE_END
#include <fcntl.h> #include <fcntl.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <unistd.h> #include <unistd.h>
#include <atomic> #include <atomic>
#include <cerrno> #include <cerrno>
#include <cstdint> #include <cstdint>
#include "absl/base/internal/errno_saver.h"
#include "absl/base/internal/raw_logging.h" #include "absl/base/internal/raw_logging.h"
namespace absl { 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. // This is a namespace-scoped variable for correct zero-initialization.
static std::atomic<uint64_t> pid_and_fds; // initially 0, an invalid pid. static std::atomic<uint64_t> pid_and_fds; // initially 0, an invalid pid.
bool AddressIsReadable(const void *addr) { 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 // 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 // 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 // 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); std::memory_order_relaxed);
} }
} while (errno == EBADF); } while (errno == EBADF);
errno = save_errno;
return bytes_written == 1; return bytes_written == 1;
} }

View file

@ -465,7 +465,7 @@ class FlagImpl {
// Flag initialization called via absl::call_once. // Flag initialization called via absl::call_once.
void Init(); void Init();
// Attempts to parse supplied `value` std::string. If parsing is successful, // 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::unique_ptr<void, DynValueDeleter> TryParse(absl::string_view value,
std::string* err) const std::string* err) const
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); 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( absl_cc_test(
NAME NAME
status_test status_test
HDRS SRCS
"status_test.cc" "status_test.cc"
COPTS COPTS
${ABSL_TEST_COPTS} ${ABSL_TEST_COPTS}

View file

@ -13,7 +13,7 @@ std::string ConvToString(Conv conv) {
std::string out; std::string out;
#define CONV_SET_CASE(c) \ #define CONV_SET_CASE(c) \
if (Contains(conv, Conv::c)) out += #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 #undef CONV_SET_CASE
if (Contains(conv, Conv::star)) out += "*"; if (Contains(conv, Conv::star)) out += "*";
return out; return out;

View file

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