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() | static void doDoc() | ||||||
| { | { | ||||||
|     const auto fields = findAllPossibleProtoFields(globalConfig().base()->GetDescriptor()); |     const auto fields = | ||||||
|  |         findAllPossibleProtoFields(globalConfig().base()->GetDescriptor()); | ||||||
|     for (const auto field : fields) |     for (const auto field : fields) | ||||||
|     { |     { | ||||||
|         const std::string& path = field.first; |         const std::string& path = field.first; | ||||||
|   | |||||||
| @@ -157,7 +157,7 @@ static ProtoField resolveProtoPath( | |||||||
|     if (!field) |     if (!field) | ||||||
|         fail(); |         fail(); | ||||||
|  |  | ||||||
|     return ProtoField(message, field, index); |     return ProtoField(path, message, field, index); | ||||||
| } | } | ||||||
|  |  | ||||||
| ProtoField makeProtoPath( | ProtoField makeProtoPath( | ||||||
| @@ -292,6 +292,10 @@ void ProtoField::set(const std::string& value) | |||||||
|                     parseEnum(_field, value)); |                     parseEnum(_field, value)); | ||||||
|                 break; |                 break; | ||||||
|  |  | ||||||
|  |             case google::protobuf::FieldDescriptor::TYPE_MESSAGE: | ||||||
|  |                 error("'{}' is a message and can't be directly set", | ||||||
|  |                     _field->name()); | ||||||
|  |  | ||||||
|             default: |             default: | ||||||
|                 error("can't set this config value type"); |                 error("can't set this config value type"); | ||||||
|         } |         } | ||||||
| @@ -339,6 +343,11 @@ void ProtoField::set(const std::string& value) | |||||||
|                     _message, _field, parseEnum(_field, value)); |                     _message, _field, parseEnum(_field, value)); | ||||||
|                 break; |                 break; | ||||||
|  |  | ||||||
|  |             case google::protobuf::FieldDescriptor::TYPE_MESSAGE: | ||||||
|  |                 error("'{}[{}]' is a message and can't be directly set", | ||||||
|  |                     _field->name(), | ||||||
|  |                     _index); | ||||||
|  |  | ||||||
|             default: |             default: | ||||||
|                 error("can't set this config value type"); |                 error("can't set this config value type"); | ||||||
|         } |         } | ||||||
| @@ -384,7 +393,8 @@ std::string ProtoField::get() const | |||||||
|                 return reflection->GetRepeatedString(*_message, _field, _index); |                 return reflection->GetRepeatedString(*_message, _field, _index); | ||||||
|  |  | ||||||
|             case google::protobuf::FieldDescriptor::TYPE_MESSAGE: |             case google::protobuf::FieldDescriptor::TYPE_MESSAGE: | ||||||
|                 error("cannot fetch message value"); |                 error("'{}' is a message and can't be directly fetched", | ||||||
|  |                     _field->name()); | ||||||
|  |  | ||||||
|             default: |             default: | ||||||
|                 error("unknown field type when fetching repeated field '{}'", |                 error("unknown field type when fetching repeated field '{}'", | ||||||
| @@ -431,7 +441,9 @@ std::string ProtoField::get() const | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             case google::protobuf::FieldDescriptor::TYPE_MESSAGE: |             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: |             default: | ||||||
|                 error("unknown field type when fetching '{}'", _field->name()); |                 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, | void setProtoByString(google::protobuf::Message* message, | ||||||
|     const std::string& path, |     const std::string& path, | ||||||
|     const std::string& value) |     const std::string& value) | ||||||
| @@ -494,17 +548,16 @@ findAllPossibleProtoFields(const google::protobuf::Descriptor* descriptor) | |||||||
|     return fields; |     return fields; | ||||||
| } | } | ||||||
|  |  | ||||||
| std::map<std::string, const google::protobuf::FieldDescriptor*> | std::vector<ProtoField> findAllProtoFields(google::protobuf::Message* message) | ||||||
| findAllProtoFields(const 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&)> |     std::function<void(google::protobuf::Message*, const std::string&)> | ||||||
|         recurse = [&](auto& message, const auto& name) |         recurse = [&](auto* message, const auto& name) | ||||||
|     { |     { | ||||||
|         const auto* reflection = message.GetReflection(); |         const auto* reflection = message->GetReflection(); | ||||||
|         std::vector<const google::protobuf::FieldDescriptor*> fields; |         std::vector<const google::protobuf::FieldDescriptor*> fields; | ||||||
|         reflection->ListFields(message, &fields); |         reflection->ListFields(*message, &fields); | ||||||
|  |  | ||||||
|         for (const auto* f : fields) |         for (const auto* f : fields) | ||||||
|         { |         { | ||||||
| @@ -515,22 +568,23 @@ findAllProtoFields(const google::protobuf::Message& message) | |||||||
|  |  | ||||||
|             if (f->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) |             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); |                     const auto n = fmt::format("{}[{}]", basename, i); | ||||||
|                     if (shouldRecurse(f)) |                     if (shouldRecurse(f)) | ||||||
|                         recurse( |                         recurse( | ||||||
|                             reflection->GetRepeatedMessage(message, f, i), n); |                             reflection->MutableRepeatedMessage(message, f, i), | ||||||
|  |                             n); | ||||||
|                     else |                     else | ||||||
|                         allFields[n] = f; |                         allFields.push_back(ProtoField(n, message, f, i)); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 if (shouldRecurse(f)) |                 if (shouldRecurse(f)) | ||||||
|                     recurse(reflection->GetMessage(message, f), basename); |                     recurse(reflection->MutableMessage(message, f), basename); | ||||||
|                 else |                 else | ||||||
|                     allFields[basename] = f; |                     allFields.push_back(ProtoField(basename, message, f)); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|   | |||||||
| @@ -17,9 +17,11 @@ public: | |||||||
| class ProtoField | class ProtoField | ||||||
| { | { | ||||||
| public: | public: | ||||||
|     ProtoField(google::protobuf::Message* message, |     ProtoField(const std::string& path, | ||||||
|  |         google::protobuf::Message* message, | ||||||
|         const google::protobuf::FieldDescriptor* field, |         const google::protobuf::FieldDescriptor* field, | ||||||
|         int index): |         int index = -1): | ||||||
|  |         _path(path), | ||||||
|         _message(message), |         _message(message), | ||||||
|         _field(field), |         _field(field), | ||||||
|         _index(index) |         _index(index) | ||||||
| @@ -28,11 +30,24 @@ public: | |||||||
|  |  | ||||||
|     void set(const std::string& value); |     void set(const std::string& value); | ||||||
|     std::string get() const; |     std::string get() const; | ||||||
|  |     google::protobuf::Message* getMessage() const; | ||||||
|  |     std::string getBytes() const; | ||||||
|  |  | ||||||
|     bool operator==(const ProtoField& other) const = default; |     bool operator==(const ProtoField& other) const = default; | ||||||
|     std::strong_ordering 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: | private: | ||||||
|  |     std::string _path; | ||||||
|     google::protobuf::Message* _message; |     google::protobuf::Message* _message; | ||||||
|     const google::protobuf::FieldDescriptor* _field; |     const google::protobuf::FieldDescriptor* _field; | ||||||
|     int _index; |     int _index; | ||||||
| @@ -56,8 +71,8 @@ extern std::set<unsigned> iterate(unsigned start, unsigned count); | |||||||
| extern std::map<std::string, const google::protobuf::FieldDescriptor*> | extern std::map<std::string, const google::protobuf::FieldDescriptor*> | ||||||
| findAllPossibleProtoFields(const google::protobuf::Descriptor* descriptor); | findAllPossibleProtoFields(const google::protobuf::Descriptor* descriptor); | ||||||
|  |  | ||||||
| extern std::map<std::string, const google::protobuf::FieldDescriptor*> | extern std::vector<ProtoField> findAllProtoFields( | ||||||
| findAllProtoFields(const google::protobuf::Message& message); |     google::protobuf::Message* message); | ||||||
|  |  | ||||||
| template <class T> | template <class T> | ||||||
| static inline const T parseProtoBytes(const std::string_view& bytes) | static inline const T parseProtoBytes(const std::string_view& bytes) | ||||||
|   | |||||||
| @@ -29,7 +29,8 @@ static unsigned getTrackStep() | |||||||
|             { |             { | ||||||
|                 case DRIVETYPE_40TRACK: |                 case DRIVETYPE_40TRACK: | ||||||
|                     error( |                     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"); |                         "drive"); | ||||||
|  |  | ||||||
|                 case DRIVETYPE_80TRACK: |                 case DRIVETYPE_80TRACK: | ||||||
| @@ -37,7 +38,8 @@ static unsigned getTrackStep() | |||||||
|  |  | ||||||
|                 case DRIVETYPE_APPLE2: |                 case DRIVETYPE_APPLE2: | ||||||
|                     error( |                     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"); |                         "drive"); | ||||||
|             } |             } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -24,14 +24,26 @@ int mainFluxfileLs(int argc, const char* argv[]) | |||||||
|         fmt::print("Contents of {}:\n", filename); |         fmt::print("Contents of {}:\n", filename); | ||||||
|         FluxFileProto f = loadFl2File(filename); |         FluxFileProto f = loadFl2File(filename); | ||||||
|  |  | ||||||
|         auto fields = findAllProtoFields(f); |         auto fields = findAllProtoFields(&f); | ||||||
| 		std::set<std::string, doj::alphanum_less<std::string>> fieldsSorted; |         std::ranges::sort(fields, | ||||||
|         for (const auto& e : fields) |             [](const auto& o1, const auto& o2) | ||||||
| 			fieldsSorted.insert(e.first); |             { | ||||||
|  |                 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/config", | ||||||
|                     "lib/core", |                     "lib/core", | ||||||
|                     "lib/fluxsource+proto_lib", |                     "lib/fluxsource+proto_lib", | ||||||
|  |                     "dep/alphanum", | ||||||
|                 ], |                 ], | ||||||
|             ), |             ), | ||||||
|         ) |         ) | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
| #include "lib/config/config.pb.h" | #include "lib/config/config.pb.h" | ||||||
| #include "lib/config/proto.h" | #include "lib/config/proto.h" | ||||||
| #include "snowhouse/snowhouse.h" | #include "snowhouse/snowhouse.h" | ||||||
|  | #include "dep/alphanum/alphanum.h" | ||||||
| #include <google/protobuf/text_format.h> | #include <google/protobuf/text_format.h> | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
| #include <regex> | #include <regex> | ||||||
| @@ -206,10 +207,11 @@ static void test_findallfields(void) | |||||||
|     if (!google::protobuf::TextFormat::MergeFromString(cleanup(s), &proto)) |     if (!google::protobuf::TextFormat::MergeFromString(cleanup(s), &proto)) | ||||||
|         error("couldn't load test proto"); |         error("couldn't load test proto"); | ||||||
|  |  | ||||||
|     auto fields = findAllProtoFields(proto); |     auto fields = findAllProtoFields(&proto); | ||||||
|     std::vector<std::string> fieldNames; |     std::vector<std::string> fieldNames; | ||||||
|     for (const auto& e : fields) |     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, |     AssertThat(fieldNames, | ||||||
|         Equals(std::vector<std::string>{"d", |         Equals(std::vector<std::string>{"d", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user