From 39e3c3cbb068ef780c0a3e9c7c77a5788b3bf167 Mon Sep 17 00:00:00 2001 From: Adam Washington Date: Mon, 6 Jul 2026 10:15:22 +0100 Subject: [PATCH 1/9] Remove vestigal LineParser instances --- src/base/messenger.h | 3 --- src/classes/cell.h | 1 + src/classes/interactionPotential.h | 10 ---------- src/classes/isotopologueSet.h | 1 - src/classes/speciesIntra.h | 7 ------- src/classes/speciesSite.h | 1 - src/gui/mainTab.h | 1 - src/math/sampledDouble.h | 1 - src/math/sampledVector.h | 3 --- src/math/windowFunction.cpp | 13 ------------- src/math/windowFunction.h | 3 --- 11 files changed, 1 insertion(+), 43 deletions(-) diff --git a/src/base/messenger.h b/src/base/messenger.h index 4a2d93b765..1f2e6759e9 100644 --- a/src/base/messenger.h +++ b/src/base/messenger.h @@ -7,9 +7,6 @@ #include #include -// Forward Declarations -class LineParser; - // Global messaging handler class Messenger { diff --git a/src/classes/cell.h b/src/classes/cell.h index 7e142e0388..a0bd8e78ef 100644 --- a/src/classes/cell.h +++ b/src/classes/cell.h @@ -5,6 +5,7 @@ #include "classes/configurationAtom.h" #include "math/vector3.h" +#include "math/vector3i.h" #include #include diff --git a/src/classes/interactionPotential.h b/src/classes/interactionPotential.h index be8308a587..237133c401 100644 --- a/src/classes/interactionPotential.h +++ b/src/classes/interactionPotential.h @@ -3,7 +3,6 @@ #pragma once -#include "base/lineParser.h" #include "base/messenger.h" #include "base/sysFunc.h" #include "templates/algorithms.h" @@ -122,15 +121,6 @@ template class InteractionPotential } // Parse parameters from specified string bool parseParameters(std::string_view paramString) { return parseParameters(DissolveSys::splitString(paramString)); } - // Parse parameters from current line - bool parseParameters(const LineParser &parser, int startArg) - { - // Construct a vector of all remaining arguments on the line, starting from the argument offset - std::vector terms; - for (auto n = startArg; n < parser.nArgs(); ++n) - terms.emplace_back(parser.argsv(n)); - return parseParameters(terms); - } // Set form and parameters void setFormAndParameters(typename Functions::Form form, const std::vector ¶ms) { diff --git a/src/classes/isotopologueSet.h b/src/classes/isotopologueSet.h index f79cb4db58..68c67d2ed9 100644 --- a/src/classes/isotopologueSet.h +++ b/src/classes/isotopologueSet.h @@ -8,7 +8,6 @@ // Forward Declarations class Species; class Isotopologue; -class LineParser; // IsotopologueSet - Isotopologues for one or more Species class IsotopologueSet : public Serialisable, ResolvableContext diff --git a/src/classes/speciesIntra.h b/src/classes/speciesIntra.h index 8478bda1c1..5e1388ddb2 100644 --- a/src/classes/speciesIntra.h +++ b/src/classes/speciesIntra.h @@ -85,13 +85,6 @@ template class SpeciesIntra : public Serialisable std::vector terms{DissolveSys::splitString(params)}; return interactionPotential_.parseParameters(terms); } - bool setInteractionParameters(LineParser &parser, int startArg) - { - if (commonTerm_) - return Messenger::error("Refused to set intramolecular parameters since common parameters are referenced.\n"); - - return interactionPotential_.parseParameters(parser, startArg); - } // Set form and parameters void setInteractionFormAndParameters(typename Functions::Form form, const std::vector ¶ms) { diff --git a/src/classes/speciesSite.h b/src/classes/speciesSite.h index e0e9a2ee2d..81426f66c0 100644 --- a/src/classes/speciesSite.h +++ b/src/classes/speciesSite.h @@ -16,7 +16,6 @@ // Forward Declarations class Configuration; -class LineParser; class Site; class Species; class SpeciesAtom; diff --git a/src/gui/mainTab.h b/src/gui/mainTab.h index 50496bf984..13fc03ddba 100644 --- a/src/gui/mainTab.h +++ b/src/gui/mainTab.h @@ -11,7 +11,6 @@ // Forward Declarations class Dissolve; class DissolveWindow; -class LineParser; class MainTabsWidget; class QLayout; class QMdiArea; diff --git a/src/math/sampledDouble.h b/src/math/sampledDouble.h index b2656275ff..cd1bfbdd17 100644 --- a/src/math/sampledDouble.h +++ b/src/math/sampledDouble.h @@ -6,7 +6,6 @@ #include "base/serialiser.h" // Forward Declarations -class LineParser; class ProcessPool; // Double value with sampling diff --git a/src/math/sampledVector.h b/src/math/sampledVector.h index 7e92524b70..de1cd770f0 100644 --- a/src/math/sampledVector.h +++ b/src/math/sampledVector.h @@ -6,9 +6,6 @@ #include "base/serialiser.h" #include -// Forward Declarations -class LineParser; - // Vector of double values with sampling class SampledVector : public Serialisable { diff --git a/src/math/windowFunction.cpp b/src/math/windowFunction.cpp index a8395bd28e..8672c11303 100644 --- a/src/math/windowFunction.cpp +++ b/src/math/windowFunction.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "math/windowFunction.h" -#include "base/lineParser.h" #include "math/data1D.h" #include "math/mathFunc.h" @@ -28,18 +27,6 @@ EnumOptions getEnumOptions(WindowFunction::Form) { return void WindowFunction::set(WindowFunction::Form form) { form_ = form; } -// Set function data from LineParser source -bool WindowFunction::set(LineParser &parser, int startArg) -{ - // First argument is the form of the function - if (forms().isValid(parser.argsv(startArg))) - return forms().errorAndPrintValid(parser.argsv(startArg)); - - form_ = forms().enumeration(parser.argsv(startArg)); - - return true; -} - // Return functional form WindowFunction::Form WindowFunction::form() const { return form_; } diff --git a/src/math/windowFunction.h b/src/math/windowFunction.h index 2b0b49cf9b..b1a5b378e2 100644 --- a/src/math/windowFunction.h +++ b/src/math/windowFunction.h @@ -6,7 +6,6 @@ #include "base/enumOptions.h" // Forward Declarations -class LineParser; class Data1D; // Window Function @@ -42,8 +41,6 @@ class WindowFunction public: // Set functional form void set(WindowFunction::Form form); - // Set function data from LineParser source - bool set(LineParser &parser, int startArg); // Return function type WindowFunction::Form form() const; // Set-up function for specified data From 4b1b865ee95e7c26f034b686fd27926ce78fdf45 Mon Sep 17 00:00:00 2001 From: Adam Washington Date: Mon, 6 Jul 2026 11:01:07 +0100 Subject: [PATCH 2/9] Remove LineParser from PartialSet saving --- src/classes/partialSet.cpp | 16 +++++++--------- src/classes/partialSetAccumulator.cpp | 21 ++++++++++----------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/classes/partialSet.cpp b/src/classes/partialSet.cpp index b24c53a610..989a431193 100644 --- a/src/classes/partialSet.cpp +++ b/src/classes/partialSet.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "classes/partialSet.h" -#include "base/lineParser.h" #include "classes/atomType.h" #include "classes/box.h" #include "classes/configuration.h" @@ -278,8 +277,6 @@ bool PartialSet::save(std::string_view prefix, std::string_view tag, std::string auto typeFractions = atomTypeFractions(); - LineParser parser; - // Write partials for_each_pair_early( typeFractions, @@ -291,19 +288,20 @@ bool PartialSet::save(std::string_view prefix, std::string_view tag, std::string std::string filename{std::format("{}-{}-{}-{}.{}", prefix, tag, popI.first->name(), popJ.first->name(), suffix)}; Messenger::printVerbose("Writing partial file '{}'...\n", filename); - parser.openOutput(filename, true); - if (!parser.isFileGoodForWriting()) + std::ofstream outfile(filename, std::ios::out); + std::ostreambuf_iterator out(outfile); + if (!outfile) return Messenger::error("Couldn't open file '{}' for writing.\n", filename); auto &full = partials_.get(key); auto &bound = boundPartials_.get(key); auto &unbound = unboundPartials_.get(key); - parser.writeLineF("# {:<14} {:<16} {:<16} {:<16}\n", abscissaUnits, "Full", "Bound", "Unbound"); + std::format_to(out, "# {:<14} {:<16} {:<16} {:<16}\n", abscissaUnits, "Full", "Bound", "Unbound"); for (auto n = 0; n < full.nValues(); ++n) - parser.writeLineF("{:16.9e} {:16.9e} {:16.9e} {:16.9e}\n", full.xAxis(n), full.value(n), bound.value(n), - unbound.value(n)); - parser.closeFiles(); + std::format_to(out, "{:16.9e} {:16.9e} {:16.9e} {:16.9e}\n", full.xAxis(n), full.value(n), bound.value(n), + unbound.value(n)); + outfile.close(); return EarlyReturn::Continue; }, diff --git a/src/classes/partialSetAccumulator.cpp b/src/classes/partialSetAccumulator.cpp index fe4e3f7302..a9e6c52a4b 100644 --- a/src/classes/partialSetAccumulator.cpp +++ b/src/classes/partialSetAccumulator.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "classes/partialSetAccumulator.h" -#include "base/lineParser.h" #include "base/sysFunc.h" #include "nodes/exportData.h" #include @@ -70,8 +69,6 @@ bool PartialSetAccumulator::save(std::string_view prefix, std::string_view tag, { assert(!prefix.empty()); - LineParser parser; - // Write partials for (auto &[key, fullPartial] : partials_) { @@ -87,17 +84,19 @@ bool PartialSetAccumulator::save(std::string_view prefix, std::string_view tag, std::string filename{std::format("{}-{}-{}.{}", prefix, tag, DissolveSys::niceName(fullPartial.tag()), suffix)}; Messenger::printVerbose("Writing partial file '{}'...\n", filename); - parser.openOutput(filename, true); - if (!parser.isFileGoodForWriting()) + std::ofstream outfile(filename, std::ios::out); + std::ostreambuf_iterator out(outfile); + + if (!outfile) return Messenger::error("Couldn't open file '{}' for writing.\n", filename); - parser.writeLineF("# {:<14} {:<16} {:<16} {:<16} {:<16} {:<16} {:<16}\n", abscissaUnits, "Full", "Error", "Bound", - "Error", "Unbound", "Error"); + std::format_to(out, "# {:<14} {:<16} {:<16} {:<16} {:<16} {:<16} {:<16}\n", abscissaUnits, "Full", "Error", + "Bound", "Error", "Unbound", "Error"); for (auto n = 0; n < fullPartial.nValues(); ++n) - parser.writeLineF("{:16.9e} {:16.9e} {:16.9e} {:16.9e} {:16.9e} {:16.9e} {:16.9e}\n", fullPartial.xAxis(n), - fullPartial.value(n), fullPartial.error(n), boundPartial.value(n), boundPartial.error(n), - unboundPartial.value(n), unboundPartial.error(n)); - parser.closeFiles(); + std::format_to(out, "{:16.9e} {:16.9e} {:16.9e} {:16.9e} {:16.9e} {:16.9e} {:16.9e}\n", fullPartial.xAxis(n), + fullPartial.value(n), fullPartial.error(n), boundPartial.value(n), boundPartial.error(n), + unboundPartial.value(n), unboundPartial.error(n)); + outfile.close(); } return ExportDataNode::write(total_, std::format("{}-{}-total.{}", prefix, tag, suffix)); From 3821412af1805fbd404fccd8c87b58207696137b Mon Sep 17 00:00:00 2001 From: Adam Washington Date: Mon, 6 Jul 2026 11:15:01 +0100 Subject: [PATCH 3/9] Remove LineParser from fit saving --- src/math/gaussFit.cpp | 24 ++++++++++++------------ src/math/poissonFit.cpp | 12 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/math/gaussFit.cpp b/src/math/gaussFit.cpp index 9d9f24157e..a4332fb18e 100644 --- a/src/math/gaussFit.cpp +++ b/src/math/gaussFit.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "math/gaussFit.h" -#include "base/lineParser.h" #include "math/data1D.h" #include "math/error.h" #include "math/filters.h" @@ -106,15 +105,16 @@ const std::vector &GaussFit::fwhm() const { return fwhm_; } // Save coefficients to specified file bool GaussFit::saveCoefficients(std::string_view filename) const { - LineParser parser; - if (!parser.openOutput(filename)) + std::ofstream outfile(std::string(filename), std::ios::out); + std::ostreambuf_iterator out(outfile); + if (!outfile) return false; - parser.writeLineF("# x A FWHM\n"); + std::format_to(out, "# x A FWHM\n"); for (auto n = 0; n < nGaussians_; ++n) - parser.writeLineF("{} {} {}\n", x_[n], A_[n], fwhm_[n]); + std::format_to(out, "{} {} {}\n", x_[n], A_[n], fwhm_[n]); - parser.closeFiles(); + outfile.close(); return true; } @@ -134,24 +134,24 @@ bool GaussFit::saveFTGaussians(std::string_view filenamePrefix, double xStep) co double xDelta = (xStep < 0.0 ? referenceData_.xAxis(1) - referenceData_.xAxis(0) : xStep); for (auto n = 0; n < nGaussians_; ++n) { - LineParser parser; - if (!parser.openOutput(std::format("{}-{:03d}.gauss", filenamePrefix, n))) + std::ofstream outfile(std::format("{}-{:03d}.gauss", filenamePrefix, n), std::ios::out); + std::ostreambuf_iterator out(outfile); + if (!outfile) return false; auto xCentre = x_[n]; auto A = A_[n]; auto fwhm = fwhm_[n]; - if (!parser.writeLineF("# x={} A={} fwhm={}\n", xCentre, A, fwhm)) - return false; + std::format_to(out, "# x={} A={} fwhm={}\n", xCentre, A, fwhm); double x = referenceData_.xAxis().front(); while (x < referenceData_.xAxis().back()) { - parser.writeLineF("{} {}\n", x, gaussianFT(x, xCentre, A, fwhm)); + std::format_to(out, "{} {}\n", x, gaussianFT(x, xCentre, A, fwhm)); x += xDelta; } - parser.closeFiles(); + outfile.close(); } return true; diff --git a/src/math/poissonFit.cpp b/src/math/poissonFit.cpp index e57427732b..67f6ad1964 100644 --- a/src/math/poissonFit.cpp +++ b/src/math/poissonFit.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "math/poissonFit.h" -#include "base/lineParser.h" #include "math/data1D.h" #include "math/error.h" #include "math/filters.h" @@ -189,15 +188,16 @@ const std::vector &PoissonFit::C() const { return C_; } // Save coefficients to specified file bool PoissonFit::saveCoefficients(std::string_view filename) const { - LineParser parser; - if (!parser.openOutput(filename)) + std::ofstream outfile(std::string(filename), std::ios::out); + std::ostreambuf_iterator out(outfile); + if (!outfile) return false; - parser.writeLineF("# C\n"); + std::format_to(out, "# C\n"); for (auto n = 0; n < nPoissons_; ++n) - parser.writeLineF("{}\n", C_[n]); + std::format_to(out, "{}\n", C_[n]); - parser.closeFiles(); + outfile.close(); return true; } From 8ffb6d1eb09c0f0dae075542b016c87dbcac5094 Mon Sep 17 00:00:00 2001 From: Adam Washington Date: Mon, 6 Jul 2026 14:28:58 +0100 Subject: [PATCH 4/9] Remove LineParser from exports --- src/nodes/exportBlockData.cpp | 1 - src/nodes/exportBlockData.h | 16 ++---- src/nodes/exportDLPUtilsPDensData.cpp | 36 ++++-------- src/nodes/exportData.cpp | 79 +++++++-------------------- 4 files changed, 35 insertions(+), 97 deletions(-) diff --git a/src/nodes/exportBlockData.cpp b/src/nodes/exportBlockData.cpp index aa29961da8..6c38513843 100644 --- a/src/nodes/exportBlockData.cpp +++ b/src/nodes/exportBlockData.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "nodes/exportBlockData.h" -#include "base/lineParser.h" ExportBlockDataNode::ExportBlockDataNode(Graph *parentGraph) : Node(parentGraph) { diff --git a/src/nodes/exportBlockData.h b/src/nodes/exportBlockData.h index 0e080a9116..63c707997f 100644 --- a/src/nodes/exportBlockData.h +++ b/src/nodes/exportBlockData.h @@ -47,23 +47,17 @@ class ExportBlockDataNode : public Node template bool write(const DataClass &data, const std::string &filePath) { // Open the file - LineParser parser; - if (!parser.openOutput(filePath)) - { - parser.closeFiles(); + std::ofstream outfile(std::string(filePath), std::ios::out); + std::ostreambuf_iterator out(outfile); + if (!outfile) return false; - } if (data.valuesHaveErrors()) - { for (auto &&[value, error] : zip(data.values(), data.errors())) - if (!parser.writeLineF("{:16.10e} {:16.10e}\n", value, error)) - return false; - } + std::format_to(out, "{:16.10e} {:16.10e}\n", value, error); else for (auto value : data.values()) - if (!parser.writeLineF("{:16.10e}\n", value)) - return false; + std::format_to(out, "{:16.10e}\n", value); return true; } diff --git a/src/nodes/exportDLPUtilsPDensData.cpp b/src/nodes/exportDLPUtilsPDensData.cpp index 0cc8116f92..513e6196a0 100644 --- a/src/nodes/exportDLPUtilsPDensData.cpp +++ b/src/nodes/exportDLPUtilsPDensData.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "nodes/exportDLPUtilsPDensData.h" -#include "base/lineParser.h" ExportDLPUtilsPDensDataNode::ExportDLPUtilsPDensDataNode(Graph *parentGraph) : Node(parentGraph) { @@ -37,12 +36,10 @@ NodeConstants::ProcessResult ExportDLPUtilsPDensDataNode::process() bool ExportDLPUtilsPDensDataNode::write(const Data3D &data, const std::string &filePath) { // Open the file - LineParser parser; - if (!parser.openOutput(filePath)) - { - parser.closeFiles(); + std::ofstream outfile(std::string(filePath), std::ios::out); + std::ostreambuf_iterator out(outfile); + if (!outfile) return false; - } const auto &xAxis = data.xAxis(); const auto &yAxis = data.xAxis(); @@ -50,35 +47,24 @@ bool ExportDLPUtilsPDensDataNode::write(const Data3D &data, const std::string &f const auto &values = data.values(); // Line 1 (Integer Extents): nx, ny, nz, xmin, ymin, zmin, xmax, ymax, zmax - if (!parser.writeLineF("{:5d}{:5d}{:5d}{:5d}{:5d}{:5d}{:5d}{:5d}{:5d}\n", values.nX(), values.nY(), values.nZ(), 0, 0, 0, - values.nX(), values.nY(), values.nZ())) - return false; + std::format_to(out, "{:5d}{:5d}{:5d}{:5d}{:5d}{:5d}{:5d}{:5d}{:5d}\n", values.nX(), values.nY(), values.nZ(), 0, 0, 0, + values.nX(), values.nY(), values.nZ()); // Line 2 (Axis Definitions) - assume orthogonal - if (!parser.writeLineF("{:9.3e} {:9.3e} {:9.3e} {:9.3e} {:9.3e} {:9.3e} {:9.3e} {:9.3e} {:9.3e}\n", xAxis[1] - xAxis[0], - 0.0, 0.0, 0.0, yAxis[1] - yAxis[0], 0.0, 0.0, 0.0, zAxis[1] - zAxis[0])) - return false; + std::format_to(out, "{:9.3e} {:9.3e} {:9.3e} {:9.3e} {:9.3e} {:9.3e} {:9.3e} {:9.3e} {:9.3e}\n", xAxis[1] - xAxis[0], 0.0, + 0.0, 0.0, yAxis[1] - yAxis[0], 0.0, 0.0, 0.0, zAxis[1] - zAxis[0]); // Line 3 (Origin) - if (!parser.writeLineF("{:10.4f}{:10.4f}{:10.4f}\n", xAxis[0], yAxis[0], zAxis[0])) - return false; + std::format_to(out, "{:10.4f}{:10.4f}{:10.4f}\n", xAxis[0], yAxis[0], zAxis[0]); // Line 4 (Loop order) - if (!parser.writeLineF("zyx\n")) - return false; + std::format_to(out, "zyx\n"); // Lines 5+ (Data) for (auto x = 0; x < values.nX(); ++x) - { for (auto y = 0; y < values.nY(); ++y) - { for (auto z = 0; z < values.nZ(); ++z) - { - if (!parser.writeLineF("{:15.9e}\n", values[std::tuple{x, y, z}])) - return false; - } - } - } + std::format_to(out, "{:15.9e}\n", values[std::tuple{x, y, z}]); return true; -} \ No newline at end of file +} diff --git a/src/nodes/exportData.cpp b/src/nodes/exportData.cpp index fc21745a89..d0b2e2d8cc 100644 --- a/src/nodes/exportData.cpp +++ b/src/nodes/exportData.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "nodes/exportData.h" -#include "base/lineParser.h" ExportDataNode::ExportDataNode(Graph *parentGraph) : Node(parentGraph) { @@ -54,36 +53,30 @@ NodeConstants::ProcessResult ExportDataNode::process() bool ExportDataNode::write(const Data1D &data, const std::string &filePath) { // Open the file - LineParser parser; - if (!parser.openOutput(filePath)) - { - parser.closeFiles(); + std::ofstream outfile(std::string(filePath), std::ios::out); + std::ostreambuf_iterator out(outfile); + if (!outfile) return false; - } // Write data if (data.valuesHaveErrors()) { for (auto &&[x, value, error] : zip(data.xAxis(), data.values(), data.errors())) - if (!parser.writeLineF("{:16.10e} {:16.10e} {:16.10e}\n", x, value, error)) - return false; + std::format_to(out, "{:16.10e} {:16.10e} {:16.10e}\n", x, value, error); } else for (auto &&[x, value] : zip(data.xAxis(), data.values())) - if (!parser.writeLineF("{:16.10e} {:16.10e}\n", x, value)) - return false; + std::format_to(out, "{:16.10e} {:16.10e}\n", x, value); return true; } bool ExportDataNode::write(const Data2D &data, const std::string &filePath) { // Open the file - LineParser parser; - if (!parser.openOutput(filePath)) - { - parser.closeFiles(); + std::ofstream outfile(std::string(filePath), std::ios::out); + std::ostreambuf_iterator out(outfile); + if (!outfile) return false; - } // Three/four-column format (x y value [error]) in blocks of similar x value, separated by blank lines const auto &xAxis = data.xAxis(); @@ -93,38 +86,24 @@ bool ExportDataNode::write(const Data2D &data, const std::string &filePath) { const auto &errors = data.errors(); for (auto x = 0; x < xAxis.size(); ++x) - { for (auto y = 0; y < yAxis.size(); ++y) - if (!parser.writeLineF("{:16.10f} {:16.10f} {:16.10f} {:16.10f}\n", xAxis[x], yAxis[y], values[{x, y}], - errors[{x, y}])) - return false; - if (!parser.writeLineF("\n")) - return false; - } + std::format_to(out, "{:16.10f} {:16.10f} {:16.10f} {:16.10f}\n\n", xAxis[x], yAxis[y], values[{x, y}], + errors[{x, y}]); } else - { for (auto x = 0; x < xAxis.size(); ++x) - { for (auto y = 0; y < yAxis.size(); ++y) - if (!parser.writeLineF("{:16.10f} {:16.10f} {:16.10f}\n", xAxis[x], yAxis[y], values[{x, y}])) - return false; - if (!parser.writeLineF("\n")) - return false; - } - } + std::format_to(out, "{:16.10f} {:16.10f} {:16.10f}\n\n", xAxis[x], yAxis[y], values[{x, y}]); return true; } bool ExportDataNode::write(const Data3D &data, const std::string &filePath) { // Open the file - LineParser parser; - if (!parser.openOutput(filePath)) - { - parser.closeFiles(); + std::ofstream outfile(std::string(filePath), std::ios::out); + std::ostreambuf_iterator out(outfile); + if (!outfile) return false; - } // Three/four-Four/five-column format (x y z value [error]) in blocks of similar x and y value, separated by blank lines const auto &xAxis = data.xAxis(); @@ -135,37 +114,17 @@ bool ExportDataNode::write(const Data3D &data, const std::string &filePath) { const auto &errors = data.errors(); for (auto x = 0; x < xAxis.size(); ++x) - { for (auto y = 0; y < yAxis.size(); ++y) - { for (auto z = 0; z < zAxis.size(); ++z) - { - if (!parser.writeLineF("{:16.10f} {:16.10f} {:16.10f} {:16.10f} {:16.10f}\n", xAxis[x], yAxis[y], zAxis[z], - values[{x, y, z}], errors[{x, y, z}])) - return false; - if (!parser.writeLineF("\n")) - return false; - } - } - } + std::format_to(out, "{:16.10f} {:16.10f} {:16.10f} {:16.10f} {:16.10f}\n\n", xAxis[x], yAxis[y], zAxis[z], + values[{x, y, z}], errors[{x, y, z}]); } else - { for (auto x = 0; x < xAxis.size(); ++x) - { for (auto y = 0; y < yAxis.size(); ++y) - { for (auto z = 0; z < zAxis.size(); ++z) - { - if (!parser.writeLineF("{:16.10f} {:16.10f} {:16.10f} {:16.10f}\n", xAxis[x], yAxis[y], zAxis[z], - values[{x, y, z}])) - return false; - if (!parser.writeLineF("\n")) - return false; - } - } - } - } + std::format_to(out, "{:16.10f} {:16.10f} {:16.10f} {:16.10f}\n\n", xAxis[x], yAxis[y], zAxis[z], + values[{x, y, z}]); return true; -} \ No newline at end of file +} From 04264904570dfccbad9c8686490d1753239a725b Mon Sep 17 00:00:00 2001 From: Adam Washington Date: Mon, 6 Jul 2026 15:01:28 +0100 Subject: [PATCH 5/9] Remove LineParser from ImportXYDataNode --- src/nodes/importXYData.cpp | 51 +++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/nodes/importXYData.cpp b/src/nodes/importXYData.cpp index 4291ec04c0..fa06e4ffdf 100644 --- a/src/nodes/importXYData.cpp +++ b/src/nodes/importXYData.cpp @@ -2,7 +2,8 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "nodes/importXYData.h" -#include "base/lineParser.h" +#include "base/applicative.h" +#include "base/parserLibrary.h" #include "math/data1D.h" #include "math/filters.h" @@ -80,6 +81,7 @@ NodeConstants::ProcessResult ImportXYDataNode::process() // Read data specified bool ImportXYDataNode::read(Data1D &data, std::string filePath, int xColumn, int yColumn, int errorColumn, bool histogram) { + using namespace Parsers; // Clear the data data.clear(); @@ -89,36 +91,39 @@ bool ImportXYDataNode::read(Data1D &data, std::string filePath, int xColumn, int --errorColumn; // Open file and check that we're OK to proceed importing from it - LineParser parser; - if ((!parser.openInput(filePath)) || (!parser.isFileGoodForReading())) + std::ifstream infile(filePath); + if (!infile) return false; - while (!parser.eofOrBlank()) - { - if (parser.getArgsDelim() != LineParser::Success) - return false; - - // Check columns provided - if ((xColumn >= parser.nArgs()) || (yColumn >= parser.nArgs())) - return false; - - // Are we reading errors too? - if (errorColumn == -1) - data.addPoint(parser.argd(xColumn), parser.argd(yColumn)); - else + std::optional> commentLine; + // Treat lines that begin with # as empty data points + auto comment = + "#"_p >> inlines() >> newlines().map([](const auto x) -> std::optional> { return {}; }); + // We *may* have to deal with mixed numeric and alphabetic data, + // so treat each line as a list of strings and only parse the + // double at the end. Use the map command to wrap the data in an optionsl + auto line = comment | (some(maybe(inlineSpaces()) >> graphs()) << spaces()) + .map([](auto x) -> std::optional> { return x; }); + auto parsed = some(line).parse(infile); + if (!parsed) + return false; + auto lines = std::get<0>(*parsed); + if (errorColumn == -1) + for (auto l : lines) { - if (errorColumn >= parser.nArgs()) - return false; - - data.addPoint(parser.argd(xColumn), parser.argd(yColumn), parser.argd(errorColumn)); + if (!l) // just a comment; + continue; + if (errorColumn == -1) + data.addPoint(std::stod(l->at(xColumn)), std::stod(l->at(yColumn))); + else + data.addPoint(std::stod(l->at(xColumn)), std::stod(l->at(yColumn)), std::stod(l->at(errorColumn))); } - } - parser.closeFiles(); + infile.close(); // If we have a histogram, convert bin boundaries to centre-bin values if (histogram) Filters::convertBinBoundaries(data); return true; -} \ No newline at end of file +} From ab0d446c926068a3cacad8fab6dae92c3bc2a329 Mon Sep 17 00:00:00 2001 From: Adam Washington Date: Mon, 6 Jul 2026 16:25:44 +0100 Subject: [PATCH 6/9] Remove most includes of lineParser.h --- src/base/messenger.cpp | 2 +- src/classes/braggReflection.cpp | 1 - src/classes/braggReflection.h | 4 ++-- src/classes/configuration.cpp | 1 - src/classes/histogramSet.cpp | 1 - src/classes/isotopologueSet.cpp | 1 - src/classes/neutronWeights.cpp | 1 - src/classes/speciesSite.cpp | 1 - src/classes/speciesSites.cpp | 1 - src/gui/models/nodeGraph/graphEdgeModel.cpp | 2 -- src/main.cpp | 1 + src/main/io.cpp | 1 - src/main/simulation.cpp | 1 - src/math/data1D.cpp | 1 - src/math/data1D.h | 1 - src/math/data2D.cpp | 1 - src/math/data3D.cpp | 1 - src/math/histogram1D.cpp | 1 - src/math/histogram1D.h | 1 + src/math/histogram2D.cpp | 3 +-- src/math/histogram3D.cpp | 3 +-- src/math/integerHistogram1D.cpp | 1 - src/math/sampledData1D.cpp | 1 - src/math/sampledDouble.cpp | 1 - src/math/sampledVector.cpp | 2 +- src/nodes/importEPSRAtoStructure.cpp | 1 + src/nodes/md.h | 1 - src/nodes/node.cpp | 1 + src/nodes/voxelDensity.h | 1 + tests/math/poisson.cpp | 1 + 30 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/base/messenger.cpp b/src/base/messenger.cpp index 340a402d35..02bf6c57ca 100644 --- a/src/base/messenger.cpp +++ b/src/base/messenger.cpp @@ -2,8 +2,8 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "base/messenger.h" -#include "base/lineParser.h" #include "base/sysFunc.h" +#include // Static Members bool Messenger::quiet_ = false; diff --git a/src/classes/braggReflection.cpp b/src/classes/braggReflection.cpp index 7954dbd8b8..1574dd2835 100644 --- a/src/classes/braggReflection.cpp +++ b/src/classes/braggReflection.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "classes/braggReflection.h" -#include "base/lineParser.h" BraggReflectionVector::BraggReflectionVector(const BraggReflectionVector &other) : reflections_(other.reflections_) {} diff --git a/src/classes/braggReflection.h b/src/classes/braggReflection.h index 5be906bf16..fb46194dc4 100644 --- a/src/classes/braggReflection.h +++ b/src/classes/braggReflection.h @@ -3,8 +3,8 @@ #pragma once -#include "base/lineParser.h" #include "base/serialiser.h" +#include "math/vector3i.h" #include "templates/array2D.h" // BraggReflection Class @@ -104,4 +104,4 @@ class BraggReflectionVector : public Serialisable void serialise(std::string tag, SerialisedValue &target) const override; // Read values from a serialisable value void deserialise(const SerialisedValue &node) override; -}; \ No newline at end of file +}; diff --git a/src/classes/configuration.cpp b/src/classes/configuration.cpp index 9c933ddce6..24836ad2cb 100644 --- a/src/classes/configuration.cpp +++ b/src/classes/configuration.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "classes/configuration.h" -#include "base/lineParser.h" #include "base/sysFunc.h" #include "classes/atomType.h" #include "classes/cell.h" diff --git a/src/classes/histogramSet.cpp b/src/classes/histogramSet.cpp index b50319d159..11981acf73 100644 --- a/src/classes/histogramSet.cpp +++ b/src/classes/histogramSet.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "classes/histogramSet.h" -#include "base/lineParser.h" #include "classes/atomType.h" #include "math/mathFunc.h" #include "templates/algorithms.h" diff --git a/src/classes/isotopologueSet.cpp b/src/classes/isotopologueSet.cpp index aab8e6c04e..35c1db876a 100644 --- a/src/classes/isotopologueSet.cpp +++ b/src/classes/isotopologueSet.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "classes/isotopologueSet.h" -#include "base/lineParser.h" #include "classes/species.h" #include diff --git a/src/classes/neutronWeights.cpp b/src/classes/neutronWeights.cpp index 9cdfc5309b..d396ba4729 100644 --- a/src/classes/neutronWeights.cpp +++ b/src/classes/neutronWeights.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "classes/neutronWeights.h" -#include "base/lineParser.h" #include "classes/atomType.h" #include "classes/isotopologueSet.h" #include "classes/species.h" diff --git a/src/classes/speciesSite.cpp b/src/classes/speciesSite.cpp index 11fe56feb3..5911ad76a1 100644 --- a/src/classes/speciesSite.cpp +++ b/src/classes/speciesSite.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "classes/speciesSite.h" -#include "base/lineParser.h" #include "classes/site.h" #include "classes/species.h" #include "data/atomicMasses.h" diff --git a/src/classes/speciesSites.cpp b/src/classes/speciesSites.cpp index e8df57c69f..005507bf37 100644 --- a/src/classes/speciesSites.cpp +++ b/src/classes/speciesSites.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "classes/speciesSites.h" -#include "base/lineParser.h" #include "classes/species.h" SpeciesSites::SpeciesSites(const std::vector &sites) diff --git a/src/gui/models/nodeGraph/graphEdgeModel.cpp b/src/gui/models/nodeGraph/graphEdgeModel.cpp index 8e9ea57622..ec02392b53 100644 --- a/src/gui/models/nodeGraph/graphEdgeModel.cpp +++ b/src/gui/models/nodeGraph/graphEdgeModel.cpp @@ -61,8 +61,6 @@ int GraphEdgeModel::rowCount(const QModelIndex &parent) const { if (!graph_) return 0; - for (auto &edge : edges()) - std::cout << edge->definition().asString() << std::endl; return edges().size(); } diff --git a/src/main.cpp b/src/main.cpp index 759be6d74a..a9bf9b711f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,6 +8,7 @@ #include "nodes/dissolve.h" #include #include +#include #include int main(int args, char **argv) diff --git a/src/main/io.cpp b/src/main/io.cpp index 264a561358..dd6ef107c1 100644 --- a/src/main/io.cpp +++ b/src/main/io.cpp @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright (c) 2026 Team Dissolve and contributors -#include "base/lineParser.h" #include "base/messenger.h" #include "base/serialiser.h" #include "base/sysFunc.h" diff --git a/src/main/simulation.cpp b/src/main/simulation.cpp index 34cb4e750b..db3f3e4122 100644 --- a/src/main/simulation.cpp +++ b/src/main/simulation.cpp @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright (c) 2026 Team Dissolve and contributors -#include "base/lineParser.h" #include "base/sysFunc.h" #include "classes/species.h" #include "main/dissolve.h" diff --git a/src/math/data1D.cpp b/src/math/data1D.cpp index adf8dbd191..b8c27d72bd 100644 --- a/src/math/data1D.cpp +++ b/src/math/data1D.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "math/data1D.h" -#include "base/lineParser.h" #include "base/messenger.h" #include "base/sysFunc.h" #include "templates/algorithms.h" diff --git a/src/math/data1D.h b/src/math/data1D.h index 4aaea592fb..1ec9036baf 100644 --- a/src/math/data1D.h +++ b/src/math/data1D.h @@ -3,7 +3,6 @@ #pragma once -#include "base/lineParser.h" #include "base/serialiser.h" #include "base/version.h" #include "math/data1DBase.h" diff --git a/src/math/data2D.cpp b/src/math/data2D.cpp index d6be8d0c44..52350363d1 100644 --- a/src/math/data2D.cpp +++ b/src/math/data2D.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "math/data2D.h" -#include "base/lineParser.h" #include "base/messenger.h" #include "base/sysFunc.h" #include "math/data1D.h" diff --git a/src/math/data3D.cpp b/src/math/data3D.cpp index b10f0d6d61..763af68ddb 100644 --- a/src/math/data3D.cpp +++ b/src/math/data3D.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "math/data3D.h" -#include "base/lineParser.h" #include "base/messenger.h" #include "base/sysFunc.h" #include "math/histogram3D.h" diff --git a/src/math/histogram1D.cpp b/src/math/histogram1D.cpp index 3ab2d225f8..0573ee30c1 100644 --- a/src/math/histogram1D.cpp +++ b/src/math/histogram1D.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "math/histogram1D.h" -#include "base/lineParser.h" #include "base/messenger.h" #include "templates/algorithms.h" #include diff --git a/src/math/histogram1D.h b/src/math/histogram1D.h index 29d0387fd9..af5c4c0e0e 100644 --- a/src/math/histogram1D.h +++ b/src/math/histogram1D.h @@ -5,6 +5,7 @@ #include "math/data1D.h" #include "math/sampledDouble.h" +#include "math/vector3.h" // One-Dimensional Histogram class Histogram1D : public Serialisable diff --git a/src/math/histogram2D.cpp b/src/math/histogram2D.cpp index 665f7c21e7..2b0528616e 100644 --- a/src/math/histogram2D.cpp +++ b/src/math/histogram2D.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "math/histogram2D.h" -#include "base/lineParser.h" #include "base/messenger.h" #include "math/histogram1D.h" @@ -243,4 +242,4 @@ void Histogram2D::deserialise(const SerialisedValue &node) averages_.linearArray() = toml::find>(node, "averages"); updateAccumulatedData(); -} \ No newline at end of file +} diff --git a/src/math/histogram3D.cpp b/src/math/histogram3D.cpp index 9a00b9ce0a..ef14ef1a78 100644 --- a/src/math/histogram3D.cpp +++ b/src/math/histogram3D.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "math/histogram3D.h" -#include "base/lineParser.h" #include "base/messenger.h" #include "math/histogram1D.h" @@ -267,4 +266,4 @@ void Histogram3D::deserialise(const SerialisedValue &node) averages_.linearArray() = toml::find>(node, "averages"); updateAccumulatedData(); -} \ No newline at end of file +} diff --git a/src/math/integerHistogram1D.cpp b/src/math/integerHistogram1D.cpp index bd10f204c5..73157ba083 100644 --- a/src/math/integerHistogram1D.cpp +++ b/src/math/integerHistogram1D.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "math/integerHistogram1D.h" -#include "base/lineParser.h" #include "base/messenger.h" #include "base/sysFunc.h" #include "math/mathFunc.h" diff --git a/src/math/sampledData1D.cpp b/src/math/sampledData1D.cpp index fb85d55178..59ac1e3358 100644 --- a/src/math/sampledData1D.cpp +++ b/src/math/sampledData1D.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "math/sampledData1D.h" -#include "base/lineParser.h" #include "base/messenger.h" #include "math/histogram1D.h" #include "templates/algorithms.h" diff --git a/src/math/sampledDouble.cpp b/src/math/sampledDouble.cpp index 448f6a9dab..d14ee198a5 100644 --- a/src/math/sampledDouble.cpp +++ b/src/math/sampledDouble.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "math/sampledDouble.h" -#include "base/lineParser.h" #include SampledDouble::SampledDouble() { clear(); } diff --git a/src/math/sampledVector.cpp b/src/math/sampledVector.cpp index 07ae14ebf9..8e3c056970 100644 --- a/src/math/sampledVector.cpp +++ b/src/math/sampledVector.cpp @@ -2,7 +2,7 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "math/sampledVector.h" -#include "base/lineParser.h" +#include "base/messenger.h" #include "templates/algorithms.h" #include diff --git a/src/nodes/importEPSRAtoStructure.cpp b/src/nodes/importEPSRAtoStructure.cpp index 15d48cd33c..89d4e1b92a 100644 --- a/src/nodes/importEPSRAtoStructure.cpp +++ b/src/nodes/importEPSRAtoStructure.cpp @@ -2,6 +2,7 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "nodes/importEPSRAtoStructure.h" +#include "base/lineParser.h" ImportEPSRAtoStructureNode::ImportEPSRAtoStructureNode(Graph *parentGraph) : Node(parentGraph) { diff --git a/src/nodes/md.h b/src/nodes/md.h index dfff130701..3907af9e16 100644 --- a/src/nodes/md.h +++ b/src/nodes/md.h @@ -4,7 +4,6 @@ #pragma once #include "base/enumOptions.h" -#include "base/lineParser.h" #include "classes/configuration.h" #include "classes/species.h" #include "main/dissolve.h" diff --git a/src/nodes/node.cpp b/src/nodes/node.cpp index a566c7abbd..2ca34a8e88 100644 --- a/src/nodes/node.cpp +++ b/src/nodes/node.cpp @@ -6,6 +6,7 @@ #include "nodes/edge.h" #include "nodes/graph.h" #include +#include /* * Definition diff --git a/src/nodes/voxelDensity.h b/src/nodes/voxelDensity.h index c81c4b6444..187644c03d 100644 --- a/src/nodes/voxelDensity.h +++ b/src/nodes/voxelDensity.h @@ -4,6 +4,7 @@ #pragma once #include "math/histogram1D.h" +#include "math/vector3i.h" #include "nodes/node.h" #include "templates/array3D.h" diff --git a/tests/math/poisson.cpp b/tests/math/poisson.cpp index 59b8f98bee..009990cdc5 100644 --- a/tests/math/poisson.cpp +++ b/tests/math/poisson.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright (c) 2026 Team Dissolve and contributors +#include "base/lineParser.h" #include "math/poissonFit.h" #include "nodes/importXYData.h" #include "tests/testing.h" From 6152d60f6adbe3c6e649f0f6baacdb05e4418ca9 Mon Sep 17 00:00:00 2001 From: Adam Washington Date: Mon, 6 Jul 2026 11:32:04 +0100 Subject: [PATCH 7/9] Add parser for EPSR Ato --- src/base/parserLibrary.cpp | 3 + src/base/parserLibrary.h | 3 + src/nodes/importEPSRAtoStructure.cpp | 111 +++++++++++++++------------ src/nodes/importEPSRAtoStructure.h | 2 +- 4 files changed, 67 insertions(+), 52 deletions(-) diff --git a/src/base/parserLibrary.cpp b/src/base/parserLibrary.cpp index df7009a88b..db7cfe95e2 100644 --- a/src/base/parserLibrary.cpp +++ b/src/base/parserLibrary.cpp @@ -75,4 +75,7 @@ Parser matrix3() .apply([](const auto m1, const auto m2, const auto m3) { return Matrix3(m1, m2, m3); }); } +// A parser that reads everything until the end of the line +Parser> toEndOfLine() { return maybe(inlines()) << newlines(); } + } // namespace Parsers diff --git a/src/base/parserLibrary.h b/src/base/parserLibrary.h index 7f02f662d9..9a333973f8 100644 --- a/src/base/parserLibrary.h +++ b/src/base/parserLibrary.h @@ -28,4 +28,7 @@ Parser vector3i(); // A parser that accepts a 3x3 matrix of floating point numbers Parser matrix3(); +// A parser that reads everything until the end of the line +Parser> toEndOfLine(); + }; // namespace Parsers diff --git a/src/nodes/importEPSRAtoStructure.cpp b/src/nodes/importEPSRAtoStructure.cpp index 89d4e1b92a..5191885bbd 100644 --- a/src/nodes/importEPSRAtoStructure.cpp +++ b/src/nodes/importEPSRAtoStructure.cpp @@ -2,7 +2,8 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "nodes/importEPSRAtoStructure.h" -#include "base/lineParser.h" +#include "base/applicative.h" +#include "base/parserLibrary.h" ImportEPSRAtoStructureNode::ImportEPSRAtoStructureNode(Graph *parentGraph) : Node(parentGraph) { @@ -33,8 +34,8 @@ NodeConstants::ProcessResult ImportEPSRAtoStructureNode::process() structure_.clear(); // Open file and check that we're OK to proceed importing from it - LineParser parser; - if ((!parser.openInput(filePath_)) || (!parser.isFileGoodForReading())) + std::ifstream infile(filePath_); + if (!infile) return error("Couldn't open file '{}' for loading EPSR ato data.\n", filePath_); // File header: @@ -42,30 +43,34 @@ NodeConstants::ProcessResult ImportEPSRAtoStructureNode::process() // or 2 : nmols, temperature (for non-cubic systems) // followed by : A, B, C // : phib, thetac, phic - if (parser.getArgsDelim() != LineParser::Success) + using namespace Parsers; + auto cubic = inlineSpaces() >> natural() & inlineSpaces() >> real() & inlineSpaces() >> real() << toEndOfLine(); + auto noncubic = inlineSpaces() >> natural() & pure(-1.0) & inlineSpaces() >> natural() << toEndOfLine(); + auto header = cubic | noncubic; + auto head = header.parse(infile); + if (!head) return NodeConstants::ProcessResult::Failed; - auto nMols = parser.argi(0); - if (parser.nArgs() == 3) + auto &[nMols, boxSize, temperature] = std::get<0>(*head); + if (boxSize != -1.0) { - double boxSize = parser.argd(1); - message("File has a cubic cell (side length {} Angstroms)", boxSize); structure_.createBox({boxSize, boxSize, boxSize}, {90.0, 90.0, 90.0}); } else { - message("File has a full cell specification"); - Vector3 lengths, angles; - if (parser.getArgsDelim() != LineParser::Success) + auto tempVect = inlineSpaces() >> vector3() << toEndOfLine(); + auto l = tempVect.parse(infile); + if (!l) return NodeConstants::ProcessResult::Failed; - lengths = parser.arg3d(0); - if (parser.getArgsDelim() != LineParser::Success) + auto lengths = std::get<0>(*l); + auto a = tempVect.parse(infile); + if (!a) return NodeConstants::ProcessResult::Failed; - angles = parser.arg3d(0); + auto angles = std::get<0>(*a); structure_.createBox(lengths, angles); } // 2 : step sizes etc. **IGNORED** - if (parser.getArgsDelim() != LineParser::Success) + if (!toEndOfLine().parse(infile)) return NodeConstants::ProcessResult::Failed; // Molecule/atom specifications are in the form: @@ -78,79 +83,83 @@ NodeConstants::ProcessResult ImportEPSRAtoStructureNode::process() // n+6: atom1, atom2 (bonds of rotation 'axis') // n+7: list of headgroup atoms that are rotated auto atomOffset = 0; - for (auto m = 0; m < nMols; m++) + auto m = 0; + for (; m < nMols; m++) { Messenger::printVerbose("Importing molecule {} from EPSR ato file...\n", m + 1); + auto molHeader = + inlineSpaces() >> natural() & inlineSpaces() >> vector3() & inlineSpaces() >> vector3() << toEndOfLine(); + auto molHead = molHeader.parse(infile); - if (parser.getArgsDelim() != LineParser::Success) + if (!molHead) return NodeConstants::ProcessResult::Failed; - auto nAtoms = parser.argi(0); - auto com = parser.arg3d(1); + auto &[nAtoms, com, phi] = std::get<0>(*molHead); - for (auto n = 0; n < nAtoms; n++) + auto n = 0; + for (; n < nAtoms; n++) { + auto atomHead = maybe(spaces()) >> alphas() << toEndOfLine(); + auto ah = atomHead.parse(infile); // Atom name - if (parser.getArgsDelim() != LineParser::Success) + if (!ah) return NodeConstants::ProcessResult::Failed; - auto name = parser.args(0); + auto name = std::get<0>(*ah); + auto del = (inlineSpaces() >> vector3() << toEndOfLine()).parse(infile); // Atom coordinates (specified as offset from com) - if (parser.getArgsDelim() != LineParser::Success) + if (!del) return NodeConstants::ProcessResult::Failed; - auto delta = parser.arg3d(0); + auto delta = std::get<0>(*del); // Add a new atom structure_.addAtom(name, com + delta); // Import in number of restraints line - if (parser.getArgsDelim() != LineParser::Success) + auto restCount = (inlineSpaces() >> natural()).parse(infile); + if (!restCount) return NodeConstants::ProcessResult::Failed; - auto nRestraints = parser.argi(0); - auto currentArg = 1; + auto nRestraints = std::get<0>(*restCount); while (nRestraints > 0) { // Look at next available argument - if none, import another line in - if (currentArg >= parser.nArgs()) - { - if (parser.getArgsDelim() != LineParser::Success) - return NodeConstants::ProcessResult::Failed; - currentArg = 0; - } - currentArg += 2; + auto rest = (spaces() >> natural() & spaces() >> real()); + auto r = rest.parse(infile); + if (!r) + return NodeConstants::ProcessResult::Failed; + auto &[a, b] = std::get<0>(*r); --nRestraints; } } // Discard molecular rotations and dihedrals // There are 14 atoms per line - first line contains number of atoms followed by (up to) 13 indices - if (parser.getArgsDelim() != LineParser::Success) + auto rotations = (maybe(spaces()) >> natural() << toEndOfLine()).parse(infile); + if (!rotations) return NodeConstants::ProcessResult::Failed; - auto nRotations = parser.argi(0); + auto nRotations = std::get<0>(*rotations); while (nRotations > 0) { - // Import line to find out which type of definition this is... - if (parser.getArgsDelim() != LineParser::Success) - return NodeConstants::ProcessResult::Failed; - - // Skip axis line - if (parser.skipLines(1) != LineParser::Success) - return NodeConstants::ProcessResult::Failed; - // If a DIHedral, we expect an integer which defines the number of constraints, and thus the number of // lines to skip before the main - if (DissolveSys::sameString(parser.argsv(0), "DIH")) + auto dih = maybe(inlineSpaces() >> "DIH"_p << toEndOfLine()); + auto d = dih.parse(infile); + if (d && std::get<0>(*d)) { - if (parser.getArgsDelim() != LineParser::Success) - return NodeConstants::ProcessResult::Failed; - if (parser.skipLines(parser.argi(0)) != LineParser::Success) + toEndOfLine().parse(infile); + auto constraints = (inlineSpaces() >> natural() << toEndOfLine()).parse(infile); + if (!constraints) return NodeConstants::ProcessResult::Failed; + for (auto i = 0; i < std::get<0>(*constraints); ++i) + toEndOfLine().parse(infile); } // Finally, import in number of atoms affected by rotation and calculate next number of lines to discard - if (parser.getArgsDelim() != LineParser::Success) - return NodeConstants::ProcessResult::Failed; - if (parser.skipLines(parser.argi(0) / 14) != LineParser::Success) + auto atoms = (inlineSpaces() >> natural() << toEndOfLine()).parse(infile); + if (!atoms) return NodeConstants::ProcessResult::Failed; + auto ats = std::get<0>(*atoms); + for (auto i = 0; i < ats / 14; ++i) + toEndOfLine().parse(infile); --nRotations; } diff --git a/src/nodes/importEPSRAtoStructure.h b/src/nodes/importEPSRAtoStructure.h index e8ab5e5db3..da4f4abf37 100644 --- a/src/nodes/importEPSRAtoStructure.h +++ b/src/nodes/importEPSRAtoStructure.h @@ -36,4 +36,4 @@ class ImportEPSRAtoStructureNode : public Node protected: // Perform processing NodeConstants::ProcessResult process() override; -}; \ No newline at end of file +}; From bb292c5f162251ba9e275850a6e495917a658281 Mon Sep 17 00:00:00 2001 From: Adam Washington Date: Wed, 8 Jul 2026 14:12:53 +0100 Subject: [PATCH 8/9] Remove LineParser from Poisson test --- tests/math/poisson.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/math/poisson.cpp b/tests/math/poisson.cpp index 009990cdc5..69632031c9 100644 --- a/tests/math/poisson.cpp +++ b/tests/math/poisson.cpp @@ -1,41 +1,41 @@ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright (c) 2026 Team Dissolve and contributors -#include "base/lineParser.h" +#include "base/applicative.h" +#include "base/parserLibrary.h" #include "math/poissonFit.h" #include "nodes/importXYData.h" #include "tests/testing.h" +#include namespace UnitTest { void testReconstruction(std::string inpAFile, std::string delfitFile, const std::vector> &targets, Data1D axisData) { - LineParser parser; - ASSERT_TRUE(parser.openInput(inpAFile)); + using namespace Parsers; + std::ifstream infile(inpAFile); + ASSERT_TRUE(infile); // First line contains parameters relating to energy / pressure calculation which we can skip - ASSERT_TRUE(parser.getArgsDelim(LineParser::Defaults) == LineParser::Success); + ASSERT_TRUE(toEndOfLine().parse(infile)); for (auto &[dataSet, column, errorThreshold] : targets) { // Data file index - ASSERT_TRUE(parser.getArgsDelim(LineParser::Defaults) == LineParser::Success); + auto index = (inlineSpaces() >> natural() << toEndOfLine()).parse(infile); + ASSERT_TRUE(index); - std::cout << std::format("Reading fit coefficients for data {} ({})...\n", dataSet, parser.argi(0)); - - // Number of coefficients, stepsize in r, sigma2 - ASSERT_TRUE(parser.getArgsDelim(LineParser::Defaults) == LineParser::Success); - const auto nCoeff = parser.argi(0); + std::cout << std::format("Reading fit coefficients for data {} ({})...\n", dataSet, std::get<0>(*index)); // Coefficients (all on one line) - ASSERT_TRUE(parser.getArgsDelim(LineParser::Defaults) == LineParser::Success); - ASSERT_TRUE(parser.nArgs() == nCoeff); - - std::vector fitCoefficients; - fitCoefficients.resize(nCoeff); - for (auto i = 0; i < nCoeff; ++i) - fitCoefficients[i] = parser.argd(i); + auto count = (inlineSpaces() >> natural() << toEndOfLine()).parse(infile); + ASSERT_TRUE(count); + auto nCoeff = std::get<0>(*count); + auto coefficients = (some(inlineSpaces() >> real()) << newlines()).parse(infile); + ASSERT_TRUE(coefficients); + auto fitCoefficients = std::get<0>(*coefficients); + ASSERT_EQ(nCoeff, fitCoefficients.size()); // Construct the fit PoissonFit coeffMinimiser(axisData); From bd75952672a9c49fb7a3f70ad7748cf4bfe882d0 Mon Sep 17 00:00:00 2001 From: Adam Washington Date: Wed, 8 Jul 2026 14:35:49 +0100 Subject: [PATCH 9/9] Remove LineParser entirely --- src/base/CMakeLists.txt | 2 - src/base/lineParser.cpp | 856 --------------------- src/base/lineParser.h | 230 ------ src/gui/render/renderable.cpp | 1 - src/gui/render/renderableConfiguration.cpp | 1 - src/gui/render/renderableData1D.cpp | 1 - src/gui/render/renderableData2D.cpp | 1 - src/gui/render/renderableData3D.cpp | 1 - src/gui/render/renderableSpecies.cpp | 1 - src/gui/render/renderableSpeciesSite.cpp | 1 - 10 files changed, 1095 deletions(-) delete mode 100644 src/base/lineParser.cpp delete mode 100644 src/base/lineParser.h diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index 90b0642706..bcd38172d7 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -8,8 +8,6 @@ add_library( enumOptionsBase.h geometry.cpp geometry.h - lineParser.cpp - lineParser.h lock.cpp lock.h messenger.cpp diff --git a/src/base/lineParser.cpp b/src/base/lineParser.cpp deleted file mode 100644 index 7d6084b983..0000000000 --- a/src/base/lineParser.cpp +++ /dev/null @@ -1,856 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#include "base/lineParser.h" -#include "base/messenger.h" -#include "base/sysFunc.h" -#include - -LineParser::LineParser() -{ - arguments_.clear(); - reset(); -} - -LineParser::~LineParser() -{ - closeFiles(); - - if (inputFile_ != nullptr) - delete inputFile_; - if (outputFile_ != nullptr) - delete outputFile_; - if (cachedFile_ != nullptr) - delete cachedFile_; - if (inputStrings_ != nullptr) - delete inputStrings_; -} - -/* - * Source / Destination Streams - */ - -// Reset data -void LineParser::reset() -{ - inputFilename_.clear(); - outputFilename_.clear(); - endOfLine_ = false; - line_.clear(); - linePos_ = 0; - lastLineNo_ = 0; - inputFile_ = nullptr; - outputFile_ = nullptr; - cachedFile_ = nullptr; - inputStrings_ = nullptr; - fileInput_ = true; - directOutput_ = false; - arguments_.clear(); -} - -// Return current stream for input -std::istream *LineParser::inputStream() const -{ - if (fileInput_) - return inputFile_; - return inputStrings_; -} - -// Return filename of current input file (if any) -std::string_view LineParser::inputFilename() const { return inputFilename_; } - -// Return filename of current output file (if any) -std::string_view LineParser::outputFilename() const { return outputFilename_; } - -// Return pointer to current line -std::string_view LineParser::line() const { return line_; } - -// Return integer line number of last read line -int LineParser::lastLineNo() const { return lastLineNo_; } - -// Open new file for reading -bool LineParser::openInput(std::string_view filename) -{ - if (inputFile_ != nullptr) - { - Messenger::warn("LineParser already appears to have an open file...\n"); - inputFile_->close(); - delete inputFile_; - inputFile_ = nullptr; - } - - fileInput_ = true; - - auto result = true; - inputFile_ = new std::ifstream(std::string(filename), std::ios::in | std::ios::binary); - if (!inputFile_->is_open()) - { - closeFiles(); - Messenger::warn("Failed to open file '{}' for reading.\n", filename); - result = false; - } - - lastLineNo_ = 0; - inputFilename_ = filename; - - return result; -} - -// Open input string for reading -bool LineParser::openInputString(std::string_view s) -{ - if (inputFile_ != nullptr) - { - Messenger::warn("LineParser already appears to have an open file...\n"); - inputFile_->close(); - delete inputFile_; - inputFile_ = nullptr; - } - if (inputStrings_ != nullptr) - { - Messenger::warn("LineParser already appears to have open strings...\n"); - delete inputStrings_; - inputStrings_ = nullptr; - } - - fileInput_ = false; - - // Create a new stringstream and copy the input string to it - inputStrings_ = new std::stringstream; - (*inputStrings_) << s; - inputStrings_->seekg(std::ios_base::beg); - - lastLineNo_ = 0; - - return true; -} - -// Open new stream for writing -bool LineParser::openOutput(std::string_view filename, bool directOutput) -{ - auto result = true; - - outputFilename_ = filename; - - // Check for existing output file - if ((outputFile_ != nullptr) || (cachedFile_ != nullptr)) - { - Messenger::warn("LineParser already appears to have an open file/cache...\n"); - if (outputFile_ != nullptr) - { - outputFile_->close(); - delete outputFile_; - outputFile_ = nullptr; - } - if (cachedFile_ != nullptr) - { - delete cachedFile_; - cachedFile_ = nullptr; - } - } - - // Open new file - directOutput_ = directOutput; - if (directOutput_) - { - outputFile_ = new std::ofstream(outputFilename_, std::ios::out); - if (!outputFile_->is_open()) - { - closeFiles(); - Messenger::error("Failed to open file '{}' for writing.\n", outputFilename_); - result = false; - } - } - else - cachedFile_ = new std::stringstream; - - return result; -} - -// Open existing stream for writing -bool LineParser::appendOutput(std::string_view filename) -{ - auto result = true; - - outputFilename_ = filename; - - // Check for existing output file - if ((outputFile_ != nullptr) || (cachedFile_ != nullptr)) - { - Messenger::warn("LineParser already appears to have an open file/cache...\n"); - if (outputFile_ != nullptr) - { - outputFile_->close(); - delete outputFile_; - outputFile_ = nullptr; - } - if (cachedFile_ != nullptr) - { - delete cachedFile_; - cachedFile_ = nullptr; - } - } - - // Open file for appending - directOutput_ = true; - outputFile_ = new std::ofstream(outputFilename_, std::ios::app); - if (!outputFile_->is_open()) - { - closeFiles(); - Messenger::error("Failed to open file '{}' for writing.\n", outputFilename_); - result = false; - } - - return result; -} - -// Close file -void LineParser::closeFiles() -{ - if (inputFile_ != nullptr) - { - inputFile_->close(); - delete inputFile_; - } - if (outputFile_ != nullptr) - { - outputFile_->close(); - delete outputFile_; - } - - if (inputStrings_ != nullptr) - delete inputStrings_; - - reset(); -} - -// Return whether current file source is good for reading -bool LineParser::isFileGoodForReading() const -{ - auto result = true; - - if (fileInput_ && (inputFile_ == nullptr)) - result = false; - else if (fileInput_ && (!inputFile_->is_open())) - result = false; - else if ((!fileInput_) && (!inputStrings_)) - result = false; - - return result; -} - -// Return whether current file source is good for writing -bool LineParser::isFileGoodForWriting() const -{ - auto result = true; - if (directOutput_) - { - if (outputFile_ == nullptr) - result = false; - else if (!outputFile_->is_open()) - result = false; - } - - return result; -} - -// Peek next character in input stream -char LineParser::peek() const -{ - if (inputStream() == nullptr) - return '\0'; - return inputStream()->peek(); -} - -// Tell current position of input stream -std::streampos LineParser::tellg() const -{ - std::streampos result = 0; - if (inputStream() != nullptr) - result = inputStream()->tellg(); - else - Messenger::warn("LineParser tried to tellg() on a non-existent input file.\n"); - return result; -} - -// Seek position in input stream -void LineParser::seekg(std::streampos pos) -{ - if (inputFile_ != nullptr) - { - if (inputStream()->eof()) - inputStream()->clear(); - inputStream()->seekg(pos); - } - else - Messenger::warn("LineParser tried to seekg() on a non-existent input file.\n"); -} - -// Seek n bytes in specified direction in input stream -void LineParser::seekg(std::streamoff off, std::ios_base::seekdir dir) -{ - if (inputStream() != nullptr) - inputFile_->seekg(off, dir); - else - Messenger::warn("LineParser tried to seekg() on a non-existent input file.\n"); -} - -// Rewind input stream to start -void LineParser::rewind() -{ - if (inputStream() != nullptr) - inputFile_->seekg(0, std::ios::beg); - else - Messenger::print("No file currently open to rewind.\n"); -} - -// Return whether the end of the input stream has been reached (or only whitespace remains) -bool LineParser::eofOrBlank() const -{ - auto result = false; - - // Do we have a valid input stream? - if (inputStream() == nullptr) - { - return true; - } - - // Simple check first - is this the end of the file? - if (inputStream()->eof()) - { - return true; - } - - // Otherwise, store the current file position and search for a non-whitespace character (or end of file) - std::streampos pos = inputStream()->tellg(); - - // Skip through whitespace, searching for 'hard' character - char c; - result = true; - do - { - inputStream()->get(c); - if (inputStream()->eof()) - break; - // If a whitespace character then skip it.... - if ((c == ' ') || (c == '\r') || (c == '\n') || (c == '\t') || (c == '\0')) - { - if (inputStream()->eof()) - break; - else - continue; - } - result = false; - break; - } while (true); - inputStream()->seekg(pos); - - return result; -} - -/* - * Read/Write Routines - */ - -// Gets next delimited arg from internal line -bool LineParser::getNextArg(int optionMask, std::string &arg) -{ - // Get the next input chunk from the internal string and put into argument specified. - auto done = false, hadquotes = false, failed = false, quoting = false; - char c, quotechar = '\0'; - endOfLine_ = false; - - while (linePos_ < line_.length()) - { - c = line_[linePos_]; - switch (c) - { - // End of line markers - case (10): // Line feed (\n) - case (13): // Carriage Return - done = true; - endOfLine_ = true; - break; - // Delimiters - // If we encounter one and arg length != 0 this signals the end of the argument. - case (','): // Comma - if (!(optionMask & LineParser::CommasAreDelimiters)) - { - arg += c; - break; - } - case (9): // Horizontal Tab - case (' '): // Space - if (quotechar != '\0') - arg += c; - else if (arg.length() != 0) - done = true; - break; - // Quote marks - // If LineParser::IgnoreQuotes, don't keep delimiters and other quote marks inside the quoted text. - case (34): // Double quotes - case (39): // Single quotes - if (optionMask & LineParser::IgnoreQuotes) - break; - if (quotechar == '\0') - { - quotechar = c; - quoting = true; - } - else if (quotechar == c) - { - quotechar = '\0'; - hadquotes = true; - done = true; - quoting = false; - } - else - arg += c; - break; - // Curly brackets - treat in the same way as quotes - case ('{'): - case ('}'): - // If explicitly not using braces, add as normal character - if (!(optionMask & LineParser::UseBraces)) - arg += c; - else - { - // If the quotechar is a left brace and we have a right brace, stop quoting - if ((quotechar == '{') && (c == '}')) - { - quotechar = '\0'; - break; - } - - // If we are already quoting by some other means, add character and exit - if (quotechar != '\0') - arg += c; - - // No previous quoting, so begin quoting if '{' - if (c == '{') - quotechar = '{'; - } - break; - // Parentheses - case ('('): // Left parenthesis - case (')'): // Right parenthesis - if (optionMask & LineParser::StripBrackets) - break; - arg += c; - break; - // Comment markers - case ('#'): // "#" Rest/all of line is a comment - if (quoting) - { - arg += c; - break; - } - endOfLine_ = true; - done = true; - break; - // Normal character - default: - arg += c; - break; - } - // Increment line position - ++linePos_; - if (done || failed) - break; - } - - // Check for end of line - if (linePos_ == line_.length()) - endOfLine_ = true; - - if (failed) - return false; - - // Return false if there are no characters in the argument, unless it was a quoted "null string" arg - return (arg.length() == 0 ? (hadquotes ? true : false) : true); -} - -// Get all arguments (delimited) from LineParser::line_ -void LineParser::getAllArgsDelim(int optionMask) -{ - // Parse the string in 'line_' into arguments in 'args' - arguments_.clear(); - endOfLine_ = false; - while (!endOfLine_) - { - // We must pass on the current optionMask, else it will be reset by the default value in getNextArg() - std::string nextArg; - if (getNextArg(optionMask, nextArg)) - { - // Add this char to the list - arguments_.push_back(nextArg); - } - } -} - -// Parse delimited (from file) -LineParser::ParseReturnValue LineParser::getArgsDelim(int optionMask) -{ - LineParser::ParseReturnValue result = readNextLine(optionMask); - - // Parse the line before returning the result of the initial line read - getAllArgsDelim(optionMask); - - return result; -} - -// Set line and parse into delimited arguments -void LineParser::getArgsDelim(int optionMask, std::string_view s) -{ - line_ = s; - linePos_ = 0; - getAllArgsDelim(optionMask); -} - -// Read single line from internal file source -LineParser::ParseReturnValue LineParser::readNextLine(int optionMask) -{ - line_.clear(); - - // Returns : 0=ok, 1=error, -1=eof - if (fileInput_ && (inputFile_ == nullptr)) - { - Messenger::error("No input file open for LineParser::readNextLine.\n"); - return LineParser::Fail; - } - else if (inputStream()->eof()) - return LineParser::EndOfFile; - - // Loop until we get 'suitable' line from file - int nchars, nspaces; - auto result = LineParser::Fail; - while (result != LineParser::Success) - { - char c; - result = LineParser::Fail; - while (inputStream()->get(c).good()) - { - if (c == '\r') - { - if (inputStream()->peek() == '\n') - inputStream()->ignore(); - break; - } - else if (c == '\n') - break; - else if ((c == ';') && (optionMask & LineParser::SemiColonLineBreaks)) - break; - - line_ += c; - - // Check here for overfilling the line_ buffer - perhaps it's a binary file? - if (line_.length() >= 8096) - result = LineParser::Fail; - } - ++lastLineNo_; - Messenger::printVerbose("Line from file is: [{}]\n", line_); - - // Remove comments from line - if (!(optionMask & LineParser::KeepComments)) - DissolveSys::removeComments(line_); - - // If we are skipping blank lines, check for a blank line here - if (!(optionMask & LineParser::KeepBlanks)) - { - // Now, see if our line contains only blanks - nchars = 0; - nspaces = 0; - for (auto &c : line_) - { - nchars++; - if (std::isspace(c)) - ++nspaces; - } - - if (nchars == nspaces) - { - // Blank line - if we're at the end of the file, return EOF. - // Otherwise, read in another line. - if (inputStream()->eof()) - result = LineParser::EndOfFile; - else if (inputStream()->fail()) - result = LineParser::Fail; - else - continue; - } - else - result = LineParser::Success; - } - else - result = LineParser::Success; - - linePos_ = 0; - - // Exit on EOF or error - if (result != LineParser::Success) - break; - }; - - return result; -} - -// Read next line from internal source file, setting as parsing source and copying to specified string -LineParser::ParseReturnValue LineParser::readNextLine(int optionMask, std::string &dest) -{ - LineParser::ParseReturnValue result = readNextLine(optionMask); - if (result != LineParser::Success) - return result; - dest = line_; - return result; -} - -// Skip lines from file -LineParser::ParseReturnValue LineParser::skipLines(int nlines) -{ - LineParser::ParseReturnValue result; - for (auto n = 0; n < nlines; ++n) - { - result = readNextLine(LineParser::KeepBlanks); - if (result != LineParser::Success) - return result; - } - - return LineParser::Success; -} - -// Write line to file -bool LineParser::writeLine(std::string_view s) const -{ - auto result = true; - - if (!directOutput_) - { - if (cachedFile_ == nullptr) - { - Messenger::print("Unable to delayed-writeLine - destination cache is not open.\n"); - return false; - } - else - (*cachedFile_) << s << std::endl; - } - else if (outputFile_ == nullptr) - { - Messenger::print("Unable to direct-writeLine - destination file is not open.\n"); - return false; - } - else - (*outputFile_) << s << std::endl; - - return result; -} - -// Write long int argument as single line -bool LineParser::writeArg(long int i) const { return writeLineF("{}\n", i); } - -// Write long long int argument as single line -bool LineParser::writeArg(long long int i) const { return writeLineF("{}\n", i); } - -// Read long int argument as single line -bool LineParser::readArg(long int &i) -{ - if (readNextLine(LineParser::Defaults) != LineParser::Success) - return false; - - i = std::stol(line_); - - return true; -} - -// Read long long int argument as single line -bool LineParser::readArg(long long int &i) -{ - if (readNextLine(LineParser::Defaults) != LineParser::Success) - return false; - - i = std::stoll(line_); - - return true; -} - -// Commit cached output stream to actual output file -bool LineParser::commitCache() -{ - auto result = true; - - // Were we using cached writing? - if (directOutput_) - { - Messenger::error("Tried to commit cached writes when direct output was enabled.\n"); - return false; - } - - std::ofstream outputFile(outputFilename_); - if (outputFile.is_open()) - { - outputFile << cachedFile_->str(); - outputFile.close(); - } - else - { - Messenger::error("Couldn't open output file '{}' for writing.\n", outputFilename_); - result = false; - } - - return result; -} - -/* - * Argument Data - */ - -// Returns number of arguments grabbed from last parse -int LineParser::nArgs() const { return arguments_.size(); } - -// Returns the specified argument as a string -std::string LineParser::args(int i) const -{ - if ((i < 0) || (i >= nArgs())) - { - Messenger::warn("LineParser::args() - Argument {} is out of range - returning \"NULL\"...\n", i); - return "NULL"; - } - return arguments_[i]; -} - -// Returns the specified argument as a character string view -std::string_view LineParser::argsv(int i) const -{ - if ((i < 0) || (i >= nArgs())) - { - Messenger::warn("LineParser::args() - Argument {} is out of range - returning \"NULL\"...\n", i); - return "NULL"; - } - return arguments_[i]; -} - -// Returns the specified argument as an integer -int LineParser::argi(int i) const -{ - if ((i < 0) || (i >= nArgs())) - { - Messenger::warn("LineParser::argi() - Argument {} is out of range - returning 0...\n", i); - return 0; - } - return std::stoi(arguments_[i]); -} - -// Returns the specified argument as a long integer -long int LineParser::argli(int i) const -{ - if ((i < 0) || (i >= nArgs())) - { - Messenger::warn("LineParser::argli() - Argument {} is out of range - returning 0...\n", i); - return 0; - } - return std::stol(arguments_[i]); -} - -// Returns the specified argument as a double -double LineParser::argd(int i) const -{ - if ((i < 0) || (i >= nArgs())) - { - Messenger::warn("LineParser::argd() - Argument {} is out of range - returning 0.0...\n", i); - return 0.0; - } - - // Attempt to convert the current argument - try - { - return std::stod(arguments_[i]); - } - catch (std::out_of_range &rangeError) - { - std::string exponent{DissolveSys::afterChar(arguments_[i], "eE")}; - if (exponent.empty()) - Messenger::printVerbose( - "LineParser::argd() : String '{}' causes an out-of-range exception on conversion - returning 0.0...", - arguments_[i]); - else if (std::stoi(exponent) >= std::numeric_limits::max_exponent) - Messenger::printVerbose("LineParser::argd() : String '{}' causes an overflow on conversion - returning 0.0...", - arguments_[i]); - else if (std::stoi(exponent) <= std::numeric_limits::min_exponent) - Messenger::printVerbose("LineParser::argd() : String '{}' causes an underflow on conversion - returning 0.0...", - arguments_[i]); - } - - return 0.0; -} - -// Returns the specified argument as a bool -bool LineParser::argb(int i) const -{ - if ((i < 0) || (i >= nArgs())) - { - Messenger::warn("LineParser::argb() - Argument {} is out of range - returning false...\n", i); - return false; - } - return DissolveSys::stob(arguments_[i]); -} - -// Return the specified and next two arguments as a Vector3i -Vector3i LineParser::arg3i(int i) const -{ - if ((i < 0) || (i >= (nArgs() - 2))) - { - Messenger::warn("LineParser::arg3i() - Argument {} is out of range - returning Vector3i()...\n", i); - return Vector3i(); - } - return Vector3i(argi(i), argi(i + 1), argi(i + 2)); -} - -// Return the specified and next two arguments as a Vector3 -Vector3 LineParser::arg3d(int i) const -{ - if ((i < 0) || (i >= (nArgs() - 2))) - { - Messenger::warn("LineParser::arg3d() - Argument {} is out of range - returning Vector3()...\n", i); - return Vector3(); - } - return Vector3(argd(i), argd(i + 1), argd(i + 2)); -} - -// Return a vector of double parameters, starting from the specified argument -std::vector LineParser::argvd(int i) const -{ - if ((i < 0) || (i >= nArgs())) - { - Messenger::warn("LineParser::argvd() - Argument {} is out of range - returning std::vector()...\n", i); - return std::vector(); - } - std::vector result; - for (auto n = i; n < nArgs(); ++n) - result.push_back(argd(n)); - return result; -} - -// Returns whether the specified argument exists (has been provided) -bool LineParser::hasArg(int i) const -{ - if ((i < 0) || (i >= nArgs())) - return false; - return true; -} - -// Utility LineParser::ParseReturnValue converter to int -int LineParser::getIntFromParseReturnValue(LineParser::ParseReturnValue value) -{ - int enumValue = value; - return enumValue; -} - -// Utility LineParser::ParseReturnValue converter from int -LineParser::ParseReturnValue LineParser::getParseReturnValueFromInt(int value) -{ - if (value == -1) - return LineParser::ParseReturnValue::EndOfFile; - else if (value == 0) - return LineParser::ParseReturnValue::Success; - - return LineParser::ParseReturnValue::Fail; -} diff --git a/src/base/lineParser.h b/src/base/lineParser.h deleted file mode 100644 index 12ae03fc43..0000000000 --- a/src/base/lineParser.h +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright (c) 2026 Team Dissolve and contributors - -#pragma once - -#include "base/messenger.h" -#include "math/vector3.h" -#include "math/vector3i.h" -#include -#include -#include -#include -#include - -// Line Parser -class LineParser -{ - public: - LineParser(); - ~LineParser(); - // Parse Options Enum - enum ParseOption - { - Defaults = 0, /* Default parsing behaviour */ - KeepComments = 1, /* Automatically strip comments (beginning # or //) from files */ - IgnoreQuotes = 2, /* Quoted text in files will not be retained as a single argument */ - KeepBlanks = 4, /* Don't automatically skip blank lines (those containing nothing or only whitespace) */ - StripBrackets = 8, /* Remove parentheses during parsing */ - NoEscapes = 16, /* Don't convert excaped characters */ - UseBraces = 32, /* Text inside curly brackets is retaind as a single argument */ - CommasAreDelimiters = 64, /* Treat commas as delimiting marks in files */ - SemiColonLineBreaks = 128, /* Treat semicolons as line-breaks */ - nParseOptions = 9 - }; - // Parse Return Value - enum ParseReturnValue - { - EndOfFile = -1, /* Operation encountered the end of the current file */ - Success = 0, /* Operation succeeded */ - Fail = 1 /* Operation failed */ - }; - - /* - * Source / Destination Streams - */ - private: - // Current input filename (if any) - std::string inputFilename_; - // Current output filename (if any) - std::string outputFilename_; - // Line to parse - std::string line_; - // Current reading position in line - int linePos_; - // Integer line number of last read line - int lastLineNo_; - // Source stream for reading - std::ifstream *inputFile_; - // Source string stream for reading - std::stringstream *inputStrings_; - // Target stream for writing - std::ofstream *outputFile_; - // Target stream for cached writing - std::stringstream *cachedFile_; - - private: - // Reset data - void reset(); - // Return current stream for input - std::istream *inputStream() const; - - public: - // Return filename of current inputFile (if any) - std::string_view inputFilename() const; - // Return filename of current outputFile (if any) - std::string_view outputFilename() const; - // Return current line - std::string_view line() const; - // Return integer line number of last read line - int lastLineNo() const; - // Return read-only status of file - bool isFileReadOnly() const; - // Open new file for reading - bool openInput(std::string_view filename); - // Open input string for reading - bool openInputString(std::string_view s); - // Open new stream for writing - bool openOutput(std::string_view filename, bool directOutput = true); - // Open existing stream for writing - bool appendOutput(std::string_view filename); - // Close file(s) - void closeFiles(); - // Return whether current file source is good for reading - bool isFileGoodForReading() const; - // Return whether current file source is good for writing - bool isFileGoodForWriting() const; - // Tell current position of input stream - std::streampos tellg() const; - // Peek next character in input stream - char peek() const; - // Seek position in input stream - void seekg(std::streampos pos); - // Seek n bytes in specified direction in input stream - void seekg(std::streamoff off, std::ios_base::seekdir dir); - // Rewind input stream to start - void rewind(); - // Return whether the end of the input stream has been reached (or only whitespace remains) - bool eofOrBlank() const; - - /* - * Read/Write Routines - */ - private: - // Whether input is from file or strings - bool fileInput_; - // Whether output is cached or direct - bool directOutput_; - // Whether the end of the string has been found in getNextArg() - bool endOfLine_; - - private: - // Gets next delimited arg from internal line - bool getNextArg(int optionMask, std::string &destarg); - // Gets all delimited args from internal line - void getAllArgsDelim(int optionMask); - - public: - // Read line from file and do delimited parse - ParseReturnValue getArgsDelim(int optionMask = LineParser::Defaults); - // Set line and parse into delimited arguments - void getArgsDelim(int optionMask, std::string_view s); - // Read next line from internal source file, setting as parsing source - ParseReturnValue readNextLine(int optionMask); - // Read next line from internal source file, setting as parsing source and copying to specified string - ParseReturnValue readNextLine(int optionMask, std::string &dest); - // Skip 'n' lines from internal file - ParseReturnValue skipLines(int nlines); - // Write line to file - bool writeLine(std::string_view s) const; - // Write formatted line to file - template bool writeLineF(std::format_string format, Args... args) const - { - auto result = true; - - if (!directOutput_) - { - if (cachedFile_ == nullptr) - { - Messenger::print("Unable to delayed-writeLineF - destination cache is not open.\n"); - return false; - } - } - else if (outputFile_ == nullptr) - { - Messenger::print("Unable to direct-writeLineF - destination file is not open.\n"); - return false; - } - - // Format the line and store it - if (directOutput_) - (*outputFile_) << std::format(format, std::forward(args)...); - else - (*cachedFile_) << std::format(format, std::forward(args)...); - - return result; - } - // Print banner comment of fixed width - template bool writeBannerComment(std::format_string format, Args... args) - { - const auto bannerWidth = 80; - static std::string bannerBorder = std::format("#{0:=^{1}}#", "", bannerWidth - 2); - - // Finally, print the banner - if (!writeLineF("\n{}\n", bannerBorder)) - return false; - if (!writeLineF("#{:^{}}#", std::format(format, std::forward(args)...), bannerWidth - 2)) - return false; - if (!writeLineF("\n{}\n", bannerBorder)) - return false; - - return true; - } - // Write long int argument as single line - bool writeArg(long int i) const; - // Write long long int argument as single line - bool writeArg(long long int i) const; - // Read long int argument as single line - bool readArg(long int &i); - // Read long long int argument as single line - bool readArg(long long int &i); - // Commit cached output stream to actual output file - bool commitCache(); - - /* - * Argument Data - */ - private: - // Parsed arguments - std::vector arguments_; - - public: - // Returns number of arguments grabbed from last parse - int nArgs() const; - // Returns the specified argument as a string - std::string args(int i) const; - // Returns the specified argument as a string view - std::string_view argsv(int i) const; - // Returns the specified argument as an integer - int argi(int i) const; - // Returns the specified argument as a long integer - long int argli(int i) const; - // Returns the specified argument as a double - double argd(int i) const; - // Returns the specified argument as a bool - bool argb(int i) const; - // Return the specified and next two arguments as a Vector3i - Vector3i arg3i(int i) const; - // Return the specified and next two arguments as a Vector3 - Vector3 arg3d(int i) const; - // Return a vector of double parameters, starting from the specified argument - std::vector argvd(int i) const; - // Returns whether the specified argument exists - bool hasArg(int i) const; - - private: - // Utility LineParser::ParseReturnValue converter to int - int getIntFromParseReturnValue(LineParser::ParseReturnValue value); - // Utility LineParser::ParseReturnValue converter from int - LineParser::ParseReturnValue getParseReturnValueFromInt(int value); -}; diff --git a/src/gui/render/renderable.cpp b/src/gui/render/renderable.cpp index 53fc8e6bb5..172639e8e0 100644 --- a/src/gui/render/renderable.cpp +++ b/src/gui/render/renderable.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "gui/render/renderable.h" -#include "base/lineParser.h" #include "base/sysFunc.h" #include "gui/render/renderableGroupManager.h" #include "gui/render/view.h" diff --git a/src/gui/render/renderableConfiguration.cpp b/src/gui/render/renderableConfiguration.cpp index 46dab22fb1..d31f7c56af 100644 --- a/src/gui/render/renderableConfiguration.cpp +++ b/src/gui/render/renderableConfiguration.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "gui/render/renderableConfiguration.h" -#include "base/lineParser.h" #include "classes/box.h" #include "classes/speciesAtom.h" #include "classes/speciesBond.h" diff --git a/src/gui/render/renderableData1D.cpp b/src/gui/render/renderableData1D.cpp index 2dae22e64f..38c27b1cad 100644 --- a/src/gui/render/renderableData1D.cpp +++ b/src/gui/render/renderableData1D.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "gui/render/renderableData1D.h" -#include "base/lineParser.h" #include "gui/render/renderableGroupManager.h" #include "gui/render/view.h" #include "math/sampledData1D.h" diff --git a/src/gui/render/renderableData2D.cpp b/src/gui/render/renderableData2D.cpp index d6d053a9e3..fddbd8beec 100644 --- a/src/gui/render/renderableData2D.cpp +++ b/src/gui/render/renderableData2D.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "gui/render/renderableData2D.h" -#include "base/lineParser.h" #include "gui/render/renderableGroupManager.h" #include "gui/render/view.h" #include "math/data2D.h" diff --git a/src/gui/render/renderableData3D.cpp b/src/gui/render/renderableData3D.cpp index 58fff0a981..3a9b5710cd 100644 --- a/src/gui/render/renderableData3D.cpp +++ b/src/gui/render/renderableData3D.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "gui/render/renderableData3D.h" -#include "base/lineParser.h" #include "gui/render/renderableGroupManager.h" #include "gui/render/view.h" #include "math/data3D.h" diff --git a/src/gui/render/renderableSpecies.cpp b/src/gui/render/renderableSpecies.cpp index f4b2127418..c333ab0d87 100644 --- a/src/gui/render/renderableSpecies.cpp +++ b/src/gui/render/renderableSpecies.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "gui/render/renderableSpecies.h" -#include "base/lineParser.h" #include "classes/configurationAtom.h" #include "data/elementColours.h" #include "gui/render/renderableConfiguration.h" diff --git a/src/gui/render/renderableSpeciesSite.cpp b/src/gui/render/renderableSpeciesSite.cpp index 35b5cbd728..a499bac379 100644 --- a/src/gui/render/renderableSpeciesSite.cpp +++ b/src/gui/render/renderableSpeciesSite.cpp @@ -2,7 +2,6 @@ // Copyright (c) 2026 Team Dissolve and contributors #include "gui/render/renderableSpeciesSite.h" -#include "base/lineParser.h" #include "classes/configurationAtom.h" #include "classes/molecule.h" #include "classes/site.h"