blob: c925b93b9b5554f2108b69eb0b80d28c66c74164 [file] [log] [blame]
// Copyright 2021 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/common/tagged_data.h"
#include <lib/syslog/cpp/macros.h>
#include <sstream>
#include "src/developer/debug/zxdb/common/string_util.h"
namespace zxdb {
TaggedData::TaggedData(DataBuffer bytes) : bytes_(std::move(bytes)) {}
TaggedData::TaggedData(DataBuffer buf, TagBuffer states)
: bytes_(std::move(buf)), tags_(std::move(states)) {
FX_DCHECK(tags_.empty() || tags_.size() == bytes_.size());
// Enforce that entirely-valid implies an empty state vector.
if (!tags_.empty()) {
if (std::find_if(tags_.begin(), tags_.end(), [](Tag s) { return s != kValid; }) == tags_.end())
tags_.clear();
}
}
bool TaggedData::RangeIsEntirely(size_t begin, size_t length, Tag tag) const {
FX_DCHECK(begin + length <= bytes_.size());
if (tags_.empty())
return tag == kValid;
FX_DCHECK(bytes_.size() == tags_.size());
for (size_t i = begin; i < begin + length; i++) {
if (tags_[i] != tag)
return false;
}
return true;
}
bool TaggedData::RangeContains(size_t begin, size_t length, Tag tag) const {
FX_DCHECK(begin + length <= bytes_.size());
if (tags_.empty())
return tag == kValid;
FX_DCHECK(bytes_.size() == tags_.size());
for (size_t i = begin; i < begin + length; i++) {
if (tags_[i] == tag)
return true;
}
return false;
}
bool TaggedData::operator==(const TaggedData& other) const {
return bytes_ == other.bytes_ && tags_ == other.tags_;
}
bool TaggedData::operator!=(const TaggedData& other) const { return !operator==(other); }
std::optional<TaggedData> TaggedData::Extract(size_t offset, size_t length) const {
if (offset + length > size())
return std::nullopt;
if (tags_.empty()) {
// Common-case of entirely valid buffer.
return TaggedData(DataBuffer(bytes_.begin() + offset, bytes_.begin() + (offset + length)));
}
// Extract a subregion of the states buffer. The constructor will "fix" the extracted region
// if it's entirely valid.
FX_DCHECK(tags_.size() == bytes_.size());
return TaggedData(DataBuffer(bytes_.begin() + offset, bytes_.begin() + (offset + length)),
TagBuffer(tags_.begin() + offset, tags_.begin() + (offset + length)));
}
std::string TaggedData::ToString() const {
std::ostringstream out;
size_t index = 0;
while (index < bytes_.size()) {
for (size_t col = 0; col < 16 && index < bytes_.size(); col++, index++) {
if (col == 8) {
// Center separator.
out << " ";
} else if (col > 0) {
out << " ";
}
if (tags_.empty() || tags_[index] == kValid) {
out << to_hex_string(bytes_[index], 2, false);
} else {
out << "??";
}
}
out << "\n";
}
return out.str();
}
} // namespace zxdb