mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Export of internal Abseil changes
-- 77c85460dc3c46593b231c5161ac55273bb0c7ef by Abseil Team <absl-team@google.com>: Support int128 in SimpleAtoi. PiperOrigin-RevId: 337946262 -- 0be53049ccf8309650e4e22f23b290e5f75ee828 by Gennadiy Rozental <rogeeff@google.com>: Update build scripts to use --mount instead of --volume to mount the host data into a container. This is somewhat more verbose, but more readable and flexible. More importantly this is what docker documentation is recomending to use now. PiperOrigin-RevId: 337898761 -- 3bc877f1679fdf61ecbf4365287a0403cfc9b53e by Samuel Benzaquen <sbenza@google.com>: Add Cord constructor for constinit instances. PiperOrigin-RevId: 337871148 -- 8b87701892b9c325e78ad4e8e4f16b785a744622 by Chris Kennelly <ckennelly@google.com>: Use the address of kSeed, rather than its value. We initialize kSeed with &kSeed, so these are equivalent, but kSeed requires a load from memory while &kSeed can be formed as a RIP-relative lea. PiperOrigin-RevId: 337868415 GitOrigin-RevId: 77c85460dc3c46593b231c5161ac55273bb0c7ef Change-Id: I3d06c18a123f1be29dad5801e8625952dc41cd95
This commit is contained in:
committed by
Gennadiy Rozental
parent
8f1c34a77a
commit
4b915e7092
@@ -196,6 +196,7 @@ set(ABSL_INTERNAL_DLL_FILES
|
||||
"strings/internal/charconv_parse.cc"
|
||||
"strings/internal/charconv_parse.h"
|
||||
"strings/internal/stl_type_traits.h"
|
||||
"strings/internal/string_constant.h"
|
||||
"strings/match.cc"
|
||||
"strings/match.h"
|
||||
"strings/numbers.cc"
|
||||
|
||||
@@ -855,7 +855,14 @@ class ABSL_DLL CityHashState
|
||||
// On other platforms this is still going to be non-deterministic but most
|
||||
// probably per-build and not per-process.
|
||||
ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Seed() {
|
||||
#if (!defined(__clang__) || __clang_major__ > 11) && \
|
||||
!defined(__apple_build_version__)
|
||||
return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&kSeed));
|
||||
#else
|
||||
// Workaround the absence of
|
||||
// https://github.com/llvm/llvm-project/commit/bc15bf66dcca76cc06fe71fca35b74dc4d521021.
|
||||
return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(kSeed));
|
||||
#endif
|
||||
}
|
||||
static const void* const kSeed;
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ cc_library(
|
||||
"ascii.h",
|
||||
"charconv.h",
|
||||
"escaping.h",
|
||||
"internal/string_constant.h",
|
||||
"match.h",
|
||||
"numbers.h",
|
||||
"str_cat.h",
|
||||
@@ -222,6 +223,19 @@ cc_test(
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "string_constant_test",
|
||||
size = "small",
|
||||
srcs = ["internal/string_constant_test.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":strings",
|
||||
"//absl/meta:type_traits",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "string_view_benchmark",
|
||||
srcs = ["string_view_benchmark.cc"],
|
||||
|
||||
@@ -21,6 +21,7 @@ absl_cc_library(
|
||||
"ascii.h"
|
||||
"charconv.h"
|
||||
"escaping.h"
|
||||
"internal/string_constant.h"
|
||||
"match.h"
|
||||
"numbers.h"
|
||||
"str_cat.h"
|
||||
@@ -158,6 +159,19 @@ absl_cc_test(
|
||||
gmock_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
string_constant_test
|
||||
SRCS
|
||||
"internal/string_constant_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::strings
|
||||
absl::type_traits
|
||||
gmock_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
string_view_test
|
||||
|
||||
@@ -241,6 +241,7 @@ static void UnrefInternal(CordRep* rep) {
|
||||
|
||||
absl::InlinedVector<CordRep*, kInlinedVectorSize> pending;
|
||||
while (true) {
|
||||
assert(!rep->refcount.IsImmortal());
|
||||
if (rep->tag == CONCAT) {
|
||||
CordRepConcat* rep_concat = rep->concat();
|
||||
CordRep* right = rep_concat->right;
|
||||
@@ -256,6 +257,7 @@ static void UnrefInternal(CordRep* rep) {
|
||||
}
|
||||
} else if (rep->tag == EXTERNAL) {
|
||||
CordRepExternal* rep_external = rep->external();
|
||||
assert(rep_external->releaser_invoker != nullptr);
|
||||
rep_external->releaser_invoker(rep_external);
|
||||
rep = nullptr;
|
||||
} else if (rep->tag == SUBSTRING) {
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
#include "absl/meta/type_traits.h"
|
||||
#include "absl/strings/internal/cord_internal.h"
|
||||
#include "absl/strings/internal/resize_uninitialized.h"
|
||||
#include "absl/strings/internal/string_constant.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
@@ -624,6 +625,14 @@ class Cord {
|
||||
return c.HashFragmented(std::move(hash_state));
|
||||
}
|
||||
|
||||
// Create a Cord with the contents of StringConstant<T>::value.
|
||||
// No allocations will be done and no data will be copied.
|
||||
// This is an INTERNAL API and subject to change or removal. This API can only
|
||||
// be used by spelling absl::strings_internal::MakeStringConstant, which is
|
||||
// also an internal API.
|
||||
template <typename T>
|
||||
explicit constexpr Cord(strings_internal::StringConstant<T>);
|
||||
|
||||
private:
|
||||
friend class CordTestPeer;
|
||||
friend bool operator==(const Cord& lhs, const Cord& rhs);
|
||||
@@ -655,6 +664,8 @@ class Cord {
|
||||
InlineRep& operator=(const InlineRep& src);
|
||||
InlineRep& operator=(InlineRep&& src) noexcept;
|
||||
|
||||
explicit constexpr InlineRep(cord_internal::InlineData data);
|
||||
|
||||
void Swap(InlineRep* rhs);
|
||||
bool empty() const;
|
||||
size_t size() const;
|
||||
@@ -884,6 +895,9 @@ Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) {
|
||||
return cord;
|
||||
}
|
||||
|
||||
constexpr Cord::InlineRep::InlineRep(cord_internal::InlineData data)
|
||||
: data_(data) {}
|
||||
|
||||
inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src) {
|
||||
data_ = src.data_;
|
||||
}
|
||||
@@ -981,6 +995,18 @@ inline void Cord::InlineRep::CopyToArray(char* dst) const {
|
||||
|
||||
constexpr inline Cord::Cord() noexcept {}
|
||||
|
||||
template <typename T>
|
||||
constexpr Cord::Cord(strings_internal::StringConstant<T>)
|
||||
: contents_(strings_internal::StringConstant<T>::value.size() <=
|
||||
cord_internal::kMaxInline
|
||||
? cord_internal::InlineData(
|
||||
strings_internal::StringConstant<T>::value)
|
||||
: cord_internal::InlineData(cord_internal::AsTree{
|
||||
&cord_internal::ConstInitExternalStorage<
|
||||
strings_internal::StringConstant<T>>::value,
|
||||
{},
|
||||
cord_internal::kTreeFlag})) {}
|
||||
|
||||
inline Cord& Cord::operator=(const Cord& x) {
|
||||
contents_ = x.contents_;
|
||||
return *this;
|
||||
|
||||
@@ -181,6 +181,8 @@ class CordTestPeer {
|
||||
const Cord& c, absl::FunctionRef<void(absl::string_view)> callback) {
|
||||
c.ForEachChunk(callback);
|
||||
}
|
||||
|
||||
static bool IsTree(const Cord& c) { return c.contents_.is_tree(); }
|
||||
};
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
@@ -1627,3 +1629,83 @@ TEST(CordDeathTest, Hardening) {
|
||||
EXPECT_DEATH_IF_SUPPORTED(static_cast<void>(cord.chunk_end()->empty()), "");
|
||||
EXPECT_DEATH_IF_SUPPORTED(++cord.chunk_end(), "");
|
||||
}
|
||||
|
||||
class AfterExitCordTester {
|
||||
public:
|
||||
bool Set(absl::Cord* cord, absl::string_view expected) {
|
||||
cord_ = cord;
|
||||
expected_ = expected;
|
||||
return true;
|
||||
}
|
||||
|
||||
~AfterExitCordTester() {
|
||||
EXPECT_EQ(*cord_, expected_);
|
||||
}
|
||||
private:
|
||||
absl::Cord* cord_;
|
||||
absl::string_view expected_;
|
||||
};
|
||||
|
||||
template <typename Str>
|
||||
void TestConstinitConstructor(Str) {
|
||||
const auto expected = Str::value;
|
||||
// Defined before `cord` to be destroyed after it.
|
||||
static AfterExitCordTester exit_tester; // NOLINT
|
||||
ABSL_CONST_INIT static absl::Cord cord(Str{}); // NOLINT
|
||||
static bool init_exit_tester = exit_tester.Set(&cord, expected);
|
||||
(void)init_exit_tester;
|
||||
|
||||
EXPECT_EQ(cord, expected);
|
||||
// Copy the object and test the copy, and the original.
|
||||
{
|
||||
absl::Cord copy = cord;
|
||||
EXPECT_EQ(copy, expected);
|
||||
}
|
||||
// The original still works
|
||||
EXPECT_EQ(cord, expected);
|
||||
|
||||
// Try making adding more structure to the tree.
|
||||
{
|
||||
absl::Cord copy = cord;
|
||||
std::string expected_copy(expected);
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
copy.Append(cord);
|
||||
absl::StrAppend(&expected_copy, expected);
|
||||
EXPECT_EQ(copy, expected_copy);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we are using the right branch during constant evaluation.
|
||||
EXPECT_EQ(absl::CordTestPeer::IsTree(cord), cord.size() >= 16);
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// Make a few more Cords from the same global rep.
|
||||
// This tests what happens when the refcount for it gets below 1.
|
||||
EXPECT_EQ(expected, absl::Cord(Str{}));
|
||||
}
|
||||
}
|
||||
|
||||
constexpr int SimpleStrlen(const char* p) {
|
||||
return *p ? 1 + SimpleStrlen(p + 1) : 0;
|
||||
}
|
||||
|
||||
struct ShortView {
|
||||
constexpr absl::string_view operator()() const {
|
||||
return absl::string_view("SSO string", SimpleStrlen("SSO string"));
|
||||
}
|
||||
};
|
||||
|
||||
struct LongView {
|
||||
constexpr absl::string_view operator()() const {
|
||||
return absl::string_view("String that does not fit SSO.",
|
||||
SimpleStrlen("String that does not fit SSO."));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST(Cord, ConstinitConstructor) {
|
||||
TestConstinitConstructor(
|
||||
absl::strings_internal::MakeStringConstant(ShortView{}));
|
||||
TestConstinitConstructor(
|
||||
absl::strings_internal::MakeStringConstant(LongView{}));
|
||||
}
|
||||
|
||||
@@ -33,14 +33,17 @@ namespace cord_internal {
|
||||
// Wraps std::atomic for reference counting.
|
||||
class Refcount {
|
||||
public:
|
||||
Refcount() : count_{1} {}
|
||||
~Refcount() {}
|
||||
constexpr Refcount() : count_{kRefIncrement} {}
|
||||
struct Immortal {};
|
||||
explicit constexpr Refcount(Immortal) : count_(kImmortalTag) {}
|
||||
|
||||
// Increments the reference count by 1. Imposes no memory ordering.
|
||||
inline void Increment() { count_.fetch_add(1, std::memory_order_relaxed); }
|
||||
// Increments the reference count. Imposes no memory ordering.
|
||||
inline void Increment() {
|
||||
count_.fetch_add(kRefIncrement, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
// Asserts that the current refcount is greater than 0. If the refcount is
|
||||
// greater than 1, decrements the reference count by 1.
|
||||
// greater than 1, decrements the reference count.
|
||||
//
|
||||
// Returns false if there are no references outstanding; true otherwise.
|
||||
// Inserts barriers to ensure that state written before this method returns
|
||||
@@ -48,19 +51,24 @@ class Refcount {
|
||||
// false.
|
||||
inline bool Decrement() {
|
||||
int32_t refcount = count_.load(std::memory_order_acquire);
|
||||
assert(refcount > 0);
|
||||
return refcount != 1 && count_.fetch_sub(1, std::memory_order_acq_rel) != 1;
|
||||
assert(refcount > 0 || refcount & kImmortalTag);
|
||||
return refcount != kRefIncrement &&
|
||||
count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) !=
|
||||
kRefIncrement;
|
||||
}
|
||||
|
||||
// Same as Decrement but expect that refcount is greater than 1.
|
||||
inline bool DecrementExpectHighRefcount() {
|
||||
int32_t refcount = count_.fetch_sub(1, std::memory_order_acq_rel);
|
||||
assert(refcount > 0);
|
||||
return refcount != 1;
|
||||
int32_t refcount =
|
||||
count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel);
|
||||
assert(refcount > 0 || refcount & kImmortalTag);
|
||||
return refcount != kRefIncrement;
|
||||
}
|
||||
|
||||
// Returns the current reference count using acquire semantics.
|
||||
inline int32_t Get() const { return count_.load(std::memory_order_acquire); }
|
||||
inline int32_t Get() const {
|
||||
return count_.load(std::memory_order_acquire) >> kImmortalShift;
|
||||
}
|
||||
|
||||
// Returns whether the atomic integer is 1.
|
||||
// If the reference count is used in the conventional way, a
|
||||
@@ -70,9 +78,27 @@ class Refcount {
|
||||
// performs the memory barrier needed for the owning thread
|
||||
// to act on the object, knowing that it has exclusive access to the
|
||||
// object.
|
||||
inline bool IsOne() { return count_.load(std::memory_order_acquire) == 1; }
|
||||
inline bool IsOne() {
|
||||
return count_.load(std::memory_order_acquire) == kRefIncrement;
|
||||
}
|
||||
|
||||
bool IsImmortal() const {
|
||||
return (count_.load(std::memory_order_relaxed) & kImmortalTag) != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
// We reserve the bottom bit to tag a reference count as immortal.
|
||||
// By making it `1` we ensure that we never reach `0` when adding/subtracting
|
||||
// `2`, thus it never looks as if it should be destroyed.
|
||||
// These are used for the StringConstant constructor where we do not increase
|
||||
// the refcount at construction time (due to constinit requirements) but we
|
||||
// will still decrease it at destruction time to avoid branching on Unref.
|
||||
enum {
|
||||
kImmortalShift = 1,
|
||||
kRefIncrement = 1 << kImmortalShift,
|
||||
kImmortalTag = kRefIncrement - 1
|
||||
};
|
||||
|
||||
std::atomic<int32_t> count_;
|
||||
};
|
||||
|
||||
@@ -97,6 +123,10 @@ enum CordRepKind {
|
||||
};
|
||||
|
||||
struct CordRep {
|
||||
CordRep() = default;
|
||||
constexpr CordRep(Refcount::Immortal immortal, size_t l)
|
||||
: length(l), refcount(immortal), tag(EXTERNAL), data{} {}
|
||||
|
||||
// The following three fields have to be less than 32 bytes since
|
||||
// that is the smallest supported flat node size.
|
||||
size_t length;
|
||||
@@ -135,6 +165,12 @@ using ExternalReleaserInvoker = void (*)(CordRepExternal*);
|
||||
// External CordReps are allocated together with a type erased releaser. The
|
||||
// releaser is stored in the memory directly following the CordRepExternal.
|
||||
struct CordRepExternal : public CordRep {
|
||||
CordRepExternal() = default;
|
||||
explicit constexpr CordRepExternal(absl::string_view str)
|
||||
: CordRep(Refcount::Immortal{}, str.size()),
|
||||
base(str.data()),
|
||||
releaser_invoker(nullptr) {}
|
||||
|
||||
const char* base;
|
||||
// Pointer to function that knows how to call and destroy the releaser.
|
||||
ExternalReleaserInvoker releaser_invoker;
|
||||
@@ -178,6 +214,14 @@ struct CordRepExternalImpl
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Str>
|
||||
struct ConstInitExternalStorage {
|
||||
ABSL_CONST_INIT static CordRepExternal value;
|
||||
};
|
||||
|
||||
template <typename Str>
|
||||
CordRepExternal ConstInitExternalStorage<Str>::value(Str::value);
|
||||
|
||||
enum {
|
||||
kMaxInline = 15,
|
||||
// Tag byte & kMaxInline means we are storing a pointer.
|
||||
@@ -195,9 +239,23 @@ struct AsTree {
|
||||
char padding[kMaxInline + 1 - sizeof(absl::cord_internal::CordRep*) - 1];
|
||||
char tagged_size;
|
||||
};
|
||||
|
||||
constexpr char GetOrNull(absl::string_view data, size_t pos) {
|
||||
return pos < data.size() ? data[pos] : '\0';
|
||||
}
|
||||
|
||||
union InlineData {
|
||||
constexpr InlineData() : as_chars{} {}
|
||||
explicit constexpr InlineData(AsTree tree) : as_tree(tree) {}
|
||||
explicit constexpr InlineData(absl::string_view chars)
|
||||
: as_chars{GetOrNull(chars, 0), GetOrNull(chars, 1),
|
||||
GetOrNull(chars, 2), GetOrNull(chars, 3),
|
||||
GetOrNull(chars, 4), GetOrNull(chars, 5),
|
||||
GetOrNull(chars, 6), GetOrNull(chars, 7),
|
||||
GetOrNull(chars, 8), GetOrNull(chars, 9),
|
||||
GetOrNull(chars, 10), GetOrNull(chars, 11),
|
||||
GetOrNull(chars, 12), GetOrNull(chars, 13),
|
||||
GetOrNull(chars, 14), static_cast<char>(chars.size())} {}
|
||||
|
||||
AsTree as_tree;
|
||||
char as_chars[kMaxInline + 1];
|
||||
|
||||
70
absl/strings/internal/string_constant.h
Normal file
70
absl/strings/internal/string_constant.h
Normal file
@@ -0,0 +1,70 @@
|
||||
// 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.
|
||||
|
||||
#ifndef ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
|
||||
#define ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
|
||||
|
||||
#include "absl/meta/type_traits.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace strings_internal {
|
||||
|
||||
// StringConstant<T> represents a compile time string constant.
|
||||
// It can be accessed via its `absl::string_view value` static member.
|
||||
// It is guaranteed that the `string_view` returned has constant `.data()`,
|
||||
// constant `.size()` and constant `value[i]` for all `0 <= i < .size()`
|
||||
//
|
||||
// The `T` is an opaque type. It is guaranteed that different string constants
|
||||
// will have different values of `T`. This allows users to associate the string
|
||||
// constant with other static state at compile time.
|
||||
//
|
||||
// Instances should be made using the `MakeStringConstant()` factory function
|
||||
// below.
|
||||
template <typename T>
|
||||
struct StringConstant {
|
||||
private:
|
||||
// Returns true if `view` points to constant data.
|
||||
// Otherwise, it can't be constant evaluated.
|
||||
static constexpr bool ValidateConstant(absl::string_view view) {
|
||||
return view.empty() || 2 * view[0] != 1;
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr absl::string_view value = T{}();
|
||||
constexpr absl::string_view operator()() const { return value; }
|
||||
|
||||
static_assert(ValidateConstant(value),
|
||||
"The input string_view must point to constant data.");
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr absl::string_view StringConstant<T>::value; // NOLINT
|
||||
|
||||
// Factory function for `StringConstant` instances.
|
||||
// It supports callables that have a constexpr default constructor and a
|
||||
// constexpr operator().
|
||||
// It must return an `absl::string_view` or `const char*` pointing to constant
|
||||
// data. This is validated at compile time.
|
||||
template <typename T>
|
||||
constexpr StringConstant<T> MakeStringConstant(T) {
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace strings_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
|
||||
60
absl/strings/internal/string_constant_test.cc
Normal file
60
absl/strings/internal/string_constant_test.cc
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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/strings/internal/string_constant.h"
|
||||
|
||||
#include "absl/meta/type_traits.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using absl::strings_internal::MakeStringConstant;
|
||||
|
||||
struct Callable {
|
||||
constexpr absl::string_view operator()() const {
|
||||
return absl::string_view("Callable", 8);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(StringConstant, Traits) {
|
||||
constexpr auto str = MakeStringConstant(Callable{});
|
||||
using T = decltype(str);
|
||||
|
||||
EXPECT_TRUE(std::is_empty<T>::value);
|
||||
EXPECT_TRUE(std::is_trivial<T>::value);
|
||||
EXPECT_TRUE(absl::is_trivially_default_constructible<T>::value);
|
||||
EXPECT_TRUE(absl::is_trivially_copy_constructible<T>::value);
|
||||
EXPECT_TRUE(absl::is_trivially_move_constructible<T>::value);
|
||||
EXPECT_TRUE(absl::is_trivially_destructible<T>::value);
|
||||
}
|
||||
|
||||
TEST(StringConstant, MakeFromCallable) {
|
||||
constexpr auto str = MakeStringConstant(Callable{});
|
||||
using T = decltype(str);
|
||||
EXPECT_EQ(Callable{}(), T::value);
|
||||
EXPECT_EQ(Callable{}(), str());
|
||||
}
|
||||
|
||||
TEST(StringConstant, MakeFromStringConstant) {
|
||||
// We want to make sure the StringConstant itself is a valid input to the
|
||||
// factory function.
|
||||
constexpr auto str = MakeStringConstant(Callable{});
|
||||
constexpr auto str2 = MakeStringConstant(str);
|
||||
using T = decltype(str2);
|
||||
EXPECT_EQ(Callable{}(), T::value);
|
||||
EXPECT_EQ(Callable{}(), str2());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -736,9 +736,18 @@ struct LookupTables {
|
||||
X / 35, X / 36, \
|
||||
}
|
||||
|
||||
// This kVmaxOverBase is generated with
|
||||
// for (int base = 2; base < 37; ++base) {
|
||||
// absl::uint128 max = std::numeric_limits<absl::uint128>::max();
|
||||
// auto result = max / base;
|
||||
// std::cout << " MakeUint128(" << absl::Uint128High64(result) << "u, "
|
||||
// << absl::Uint128Low64(result) << "u),\n";
|
||||
// }
|
||||
// See https://godbolt.org/z/aneYsb
|
||||
//
|
||||
// uint128& operator/=(uint128) is not constexpr, so hardcode the resulting
|
||||
// array to avoid a static initializer.
|
||||
template <>
|
||||
template<>
|
||||
const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
|
||||
0,
|
||||
0,
|
||||
@@ -779,6 +788,111 @@ const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
|
||||
MakeUint128(512409557603043100u, 8198552921648689607u),
|
||||
};
|
||||
|
||||
// This kVmaxOverBase generated with
|
||||
// for (int base = 2; base < 37; ++base) {
|
||||
// absl::int128 max = std::numeric_limits<absl::int128>::max();
|
||||
// auto result = max / base;
|
||||
// std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", "
|
||||
// << absl::Int128Low64(result) << "u),\n";
|
||||
// }
|
||||
// See https://godbolt.org/z/7djYWz
|
||||
//
|
||||
// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
|
||||
// to avoid a static initializer.
|
||||
template<>
|
||||
const int128 LookupTables<int128>::kVmaxOverBase[] = {
|
||||
0,
|
||||
0,
|
||||
MakeInt128(4611686018427387903, 18446744073709551615u),
|
||||
MakeInt128(3074457345618258602, 12297829382473034410u),
|
||||
MakeInt128(2305843009213693951, 18446744073709551615u),
|
||||
MakeInt128(1844674407370955161, 11068046444225730969u),
|
||||
MakeInt128(1537228672809129301, 6148914691236517205u),
|
||||
MakeInt128(1317624576693539401, 2635249153387078802u),
|
||||
MakeInt128(1152921504606846975, 18446744073709551615u),
|
||||
MakeInt128(1024819115206086200, 16397105843297379214u),
|
||||
MakeInt128(922337203685477580, 14757395258967641292u),
|
||||
MakeInt128(838488366986797800, 13415813871788764811u),
|
||||
MakeInt128(768614336404564650, 12297829382473034410u),
|
||||
MakeInt128(709490156681136600, 11351842506898185609u),
|
||||
MakeInt128(658812288346769700, 10540996613548315209u),
|
||||
MakeInt128(614891469123651720, 9838263505978427528u),
|
||||
MakeInt128(576460752303423487, 18446744073709551615u),
|
||||
MakeInt128(542551296285575047, 9765923333140350855u),
|
||||
MakeInt128(512409557603043100, 8198552921648689607u),
|
||||
MakeInt128(485440633518672410, 17475862806672206794u),
|
||||
MakeInt128(461168601842738790, 7378697629483820646u),
|
||||
MakeInt128(439208192231179800, 7027331075698876806u),
|
||||
MakeInt128(419244183493398900, 6707906935894382405u),
|
||||
MakeInt128(401016175515425035, 2406097053092550210u),
|
||||
MakeInt128(384307168202282325, 6148914691236517205u),
|
||||
MakeInt128(368934881474191032, 5902958103587056517u),
|
||||
MakeInt128(354745078340568300, 5675921253449092804u),
|
||||
MakeInt128(341606371735362066, 17763531330238827482u),
|
||||
MakeInt128(329406144173384850, 5270498306774157604u),
|
||||
MakeInt128(318047311615681924, 7633135478776366185u),
|
||||
MakeInt128(307445734561825860, 4919131752989213764u),
|
||||
MakeInt128(297528130221121800, 4760450083537948804u),
|
||||
MakeInt128(288230376151711743, 18446744073709551615u),
|
||||
MakeInt128(279496122328932600, 4471937957262921603u),
|
||||
MakeInt128(271275648142787523, 14106333703424951235u),
|
||||
MakeInt128(263524915338707880, 4216398645419326083u),
|
||||
MakeInt128(256204778801521550, 4099276460824344803u),
|
||||
};
|
||||
|
||||
// This kVminOverBase generated with
|
||||
// for (int base = 2; base < 37; ++base) {
|
||||
// absl::int128 min = std::numeric_limits<absl::int128>::min();
|
||||
// auto result = min / base;
|
||||
// std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", "
|
||||
// << absl::Int128Low64(result) << "u),\n";
|
||||
// }
|
||||
//
|
||||
// See https://godbolt.org/z/7djYWz
|
||||
//
|
||||
// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
|
||||
// to avoid a static initializer.
|
||||
template<>
|
||||
const int128 LookupTables<int128>::kVminOverBase[] = {
|
||||
0,
|
||||
0,
|
||||
MakeInt128(-4611686018427387904, 0u),
|
||||
MakeInt128(-3074457345618258603, 6148914691236517206u),
|
||||
MakeInt128(-2305843009213693952, 0u),
|
||||
MakeInt128(-1844674407370955162, 7378697629483820647u),
|
||||
MakeInt128(-1537228672809129302, 12297829382473034411u),
|
||||
MakeInt128(-1317624576693539402, 15811494920322472814u),
|
||||
MakeInt128(-1152921504606846976, 0u),
|
||||
MakeInt128(-1024819115206086201, 2049638230412172402u),
|
||||
MakeInt128(-922337203685477581, 3689348814741910324u),
|
||||
MakeInt128(-838488366986797801, 5030930201920786805u),
|
||||
MakeInt128(-768614336404564651, 6148914691236517206u),
|
||||
MakeInt128(-709490156681136601, 7094901566811366007u),
|
||||
MakeInt128(-658812288346769701, 7905747460161236407u),
|
||||
MakeInt128(-614891469123651721, 8608480567731124088u),
|
||||
MakeInt128(-576460752303423488, 0u),
|
||||
MakeInt128(-542551296285575048, 8680820740569200761u),
|
||||
MakeInt128(-512409557603043101, 10248191152060862009u),
|
||||
MakeInt128(-485440633518672411, 970881267037344822u),
|
||||
MakeInt128(-461168601842738791, 11068046444225730970u),
|
||||
MakeInt128(-439208192231179801, 11419412998010674810u),
|
||||
MakeInt128(-419244183493398901, 11738837137815169211u),
|
||||
MakeInt128(-401016175515425036, 16040647020617001406u),
|
||||
MakeInt128(-384307168202282326, 12297829382473034411u),
|
||||
MakeInt128(-368934881474191033, 12543785970122495099u),
|
||||
MakeInt128(-354745078340568301, 12770822820260458812u),
|
||||
MakeInt128(-341606371735362067, 683212743470724134u),
|
||||
MakeInt128(-329406144173384851, 13176245766935394012u),
|
||||
MakeInt128(-318047311615681925, 10813608594933185431u),
|
||||
MakeInt128(-307445734561825861, 13527612320720337852u),
|
||||
MakeInt128(-297528130221121801, 13686293990171602812u),
|
||||
MakeInt128(-288230376151711744, 0u),
|
||||
MakeInt128(-279496122328932601, 13974806116446630013u),
|
||||
MakeInt128(-271275648142787524, 4340410370284600381u),
|
||||
MakeInt128(-263524915338707881, 14230345428290225533u),
|
||||
MakeInt128(-256204778801521551, 14347467612885206813u),
|
||||
};
|
||||
|
||||
template <typename IntType>
|
||||
const IntType LookupTables<IntType>::kVmaxOverBase[] =
|
||||
X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max());
|
||||
@@ -948,6 +1062,10 @@ bool safe_strto64_base(absl::string_view text, int64_t* value, int base) {
|
||||
return safe_int_internal<int64_t>(text, value, base);
|
||||
}
|
||||
|
||||
bool safe_strto128_base(absl::string_view text, int128* value, int base) {
|
||||
return safe_int_internal<absl::int128>(text, value, base);
|
||||
}
|
||||
|
||||
bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base) {
|
||||
return safe_uint_internal<uint32_t>(text, value, base);
|
||||
}
|
||||
|
||||
@@ -127,6 +127,8 @@ inline void PutTwoDigits(size_t i, char* buf) {
|
||||
// safe_strto?() functions for implementing SimpleAtoi()
|
||||
bool safe_strto32_base(absl::string_view text, int32_t* value, int base);
|
||||
bool safe_strto64_base(absl::string_view text, int64_t* value, int base);
|
||||
bool safe_strto128_base(absl::string_view text, absl::int128* value,
|
||||
int base);
|
||||
bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base);
|
||||
bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base);
|
||||
bool safe_strtou128_base(absl::string_view text, absl::uint128* value,
|
||||
@@ -255,6 +257,11 @@ ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out) {
|
||||
return numbers_internal::safe_strtoi_base(str, out, 10);
|
||||
}
|
||||
|
||||
ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
|
||||
absl::int128* out) {
|
||||
return numbers_internal::safe_strto128_base(str, out, 10);
|
||||
}
|
||||
|
||||
ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
|
||||
absl::uint128* out) {
|
||||
return numbers_internal::safe_strtou128_base(str, out, 10);
|
||||
|
||||
@@ -251,7 +251,7 @@ TEST(Numbers, TestFastPrints) {
|
||||
template <typename int_type, typename in_val_type>
|
||||
void VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) {
|
||||
std::string s;
|
||||
// uint128 can be streamed but not StrCat'd
|
||||
// (u)int128 can be streamed but not StrCat'd.
|
||||
absl::strings_internal::OStringStream(&s) << in_value;
|
||||
int_type x = static_cast<int_type>(~exp_value);
|
||||
EXPECT_TRUE(SimpleAtoi(s, &x))
|
||||
@@ -264,7 +264,9 @@ void VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) {
|
||||
|
||||
template <typename int_type, typename in_val_type>
|
||||
void VerifySimpleAtoiBad(in_val_type in_value) {
|
||||
std::string s = absl::StrCat(in_value);
|
||||
std::string s;
|
||||
// (u)int128 can be streamed but not StrCat'd.
|
||||
absl::strings_internal::OStringStream(&s) << in_value;
|
||||
int_type x;
|
||||
EXPECT_FALSE(SimpleAtoi(s, &x));
|
||||
EXPECT_FALSE(SimpleAtoi(s.c_str(), &x));
|
||||
@@ -347,6 +349,31 @@ TEST(NumbersTest, Atoi) {
|
||||
std::numeric_limits<absl::uint128>::max(),
|
||||
std::numeric_limits<absl::uint128>::max());
|
||||
|
||||
// SimpleAtoi(absl::string_view, absl::int128)
|
||||
VerifySimpleAtoiGood<absl::int128>(0, 0);
|
||||
VerifySimpleAtoiGood<absl::int128>(42, 42);
|
||||
VerifySimpleAtoiGood<absl::int128>(-42, -42);
|
||||
|
||||
VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::min(),
|
||||
std::numeric_limits<int32_t>::min());
|
||||
VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::max(),
|
||||
std::numeric_limits<int32_t>::max());
|
||||
VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint32_t>::max(),
|
||||
std::numeric_limits<uint32_t>::max());
|
||||
VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::min(),
|
||||
std::numeric_limits<int64_t>::min());
|
||||
VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::max(),
|
||||
std::numeric_limits<int64_t>::max());
|
||||
VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint64_t>::max(),
|
||||
std::numeric_limits<uint64_t>::max());
|
||||
VerifySimpleAtoiGood<absl::int128>(
|
||||
std::numeric_limits<absl::int128>::min(),
|
||||
std::numeric_limits<absl::int128>::min());
|
||||
VerifySimpleAtoiGood<absl::int128>(
|
||||
std::numeric_limits<absl::int128>::max(),
|
||||
std::numeric_limits<absl::int128>::max());
|
||||
VerifySimpleAtoiBad<absl::int128>(std::numeric_limits<absl::uint128>::max());
|
||||
|
||||
// Some other types
|
||||
VerifySimpleAtoiGood<int>(-42, -42);
|
||||
VerifySimpleAtoiGood<int32_t>(-42, -42);
|
||||
@@ -725,6 +752,51 @@ TEST(stringtest, safe_strtou128_random) {
|
||||
EXPECT_FALSE(parse_func(s, &parsed_value, base));
|
||||
}
|
||||
}
|
||||
TEST(stringtest, safe_strto128_random) {
|
||||
// random number generators don't work for int128, and
|
||||
// int128 can be streamed but not StrCat'd, so this code must be custom
|
||||
// implemented for int128, but is generally the same as what's above.
|
||||
// test_random_integer_parse_base<absl::int128>(
|
||||
// &absl::numbers_internal::safe_strto128_base);
|
||||
using RandomEngine = std::minstd_rand0;
|
||||
using IntType = absl::int128;
|
||||
constexpr auto parse_func = &absl::numbers_internal::safe_strto128_base;
|
||||
|
||||
std::random_device rd;
|
||||
RandomEngine rng(rd());
|
||||
std::uniform_int_distribution<int64_t> random_int64(
|
||||
std::numeric_limits<int64_t>::min());
|
||||
std::uniform_int_distribution<uint64_t> random_uint64(
|
||||
std::numeric_limits<uint64_t>::min());
|
||||
std::uniform_int_distribution<int> random_base(2, 35);
|
||||
|
||||
for (size_t i = 0; i < kNumRandomTests; ++i) {
|
||||
int64_t high = random_int64(rng);
|
||||
uint64_t low = random_uint64(rng);
|
||||
IntType value = absl::MakeInt128(high, low);
|
||||
|
||||
int base = random_base(rng);
|
||||
std::string str_value;
|
||||
EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));
|
||||
IntType parsed_value;
|
||||
|
||||
// Test successful parse
|
||||
EXPECT_TRUE(parse_func(str_value, &parsed_value, base));
|
||||
EXPECT_EQ(parsed_value, value);
|
||||
|
||||
// Test overflow
|
||||
std::string s;
|
||||
absl::strings_internal::OStringStream(&s)
|
||||
<< std::numeric_limits<IntType>::max() << value;
|
||||
EXPECT_FALSE(parse_func(s, &parsed_value, base));
|
||||
|
||||
// Test underflow
|
||||
s.clear();
|
||||
absl::strings_internal::OStringStream(&s)
|
||||
<< std::numeric_limits<IntType>::min() << value;
|
||||
EXPECT_FALSE(parse_func(s, &parsed_value, base));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(stringtest, safe_strtou32_base) {
|
||||
for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
|
||||
|
||||
@@ -24,7 +24,7 @@ source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
|
||||
readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}
|
||||
|
||||
time docker run \
|
||||
--volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
|
||||
--mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
|
||||
--workdir=/abseil-cpp \
|
||||
--tmpfs=/buildfs:exec \
|
||||
--cap-add=SYS_PTRACE \
|
||||
|
||||
@@ -42,7 +42,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
|
||||
# USE_BAZEL_CACHE=1 only works on Kokoro.
|
||||
# Without access to the credentials this won't work.
|
||||
if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
|
||||
DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
|
||||
DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
|
||||
# Bazel doesn't track changes to tools outside of the workspace
|
||||
# (e.g. /usr/bin/gcc), so by appending the docker container to the
|
||||
# remote_http_cache url, we make changes to the container part of
|
||||
@@ -55,7 +55,7 @@ fi
|
||||
# external dependencies first.
|
||||
# https://docs.bazel.build/versions/master/guide.html#distdir
|
||||
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
|
||||
DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
|
||||
DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
|
||||
BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
|
||||
fi
|
||||
|
||||
@@ -64,7 +64,7 @@ for std in ${STD}; do
|
||||
for exceptions_mode in ${EXCEPTIONS_MODE}; do
|
||||
echo "--------------------------------------------------------------------"
|
||||
time docker run \
|
||||
--volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
|
||||
--mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
|
||||
--workdir=/abseil-cpp \
|
||||
--cap-add=SYS_PTRACE \
|
||||
--rm \
|
||||
|
||||
@@ -42,7 +42,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
|
||||
# USE_BAZEL_CACHE=1 only works on Kokoro.
|
||||
# Without access to the credentials this won't work.
|
||||
if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
|
||||
DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
|
||||
DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
|
||||
# Bazel doesn't track changes to tools outside of the workspace
|
||||
# (e.g. /usr/bin/gcc), so by appending the docker container to the
|
||||
# remote_http_cache url, we make changes to the container part of
|
||||
@@ -55,7 +55,7 @@ fi
|
||||
# external dependencies first.
|
||||
# https://docs.bazel.build/versions/master/guide.html#distdir
|
||||
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
|
||||
DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
|
||||
DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
|
||||
BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
|
||||
fi
|
||||
|
||||
@@ -64,7 +64,7 @@ for std in ${STD}; do
|
||||
for exceptions_mode in ${EXCEPTIONS_MODE}; do
|
||||
echo "--------------------------------------------------------------------"
|
||||
time docker run \
|
||||
--volume="${ABSEIL_ROOT}:/abseil-cpp-ro:ro" \
|
||||
--mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \
|
||||
--tmpfs=/abseil-cpp \
|
||||
--workdir=/abseil-cpp \
|
||||
--cap-add=SYS_PTRACE \
|
||||
|
||||
@@ -42,7 +42,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
|
||||
# USE_BAZEL_CACHE=1 only works on Kokoro.
|
||||
# Without access to the credentials this won't work.
|
||||
if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
|
||||
DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
|
||||
DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
|
||||
# Bazel doesn't track changes to tools outside of the workspace
|
||||
# (e.g. /usr/bin/gcc), so by appending the docker container to the
|
||||
# remote_http_cache url, we make changes to the container part of
|
||||
@@ -55,7 +55,7 @@ fi
|
||||
# external dependencies first.
|
||||
# https://docs.bazel.build/versions/master/guide.html#distdir
|
||||
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
|
||||
DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
|
||||
DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
|
||||
BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
|
||||
fi
|
||||
|
||||
@@ -64,7 +64,7 @@ for std in ${STD}; do
|
||||
for exceptions_mode in ${EXCEPTIONS_MODE}; do
|
||||
echo "--------------------------------------------------------------------"
|
||||
time docker run \
|
||||
--volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
|
||||
--mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
|
||||
--workdir=/abseil-cpp \
|
||||
--cap-add=SYS_PTRACE \
|
||||
--rm \
|
||||
|
||||
@@ -42,7 +42,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
|
||||
# USE_BAZEL_CACHE=1 only works on Kokoro.
|
||||
# Without access to the credentials this won't work.
|
||||
if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
|
||||
DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
|
||||
DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
|
||||
# Bazel doesn't track changes to tools outside of the workspace
|
||||
# (e.g. /usr/bin/gcc), so by appending the docker container to the
|
||||
# remote_http_cache url, we make changes to the container part of
|
||||
@@ -55,7 +55,7 @@ fi
|
||||
# external dependencies first.
|
||||
# https://docs.bazel.build/versions/master/guide.html#distdir
|
||||
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
|
||||
DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
|
||||
DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
|
||||
BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
|
||||
fi
|
||||
|
||||
@@ -64,7 +64,7 @@ for std in ${STD}; do
|
||||
for exceptions_mode in ${EXCEPTIONS_MODE}; do
|
||||
echo "--------------------------------------------------------------------"
|
||||
time docker run \
|
||||
--volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
|
||||
--mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
|
||||
--workdir=/abseil-cpp \
|
||||
--cap-add=SYS_PTRACE \
|
||||
--rm \
|
||||
|
||||
@@ -42,7 +42,7 @@ readonly DOCKER_CONTAINER=${LINUX_GCC_49_CONTAINER}
|
||||
# USE_BAZEL_CACHE=1 only works on Kokoro.
|
||||
# Without access to the credentials this won't work.
|
||||
if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
|
||||
DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
|
||||
DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
|
||||
# Bazel doesn't track changes to tools outside of the workspace
|
||||
# (e.g. /usr/bin/gcc), so by appending the docker container to the
|
||||
# remote_http_cache url, we make changes to the container part of
|
||||
@@ -55,7 +55,7 @@ fi
|
||||
# external dependencies first.
|
||||
# https://docs.bazel.build/versions/master/guide.html#distdir
|
||||
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
|
||||
DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
|
||||
DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
|
||||
BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
|
||||
fi
|
||||
|
||||
@@ -64,7 +64,7 @@ for std in ${STD}; do
|
||||
for exceptions_mode in ${EXCEPTIONS_MODE}; do
|
||||
echo "--------------------------------------------------------------------"
|
||||
time docker run \
|
||||
--volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
|
||||
--mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
|
||||
--workdir=/abseil-cpp \
|
||||
--cap-add=SYS_PTRACE \
|
||||
--rm \
|
||||
|
||||
@@ -42,7 +42,7 @@ readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}
|
||||
# USE_BAZEL_CACHE=1 only works on Kokoro.
|
||||
# Without access to the credentials this won't work.
|
||||
if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
|
||||
DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
|
||||
DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
|
||||
# Bazel doesn't track changes to tools outside of the workspace
|
||||
# (e.g. /usr/bin/gcc), so by appending the docker container to the
|
||||
# remote_http_cache url, we make changes to the container part of
|
||||
@@ -55,7 +55,7 @@ fi
|
||||
# external dependencies first.
|
||||
# https://docs.bazel.build/versions/master/guide.html#distdir
|
||||
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
|
||||
DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
|
||||
DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
|
||||
BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
|
||||
fi
|
||||
|
||||
@@ -64,7 +64,7 @@ for std in ${STD}; do
|
||||
for exceptions_mode in ${EXCEPTIONS_MODE}; do
|
||||
echo "--------------------------------------------------------------------"
|
||||
time docker run \
|
||||
--volume="${ABSEIL_ROOT}:/abseil-cpp-ro:ro" \
|
||||
--mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \
|
||||
--tmpfs=/abseil-cpp \
|
||||
--workdir=/abseil-cpp \
|
||||
--cap-add=SYS_PTRACE \
|
||||
|
||||
@@ -45,7 +45,7 @@ for std in ${ABSL_CMAKE_CXX_STANDARDS}; do
|
||||
for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do
|
||||
for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do
|
||||
time docker run \
|
||||
--volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
|
||||
--mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
|
||||
--workdir=/abseil-cpp \
|
||||
--tmpfs=/buildfs:exec \
|
||||
--cap-add=SYS_PTRACE \
|
||||
|
||||
@@ -45,7 +45,7 @@ for std in ${ABSL_CMAKE_CXX_STANDARDS}; do
|
||||
for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do
|
||||
for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do
|
||||
time docker run \
|
||||
--volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
|
||||
--mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
|
||||
--workdir=/abseil-cpp \
|
||||
--tmpfs=/buildfs:exec \
|
||||
--cap-add=SYS_PTRACE \
|
||||
|
||||
Reference in New Issue
Block a user