summaryrefslogtreecommitdiff
path: root/absl
diff options
context:
space:
mode:
Diffstat (limited to 'absl')
-rw-r--r--absl/CMakeLists.txt6
-rw-r--r--absl/base/attributes.h14
-rw-r--r--absl/base/config.h19
-rw-r--r--absl/base/internal/raw_logging.cc5
-rw-r--r--absl/base/internal/raw_logging.h5
-rw-r--r--absl/base/internal/sysinfo.cc28
-rw-r--r--absl/base/internal/thread_identity.cc12
-rw-r--r--absl/base/internal/thread_identity.h9
-rw-r--r--absl/base/options.h9
-rw-r--r--absl/container/btree_map.h24
-rw-r--r--absl/container/btree_test.cc59
-rw-r--r--absl/container/internal/btree_container.h65
-rw-r--r--absl/container/internal/hashtablez_sampler.cc9
-rw-r--r--absl/container/internal/hashtablez_sampler.h13
-rw-r--r--absl/container/internal/hashtablez_sampler_test.cc2
-rw-r--r--absl/container/internal/raw_hash_set_test.cc51
-rw-r--r--absl/copts/AbseilConfigureCopts.cmake7
-rw-r--r--absl/debugging/symbolize_test.cc2
-rw-r--r--absl/flags/BUILD.bazel17
-rw-r--r--absl/flags/flag.cc9
-rw-r--r--absl/flags/flag.h24
-rw-r--r--absl/flags/flag_benchmark.cc111
-rw-r--r--absl/hash/internal/hash.h3
-rw-r--r--absl/numeric/int128.cc4
-rw-r--r--absl/numeric/int128.h2
-rw-r--r--absl/random/BUILD.bazel2
-rw-r--r--absl/random/CMakeLists.txt1
-rw-r--r--absl/random/gaussian_distribution.h3
-rw-r--r--absl/strings/BUILD.bazel5
-rw-r--r--absl/strings/CMakeLists.txt5
-rw-r--r--absl/strings/ascii.cc6
-rw-r--r--absl/strings/ascii.h7
-rw-r--r--absl/strings/internal/charconv_bigint.cc4
-rw-r--r--absl/strings/internal/charconv_bigint.h6
-rw-r--r--absl/strings/internal/str_format/bind.h4
-rw-r--r--absl/strings/internal/str_format/extension.h6
-rw-r--r--absl/strings/numbers.cc7
-rw-r--r--absl/strings/numbers.h9
-rw-r--r--absl/strings/string_view.h25
-rw-r--r--absl/time/format.cc13
-rw-r--r--absl/time/internal/cctz/src/time_zone_fixed.cc28
-rw-r--r--absl/time/internal/cctz/src/time_zone_format_test.cc4
-rw-r--r--absl/time/internal/cctz/src/time_zone_info.cc6
-rw-r--r--absl/time/internal/cctz/src/time_zone_lookup_test.cc15
-rw-r--r--absl/time/time.h87
45 files changed, 527 insertions, 225 deletions
diff --git a/absl/CMakeLists.txt b/absl/CMakeLists.txt
index 3e78397c..a1b1f8d8 100644
--- a/absl/CMakeLists.txt
+++ b/absl/CMakeLists.txt
@@ -14,8 +14,6 @@
# limitations under the License.
#
-
-
add_subdirectory(base)
add_subdirectory(algorithm)
add_subdirectory(container)
@@ -31,3 +29,7 @@ add_subdirectory(synchronization)
add_subdirectory(time)
add_subdirectory(types)
add_subdirectory(utility)
+
+if (${ABSL_BUILD_DLL})
+ absl_make_dll()
+endif()
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index acd1c526..8f77db77 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -563,7 +563,19 @@
// ABSL_ATTRIBUTE_PACKED
//
-// Prevents the compiler from padding a structure to natural alignment
+// Instructs the compiler not to use natural alignment for a tagged data
+// structure, but instead to reduce its alignment to 1. This attribute can
+// either be applied to members of a structure or to a structure in its
+// entirety. Applying this attribute (judiciously) to a structure in its
+// entirety to optimize the memory footprint of very commonly-used structs is
+// fine. Do not apply this attribute to a structure in its entirety if the
+// purpose is to control the offsets of the members in the structure. Instead,
+// apply this attribute only to structure members that need it.
+//
+// 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.
#if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__))
#else
diff --git a/absl/base/config.h b/absl/base/config.h
index c4e8dce4..eac5d268 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -643,4 +643,23 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#undef ABSL_INTERNAL_HAS_KEYWORD
+// ABSL_DLL
+//
+// When building Abseil as a DLL, this macro expands to `__declspec(dllexport)`
+// so we can annotate symbols appropriately as being exported. When used in
+// headers consuming a DLL, this macro expands to `__declspec(dllimport)` so
+// that consumers know the symbol is defined inside the DLL. In all other cases,
+// the macro expands to nothing.
+#if defined(_MSC_VER)
+#if defined(ABSL_BUILD_DLL)
+#define ABSL_DLL __declspec(dllexport)
+#elif defined(ABSL_CONSUME_DLL)
+#define ABSL_DLL __declspec(dllimport)
+#else
+#define ABSL_DLL
+#endif
+#else
+#define ABSL_DLL
+#endif // defined(_MSC_VER)
+
#endif // ABSL_BASE_CONFIG_H_
diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc
index d79c5486..e36eb29a 100644
--- a/absl/base/internal/raw_logging.cc
+++ b/absl/base/internal/raw_logging.cc
@@ -225,8 +225,9 @@ bool RawLoggingFullySupported() {
#endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
}
-ABSL_CONST_INIT absl::base_internal::AtomicHook<InternalLogFunction>
- internal_log_function(DefaultInternalLog);
+ABSL_CONST_INIT ABSL_DLL
+ absl::base_internal::AtomicHook<InternalLogFunction>
+ internal_log_function(DefaultInternalLog);
void RegisterInternalLogFunction(InternalLogFunction func) {
internal_log_function.Store(func);
diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h
index cff45058..ac74f97d 100644
--- a/absl/base/internal/raw_logging.h
+++ b/absl/base/internal/raw_logging.h
@@ -22,9 +22,11 @@
#include <string>
#include "absl/base/attributes.h"
+#include "absl/base/config.h"
#include "absl/base/internal/atomic_hook.h"
#include "absl/base/log_severity.h"
#include "absl/base/macros.h"
+#include "absl/base/optimization.h"
#include "absl/base/port.h"
// This is similar to LOG(severity) << format..., but
@@ -168,7 +170,8 @@ using InternalLogFunction = void (*)(absl::LogSeverity severity,
const char* file, int line,
const std::string& message);
-extern base_internal::AtomicHook<InternalLogFunction> internal_log_function;
+ABSL_DLL extern base_internal::AtomicHook<InternalLogFunction>
+ internal_log_function;
void RegisterInternalLogFunction(InternalLogFunction func);
diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc
index 7945322f..a0930e97 100644
--- a/absl/base/internal/sysinfo.cc
+++ b/absl/base/internal/sysinfo.cc
@@ -58,10 +58,6 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
-static once_flag init_system_info_once;
-static int num_cpus = 0;
-static double nominal_cpu_frequency = 1.0; // 0.0 might be dangerous.
-
static int GetNumCPUs() {
#if defined(__myriad2__)
return 1;
@@ -265,21 +261,27 @@ static double GetNominalCPUFrequency() {
#endif
-// InitializeSystemInfo() may be called before main() and before
-// malloc is properly initialized, therefore this must not allocate
-// memory.
-static void InitializeSystemInfo() {
- num_cpus = GetNumCPUs();
- nominal_cpu_frequency = GetNominalCPUFrequency();
-}
+ABSL_CONST_INIT static once_flag init_num_cpus_once;
+ABSL_CONST_INIT static int num_cpus = 0;
+// NumCPUs() may be called before main() and before malloc is properly
+// initialized, therefore this must not allocate memory.
int NumCPUs() {
- base_internal::LowLevelCallOnce(&init_system_info_once, InitializeSystemInfo);
+ base_internal::LowLevelCallOnce(
+ &init_num_cpus_once, []() { num_cpus = GetNumCPUs(); });
return num_cpus;
}
+// A default frequency of 0.0 might be dangerous if it is used in division.
+ABSL_CONST_INIT static once_flag init_nominal_cpu_frequency_once;
+ABSL_CONST_INIT static double nominal_cpu_frequency = 1.0;
+
+// NominalCPUFrequency() may be called before main() and before malloc is
+// properly initialized, therefore this must not allocate memory.
double NominalCPUFrequency() {
- base_internal::LowLevelCallOnce(&init_system_info_once, InitializeSystemInfo);
+ base_internal::LowLevelCallOnce(
+ &init_nominal_cpu_frequency_once,
+ []() { nominal_cpu_frequency = GetNominalCPUFrequency(); });
return nominal_cpu_frequency;
}
diff --git a/absl/base/internal/thread_identity.cc b/absl/base/internal/thread_identity.cc
index 6a28f246..d63a04ae 100644
--- a/absl/base/internal/thread_identity.cc
+++ b/absl/base/internal/thread_identity.cc
@@ -113,6 +113,18 @@ void SetCurrentThreadIdentity(
#endif
}
+#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
+ ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
+
+// Please see the comment on `CurrentThreadIdentityIfPresent` in
+// thread_identity.h. Because DLLs cannot expose thread_local variables in
+// headers, we opt for the correct-but-slower option of placing the definition
+// of this function only in a translation unit inside DLL.
+#if defined(ABSL_BUILD_DLL) || defined(ABSL_CONSUME_DLL)
+ThreadIdentity* CurrentThreadIdentityIfPresent() { return thread_identity_ptr; }
+#endif
+#endif
+
void ClearCurrentThreadIdentity() {
#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h
index 5dfd0715..ceb109b4 100644
--- a/absl/base/internal/thread_identity.h
+++ b/absl/base/internal/thread_identity.h
@@ -30,6 +30,7 @@
#include <atomic>
#include <cstdint>
+#include "absl/base/config.h"
#include "absl/base/internal/per_thread_tls.h"
namespace absl {
@@ -234,9 +235,17 @@ ABSL_CONST_INIT extern thread_local ThreadIdentity* thread_identity_ptr;
#error Thread-local storage not detected on this platform
#endif
+// thread_local variables cannot be in headers exposed by DLLs. However, it is
+// important for performance reasons in general that
+// `CurrentThreadIdentityIfPresent` be inlined. This is not possible across a
+// DLL boundary so, with DLLs, we opt to have the function not be inlined. Note
+// that `CurrentThreadIdentityIfPresent` is declared above so we can exclude
+// this entire inline definition when compiling as a DLL.
+#if !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL)
inline ThreadIdentity* CurrentThreadIdentityIfPresent() {
return thread_identity_ptr;
}
+#endif
#elif ABSL_THREAD_IDENTITY_MODE != \
ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
diff --git a/absl/base/options.h b/absl/base/options.h
index 592b33b7..6868c77b 100644
--- a/absl/base/options.h
+++ b/absl/base/options.h
@@ -66,7 +66,13 @@
// NOTE: the defaults within this file all assume that Abseil can select the
// proper Abseil implementation at compile-time, which will not be sufficient
// to guarantee ABI stability to package managers.
-//
+
+// Include a standard library header to allow configuration based on the
+// standard library in use.
+#ifdef __cplusplus
+#include <ciso646>
+#endif
+
// -----------------------------------------------------------------------------
// Type Compatibility Options
// -----------------------------------------------------------------------------
@@ -158,7 +164,6 @@
#define ABSL_OPTION_USE_STD_STRING_VIEW 2
-
// ABSL_OPTION_USE_STD_VARIANT
//
// This option controls whether absl::variant is implemented as an alias to
diff --git a/absl/container/btree_map.h b/absl/container/btree_map.h
index cbfcb58c..d23f4ee5 100644
--- a/absl/container/btree_map.h
+++ b/absl/container/btree_map.h
@@ -226,6 +226,30 @@ class btree_map
// Inserts the elements within the initializer list `ilist`.
using Base::insert;
+ // btree_map::insert_or_assign()
+ //
+ // Inserts an element of the specified value into the `btree_map` provided
+ // that a value with the given key does not already exist, or replaces the
+ // corresponding mapped type with the forwarded `obj` argument if a key for
+ // that value already exists, returning an iterator pointing to the newly
+ // inserted element. Overloads are listed below.
+ //
+ // pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj):
+ // pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj):
+ //
+ // Inserts/Assigns (or moves) the element of the specified key into the
+ // `btree_map`. If the returned bool is true, insertion took place, and if
+ // it's false, assignment took place.
+ //
+ // iterator insert_or_assign(const_iterator hint,
+ // const key_type& k, M&& obj):
+ // iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj):
+ //
+ // Inserts/Assigns (or moves) the element of the specified key into the
+ // `btree_map` using the position of `hint` as a non-binding suggestion
+ // for where to begin the insertion search.
+ using Base::insert_or_assign;
+
// btree_map::emplace()
//
// Inserts an element of the specified value by constructing it in-place
diff --git a/absl/container/btree_test.cc b/absl/container/btree_test.cc
index 8692b9c2..af8ee00b 100644
--- a/absl/container/btree_test.cc
+++ b/absl/container/btree_test.cc
@@ -2345,6 +2345,65 @@ TEST(Btree, EraseIf) {
}
}
+TEST(Btree, InsertOrAssign) {
+ absl::btree_map<int, int> m = {{1, 1}, {3, 3}};
+ using value_type = typename decltype(m)::value_type;
+
+ auto ret = m.insert_or_assign(4, 4);
+ EXPECT_EQ(*ret.first, value_type(4, 4));
+ EXPECT_TRUE(ret.second);
+ ret = m.insert_or_assign(3, 100);
+ EXPECT_EQ(*ret.first, value_type(3, 100));
+ EXPECT_FALSE(ret.second);
+
+ auto hint_ret = m.insert_or_assign(ret.first, 3, 200);
+ EXPECT_EQ(*hint_ret, value_type(3, 200));
+ hint_ret = m.insert_or_assign(m.find(1), 0, 1);
+ EXPECT_EQ(*hint_ret, value_type(0, 1));
+ // Test with bad hint.
+ hint_ret = m.insert_or_assign(m.end(), -1, 1);
+ EXPECT_EQ(*hint_ret, value_type(-1, 1));
+
+ EXPECT_THAT(m, ElementsAre(Pair(-1, 1), Pair(0, 1), Pair(1, 1), Pair(3, 200),
+ Pair(4, 4)));
+}
+
+TEST(Btree, InsertOrAssignMovableOnly) {
+ absl::btree_map<int, MovableOnlyInstance> m;
+ using value_type = typename decltype(m)::value_type;
+
+ auto ret = m.insert_or_assign(4, MovableOnlyInstance(4));
+ EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(4)));
+ EXPECT_TRUE(ret.second);
+ ret = m.insert_or_assign(4, MovableOnlyInstance(100));
+ EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(100)));
+ EXPECT_FALSE(ret.second);
+
+ auto hint_ret = m.insert_or_assign(ret.first, 3, MovableOnlyInstance(200));
+ EXPECT_EQ(*hint_ret, value_type(3, MovableOnlyInstance(200)));
+
+ EXPECT_EQ(m.size(), 2);
+}
+
+TEST(Btree, BitfieldArgument) {
+ union {
+ int n : 1;
+ };
+ n = 0;
+ absl::btree_map<int, int> m;
+ m.erase(n);
+ m.count(n);
+ m.find(n);
+ m.contains(n);
+ m.equal_range(n);
+ m.insert_or_assign(n, n);
+ m.insert_or_assign(m.end(), n, n);
+ m.try_emplace(n);
+ m.try_emplace(m.end(), n);
+ m.at(n);
+ m[n];
+}
+
} // namespace
} // namespace container_internal
ABSL_NAMESPACE_END
diff --git a/absl/container/internal/btree_container.h b/absl/container/internal/btree_container.h
index 04795c2e..3e6ff4b8 100644
--- a/absl/container/internal/btree_container.h
+++ b/absl/container/internal/btree_container.h
@@ -372,7 +372,7 @@ class btree_map_container : public btree_set_container<Tree> {
using super_type = btree_set_container<Tree>;
using params_type = typename Tree::params_type;
- protected:
+ private:
template <class K>
using key_arg = typename super_type::template key_arg<K>;
@@ -390,6 +390,69 @@ class btree_map_container : public btree_set_container<Tree> {
btree_map_container() {}
// Insertion routines.
+ // Note: the nullptr template arguments and extra `const M&` overloads allow
+ // for supporting bitfield arguments.
+ // Note: when we call `std::forward<M>(obj)` twice, it's safe because
+ // insert_unique/insert_hint_unique are guaranteed to not consume `obj` when
+ // `ret.second` is false.
+ template <class M>
+ std::pair<iterator, bool> insert_or_assign(const key_type &k, const M &obj) {
+ const std::pair<iterator, bool> ret = this->tree_.insert_unique(k, k, obj);
+ if (!ret.second) ret.first->second = obj;
+ return ret;
+ }
+ template <class M, key_type * = nullptr>
+ std::pair<iterator, bool> insert_or_assign(key_type &&k, const M &obj) {
+ const std::pair<iterator, bool> ret =
+ this->tree_.insert_unique(k, std::move(k), obj);
+ if (!ret.second) ret.first->second = obj;
+ return ret;
+ }
+ template <class M, M * = nullptr>
+ std::pair<iterator, bool> insert_or_assign(const key_type &k, M &&obj) {
+ const std::pair<iterator, bool> ret =
+ this->tree_.insert_unique(k, k, std::forward<M>(obj));
+ if (!ret.second) ret.first->second = std::forward<M>(obj);
+ return ret;
+ }
+ template <class M, key_type * = nullptr, M * = nullptr>
+ std::pair<iterator, bool> insert_or_assign(key_type &&k, M &&obj) {
+ const std::pair<iterator, bool> ret =
+ this->tree_.insert_unique(k, std::move(k), std::forward<M>(obj));
+ if (!ret.second) ret.first->second = std::forward<M>(obj);
+ return ret;
+ }
+ template <class M>
+ iterator insert_or_assign(const_iterator position, const key_type &k,
+ const M &obj) {
+ const std::pair<iterator, bool> ret =
+ this->tree_.insert_hint_unique(iterator(position), k, k, obj);
+ if (!ret.second) ret.first->second = obj;
+ return ret.first;
+ }
+ template <class M, key_type * = nullptr>
+ iterator insert_or_assign(const_iterator position, key_type &&k,
+ const M &obj) {
+ const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique(
+ iterator(position), k, std::move(k), obj);
+ if (!ret.second) ret.first->second = obj;
+ return ret.first;
+ }
+ template <class M, M * = nullptr>
+ iterator insert_or_assign(const_iterator position, const key_type &k,
+ M &&obj) {
+ const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique(
+ iterator(position), k, k, std::forward<M>(obj));
+ if (!ret.second) ret.first->second = std::forward<M>(obj);
+ return ret.first;
+ }
+ template <class M, key_type * = nullptr, M * = nullptr>
+ iterator insert_or_assign(const_iterator position, key_type &&k, M &&obj) {
+ const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique(
+ iterator(position), k, std::move(k), std::forward<M>(obj));
+ if (!ret.second) ret.first->second = std::forward<M>(obj);
+ return ret.first;
+ }
template <typename... Args>
std::pair<iterator, bool> try_emplace(const key_type &k, Args &&... args) {
return this->tree_.insert_unique(
diff --git a/absl/container/internal/hashtablez_sampler.cc b/absl/container/internal/hashtablez_sampler.cc
index e15f4444..56447251 100644
--- a/absl/container/internal/hashtablez_sampler.cc
+++ b/absl/container/internal/hashtablez_sampler.cc
@@ -39,17 +39,16 @@ ABSL_CONST_INIT std::atomic<bool> g_hashtablez_enabled{
ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_sample_parameter{1 << 10};
ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_max_samples{1 << 20};
-#if ABSL_PER_THREAD_TLS == 1
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
ABSL_PER_THREAD_TLS_KEYWORD absl::base_internal::ExponentialBiased
g_exponential_biased_generator;
#endif
} // namespace
-#if ABSL_PER_THREAD_TLS == 1
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample = 0;
-#endif // ABSL_PER_THREAD_TLS == 1
-
+#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
HashtablezSampler& HashtablezSampler::Global() {
static auto* sampler = new HashtablezSampler();
@@ -192,7 +191,7 @@ HashtablezInfo* SampleSlow(int64_t* next_sample) {
return HashtablezSampler::Global().Register();
}
-#if ABSL_PER_THREAD_TLS == 0
+#if !defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
*next_sample = std::numeric_limits<int64_t>::max();
return nullptr;
#else
diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h
index c4f9629f..34d5e572 100644
--- a/absl/container/internal/hashtablez_sampler.h
+++ b/absl/container/internal/hashtablez_sampler.h
@@ -180,14 +180,23 @@ class HashtablezInfoHandle {
HashtablezInfo* info_;
};
-#if ABSL_PER_THREAD_TLS == 1
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+#error ABSL_INTERNAL_HASHTABLEZ_SAMPLE cannot be directly set
+#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+
+#if (ABSL_PER_THREAD_TLS == 1) && !defined(ABSL_BUILD_DLL) && \
+ !defined(ABSL_CONSUME_DLL)
+#define ABSL_INTERNAL_HASHTABLEZ_SAMPLE
+#endif
+
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
extern ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample;
#endif // ABSL_PER_THREAD_TLS
// Returns an RAII sampling handle that manages registration and unregistation
// with the global sampler.
inline HashtablezInfoHandle Sample() {
-#if ABSL_PER_THREAD_TLS == 1
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
if (ABSL_PREDICT_TRUE(--global_next_sample > 0)) {
return HashtablezInfoHandle(nullptr);
}
diff --git a/absl/container/internal/hashtablez_sampler_test.cc b/absl/container/internal/hashtablez_sampler_test.cc
index 102b2375..36f5ccdd 100644
--- a/absl/container/internal/hashtablez_sampler_test.cc
+++ b/absl/container/internal/hashtablez_sampler_test.cc
@@ -169,7 +169,7 @@ TEST(HashtablezInfoTest, RecordRehash) {
EXPECT_EQ(info.num_erases.load(), 0);
}
-#if ABSL_PER_THREAD_TLS == 1
+#if defined(ABSL_HASHTABLEZ_SAMPLE)
TEST(HashtablezSamplerTest, SmallSampleParameter) {
SetHashtablezEnabled(true);
SetHashtablezSampleParameter(100);
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index 38e5e0e8..a96ae68a 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -418,53 +418,6 @@ TEST(Table, Empty) {
EXPECT_TRUE(t.empty());
}
-#ifdef __GNUC__
-template <class T>
-ABSL_ATTRIBUTE_ALWAYS_INLINE inline void DoNotOptimize(const T& v) {
- asm volatile("" : : "r,m"(v) : "memory");
-}
-#endif
-
-TEST(Table, Prefetch) {
- IntTable t;
- t.emplace(1);
- // Works for both present and absent keys.
- t.prefetch(1);
- t.prefetch(2);
-
- // Do not run in debug mode, when prefetch is not implemented, or when
- // sanitizers are enabled, or on WebAssembly.
-#if defined(NDEBUG) && defined(__GNUC__) && defined(__x86_64__) && \
- !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) && \
- !defined(THREAD_SANITIZER) && !defined(UNDEFINED_BEHAVIOR_SANITIZER) && \
- !defined(__EMSCRIPTEN__)
- const auto now = [] { return absl::base_internal::CycleClock::Now(); };
-
- // Make size enough to not fit in L2 cache (16.7 Mb)
- static constexpr int size = 1 << 22;
- for (int i = 0; i < size; ++i) t.insert(i);
-
- int64_t no_prefetch = 0, prefetch = 0;
- for (int iter = 0; iter < 10; ++iter) {
- int64_t time = now();
- for (int i = 0; i < size; ++i) {
- DoNotOptimize(t.find(i));
- }
- no_prefetch += now() - time;
-
- time = now();
- for (int i = 0; i < size; ++i) {
- t.prefetch(i + 20);
- DoNotOptimize(t.find(i));
- }
- prefetch += now() - time;
- }
-
- // no_prefetch is at least 30% slower.
- EXPECT_GE(1.0 * no_prefetch / prefetch, 1.3);
-#endif
-}
-
TEST(Table, LookupEmpty) {
IntTable t;
auto it = t.find(0);
@@ -1842,7 +1795,7 @@ TEST(TableDeathTest, EraseOfEndAsserts) {
EXPECT_DEATH_IF_SUPPORTED(t.erase(t.end()), kDeathMsg);
}
-#if ABSL_PER_THREAD_TLS == 1
+#if defined(ABSL_HASHTABLEZ_SAMPLE)
TEST(RawHashSamplerTest, Sample) {
// Enable the feature even if the prod default is off.
SetHashtablezEnabled(true);
@@ -1863,7 +1816,7 @@ TEST(RawHashSamplerTest, Sample) {
EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
0.01, 0.005);
}
-#endif
+#endif // ABSL_HASHTABLEZ_SAMPLER
TEST(RawHashSamplerTest, DoNotSampleCustomAllocators) {
// Enable the feature even if the prod default is off.
diff --git a/absl/copts/AbseilConfigureCopts.cmake b/absl/copts/AbseilConfigureCopts.cmake
index 7543928a..77d4ace8 100644
--- a/absl/copts/AbseilConfigureCopts.cmake
+++ b/absl/copts/AbseilConfigureCopts.cmake
@@ -5,6 +5,13 @@ set(ABSL_LSAN_LINKOPTS "")
set(ABSL_HAVE_LSAN OFF)
set(ABSL_DEFAULT_LINKOPTS "")
+if (BUILD_SHARED_LIBS AND MSVC)
+ set(ABSL_BUILD_DLL TRUE)
+ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
+else()
+ set(ABSL_BUILD_DLL FALSE)
+endif()
+
if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "AMD64")
if (MSVC)
set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_MSVC_X64_FLAGS}")
diff --git a/absl/debugging/symbolize_test.cc b/absl/debugging/symbolize_test.cc
index 0bac60b9..a1d03aab 100644
--- a/absl/debugging/symbolize_test.cc
+++ b/absl/debugging/symbolize_test.cc
@@ -473,6 +473,7 @@ void ABSL_ATTRIBUTE_NOINLINE TestWithReturnAddress() {
}
#elif defined(_WIN32)
+#if !defined(ABSL_CONSUME_DLL)
TEST(Symbolize, Basics) {
EXPECT_STREQ("nonstatic_func", TrySymbolize((void *)(&nonstatic_func)));
@@ -511,6 +512,7 @@ TEST(Symbolize, SymbolizeWithDemangling) {
EXPECT_TRUE(strstr(result, "Foo::func") != nullptr) << result;
}
+#endif // !defined(ABSL_CONSUME_DLL)
#else // Symbolizer unimplemented
TEST(Symbolize, Unimplemented) {
diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel
index 6c7b2b6e..cbdbae52 100644
--- a/absl/flags/BUILD.bazel
+++ b/absl/flags/BUILD.bazel
@@ -324,6 +324,23 @@ cc_test(
],
)
+cc_binary(
+ name = "flag_benchmark",
+ testonly = 1,
+ srcs = [
+ "flag_benchmark.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ tags = ["benchmark"],
+ visibility = ["//visibility:private"],
+ deps = [
+ ":flag",
+ "//absl/time",
+ "//absl/types:optional",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+)
+
cc_test(
name = "marshalling_test",
size = "small",
diff --git a/absl/flags/flag.cc b/absl/flags/flag.cc
index 9af80079..e67f7304 100644
--- a/absl/flags/flag.cc
+++ b/absl/flags/flag.cc
@@ -22,7 +22,14 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-// This global nutex protects on-demand construction of flag objects in MSVC
+#ifndef NDEBUG
+#define ABSL_FLAGS_GET(T) \
+ T GetFlag(const absl::Flag<T>& flag) { return flag.Get(); }
+ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(ABSL_FLAGS_GET)
+#undef ABSL_FLAGS_GET
+#endif
+
+// This global mutex protects on-demand construction of flag objects in MSVC
// builds.
#if defined(_MSC_VER) && !defined(__clang__)
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
index cc22cdb9..bd61668f 100644
--- a/absl/flags/flag.h
+++ b/absl/flags/flag.h
@@ -186,25 +186,29 @@ class Flag {
//
// // FLAGS_firstname is a Flag of type `std::string`
// std::string first_name = absl::GetFlag(FLAGS_firstname);
-template <typename T,
- typename std::enable_if<
- !flags_internal::IsAtomicFlagTypeTrait<T>::value, int>::type = 0>
-ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
- return flag.Get();
-}
-
+#ifndef NDEBUG
// We want to validate the type mismatch between type definition and
// declaration. The lock-free implementation does not allow us to do it,
// so in debug builds we always use the slower implementation, which always
// validates the type.
-#ifndef NDEBUG
+template <typename T>
+ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
+ return flag.Get();
+}
+// We currently need an external linkage for built-in types because shared
+// libraries have different addresses of flags_internal::FlagOps<T> which
+// might cause log spam when checking the same flag type.
+#define ABSL_FLAGS_INTERNAL_BUILT_IN_EXPORT(T) \
+ ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag);
+ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(ABSL_FLAGS_INTERNAL_BUILT_IN_EXPORT)
+#undef ABSL_FLAGS_INTERNAL_BUILT_IN_EXPORT
+#else
template <typename T,
typename std::enable_if<
- flags_internal::IsAtomicFlagTypeTrait<T>::value, int>::type = 0>
+ !flags_internal::IsAtomicFlagTypeTrait<T>::value, int>::type = 0>
ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
return flag.Get();
}
-#else
// Overload for `GetFlag()` for types that support lock-free reads.
template <typename T,
typename std::enable_if<
diff --git a/absl/flags/flag_benchmark.cc b/absl/flags/flag_benchmark.cc
new file mode 100644
index 00000000..87f73170
--- /dev/null
+++ b/absl/flags/flag_benchmark.cc
@@ -0,0 +1,111 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/flag.h"
+#include "absl/time/time.h"
+#include "absl/types/optional.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+using String = std::string;
+using VectorOfStrings = std::vector<std::string>;
+using AbslDuration = absl::Duration;
+
+// We do not want to take over marshalling for the types absl::optional<int>,
+// absl::optional<std::string> which we do not own. Instead we introduce unique
+// "aliases" to these types, which we do.
+using AbslOptionalInt = absl::optional<int>;
+struct OptionalInt : AbslOptionalInt {
+ using AbslOptionalInt::AbslOptionalInt;
+};
+// Next two functions represent Abseil Flags marshalling for OptionalInt.
+bool AbslParseFlag(absl::string_view src, OptionalInt* flag,
+ std::string* error) {
+ int val;
+ if (src.empty())
+ flag->reset();
+ else if (!absl::ParseFlag(src, &val, error))
+ return false;
+ *flag = val;
+ return true;
+}
+std::string AbslUnparseFlag(const OptionalInt& flag) {
+ return !flag ? "" : absl::UnparseFlag(*flag);
+}
+
+using AbslOptionalString = absl::optional<std::string>;
+struct OptionalString : AbslOptionalString {
+ using AbslOptionalString::AbslOptionalString;
+};
+// Next two functions represent Abseil Flags marshalling for OptionalString.
+bool AbslParseFlag(absl::string_view src, OptionalString* flag,
+ std::string* error) {
+ std::string val;
+ if (src.empty())
+ flag->reset();
+ else if (!absl::ParseFlag(src, &val, error))
+ return false;
+ *flag = val;
+ return true;
+}
+std::string AbslUnparseFlag(const OptionalString& flag) {
+ return !flag ? "" : absl::UnparseFlag(*flag);
+}
+
+struct UDT {
+ UDT() = default;
+ UDT(const UDT&) {}
+ UDT& operator=(const UDT&) { return *this; }
+};
+// Next two functions represent Abseil Flags marshalling for UDT.
+bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
+std::string AbslUnparseFlag(const UDT&) { return ""; }
+
+} // namespace
+
+#define BENCHMARKED_TYPES(A) \
+ A(bool) \
+ A(int16_t) \
+ A(uint16_t) \
+ A(int32_t) \
+ A(uint32_t) \
+ A(int64_t) \
+ A(uint64_t) \
+ A(double) \
+ A(float) \
+ A(String) \
+ A(VectorOfStrings) \
+ A(OptionalInt) \
+ A(OptionalString) \
+ A(AbslDuration) \
+ A(UDT)
+
+#define FLAG_DEF(T) ABSL_FLAG(T, T##_flag, {}, "");
+
+BENCHMARKED_TYPES(FLAG_DEF)
+
+namespace {
+
+#define BM_GetFlag(T) \
+ void BM_GetFlag_##T(benchmark::State& state) { \
+ for (auto _ : state) { \
+ benchmark::DoNotOptimize(absl::GetFlag(FLAGS_##T##_flag)); \
+ } \
+ } \
+ BENCHMARK(BM_GetFlag_##T);
+
+BENCHMARKED_TYPES(BM_GetFlag)
+
+} // namespace
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index 8639181f..ae7a60cd 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -708,7 +708,8 @@ struct is_hashable
: std::integral_constant<bool, HashSelect::template Apply<T>::value> {};
// CityHashState
-class CityHashState : public HashStateBase<CityHashState> {
+class ABSL_DLL CityHashState
+ : public HashStateBase<CityHashState> {
// absl::uint128 is not an alias or a thin wrapper around the intrinsic.
// We use the intrinsic when available to improve performance.
#ifdef ABSL_HAVE_INTRINSIC_INT128
diff --git a/absl/numeric/int128.cc b/absl/numeric/int128.cc
index a20a77e7..b605a870 100644
--- a/absl/numeric/int128.cc
+++ b/absl/numeric/int128.cc
@@ -25,8 +25,8 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-const uint128 kuint128max = MakeUint128(std::numeric_limits<uint64_t>::max(),
- std::numeric_limits<uint64_t>::max());
+ABSL_DLL const uint128 kuint128max = MakeUint128(
+ std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max());
namespace {
diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h
index 718f70b1..636e3a5b 100644
--- a/absl/numeric/int128.h
+++ b/absl/numeric/int128.h
@@ -234,7 +234,7 @@ class
// Prefer to use the constexpr `Uint128Max()`.
//
// TODO(absl-team) deprecate kuint128max once migration tool is released.
-extern const uint128 kuint128max;
+ABSL_DLL extern const uint128 kuint128max;
// allow uint128 to be logged
std::ostream& operator<<(std::ostream& os, uint128 v);
diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel
index 2585b397..f78fbc7e 100644
--- a/absl/random/BUILD.bazel
+++ b/absl/random/BUILD.bazel
@@ -67,6 +67,7 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/base:base_internal",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/meta:type_traits",
"//absl/random/internal:distributions",
@@ -183,6 +184,7 @@ cc_test(
timeout = "eternal", # Android can take a very long time
srcs = ["beta_distribution_test.cc"],
copts = ABSL_TEST_COPTS,
+ flaky = 1,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":distributions",
diff --git a/absl/random/CMakeLists.txt b/absl/random/CMakeLists.txt
index 46dbc3ef..efa55d8f 100644
--- a/absl/random/CMakeLists.txt
+++ b/absl/random/CMakeLists.txt
@@ -183,6 +183,7 @@ absl_cc_library(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::base_internal
+ absl::config
absl::core_headers
absl::random_internal_generate_real
absl::random_internal_distributions
diff --git a/absl/random/gaussian_distribution.h b/absl/random/gaussian_distribution.h
index c1427b06..4b07a5c0 100644
--- a/absl/random/gaussian_distribution.h
+++ b/absl/random/gaussian_distribution.h
@@ -28,6 +28,7 @@
#include <limits>
#include <type_traits>
+#include "absl/base/config.h"
#include "absl/random/internal/fast_uniform_bits.h"
#include "absl/random/internal/generate_real.h"
#include "absl/random/internal/iostream_state_saver.h"
@@ -43,7 +44,7 @@ namespace random_internal {
// The specific algorithm has some of the improvements suggested by the
// 2005 paper, "An Improved Ziggurat Method to Generate Normal Random Samples",
// Jurgen A Doornik. (https://www.doornik.com/research/ziggurat.pdf)
-class gaussian_distribution_base {
+class ABSL_DLL gaussian_distribution_base {
public:
template <typename URBG>
inline double zignor(URBG& g); // NOLINT(runtime/references)
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index dc7e1bfd..d5a362d0 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -37,7 +37,6 @@ cc_library(
"internal/charconv_bigint.h",
"internal/charconv_parse.cc",
"internal/charconv_parse.h",
- "internal/escaping.cc",
"internal/memutil.cc",
"internal/memutil.h",
"internal/stl_type_traits.h",
@@ -55,7 +54,6 @@ cc_library(
"ascii.h",
"charconv.h",
"escaping.h",
- "internal/escaping.h",
"match.h",
"numbers.h",
"str_cat.h",
@@ -85,11 +83,13 @@ cc_library(
cc_library(
name = "internal",
srcs = [
+ "internal/escaping.cc",
"internal/ostringstream.cc",
"internal/utf8.cc",
],
hdrs = [
"internal/char_map.h",
+ "internal/escaping.h",
"internal/ostringstream.h",
"internal/resize_uninitialized.h",
"internal/utf8.h",
@@ -99,6 +99,7 @@ cc_library(
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:endian",
+ "//absl/base:raw_logging_internal",
"//absl/meta:type_traits",
],
)
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index 36702f71..3feb5e94 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -38,8 +38,6 @@ absl_cc_library(
"internal/charconv_bigint.h"
"internal/charconv_parse.cc"
"internal/charconv_parse.h"
- "internal/escaping.cc"
- "internal/escaping.h"
"internal/memutil.cc"
"internal/memutil.h"
"internal/stl_type_traits.h"
@@ -74,6 +72,8 @@ absl_cc_library(
strings_internal
HDRS
"internal/char_map.h"
+ "internal/escaping.cc"
+ "internal/escaping.h"
"internal/ostringstream.h"
"internal/resize_uninitialized.h"
"internal/utf8.h"
@@ -86,6 +86,7 @@ absl_cc_library(
absl::config
absl::core_headers
absl::endian
+ absl::raw_logging_internal
absl::type_traits
)
diff --git a/absl/strings/ascii.cc b/absl/strings/ascii.cc
index abea3e4f..93bb03e9 100644
--- a/absl/strings/ascii.cc
+++ b/absl/strings/ascii.cc
@@ -57,7 +57,7 @@ namespace ascii_internal {
// of these bits is tightly coupled to this implementation, the individual bits
// are not named. Note that bitfields for all characters above ASCII 127 are
// zero-initialized.
-const unsigned char kPropertyBits[256] = {
+ABSL_DLL const unsigned char kPropertyBits[256] = {
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x00
0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x10
@@ -79,7 +79,7 @@ const unsigned char kPropertyBits[256] = {
// Array of characters for the ascii_tolower() function. For values 'A'
// through 'Z', return the lower-case character; otherwise, return the
// identity of the passed character.
-const char kToLower[256] = {
+ABSL_DLL const char kToLower[256] = {
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
@@ -117,7 +117,7 @@ const char kToLower[256] = {
// Array of characters for the ascii_toupper() function. For values 'a'
// through 'z', return the upper-case character; otherwise, return the
// identity of the passed character.
-const char kToUpper[256] = {
+ABSL_DLL const char kToUpper[256] = {
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
diff --git a/absl/strings/ascii.h b/absl/strings/ascii.h
index 792aabe5..b46bc71f 100644
--- a/absl/strings/ascii.h
+++ b/absl/strings/ascii.h
@@ -56,6 +56,7 @@
#include <string>
#include "absl/base/attributes.h"
+#include "absl/base/config.h"
#include "absl/strings/string_view.h"
namespace absl {
@@ -63,13 +64,13 @@ ABSL_NAMESPACE_BEGIN
namespace ascii_internal {
// Declaration for an array of bitfields holding character information.
-extern const unsigned char kPropertyBits[256];
+ABSL_DLL extern const unsigned char kPropertyBits[256];
// Declaration for the array of characters to upper-case characters.
-extern const char kToUpper[256];
+ABSL_DLL extern const char kToUpper[256];
// Declaration for the array of characters to lower-case characters.
-extern const char kToLower[256];
+ABSL_DLL extern const char kToLower[256];
} // namespace ascii_internal
diff --git a/absl/strings/internal/charconv_bigint.cc b/absl/strings/internal/charconv_bigint.cc
index 860c27b2..66f33e72 100644
--- a/absl/strings/internal/charconv_bigint.cc
+++ b/absl/strings/internal/charconv_bigint.cc
@@ -158,12 +158,12 @@ const uint32_t* LargePowerOfFiveData(int i) {
int LargePowerOfFiveSize(int i) { return 2 * i; }
} // namespace
-const uint32_t kFiveToNth[14] = {
+ABSL_DLL const uint32_t kFiveToNth[14] = {
1, 5, 25, 125, 625, 3125, 15625,
78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125,
};
-const uint32_t kTenToNth[10] = {
+ABSL_DLL const uint32_t kTenToNth[10] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,
};
diff --git a/absl/strings/internal/charconv_bigint.h b/absl/strings/internal/charconv_bigint.h
index 108e1eb2..999e9ae3 100644
--- a/absl/strings/internal/charconv_bigint.h
+++ b/absl/strings/internal/charconv_bigint.h
@@ -20,6 +20,7 @@
#include <iostream>
#include <string>
+#include "absl/base/config.h"
#include "absl/strings/ascii.h"
#include "absl/strings/internal/charconv_parse.h"
#include "absl/strings/string_view.h"
@@ -33,8 +34,9 @@ constexpr int kMaxSmallPowerOfFive = 13;
// The largest power that 10 that can be raised to, and still fit in a uint32_t.
constexpr int kMaxSmallPowerOfTen = 9;
-extern const uint32_t kFiveToNth[kMaxSmallPowerOfFive + 1];
-extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];
+ABSL_DLL extern const uint32_t
+ kFiveToNth[kMaxSmallPowerOfFive + 1];
+ABSL_DLL extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];
// Large, fixed-width unsigned integer.
//
diff --git a/absl/strings/internal/str_format/bind.h b/absl/strings/internal/str_format/bind.h
index 2bf0c085..cf41b197 100644
--- a/absl/strings/internal/str_format/bind.h
+++ b/absl/strings/internal/str_format/bind.h
@@ -122,8 +122,8 @@ class FormatSpecTemplate
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
template <Conv... C, typename = typename std::enable_if<
- sizeof...(C) == sizeof...(Args) &&
- AllOf(Contains(ArgumentToConv<Args>(),
+ AllOf(sizeof...(C) == sizeof...(Args),
+ Contains(ArgumentToConv<Args>(),
C)...)>::type>
FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc) // NOLINT
: Base(&pc) {}
diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h
index 51d7dd6f..0a764035 100644
--- a/absl/strings/internal/str_format/extension.h
+++ b/absl/strings/internal/str_format/extension.h
@@ -17,10 +17,12 @@
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
#include <limits.h>
+
#include <cstddef>
#include <cstring>
#include <ostream>
+#include "absl/base/config.h"
#include "absl/base/port.h"
#include "absl/strings/internal/str_format/output.h"
#include "absl/strings/string_view.h"
@@ -134,7 +136,7 @@ struct Flags {
}
};
-struct LengthMod {
+struct ABSL_DLL LengthMod {
public:
enum Id : uint8_t {
h, hh, l, ll, L, j, z, t, q, none
@@ -196,7 +198,7 @@ struct LengthMod {
X_VAL(n) X_SEP X_VAL(p)
// clang-format on
-struct ConversionChar {
+struct ABSL_DLL ConversionChar {
public:
enum Id : uint8_t {
c, C, s, S, // text
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index a0e5a7fd..68c26dd6 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -900,9 +900,10 @@ inline bool safe_uint_internal(absl::string_view text, IntType* value_p,
namespace numbers_internal {
// Digit conversion.
-ABSL_CONST_INIT const char kHexChar[] = "0123456789abcdef";
+ABSL_CONST_INIT ABSL_DLL const char kHexChar[] =
+ "0123456789abcdef";
-ABSL_CONST_INIT const char kHexTable[513] =
+ABSL_CONST_INIT ABSL_DLL const char kHexTable[513] =
"000102030405060708090a0b0c0d0e0f"
"101112131415161718191a1b1c1d1e1f"
"202122232425262728292a2b2c2d2e2f"
@@ -920,7 +921,7 @@ ABSL_CONST_INIT const char kHexTable[513] =
"e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
-ABSL_CONST_INIT const char two_ASCII_digits[100][2] = {
+ABSL_CONST_INIT ABSL_DLL const char two_ASCII_digits[100][2] = {
{'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'},
{'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'},
{'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'},
diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h
index 61204683..d872cca5 100644
--- a/absl/strings/numbers.h
+++ b/absl/strings/numbers.h
@@ -36,6 +36,7 @@
#include <string>
#include <type_traits>
+#include "absl/base/config.h"
#include "absl/base/internal/bits.h"
#ifdef __SSE4_2__
// TODO(jorg): Remove this when we figure out the right way
@@ -106,9 +107,11 @@ ABSL_NAMESPACE_BEGIN
namespace numbers_internal {
// Digit conversion.
-extern const char kHexChar[17]; // 0123456789abcdef
-extern const char kHexTable[513]; // 000102030405060708090a0b0c0d0e0f1011...
-extern const char two_ASCII_digits[100][2]; // 00, 01, 02, 03...
+ABSL_DLL extern const char kHexChar[17]; // 0123456789abcdef
+ABSL_DLL extern const char
+ kHexTable[513]; // 000102030405060708090a0b0c0d0e0f1011...
+ABSL_DLL extern const char
+ two_ASCII_digits[100][2]; // 00, 01, 02, 03...
// Writes a two-character representation of 'i' to 'buf'. 'i' must be in the
// range 0 <= i < 100, and buf must have space for two characters. Example:
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h
index 4f7dd6b3..01965b0e 100644
--- a/absl/strings/string_view.h
+++ b/absl/strings/string_view.h
@@ -28,7 +28,19 @@
#define ABSL_STRINGS_STRING_VIEW_H_
#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <iosfwd>
+#include <iterator>
+#include <limits>
+#include <string>
+
#include "absl/base/config.h"
+#include "absl/base/internal/throw_delegate.h"
+#include "absl/base/macros.h"
+#include "absl/base/optimization.h"
+#include "absl/base/port.h"
#ifdef ABSL_USES_STD_STRING_VIEW
@@ -49,19 +61,6 @@ ABSL_NAMESPACE_END
#define ABSL_INTERNAL_STRING_VIEW_MEMCMP memcmp
#endif // ABSL_HAVE_BUILTIN(__builtin_memcmp)
-#include <cassert>
-#include <cstddef>
-#include <cstring>
-#include <iosfwd>
-#include <iterator>
-#include <limits>
-#include <string>
-
-#include "absl/base/internal/throw_delegate.h"
-#include "absl/base/macros.h"
-#include "absl/base/optimization.h"
-#include "absl/base/port.h"
-
namespace absl {
ABSL_NAMESPACE_BEGIN
diff --git a/absl/time/format.cc b/absl/time/format.cc
index 5997ef0c..ee088f33 100644
--- a/absl/time/format.cc
+++ b/absl/time/format.cc
@@ -24,11 +24,14 @@ namespace cctz = absl::time_internal::cctz;
namespace absl {
ABSL_NAMESPACE_BEGIN
-extern const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
-extern const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
-
-extern const char RFC1123_full[] = "%a, %d %b %E4Y %H:%M:%S %z";
-extern const char RFC1123_no_wday[] = "%d %b %E4Y %H:%M:%S %z";
+ABSL_DLL extern const char RFC3339_full[] =
+ "%Y-%m-%dT%H:%M:%E*S%Ez";
+ABSL_DLL extern const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
+
+ABSL_DLL extern const char RFC1123_full[] =
+ "%a, %d %b %E4Y %H:%M:%S %z";
+ABSL_DLL extern const char RFC1123_no_wday[] =
+ "%d %b %E4Y %H:%M:%S %z";
namespace {
diff --git a/absl/time/internal/cctz/src/time_zone_fixed.cc b/absl/time/internal/cctz/src/time_zone_fixed.cc
index a342e37d..303c0244 100644
--- a/absl/time/internal/cctz/src/time_zone_fixed.cc
+++ b/absl/time/internal/cctz/src/time_zone_fixed.cc
@@ -89,29 +89,29 @@ std::string FixedOffsetToName(const seconds& offset) {
// offsets and to (somewhat) limit the total number of zones.
return "UTC";
}
- int seconds = static_cast<int>(offset.count());
- const char sign = (seconds < 0 ? '-' : '+');
- int minutes = seconds / 60;
- seconds %= 60;
+ int offset_seconds = static_cast<int>(offset.count());
+ const char sign = (offset_seconds < 0 ? '-' : '+');
+ int offset_minutes = offset_seconds / 60;
+ offset_seconds %= 60;
if (sign == '-') {
- if (seconds > 0) {
- seconds -= 60;
- minutes += 1;
+ if (offset_seconds > 0) {
+ offset_seconds -= 60;
+ offset_minutes += 1;
}
- seconds = -seconds;
- minutes = -minutes;
+ offset_seconds = -offset_seconds;
+ offset_minutes = -offset_minutes;
}
- int hours = minutes / 60;
- minutes %= 60;
+ int offset_hours = offset_minutes / 60;
+ offset_minutes %= 60;
const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
char buf[prefix_len + sizeof("-24:00:00")];
char* ep = std::copy(kFixedZonePrefix, kFixedZonePrefix + prefix_len, buf);
*ep++ = sign;
- ep = Format02d(ep, hours);
+ ep = Format02d(ep, offset_hours);
*ep++ = ':';
- ep = Format02d(ep, minutes);
+ ep = Format02d(ep, offset_minutes);
*ep++ = ':';
- ep = Format02d(ep, seconds);
+ ep = Format02d(ep, offset_seconds);
*ep++ = '\0';
assert(ep == buf + sizeof(buf));
return buf;
diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc
index de75629a..caebcc4d 100644
--- a/absl/time/internal/cctz/src/time_zone_format_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_format_test.cc
@@ -1252,9 +1252,9 @@ TEST(Parse, ExtendedSubecondsScan) {
const auto expected = chrono::system_clock::from_time_t(0) +
chrono::nanoseconds(micros * 1000 + ns);
for (int ps = 0; ps < 1000; ps += 250) {
- std::ostringstream oss;
+ std::ostringstream ps_oss;
oss << std::setfill('0') << std::setw(3) << ps;
- const std::string input = nanos + oss.str() + "999";
+ const std::string input = nanos + ps_oss.str() + "999";
EXPECT_TRUE(parse("%E*f", input, tz, &tp));
EXPECT_EQ(expected + chrono::nanoseconds(ps) / 1000, tp) << input;
}
diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc
index 971542d0..f1697cdf 100644
--- a/absl/time/internal/cctz/src/time_zone_info.cc
+++ b/absl/time/internal/cctz/src/time_zone_info.cc
@@ -641,9 +641,9 @@ std::unique_ptr<ZoneInfoSource> FileZoneInfoSource::Open(
if (fp == nullptr) return nullptr;
std::size_t length = 0;
if (fseek(fp, 0, SEEK_END) == 0) {
- long pos = ftell(fp);
- if (pos >= 0) {
- length = static_cast<std::size_t>(pos);
+ long offset = ftell(fp);
+ if (offset >= 0) {
+ length = static_cast<std::size_t>(offset);
}
rewind(fp);
}
diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
index 227b1278..99137a08 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -1028,16 +1028,17 @@ TEST(MakeTime, LocalTimeLibC) {
ASSERT_EQ(0, setenv("TZ", *np, 1)); // change what "localtime" means
const auto zi = local_time_zone();
const auto lc = LoadZone("libc:localtime");
- time_zone::civil_transition trans;
+ time_zone::civil_transition transition;
for (auto tp = zi.lookup(civil_second()).trans;
- zi.next_transition(tp, &trans); tp = zi.lookup(trans.to).trans) {
- const auto fcl = zi.lookup(trans.from);
- const auto tcl = zi.lookup(trans.to);
+ zi.next_transition(tp, &transition);
+ tp = zi.lookup(transition.to).trans) {
+ const auto fcl = zi.lookup(transition.from);
+ const auto tcl = zi.lookup(transition.to);
civil_second cs; // compare cs in zi and lc
if (fcl.kind == time_zone::civil_lookup::UNIQUE) {
if (tcl.kind == time_zone::civil_lookup::UNIQUE) {
// Both unique; must be an is_dst or abbr change.
- ASSERT_EQ(trans.from, trans.to);
+ ASSERT_EQ(transition.from, transition.to);
const auto trans = fcl.trans;
const auto tal = zi.lookup(trans);
const auto tprev = trans - absl::time_internal::cctz::seconds(1);
@@ -1048,11 +1049,11 @@ TEST(MakeTime, LocalTimeLibC) {
continue;
}
ASSERT_EQ(time_zone::civil_lookup::REPEATED, tcl.kind);
- cs = trans.to;
+ cs = transition.to;
} else {
ASSERT_EQ(time_zone::civil_lookup::UNIQUE, tcl.kind);
ASSERT_EQ(time_zone::civil_lookup::SKIPPED, fcl.kind);
- cs = trans.from;
+ cs = transition.from;
}
if (cs.year() > 2037) break; // limit test time (and to 32-bit time_t)
const auto cl_zi = zi.lookup(cs);
diff --git a/absl/time/time.h b/absl/time/time.h
index 1be5727c..33a4a630 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -527,59 +527,30 @@ std::chrono::seconds ToChronoSeconds(Duration d);
std::chrono::minutes ToChronoMinutes(Duration d);
std::chrono::hours ToChronoHours(Duration d);
-
// FormatDuration()
//
-// Returns a string represention of the duration in a format consisting of a
-// 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()`
+// Returns a string representing the duration in the form "72h3m0.5s".
+// Returns "inf" or "-inf" for +/- `InfiniteDuration()`.
std::string FormatDuration(Duration d);
+// Output stream operator.
+inline std::ostream& operator<<(std::ostream& os, Duration d) {
+ return os << FormatDuration(d);
+}
+
// ParseDuration()
//
-// Parses a `dur_string` of the format noted above into an `absl::Duration`
-// value.
-//
-// Parses "0" as a zero-length duration value. Parses "-inf" or "+inf" as
-// infinite durations values.
+// Parses a duration string consisting of a possibly signed sequence of
+// decimal numbers, each with an optional fractional part and a unit
+// suffix. The valid suffixes are "ns", "us" "ms", "s", "m", and "h".
+// Simple examples include "300ms", "-1.5h", and "2h45m". Parses "0" as
+// `ZeroDuration()`. Parses "inf" and "-inf" as +/- `InfiniteDuration()`.
bool ParseDuration(const std::string& dur_string, Duration* d);
-// AbslParseFlag()
-//
-// 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()`
+// Support for flag values of type Duration. Duration flags must be specified
+// in a format that is valid input for absl::ParseDuration().
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);
-
-// 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.")
bool ParseFlag(const std::string& text, Duration* dst, std::string* error);
ABSL_DEPRECATED("Use AbslUnparseFlag() instead.")
@@ -842,29 +813,18 @@ Time FromChrono(const std::chrono::system_clock::time_point& tp);
// // tp == std::chrono::system_clock::from_time_t(123);
std::chrono::system_clock::time_point ToChronoTime(Time);
-// AbslParseFlag()
-//
-// 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:
+// Support for flag values of type Time. Time flags must be specified in a
+// format that matches absl::RFC3339_full. For example:
//
// --start_time=2016-01-02T03:04:05.678+08:00
//
// 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
-// seconds/milliseconds/etc from the Unix epoch, use an `absl::Duration` flag
-// and add that duration to `absl::UnixEpoch()` to get an `absl::Time`.
+// seconds/milliseconds/etc from the Unix epoch, use an absl::Duration flag
+// and add that duration to absl::UnixEpoch() to get an absl::Time.
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);
-
ABSL_DEPRECATED("Use AbslParseFlag() instead.")
bool ParseFlag(const std::string& text, Time* t, std::string* error);
ABSL_DEPRECATED("Use AbslUnparseFlag() instead.")
@@ -1243,15 +1203,18 @@ struct tm ToTM(Time t, TimeZone tz);
// time with UTC offset. Also note the use of "%Y": RFC3339 mandates that
// years have exactly four digits, but we allow them to take their natural
// width.
-extern const char RFC3339_full[]; // %Y-%m-%dT%H:%M:%E*S%Ez
-extern const char RFC3339_sec[]; // %Y-%m-%dT%H:%M:%S%Ez
+ABSL_DLL extern const char
+ RFC3339_full[]; // %Y-%m-%dT%H:%M:%E*S%Ez
+ABSL_DLL extern const char RFC3339_sec[]; // %Y-%m-%dT%H:%M:%S%Ez
// RFC1123_full
// RFC1123_no_wday
//
// FormatTime()/ParseTime() format specifiers for RFC1123 date/time strings.
-extern const char RFC1123_full[]; // %a, %d %b %E4Y %H:%M:%S %z
-extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
+ABSL_DLL extern const char
+ RFC1123_full[]; // %a, %d %b %E4Y %H:%M:%S %z
+ABSL_DLL extern const char
+ RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
// FormatTime()
//