Use std::string_view and fmtlib across all libraries (#3402)

- Twine, StringRef, Format, and NativeFormatting have been removed
- Logging now uses fmtlib style formatting
- Nearly all uses of wpi::outs/errs have been replaced with fmt::print() or
std::puts()/std::fputs() (for unformatted strings).
- A wpi/fmt/raw_ostream.h header has been added to enable
fmt::print() with wpi::raw_ostream
This commit is contained in:
Peter Johnson
2021-06-06 16:13:58 -07:00
committed by GitHub
parent 4f1cecb8e7
commit b2c3b2dd8e
441 changed files with 5061 additions and 9749 deletions

View File

@@ -4,21 +4,22 @@
#include "glass/networktables/NTCommandScheduler.h"
#include <iostream>
#include <fmt/format.h>
#include <wpi/StringExtras.h>
using namespace glass;
NTCommandSchedulerModel::NTCommandSchedulerModel(wpi::StringRef path)
NTCommandSchedulerModel::NTCommandSchedulerModel(std::string_view path)
: NTCommandSchedulerModel(nt::GetDefaultInstance(), path) {}
NTCommandSchedulerModel::NTCommandSchedulerModel(NT_Inst instance,
wpi::StringRef path)
std::string_view path)
: m_nt(instance),
m_name(m_nt.GetEntry(path + "/.name")),
m_commands(m_nt.GetEntry(path + "/Names")),
m_ids(m_nt.GetEntry(path + "/Ids")),
m_cancel(m_nt.GetEntry(path + "/Cancel")),
m_nameValue(path.rsplit('/').second) {
m_name(m_nt.GetEntry(fmt::format("{}/.name", path))),
m_commands(m_nt.GetEntry(fmt::format("{}/Names", path))),
m_ids(m_nt.GetEntry(fmt::format("{}/Ids", path))),
m_cancel(m_nt.GetEntry(fmt::format("{}/Cancel", path))),
m_nameValue(wpi::rsplit(path, '/').second) {
m_nt.AddListener(m_name);
m_nt.AddListener(m_commands);
m_nt.AddListener(m_ids);

View File

@@ -4,18 +4,21 @@
#include "glass/networktables/NTCommandSelector.h"
#include <fmt/format.h>
#include <wpi/StringExtras.h>
using namespace glass;
NTCommandSelectorModel::NTCommandSelectorModel(wpi::StringRef path)
NTCommandSelectorModel::NTCommandSelectorModel(std::string_view path)
: NTCommandSelectorModel(nt::GetDefaultInstance(), path) {}
NTCommandSelectorModel::NTCommandSelectorModel(NT_Inst instance,
wpi::StringRef path)
std::string_view path)
: m_nt(instance),
m_running(m_nt.GetEntry(path + "/running")),
m_name(m_nt.GetEntry(path + "/.name")),
m_runningData("NTCmd:" + path),
m_nameValue(path.rsplit('/').second) {
m_running(m_nt.GetEntry(fmt::format("{}/running", path))),
m_name(m_nt.GetEntry(fmt::format("{}/.name", path))),
m_runningData(fmt::format("NTCmd:{}", path)),
m_nameValue(wpi::rsplit(path, '/').second) {
m_runningData.SetDigital(true);
m_nt.AddListener(m_running);
m_nt.AddListener(m_name);

View File

@@ -4,24 +4,26 @@
#include "glass/networktables/NTDifferentialDrive.h"
#include <fmt/format.h>
#include <imgui.h>
#include <wpi/MathExtras.h>
#include <wpi/StringExtras.h>
using namespace glass;
NTDifferentialDriveModel::NTDifferentialDriveModel(wpi::StringRef path)
NTDifferentialDriveModel::NTDifferentialDriveModel(std::string_view path)
: NTDifferentialDriveModel(nt::GetDefaultInstance(), path) {}
NTDifferentialDriveModel::NTDifferentialDriveModel(NT_Inst instance,
wpi::StringRef path)
std::string_view path)
: m_nt(instance),
m_name(m_nt.GetEntry(path + "/.name")),
m_controllable(m_nt.GetEntry(path + "/.controllable")),
m_lPercent(m_nt.GetEntry(path + "/Left Motor Speed")),
m_rPercent(m_nt.GetEntry(path + "/Right Motor Speed")),
m_nameValue(path.rsplit('/').second),
m_lPercentData("NTDiffDriveL:" + path),
m_rPercentData("NTDiffDriveR:" + path) {
m_name(m_nt.GetEntry(fmt::format("{}/.name", path))),
m_controllable(m_nt.GetEntry(fmt::format("{}/.controllable", path))),
m_lPercent(m_nt.GetEntry(fmt::format("{}/Left Motor Speed", path))),
m_rPercent(m_nt.GetEntry(fmt::format("{}/Right Motor Speed", path))),
m_nameValue(wpi::rsplit(path, '/').second),
m_lPercentData(fmt::format("NTDiffDriveL:{}", path)),
m_rPercentData(fmt::format("NTDiffDriveR:{}", path)) {
m_nt.AddListener(m_name);
m_nt.AddListener(m_controllable);
m_nt.AddListener(m_lPercent);

View File

@@ -4,19 +4,20 @@
#include "glass/networktables/NTDigitalInput.h"
#include <wpi/Twine.h>
#include <fmt/format.h>
#include <wpi/StringExtras.h>
using namespace glass;
NTDigitalInputModel::NTDigitalInputModel(wpi::StringRef path)
NTDigitalInputModel::NTDigitalInputModel(std::string_view path)
: NTDigitalInputModel{nt::GetDefaultInstance(), path} {}
NTDigitalInputModel::NTDigitalInputModel(NT_Inst inst, wpi::StringRef path)
NTDigitalInputModel::NTDigitalInputModel(NT_Inst inst, std::string_view path)
: m_nt{inst},
m_value{m_nt.GetEntry(path + "/Value")},
m_name{m_nt.GetEntry(path + "/.name")},
m_valueData{"NT_DIn:" + path},
m_nameValue{path.rsplit('/').second} {
m_value{m_nt.GetEntry(fmt::format("{}/Value", path))},
m_name{m_nt.GetEntry(fmt::format("{}/.name", path))},
m_valueData{fmt::format("NT_DIn:{}", path)},
m_nameValue{wpi::rsplit(path, '/').second} {
m_nt.AddListener(m_value);
m_nt.AddListener(m_name);

View File

@@ -4,19 +4,19 @@
#include "glass/networktables/NTDigitalOutput.h"
#include <wpi/Twine.h>
#include <fmt/format.h>
using namespace glass;
NTDigitalOutputModel::NTDigitalOutputModel(wpi::StringRef path)
NTDigitalOutputModel::NTDigitalOutputModel(std::string_view path)
: NTDigitalOutputModel{nt::GetDefaultInstance(), path} {}
NTDigitalOutputModel::NTDigitalOutputModel(NT_Inst inst, wpi::StringRef path)
NTDigitalOutputModel::NTDigitalOutputModel(NT_Inst inst, std::string_view path)
: m_nt{inst},
m_value{m_nt.GetEntry(path + "/Value")},
m_name{m_nt.GetEntry(path + "/.name")},
m_controllable{m_nt.GetEntry(path + "/.controllable")},
m_valueData{"NT_DOut:" + path} {
m_value{m_nt.GetEntry(fmt::format("{}/Value", path))},
m_name{m_nt.GetEntry(fmt::format("{}/.name", path))},
m_controllable{m_nt.GetEntry(fmt::format("{}/.controllable", path))},
m_valueData{fmt::format("NT_DOut:{}", path)} {
m_nt.AddListener(m_value);
m_nt.AddListener(m_name);
m_nt.AddListener(m_controllable);

View File

@@ -6,27 +6,28 @@
#include <stdint.h>
#include <wpi/Twine.h>
#include <fmt/format.h>
#include <wpi/timestamp.h>
using namespace glass;
NTFMSModel::NTFMSModel(wpi::StringRef path)
NTFMSModel::NTFMSModel(std::string_view path)
: NTFMSModel{nt::GetDefaultInstance(), path} {}
NTFMSModel::NTFMSModel(NT_Inst inst, wpi::StringRef path)
NTFMSModel::NTFMSModel(NT_Inst inst, std::string_view path)
: m_nt{inst},
m_gameSpecificMessage{m_nt.GetEntry(path + "/GameSpecificMessage")},
m_alliance{m_nt.GetEntry(path + "/IsRedAlliance")},
m_station{m_nt.GetEntry(path + "/StationNumber")},
m_controlWord{m_nt.GetEntry(path + "/FMSControlData")},
m_fmsAttached{"NT_FMS:FMSAttached:" + path},
m_dsAttached{"NT_FMS:DSAttached:" + path},
m_allianceStationId{"NT_FMS:AllianceStationID:" + path},
m_estop{"NT_FMS:EStop:" + path},
m_enabled{"NT_FMS:RobotEnabled:" + path},
m_test{"NT_FMS:TestMode:" + path},
m_autonomous{"NT_FMS:AutonomousMode:" + path} {
m_gameSpecificMessage{
m_nt.GetEntry(fmt::format("{}/GameSpecificMessage", path))},
m_alliance{m_nt.GetEntry(fmt::format("{}/IsRedAlliance", path))},
m_station{m_nt.GetEntry(fmt::format("{}/StationNumber", path))},
m_controlWord{m_nt.GetEntry(fmt::format("{}/FMSControlData", path))},
m_fmsAttached{fmt::format("NT_FMS:FMSAttached:{}", path)},
m_dsAttached{fmt::format("NT_FMS:DSAttached:{}", path)},
m_allianceStationId{fmt::format("NT_FMS:AllianceStationID:{}", path)},
m_estop{fmt::format("NT_FMS:EStop:{}", path)},
m_enabled{fmt::format("NT_FMS:RobotEnabled:{}", path)},
m_test{fmt::format("NT_FMS:TestMode:{}", path)},
m_autonomous{fmt::format("NT_FMS:AutonomousMode:{}", path)} {
m_nt.AddListener(m_alliance);
m_nt.AddListener(m_station);
m_nt.AddListener(m_controlWord);
@@ -39,7 +40,7 @@ NTFMSModel::NTFMSModel(NT_Inst inst, wpi::StringRef path)
m_autonomous.SetDigital(true);
}
wpi::StringRef NTFMSModel::GetGameSpecificMessage(
std::string_view NTFMSModel::GetGameSpecificMessage(
wpi::SmallVectorImpl<char>& buf) {
buf.clear();
auto value = nt::GetEntryValue(m_gameSpecificMessage);
@@ -47,7 +48,7 @@ wpi::StringRef NTFMSModel::GetGameSpecificMessage(
auto str = value->GetString();
buf.append(str.begin(), str.end());
}
return wpi::StringRef{buf.data(), buf.size()};
return std::string_view{buf.data(), buf.size()};
}
void NTFMSModel::Update() {

View File

@@ -7,17 +7,18 @@
#include <algorithm>
#include <vector>
#include <fmt/format.h>
#include <ntcore_cpp.h>
#include <wpi/Endian.h>
#include <wpi/MathExtras.h>
#include <wpi/SmallString.h>
#include <wpi/SmallVector.h>
#include <wpi/StringExtras.h>
using namespace glass;
class NTField2DModel::ObjectModel : public FieldObjectModel {
public:
ObjectModel(wpi::StringRef name, NT_Entry entry)
ObjectModel(std::string_view name, NT_Entry entry)
: m_name{name}, m_entry{entry} {}
const char* GetName() const override { return m_name.c_str(); }
@@ -63,7 +64,7 @@ void NTField2DModel::ObjectModel::NTUpdate(const nt::Value& value) {
}
} else if (value.IsRaw()) {
// treat it simply as an array of doubles
wpi::StringRef data = value.GetRaw();
std::string_view data = value.GetRaw();
// must be triples of doubles
auto size = data.size();
@@ -71,7 +72,7 @@ void NTField2DModel::ObjectModel::NTUpdate(const nt::Value& value) {
return;
}
m_poses.resize(size / (3 * 8));
const char* p = data.begin();
const char* p = data.data();
for (size_t i = 0; i < size / (3 * 8); ++i) {
double x = wpi::BitsToDouble(
wpi::support::endian::readNext<uint64_t, wpi::support::big,
@@ -115,8 +116,8 @@ void NTField2DModel::ObjectModel::UpdateNT() {
p, wpi::DoubleToBits(pose.Rotation().Degrees().to<double>()));
p += 8;
}
nt::SetEntryTypeValue(
m_entry, nt::Value::MakeRaw(wpi::StringRef{arr.data(), arr.size()}));
nt::SetEntryTypeValue(m_entry,
nt::Value::MakeRaw({arr.data(), arr.size()}));
}
}
@@ -147,13 +148,13 @@ void NTField2DModel::ObjectModel::SetRotation(size_t i, frc::Rotation2d rot) {
}
}
NTField2DModel::NTField2DModel(wpi::StringRef path)
NTField2DModel::NTField2DModel(std::string_view path)
: NTField2DModel{nt::GetDefaultInstance(), path} {}
NTField2DModel::NTField2DModel(NT_Inst inst, wpi::StringRef path)
NTField2DModel::NTField2DModel(NT_Inst inst, std::string_view path)
: m_nt{inst},
m_path{(path + "/").str()},
m_name{m_nt.GetEntry(path + "/.name")} {
m_path{fmt::format("{}/", path)},
m_name{m_nt.GetEntry(fmt::format("{}/.name", path))} {
m_nt.AddListener(m_path, NT_NOTIFY_LOCAL | NT_NOTIFY_NEW | NT_NOTIFY_DELETE |
NT_NOTIFY_UPDATE | NT_NOTIFY_IMMEDIATE);
}
@@ -182,8 +183,9 @@ void NTField2DModel::Update() {
}
// handle create/delete
if (wpi::StringRef{event.name}.startswith(m_path)) {
auto name = wpi::StringRef{event.name}.drop_front(m_path.size());
std::string_view name = event.name;
if (wpi::starts_with(name, m_path)) {
name.remove_prefix(m_path.size());
if (name.empty() || name[0] == '.') {
continue;
}
@@ -216,9 +218,8 @@ bool NTField2DModel::IsReadOnly() {
return false;
}
FieldObjectModel* NTField2DModel::AddFieldObject(const wpi::Twine& name) {
wpi::SmallString<128> fullNameBuf;
wpi::StringRef fullName = (m_path + name).toStringRef(fullNameBuf);
FieldObjectModel* NTField2DModel::AddFieldObject(std::string_view name) {
auto fullName = fmt::format("{}{}", m_path, name);
auto [it, match] = Find(fullName);
if (!match) {
it = m_objects.emplace(
@@ -227,9 +228,8 @@ FieldObjectModel* NTField2DModel::AddFieldObject(const wpi::Twine& name) {
return it->get();
}
void NTField2DModel::RemoveFieldObject(const wpi::Twine& name) {
wpi::SmallString<128> fullNameBuf;
auto [it, match] = Find((m_path + name).toStringRef(fullNameBuf));
void NTField2DModel::RemoveFieldObject(std::string_view name) {
auto [it, match] = Find(fmt::format("{}{}", m_path, name));
if (match) {
nt::DeleteEntry((*it)->GetEntry());
m_objects.erase(it);
@@ -237,19 +237,19 @@ void NTField2DModel::RemoveFieldObject(const wpi::Twine& name) {
}
void NTField2DModel::ForEachFieldObject(
wpi::function_ref<void(FieldObjectModel& model, wpi::StringRef name)>
wpi::function_ref<void(FieldObjectModel& model, std::string_view name)>
func) {
for (auto&& obj : m_objects) {
if (obj->Exists()) {
func(*obj, wpi::StringRef{obj->GetName()}.drop_front(m_path.size()));
func(*obj, wpi::drop_front(obj->GetName(), m_path.size()));
}
}
}
std::pair<NTField2DModel::Objects::iterator, bool> NTField2DModel::Find(
wpi::StringRef fullName) {
std::string_view fullName) {
auto it = std::lower_bound(
m_objects.begin(), m_objects.end(), fullName,
[](const auto& e, wpi::StringRef name) { return e->GetName() < name; });
[](const auto& e, std::string_view name) { return e->GetName() < name; });
return {it, it != m_objects.end() && (*it)->GetName() == fullName};
}

View File

@@ -4,17 +4,20 @@
#include "glass/networktables/NTGyro.h"
#include <fmt/format.h>
#include <wpi/StringExtras.h>
using namespace glass;
NTGyroModel::NTGyroModel(wpi::StringRef path)
NTGyroModel::NTGyroModel(std::string_view path)
: NTGyroModel(nt::GetDefaultInstance(), path) {}
NTGyroModel::NTGyroModel(NT_Inst instance, wpi::StringRef path)
NTGyroModel::NTGyroModel(NT_Inst instance, std::string_view path)
: m_nt(instance),
m_angle(m_nt.GetEntry(path + "/Value")),
m_name(m_nt.GetEntry(path + "/.name")),
m_angleData("NT_Gyro:" + path),
m_nameValue(path.rsplit('/').second) {
m_angle(m_nt.GetEntry(fmt::format("{}/Value", path))),
m_name(m_nt.GetEntry(fmt::format("{}/.name", path))),
m_angleData(fmt::format("NT_Gyro:{}", path)),
m_nameValue(wpi::rsplit(path, '/').second) {
m_nt.AddListener(m_angle);
m_nt.AddListener(m_name);
}

View File

@@ -4,27 +4,33 @@
#include "glass/networktables/NTMecanumDrive.h"
#include <fmt/format.h>
#include <imgui.h>
#include <wpi/MathExtras.h>
#include <wpi/StringExtras.h>
using namespace glass;
NTMecanumDriveModel::NTMecanumDriveModel(wpi::StringRef path)
NTMecanumDriveModel::NTMecanumDriveModel(std::string_view path)
: NTMecanumDriveModel(nt::GetDefaultInstance(), path) {}
NTMecanumDriveModel::NTMecanumDriveModel(NT_Inst instance, wpi::StringRef path)
NTMecanumDriveModel::NTMecanumDriveModel(NT_Inst instance,
std::string_view path)
: m_nt(instance),
m_name(m_nt.GetEntry(path + "/.name")),
m_controllable(m_nt.GetEntry(path + "/.controllable")),
m_flPercent(m_nt.GetEntry(path + "/Front Left Motor Speed")),
m_frPercent(m_nt.GetEntry(path + "/Front Right Motor Speed")),
m_rlPercent(m_nt.GetEntry(path + "/Rear Left Motor Speed")),
m_rrPercent(m_nt.GetEntry(path + "/Rear Right Motor Speed")),
m_nameValue(path.rsplit('/').second),
m_flPercentData("NTMcnmDriveFL:" + path),
m_frPercentData("NTMcnmDriveFR:" + path),
m_rlPercentData("NTMcnmDriveRL:" + path),
m_rrPercentData("NTMcnmDriveRR:" + path) {
m_name(m_nt.GetEntry(fmt::format("{}/.name", path))),
m_controllable(m_nt.GetEntry(fmt::format("{}/.controllable", path))),
m_flPercent(
m_nt.GetEntry(fmt::format("{}/Front Left Motor Speed", path))),
m_frPercent(
m_nt.GetEntry(fmt::format("{}/Front Right Motor Speed", path))),
m_rlPercent(m_nt.GetEntry(fmt::format("{}/Rear Left Motor Speed", path))),
m_rrPercent(
m_nt.GetEntry(fmt::format("{}/Rear Right Motor Speed", path))),
m_nameValue(wpi::rsplit(path, '/').second),
m_flPercentData(fmt::format("NTMcnmDriveFL:{}", path)),
m_frPercentData(fmt::format("NTMcnmDriveFR:{}", path)),
m_rlPercentData(fmt::format("NTMcnmDriveRL:{}", path)),
m_rrPercentData(fmt::format("NTMcnmDriveRR:{}", path)) {
m_nt.AddListener(m_name);
m_nt.AddListener(m_controllable);
m_nt.AddListener(m_flPercent);

View File

@@ -5,25 +5,27 @@
#include "glass/networktables/NTMechanism2D.h"
#include <algorithm>
#include <string_view>
#include <vector>
#include <fmt/format.h>
#include <imgui.h>
#include <ntcore_cpp.h>
#include <wpi/StringExtras.h>
#include "glass/other/Mechanism2D.h"
using namespace glass;
// Convert "#RRGGBB" hex color to ImU32 color
static void ConvertColor(wpi::StringRef in, ImU32* out) {
static void ConvertColor(std::string_view in, ImU32* out) {
if (in.size() != 7 || in[0] != '#') {
return;
}
ImU32 val = 0;
if (in.drop_front().getAsInteger(16, val)) {
return;
if (auto v = wpi::parse_integer<ImU32>(wpi::drop_front(in), 16)) {
ImU32 val = v.value();
*out = IM_COL32((val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff, 255);
}
*out = IM_COL32((val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff, 255);
}
namespace {
@@ -32,13 +34,13 @@ class NTMechanismObjectModel;
class NTMechanismGroupImpl final {
public:
NTMechanismGroupImpl(NT_Inst inst, const wpi::Twine& path,
wpi::StringRef name)
: m_inst{inst}, m_path{path.str()}, m_name{name} {}
NTMechanismGroupImpl(NT_Inst inst, std::string_view path,
std::string_view name)
: m_inst{inst}, m_path{path}, m_name{name} {}
const char* GetName() const { return m_name.c_str(); }
void ForEachObject(wpi::function_ref<void(MechanismObjectModel& model)> func);
void NTUpdate(const nt::EntryNotification& event, wpi::StringRef name);
void NTUpdate(const nt::EntryNotification& event, std::string_view name);
protected:
NT_Inst m_inst;
@@ -49,14 +51,14 @@ class NTMechanismGroupImpl final {
class NTMechanismObjectModel final : public MechanismObjectModel {
public:
NTMechanismObjectModel(NT_Inst inst, const wpi::Twine& path,
wpi::StringRef name)
NTMechanismObjectModel(NT_Inst inst, std::string_view path,
std::string_view name)
: m_group{inst, path, name},
m_type{nt::GetEntry(inst, path + "/.type")},
m_color{nt::GetEntry(inst, path + "/color")},
m_weight{nt::GetEntry(inst, path + "/weight")},
m_angle{nt::GetEntry(inst, path + "/angle")},
m_length{nt::GetEntry(inst, path + "/length")} {}
m_type{nt::GetEntry(inst, fmt::format("{}/.type", path))},
m_color{nt::GetEntry(inst, fmt::format("{}/color", path))},
m_weight{nt::GetEntry(inst, fmt::format("{}/weight", path))},
m_angle{nt::GetEntry(inst, fmt::format("{}/angle", path))},
m_length{nt::GetEntry(inst, fmt::format("{}/length", path))} {}
const char* GetName() const final { return m_group.GetName(); }
void ForEachObject(
@@ -70,7 +72,7 @@ class NTMechanismObjectModel final : public MechanismObjectModel {
frc::Rotation2d GetAngle() const final { return m_angleValue; }
units::meter_t GetLength() const final { return m_lengthValue; }
bool NTUpdate(const nt::EntryNotification& event, wpi::StringRef childName);
bool NTUpdate(const nt::EntryNotification& event, std::string_view childName);
private:
NTMechanismGroupImpl m_group;
@@ -98,25 +100,26 @@ void NTMechanismGroupImpl::ForEachObject(
}
void NTMechanismGroupImpl::NTUpdate(const nt::EntryNotification& event,
wpi::StringRef name) {
std::string_view name) {
if (name.empty()) {
return;
}
wpi::StringRef childName;
std::tie(name, childName) = name.split('/');
std::string_view childName;
std::tie(name, childName) = wpi::split(name, '/');
if (childName.empty()) {
return;
}
auto it = std::lower_bound(
m_objects.begin(), m_objects.end(), name,
[](const auto& e, wpi::StringRef name) { return e->GetName() < name; });
[](const auto& e, std::string_view name) { return e->GetName() < name; });
bool match = it != m_objects.end() && (*it)->GetName() == name;
if (event.flags & NT_NOTIFY_NEW) {
if (!match) {
it = m_objects.emplace(it, std::make_unique<NTMechanismObjectModel>(
m_inst, m_path + "/" + name, name));
it = m_objects.emplace(
it, std::make_unique<NTMechanismObjectModel>(
m_inst, fmt::format("{}/{}", m_path, name), name));
match = true;
}
}
@@ -128,7 +131,7 @@ void NTMechanismGroupImpl::NTUpdate(const nt::EntryNotification& event,
}
bool NTMechanismObjectModel::NTUpdate(const nt::EntryNotification& event,
wpi::StringRef childName) {
std::string_view childName) {
if (event.entry == m_type) {
if ((event.flags & NT_NOTIFY_DELETE) != 0) {
return true;
@@ -160,10 +163,10 @@ bool NTMechanismObjectModel::NTUpdate(const nt::EntryNotification& event,
class NTMechanism2DModel::RootModel final : public MechanismRootModel {
public:
RootModel(NT_Inst inst, const wpi::Twine& path, wpi::StringRef name)
RootModel(NT_Inst inst, std::string_view path, std::string_view name)
: m_group{inst, path, name},
m_x{nt::GetEntry(inst, path + "/x")},
m_y{nt::GetEntry(inst, path + "/y")} {}
m_x{nt::GetEntry(inst, fmt::format("{}/x", path))},
m_y{nt::GetEntry(inst, fmt::format("{}/y", path))} {}
const char* GetName() const final { return m_group.GetName(); }
void ForEachObject(
@@ -171,7 +174,7 @@ class NTMechanism2DModel::RootModel final : public MechanismRootModel {
m_group.ForEachObject(func);
}
bool NTUpdate(const nt::EntryNotification& event, wpi::StringRef childName);
bool NTUpdate(const nt::EntryNotification& event, std::string_view childName);
frc::Translation2d GetPosition() const override { return m_pos; };
@@ -183,7 +186,7 @@ class NTMechanism2DModel::RootModel final : public MechanismRootModel {
};
bool NTMechanism2DModel::RootModel::NTUpdate(const nt::EntryNotification& event,
wpi::StringRef childName) {
std::string_view childName) {
if ((event.flags & NT_NOTIFY_DELETE) != 0 &&
(event.entry == m_x || event.entry == m_y)) {
return true;
@@ -203,15 +206,15 @@ bool NTMechanism2DModel::RootModel::NTUpdate(const nt::EntryNotification& event,
return false;
}
NTMechanism2DModel::NTMechanism2DModel(wpi::StringRef path)
NTMechanism2DModel::NTMechanism2DModel(std::string_view path)
: NTMechanism2DModel{nt::GetDefaultInstance(), path} {}
NTMechanism2DModel::NTMechanism2DModel(NT_Inst inst, wpi::StringRef path)
NTMechanism2DModel::NTMechanism2DModel(NT_Inst inst, std::string_view path)
: m_nt{inst},
m_path{(path + "/").str()},
m_name{m_nt.GetEntry(path + "/.name")},
m_dimensions{m_nt.GetEntry(path + "/dims")},
m_bgColor{m_nt.GetEntry(path + "/backgroundColor")},
m_path{fmt::format("{}/", path)},
m_name{m_nt.GetEntry(fmt::format("{}/.name", path))},
m_dimensions{m_nt.GetEntry(fmt::format("{}/dims", path))},
m_bgColor{m_nt.GetEntry(fmt::format("{}/backgroundColor", path))},
m_dimensionsValue{1_m, 1_m} {
m_nt.AddListener(m_path, NT_NOTIFY_LOCAL | NT_NOTIFY_NEW | NT_NOTIFY_DELETE |
NT_NOTIFY_UPDATE | NT_NOTIFY_IMMEDIATE);
@@ -247,28 +250,30 @@ void NTMechanism2DModel::Update() {
}
}
if (wpi::StringRef{event.name}.startswith(m_path)) {
auto name = wpi::StringRef{event.name}.drop_front(m_path.size());
std::string_view name = event.name;
if (wpi::starts_with(name, m_path)) {
name.remove_prefix(m_path.size());
if (name.empty() || name[0] == '.') {
continue;
}
wpi::StringRef childName;
std::tie(name, childName) = name.split('/');
std::string_view childName;
std::tie(name, childName) = wpi::split(name, '/');
if (childName.empty()) {
continue;
}
auto it = std::lower_bound(m_roots.begin(), m_roots.end(), name,
[](const auto& e, wpi::StringRef name) {
[](const auto& e, std::string_view name) {
return e->GetName() < name;
});
bool match = it != m_roots.end() && (*it)->GetName() == name;
if (event.flags & NT_NOTIFY_NEW) {
if (!match) {
it =
m_roots.emplace(it, std::make_unique<RootModel>(
m_nt.GetInstance(), m_path + name, name));
it = m_roots.emplace(
it,
std::make_unique<RootModel>(
m_nt.GetInstance(), fmt::format("{}{}", m_path, name), name));
match = true;
}
}

View File

@@ -4,25 +4,28 @@
#include "glass/networktables/NTPIDController.h"
#include <fmt/format.h>
#include <wpi/StringExtras.h>
using namespace glass;
NTPIDControllerModel::NTPIDControllerModel(wpi::StringRef path)
NTPIDControllerModel::NTPIDControllerModel(std::string_view path)
: NTPIDControllerModel(nt::GetDefaultInstance(), path) {}
NTPIDControllerModel::NTPIDControllerModel(NT_Inst instance,
wpi::StringRef path)
std::string_view path)
: m_nt(instance),
m_name(m_nt.GetEntry(path + "/.name")),
m_controllable(m_nt.GetEntry(path + "/.controllable")),
m_p(m_nt.GetEntry(path + "/p")),
m_i(m_nt.GetEntry(path + "/i")),
m_d(m_nt.GetEntry(path + "/d")),
m_setpoint(m_nt.GetEntry(path + "/setpoint")),
m_pData("NTPIDCtrlP:" + path),
m_iData("NTPIDCtrlI:" + path),
m_dData("NTPIDCtrlD:" + path),
m_setpointData("NTPIDCtrlStpt:" + path),
m_nameValue(path.rsplit('/').second) {
m_name(m_nt.GetEntry(fmt::format("{}/.name", path))),
m_controllable(m_nt.GetEntry(fmt::format("{}/.controllable", path))),
m_p(m_nt.GetEntry(fmt::format("{}/p", path))),
m_i(m_nt.GetEntry(fmt::format("{}/i", path))),
m_d(m_nt.GetEntry(fmt::format("{}/d", path))),
m_setpoint(m_nt.GetEntry(fmt::format("{}/setpoint", path))),
m_pData(fmt::format("NTPIDCtrlP:{}", path)),
m_iData(fmt::format("NTPIDCtrlI:{}", path)),
m_dData(fmt::format("NTPIDCtrlD:{}", path)),
m_setpointData(fmt::format("NTPIDCtrlStpt:{}", path)),
m_nameValue(wpi::rsplit(path, '/').second) {
m_nt.AddListener(m_name);
m_nt.AddListener(m_controllable);
m_nt.AddListener(m_p);

View File

@@ -4,19 +4,22 @@
#include "glass/networktables/NTSpeedController.h"
#include <fmt/format.h>
#include <wpi/StringExtras.h>
using namespace glass;
NTSpeedControllerModel::NTSpeedControllerModel(wpi::StringRef path)
NTSpeedControllerModel::NTSpeedControllerModel(std::string_view path)
: NTSpeedControllerModel(nt::GetDefaultInstance(), path) {}
NTSpeedControllerModel::NTSpeedControllerModel(NT_Inst instance,
wpi::StringRef path)
std::string_view path)
: m_nt(instance),
m_value(m_nt.GetEntry(path + "/Value")),
m_name(m_nt.GetEntry(path + "/.name")),
m_controllable(m_nt.GetEntry(path + "/.controllable")),
m_valueData("NT_SpdCtrl:" + path),
m_nameValue(path.rsplit('/').second) {
m_value(m_nt.GetEntry(fmt::format("{}/Value", path))),
m_name(m_nt.GetEntry(fmt::format("{}/.name", path))),
m_controllable(m_nt.GetEntry(fmt::format("{}/.controllable"))),
m_valueData(fmt::format("NT_SpdCtrl:{}", path)),
m_nameValue(wpi::rsplit(path, '/').second) {
m_nt.AddListener(m_value);
m_nt.AddListener(m_name);
m_nt.AddListener(m_controllable);

View File

@@ -4,32 +4,34 @@
#include "glass/networktables/NTStringChooser.h"
#include <fmt/format.h>
using namespace glass;
NTStringChooserModel::NTStringChooserModel(wpi::StringRef path)
NTStringChooserModel::NTStringChooserModel(std::string_view path)
: NTStringChooserModel{nt::GetDefaultInstance(), path} {}
NTStringChooserModel::NTStringChooserModel(NT_Inst inst, wpi::StringRef path)
NTStringChooserModel::NTStringChooserModel(NT_Inst inst, std::string_view path)
: m_nt{inst},
m_default{m_nt.GetEntry(path + "/default")},
m_selected{m_nt.GetEntry(path + "/selected")},
m_active{m_nt.GetEntry(path + "/active")},
m_options{m_nt.GetEntry(path + "/options")} {
m_default{m_nt.GetEntry(fmt::format("{}/default", path))},
m_selected{m_nt.GetEntry(fmt::format("{}/selected", path))},
m_active{m_nt.GetEntry(fmt::format("{}/active", path))},
m_options{m_nt.GetEntry(fmt::format("{}/options", path))} {
m_nt.AddListener(m_default);
m_nt.AddListener(m_selected);
m_nt.AddListener(m_active);
m_nt.AddListener(m_options);
}
void NTStringChooserModel::SetDefault(wpi::StringRef val) {
void NTStringChooserModel::SetDefault(std::string_view val) {
nt::SetEntryValue(m_default, nt::Value::MakeString(val));
}
void NTStringChooserModel::SetSelected(wpi::StringRef val) {
void NTStringChooserModel::SetSelected(std::string_view val) {
nt::SetEntryValue(m_selected, nt::Value::MakeString(val));
}
void NTStringChooserModel::SetActive(wpi::StringRef val) {
void NTStringChooserModel::SetActive(std::string_view val) {
nt::SetEntryValue(m_active, nt::Value::MakeString(val));
}

View File

@@ -4,16 +4,18 @@
#include "glass/networktables/NTSubsystem.h"
#include <fmt/format.h>
using namespace glass;
NTSubsystemModel::NTSubsystemModel(wpi::StringRef path)
NTSubsystemModel::NTSubsystemModel(std::string_view path)
: NTSubsystemModel(nt::GetDefaultInstance(), path) {}
NTSubsystemModel::NTSubsystemModel(NT_Inst instance, wpi::StringRef path)
NTSubsystemModel::NTSubsystemModel(NT_Inst instance, std::string_view path)
: m_nt(instance),
m_name(m_nt.GetEntry(path + "/.name")),
m_defaultCommand(m_nt.GetEntry(path + "/.default")),
m_currentCommand(m_nt.GetEntry(path + "/.command")) {
m_name(m_nt.GetEntry(fmt::format("{}/.name", path))),
m_defaultCommand(m_nt.GetEntry(fmt::format("{}/.default", path))),
m_currentCommand(m_nt.GetEntry(fmt::format("{}/.command", path))) {
m_nt.AddListener(m_name);
m_nt.AddListener(m_defaultCommand);
m_nt.AddListener(m_currentCommand);

View File

@@ -11,14 +11,15 @@
#include <cstring>
#include <initializer_list>
#include <memory>
#include <string_view>
#include <vector>
#include <fmt/format.h>
#include <imgui.h>
#include <ntcore_cpp.h>
#include <wpi/ArrayRef.h>
#include <wpi/Format.h>
#include <wpi/SmallString.h>
#include <wpi/StringRef.h>
#include <wpi/StringExtras.h>
#include <wpi/raw_ostream.h>
#include "glass/Context.h"
@@ -47,19 +48,7 @@ static std::string BooleanArrayToString(wpi::ArrayRef<int> in) {
}
static std::string DoubleArrayToString(wpi::ArrayRef<double> in) {
std::string rv;
wpi::raw_string_ostream os{rv};
os << '[';
bool first = true;
for (auto v : in) {
if (!first) {
os << ',';
}
first = false;
os << wpi::format("%.6f", v);
}
os << ']';
return rv;
return fmt::format("[{:.6f}]", fmt::join(in, ","));
}
static std::string StringArrayToString(wpi::ArrayRef<std::string> in) {
@@ -107,14 +96,14 @@ void NetworkTablesModel::Entry::UpdateValue() {
switch (value->type()) {
case NT_BOOLEAN:
if (!source) {
source = std::make_unique<DataSource>(wpi::Twine{"NT:"} + name);
source = std::make_unique<DataSource>(fmt::format("NT:{}", name));
}
source->SetValue(value->GetBoolean() ? 1 : 0);
source->SetDigital(true);
break;
case NT_DOUBLE:
if (!source) {
source = std::make_unique<DataSource>(wpi::Twine{"NT:"} + name);
source = std::make_unique<DataSource>(fmt::format("NT:{}", name));
}
source->SetValue(value->GetDouble());
source->SetDigital(false);
@@ -185,10 +174,10 @@ void NetworkTablesModel::Update() {
// rebuild tree
m_root.clear();
wpi::SmallVector<wpi::StringRef, 16> parts;
wpi::SmallVector<std::string_view, 16> parts;
for (auto& entry : m_sortedEntries) {
parts.clear();
wpi::StringRef{entry->name}.split(parts, '/', -1, false);
wpi::split(entry->name, parts, '/', -1, false);
// ignore a raw "/" key
if (parts.empty()) {
@@ -206,8 +195,8 @@ void NetworkTablesModel::Update() {
// path is from the beginning of the string to the end of the current
// part; this works because part is a reference to the internals of
// entry->name
nodes->back().path.assign(entry->name.data(),
part.end() - entry->name.data());
nodes->back().path.assign(
entry->name.data(), part.data() + part.size() - entry->name.data());
it = nodes->end() - 1;
}
nodes = &it->children;
@@ -229,33 +218,33 @@ bool NetworkTablesModel::Exists() {
return nt::IsConnected(m_inst);
}
static std::shared_ptr<nt::Value> StringToBooleanArray(wpi::StringRef in) {
in = in.trim();
static std::shared_ptr<nt::Value> StringToBooleanArray(std::string_view in) {
in = wpi::trim(in);
if (in.empty()) {
return nt::NetworkTableValue::MakeBooleanArray(
std::initializer_list<bool>{});
}
if (in.front() == '[') {
in = in.drop_front();
in.remove_prefix(1);
}
if (in.back() == ']') {
in = in.drop_back();
in.remove_suffix(1);
}
in = in.trim();
in = wpi::trim(in);
wpi::SmallVector<wpi::StringRef, 16> inSplit;
wpi::SmallVector<std::string_view, 16> inSplit;
wpi::SmallVector<int, 16> out;
in.split(inSplit, ',', -1, false);
wpi::split(in, inSplit, ',', -1, false);
for (auto val : inSplit) {
val = val.trim();
if (val.equals_lower("true")) {
val = wpi::trim(val);
if (wpi::equals_lower(val, "true")) {
out.emplace_back(1);
} else if (val.equals_lower("false")) {
} else if (wpi::equals_lower(val, "false")) {
out.emplace_back(0);
} else {
wpi::errs() << "GUI: NetworkTables: Could not understand value '" << val
<< "'\n";
fmt::print(stderr,
"GUI: NetworkTables: Could not understand value '{}'\n", val);
return nullptr;
}
}
@@ -263,33 +252,30 @@ static std::shared_ptr<nt::Value> StringToBooleanArray(wpi::StringRef in) {
return nt::NetworkTableValue::MakeBooleanArray(out);
}
static std::shared_ptr<nt::Value> StringToDoubleArray(wpi::StringRef in) {
in = in.trim();
static std::shared_ptr<nt::Value> StringToDoubleArray(std::string_view in) {
in = wpi::trim(in);
if (in.empty()) {
return nt::NetworkTableValue::MakeDoubleArray(
std::initializer_list<double>{});
}
if (in.front() == '[') {
in = in.drop_front();
in.remove_prefix(1);
}
if (in.back() == ']') {
in = in.drop_back();
in.remove_suffix(1);
}
in = in.trim();
in = wpi::trim(in);
wpi::SmallVector<wpi::StringRef, 16> inSplit;
wpi::SmallVector<std::string_view, 16> inSplit;
wpi::SmallVector<double, 16> out;
in.split(inSplit, ',', -1, false);
wpi::split(in, inSplit, ',', -1, false);
for (auto val : inSplit) {
val = val.trim();
wpi::SmallString<32> valStr = val;
double d;
if (std::sscanf(valStr.c_str(), "%lf", &d) == 1) {
out.emplace_back(d);
if (auto num = wpi::parse_float<double>(wpi::trim(val))) {
out.emplace_back(num.value());
} else {
wpi::errs() << "GUI: NetworkTables: Could not understand value '" << val
<< "'\n";
fmt::print(stderr,
"GUI: NetworkTables: Could not understand value '{}'\n", val);
return nullptr;
}
}
@@ -307,8 +293,8 @@ static int fromxdigit(char ch) {
}
}
static wpi::StringRef UnescapeString(wpi::StringRef source,
wpi::SmallVectorImpl<char>& buf) {
static std::string_view UnescapeString(std::string_view source,
wpi::SmallVectorImpl<char>& buf) {
assert(source.size() >= 2 && source.front() == '"' && source.back() == '"');
buf.clear();
buf.reserve(source.size() - 2);
@@ -342,36 +328,36 @@ static wpi::StringRef UnescapeString(wpi::StringRef source,
break;
}
}
return wpi::StringRef{buf.data(), buf.size()};
return {buf.data(), buf.size()};
}
static std::shared_ptr<nt::Value> StringToStringArray(wpi::StringRef in) {
in = in.trim();
static std::shared_ptr<nt::Value> StringToStringArray(std::string_view in) {
in = wpi::trim(in);
if (in.empty()) {
return nt::NetworkTableValue::MakeStringArray(
std::initializer_list<std::string>{});
}
if (in.front() == '[') {
in = in.drop_front();
in.remove_prefix(1);
}
if (in.back() == ']') {
in = in.drop_back();
in.remove_suffix(1);
}
in = in.trim();
in = wpi::trim(in);
wpi::SmallVector<wpi::StringRef, 16> inSplit;
wpi::SmallVector<std::string_view, 16> inSplit;
std::vector<std::string> out;
wpi::SmallString<32> buf;
in.split(inSplit, ',', -1, false);
wpi::split(in, inSplit, ',', -1, false);
for (auto val : inSplit) {
val = val.trim();
val = wpi::trim(val);
if (val.empty()) {
continue;
}
if (val.front() != '"' || val.back() != '"') {
wpi::errs() << "GUI: NetworkTables: Could not understand value '" << val
<< "'\n";
fmt::print(stderr,
"GUI: NetworkTables: Could not understand value '{}'\n", val);
return nullptr;
}
out.emplace_back(UnescapeString(val, buf));
@@ -421,7 +407,7 @@ static void EmitEntryValueReadonly(NetworkTablesModel::Entry& entry) {
static constexpr size_t kTextBufferSize = 4096;
static char* GetTextBuffer(wpi::StringRef in) {
static char* GetTextBuffer(std::string_view in) {
static char textBuffer[kTextBufferSize];
size_t len = (std::min)(in.size(), kTextBufferSize - 1);
std::memcpy(textBuffer, in.data(), len);
@@ -524,7 +510,7 @@ static void EmitParentContextMenu(const std::string& path,
if (path == "/") {
fullNewPath = path + nameBuffer;
} else {
fullNewPath = (path + wpi::Twine('/') + nameBuffer).str();
fullNewPath = fmt::format("{}/{}", path, nameBuffer);
}
ImGui::Text("Adding: %s", fullNewPath.c_str());

View File

@@ -6,18 +6,22 @@
#include <algorithm>
#include <fmt/format.h>
#include <ntcore_cpp.h>
#include <wpi/SmallString.h>
#include <wpi/StringExtras.h>
#include <wpigui.h>
using namespace glass;
NetworkTablesProvider::NetworkTablesProvider(const wpi::Twine& iniName)
NetworkTablesProvider::NetworkTablesProvider(std::string_view iniName)
: NetworkTablesProvider{iniName, nt::GetDefaultInstance()} {}
NetworkTablesProvider::NetworkTablesProvider(const wpi::Twine& iniName,
NetworkTablesProvider::NetworkTablesProvider(std::string_view iniName,
NT_Inst inst)
: Provider{iniName + "Window"}, m_nt{inst}, m_typeCache{iniName} {
: Provider{fmt::format("{}Window", iniName)},
m_nt{inst},
m_typeCache{iniName} {
m_nt.AddListener("", NT_NOTIFY_LOCAL | NT_NOTIFY_NEW | NT_NOTIFY_DELETE |
NT_NOTIFY_IMMEDIATE);
}
@@ -28,11 +32,11 @@ void NetworkTablesProvider::GlobalInit() {
}
void NetworkTablesProvider::DisplayMenu() {
wpi::SmallVector<wpi::StringRef, 6> path;
wpi::SmallVector<std::string_view, 6> path;
wpi::SmallString<64> name;
for (auto&& entry : m_viewEntries) {
path.clear();
wpi::StringRef{entry->name}.split(path, '/', -1, false);
wpi::split(entry->name, path, '/', -1, false);
bool fullDepth = true;
int depth = 0;
@@ -69,12 +73,12 @@ void NetworkTablesProvider::Update() {
// add/remove entries from NT changes
for (auto&& event : m_nt.PollListener()) {
// look for .type fields
wpi::StringRef eventName{event.name};
if (!eventName.endswith("/.type") || !event.value ||
std::string_view eventName{event.name};
if (!wpi::ends_with(eventName, "/.type") || !event.value ||
!event.value->IsString()) {
continue;
}
auto tableName = eventName.drop_back(6);
auto tableName = wpi::drop_back(eventName, 6);
// only handle ones where we have a builder
auto builderIt = m_typeMap.find(event.value->GetString());
@@ -117,14 +121,15 @@ void NetworkTablesProvider::Update() {
}
auto entry = GetOrCreateView(
builderIt->second, nt::GetEntry(m_nt.GetInstance(), id + "/.type"), id);
builderIt->second,
nt::GetEntry(m_nt.GetInstance(), fmt::format("{}/.type", id)), id);
if (entry) {
Show(entry, window.get());
}
}
}
void NetworkTablesProvider::Register(wpi::StringRef typeName,
void NetworkTablesProvider::Register(std::string_view typeName,
CreateModelFunc createModel,
CreateViewFunc createView) {
m_typeMap[typeName] = Builder{std::move(createModel), std::move(createView)};
@@ -153,9 +158,9 @@ void NetworkTablesProvider::Show(ViewEntry* entry, Window* window) {
if (!window) {
return;
}
if (wpi::StringRef{entry->name}.startswith("/SmartDashboard/")) {
window->SetDefaultName(wpi::StringRef{entry->name}.drop_front(16) +
" (SmartDashboard)");
if (wpi::starts_with(entry->name, "/SmartDashboard/")) {
window->SetDefaultName(
fmt::format("{} (SmartDashboard)", wpi::drop_front(entry->name, 16)));
}
entry->window = window;
@@ -171,7 +176,7 @@ void NetworkTablesProvider::Show(ViewEntry* entry, Window* window) {
}
NetworkTablesProvider::ViewEntry* NetworkTablesProvider::GetOrCreateView(
const Builder& builder, NT_Entry typeEntry, wpi::StringRef name) {
const Builder& builder, NT_Entry typeEntry, std::string_view name) {
// get view entry if it already exists
auto viewIt = FindViewEntry(name);
if (viewIt != m_viewEntries.end() && (*viewIt)->name == name) {

View File

@@ -4,14 +4,15 @@
#include "glass/networktables/NetworkTablesSettings.h"
#include <optional>
#include <string_view>
#include <utility>
#include <imgui.h>
#include <imgui_stdlib.h>
#include <ntcore_cpp.h>
#include <wpi/SmallVector.h>
#include <wpi/StringRef.h>
#include <wpi/raw_ostream.h>
#include <wpi/StringExtras.h>
#include "glass/Context.h"
@@ -55,14 +56,15 @@ void NetworkTablesSettings::Thread::Main() {
} while (mode != m_mode || dsClient != m_dsClient);
if (m_mode == 1) {
wpi::StringRef serverTeam{m_serverTeam};
unsigned int team;
if (!serverTeam.contains('.') && !serverTeam.getAsInteger(10, team)) {
nt::StartClientTeam(m_inst, team, NT_DEFAULT_PORT);
std::string_view serverTeam{m_serverTeam};
std::optional<unsigned int> team;
if (!wpi::contains(serverTeam, '.') &&
(team = wpi::parse_integer<unsigned int>(serverTeam, 10))) {
nt::StartClientTeam(m_inst, team.value(), NT_DEFAULT_PORT);
} else {
wpi::SmallVector<wpi::StringRef, 4> serverNames;
wpi::SmallVector<std::pair<wpi::StringRef, unsigned int>, 4> servers;
serverTeam.split(serverNames, ',', -1, false);
wpi::SmallVector<std::string_view, 4> serverNames;
wpi::SmallVector<std::pair<std::string_view, unsigned int>, 4> servers;
wpi::split(serverTeam, serverNames, ',', -1, false);
for (auto&& serverName : serverNames) {
servers.emplace_back(serverName, NT_DEFAULT_PORT);
}