mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-24 11:11:02 -07:00
More overhauling of the proto layer; fluxfile ls now works.
This commit is contained in:
@@ -264,7 +264,8 @@ static void doShowConfig()
|
||||
|
||||
static void doDoc()
|
||||
{
|
||||
const auto fields = findAllPossibleProtoFields(globalConfig().base()->GetDescriptor());
|
||||
const auto fields =
|
||||
findAllPossibleProtoFields(globalConfig().base()->GetDescriptor());
|
||||
for (const auto field : fields)
|
||||
{
|
||||
const std::string& path = field.first;
|
||||
|
||||
@@ -157,7 +157,7 @@ static ProtoField resolveProtoPath(
|
||||
if (!field)
|
||||
fail();
|
||||
|
||||
return ProtoField(message, field, index);
|
||||
return ProtoField(path, message, field, index);
|
||||
}
|
||||
|
||||
ProtoField makeProtoPath(
|
||||
@@ -292,6 +292,10 @@ void ProtoField::set(const std::string& value)
|
||||
parseEnum(_field, value));
|
||||
break;
|
||||
|
||||
case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
|
||||
error("'{}' is a message and can't be directly set",
|
||||
_field->name());
|
||||
|
||||
default:
|
||||
error("can't set this config value type");
|
||||
}
|
||||
@@ -339,6 +343,11 @@ void ProtoField::set(const std::string& value)
|
||||
_message, _field, parseEnum(_field, value));
|
||||
break;
|
||||
|
||||
case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
|
||||
error("'{}[{}]' is a message and can't be directly set",
|
||||
_field->name(),
|
||||
_index);
|
||||
|
||||
default:
|
||||
error("can't set this config value type");
|
||||
}
|
||||
@@ -384,7 +393,8 @@ std::string ProtoField::get() const
|
||||
return reflection->GetRepeatedString(*_message, _field, _index);
|
||||
|
||||
case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
|
||||
error("cannot fetch message value");
|
||||
error("'{}' is a message and can't be directly fetched",
|
||||
_field->name());
|
||||
|
||||
default:
|
||||
error("unknown field type when fetching repeated field '{}'",
|
||||
@@ -431,7 +441,9 @@ std::string ProtoField::get() const
|
||||
}
|
||||
|
||||
case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
|
||||
error("cannot fetch message value");
|
||||
error("'{}[{}]' is a message and can't be directly set",
|
||||
_field->name(),
|
||||
_index);
|
||||
|
||||
default:
|
||||
error("unknown field type when fetching '{}'", _field->name());
|
||||
@@ -439,6 +451,48 @@ std::string ProtoField::get() const
|
||||
}
|
||||
}
|
||||
|
||||
google::protobuf::Message* ProtoField::getMessage() const
|
||||
{
|
||||
const auto* reflection = _message->GetReflection();
|
||||
if (_field->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED)
|
||||
{
|
||||
if (_index == -1)
|
||||
error("field '{}' is repeated but no index is provided",
|
||||
_field->name());
|
||||
|
||||
return reflection->MutableRepeatedMessage(_message, _field, _index);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_index != -1)
|
||||
error("field '{}' is not repeated but an index is provided",
|
||||
_field->name());
|
||||
|
||||
return reflection->MutableMessage(_message, _field);
|
||||
}
|
||||
}
|
||||
|
||||
std::string ProtoField::getBytes() const
|
||||
{
|
||||
const auto* reflection = _message->GetReflection();
|
||||
if (_field->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED)
|
||||
{
|
||||
if (_index == -1)
|
||||
error("field '{}' is repeated but no index is provided",
|
||||
_field->name());
|
||||
|
||||
return reflection->GetRepeatedString(*_message, _field, _index);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_index != -1)
|
||||
error("field '{}' is not repeated but an index is provided",
|
||||
_field->name());
|
||||
|
||||
return reflection->GetString(*_message, _field);
|
||||
}
|
||||
}
|
||||
|
||||
void setProtoByString(google::protobuf::Message* message,
|
||||
const std::string& path,
|
||||
const std::string& value)
|
||||
@@ -494,17 +548,16 @@ findAllPossibleProtoFields(const google::protobuf::Descriptor* descriptor)
|
||||
return fields;
|
||||
}
|
||||
|
||||
std::map<std::string, const google::protobuf::FieldDescriptor*>
|
||||
findAllProtoFields(const google::protobuf::Message& message)
|
||||
std::vector<ProtoField> findAllProtoFields(google::protobuf::Message* message)
|
||||
{
|
||||
std::map<std::string, const google::protobuf::FieldDescriptor*> allFields;
|
||||
std::vector<ProtoField> allFields;
|
||||
|
||||
std::function<void(const google::protobuf::Message&, const std::string&)>
|
||||
recurse = [&](auto& message, const auto& name)
|
||||
std::function<void(google::protobuf::Message*, const std::string&)>
|
||||
recurse = [&](auto* message, const auto& name)
|
||||
{
|
||||
const auto* reflection = message.GetReflection();
|
||||
const auto* reflection = message->GetReflection();
|
||||
std::vector<const google::protobuf::FieldDescriptor*> fields;
|
||||
reflection->ListFields(message, &fields);
|
||||
reflection->ListFields(*message, &fields);
|
||||
|
||||
for (const auto* f : fields)
|
||||
{
|
||||
@@ -515,22 +568,23 @@ findAllProtoFields(const google::protobuf::Message& message)
|
||||
|
||||
if (f->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED)
|
||||
{
|
||||
for (int i = 0; i < reflection->FieldSize(message, f); i++)
|
||||
for (int i = 0; i < reflection->FieldSize(*message, f); i++)
|
||||
{
|
||||
const auto n = fmt::format("{}[{}]", basename, i);
|
||||
if (shouldRecurse(f))
|
||||
recurse(
|
||||
reflection->GetRepeatedMessage(message, f, i), n);
|
||||
reflection->MutableRepeatedMessage(message, f, i),
|
||||
n);
|
||||
else
|
||||
allFields[n] = f;
|
||||
allFields.push_back(ProtoField(n, message, f, i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shouldRecurse(f))
|
||||
recurse(reflection->GetMessage(message, f), basename);
|
||||
recurse(reflection->MutableMessage(message, f), basename);
|
||||
else
|
||||
allFields[basename] = f;
|
||||
allFields.push_back(ProtoField(basename, message, f));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -17,9 +17,11 @@ public:
|
||||
class ProtoField
|
||||
{
|
||||
public:
|
||||
ProtoField(google::protobuf::Message* message,
|
||||
ProtoField(const std::string& path,
|
||||
google::protobuf::Message* message,
|
||||
const google::protobuf::FieldDescriptor* field,
|
||||
int index):
|
||||
int index = -1):
|
||||
_path(path),
|
||||
_message(message),
|
||||
_field(field),
|
||||
_index(index)
|
||||
@@ -28,11 +30,24 @@ public:
|
||||
|
||||
void set(const std::string& value);
|
||||
std::string get() const;
|
||||
google::protobuf::Message* getMessage() const;
|
||||
std::string getBytes() const;
|
||||
|
||||
bool operator==(const ProtoField& other) const = default;
|
||||
std::strong_ordering operator<=>(const ProtoField& other) const = default;
|
||||
|
||||
const std::string& path() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
const google::protobuf::FieldDescriptor* descriptor() const
|
||||
{
|
||||
return _field;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _path;
|
||||
google::protobuf::Message* _message;
|
||||
const google::protobuf::FieldDescriptor* _field;
|
||||
int _index;
|
||||
@@ -56,8 +71,8 @@ extern std::set<unsigned> iterate(unsigned start, unsigned count);
|
||||
extern std::map<std::string, const google::protobuf::FieldDescriptor*>
|
||||
findAllPossibleProtoFields(const google::protobuf::Descriptor* descriptor);
|
||||
|
||||
extern std::map<std::string, const google::protobuf::FieldDescriptor*>
|
||||
findAllProtoFields(const google::protobuf::Message& message);
|
||||
extern std::vector<ProtoField> findAllProtoFields(
|
||||
google::protobuf::Message* message);
|
||||
|
||||
template <class T>
|
||||
static inline const T parseProtoBytes(const std::string_view& bytes)
|
||||
|
||||
@@ -29,7 +29,8 @@ static unsigned getTrackStep()
|
||||
{
|
||||
case DRIVETYPE_40TRACK:
|
||||
error(
|
||||
"you can't read/write an 80 track image from/to a 40 track "
|
||||
"you can't read/write an 80 track image from/to a 40 "
|
||||
"track "
|
||||
"drive");
|
||||
|
||||
case DRIVETYPE_80TRACK:
|
||||
@@ -37,7 +38,8 @@ static unsigned getTrackStep()
|
||||
|
||||
case DRIVETYPE_APPLE2:
|
||||
error(
|
||||
"you can't read/write an 80 track image from/to an Apple II "
|
||||
"you can't read/write an 80 track image from/to an "
|
||||
"Apple II "
|
||||
"drive");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,14 +24,26 @@ int mainFluxfileLs(int argc, const char* argv[])
|
||||
fmt::print("Contents of {}:\n", filename);
|
||||
FluxFileProto f = loadFl2File(filename);
|
||||
|
||||
auto fields = findAllProtoFields(f);
|
||||
std::set<std::string, doj::alphanum_less<std::string>> fieldsSorted;
|
||||
for (const auto& e : fields)
|
||||
fieldsSorted.insert(e.first);
|
||||
auto fields = findAllProtoFields(&f);
|
||||
std::ranges::sort(fields,
|
||||
[](const auto& o1, const auto& o2)
|
||||
{
|
||||
return doj::alphanum_comp(o1.path(), o2.path()) < 0;
|
||||
});
|
||||
|
||||
for (const auto& e : fieldsSorted)
|
||||
for (const auto& pf : fields)
|
||||
{
|
||||
fmt::print("{}: {}\n", e, getProtoByString(&f, e));
|
||||
auto path = pf.path();
|
||||
if (pf.descriptor()->options().GetExtension(::isflux))
|
||||
{
|
||||
Fluxmap fluxmap(pf.getBytes());
|
||||
fmt::print("{}: {:0.3f} ms of flux in {} bytes\n",
|
||||
path,
|
||||
fluxmap.duration() / 1000000.0,
|
||||
fluxmap.bytes());
|
||||
}
|
||||
else
|
||||
fmt::print("{}: {}\n", path, pf.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ export(
|
||||
"lib/config",
|
||||
"lib/core",
|
||||
"lib/fluxsource+proto_lib",
|
||||
"dep/alphanum",
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "lib/config/config.pb.h"
|
||||
#include "lib/config/proto.h"
|
||||
#include "snowhouse/snowhouse.h"
|
||||
#include "dep/alphanum/alphanum.h"
|
||||
#include <google/protobuf/text_format.h>
|
||||
#include <assert.h>
|
||||
#include <regex>
|
||||
@@ -206,10 +207,11 @@ static void test_findallfields(void)
|
||||
if (!google::protobuf::TextFormat::MergeFromString(cleanup(s), &proto))
|
||||
error("couldn't load test proto");
|
||||
|
||||
auto fields = findAllProtoFields(proto);
|
||||
auto fields = findAllProtoFields(&proto);
|
||||
std::vector<std::string> fieldNames;
|
||||
for (const auto& e : fields)
|
||||
fieldNames.push_back(e.first);
|
||||
fieldNames.push_back(e.path());
|
||||
std::ranges::sort(fieldNames, doj::alphanum_less<std::string>());
|
||||
|
||||
AssertThat(fieldNames,
|
||||
Equals(std::vector<std::string>{"d",
|
||||
|
||||
Reference in New Issue
Block a user