mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			115 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "globals.h"
 | |
| #include "proto.h"
 | |
| #include "fmt/format.h"
 | |
| 
 | |
| Config config;
 | |
| 
 | |
| static double toDouble(const std::string& value)
 | |
| {
 | |
| 	size_t idx;
 | |
| 	double d = std::stod(value, &idx);
 | |
| 	if (value[idx] != '\0')
 | |
| 		Error() << fmt::format("invalid number '{}'", value);
 | |
| 	return d;
 | |
| }
 | |
| 
 | |
| static int64_t toInt64(const std::string& value)
 | |
| {
 | |
| 	size_t idx;
 | |
| 	int64_t d = std::stoll(value, &idx);
 | |
| 	if (value[idx] != '\0')
 | |
| 		Error() << fmt::format("invalid number '{}'", value);
 | |
| 	return d;
 | |
| }
 | |
| 
 | |
| static uint64_t toUint64(const std::string& value)
 | |
| {
 | |
| 	size_t idx;
 | |
| 	uint64_t d = std::stoull(value, &idx);
 | |
| 	if (value[idx] != '\0')
 | |
| 		Error() << fmt::format("invalid number '{}'", value);
 | |
| 	return d;
 | |
| }
 | |
| 
 | |
| void setProtoByString(google::protobuf::Message* message, const std::string& path, const std::string& value)
 | |
| {
 | |
| 	std::string::size_type dot = path.rfind('.');
 | |
| 	std::string leading = (dot == std::string::npos) ? "" : path.substr(0, dot);
 | |
| 	std::string trailing = (dot == std::string::npos) ? path : path.substr(dot+1);
 | |
| 
 | |
| 	const auto* descriptor = message->GetDescriptor();
 | |
| 
 | |
| 	std::string item;
 | |
|     std::stringstream ss(leading);
 | |
|     while (std::getline(ss, item, '.'))
 | |
| 	{
 | |
| 		const auto* field = descriptor->FindFieldByName(item);
 | |
| 		if (!field)
 | |
| 			Error() << fmt::format("no such config field '{}' in '{}'", item, path);
 | |
| 		if (field->type() != google::protobuf::FieldDescriptor::TYPE_MESSAGE)
 | |
| 			Error() << fmt::format("config field '{}' in '{}' is not a message", item, path);
 | |
| 
 | |
| 		const auto* reflection = message->GetReflection();
 | |
| 		switch (field->label())
 | |
| 		{
 | |
| 			case google::protobuf::FieldDescriptor::LABEL_OPTIONAL:
 | |
| 				message = reflection->MutableMessage(message, field);
 | |
| 				break;
 | |
| 
 | |
| 			case google::protobuf::FieldDescriptor::LABEL_REPEATED:
 | |
| 				if (reflection->FieldSize(*message, field) == 0)
 | |
| 					message = reflection->AddMessage(message, field);
 | |
| 				else
 | |
| 					message = reflection->MutableRepeatedMessage(message, field, 0);
 | |
| 				break;
 | |
| 		}
 | |
| 
 | |
| 		descriptor = message->GetDescriptor();
 | |
|     }
 | |
| 
 | |
| 	const auto* field = descriptor->FindFieldByName(trailing);
 | |
| 	if (!field)
 | |
| 		Error() << fmt::format("no such config field '{}' in '{}'", item, path);
 | |
| 
 | |
| 	const auto* reflection = message->GetReflection();
 | |
| 	switch (field->type())
 | |
| 	{
 | |
| 		case google::protobuf::FieldDescriptor::TYPE_DOUBLE:
 | |
| 			reflection->SetDouble(message, field, toDouble(value));
 | |
| 			break;
 | |
| 
 | |
| 		case google::protobuf::FieldDescriptor::TYPE_INT32:
 | |
| 			reflection->SetInt32(message, field, toInt64(value));
 | |
| 			break;
 | |
| 
 | |
| 		case google::protobuf::FieldDescriptor::TYPE_INT64:
 | |
| 			reflection->SetInt64(message, field, toInt64(value));
 | |
| 			break;
 | |
| 
 | |
| 		case google::protobuf::FieldDescriptor::TYPE_UINT32:
 | |
| 			reflection->SetUInt32(message, field, toUint64(value));
 | |
| 			break;
 | |
| 
 | |
| 		case google::protobuf::FieldDescriptor::TYPE_UINT64:
 | |
| 			reflection->SetUInt64(message, field, toUint64(value));
 | |
| 			break;
 | |
| 
 | |
| 		case google::protobuf::FieldDescriptor::TYPE_STRING:
 | |
| 			reflection->SetString(message, field, value);
 | |
| 			break;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| std::set<int> iterate(const Range& range)
 | |
| {
 | |
| 	std::set<int> set;
 | |
| 	for (int i=range.start(); i<=range.end(); i+=range.step())
 | |
| 		set.insert(i);
 | |
| 
 | |
| 	for (const int i : range.also())
 | |
| 		set.insert(i);
 | |
| 
 | |
| 	return set;
 | |
| }
 | |
| 
 |