blob: a9651738816f0bce408611f791b6afb382bcb936 [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.
#ifndef SRC_DEVELOPER_DEBUG_ZXDB_COMMON_DATA_EXTRACTOR_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_COMMON_DATA_EXTRACTOR_H_
#include <string.h>
#include <algorithm>
#include <optional>
#include "src/lib/containers/cpp/array_view.h"
namespace zxdb {
class DataExtractor {
public:
DataExtractor() = default;
explicit DataExtractor(containers::array_view<uint8_t> data) : data_(data) {}
// Returns the current position in the buffer.
size_t cur() const { return cur_; }
// Returns true is there is more data to read.
bool done() const { return cur_ >= data_.size(); }
// Reads the given value, returning it if there is room, and advancing the current location. If
// there is not enough bytes, the current position will remain unchanged and a nullopt will be
// returned.
//
// Normally one would read an explicitly sized value so the result doesn't depend on the current
// machine:
//
// auto result = extractor.Read<uint32_t>();
template <typename T>
std::optional<T> Read() {
T result;
if (!ReadBytes(sizeof(T), &result))
return std::nullopt;
return result;
}
// Rturns true if there are at least the number of remaining bytes in the buffer.
bool CanRead(size_t bytes) const {
return bytes <= data_.size() && // Prevent overflow of subtraction below.
data_.size() - cur_ >= bytes;
}
// Advances the current location by the given number of bytes. If it advances past the end, it
// will stop there.
void Advance(size_t bytes) { cur_ = std::min(cur_ + bytes, data_.size()); }
// Copies the given number of bytes into the |dest| buffer and advances the current position.
// Returns true on success. False means there weren't enough bytes to read.
bool ReadBytes(size_t bytes, void* dest) {
if (!CanRead(bytes))
return false;
memcpy(dest, &data_[cur_], bytes);
cur_ += bytes;
return true;
}
private:
containers::array_view<uint8_t> data_;
size_t cur_ = 0; // Current index in data_.
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_COMMON_DATA_EXTRACTOR_H_