Skip to content

Commit

Permalink
Add {PrefixLimiting,PositionShifting}BackwardWriter, backward writing
Browse files Browse the repository at this point in the history
counterparts of `{PrefixLimiting,PositionShifting}Writer`.

PiperOrigin-RevId: 720529427
  • Loading branch information
QrczakMK committed Jan 28, 2025
1 parent 8614313 commit 450ae5c
Show file tree
Hide file tree
Showing 7 changed files with 1,074 additions and 8 deletions.
52 changes: 52 additions & 0 deletions riegeli/bytes/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,32 @@ cc_library(
],
)

cc_library(
name = "prefix_limiting_backward_writer",
srcs = ["prefix_limiting_backward_writer.cc"],
hdrs = ["prefix_limiting_backward_writer.h"],
deps = [
":backward_writer",
"//riegeli/base:arithmetic",
"//riegeli/base:assert",
"//riegeli/base:buffering",
"//riegeli/base:byte_fill",
"//riegeli/base:chain",
"//riegeli/base:dependency",
"//riegeli/base:external_ref",
"//riegeli/base:initializer",
"//riegeli/base:moving_dependency",
"//riegeli/base:object",
"//riegeli/base:status",
"//riegeli/base:types",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:cord",
"@com_google_absl//absl/types:optional",
],
)

cc_library(
name = "position_shifting_reader",
srcs = ["position_shifting_reader.cc"],
Expand Down Expand Up @@ -610,6 +636,32 @@ cc_library(
],
)

cc_library(
name = "position_shifting_backward_writer",
srcs = ["position_shifting_backward_writer.cc"],
hdrs = ["position_shifting_backward_writer.h"],
deps = [
":backward_writer",
"//riegeli/base:arithmetic",
"//riegeli/base:assert",
"//riegeli/base:buffering",
"//riegeli/base:byte_fill",
"//riegeli/base:chain",
"//riegeli/base:dependency",
"//riegeli/base:external_ref",
"//riegeli/base:initializer",
"//riegeli/base:moving_dependency",
"//riegeli/base:object",
"//riegeli/base:status",
"//riegeli/base:types",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:cord",
"@com_google_absl//absl/types:optional",
],
)

cc_library(
name = "null_writer",
srcs = ["null_writer.cc"],
Expand Down
164 changes: 164 additions & 0 deletions riegeli/bytes/position_shifting_backward_writer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// Copyright 2021 Google LLC
//
// 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
//
// http://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 "riegeli/bytes/position_shifting_backward_writer.h"

#include <stddef.h>

#include <utility>

#include "absl/base/optimization.h"
#include "absl/status/status.h"
#include "absl/strings/cord.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "riegeli/base/arithmetic.h"
#include "riegeli/base/assert.h"
#include "riegeli/base/buffering.h"
#include "riegeli/base/byte_fill.h"
#include "riegeli/base/chain.h"
#include "riegeli/base/external_ref.h"
#include "riegeli/base/object.h"
#include "riegeli/base/status.h"
#include "riegeli/base/types.h"
#include "riegeli/bytes/backward_writer.h"

namespace riegeli {

void PositionShiftingBackwardWriterBase::Done() {
if (ABSL_PREDICT_TRUE(ok())) {
BackwardWriter& dest = *DestWriter();
SyncBuffer(dest);
}
BackwardWriter::Done();
}

bool PositionShiftingBackwardWriterBase::FailUnderflow(Position new_pos,
Object& object) {
return object.Fail(absl::InvalidArgumentError(
absl::StrCat("PositionShiftingBackwardWriter does not support "
"truncating before the base position: ",
new_pos, " < ", base_pos_)));
}

absl::Status PositionShiftingBackwardWriterBase::AnnotateStatusImpl(
absl::Status status) {
if (is_open()) {
BackwardWriter& dest = *DestWriter();
SyncBuffer(dest);
status = dest.AnnotateStatus(std::move(status));
MakeBuffer(dest);
}
// The status might have been annotated by `dest` with the original position.
// Clarify that the current position is the relative position instead of
// delegating to `BackwardWriter::AnnotateStatusImpl()`.
return AnnotateOverDest(std::move(status));
}

absl::Status PositionShiftingBackwardWriterBase::AnnotateOverDest(
absl::Status status) {
if (is_open() && base_pos_ > 0) {
return Annotate(status,
absl::StrCat("with relative position at byte ", pos()));
}
return status;
}

bool PositionShiftingBackwardWriterBase::PushSlow(size_t min_length,
size_t recommended_length) {
RIEGELI_ASSERT_LT(available(), min_length)
<< "Failed precondition of BackwardWriter::PushSlow(): "
"enough space available, use Push() instead";
if (ABSL_PREDICT_FALSE(!ok())) return false;
BackwardWriter& dest = *DestWriter();
SyncBuffer(dest);
const bool push_ok = dest.Push(min_length, recommended_length);
return MakeBuffer(dest, min_length) && push_ok;
}

bool PositionShiftingBackwardWriterBase::WriteSlow(absl::string_view src) {
RIEGELI_ASSERT_LT(available(), src.size())
<< "Failed precondition of BackwardWriter::WriteSlow(string_view): "
"enough space available, use Write(string_view) instead";
return WriteInternal(src);
}

bool PositionShiftingBackwardWriterBase::WriteSlow(ExternalRef src) {
RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), src.size())
<< "Failed precondition of BackwardWriter::WriteSlow(ExternalRef): "
"enough space available, use Write(ExternalRef) instead";
return WriteInternal(std::move(src));
}

bool PositionShiftingBackwardWriterBase::WriteSlow(const Chain& src) {
RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), src.size())
<< "Failed precondition of BackwardWriter::WriteSlow(Chain): "
"enough space available, use Write(Chain) instead";
return WriteInternal(src);
}

bool PositionShiftingBackwardWriterBase::WriteSlow(Chain&& src) {
RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), src.size())
<< "Failed precondition of BackwardWriter::WriteSlow(Chain&&): "
"enough space available, use Write(Chain&&) instead";
return WriteInternal(std::move(src));
}

bool PositionShiftingBackwardWriterBase::WriteSlow(const absl::Cord& src) {
RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), src.size())
<< "Failed precondition of BackwardWriter::WriteSlow(Cord): "
"enough space available, use Write(Cord) instead";
return WriteInternal(src);
}

bool PositionShiftingBackwardWriterBase::WriteSlow(absl::Cord&& src) {
RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), src.size())
<< "Failed precondition of BackwardWriter::WriteSlow(Cord&&): "
"enough space available, use Write(Cord&&) instead";
return WriteInternal(std::move(src));
}

bool PositionShiftingBackwardWriterBase::WriteSlow(ByteFill src) {
RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), src.size())
<< "Failed precondition of BackwardWriter::WriteSlow(ByteFill): "
"enough space available, use Write(ByteFill) instead";
return WriteInternal(src);
}

template <typename Src>
inline bool PositionShiftingBackwardWriterBase::WriteInternal(Src&& src) {
if (ABSL_PREDICT_FALSE(!ok())) return false;
BackwardWriter& dest = *DestWriter();
SyncBuffer(dest);
const bool write_ok = dest.Write(std::forward<Src>(src));
return MakeBuffer(dest) && write_ok;
}

bool PositionShiftingBackwardWriterBase::SupportsTruncate() {
BackwardWriter* const dest = DestWriter();
return dest != nullptr && dest->SupportsTruncate();
}

bool PositionShiftingBackwardWriterBase::TruncateImpl(Position new_size) {
if (ABSL_PREDICT_FALSE(!ok())) return false;
if (ABSL_PREDICT_FALSE(new_size < base_pos_)) {
return FailUnderflow(new_size, *this);
}
BackwardWriter& dest = *DestWriter();
SyncBuffer(dest);
const bool truncate_ok = dest.Truncate(new_size - base_pos_);
return MakeBuffer(dest) && truncate_ok;
}

} // namespace riegeli
Loading

0 comments on commit 450ae5c

Please # to comment.