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); | ||||
|  | ||||
|         for (const auto& e : fieldsSorted) | ||||
|         auto fields = findAllProtoFields(&f); | ||||
|         std::ranges::sort(fields, | ||||
|             [](const auto& o1, const auto& o2) | ||||
|             { | ||||
|             fmt::print("{}: {}\n", e, getProtoByString(&f, e)); | ||||
|                 return doj::alphanum_comp(o1.path(), o2.path()) < 0; | ||||
|             }); | ||||
|  | ||||
|         for (const auto& pf : fields) | ||||
|         { | ||||
|             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