Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions datalog/src/main/native/cpp/DataLogEditor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include "wpi/datalog/DataLogEditor.hpp"
#include <algorithm>
#include <cstddef>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "wpi/datalog/DataLogReader.hpp"
#include "wpi/datalog/DataLogReaderThread.hpp"

namespace wpi::log {

DataLogEditor::DataLogEditor(std::unique_ptr<DataLogReaderThread> datalog) {
state = std::make_shared<DataLogEditInfo>();
state->readerThread = std::move(datalog);
}

DataLogEditor DataLogEditor::WithTimestamps(std::vector<std::pair<int64_t, int64_t>> timestamps) const {
state->filterTimestamps = true;
state->allowedTimestamps = timestamps;
return DataLogEditor{state};
}

DataLogEditor DataLogEditor::WithEntryNames(std::vector<std::string> entryNames) const {
state->filterEntryNames = true;
state->allowedEntryNames = entryNames;
return DataLogEditor{state};
}

DataLogEditor DataLogEditor::WithRenamedEntries(std::map<std::string, std::string> renames) const {
state->renameEntries = true;
state->entryRenames = std::move(renames);
return DataLogEditor{state};
}

std::vector<DataLogRecord> DataLogEditor::ExecuteEdits() {
// we need to do the renames before we drop entries
const DataLogReaderEntry* entryData;
for (const DataLogRecord& record : state->records) {
entryData = state->readerThread->GetEntry(record.GetEntry());
// exclude based on timestamp
auto timestamp = record.GetTimestamp();
// if we allow this timestamp or it is a start/finish record, add it
if (std::ranges::any_of(state->allowedTimestamps, [timestamp](const std::pair<int64_t, int64_t>& pair) {
return timestamp >= pair.first && timestamp <= pair.second;
}) || record.IsControl()) {
state->records.push_back(record);
}


if (record.IsStart() && state->entryRenames.contains(std::string{entryData->name})) {
// its the start record of the one we want and its guaranteed to be in the filtered list so lets replace it with a copy that includes the correct name
StartRecordData srd;
record.GetStartData(&srd);
srd.name = state->entryRenames[std::string{srd.name}];
auto it = std::find_if(state->records.begin(), state->records.end(), [srd](DataLogRecord& targetRecord) {
return targetRecord.GetEntry() == srd.entry;
});
ptrdiff_t idx = it - state->records.begin();
state->records.at(idx) = DataLogRecord{entryData->entry, timestamp, reinterpret_cast<std::span<uint8_t>>(srd)};

Check failure on line 60 in datalog/src/main/native/cpp/DataLogEditor.cpp

View workflow job for this annotation

GitHub Actions / Build - Windows

'<function-style-cast>': cannot convert from 'initializer list' to 'wpi::log::DataLogRecord'

Check failure on line 60 in datalog/src/main/native/cpp/DataLogEditor.cpp

View workflow job for this annotation

GitHub Actions / Build - Windows

'reinterpret_cast': cannot convert from 'wpi::log::StartRecordData' to 'std::span<uint8_t,18446744073709551615>'
}
}
return state->records;
}
}
46 changes: 46 additions & 0 deletions datalog/src/main/native/include/wpi/datalog/DataLogEditor.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once

#include <cstdint>
#include <map>
#include <memory>
#include <utility>
#include <vector>
#include "wpi/datalog/DataLogReader.hpp"
#include "wpi/datalog/DataLogReaderThread.hpp"

namespace wpi::log {
class DataLogEditor {
public:
explicit DataLogEditor(std::unique_ptr<DataLogReaderThread> datalog);

DataLogEditor WithTimestamps(std::vector<std::pair<int64_t, int64_t>> timestamps) const;

DataLogEditor WithEntryNames(std::vector<std::string> entryNames) const;

DataLogEditor WithRenamedEntries(std::map<std::string, std::string> renames) const;

std::vector<DataLogRecord> ExecuteEdits();

private:
struct DataLogEditInfo {
// record list (input to the filter function)
std::vector<DataLogRecord> records;
// used to get the initial record list and to check what entry a record is from
std::unique_ptr<DataLogReaderThread> readerThread;

// edit stage enable flags
bool filterTimestamps = false;
bool filterEntryNames = false;
bool renameEntries = false;

// edit info
std::vector<std::pair<int64_t, int64_t>> allowedTimestamps;
std::vector<std::string> allowedEntryNames;
std::map<std::string, std::string> entryRenames;
};

explicit DataLogEditor(std::shared_ptr<DataLogEditInfo> config) : state(std::move(config)) {}

std::shared_ptr<DataLogEditInfo> state;
};
}
Loading