diff options
author | Derek Mauro <dmauro@google.com> | 2022-10-28 11:21:06 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-10-28 11:22:03 -0700 |
commit | 1db72eb03e3685742c62abea9d13ddab2adcdf01 (patch) | |
tree | b2e9c4182d1ba593b924152d24a8e9e1e8569c9e /absl/strings/internal | |
parent | fd9fbe74511fb2a060a3b15a1572b52fe16a6a43 (diff) |
Support empty Cords with an expected checksum
PiperOrigin-RevId: 484578104
Change-Id: Ie4be3e4de27dc28d88395e16fd075fb10ab7a302
Diffstat (limited to 'absl/strings/internal')
-rw-r--r-- | absl/strings/internal/cord_rep_crc.cc | 9 | ||||
-rw-r--r-- | absl/strings/internal/cord_rep_crc.h | 2 | ||||
-rw-r--r-- | absl/strings/internal/cord_rep_crc_test.cc | 15 |
3 files changed, 17 insertions, 9 deletions
diff --git a/absl/strings/internal/cord_rep_crc.cc b/absl/strings/internal/cord_rep_crc.cc index ee140354..7d7273ef 100644 --- a/absl/strings/internal/cord_rep_crc.cc +++ b/absl/strings/internal/cord_rep_crc.cc @@ -25,8 +25,7 @@ ABSL_NAMESPACE_BEGIN namespace cord_internal { CordRepCrc* CordRepCrc::New(CordRep* child, uint32_t crc) { - assert(child != nullptr); - if (child->IsCrc()) { + if (child != nullptr && child->IsCrc()) { if (child->refcount.IsOne()) { child->crc()->crc = crc; return child->crc(); @@ -37,7 +36,7 @@ CordRepCrc* CordRepCrc::New(CordRep* child, uint32_t crc) { CordRep::Unref(old); } auto* new_cordrep = new CordRepCrc; - new_cordrep->length = child->length; + new_cordrep->length = child != nullptr ? child->length : 0; new_cordrep->tag = cord_internal::CRC; new_cordrep->child = child; new_cordrep->crc = crc; @@ -45,7 +44,9 @@ CordRepCrc* CordRepCrc::New(CordRep* child, uint32_t crc) { } void CordRepCrc::Destroy(CordRepCrc* node) { - CordRep::Unref(node->child); + if (node->child != nullptr) { + CordRep::Unref(node->child); + } delete node; } diff --git a/absl/strings/internal/cord_rep_crc.h b/absl/strings/internal/cord_rep_crc.h index 5294b0d1..455a1127 100644 --- a/absl/strings/internal/cord_rep_crc.h +++ b/absl/strings/internal/cord_rep_crc.h @@ -40,7 +40,7 @@ struct CordRepCrc : public CordRep { // 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. + // `child` must only be null if the Cord is empty. Never returns null. static CordRepCrc* New(CordRep* child, uint32_t crc); // Destroys (deletes) the provided node. `node` must not be null. diff --git a/absl/strings/internal/cord_rep_crc_test.cc b/absl/strings/internal/cord_rep_crc_test.cc index d73ea7b3..42a9110b 100644 --- a/absl/strings/internal/cord_rep_crc_test.cc +++ b/absl/strings/internal/cord_rep_crc_test.cc @@ -27,14 +27,11 @@ namespace { using ::absl::cordrep_testing::MakeFlat; using ::testing::Eq; +using ::testing::IsNull; 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), ""); } @@ -82,6 +79,16 @@ TEST(CordRepCrc, NewExistingCrcShared) { CordRep::Unref(new_crc); } +TEST(CordRepCrc, NewEmpty) { + CordRepCrc* crc = CordRepCrc::New(nullptr, 12345); + EXPECT_TRUE(crc->refcount.IsOne()); + EXPECT_THAT(crc->child, IsNull()); + EXPECT_THAT(crc->length, Eq(0u)); + EXPECT_THAT(crc->crc, Eq(12345u)); + EXPECT_TRUE(crc->refcount.IsOne()); + CordRepCrc::Destroy(crc); +} + TEST(CordRepCrc, RemoveCrcNotCrc) { CordRep* rep = cordrep_testing::MakeFlat("Hello world"); CordRep* nocrc = RemoveCrcNode(rep); |