Commit 3836cdc9 authored by Dominik Charousset's avatar Dominik Charousset

Integrate strings and URIs into parse API

parent b09395a4
...@@ -64,6 +64,12 @@ void parse(parse_state& ps, double& x); ...@@ -64,6 +64,12 @@ void parse(parse_state& ps, double& x);
void parse(parse_state& ps, atom_value& x); void parse(parse_state& ps, atom_value& x);
void parse(parse_state& ps, uri& x);
// -- STL types ----------------------------------------------------------------
void parse(parse_state& ps, std::string& x);
// -- container types ---------------------------------------------------------- // -- container types ----------------------------------------------------------
template <class First, class Second> template <class First, class Second>
......
...@@ -38,7 +38,7 @@ namespace parser { ...@@ -38,7 +38,7 @@ namespace parser {
/// Reads a quoted or unquoted string. Quoted strings allow escaping, while /// Reads a quoted or unquoted string. Quoted strings allow escaping, while
/// unquoted strings may only include alphanumeric characters. /// unquoted strings may only include alphanumeric characters.
template <class Iterator, class Sentinel, class Consumer> template <class Iterator, class Sentinel, class Consumer>
void read_string(state<Iterator, Sentinel>& ps, Consumer& consumer) { void read_string(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
std::string res; std::string res;
auto g = caf::detail::make_scope_guard([&] { auto g = caf::detail::make_scope_guard([&] {
if (ps.code <= pec::trailing_character) if (ps.code <= pec::trailing_character)
......
...@@ -135,10 +135,6 @@ typename Inspector::result_type inspect(Inspector& f, uri::authority_type& x) { ...@@ -135,10 +135,6 @@ typename Inspector::result_type inspect(Inspector& f, uri::authority_type& x) {
/// @relates uri /// @relates uri
std::string to_string(const uri& x); std::string to_string(const uri& x);
/// @relates uri
/// @private
void parse(detail::parser::state<string_view::iterator> ps, uri& dest);
/// @relates uri /// @relates uri
error parse(string_view str, uri& dest); error parse(string_view str, uri& dest);
......
...@@ -19,10 +19,14 @@ ...@@ -19,10 +19,14 @@
#include "caf/detail/parse.hpp" #include "caf/detail/parse.hpp"
#include "caf/detail/consumer.hpp" #include "caf/detail/consumer.hpp"
#include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/read_atom.hpp" #include "caf/detail/parser/read_atom.hpp"
#include "caf/detail/parser/read_floating_point.hpp" #include "caf/detail/parser/read_floating_point.hpp"
#include "caf/detail/parser/read_signed_integer.hpp" #include "caf/detail/parser/read_signed_integer.hpp"
#include "caf/detail/parser/read_string.hpp"
#include "caf/detail/parser/read_unsigned_integer.hpp" #include "caf/detail/parser/read_unsigned_integer.hpp"
#include "caf/detail/parser/read_uri.hpp"
#include "caf/uri_builder.hpp"
#define PARSE_IMPL(type, parser_name) \ #define PARSE_IMPL(type, parser_name) \
void parse(parse_state& ps, type& x) { \ void parse(parse_state& ps, type& x) { \
...@@ -56,5 +60,38 @@ void parse(parse_state& ps, atom_value& x) { ...@@ -56,5 +60,38 @@ void parse(parse_state& ps, atom_value& x) {
parser::read_atom(ps, make_consumer(x), true); parser::read_atom(ps, make_consumer(x), true);
} }
void parse(parse_state& ps, uri& x) {
uri_builder builder;
if (ps.consume('<')) {
parser::read_uri(ps, builder);
if (ps.code > pec::trailing_character)
return;
if (!ps.consume('>')) {
ps.code = pec::unexpected_character;
return;
}
} else {
read_uri(ps, builder);
}
if (ps.code <= pec::trailing_character)
x = builder.make();
}
void parse(parse_state& ps, std::string& x) {
ps.skip_whitespaces();
if (ps.current() == '"') {
parser::read_string(ps, make_consumer(x));
return;
}
auto c = ps.current();
while (c != '\0' && (isalnum(c) || isspace(c))) {
x += c;
c = ps.next();
}
while (!x.empty() && isspace(x.back()))
x.pop_back();
ps.code = ps.at_end() ? pec::success : pec::trailing_character;
}
} // namespace detail } // namespace detail
} // namespace caf } // namespace caf
...@@ -20,12 +20,11 @@ ...@@ -20,12 +20,11 @@
#include "caf/deserializer.hpp" #include "caf/deserializer.hpp"
#include "caf/detail/fnv_hash.hpp" #include "caf/detail/fnv_hash.hpp"
#include "caf/detail/parser/read_uri.hpp" #include "caf/detail/parse.hpp"
#include "caf/detail/uri_impl.hpp" #include "caf/detail/uri_impl.hpp"
#include "caf/error.hpp" #include "caf/error.hpp"
#include "caf/make_counted.hpp" #include "caf/make_counted.hpp"
#include "caf/serializer.hpp" #include "caf/serializer.hpp"
#include "caf/uri_builder.hpp"
namespace caf { namespace caf {
...@@ -101,24 +100,13 @@ std::string to_string(const uri& x) { ...@@ -101,24 +100,13 @@ std::string to_string(const uri& x) {
return result; return result;
} }
void parse(detail::parser::state<string_view::iterator> ps, uri& dest) {
uri_builder builder;
read_uri(ps, builder);
if (ps.code <= pec::trailing_character)
dest = builder.make();
}
error parse(string_view str, uri& dest) { error parse(string_view str, uri& dest) {
using namespace detail::parser; detail::parse_state ps{str.begin(), str.end()};
uri_builder builder; parse(ps, dest);
state<string_view::iterator> res{str.begin(), str.end()}; if (ps.code == pec::success)
read_uri(res, builder);
if (res.code == pec::success) {
dest = builder.make();
return none; return none;
} return make_error(ps.code, static_cast<size_t>(ps.line),
return make_error(res.code, static_cast<size_t>(res.line), static_cast<size_t>(ps.column));
static_cast<size_t>(res.column));
} }
} // namespace caf } // namespace caf
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "caf/expected.hpp" #include "caf/expected.hpp"
#include "caf/string_view.hpp" #include "caf/string_view.hpp"
#include "caf/uri.hpp"
using namespace caf; using namespace caf;
...@@ -121,7 +122,7 @@ CAF_TEST(invalid floating point numbers) { ...@@ -121,7 +122,7 @@ CAF_TEST(invalid floating point numbers) {
CHECK_INVALID(double, "++10e-10", pec::unexpected_character); CHECK_INVALID(double, "++10e-10", pec::unexpected_character);
} }
CAF_TEST(valid atom value) { CAF_TEST(valid atom values) {
CAF_CHECK_EQUAL(read<atom_value>("foo"), atom("foo")); CAF_CHECK_EQUAL(read<atom_value>("foo"), atom("foo"));
CAF_CHECK_EQUAL(read<atom_value>("'foo'"), atom("foo")); CAF_CHECK_EQUAL(read<atom_value>("'foo'"), atom("foo"));
CAF_CHECK_EQUAL(read<atom_value>("foooooooooo"), pec::too_many_characters); CAF_CHECK_EQUAL(read<atom_value>("foooooooooo"), pec::too_many_characters);
...@@ -129,9 +130,16 @@ CAF_TEST(valid atom value) { ...@@ -129,9 +130,16 @@ CAF_TEST(valid atom value) {
CAF_CHECK_EQUAL(read<atom_value>("$"), pec::unexpected_character); CAF_CHECK_EQUAL(read<atom_value>("$"), pec::unexpected_character);
} }
CAF_TEST(strings) {
CAF_CHECK_EQUAL(read<std::string>(" foo\t "), "foo");
CAF_CHECK_EQUAL(read<std::string>(" \" foo\t\" "), " foo\t");
}
CAF_TEST(lists) { CAF_TEST(lists) {
using int_list = std::vector<int>; using int_list = std::vector<int>;
using atom_list = std::vector<atom_value>; using atom_list = std::vector<atom_value>;
using string_list = std::vector<std::string>;
CAF_CHECK_EQUAL(read<int_list>("1"), int_list({1}));
CAF_CHECK_EQUAL(read<int_list>("1, 2, 3"), int_list({1, 2, 3})); CAF_CHECK_EQUAL(read<int_list>("1, 2, 3"), int_list({1, 2, 3}));
CAF_CHECK_EQUAL(read<int_list>("[1, 2, 3]"), int_list({1, 2, 3})); CAF_CHECK_EQUAL(read<int_list>("[1, 2, 3]"), int_list({1, 2, 3}));
CAF_CHECK_EQUAL(read<atom_list>("foo, bar, baz"), CAF_CHECK_EQUAL(read<atom_list>("foo, bar, baz"),
...@@ -140,6 +148,8 @@ CAF_TEST(lists) { ...@@ -140,6 +148,8 @@ CAF_TEST(lists) {
atom_list({atom("foo"), atom("bar"), atom("baz")})); atom_list({atom("foo"), atom("bar"), atom("baz")}));
CAF_CHECK_EQUAL(read<atom_list>("[ foo , 'bar', 'baz'] "), CAF_CHECK_EQUAL(read<atom_list>("[ foo , 'bar', 'baz'] "),
atom_list({atom("foo"), atom("bar"), atom("baz")})); atom_list({atom("foo"), atom("bar"), atom("baz")}));
CAF_CHECK_EQUAL(read<string_list>("a, b , \" c \""),
string_list({"a", "b", " c "}));
} }
CAF_TEST(maps) { CAF_TEST(maps) {
...@@ -149,3 +159,22 @@ CAF_TEST(maps) { ...@@ -149,3 +159,22 @@ CAF_TEST(maps) {
CAF_CHECK_EQUAL(read<int_map>("{ a = 1 , 'b' = 42 ,} \t "), CAF_CHECK_EQUAL(read<int_map>("{ a = 1 , 'b' = 42 ,} \t "),
int_map({{atom("a"), 1}, {atom("b"), 42}})); int_map({{atom("a"), 1}, {atom("b"), 42}}));
} }
CAF_TEST(uris) {
using uri_list = std::vector<uri>;
auto x_res = read<uri>("foo:bar");
if (x_res == none) {
CAF_ERROR("my:path not recognized as URI");
return;
}
auto x = *x_res;
CAF_CHECK_EQUAL(x.scheme(), "foo");
CAF_CHECK_EQUAL(x.path(), "bar");
auto ls = unbox(read<uri_list>("foo:bar, <http://actor-framework.org/doc>"));
CAF_REQUIRE_EQUAL(ls.size(), 2u);
CAF_CHECK_EQUAL(ls[0].scheme(), "foo");
CAF_CHECK_EQUAL(ls[0].path(), "bar");
CAF_CHECK_EQUAL(ls[1].scheme(), "http");
CAF_CHECK_EQUAL(ls[1].authority().host, std::string{"actor-framework.org"});
CAF_CHECK_EQUAL(ls[1].path(), "doc");
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment