mirror of
				https://github.com/TomHarte/CLK.git
				synced 2025-10-31 05:16:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			121 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //
 | |
| //  MultiConfigurable.cpp
 | |
| //  Clock Signal
 | |
| //
 | |
| //  Created by Thomas Harte on 09/02/2018.
 | |
| //  Copyright 2018 Thomas Harte. All rights reserved.
 | |
| //
 | |
| 
 | |
| #include "MultiConfigurable.hpp"
 | |
| 
 | |
| #include <algorithm>
 | |
| 
 | |
| using namespace Analyser::Dynamic;
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| class MultiStruct: public Reflection::Struct {
 | |
| 	public:
 | |
| 		MultiStruct(const std::vector<Configurable::Device *> &devices) : devices_(devices) {
 | |
| 			for(auto device: devices) {
 | |
| 				options_.emplace_back(device->get_options());
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		void apply() {
 | |
| 			auto options = options_.begin();
 | |
| 			for(auto device: devices_) {
 | |
| 				device->set_options(*options);
 | |
| 				++options;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		std::vector<std::string> all_keys() const final {
 | |
| 			std::set<std::string> keys;
 | |
| 			for(auto &options: options_) {
 | |
| 				const auto new_keys = options->all_keys();
 | |
| 				keys.insert(new_keys.begin(), new_keys.end());
 | |
| 			}
 | |
| 			return std::vector<std::string>(keys.begin(), keys.end());
 | |
| 		}
 | |
| 
 | |
| 		std::vector<std::string> values_for(const std::string &name) const final {
 | |
| 			std::set<std::string> values;
 | |
| 			for(auto &options: options_) {
 | |
| 				const auto new_values = options->values_for(name);
 | |
| 				values.insert(new_values.begin(), new_values.end());
 | |
| 			}
 | |
| 			return std::vector<std::string>(values.begin(), values.end());
 | |
| 		}
 | |
| 
 | |
| 		const std::type_info *type_of(const std::string &name) const final {
 | |
| 			for(auto &options: options_) {
 | |
| 				auto info = options->type_of(name);
 | |
| 				if(info) return info;
 | |
| 			}
 | |
| 			return nullptr;
 | |
| 		}
 | |
| 
 | |
| 		size_t count_of(const std::string &name) const final {
 | |
| 			for(auto &options: options_) {
 | |
| 				auto info = options->type_of(name);
 | |
| 				if(info) return options->count_of(name);
 | |
| 			}
 | |
| 			return 0;
 | |
| 		}
 | |
| 
 | |
| 		const void *get(const std::string &name) const final {
 | |
| 			for(auto &options: options_) {
 | |
| 				auto value = options->get(name);
 | |
| 				if(value) return value;
 | |
| 			}
 | |
| 			return nullptr;
 | |
| 		}
 | |
| 
 | |
| 		void *get(const std::string &name) final {
 | |
| 			for(auto &options: options_) {
 | |
| 				auto value = options->get(name);
 | |
| 				if(value) return value;
 | |
| 			}
 | |
| 			return nullptr;
 | |
| 		}
 | |
| 
 | |
| 		void set(const std::string &name, const void *value, size_t offset) final {
 | |
| 			const auto safe_type = type_of(name);
 | |
| 			if(!safe_type) return;
 | |
| 
 | |
| 			// Set this property only where the child's type is the same as that
 | |
| 			// which was returned from here for type_of.
 | |
| 			for(auto &options: options_) {
 | |
| 				const auto type = options->type_of(name);
 | |
| 				if(!type) continue;
 | |
| 
 | |
| 				if(*type == *safe_type) {
 | |
| 					options->set(name, value, offset);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 	private:
 | |
| 		const std::vector<Configurable::Device *> &devices_;
 | |
| 		std::vector<std::unique_ptr<Reflection::Struct>> options_;
 | |
| };
 | |
| 
 | |
| }
 | |
| 
 | |
| MultiConfigurable::MultiConfigurable(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines) {
 | |
| 	for(const auto &machine: machines) {
 | |
| 		Configurable::Device *device = machine->configurable_device();
 | |
| 		if(device) devices_.push_back(device);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void MultiConfigurable::set_options(const std::unique_ptr<Reflection::Struct> &str) {
 | |
| 	const auto options = dynamic_cast<MultiStruct *>(str.get());
 | |
| 	options->apply();
 | |
| }
 | |
| 
 | |
| std::unique_ptr<Reflection::Struct> MultiConfigurable::get_options() {
 | |
| 	return std::make_unique<MultiStruct>(devices_);
 | |
| }
 |