Tidy up split_commas function and use it in Server

Conflicts:
	src/ripple/server/impl/ServerHandlerImp.cpp
This commit is contained in:
Vinnie Falco
2014-11-11 08:51:56 -08:00
parent f24e859f17
commit c2043a223b
3 changed files with 61 additions and 96 deletions

View File

@@ -23,11 +23,10 @@
#include <algorithm> #include <algorithm>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector>
#include <boost/regex.hpp> #include <boost/regex.hpp>
namespace beast { namespace beast {
namespace http {
/** Routines for performing RFC2616 compliance. /** Routines for performing RFC2616 compliance.
RFC2616: RFC2616:
@@ -156,21 +155,23 @@ trim (std::string const& s)
return trim <std::string> (s); return trim <std::string> (s);
} }
/** Call a functor for each comma delimited element. /** Parse a character sequence of values separated by commas.
Quotes and escape sequences will be parsed and converted appropriately. Double quotes and escape sequences will be converted. Excess white
Excess white space, commas, double quotes, and empty elements are not space, commas, double quotes, and empty elements are not copied.
passed to func.
Format: Format:
#(token|quoted-string) #(token|quoted-string)
Reference: Reference:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2 http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2
*/ */
template <class FwdIter, class Function> template <class FwdIt,
void class Result = std::vector<std::basic_string<typename FwdIt::value_type>>>
for_each_element (FwdIter first, FwdIter last, Function func) Result
split_commas(FwdIt first, FwdIt last)
{ {
FwdIter iter (first); Result result;
std::string e; using string = typename Result::value_type;
FwdIt iter = first;
string e;
while (iter != last) while (iter != last)
{ {
if (*iter == '"') if (*iter == '"')
@@ -200,7 +201,7 @@ for_each_element (FwdIter first, FwdIter last, Function func)
} }
if (! e.empty()) if (! e.empty())
{ {
func (e); result.emplace_back(std::move(e));
e.clear(); e.clear();
} }
} }
@@ -209,7 +210,7 @@ for_each_element (FwdIter first, FwdIter last, Function func)
e = trim_right (e); e = trim_right (e);
if (! e.empty()) if (! e.empty())
{ {
func (e); result.emplace_back(std::move(e));
e.clear(); e.clear();
} }
++iter; ++iter;
@@ -228,51 +229,20 @@ for_each_element (FwdIter first, FwdIter last, Function func)
{ {
e = trim_right (e); e = trim_right (e);
if (! e.empty()) if (! e.empty())
func (e); result.emplace_back(std::move(e));
}
}
// Parse a comma-delimited list of values.
template <class CharT, class Traits, class Allocator>
std::vector<std::basic_string<CharT, Traits, Allocator>>
parse_csv (std::basic_string <CharT, Traits, Allocator> const& in,
std::ostream& log)
{
auto first = in.cbegin();
auto const last = in.cend();
std::vector<std::basic_string<CharT, Traits, Allocator>> result;
if (first != last)
{
static boost::regex const re(
"^" // start of line
"(?:\\s*)" // whitespace (optional)
"([a-zA-Z][_a-zA-Z0-9]*)" // identifier
"(?:\\s*)" // whitespace (optional)
"(?:,?)" // comma (optional)
"(?:\\s*)" // whitespace (optional)
, boost::regex_constants::optimize
);
for(;;)
{
boost::smatch m;
if (! boost::regex_search(first, last, m, re,
boost::regex_constants::match_continuous))
{
log << "Expected <identifier>\n";
throw std::exception();
}
result.push_back(m[1]);
first = m[0].second;
if (first == last)
break;
}
} }
return result; return result;
} }
template <class Result = std::vector<std::string>>
Result
split_commas(std::string const& s)
{
return split_commas(s.begin(), s.end());
}
} // rfc2616 } // rfc2616
} // http
} // beast } // beast
#endif #endif

View File

@@ -27,67 +27,60 @@
#include <vector> #include <vector>
namespace beast { namespace beast {
namespace http {
namespace rfc2616 { namespace rfc2616 {
class rfc2616_test : public beast::unit_test::suite class rfc2616_test : public beast::unit_test::suite
{ {
public: public:
void void
check (std::string const& value, check (std::string const& s,
std::vector <std::string> const& expected) std::vector <std::string> const& expected)
{ {
std::vector <std::string> parsed; auto const parsed = split_commas(s.begin(), s.end());
for_each_element (value.begin(), value.end(),
[&](std::string const& element)
{
parsed.push_back (element);
});
expect (parsed == expected); expect (parsed == expected);
} }
void void test_split_commas()
run()
{ {
testcase("split_commas");
check ("", {}); check ("", {});
check (" ", {}); check (" ", {});
check (" ", {}); check (" ", {});
check ("\t", {}); check ("\t", {});
check (" \t ", {}); check (" \t ", {});
check (",", {}); check (",", {});
check (",,", {}); check (",,", {});
check (" ,", {}); check (" ,", {});
check (" , ,", {}); check (" , ,", {});
check ("x", {"x"}); check ("x", {"x"});
check (" x", {"x"}); check (" x", {"x"});
check (" \t x", {"x"}); check (" \t x", {"x"});
check ("x ", {"x"}); check ("x ", {"x"});
check ("x \t", {"x"}); check ("x \t", {"x"});
check (" \t x \t ", {"x"}); check (" \t x \t ", {"x"});
check ("\"\"", {}); check ("\"\"", {});
check (" \"\"", {}); check (" \"\"", {});
check ("\"\" ", {}); check ("\"\" ", {});
check ("\"x\"", {"x"}); check ("\"x\"", {"x"});
check ("\" \"", {" "}); check ("\" \"", {" "});
check ("\" x\"", {" x"}); check ("\" x\"", {" x"});
check ("\"x \"", {"x "}); check ("\"x \"", {"x "});
check ("\" x \"", {" x "}); check ("\" x \"", {" x "});
check ("\"\tx \"", {"\tx "}); check ("\"\tx \"", {"\tx "});
check ("x,y", { "x", "y" }); check ("x,y", { "x", "y" });
check ("x ,\ty ", { "x", "y" }); check ("x ,\ty ", { "x", "y" });
check ("x, y, z", {"x","y","z"}); check ("x, y, z", {"x","y","z"});
check ("x, \"y\", z", {"x","y","z"}); check ("x, \"y\", z", {"x","y","z"});
} }
void
run()
{
test_split_commas();
}
}; };
BEAST_DEFINE_TESTSUITE(rfc2616,http,beast); BEAST_DEFINE_TESTSUITE(rfc2616,http,beast);
} }
} }
}

View File

@@ -29,6 +29,7 @@
#include <ripple/resource/Manager.h> #include <ripple/resource/Manager.h>
#include <ripple/resource/Fees.h> #include <ripple/resource/Fees.h>
#include <beast/cxx14/algorithm.h> // <algorithm> #include <beast/cxx14/algorithm.h> // <algorithm>
#include <beast/http/rfc2616.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/regex.hpp> #include <boost/regex.hpp>
@@ -551,7 +552,8 @@ parse_Port (ParsedPort& port, Section const& section, std::ostream& log)
auto const result = section.find("protocol"); auto const result = section.find("protocol");
if (result.second) if (result.second)
{ {
for (auto const& s : parse_csv(result.first, log)) for (auto const& s : beast::rfc2616::split_commas(
result.first.begin(), result.first.end()))
port.protocol.insert(s); port.protocol.insert(s);
} }
} }