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 c1e070c042
commit 5d33ce352e
2 changed files with 58 additions and 95 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,62 +27,56 @@
#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 test_split_commas()
{
testcase("split_commas");
check ("", {});
check (" ", {});
check (" ", {});
check ("\t", {});
check (" \t ", {});
check (",", {});
check (",,", {});
check (" ,", {});
check (" , ,", {});
check ("x", {"x"});
check (" x", {"x"});
check (" \t x", {"x"});
check ("x ", {"x"});
check ("x \t", {"x"});
check (" \t x \t ", {"x"});
check ("\"\"", {});
check (" \"\"", {});
check ("\"\" ", {});
check ("\"x\"", {"x"});
check ("\" \"", {" "});
check ("\" x\"", {" x"});
check ("\"x \"", {"x "});
check ("\" x \"", {" x "});
check ("\"\tx \"", {"\tx "});
check ("x,y", { "x", "y" });
check ("x ,\ty ", { "x", "y" });
check ("x, y, z", {"x","y","z"});
check ("x, \"y\", z", {"x","y","z"});
}
void void
run() run()
{ {
check ("", {}); test_split_commas();
check (" ", {});
check (" ", {});
check ("\t", {});
check (" \t ", {});
check (",", {});
check (",,", {});
check (" ,", {});
check (" , ,", {});
check ("x", {"x"});
check (" x", {"x"});
check (" \t x", {"x"});
check ("x ", {"x"});
check ("x \t", {"x"});
check (" \t x \t ", {"x"});
check ("\"\"", {});
check (" \"\"", {});
check ("\"\" ", {});
check ("\"x\"", {"x"});
check ("\" \"", {" "});
check ("\" x\"", {" x"});
check ("\"x \"", {"x "});
check ("\" x \"", {" x "});
check ("\"\tx \"", {"\tx "});
check ("x,y", { "x", "y" });
check ("x ,\ty ", { "x", "y" });
check ("x, y, z", {"x","y","z"});
check ("x, \"y\", z", {"x","y","z"});
} }
}; };
@@ -90,4 +84,3 @@ BEAST_DEFINE_TESTSUITE(rfc2616,http,beast);
} }
} }
}