Commit fb16cb93fdeff4dc079622a9f5bd498ae4057730
1 parent
b5ea5ce0
Added file validator functions, not used yet
Showing
2 changed files
with
77 additions
and
7 deletions
include/CLI.hpp
| ... | ... | @@ -14,6 +14,12 @@ |
| 14 | 14 | #include <iomanip> |
| 15 | 15 | #include <numeric> |
| 16 | 16 | |
| 17 | +// C standard library | |
| 18 | +// Only needed for existence checking | |
| 19 | +// Could be swapped for filesystem in C++17 | |
| 20 | +#include <sys/types.h> | |
| 21 | +#include <sys/stat.h> | |
| 22 | + | |
| 17 | 23 | //#define CLI_LOG 1 |
| 18 | 24 | |
| 19 | 25 | namespace CLI { |
| ... | ... | @@ -61,6 +67,7 @@ struct Combiner { |
| 61 | 67 | bool positional; |
| 62 | 68 | bool required; |
| 63 | 69 | bool defaulted; |
| 70 | + std::vector<std::function<bool(std::string)>> validators; | |
| 64 | 71 | |
| 65 | 72 | /// Can be or-ed together |
| 66 | 73 | Combiner operator | (Combiner b) const { |
| ... | ... | @@ -69,18 +76,49 @@ struct Combiner { |
| 69 | 76 | self.positional = positional || b.positional; |
| 70 | 77 | self.required = required || b.required; |
| 71 | 78 | self.defaulted = defaulted || b.defaulted; |
| 79 | + self.validators.reserve(validators.size() + b.validators.size()); | |
| 80 | + self.validators.insert(self.validators.end(), validators.begin(), validators.end()); | |
| 81 | + self.validators.insert(self.validators.end(), b.validators.begin(), b.validators.end()); | |
| 72 | 82 | return self; |
| 73 | 83 | } |
| 74 | 84 | |
| 75 | 85 | /// Call to give the number of arguments expected on cli |
| 76 | 86 | Combiner operator() (int n) const { |
| 77 | - return Combiner{n, positional, required, defaulted}; | |
| 87 | + Combiner self = *this; | |
| 88 | + self.num = n; | |
| 89 | + return *this; | |
| 90 | + } | |
| 91 | + /// Call to give a validator | |
| 92 | + Combiner operator() (std::function<bool(std::string)> func) const { | |
| 93 | + Combiner self = *this; | |
| 94 | + self.validators.push_back(func); | |
| 95 | + return self; | |
| 78 | 96 | } |
| 79 | 97 | Combiner operator, (Combiner b) const { |
| 80 | 98 | return *this | b; |
| 81 | 99 | } |
| 82 | 100 | }; |
| 83 | 101 | |
| 102 | +bool _ExistingFile(std::string filename) { | |
| 103 | +// std::fstream f(name.c_str()); | |
| 104 | +// return f.good(); | |
| 105 | +// Fastest way according to http://stackoverflow.com/questions/12774207/fastest-way-to-check-if-a-file-exist-using-standard-c-c11-c | |
| 106 | + struct stat buffer; | |
| 107 | + return (stat(filename.c_str(), &buffer) == 0); | |
| 108 | +} | |
| 109 | + | |
| 110 | +bool _ExistingDirectory(std::string filename) { | |
| 111 | + struct stat buffer; | |
| 112 | + if(stat(filename.c_str(), &buffer) == 0 && (buffer.st_mode & S_IFDIR) ) | |
| 113 | + return true; | |
| 114 | + return false; | |
| 115 | +} | |
| 116 | + | |
| 117 | +bool _NonexistentPath(std::string filename) { | |
| 118 | + struct stat buffer; | |
| 119 | + return stat(filename.c_str(), &buffer) != 0; | |
| 120 | +} | |
| 121 | + | |
| 84 | 122 | struct Error : public std::runtime_error { |
| 85 | 123 | Error(std::string parent, std::string name) : runtime_error(parent + ": " + name) {} |
| 86 | 124 | }; |
| ... | ... | @@ -137,12 +175,20 @@ std::tuple<std::string, std::string> split(std::string fullname) { |
| 137 | 175 | } else throw BadNameString(fullname); |
| 138 | 176 | } |
| 139 | 177 | |
| 140 | -const Combiner NOTHING {0, false,false,false}; | |
| 141 | -const Combiner REQUIRED {1, false,true, false}; | |
| 142 | -const Combiner DEFAULT {1, false,false,true}; | |
| 143 | -const Combiner POSITIONAL{1, true, false,false}; | |
| 144 | -const Combiner ARGS {1, false,false,false}; | |
| 145 | -const Combiner UNLIMITED {-1,false,false,false}; | |
| 178 | +const Combiner NOTHING {0, false,false,false, {}}; | |
| 179 | +const Combiner REQUIRED {1, false,true, false, {}}; | |
| 180 | +const Combiner DEFAULT {1, false,false,true, {}}; | |
| 181 | +const Combiner POSITIONAL {1, true, false,false, {}}; | |
| 182 | +const Combiner ARGS {1, false,false,false, {}}; | |
| 183 | +const Combiner UNLIMITED {-1,false,false,false, {}}; | |
| 184 | +const Combiner VALIDATORS {1, false, false, false, {}}; | |
| 185 | + | |
| 186 | +// Warning about using these validators: | |
| 187 | +// The files could be added/deleted after the validation. This is not common, | |
| 188 | +// but if this is a possibility, check the file you open afterwards | |
| 189 | +const Combiner ExistingFile {1, false, false, false, {_ExistingFile}}; | |
| 190 | +const Combiner ExistingDirectory {1, false, false, false, {_ExistingDirectory}}; | |
| 191 | +const Combiner NonexistentPath {1, false, false, false, {_NonexistentPath}}; | |
| 146 | 192 | |
| 147 | 193 | typedef std::vector<std::vector<std::string>> results_t; |
| 148 | 194 | typedef std::function<bool(results_t)> callback_t; | ... | ... |
tests/SmallTest.cpp
| 1 | 1 | #include "CLI.hpp" |
| 2 | 2 | #include "gtest/gtest.h" |
| 3 | +#include <cstdio> | |
| 4 | +#include <fstream> | |
| 3 | 5 | |
| 4 | 6 | |
| 5 | 7 | TEST(Split, GoodStrings) { |
| ... | ... | @@ -41,3 +43,25 @@ TEST(Split, BadStrings) { |
| 41 | 43 | |
| 42 | 44 | |
| 43 | 45 | } |
| 46 | + | |
| 47 | +TEST(Validators, FileExists) { | |
| 48 | + std::string myfile{"TestFileNotUsed.txt"}; | |
| 49 | + EXPECT_FALSE(CLI::_ExistingFile(myfile)); | |
| 50 | + bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file | |
| 51 | + EXPECT_TRUE(ok); | |
| 52 | + EXPECT_TRUE(CLI::_ExistingFile(myfile)); | |
| 53 | + | |
| 54 | + std::remove(myfile.c_str()); | |
| 55 | + EXPECT_FALSE(CLI::_ExistingFile(myfile)); | |
| 56 | +} | |
| 57 | + | |
| 58 | +TEST(Validators, FileNotExists) { | |
| 59 | + std::string myfile{"TestFileNotUsed.txt"}; | |
| 60 | + EXPECT_TRUE(CLI::_NonexistentPath(myfile)); | |
| 61 | + bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file | |
| 62 | + EXPECT_TRUE(ok); | |
| 63 | + EXPECT_FALSE(CLI::_NonexistentPath(myfile)); | |
| 64 | + | |
| 65 | + std::remove(myfile.c_str()); | |
| 66 | + EXPECT_TRUE(CLI::_NonexistentPath(myfile)); | |
| 67 | +} | ... | ... |