Mantid
Loading...
Searching...
No Matches
FileValidator.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
9#include <boost/algorithm/string/case_conv.hpp>
10#include <filesystem>
11#include <fstream>
12#include <memory>
13#include <sstream>
14
15namespace Mantid::Kernel {
16
17namespace {
18// Initialize the static logger
19Logger g_log("FileValidator");
20} // namespace
21
27FileValidator::FileValidator(const std::vector<std::string> &extensions, bool testFileExists)
28 : TypedValidator<std::string>(), m_testExist(testFileExists) {
29 for (const auto &extension : extensions) {
30 const std::string ext = boost::to_lower_copy(extension);
31 if (std::find(m_extensions.begin(), m_extensions.end(), ext) == m_extensions.end()) {
32 m_extensions.emplace_back(ext);
33 }
34 }
35}
36
38std::vector<std::string> FileValidator::allowedValues() const { return m_extensions; }
39
44IValidator_sptr FileValidator::clone() const { return std::make_shared<FileValidator>(*this); }
45
51std::string FileValidator::checkValidity(const std::string &value) const {
52 // Check if the path is syntactically valid
53 try {
54 std::filesystem::path testPath(value);
55 // Just creating a path object validates syntax in most cases
56 } catch (const std::exception &) {
57 return "Error in path syntax: \"" + value + "\".";
58 }
59
60 // Check the extension but just issue a warning if it is not one of the
61 // suggested values
62 if (!(value.empty())) {
63 if (!(this->endswith(value))) {
64 // Dropped from warning to debug level as it was printing out on every
65 // search of the archive, even when successful. re #5998
66 g_log.debug() << "Unrecognised extension in file \"" << value << "\"";
67 if (!this->m_extensions.empty()) {
68 g_log.debug() << " [ ";
69 for (const auto &extension : this->m_extensions)
70 g_log.debug() << extension << " ";
71 g_log.debug() << "]";
72 }
73 g_log.debug() << "\".\n";
74 }
75 }
76
77 // create a variable for the absolute path to be used in error messages
78 std::string abspath(value);
79 if (!value.empty()) {
80 std::filesystem::path path(value);
81 if (path.is_absolute())
82 abspath = std::filesystem::absolute(path).string();
83 }
84
85 // If the file is required to exist check it is there
86 if (m_testExist && (value.empty() || !std::filesystem::exists(value))) {
87 return "File \"" + abspath + "\" not found";
88 }
89
90 if (m_testExist && (std::filesystem::exists(value))) {
91 std::ifstream in;
92 in.open(value.c_str());
93 if (!in) {
94 std::stringstream error;
95 error << "Failed to open " + value + ": " << strerror(errno);
96 return error.str();
97 }
98 }
99
100 // Otherwise we are okay, file extensions are just a suggestion so no
101 // validation on them is necessary
102 return "";
103}
104
110bool has_ending(const std::string &value, const std::string &ending) {
111 if (ending.empty()) // always match against an empty extension
112 return true;
113 if (value.length() < ending.length()) // filename is not long enough
114 return false;
115 int result = value.compare(value.length() - ending.length(), ending.length(), ending);
116 return (result == 0); // only care if it matches
117}
118
124bool FileValidator::endswith(const std::string &value) const {
125 if (m_extensions.empty()) // automatically match a lack of extensions
126 return true;
127 if ((m_extensions.size() == 1) && (m_extensions.begin()->empty()))
128 return true;
129
130 // create a lowercase copy of the filename
131 std::string value_copy(value);
132 std::transform(value_copy.begin(), value_copy.end(), value_copy.begin(), tolower);
133
134 // check for the ending
135 return std::any_of(m_extensions.cbegin(), m_extensions.cend(), [&](const auto extension) {
136 return has_ending(value, extension) || has_ending(value_copy, extension);
137 });
138}
139
140} // namespace Mantid::Kernel
double value
The value of the point.
Definition FitMW.cpp:51
double error
bool m_testExist
Flag indicating whether to test for existence of filename.
std::string checkValidity(const std::string &value) const override
If m_fullTest=true if checks that the files exists, otherwise just that path syntax looks valid.
bool endswith(const std::string &value) const
Checks the extension of a filename.
std::vector< std::string > m_extensions
The list of permitted extensions.
std::vector< std::string > allowedValues() const override
Returns the set of valid values.
IValidator_sptr clone() const override
Clone the validator.
FileValidator(const std::vector< std::string > &extensions=std::vector< std::string >(), bool testFileExists=true)
Constructor.
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
bool has_ending(const std::string &value, const std::string &ending)
Confirm that the value string ends with then ending string.
std::shared_ptr< IValidator > IValidator_sptr
A shared_ptr to an IValidator.
Definition IValidator.h:26
STL namespace.