Commit 2cfb52d8 authored by Dominik Charousset's avatar Dominik Charousset

Implement `from_string` for new UTI interface

Add a `from_string` implementation for the new API of `uniform_type_info`.
Also improve the string deserializer to correctly parse the serialized form of
a `node_id`, i.e., correctly handle the '@' sign that separates process and
host id.
parent db1e1c08
...@@ -34,7 +34,7 @@ namespace cppa { ...@@ -34,7 +34,7 @@ namespace cppa {
* @returns An {@link cppa::object object} instance that contains * @returns An {@link cppa::object object} instance that contains
* the deserialized value. * the deserialized value.
*/ */
uniform_value from_string(const std::string& what); uniform_value from_string_impl(const std::string& what);
/** /**
* @brief Convenience function that deserializes a value from @p what and * @brief Convenience function that deserializes a value from @p what and
...@@ -42,23 +42,23 @@ uniform_value from_string(const std::string& what); ...@@ -42,23 +42,23 @@ uniform_value from_string(const std::string& what);
* @throws std::logic_error if the result is not of type @p T. * @throws std::logic_error if the result is not of type @p T.
* @returns The deserialized value as instance of @p T. * @returns The deserialized value as instance of @p T.
*/ */
/*
template<typename T> template<typename T>
T from_string(const std::string& what) { optional<T> from_string(const std::string& what) {
any o = from_string(what); auto uti = uniform_typeid<T>();
const std::type_info& tinfo = typeid(T); auto uv = from_string_impl(what);
if (tinfo == *(o.type())) { if (!uv || (*uv->ti) != typeid(T)) {
return std::move(get_ref<T>(o)); // try again using the type name
std::string tmp = uti->name();
tmp += " ( ";
tmp += what;
tmp += " )";
uv = from_string_impl(tmp);
} }
else { if (uv && (*uv->ti) == typeid(T)) {
std::string error_msg = "expected type name "; return T{std::move(*reinterpret_cast<T*>(uv->val))};
error_msg += uniform_typeid(tinfo)->name();
error_msg += " found ";
error_msg += o.type()->name();
throw std::logic_error(error_msg);
} }
return none;
} }
*/
} // namespace cppa } // namespace cppa
......
...@@ -299,7 +299,7 @@ class string_deserializer : public deserializer, public dummy_backend { ...@@ -299,7 +299,7 @@ class string_deserializer : public deserializer, public dummy_backend {
const uniform_type_info* begin_object() override { const uniform_type_info* begin_object() override {
skip_space_and_comma(); skip_space_and_comma();
string type_name; string type_name;
// shortcuts for builtin types // shortcuts for built-in types
if (*m_pos == '"') { if (*m_pos == '"') {
type_name = "@str"; type_name = "@str";
} else if (*m_pos == '\'') { } else if (*m_pos == '\'') {
...@@ -315,11 +315,9 @@ class string_deserializer : public deserializer, public dummy_backend { ...@@ -315,11 +315,9 @@ class string_deserializer : public deserializer, public dummy_backend {
m_pos = substr_end; m_pos = substr_end;
} }
m_open_objects.push(type_name); m_open_objects.push(type_name);
//++m_obj_count;
skip_space_and_comma(); skip_space_and_comma();
// suppress leading parenthesis for builtin types // suppress leading parenthesis for built-in types
m_obj_had_left_parenthesis.push(try_consume('(')); m_obj_had_left_parenthesis.push(try_consume('('));
// consume('(');
return detail::singletons::get_uniform_type_info_map()->by_uniform_name( return detail::singletons::get_uniform_type_info_map()->by_uniform_name(
type_name); type_name);
} }
...@@ -401,6 +399,7 @@ class string_deserializer : public deserializer, public dummy_backend { ...@@ -401,6 +399,7 @@ class string_deserializer : public deserializer, public dummy_backend {
case '}': case '}':
case ' ': case ' ':
case ',': case ',':
case '@':
return true; return true;
default: default:
return false; return false;
...@@ -479,21 +478,33 @@ class string_deserializer : public deserializer, public dummy_backend { ...@@ -479,21 +478,33 @@ class string_deserializer : public deserializer, public dummy_backend {
} }
void read_raw(size_t buf_size, void* vbuf) override { void read_raw(size_t buf_size, void* vbuf) override {
if (buf_size == node_id::host_id_size
&& !m_open_objects.empty()
&& m_open_objects.top() == "@node") {
// node ids are formatted as process_id@host_id
// this read_raw reads the host_id, i.e., we need
// to skip the '@' character
consume('@');
}
auto buf = reinterpret_cast<unsigned char*>(vbuf); auto buf = reinterpret_cast<unsigned char*>(vbuf);
integrity_check(); integrity_check();
skip_space_and_comma(); skip_space_and_comma();
auto next_nibble = [&]()->size_t { auto next_nibble = [&]() -> size_t {
if (*m_pos == '\0') { if (*m_pos == '\0') {
throw_malformed("unexpected end-of-string"); throw_malformed("unexpected end-of-string");
} }
char c = *m_pos++; char c = *m_pos++;
if (!isxdigit(c)) { if (!isxdigit(c)) {
throw_malformed("unexpected character, expected [0-9a-f]"); std::string errmsg = "unexpected character: '";
errmsg += c;
errmsg += "', expected [0-9a-f]";
throw_malformed(errmsg);
} }
return static_cast<size_t>(isdigit(c) ? c - '0' : (c - 'a' + 10)); return static_cast<size_t>(isdigit(c) ? c - '0' : (c - 'a' + 10));
}; };
for (size_t i = 0; i < buf_size; ++i) { for (size_t i = 0; i < buf_size; ++i) {
// one byte consists of two nibbles
auto nibble = next_nibble(); auto nibble = next_nibble();
*buf++ = static_cast<unsigned char>((nibble << 4) | next_nibble()); *buf++ = static_cast<unsigned char>((nibble << 4) | next_nibble());
} }
...@@ -503,15 +514,6 @@ class string_deserializer : public deserializer, public dummy_backend { ...@@ -503,15 +514,6 @@ class string_deserializer : public deserializer, public dummy_backend {
} // namespace <anonymous> } // namespace <anonymous>
uniform_value from_string(const string& what) {
string_deserializer strd(what);
auto utype = strd.begin_object();
auto result = utype->deserialize(&strd);
strd.end_object();
return result;
return {};
}
namespace detail { namespace detail {
string to_string_impl(const void* what, const uniform_type_info* utype) { string to_string_impl(const void* what, const uniform_type_info* utype) {
...@@ -535,4 +537,14 @@ ostream& operator<<(ostream& out, skip_message_t) { ...@@ -535,4 +537,14 @@ ostream& operator<<(ostream& out, skip_message_t) {
return out << "skip_message"; return out << "skip_message";
} }
uniform_value from_string_impl(const string& what) {
string_deserializer strd(what);
auto utype = strd.begin_object();
if (utype) {
return utype->deserialize(&strd);
}
strd.end_object();
return {};
}
} // namespace cppa } // namespace cppa
...@@ -141,6 +141,12 @@ int main() { ...@@ -141,6 +141,12 @@ int main() {
announce(typeid(raw_struct), announce(typeid(raw_struct),
uniform_type_info_ptr{new raw_struct_type_info}); uniform_type_info_ptr{new raw_struct_type_info});
auto nid = detail::singletons::get_node_id();
auto nid_str = to_string(nid);
CPPA_PRINT("nid_str = " << nid_str);
auto nid2 = from_string<node_id>(nid_str);
CPPA_CHECK(nid2 && nid == *nid2);
/* /*
auto oarr = new detail::object_array; auto oarr = new detail::object_array;
oarr->push_back(object::from(static_cast<uint32_t>(42))); oarr->push_back(object::from(static_cast<uint32_t>(42)));
......
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