blob: 8b704da628a1a61fa3c8edf0944736d5c325a2a1 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/debug/zxdb/console/async_output_buffer.h"
#include <lib/syslog/cpp/macros.h>
#include "src/developer/debug/zxdb/common/err.h"
namespace zxdb {
void AsyncOutputBuffer::SetCompletionCallback(CompletionCallback cb) {
FX_DCHECK(!is_complete());
// Don't clobber with a different callback, but let it be cleared.
FX_DCHECK(!cb || !completion_callback_);
completion_callback_ = std::move(cb);
}
void AsyncOutputBuffer::Append(std::string str, TextForegroundColor fg, TextBackgroundColor bg) {
FX_DCHECK(!marked_complete_);
nodes_.emplace_back(Span(std::move(str), fg, bg));
}
void AsyncOutputBuffer::Append(fxl::RefPtr<AsyncOutputBuffer> buf) {
FX_DCHECK(!marked_complete_);
if (!buf->is_complete()) {
pending_resolution_++;
// We're keeping a reference to the appended buffer so we know it's safe to capture |this|. We
// don't want to use a RefPtr here or it will create a reference cycle.
buf->SetCompletionCallback([this]() {
FX_DCHECK(pending_resolution_ > 0);
pending_resolution_--;
CheckComplete();
});
}
nodes_.emplace_back(std::move(buf));
}
void AsyncOutputBuffer::Append(Syntax syntax, std::string str) {
FX_DCHECK(!marked_complete_);
nodes_.emplace_back(Span(syntax, std::move(str)));
}
void AsyncOutputBuffer::Append(OutputBuffer buf) {
FX_DCHECK(!marked_complete_);
for (Span& span : buf.spans())
nodes_.emplace_back(std::move(span));
}
void AsyncOutputBuffer::Append(const Err& err) {
FX_DCHECK(!marked_complete_);
nodes_.emplace_back(Span(Syntax::kNormal, err.msg()));
}
void AsyncOutputBuffer::Complete() {
FX_DCHECK(!marked_complete_);
marked_complete_ = true;
CheckComplete();
}
void AsyncOutputBuffer::Complete(std::string str, TextForegroundColor fg, TextBackgroundColor bg) {
Append(std::move(str), fg, bg);
Complete();
}
void AsyncOutputBuffer::Complete(fxl::RefPtr<AsyncOutputBuffer> buf) {
Append(std::move(buf));
Complete();
}
void AsyncOutputBuffer::Complete(Syntax syntax, std::string str) {
Append(std::move(str));
Complete();
}
void AsyncOutputBuffer::Complete(OutputBuffer buf) {
Append(std::move(buf));
Complete();
}
void AsyncOutputBuffer::Complete(const Err& err) {
Append(err);
Complete();
}
OutputBuffer AsyncOutputBuffer::DestructiveFlatten() {
FX_DCHECK(is_complete());
OutputBuffer out;
DestructiveCollectNodes(&out);
return out;
}
void AsyncOutputBuffer::CheckComplete() {
if (is_complete() && completion_callback_) {
// Clear the object's callback before issuing it.
CompletionCallback stack_cb = std::move(completion_callback_);
stack_cb();
}
}
void AsyncOutputBuffer::DestructiveCollectNodes(OutputBuffer* out) {
FX_DCHECK(is_complete());
for (auto& node : nodes_) {
if (std::holds_alternative<Span>(node))
out->Append(std::move(std::get<Span>(node)));
else
std::get<Ref>(node)->DestructiveCollectNodes(out);
}
}
} // namespace zxdb