blob: 6086e1171bc27cb31d3d892a2bd1201e020848d6 [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.
#ifndef SRC_DEVELOPER_DEBUG_ZXDB_COMMON_TAGGED_DATA_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_COMMON_TAGGED_DATA_H_
#include <optional>
#include <vector>
namespace zxdb {
// A data buffer with per-byte tags for validity. This allows us to express that certain bytes may
// be valid while others might be unknown. This can happen for optimized code where, for example,
// some portions of a struct are kept in registers so can be known, but other portions of the struct
// are optimized out.
class TaggedData {
public:
enum Tag : uint8_t {
kValid,
kUnknown,
};
using DataBuffer = std::vector<uint8_t>;
using TagBuffer = std::vector<Tag>;
// Constructs a buffer of entirely valid data. To construct one with different regions of valid
// and invalid, use the TaggedDataBuilder.
explicit TaggedData(DataBuffer bytes = DataBuffer());
const DataBuffer& bytes() const { return bytes_; }
// NOTE: there is no accessor for the tag buffer to allow us to change the format in the future.
// If this is used for very large things, we may want to go for a range-based representation.
// There is also some possibility that it will need to represent bit validity in the future.
// If additional querying is needed, add functions to query the state of a given range rather than
// exposing the TagBuffer externally.
// Returns true if the given range (which is asserted to be valid) satisfies the condition.
bool RangeIsEntirely(size_t begin, size_t length, Tag tag) const;
bool RangeContains(size_t begin, size_t length, Tag tag) const;
bool RangeIsValid(size_t begin, size_t length) const {
return RangeIsEntirely(begin, length, kValid);
}
size_t size() const { return bytes_.size(); }
bool empty() const { return bytes_.empty(); }
bool operator==(const TaggedData& other) const;
bool operator!=(const TaggedData& other) const;
// Returns true if the entire buffer is valid.
bool all_valid() const { return tags_.empty(); }
// Extracts a subrange of the buffer. Returns nullopt if the range falls outside of the data
// range.
std::optional<TaggedData> Extract(size_t offset, size_t length) const;
std::string ToString() const;
private:
friend class TaggedDataBuilder;
// When the Tag vector is empty (should be the common-case), all bytes are marked valid.
explicit TaggedData(DataBuffer bytes, TagBuffer states);
DataBuffer bytes_;
// Empty if all bytes are valid. Otherwise, the same size as bytes_ with per-byte validity.
TagBuffer tags_;
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_COMMON_TAGGED_DATA_H_