Skip to content

Commit

Permalink
feat: (#1724) Enable loading of TOML files (#1742)
Browse files Browse the repository at this point in the history
  • Loading branch information
rprospero committed Apr 8, 2024
1 parent 2155174 commit 8769df9
Show file tree
Hide file tree
Showing 15 changed files with 92 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/base/geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ template <> struct from<Geometry::GeometryType>
else if (typeString == "torsion")
return Geometry::GeometryType::TorsionType;
else
throw toml::syntax_error(
throw toml::type_error(
fmt::format("Unhandled geometry type '{}' - can't convert from TOML value.\n", std::string(typeString)),
node.location());
}
Expand Down
2 changes: 1 addition & 1 deletion src/classes/isotopologues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ void Isotopologues::deserialise(const SerialisedValue &node, const CoreData &cor
{
auto iso = species_->findIsotopologue(name);
if (!iso)
throw toml::syntax_error(fmt::format("Cannot find iso {}", name), location);
throw toml::type_error(fmt::format("Cannot find iso {}", name), location);
add(iso, item.as_floating());
});
}
2 changes: 1 addition & 1 deletion src/classes/speciesIntra.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ template <class Intra, class Functions> class SpeciesIntra : public Serialisable
[&map](const auto &name) { return map[name]; });
break;
default:
throw toml::syntax_error("Cannot understand parameter value", node.location());
throw toml::type_error("Cannot understand parameter value", node.location());
}
setInteractionFormAndParameters(interactionForm(), values);
});
Expand Down
8 changes: 4 additions & 4 deletions src/keywords/atomTypeVector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,14 @@ void AtomTypeVectorKeyword::deserialise(const SerialisedValue &node, const CoreD
[&item](const auto atomType)
{ return DissolveSys::sameString(atomType->name(), std::string_view(std::string(item.as_string()))); });
if (it == coreData.atomTypes().end())
throw toml::syntax_error(fmt::format("Unrecognised AtomType '{}' given to '{}' keyword.\n",
std::string(item.as_string()), name()),
item.location());
throw toml::type_error(fmt::format("Unrecognised AtomType '{}' given to '{}' keyword.\n",
std::string(item.as_string()), name()),
item.location());
auto atomType = *it;

// If the AtomType is already present, complain
if (std::find(data_.begin(), data_.end(), atomType) != data_.end())
throw toml::syntax_error(
throw toml::type_error(
fmt::format("AtomType '{}' specified in selection twice.\n", std::string(item.as_string())),
item.location());

Expand Down
6 changes: 3 additions & 3 deletions src/keywords/configurationVector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ void ConfigurationVectorKeyword::deserialise(const SerialisedValue &node, const
{
auto *cfg = coreData.findConfiguration(std::string_view(std::string(name.as_string())));
if (!cfg)
throw toml::syntax_error(
throw toml::type_error(
fmt::format("Error defining Configuration targets - no Configuration named '{}' exists.\n",
std::string(name.as_string())),
name.location());

// Check that the configuration isn't already present
if (std::find(data_.begin(), data_.end(), cfg) != data_.end())
throw toml::syntax_error(fmt::format("Configuration '{}' has already been referenced.\n", cfg->name()),
name.location());
throw toml::type_error(fmt::format("Configuration '{}' has already been referenced.\n", cfg->name()),
name.location());

data_.push_back(cfg);
});
Expand Down
2 changes: 1 addition & 1 deletion src/keywords/layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void LayerKeyword::deserialise(const SerialisedValue &node, const CoreData &core
{
data_ = coreData.findProcessingLayer(std::string(node.as_string()));
if (!data_)
throw toml::syntax_error(
throw toml::type_error(
fmt::format("Layer '{}' given to keyword {} doesn't exist.\n", std::string(node.as_string()), KeywordBase::name()),
node.location());
}
Expand Down
6 changes: 3 additions & 3 deletions src/keywords/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ template <class M> class ModuleKeyword : public ModuleKeywordBase
{
auto *module = Module::find(std::string(node.as_string()));
if (!module)
throw toml::syntax_error(fmt::format("Module '{}' given to keyword {} doesn't exist.\n",
std::string(node.as_string()), KeywordBase::name()),
node.location());
throw toml::type_error(fmt::format("Module '{}' given to keyword {} doesn't exist.\n",
std::string(node.as_string()), KeywordBase::name()),
node.location());

setData(module);
}
Expand Down
4 changes: 2 additions & 2 deletions src/keywords/moduleVector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,13 @@ void ModuleVectorKeyword::deserialise(const SerialisedValue &node, const CoreDat
auto title = toml::get<std::string>(item);
auto *module = Module::find(title);
if (!module)
throw toml::syntax_error(fmt::format("No Module named '{}' exists.\n", title), item.location());
throw toml::type_error(fmt::format("No Module named '{}' exists.\n", title), item.location());

// Check the module's type if we can
if (!moduleTypes_.empty() &&
std::find_if(moduleTypes_.cbegin(), moduleTypes_.cend(),
[module](const auto &s) { return s == module->type(); }) == moduleTypes_.cend())
throw toml::syntax_error(
throw toml::type_error(
fmt::format("Module '{}' is of type '{}', and is not relevant to keyword '{}' (allowed types = {}).\n",
title, module->type(), name(), joinStrings(moduleTypes_)),
item.location());
Expand Down
4 changes: 2 additions & 2 deletions src/keywords/nodeAndInteger.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ class NodeAndIntegerKeywordBase : public NodeKeywordUnderlay, public KeywordBase
auto nodeName = toml::find<std::string>(node, "node");
auto realNode = findNode(nodeName);
if (!realNode)
throw toml::syntax_error(
fmt::format("Node '{}' given to keyword {} doesn't exist.\n", nodeName, KeywordBase::name()), node.location());
throw toml::type_error(fmt::format("Node '{}' given to keyword {} doesn't exist.\n", nodeName, KeywordBase::name()),
node.location());

setInteger(toml::find<int>(node, "int"));
setNode(realNode);
Expand Down
8 changes: 4 additions & 4 deletions src/keywords/nodeVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,12 @@ template <class N> class NodeVectorKeyword : public NodeVectorKeywordBase

ConstNodeRef noderef = findNode(nodeName);
if (!noderef)
throw toml::syntax_error(fmt::format("Node '{}' given to keyword {} doesn't exist.\n",
std::string(item.as_string()), name()),
item.location());
throw toml::type_error(fmt::format("Node '{}' given to keyword {} doesn't exist.\n",
std::string(item.as_string()), name()),
item.location());

if (!validNode(noderef.get(), name()))
throw toml::syntax_error(fmt::format("Invalid node: {}", name()), item.location());
throw toml::type_error(fmt::format("Invalid node: {}", name()), item.location());

data_.push_back(std::dynamic_pointer_cast<const N>(noderef));
});
Expand Down
8 changes: 4 additions & 4 deletions src/keywords/speciesSite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,19 @@ void SpeciesSiteKeyword::deserialise(const SerialisedValue &node, const CoreData
Species *sp = coreData.findSpecies(species);
if (!sp)
{
throw toml::syntax_error(fmt::format("Error setting SpeciesSite - no Species named '{}' exists.\n", species),
node.location());
throw toml::type_error(fmt::format("Error setting SpeciesSite - no Species named '{}' exists.\n", species),
node.location());
}

// Find specified Site (second argument) in the Species
data_ = sp->findSite(site);
if (!data_)
throw toml::syntax_error(
throw toml::type_error(
fmt::format("Error setting SpeciesSite - no such site named '{}' exists in Species '{}'.\n", site, sp->name()),
node.location());

if (axesRequired_ && (!data_->hasAxes()))
throw toml::syntax_error(
throw toml::type_error(
fmt::format("Can't select site '{}' for keyword '{}', as the keyword requires axes specifications to be present.\n",
data_->name(), name()),
node.location());
Expand Down
8 changes: 4 additions & 4 deletions src/keywords/speciesSiteVector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,12 @@ void SpeciesSiteVectorKeyword::deserialise(const SerialisedValue &node, const Co
if (site)
data_.push_back(site);
else
throw toml::syntax_error(fmt::format("Cannot find Site {}", toml::find<std::string>(item, "site")),
item.location());
throw toml::type_error(fmt::format("Cannot find Site {}", toml::find<std::string>(item, "site")),
item.location());
}
else
toml::syntax_error(fmt::format("Cannot find Species {}", toml::find<std::string>(item, "species")),
item.location());
toml::type_error(fmt::format("Cannot find Species {}", toml::find<std::string>(item, "species")),
item.location());
});
}

Expand Down
2 changes: 1 addition & 1 deletion src/keywords/speciesVector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ void SpeciesVectorKeyword::deserialise(const SerialisedValue &node, const CoreDa
auto title = toml::get<std::string>(item);
auto *species = coreData.findSpecies(title);
if (!species)
throw toml::syntax_error(fmt::format("No Species named '{}' exists.\n", title), item.location());
throw toml::type_error(fmt::format("No Species named '{}' exists.\n", title), item.location());

data_.push_back(species);
});
Expand Down
4 changes: 2 additions & 2 deletions src/keywords/weightedModuleVector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,13 @@ void WeightedModuleVectorKeyword::deserialise(const SerialisedValue &node, const
auto moduleName = toml::find<std::string>(item, "target");
auto *module = Module::find(moduleName);
if (!module)
throw toml::syntax_error(fmt::format("No Module named '{}' exists.\n", moduleName), item.location());
throw toml::type_error(fmt::format("No Module named '{}' exists.\n", moduleName), item.location());

// Check the module's type if we can
if (!moduleTypes_.empty() &&
std::find_if(moduleTypes_.cbegin(), moduleTypes_.cend(),
[module](const auto &s) { return s == module->type(); }) == moduleTypes_.cend())
throw toml::syntax_error(
throw toml::type_error(
fmt::format("Module '{}' is of type '{}', and is not relevant to keyword '{}' (allowed types = {}).\n",
moduleName, module->type(), name(), joinStrings(moduleTypes_)),
item.location());
Expand Down
67 changes: 59 additions & 8 deletions src/main/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
#include "main/keywords.h"
#include "main/version.h"
#include <cstring>
#include <fstream>
#include <functional>
#include <map>
#include <toml/parser.hpp>

// Load input file through supplied parser
bool Dissolve::loadInput(LineParser &parser)
Expand Down Expand Up @@ -221,19 +223,68 @@ void Dissolve::deserialise(const SerialisedValue &originalNode)
// Load input from supplied file
bool Dissolve::loadInput(std::string_view filename)
{
// Open file and check that we're OK to proceed reading from it
LineParser parser(&worldPool());
if (!parser.openInput(filename))
// If the file name ends in TOML, insist on a TOML parse
if (filename.find(".toml") == filename.size() - 5)
{
try
{
SerialisedValue contents = toml::parse(std::string(filename));
deserialise(contents);
return true;
}
catch (toml::syntax_error e)
{
Messenger::error("Syntax error in TOML file (are you sure you meant the .toml extension?).\n\n{}", e.what());
}
catch (toml::type_error e)
{
Messenger::error("Could not load TOML file\n\n{}", e.what());
}
return false;
}

auto result = loadInput(parser);
if (result)
// Fail if the file starts with restart header
{
std::ifstream infile{std::string(filename)};
std::string firstLine;
infile >> firstLine;
infile.close();
if (firstLine.find("# Restart file") == 0)
{
Messenger::error("File {} is a restart file and not an input file", filename);
return false;
}
}

try
{
Messenger::print("Finished reading input file.\n");
setInputFilename(filename);
SerialisedValue contents = toml::parse(std::string(filename));
deserialise(contents);
return true;
}
catch (toml::syntax_error e)
{
// The file didn't have TOML syntax, so try the original parser
// Open file and check that we're OK to proceed reading from it
LineParser parser(&worldPool());
if (!parser.openInput(filename))
return false;

return result;
auto result = loadInput(parser);
if (result)
{
Messenger::print("Finished reading input file.\n");
setInputFilename(filename);
}

return result;
}
catch (toml::type_error e)
{
// The file *was* a TOML file, but it had problems loading
Messenger::error("Could not load TOML file\n\n{}", e.what());
}
return false;
}

// Save input file
Expand Down

0 comments on commit 8769df9

Please sign in to comment.