From fb16cb93fdeff4dc079622a9f5bd498ae4057730 Mon Sep 17 00:00:00 2001 From: Henry Fredrick Schreiner Date: Mon, 30 Jan 2017 10:05:31 -0500 Subject: [PATCH] Added file validator functions, not used yet --- include/CLI.hpp | 60 +++++++++++++++++++++++++++++++++++++++------ tests/SmallTest.cpp | 24 ++++++++++++++++++ 2 files changed, 77 insertions(+), 7 deletions(-) diff --git a/include/CLI.hpp b/include/CLI.hpp index b15997c1..42dbbf84 100644 --- a/include/CLI.hpp +++ b/include/CLI.hpp @@ -14,6 +14,12 @@ #include #include +// C standard library +// Only needed for existence checking +// Could be swapped for filesystem in C++17 +#include +#include + //#define CLI_LOG 1 namespace CLI { @@ -61,6 +67,7 @@ struct Combiner { bool positional; bool required; bool defaulted; + std::vector> validators; /// Can be or-ed together Combiner operator | (Combiner b) const { @@ -69,18 +76,49 @@ struct Combiner { self.positional = positional || b.positional; self.required = required || b.required; self.defaulted = defaulted || b.defaulted; + self.validators.reserve(validators.size() + b.validators.size()); + self.validators.insert(self.validators.end(), validators.begin(), validators.end()); + self.validators.insert(self.validators.end(), b.validators.begin(), b.validators.end()); return self; } /// Call to give the number of arguments expected on cli Combiner operator() (int n) const { - return Combiner{n, positional, required, defaulted}; + Combiner self = *this; + self.num = n; + return *this; + } + /// Call to give a validator + Combiner operator() (std::function func) const { + Combiner self = *this; + self.validators.push_back(func); + return self; } Combiner operator, (Combiner b) const { return *this | b; } }; +bool _ExistingFile(std::string filename) { +// std::fstream f(name.c_str()); +// return f.good(); +// Fastest way according to http://stackoverflow.com/questions/12774207/fastest-way-to-check-if-a-file-exist-using-standard-c-c11-c + struct stat buffer; + return (stat(filename.c_str(), &buffer) == 0); +} + +bool _ExistingDirectory(std::string filename) { + struct stat buffer; + if(stat(filename.c_str(), &buffer) == 0 && (buffer.st_mode & S_IFDIR) ) + return true; + return false; +} + +bool _NonexistentPath(std::string filename) { + struct stat buffer; + return stat(filename.c_str(), &buffer) != 0; +} + struct Error : public std::runtime_error { Error(std::string parent, std::string name) : runtime_error(parent + ": " + name) {} }; @@ -137,12 +175,20 @@ std::tuple split(std::string fullname) { } else throw BadNameString(fullname); } -const Combiner NOTHING {0, false,false,false}; -const Combiner REQUIRED {1, false,true, false}; -const Combiner DEFAULT {1, false,false,true}; -const Combiner POSITIONAL{1, true, false,false}; -const Combiner ARGS {1, false,false,false}; -const Combiner UNLIMITED {-1,false,false,false}; +const Combiner NOTHING {0, false,false,false, {}}; +const Combiner REQUIRED {1, false,true, false, {}}; +const Combiner DEFAULT {1, false,false,true, {}}; +const Combiner POSITIONAL {1, true, false,false, {}}; +const Combiner ARGS {1, false,false,false, {}}; +const Combiner UNLIMITED {-1,false,false,false, {}}; +const Combiner VALIDATORS {1, false, false, false, {}}; + +// Warning about using these validators: +// The files could be added/deleted after the validation. This is not common, +// but if this is a possibility, check the file you open afterwards +const Combiner ExistingFile {1, false, false, false, {_ExistingFile}}; +const Combiner ExistingDirectory {1, false, false, false, {_ExistingDirectory}}; +const Combiner NonexistentPath {1, false, false, false, {_NonexistentPath}}; typedef std::vector> results_t; typedef std::function callback_t; diff --git a/tests/SmallTest.cpp b/tests/SmallTest.cpp index 22e41727..924af48d 100644 --- a/tests/SmallTest.cpp +++ b/tests/SmallTest.cpp @@ -1,5 +1,7 @@ #include "CLI.hpp" #include "gtest/gtest.h" +#include +#include TEST(Split, GoodStrings) { @@ -41,3 +43,25 @@ TEST(Split, BadStrings) { } + +TEST(Validators, FileExists) { + std::string myfile{"TestFileNotUsed.txt"}; + EXPECT_FALSE(CLI::_ExistingFile(myfile)); + bool ok = static_cast(std::ofstream(myfile.c_str()).put('a')); // create file + EXPECT_TRUE(ok); + EXPECT_TRUE(CLI::_ExistingFile(myfile)); + + std::remove(myfile.c_str()); + EXPECT_FALSE(CLI::_ExistingFile(myfile)); +} + +TEST(Validators, FileNotExists) { + std::string myfile{"TestFileNotUsed.txt"}; + EXPECT_TRUE(CLI::_NonexistentPath(myfile)); + bool ok = static_cast(std::ofstream(myfile.c_str()).put('a')); // create file + EXPECT_TRUE(ok); + EXPECT_FALSE(CLI::_NonexistentPath(myfile)); + + std::remove(myfile.c_str()); + EXPECT_TRUE(CLI::_NonexistentPath(myfile)); +}