--
5e45aadfb89e366dedd1fcad5034a76c5c10ad76 by James Y Knight <jyknight@google.com>:
Correct the conditions for std::{optional,variant,any} availability on Apple platforms.
Before XCode 12.5, the availability declarations incorrectly excluded one release on which the features were in fact available. This was corrected in 7fb40e1569
Unfortunately, we cannot simply switch abseil to the corrected versions, as that will cause build failures when using the older XCode toolchain. So, we check the version, and choose the correct set of versions for the toolchain in use.
PiperOrigin-RevId: 407667302
--
376fa06cde048e536e9447336b27bebf598ed4ea by Greg Falcon <gfalcon@google.com>:
Cord implementation change: Add a new CordRepCrc node type.
This is an implementation detail that will allow storing expected CRCs alongside cord data. This node is intended only to live at the top of Cord trees.
PiperOrigin-RevId: 407587140
GitOrigin-RevId: 5e45aadfb89e366dedd1fcad5034a76c5c10ad76
Change-Id: Iea3ca001c0cbb4deec8286b5581b30dc172a9918
pull/1057/head
parent
d6c75d9dd8
commit
c86347d4ce
11 changed files with 368 additions and 26 deletions
@ -0,0 +1,54 @@ |
|||||||
|
// Copyright 2021 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/cord_rep_crc.h" |
||||||
|
|
||||||
|
#include <cassert> |
||||||
|
#include <cstdint> |
||||||
|
|
||||||
|
#include "absl/base/config.h" |
||||||
|
#include "absl/strings/internal/cord_internal.h" |
||||||
|
|
||||||
|
namespace absl { |
||||||
|
ABSL_NAMESPACE_BEGIN |
||||||
|
namespace cord_internal { |
||||||
|
|
||||||
|
CordRepCrc* CordRepCrc::New(CordRep* child, uint32_t crc) { |
||||||
|
assert(child != nullptr); |
||||||
|
if (child->IsCrc()) { |
||||||
|
if (child->refcount.IsOne()) { |
||||||
|
child->crc()->crc = crc; |
||||||
|
return child->crc(); |
||||||
|
} |
||||||
|
CordRep* old = child; |
||||||
|
child = old->crc()->child; |
||||||
|
CordRep::Ref(child); |
||||||
|
CordRep::Unref(old); |
||||||
|
} |
||||||
|
auto* new_cordrep = new CordRepCrc; |
||||||
|
new_cordrep->length = child->length; |
||||||
|
new_cordrep->tag = cord_internal::CRC; |
||||||
|
new_cordrep->child = child; |
||||||
|
new_cordrep->crc = crc; |
||||||
|
return new_cordrep; |
||||||
|
} |
||||||
|
|
||||||
|
void CordRepCrc::Destroy(CordRepCrc* node) { |
||||||
|
CordRep::Unref(node->child); |
||||||
|
delete node; |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace cord_internal
|
||||||
|
ABSL_NAMESPACE_END |
||||||
|
} // namespace absl
|
@ -0,0 +1,93 @@ |
|||||||
|
// Copyright 2021 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_CORD_REP_CRC_H_ |
||||||
|
#define ABSL_STRINGS_INTERNAL_CORD_REP_CRC_H_ |
||||||
|
|
||||||
|
#include <cassert> |
||||||
|
#include <cstdint> |
||||||
|
|
||||||
|
#include "absl/base/config.h" |
||||||
|
#include "absl/base/optimization.h" |
||||||
|
#include "absl/strings/internal/cord_internal.h" |
||||||
|
|
||||||
|
namespace absl { |
||||||
|
ABSL_NAMESPACE_BEGIN |
||||||
|
namespace cord_internal { |
||||||
|
|
||||||
|
// CordRepCrc is a CordRep node intended only to appear at the top level of a
|
||||||
|
// cord tree. It associates an "expected CRC" with the contained data, to allow
|
||||||
|
// for easy passage of checksum data in Cord data flows.
|
||||||
|
//
|
||||||
|
// From Cord's perspective, the crc value has no semantics; any validation of
|
||||||
|
// the contained checksum is the user's responsibility.
|
||||||
|
struct CordRepCrc : public CordRep { |
||||||
|
CordRep* child; |
||||||
|
uint32_t crc; |
||||||
|
|
||||||
|
// Consumes `child` and returns a CordRepCrc prefixed tree containing `child`.
|
||||||
|
// If the specified `child` is itself a CordRepCrc node, then this method
|
||||||
|
// either replaces the existing node, or directly updates the crc value in it
|
||||||
|
// depending on the node being shared or not, i.e.: refcount.IsOne().
|
||||||
|
// `child` must not be null. Never returns null.
|
||||||
|
static CordRepCrc* New(CordRep* child, uint32_t crc); |
||||||
|
|
||||||
|
// Destroys (deletes) the provided node. `node` must not be null.
|
||||||
|
static void Destroy(CordRepCrc* node); |
||||||
|
}; |
||||||
|
|
||||||
|
// Consumes `rep` and returns a CordRep* with any outer CordRepCrc wrapper
|
||||||
|
// removed. This is usually a no-op (returning `rep`), but this will remove and
|
||||||
|
// unref an outer CordRepCrc node.
|
||||||
|
inline CordRep* RemoveCrcNode(CordRep* rep) { |
||||||
|
assert(rep != nullptr); |
||||||
|
if (ABSL_PREDICT_FALSE(rep->IsCrc())) { |
||||||
|
CordRep* child = rep->crc()->child; |
||||||
|
if (rep->refcount.IsOne()) { |
||||||
|
delete rep->crc(); |
||||||
|
} else { |
||||||
|
CordRep::Ref(child); |
||||||
|
CordRep::Unref(rep); |
||||||
|
} |
||||||
|
return child; |
||||||
|
} |
||||||
|
return rep; |
||||||
|
} |
||||||
|
|
||||||
|
// Returns `rep` if it is not a CordRepCrc node, or its child if it is.
|
||||||
|
// Does not consume or create a reference on `rep` or the returned value.
|
||||||
|
inline CordRep* SkipCrcNode(CordRep* rep) { |
||||||
|
assert(rep != nullptr); |
||||||
|
if (ABSL_PREDICT_FALSE(rep->IsCrc())) { |
||||||
|
return rep->crc()->child; |
||||||
|
} else { |
||||||
|
return rep; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline CordRepCrc* CordRep::crc() { |
||||||
|
assert(IsCrc()); |
||||||
|
return static_cast<CordRepCrc*>(this); |
||||||
|
} |
||||||
|
|
||||||
|
inline const CordRepCrc* CordRep::crc() const { |
||||||
|
assert(IsCrc()); |
||||||
|
return static_cast<const CordRepCrc*>(this); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace cord_internal
|
||||||
|
ABSL_NAMESPACE_END |
||||||
|
} // namespace absl
|
||||||
|
|
||||||
|
#endif // ABSL_STRINGS_INTERNAL_CORD_REP_CRC_H_
|
@ -0,0 +1,115 @@ |
|||||||
|
// Copyright 2021 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/cord_rep_crc.h" |
||||||
|
|
||||||
|
#include "gmock/gmock.h" |
||||||
|
#include "gtest/gtest.h" |
||||||
|
#include "absl/base/config.h" |
||||||
|
#include "absl/strings/internal/cord_internal.h" |
||||||
|
#include "absl/strings/internal/cord_rep_test_util.h" |
||||||
|
|
||||||
|
namespace absl { |
||||||
|
ABSL_NAMESPACE_BEGIN |
||||||
|
namespace cord_internal { |
||||||
|
namespace { |
||||||
|
|
||||||
|
using ::absl::cordrep_testing::MakeFlat; |
||||||
|
using ::testing::Eq; |
||||||
|
using ::testing::Ne; |
||||||
|
|
||||||
|
#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST |
||||||
|
|
||||||
|
TEST(CordRepCrc, NewWithNullPtr) { |
||||||
|
EXPECT_DEATH(CordRepCrc::New(nullptr, 0), ""); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(CordRepCrc, RemoveCrcWithNullptr) { |
||||||
|
EXPECT_DEATH(RemoveCrcNode(nullptr), ""); |
||||||
|
} |
||||||
|
|
||||||
|
#endif // !NDEBUG && GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
|
TEST(CordRepCrc, NewDestroy) { |
||||||
|
CordRep* rep = cordrep_testing::MakeFlat("Hello world"); |
||||||
|
CordRepCrc* crc = CordRepCrc::New(rep, 12345); |
||||||
|
EXPECT_TRUE(crc->refcount.IsOne()); |
||||||
|
EXPECT_THAT(crc->child, Eq(rep)); |
||||||
|
EXPECT_THAT(crc->crc, Eq(12345)); |
||||||
|
EXPECT_TRUE(rep->refcount.IsOne()); |
||||||
|
CordRepCrc::Destroy(crc); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(CordRepCrc, NewExistingCrcNotShared) { |
||||||
|
CordRep* rep = cordrep_testing::MakeFlat("Hello world"); |
||||||
|
CordRepCrc* crc = CordRepCrc::New(rep, 12345); |
||||||
|
CordRepCrc* new_crc = CordRepCrc::New(crc, 54321); |
||||||
|
EXPECT_THAT(new_crc, Eq(crc)); |
||||||
|
EXPECT_TRUE(new_crc->refcount.IsOne()); |
||||||
|
EXPECT_THAT(new_crc->child, Eq(rep)); |
||||||
|
EXPECT_THAT(new_crc->crc, Eq(54321)); |
||||||
|
EXPECT_TRUE(rep->refcount.IsOne()); |
||||||
|
CordRepCrc::Destroy(new_crc); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(CordRepCrc, NewExistingCrcShared) { |
||||||
|
CordRep* rep = cordrep_testing::MakeFlat("Hello world"); |
||||||
|
CordRepCrc* crc = CordRepCrc::New(rep, 12345); |
||||||
|
CordRep::Ref(crc); |
||||||
|
CordRepCrc* new_crc = CordRepCrc::New(crc, 54321); |
||||||
|
|
||||||
|
EXPECT_THAT(new_crc, Ne(crc)); |
||||||
|
EXPECT_TRUE(new_crc->refcount.IsOne()); |
||||||
|
EXPECT_TRUE(crc->refcount.IsOne()); |
||||||
|
EXPECT_FALSE(rep->refcount.IsOne()); |
||||||
|
EXPECT_THAT(crc->child, Eq(rep)); |
||||||
|
EXPECT_THAT(new_crc->child, Eq(rep)); |
||||||
|
EXPECT_THAT(crc->crc, Eq(12345)); |
||||||
|
EXPECT_THAT(new_crc->crc, Eq(54321)); |
||||||
|
|
||||||
|
CordRep::Unref(crc); |
||||||
|
CordRep::Unref(new_crc); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(CordRepCrc, RemoveCrcNotCrc) { |
||||||
|
CordRep* rep = cordrep_testing::MakeFlat("Hello world"); |
||||||
|
CordRep* nocrc = RemoveCrcNode(rep); |
||||||
|
EXPECT_THAT(nocrc, Eq(rep)); |
||||||
|
CordRep::Unref(nocrc); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(CordRepCrc, RemoveCrcNotShared) { |
||||||
|
CordRep* rep = cordrep_testing::MakeFlat("Hello world"); |
||||||
|
CordRepCrc* crc = CordRepCrc::New(rep, 12345); |
||||||
|
CordRep* nocrc = RemoveCrcNode(crc); |
||||||
|
EXPECT_THAT(nocrc, Eq(rep)); |
||||||
|
EXPECT_TRUE(rep->refcount.IsOne()); |
||||||
|
CordRep::Unref(nocrc); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(CordRepCrc, RemoveCrcShared) { |
||||||
|
CordRep* rep = cordrep_testing::MakeFlat("Hello world"); |
||||||
|
CordRepCrc* crc = CordRepCrc::New(rep, 12345); |
||||||
|
CordRep::Ref(crc); |
||||||
|
CordRep* nocrc = RemoveCrcNode(crc); |
||||||
|
EXPECT_THAT(nocrc, Eq(rep)); |
||||||
|
EXPECT_FALSE(rep->refcount.IsOne()); |
||||||
|
CordRep::Unref(nocrc); |
||||||
|
CordRep::Unref(crc); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace cord_internal
|
||||||
|
ABSL_NAMESPACE_END |
||||||
|
} // namespace absl
|
Loading…
Reference in new issue