From b4b456f59409cce345dbb40d2a79435d5ebec5fb Mon Sep 17 00:00:00 2001 From: Henry Fredrick Schreiner Date: Fri, 17 Feb 2017 21:23:23 -0500 Subject: [PATCH] Adding ini support for spaces filtering and quotes --- README.md | 2 +- include/CLI/Ini.hpp | 8 ++++++++ include/CLI/StringTools.hpp | 35 +++++++++++++++++++++++++++----- tests/HelpersTest.cpp | 18 +++++++++++++++++ tests/IniTest.cpp | 40 ++++++++++++++++++++++++++++++++++++- 5 files changed, 96 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 89dfdc77..cc0907aa 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,8 @@ So, this library was designed to provide a great syntax, good compiler compatibi This library was built to supply the Application object for the GooFit CUDA/OMP fitting library. Before version 2.0 of GooFit is released, this library will reach version 1.0 status. The current tasks still planned are: * Expand tests to include a few more features - * Test config parser's support for spaces, etc in `ini` files * Collect user feedback + * Ini configuration support is basic (long options only, no vector support), is more needed? * Evaluate compatibility with [ROOT](https://root.cern.ch)'s TApplication object. * Add way for subclasses to return remaining options rather than throwing error diff --git a/include/CLI/Ini.hpp b/include/CLI/Ini.hpp index cbe41902..54e87a03 100644 --- a/include/CLI/Ini.hpp +++ b/include/CLI/Ini.hpp @@ -29,6 +29,14 @@ std::vector parse_ini(std::istream &input) { section = line.substr(1,len-2); std::transform(std::begin(section), std::end(section), std::begin(section), ::tolower); } else if (len > 0) { + // Find = in string, split and recombine + auto pos = line.find("="); + if(pos != std::string::npos) { + std::string name = detail::trim_copy(line.substr(0,pos)); + std::string item = detail::trim_copy(line.substr(pos+1)); + trim(item, "\"\'"); + line = name + "=" + item; + } if(section == "default") output.push_back("--" + line); else diff --git a/include/CLI/StringTools.hpp b/include/CLI/StringTools.hpp index 35a8ec06..d3fe4a20 100644 --- a/include/CLI/StringTools.hpp +++ b/include/CLI/StringTools.hpp @@ -31,15 +31,30 @@ std::string join(const T& v, std::string delim = ",") { /// Trim whitespace from left of string std::string& ltrim(std::string &str) { - auto it2 = std::find_if( str.begin() , str.end() , [](char ch){ return !std::isspace(ch , std::locale::classic() ) ; } ); - str.erase( str.begin() , it2); + auto it = std::find_if(str.begin(), str.end(), [](char ch){ return !std::isspace(ch , std::locale::classic());}); + str.erase(str.begin(), it); return str; } +/// Trim anything from left of string +std::string& ltrim(std::string &str, const std::string &filter) { + auto it = std::find_if(str.begin(), str.end(), [&filter](char ch){return filter.find(ch) == std::string::npos;}); + str.erase(str.begin(), it); + return str; +} + + /// Trim whitespace from right of string std::string& rtrim(std::string &str) { - auto it1 = std::find_if( str.rbegin() , str.rend() , [](char ch){ return !std::isspace(ch , std::locale::classic() ) ; } ); - str.erase( it1.base() , str.end() ); + auto it = std::find_if(str.rbegin(), str.rend(), [](char ch){ return !std::isspace(ch, std::locale::classic());}); + str.erase(it.base() , str.end() ); + return str; +} + +/// Trim anything from right of string +std::string& rtrim(std::string &str, const std::string &filter) { + auto it = std::find_if(str.rbegin(), str.rend(), [&filter](char ch){return filter.find(ch) == std::string::npos;}); + str.erase(it.base(), str.end()); return str; } @@ -48,12 +63,22 @@ std::string& trim(std::string &str) { return ltrim(rtrim(str)); } +/// Trim anything from string +std::string& trim(std::string &str, const std::string filter) { + return ltrim(rtrim(str, filter), filter); +} + /// Make a copy of the string and then trim it std::string trim_copy(const std::string &str) { std::string s = str; - return ltrim(rtrim(s)); + return trim(s); } +/// Make a copy of the string and then trim it, any filter string can be used (any char in string is filtered) +std::string trim_copy(const std::string &str, const std::string &filter) { + std::string s = str; + return rtrim(s, filter); +} /// Print a two part "help" string void format_help(std::stringstream &out, std::string name, std::string description, size_t wid) { name = " " + name; diff --git a/tests/HelpersTest.cpp b/tests/HelpersTest.cpp index b453f732..eba88c18 100644 --- a/tests/HelpersTest.cpp +++ b/tests/HelpersTest.cpp @@ -19,7 +19,25 @@ TEST(Trim, Various) { std::string s4{" a b "}; EXPECT_EQ("a b", CLI::detail::trim(s4)); +} + +TEST(Trim, VariousFilters) { + std::string s1{" sdlfkj sdflk sd s "}; + std::string a1{"sdlfkj sdflk sd s"}; + CLI::detail::trim(s1, " "); + EXPECT_EQ(a1, s1); + + std::string s2{" a \t"}; + CLI::detail::trim(s2, " "); + EXPECT_EQ("a \t", s2); + + std::string s3{"abdavda"}; + CLI::detail::trim(s3, "a"); + EXPECT_EQ("bdavd", s3); + + std::string s4{"abcabcabc"}; + EXPECT_EQ("cabcabc", CLI::detail::trim(s4, "ab")); } diff --git a/tests/IniTest.cpp b/tests/IniTest.cpp index c1e688e9..af26cd50 100644 --- a/tests/IniTest.cpp +++ b/tests/IniTest.cpp @@ -23,6 +23,39 @@ TEST(StringBased, First) { } +TEST(StringBased, Quotes) { + std::stringstream ofile; + + ofile << "one = \"three\"" << std::endl; + ofile << "two = \'four\'" << std::endl; + ofile << "five = \"six and seven\"" << std::endl; + + ofile.seekg(0, std::ios::beg); + + std::vector output = CLI::detail::parse_ini(ofile); + + std::vector answer = {"--one=three", "--two=four", "--five=six and seven"}; + + EXPECT_EQ(answer, output); + +} + + +TEST(StringBased, Spaces) { + std::stringstream ofile; + + ofile << "one = three" << std::endl; + ofile << "two = four" << std::endl; + + ofile.seekg(0, std::ios::beg); + + std::vector output = CLI::detail::parse_ini(ofile); + + std::vector answer = {"--one=three", "--two=four"}; + + EXPECT_EQ(answer, output); + +} TEST(StringBased, Sections) { std::stringstream ofile; @@ -153,7 +186,7 @@ TEST_F(TApp, IniOutputSimple) { } - +/// Flags should not show up in config file TEST_F(TApp, IniOutputFlag) { int v; @@ -169,3 +202,8 @@ TEST_F(TApp, IniOutputFlag) { EXPECT_THAT(str, Not(HasSubstr("nothing="))); } + +TEST_F(TApp, IniSpaces) { + + +}