mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
Update for jart/json.cpp change
This commit is contained in:
@@ -67,63 +67,55 @@ static bool JsonToWindow(const wpi::util::json& jfile, const char* filename) {
|
||||
std::string iniStr;
|
||||
wpi::util::raw_string_ostream ini{iniStr};
|
||||
|
||||
for (auto&& jsection : jfile.items()) {
|
||||
if (jsection.key() == "Docking") {
|
||||
for (auto&& [sect_key, sect_value] : jfile.get_object()) {
|
||||
if (sect_key == "Docking") {
|
||||
continue;
|
||||
}
|
||||
if (!jsection.value().is_object()) {
|
||||
ImGui::LogText("%s section %s is not object", filename,
|
||||
jsection.key().c_str());
|
||||
if (!sect_value.is_object()) {
|
||||
ImGui::LogText("%s section %s is not object", filename, sect_key.c_str());
|
||||
return false;
|
||||
}
|
||||
for (auto&& jsubsection : jsection.value().items()) {
|
||||
if (!jsubsection.value().is_object()) {
|
||||
for (auto&& [sub_key, sub_value] : sect_value.get_object()) {
|
||||
if (!sub_value.is_object()) {
|
||||
ImGui::LogText("%s section %s subsection %s is not object", filename,
|
||||
jsection.key().c_str(), jsubsection.key().c_str());
|
||||
sect_key.c_str(), sub_key.c_str());
|
||||
return false;
|
||||
}
|
||||
ini << '[' << jsection.key() << "][" << jsubsection.key() << "]\n";
|
||||
for (auto&& jkv : jsubsection.value().items()) {
|
||||
try {
|
||||
auto& value = jkv.value().get_ref<const std::string&>();
|
||||
ini << jkv.key() << '=' << value << "\n";
|
||||
} catch (wpi::util::json::exception&) {
|
||||
ini << '[' << sect_key << "][" << sub_key << "]\n";
|
||||
for (auto&& [key, value] : sub_value.get_object()) {
|
||||
if (!value.is_string()) {
|
||||
ImGui::LogText("%s section %s subsection %s value %s is not string",
|
||||
filename, jsection.key().c_str(),
|
||||
jsubsection.key().c_str(), jkv.key().c_str());
|
||||
filename, sect_key.c_str(), sub_key.c_str(),
|
||||
key.c_str());
|
||||
return false;
|
||||
}
|
||||
ini << key << '=' << value.get_string() << "\n";
|
||||
}
|
||||
ini << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
// emit Docking section last
|
||||
auto docking = jfile.find("Docking");
|
||||
if (docking != jfile.end()) {
|
||||
for (auto&& jsubsection : docking->items()) {
|
||||
if (!jsubsection.value().is_array()) {
|
||||
if (auto docking = jfile.lookup("Docking")) {
|
||||
for (auto&& [sub_key, sub_value] : docking->get_object()) {
|
||||
if (!sub_value.is_array()) {
|
||||
ImGui::LogText("%s section %s subsection %s is not array", filename,
|
||||
"Docking", jsubsection.key().c_str());
|
||||
"Docking", sub_key.c_str());
|
||||
return false;
|
||||
}
|
||||
ini << "[Docking][" << jsubsection.key() << "]\n";
|
||||
for (auto&& jv : jsubsection.value()) {
|
||||
try {
|
||||
auto& value = jv.get_ref<const std::string&>();
|
||||
ini << value << "\n";
|
||||
} catch (wpi::util::json::exception&) {
|
||||
ini << "[Docking][" << sub_key << "]\n";
|
||||
for (auto&& value : sub_value.get_array()) {
|
||||
if (!value.is_string()) {
|
||||
ImGui::LogText("%s section %s subsection %s value is not string",
|
||||
filename, "Docking", jsubsection.key().c_str());
|
||||
filename, "Docking", sub_key.c_str());
|
||||
return false;
|
||||
}
|
||||
ini << value.get_string() << "\n";
|
||||
}
|
||||
ini << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
ini.flush();
|
||||
|
||||
ImGui::LoadIniSettingsFromMemory(iniStr.data(), iniStr.size());
|
||||
return true;
|
||||
}
|
||||
@@ -135,12 +127,12 @@ static bool LoadWindowStorageImpl(const std::string& filename) {
|
||||
fileBuffer.error().message().c_str());
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return JsonToWindow(
|
||||
wpi::util::json::parse(fileBuffer.value()->GetCharBuffer()),
|
||||
filename.c_str());
|
||||
} catch (wpi::util::json::parse_error& e) {
|
||||
ImGui::LogText("Error loading %s: %s", filename.c_str(), e.what());
|
||||
auto buffer = fileBuffer.value()->GetCharBuffer();
|
||||
auto j = wpi::util::json::parse({buffer.data(), buffer.size()});
|
||||
if (j) {
|
||||
return JsonToWindow(*j, filename.c_str());
|
||||
} else {
|
||||
ImGui::LogText("Error loading %s: %s", filename.c_str(), j.error());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -154,12 +146,12 @@ static bool LoadStorageRootImpl(Context* ctx, const std::string& filename,
|
||||
return false;
|
||||
}
|
||||
auto [it, createdStorage] = ctx->storageRoots.try_emplace(rootName);
|
||||
try {
|
||||
it->second.FromJson(
|
||||
wpi::util::json::parse(fileBuffer.value()->GetCharBuffer()),
|
||||
filename.c_str());
|
||||
} catch (wpi::util::json::parse_error& e) {
|
||||
ImGui::LogText("Error loading %s: %s", filename.c_str(), e.what());
|
||||
auto buffer = fileBuffer.value()->GetCharBuffer();
|
||||
auto j = wpi::util::json::parse({buffer.data(), buffer.size()});
|
||||
if (j) {
|
||||
it->second.FromJson(*j, filename.c_str());
|
||||
} else {
|
||||
ImGui::LogText("Error loading %s: %s", filename.c_str(), j.error());
|
||||
if (createdStorage) {
|
||||
ctx->storageRoots.erase(it);
|
||||
}
|
||||
@@ -257,7 +249,7 @@ bool SaveWindowStorageImpl(const std::string& filename) {
|
||||
ec.message().c_str());
|
||||
return false;
|
||||
}
|
||||
WindowToJson().dump(os, 2);
|
||||
WindowToJson().marshal(os, true, 2);
|
||||
os << '\n';
|
||||
return true;
|
||||
}
|
||||
@@ -271,7 +263,7 @@ static bool SaveStorageRootImpl(Context* ctx, const std::string& filename,
|
||||
ec.message().c_str());
|
||||
return false;
|
||||
}
|
||||
storage.ToJson().dump(os, 2);
|
||||
storage.ToJson().marshal(os, true, 2);
|
||||
os << '\n';
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -348,7 +348,7 @@ void Storage::EraseChildren() {
|
||||
static bool JsonArrayToStorage(Storage::Value* valuePtr,
|
||||
const wpi::util::json& jarr,
|
||||
const char* filename) {
|
||||
auto& arr = jarr.get_ref<const wpi::util::json::array_t&>();
|
||||
auto& arr = jarr.get_array();
|
||||
if (arr.empty()) {
|
||||
ImGui::LogText("empty array in %s, ignoring", filename);
|
||||
return false;
|
||||
@@ -356,42 +356,45 @@ static bool JsonArrayToStorage(Storage::Value* valuePtr,
|
||||
|
||||
// guess array type from first element
|
||||
switch (arr[0].type()) {
|
||||
case wpi::util::json::value_t::boolean:
|
||||
case wpi::util::json::Type::Bool:
|
||||
if (valuePtr->type != Storage::Value::kBoolArray) {
|
||||
valuePtr->Reset(Storage::Value::kBoolArray);
|
||||
valuePtr->boolArray = new std::vector<int>();
|
||||
valuePtr->boolArrayDefault = nullptr;
|
||||
}
|
||||
break;
|
||||
case wpi::util::json::value_t::number_float:
|
||||
case wpi::util::json::Type::Float:
|
||||
case wpi::util::json::Type::Double:
|
||||
if (valuePtr->type != Storage::Value::kDoubleArray) {
|
||||
valuePtr->Reset(Storage::Value::kDoubleArray);
|
||||
valuePtr->doubleArray = new std::vector<double>();
|
||||
valuePtr->doubleArrayDefault = nullptr;
|
||||
}
|
||||
break;
|
||||
case wpi::util::json::value_t::number_integer:
|
||||
case wpi::util::json::value_t::number_unsigned:
|
||||
case wpi::util::json::Type::Int:
|
||||
if (valuePtr->type != Storage::Value::kInt64Array) {
|
||||
valuePtr->Reset(Storage::Value::kInt64Array);
|
||||
valuePtr->int64Array = new std::vector<int64_t>();
|
||||
valuePtr->int64ArrayDefault = nullptr;
|
||||
}
|
||||
break;
|
||||
case wpi::util::json::value_t::string:
|
||||
case wpi::util::json::Type::Uint:
|
||||
ImGui::LogText("too large of integer in %s, ignoring", filename);
|
||||
return false;
|
||||
case wpi::util::json::Type::String:
|
||||
if (valuePtr->type != Storage::Value::kStringArray) {
|
||||
valuePtr->Reset(Storage::Value::kStringArray);
|
||||
valuePtr->stringArray = new std::vector<std::string>();
|
||||
valuePtr->stringArrayDefault = nullptr;
|
||||
}
|
||||
break;
|
||||
case wpi::util::json::value_t::object:
|
||||
case wpi::util::json::Type::Object:
|
||||
if (valuePtr->type != Storage::Value::kChildArray) {
|
||||
valuePtr->Reset(Storage::Value::kChildArray);
|
||||
valuePtr->childArray = new std::vector<std::unique_ptr<Storage>>();
|
||||
}
|
||||
break;
|
||||
case wpi::util::json::value_t::array:
|
||||
case wpi::util::json::Type::Array:
|
||||
ImGui::LogText("nested array in %s, ignoring", filename);
|
||||
return false;
|
||||
default:
|
||||
@@ -402,47 +405,47 @@ static bool JsonArrayToStorage(Storage::Value* valuePtr,
|
||||
// loop over array to store elements
|
||||
for (auto jvalue : arr) {
|
||||
switch (jvalue.type()) {
|
||||
case wpi::util::json::value_t::boolean:
|
||||
case wpi::util::json::Type::Bool:
|
||||
if (valuePtr->type == Storage::Value::kBoolArray) {
|
||||
valuePtr->boolArray->push_back(jvalue.get<bool>());
|
||||
valuePtr->boolArray->push_back(jvalue.get_bool());
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case wpi::util::json::value_t::number_float:
|
||||
case wpi::util::json::Type::Float:
|
||||
if (valuePtr->type == Storage::Value::kDoubleArray) {
|
||||
valuePtr->doubleArray->push_back(jvalue.get<double>());
|
||||
valuePtr->doubleArray->push_back(jvalue.get_float());
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case wpi::util::json::value_t::number_integer:
|
||||
case wpi::util::json::Type::Double:
|
||||
if (valuePtr->type == Storage::Value::kDoubleArray) {
|
||||
valuePtr->doubleArray->push_back(jvalue.get_double());
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case wpi::util::json::Type::Int:
|
||||
if (valuePtr->type == Storage::Value::kInt64Array) {
|
||||
valuePtr->int64Array->push_back(jvalue.get<int64_t>());
|
||||
valuePtr->int64Array->push_back(jvalue.get_int());
|
||||
} else if (valuePtr->type == Storage::Value::kDoubleArray) {
|
||||
valuePtr->doubleArray->push_back(jvalue.get<int64_t>());
|
||||
valuePtr->doubleArray->push_back(jvalue.get_int());
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case wpi::util::json::value_t::number_unsigned:
|
||||
if (valuePtr->type == Storage::Value::kInt64Array) {
|
||||
valuePtr->int64Array->push_back(jvalue.get<uint64_t>());
|
||||
} else if (valuePtr->type == Storage::Value::kDoubleArray) {
|
||||
valuePtr->doubleArray->push_back(jvalue.get<uint64_t>());
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case wpi::util::json::value_t::string:
|
||||
case wpi::util::json::Type::Uint:
|
||||
ImGui::LogText("too large of integer in %s, ignoring", filename);
|
||||
return false;
|
||||
case wpi::util::json::Type::String:
|
||||
if (valuePtr->type == Storage::Value::kStringArray) {
|
||||
valuePtr->stringArray->emplace_back(
|
||||
jvalue.get_ref<const std::string&>());
|
||||
valuePtr->stringArray->emplace_back(jvalue.get_string());
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case wpi::util::json::value_t::object:
|
||||
case wpi::util::json::Type::Object:
|
||||
if (valuePtr->type == Storage::Value::kChildArray) {
|
||||
valuePtr->childArray->emplace_back(std::make_unique<Storage>());
|
||||
valuePtr->childArray->back()->FromJson(jvalue, filename);
|
||||
@@ -450,7 +453,7 @@ static bool JsonArrayToStorage(Storage::Value* valuePtr,
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case wpi::util::json::value_t::array:
|
||||
case wpi::util::json::Type::Array:
|
||||
ImGui::LogText("nested array in %s, ignoring", filename);
|
||||
return false;
|
||||
default:
|
||||
@@ -474,53 +477,52 @@ bool Storage::FromJson(const wpi::util::json& json, const char* filename) {
|
||||
ImGui::LogText("non-object in %s", filename);
|
||||
return false;
|
||||
}
|
||||
for (auto&& jkv : json.items()) {
|
||||
auto& valuePtr = m_values[jkv.key()];
|
||||
for (auto&& [key, jvalue] : json.get_object()) {
|
||||
auto& valuePtr = m_values[key];
|
||||
bool created = false;
|
||||
if (!valuePtr) {
|
||||
valuePtr = std::make_unique<Value>();
|
||||
created = true;
|
||||
}
|
||||
auto& jvalue = jkv.value();
|
||||
switch (jvalue.type()) {
|
||||
case wpi::util::json::value_t::boolean:
|
||||
case wpi::util::json::Type::Bool:
|
||||
valuePtr->Reset(Value::kBool);
|
||||
valuePtr->boolVal = jvalue.get<bool>();
|
||||
valuePtr->boolVal = jvalue.get_bool();
|
||||
break;
|
||||
case wpi::util::json::value_t::number_float:
|
||||
case wpi::util::json::Type::Float:
|
||||
valuePtr->Reset(Value::kDouble);
|
||||
valuePtr->doubleVal = jvalue.get<double>();
|
||||
valuePtr->doubleVal = jvalue.get_float();
|
||||
break;
|
||||
case wpi::util::json::value_t::number_integer:
|
||||
case wpi::util::json::Type::Double:
|
||||
valuePtr->Reset(Value::kDouble);
|
||||
valuePtr->doubleVal = jvalue.get_double();
|
||||
break;
|
||||
case wpi::util::json::Type::Int:
|
||||
valuePtr->Reset(Value::kInt64);
|
||||
valuePtr->int64Val = jvalue.get<int64_t>();
|
||||
valuePtr->int64Val = jvalue.get_int();
|
||||
break;
|
||||
case wpi::util::json::value_t::number_unsigned:
|
||||
valuePtr->Reset(Value::kInt64);
|
||||
valuePtr->int64Val = jvalue.get<uint64_t>();
|
||||
break;
|
||||
case wpi::util::json::value_t::string:
|
||||
case wpi::util::json::Type::String:
|
||||
valuePtr->Reset(Value::kString);
|
||||
valuePtr->stringVal = jvalue.get_ref<const std::string&>();
|
||||
valuePtr->stringVal = jvalue.get_string();
|
||||
break;
|
||||
case wpi::util::json::value_t::object:
|
||||
case wpi::util::json::Type::Object:
|
||||
if (valuePtr->type != Value::kChild) {
|
||||
valuePtr->Reset(Value::kChild);
|
||||
valuePtr->child = new Storage;
|
||||
}
|
||||
valuePtr->child->FromJson(jvalue, filename); // recurse
|
||||
break;
|
||||
case wpi::util::json::value_t::array:
|
||||
case wpi::util::json::Type::Array:
|
||||
if (!JsonArrayToStorage(valuePtr.get(), jvalue, filename)) {
|
||||
if (created) {
|
||||
m_values.erase(jkv.key());
|
||||
m_values.erase(key);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ImGui::LogText("null value in %s, ignoring", filename);
|
||||
if (created) {
|
||||
m_values.erase(jkv.key());
|
||||
m_values.erase(key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -545,8 +547,9 @@ wpi::util::json StorageToJsonArray<std::unique_ptr<Storage>>(
|
||||
jarr.emplace_back(v->ToJson());
|
||||
}
|
||||
// remove any trailing empty items
|
||||
while (!jarr.empty() && jarr.back().empty()) {
|
||||
jarr.get_ref<wpi::util::json::array_t&>().pop_back();
|
||||
auto& jarrArr = jarr.get_array();
|
||||
while (!jarrArr.empty() && jarrArr.back().empty()) {
|
||||
jarrArr.pop_back();
|
||||
}
|
||||
return jarr;
|
||||
}
|
||||
@@ -602,7 +605,7 @@ wpi::util::json Storage::ToJson() const {
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
j.emplace(kv.first, std::move(jelem));
|
||||
j[kv.first] = std::move(jelem);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
@@ -451,16 +451,14 @@ void FieldInfo::LoadImage() {
|
||||
|
||||
bool FieldInfo::LoadJson(std::span<const char> is, std::string_view filename) {
|
||||
// parse file
|
||||
wpi::util::json j;
|
||||
try {
|
||||
j = wpi::util::json::parse(is);
|
||||
} catch (const wpi::util::json::parse_error& e) {
|
||||
wpi::util::print(stderr, "GUI: JSON: could not parse: {}\n", e.what());
|
||||
auto j = wpi::util::json::parse({is.data(), is.size()});
|
||||
if (!j) {
|
||||
wpi::util::print(stderr, "GUI: JSON: could not parse: {}\n", j.error());
|
||||
return false;
|
||||
}
|
||||
|
||||
// top level must be an object
|
||||
if (!j.is_object()) {
|
||||
if (!j->is_object()) {
|
||||
std::fputs("GUI: JSON: does not contain a top object\n", stderr);
|
||||
return false;
|
||||
}
|
||||
@@ -468,8 +466,8 @@ bool FieldInfo::LoadJson(std::span<const char> is, std::string_view filename) {
|
||||
// image filename
|
||||
std::string image;
|
||||
try {
|
||||
image = j.at("field-image").get<std::string>();
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
image = j->at("field-image").get_string();
|
||||
} catch (const std::logic_error& e) {
|
||||
wpi::util::print(stderr, "GUI: JSON: could not read field-image: {}\n",
|
||||
e.what());
|
||||
return false;
|
||||
@@ -478,11 +476,11 @@ bool FieldInfo::LoadJson(std::span<const char> is, std::string_view filename) {
|
||||
// corners
|
||||
int top, left, bottom, right;
|
||||
try {
|
||||
top = j.at("field-corners").at("top-left").at(1).get<int>();
|
||||
left = j.at("field-corners").at("top-left").at(0).get<int>();
|
||||
bottom = j.at("field-corners").at("bottom-right").at(1).get<int>();
|
||||
right = j.at("field-corners").at("bottom-right").at(0).get<int>();
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
top = j->at("field-corners").at("top-left").at(1).get_int();
|
||||
left = j->at("field-corners").at("top-left").at(0).get_int();
|
||||
bottom = j->at("field-corners").at("bottom-right").at(1).get_int();
|
||||
right = j->at("field-corners").at("bottom-right").at(0).get_int();
|
||||
} catch (const std::logic_error& e) {
|
||||
wpi::util::print(stderr, "GUI: JSON: could not read field-corners: {}\n",
|
||||
e.what());
|
||||
return false;
|
||||
@@ -492,9 +490,9 @@ bool FieldInfo::LoadJson(std::span<const char> is, std::string_view filename) {
|
||||
float width;
|
||||
float height;
|
||||
try {
|
||||
width = j.at("field-size").at(0).get<float>();
|
||||
height = j.at("field-size").at(1).get<float>();
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
width = j->at("field-size").at(0).get_float();
|
||||
height = j->at("field-size").at(1).get_float();
|
||||
} catch (const std::logic_error& e) {
|
||||
wpi::util::print(stderr, "GUI: JSON: could not read field-size: {}\n",
|
||||
e.what());
|
||||
return false;
|
||||
@@ -503,8 +501,8 @@ bool FieldInfo::LoadJson(std::span<const char> is, std::string_view filename) {
|
||||
// units for size
|
||||
std::string unit;
|
||||
try {
|
||||
unit = j.at("field-unit").get<std::string>();
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
unit = j->at("field-unit").get_string();
|
||||
} catch (const std::logic_error& e) {
|
||||
wpi::util::print(stderr, "GUI: JSON: could not read field-unit: {}\n",
|
||||
e.what());
|
||||
return false;
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
|
||||
#include "wpi/util/StringMap.hpp"
|
||||
#include "wpi/util/iterator_range.hpp"
|
||||
#include "wpi/util/json_fwd.hpp"
|
||||
|
||||
namespace wpi::util {
|
||||
class json;
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpi::glass {
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ NTStringChooserModel::NTStringChooserModel(wpi::nt::NetworkTableInstance inst,
|
||||
.Subscribe("")},
|
||||
m_selectedPub{m_inst.GetStringTopic(fmt::format("{}/selected", path))
|
||||
.PublishEx(wpi::nt::StringTopic::TYPE_STRING,
|
||||
{{"retained", true}})},
|
||||
wpi::util::json::object("retained", true))},
|
||||
m_active{
|
||||
m_inst.GetStringTopic(fmt::format("{}/active", path)).Subscribe("")},
|
||||
m_options{m_inst.GetStringArrayTopic(fmt::format("{}/options", path))
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
@@ -110,18 +109,16 @@ void NetworkTablesModel::Entry::UpdateInfo(wpi::nt::TopicInfo&& info_) {
|
||||
properties = info.GetProperties();
|
||||
|
||||
persistent = false;
|
||||
auto it = properties.find("persistent");
|
||||
if (it != properties.end()) {
|
||||
if (auto v = it->get_ptr<const bool*>()) {
|
||||
persistent = *v;
|
||||
if (auto prop = properties.lookup("persistent")) {
|
||||
if (prop->is_bool()) {
|
||||
persistent = prop->get_bool();
|
||||
}
|
||||
}
|
||||
|
||||
retained = false;
|
||||
it = properties.find("retained");
|
||||
if (it != properties.end()) {
|
||||
if (auto v = it->get_ptr<const bool*>()) {
|
||||
retained = *v;
|
||||
if (auto prop = properties.lookup("retained")) {
|
||||
if (prop->is_bool()) {
|
||||
retained = prop->get_bool();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -642,7 +639,7 @@ static void UpdateJsonValueSource(NetworkTablesModel& model,
|
||||
const wpi::util::json& j,
|
||||
std::string_view name, int64_t time) {
|
||||
switch (j.type()) {
|
||||
case wpi::util::json::value_t::object: {
|
||||
case wpi::util::json::Type::Object: {
|
||||
if (!out->valueChildrenMap) {
|
||||
out->valueChildren.clear();
|
||||
out->valueChildrenMap = true;
|
||||
@@ -652,19 +649,19 @@ static void UpdateJsonValueSource(NetworkTablesModel& model,
|
||||
elems[out->valueChildren[i].name] = i;
|
||||
}
|
||||
bool added = false;
|
||||
for (auto&& kv : j.items()) {
|
||||
auto it = elems.find(kv.key());
|
||||
for (auto&& [key, value] : j.get_object()) {
|
||||
auto it = elems.find(key);
|
||||
if (it != elems.end()) {
|
||||
auto& child = out->valueChildren[it->second];
|
||||
UpdateJsonValueSource(model, &child, kv.value(), child.path, time);
|
||||
UpdateJsonValueSource(model, &child, value, child.path, time);
|
||||
elems.erase(it);
|
||||
} else {
|
||||
added = true;
|
||||
out->valueChildren.emplace_back();
|
||||
auto& child = out->valueChildren.back();
|
||||
child.name = kv.key();
|
||||
child.name = key;
|
||||
child.path = fmt::format("{}/{}", name, child.name);
|
||||
UpdateJsonValueSource(model, &child, kv.value(), child.path, time);
|
||||
UpdateJsonValueSource(model, &child, value, child.path, time);
|
||||
}
|
||||
}
|
||||
// erase unmatched keys
|
||||
@@ -680,12 +677,13 @@ static void UpdateJsonValueSource(NetworkTablesModel& model,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case wpi::util::json::value_t::array: {
|
||||
case wpi::util::json::Type::Array: {
|
||||
auto& arr = j.get_array();
|
||||
if (out->valueChildrenMap) {
|
||||
out->valueChildren.clear();
|
||||
out->valueChildrenMap = false;
|
||||
}
|
||||
out->valueChildren.resize(j.size());
|
||||
out->valueChildren.resize(arr.size());
|
||||
unsigned int i = 0;
|
||||
for (auto&& child : out->valueChildren) {
|
||||
if (child.name.empty()) {
|
||||
@@ -693,29 +691,24 @@ static void UpdateJsonValueSource(NetworkTablesModel& model,
|
||||
child.path = fmt::format("{}{}", name, child.name);
|
||||
}
|
||||
// recurse
|
||||
UpdateJsonValueSource(model, &child, j[i++], child.path, time);
|
||||
UpdateJsonValueSource(model, &child, arr[i++], child.path, time);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case wpi::util::json::value_t::string:
|
||||
out->value =
|
||||
wpi::nt::Value::MakeString(j.get_ref<const std::string&>(), time);
|
||||
case wpi::util::json::Type::String:
|
||||
out->value = wpi::nt::Value::MakeString(j.get_string(), time);
|
||||
out->UpdateFromValue(model, name, "");
|
||||
break;
|
||||
case wpi::util::json::value_t::boolean:
|
||||
out->value = wpi::nt::Value::MakeBoolean(j.get<bool>(), time);
|
||||
case wpi::util::json::Type::Bool:
|
||||
out->value = wpi::nt::Value::MakeBoolean(j.get_bool(), time);
|
||||
out->UpdateFromValue(model, name, "");
|
||||
break;
|
||||
case wpi::util::json::value_t::number_integer:
|
||||
out->value = wpi::nt::Value::MakeInteger(j.get<int64_t>(), time);
|
||||
case wpi::util::json::Type::Int:
|
||||
out->value = wpi::nt::Value::MakeInteger(j.get_int(), time);
|
||||
out->UpdateFromValue(model, name, "");
|
||||
break;
|
||||
case wpi::util::json::value_t::number_unsigned:
|
||||
out->value = wpi::nt::Value::MakeInteger(j.get<uint64_t>(), time);
|
||||
out->UpdateFromValue(model, name, "");
|
||||
break;
|
||||
case wpi::util::json::value_t::number_float:
|
||||
out->value = wpi::nt::Value::MakeDouble(j.get<double>(), time);
|
||||
case wpi::util::json::Type::Float:
|
||||
out->value = wpi::nt::Value::MakeDouble(j.get_double(), time);
|
||||
out->UpdateFromValue(model, name, "");
|
||||
break;
|
||||
default:
|
||||
@@ -877,12 +870,8 @@ void NetworkTablesModel::ValueSource::UpdateFromValue(
|
||||
}
|
||||
case NT_STRING:
|
||||
if (typeStr == "json") {
|
||||
try {
|
||||
UpdateJsonValueSource(model, this,
|
||||
wpi::util::json::parse(value.GetString()), name,
|
||||
value.last_change());
|
||||
} catch (wpi::util::json::exception&) {
|
||||
// ignore
|
||||
if (auto j = wpi::util::json::parse(value.GetString())) {
|
||||
UpdateJsonValueSource(model, this, *j, name, value.last_change());
|
||||
}
|
||||
} else {
|
||||
valueChildren.clear();
|
||||
|
||||
Reference in New Issue
Block a user