mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	Crudely bodge image writes into working.
This commit is contained in:
		| @@ -451,6 +451,29 @@ bool Config::applyOption(const std::string& name, const std::string value) | ||||
|     return optionInfo.usesValue; | ||||
| } | ||||
|  | ||||
| void Config::applyOptionsFile(const std::string& data) | ||||
| { | ||||
|     if (!data.empty()) | ||||
|     { | ||||
|         for (auto setting : split(data, '\n')) | ||||
|         { | ||||
|             setting = trimWhitespace(setting); | ||||
|             if (setting.size() == 0) | ||||
|                 continue; | ||||
|             if (setting[0] == '#') | ||||
|                 continue; | ||||
|  | ||||
|             auto equals = setting.find('='); | ||||
|             if (equals == std::string::npos) | ||||
|                 error("Malformed setting line '{}'", setting); | ||||
|  | ||||
|             auto key = setting.substr(0, equals); | ||||
|             auto value = setting.substr(equals + 1); | ||||
|             globalConfig().set(key, value); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void Config::applyDefaultOptions() | ||||
| { | ||||
|     std::set<const OptionGroupProto*> appliedOptionGroups; | ||||
|   | ||||
| @@ -142,6 +142,7 @@ public: | ||||
|     bool isOptionValid(const OptionProto& option); | ||||
|     void applyOption(const OptionInfo& optionInfo); | ||||
|     bool applyOption(const std::string& name, const std::string value = ""); | ||||
|     void applyOptionsFile(const std::string& data); | ||||
|     void applyDefaultOptions(); | ||||
|     void clearOptions(); | ||||
|  | ||||
|   | ||||
| @@ -540,12 +540,13 @@ findAllPossibleProtoFields(const google::protobuf::Descriptor* descriptor) | ||||
|     return fields; | ||||
| } | ||||
|  | ||||
| std::vector<ProtoField> findAllProtoFields(google::protobuf::Message* message) | ||||
| std::vector<ProtoField> findAllProtoFields( | ||||
|     const google::protobuf::Message* message) | ||||
| { | ||||
|     std::vector<ProtoField> allFields; | ||||
|  | ||||
|     std::function<void(google::protobuf::Message*, const std::string&)> | ||||
|         recurse = [&](auto* message, const auto& name) | ||||
|     std::function<void(const google::protobuf::Message*, const std::string&)> | ||||
|         recurse = [&](const auto* message, const auto& name) | ||||
|     { | ||||
|         const auto* reflection = message->GetReflection(); | ||||
|         std::vector<const google::protobuf::FieldDescriptor*> fields; | ||||
| @@ -565,18 +566,19 @@ std::vector<ProtoField> findAllProtoFields(google::protobuf::Message* message) | ||||
|                     const auto n = fmt::format("{}[{}]", basename, i); | ||||
|                     if (shouldRecurse(f)) | ||||
|                         recurse( | ||||
|                             reflection->MutableRepeatedMessage(message, f, i), | ||||
|                             n); | ||||
|                             &reflection->GetRepeatedMessage(*message, f, i), n); | ||||
|                     else | ||||
|                         allFields.push_back(ProtoField(n, message, f, i)); | ||||
|                         allFields.push_back(ProtoField( | ||||
|                             n, (google::protobuf::Message*)message, f, i)); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (shouldRecurse(f)) | ||||
|                     recurse(reflection->MutableMessage(message, f), basename); | ||||
|                     recurse(&reflection->GetMessage(*message, f), basename); | ||||
|                 else | ||||
|                     allFields.push_back(ProtoField(basename, message, f)); | ||||
|                     allFields.push_back(ProtoField( | ||||
|                         basename, (google::protobuf::Message*)message, f)); | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| @@ -584,3 +586,12 @@ std::vector<ProtoField> findAllProtoFields(google::protobuf::Message* message) | ||||
|     recurse(message, ""); | ||||
|     return allFields; | ||||
| } | ||||
|  | ||||
| std::string renderProtoAsConfig(const google::protobuf::Message* message) | ||||
| { | ||||
|     auto allFields = findAllProtoFields(message); | ||||
|     std::stringstream ss; | ||||
|     for (const auto& field : allFields) | ||||
|         ss << field.path() << "=" << field.get() << "\n"; | ||||
|     return ss.str(); | ||||
| } | ||||
|   | ||||
| @@ -72,7 +72,9 @@ extern std::map<std::string, const google::protobuf::FieldDescriptor*> | ||||
| findAllPossibleProtoFields(const google::protobuf::Descriptor* descriptor); | ||||
|  | ||||
| extern std::vector<ProtoField> findAllProtoFields( | ||||
|     google::protobuf::Message* message); | ||||
|     const google::protobuf::Message* message); | ||||
| extern std::string renderProtoAsConfig( | ||||
|     const google::protobuf::Message* message); | ||||
|  | ||||
| template <class T> | ||||
| static inline const T parseProtoBytes(const std::string_view& bytes) | ||||
|   | ||||
| @@ -11,9 +11,7 @@ std::unique_ptr<FluxSource> FluxSource::create(Config& config) | ||||
| { | ||||
|     if (!config.hasFluxSource()) | ||||
|         error("no flux source configured"); | ||||
|     auto fluxSource = create(config->flux_source()); | ||||
|     globalConfig().base()->MergeFrom(fluxSource->getExtraConfig()); | ||||
|     return fluxSource; | ||||
|     return create(config->flux_source()); | ||||
| } | ||||
|  | ||||
| std::unique_ptr<FluxSource> FluxSource::create(const FluxSourceProto& config) | ||||
|   | ||||
| @@ -111,6 +111,8 @@ public: | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         _extraConfig.mutable_layout()->add_layoutdata()->set_sector_size(524); | ||||
|  | ||||
|         image->setGeometry({.numCylinders = numCylinders, | ||||
|             .numHeads = numHeads, | ||||
|             .numSectors = 12, | ||||
|   | ||||
| @@ -54,6 +54,7 @@ int mainWrite(int argc, const char* argv[]) | ||||
|  | ||||
|     auto reader = ImageReader::create(globalConfig()); | ||||
|     std::shared_ptr<Image> image = reader->readImage(); | ||||
|     globalConfig().overrides()->MergeFrom(reader->getExtraConfig()); | ||||
|  | ||||
|     auto diskLayout = createDiskLayout(); | ||||
|     auto encoder = Arch::createEncoder(globalConfig()); | ||||
|   | ||||
| @@ -18,9 +18,25 @@ using namespace hex; | ||||
|  | ||||
| static DynamicSettingFactory settings("fluxengine.settings"); | ||||
|  | ||||
| static constexpr const char* DEFAULT_CUSTOM_SETTINGS = R"R( | ||||
| # These settings will override the ones above. | ||||
| # Here are some useful ones: | ||||
| # decoder.retries=0 | ||||
| # drive.revolutions=1.2 | ||||
| )R"; | ||||
|  | ||||
| ConfigView::ConfigView(): | ||||
|     View::Window("fluxengine.view.config.name", ICON_VS_COMPASS) | ||||
| { | ||||
|     Events::SetSystemConfig::subscribe( | ||||
|         [](std::string customConfig) | ||||
|         { | ||||
|             auto customSetting = settings.get<std::string>("systemProperties"); | ||||
|             customSetting = | ||||
|                 "# These settings were set by a file and\n" | ||||
|                 "# may contradict the ones above (it's a bug).\n" + | ||||
|                 customConfig; | ||||
|         }); | ||||
| } | ||||
|  | ||||
| static void emitOptions(DynamicSetting<std::string>& setting, | ||||
| @@ -336,11 +352,33 @@ void ConfigView::drawContent() | ||||
|  | ||||
|     ImGui::SeparatorText("fluxengine.view.config.customProperties"_lang); | ||||
|  | ||||
|     auto customSetting = settings.get<std::string>("custom"); | ||||
|     std::string buffer = customSetting; | ||||
|     if (ImGui::InputTextMultiline("##customProperties", | ||||
|             buffer, | ||||
|             ImGui::GetContentRegionAvail(), | ||||
|             ImGuiInputTextFlags_None)) | ||||
|         customSetting = buffer; | ||||
|     if (ImGui::BeginTabBar("customconfig", ImGuiTabBarFlags_None)) | ||||
|     { | ||||
|         DEFER(ImGui::EndTabBar()); | ||||
|         if (ImGui::BeginTabItem("User")) | ||||
|         { | ||||
|             DEFER(ImGui::EndTabItem()); | ||||
|  | ||||
|             auto setting = | ||||
|                 settings.get<std::string>("custom", DEFAULT_CUSTOM_SETTINGS); | ||||
|             std::string buffer = setting; | ||||
|             if (ImGui::InputTextMultiline("##customProperties", | ||||
|                     buffer, | ||||
|                     ImGui::GetContentRegionAvail(), | ||||
|                     ImGuiInputTextFlags_None)) | ||||
|                 setting = buffer; | ||||
|         } | ||||
|         if (ImGui::BeginTabItem("System")) | ||||
|         { | ||||
|             DEFER(ImGui::EndTabItem()); | ||||
|  | ||||
|             auto setting = settings.get<std::string>("systemProperties"); | ||||
|             std::string buffer = setting; | ||||
|             if (ImGui::InputTextMultiline("##systemProperties", | ||||
|                     buffer, | ||||
|                     ImGui::GetContentRegionAvail(), | ||||
|                     ImGuiInputTextFlags_None)) | ||||
|                 setting = buffer; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #include "lib/core/globals.h" | ||||
| #include "lib/core/utils.h" | ||||
| #include "lib/config/config.h" | ||||
| #include "lib/config/proto.h" | ||||
| #include "lib/data/disk.h" | ||||
| #include "lib/data/image.h" | ||||
| #include "lib/fluxsource/fluxsource.h" | ||||
| @@ -50,7 +51,7 @@ static bool formattingSupported; | ||||
| static std::map<std::string, Datastore::Device> devices; | ||||
| static std::shared_ptr<const DiskLayout> diskLayout; | ||||
|  | ||||
| static void wtRebuildConfiguration(); | ||||
| static void wtRebuildConfiguration(bool useCustom); | ||||
|  | ||||
| static void workerThread_cb() | ||||
| { | ||||
| @@ -271,7 +272,11 @@ void Datastore::init() | ||||
|                 hex::Region{startOffset, endOffset - startOffset}); | ||||
|         }); | ||||
|  | ||||
|     runOnWorkerThread(wtRebuildConfiguration); | ||||
|     runOnWorkerThread( | ||||
|         [] | ||||
|         { | ||||
|             wtRebuildConfiguration(true); | ||||
|         }); | ||||
| } | ||||
|  | ||||
| bool Datastore::isBusy() | ||||
| @@ -338,7 +343,7 @@ static void wtClearDiskData() | ||||
|         }); | ||||
| } | ||||
|  | ||||
| void wtRebuildConfiguration() | ||||
| void wtRebuildConfiguration(bool withCustom = false) | ||||
| { | ||||
|     /* Reset and apply the format configuration. */ | ||||
|  | ||||
| @@ -392,26 +397,10 @@ void wtRebuildConfiguration() | ||||
|  | ||||
|     /* Custom settings. */ | ||||
|  | ||||
|     auto customSettings = readSettingFromUiThread<std::string>("custom", ""); | ||||
|     if (!customSettings.empty()) | ||||
|     { | ||||
|         for (auto setting : split(customSettings, '\n')) | ||||
|         { | ||||
|             setting = trimWhitespace(setting); | ||||
|             if (setting.size() == 0) | ||||
|                 continue; | ||||
|             if (setting[0] == '#') | ||||
|                 continue; | ||||
|  | ||||
|             auto equals = setting.find('='); | ||||
|             if (equals == std::string::npos) | ||||
|                 error("Malformed setting line '{}'", setting); | ||||
|  | ||||
|             auto key = setting.substr(0, equals); | ||||
|             auto value = setting.substr(equals + 1); | ||||
|             globalConfig().set(key, value); | ||||
|         } | ||||
|     } | ||||
|     globalConfig().applyOptionsFile( | ||||
|         readSettingFromUiThread<std::string>("systemProperties", "")); | ||||
|     globalConfig().applyOptionsFile( | ||||
|         readSettingFromUiThread<std::string>("custom", "")); | ||||
|  | ||||
|     /* Finalise the options. */ | ||||
|  | ||||
| @@ -540,7 +529,7 @@ void Datastore::beginRead(bool rereadBadSectors) | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 wtRebuildConfiguration(); | ||||
|                 wtRebuildConfiguration(true); | ||||
|                 if (!rereadBadSectors) | ||||
|                     wtClearDiskData(); | ||||
|  | ||||
| @@ -576,7 +565,7 @@ void Datastore::beginWrite() | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 wtRebuildConfiguration(); | ||||
|                 wtRebuildConfiguration(true); | ||||
|                 wtWaitForUiThreadToCatchUp(); | ||||
|  | ||||
|                 auto fluxSinkFactory = FluxSinkFactory::create(globalConfig()); | ||||
| @@ -642,7 +631,7 @@ void Datastore::reset() | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 wtRebuildConfiguration(); | ||||
|                 wtRebuildConfiguration(false); | ||||
|                 wtClearDiskData(); | ||||
|                 wtWaitForUiThreadToCatchUp(); | ||||
|             } | ||||
| @@ -682,7 +671,7 @@ void Datastore::writeImage(const std::fs::path& path) | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 wtRebuildConfiguration(); | ||||
|                 wtRebuildConfiguration(true); | ||||
|                 wtWaitForUiThreadToCatchUp(); | ||||
|                 globalConfig().setImageWriter(path.string()); | ||||
|                 ImageWriter::create(globalConfig()) | ||||
| @@ -708,11 +697,23 @@ void Datastore::readImage(const std::fs::path& path) | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 wtRebuildConfiguration(); | ||||
|                 wtRebuildConfiguration(true); | ||||
|                 wtWaitForUiThreadToCatchUp(); | ||||
|                 globalConfig().setImageReader(path.string()); | ||||
|                 std::shared_ptr<Image> image = | ||||
|                     ImageReader::create(globalConfig())->readImage(); | ||||
|                 auto imageReader = ImageReader::create(globalConfig()); | ||||
|                 std::shared_ptr<Image> image = imageReader->readImage(); | ||||
|  | ||||
|                 const auto& extraConfig = imageReader->getExtraConfig(); | ||||
|                 auto customConfig = renderProtoAsConfig(&extraConfig); | ||||
|  | ||||
|                 /* Update the setting, and then rebuild the config again as it | ||||
|                  * will have changed. */ | ||||
|  | ||||
|                 wtRunSynchronouslyOnUiThread((std::function<void()>)[=] { | ||||
|                     Events::SetSystemConfig::post(customConfig); | ||||
|                 }); | ||||
|                 wtRebuildConfiguration(true); | ||||
|                 wtWaitForUiThreadToCatchUp(); | ||||
|  | ||||
|                 auto disk = wtMakeDiskDataFromImage(image); | ||||
|                 hex::TaskManager::doLater( | ||||
| @@ -741,7 +742,7 @@ void Datastore::writeFluxFile(const std::fs::path& path) | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 wtRebuildConfiguration(); | ||||
|                 wtRebuildConfiguration(true); | ||||
|                 wtWaitForUiThreadToCatchUp(); | ||||
|  | ||||
|                 if (!disk || !disk->image) | ||||
| @@ -777,7 +778,7 @@ void Datastore::createBlankImage() | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 wtRebuildConfiguration(); | ||||
|                 wtRebuildConfiguration(false); | ||||
|                 wtClearDiskData(); | ||||
|                 wtWaitForUiThreadToCatchUp(); | ||||
|  | ||||
| @@ -794,6 +795,7 @@ void Datastore::createBlankImage() | ||||
|                 hex::TaskManager::doLater( | ||||
|                     [=] | ||||
|                     { | ||||
|                         Events::SetSystemConfig::post(""); | ||||
|                         ::disk = disk; | ||||
|                     }); | ||||
|             } | ||||
|   | ||||
| @@ -39,6 +39,7 @@ namespace Events | ||||
|     EVENT_DEF(DiskActivityNotification, DiskActivityType, unsigned, unsigned); | ||||
|     EVENT_DEF(OperationStart, std::string); | ||||
|     EVENT_DEF(OperationStop, OperationState); | ||||
|     EVENT_DEF(SetSystemConfig, std::string); | ||||
| } | ||||
|  | ||||
| #define DEFER(_stmt) \ | ||||
|   | ||||
| @@ -226,6 +226,49 @@ static void test_findallfields(void) | ||||
|             "u64"})); | ||||
| } | ||||
|  | ||||
| static void test_rendering(void) | ||||
| { | ||||
|     std::string s = R"M( | ||||
| 		i64: -1 | ||||
| 		i32: -2 | ||||
| 		u64: 3 | ||||
| 		u32: 4 | ||||
| 		d: 5.5 | ||||
| 		f: 6.7 | ||||
| 		m { | ||||
| 			s: "string" | ||||
| 		} | ||||
| 		r { | ||||
| 			s: "val2" | ||||
| 		} | ||||
| 		r { | ||||
| 			s: "val3" | ||||
| 		} | ||||
| 		secondoption { | ||||
| 			s: "2" | ||||
| 		} | ||||
| 	)M"; | ||||
|  | ||||
|     TestProto proto; | ||||
|     if (!google::protobuf::TextFormat::MergeFromString(cleanup(s), &proto)) | ||||
|         error("couldn't load test proto"); | ||||
|  | ||||
|     auto config = renderProtoAsConfig(&proto); | ||||
|  | ||||
|     AssertThat(cleanup(config), Equals(cleanup(R"M( | ||||
|             i64=-1 | ||||
|             i32=-2 | ||||
|             u64=3 | ||||
|             u32=4 | ||||
|             d=5.5 | ||||
|             m.s=string | ||||
|             r[0].s=val2 | ||||
|             r[1].s=val3 | ||||
|             secondoption.s=2 | ||||
|             f=6.7 | ||||
|             )M"))); | ||||
| } | ||||
|  | ||||
| int main(int argc, const char* argv[]) | ||||
| { | ||||
|     try | ||||
| @@ -237,6 +280,7 @@ int main(int argc, const char* argv[]) | ||||
|         test_fields(); | ||||
|         test_options(); | ||||
|         test_findallfields(); | ||||
|         test_rendering(); | ||||
|     } | ||||
|     catch (const ErrorException& e) | ||||
|     { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user