Commit 690dfbd7 authored by Dominik Charousset's avatar Dominik Charousset

nicer and less verbose string serialization

parent bb1056d2
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <cctype> #include <cctype>
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include <iostream>
#include <algorithm> #include <algorithm>
#include "cppa/atom.hpp" #include "cppa/atom.hpp"
...@@ -49,6 +50,13 @@ namespace cppa { ...@@ -49,6 +50,13 @@ namespace cppa {
namespace { namespace {
bool isbuiltin(const string& type_name) {
return type_name == "@str" || type_name == "@atom" || type_name == "@<>";
}
// serializes types as type_name(...) except:
// - strings are serialized "..."
// - atoms are serialized '...'
class string_serializer : public serializer { class string_serializer : public serializer {
ostream& out; ostream& out;
...@@ -56,8 +64,9 @@ class string_serializer : public serializer { ...@@ -56,8 +64,9 @@ class string_serializer : public serializer {
struct pt_writer { struct pt_writer {
ostream& out; ostream& out;
bool suppress_quotes;
pt_writer(ostream& mout) : out(mout) { } pt_writer(ostream& mout, bool suppress_quotes = false) : out(mout), suppress_quotes(suppress_quotes) { }
template<typename T> template<typename T>
void operator()(const T& value) { void operator()(const T& value) {
...@@ -65,12 +74,12 @@ class string_serializer : public serializer { ...@@ -65,12 +74,12 @@ class string_serializer : public serializer {
} }
void operator()(const string& str) { void operator()(const string& str) {
out << "\"";// << str << "\""; if (!suppress_quotes) out << "\"";
for (char c : str) { for (char c : str) {
if (c == '"') out << "\\\""; if (c == '"') out << "\\\"";
else out << c; else out << c;
} }
out << '"'; if (!suppress_quotes) out << "\"";
} }
void operator()(const u16string&) { } void operator()(const u16string&) { }
...@@ -89,7 +98,9 @@ class string_serializer : public serializer { ...@@ -89,7 +98,9 @@ class string_serializer : public serializer {
m_after_value = false; m_after_value = false;
} }
else if (m_obj_just_opened) { else if (m_obj_just_opened) {
if (!m_open_objects.empty() && !isbuiltin(m_open_objects.top())) {
out << " ( "; out << " ( ";
}
m_obj_just_opened = false; m_obj_just_opened = false;
} }
} }
...@@ -103,19 +114,21 @@ class string_serializer : public serializer { ...@@ -103,19 +114,21 @@ class string_serializer : public serializer {
void begin_object(const string& type_name) { void begin_object(const string& type_name) {
clear(); clear();
m_open_objects.push(type_name); m_open_objects.push(type_name);
out << type_name;// << " ( "; // do not print type names for strings and atoms
if (!isbuiltin(type_name)) out << type_name;
m_obj_just_opened = true; m_obj_just_opened = true;
} }
void end_object() { void end_object() {
if (m_obj_just_opened) { if (m_obj_just_opened) {
// no open brackets to close // no open brackets to close
m_obj_just_opened = false; m_obj_just_opened = false;
} }
else {
out << (m_after_value ? " )" : ")");
}
m_after_value = true; m_after_value = true;
if (!m_open_objects.empty()) { if (!m_open_objects.empty()) {
if (!isbuiltin(m_open_objects.top())) {
out << (m_after_value ? " )" : ")");
}
m_open_objects.pop(); m_open_objects.pop();
} }
} }
...@@ -141,7 +154,9 @@ class string_serializer : public serializer { ...@@ -141,7 +154,9 @@ class string_serializer : public serializer {
} }
// write atoms as strings instead of integer values // write atoms as strings instead of integer values
auto av = static_cast<atom_value>(get<uint64_t>(value)); auto av = static_cast<atom_value>(get<uint64_t>(value));
(pt_writer(out))(to_string(av)); out << "'";
(pt_writer(out, true))(to_string(av));
out << "'";
} }
else { else {
value.apply(pt_writer(out)); value.apply(pt_writer(out));
...@@ -239,7 +254,8 @@ class string_deserializer : public deserializer { ...@@ -239,7 +254,8 @@ class string_deserializer : public deserializer {
if (m_open_objects.empty() || m_obj_had_left_parenthesis.empty()) { if (m_open_objects.empty() || m_obj_had_left_parenthesis.empty()) {
throw_malformed("missing begin_object()"); throw_malformed("missing begin_object()");
} }
if (m_obj_had_left_parenthesis.top() == false) { if ( m_obj_had_left_parenthesis.top() == false
&& !isbuiltin(m_open_objects.top())) {
throw_malformed("expected left parenthesis after " throw_malformed("expected left parenthesis after "
"begin_object call or void value"); "begin_object call or void value");
} }
...@@ -257,6 +273,17 @@ class string_deserializer : public deserializer { ...@@ -257,6 +273,17 @@ class string_deserializer : public deserializer {
string seek_object() { string seek_object() {
skip_space_and_comma(); skip_space_and_comma();
// shortcuts for builtin types
if (*m_pos == '"') {
return "@str";
}
else if (*m_pos == '\'') {
return "@atom";
}
else if (*m_pos == '{') {
return "@<>";
}
// default case
auto substr_end = next_delimiter(); auto substr_end = next_delimiter();
if (m_pos == substr_end) { if (m_pos == substr_end) {
throw_malformed("could not seek object type name"); throw_malformed("could not seek object type name");
...@@ -267,9 +294,10 @@ class string_deserializer : public deserializer { ...@@ -267,9 +294,10 @@ class string_deserializer : public deserializer {
} }
string peek_object() { string peek_object() {
auto pos = m_pos;
string result = seek_object(); string result = seek_object();
// restore position in stream // restore position in stream
m_pos -= result.size(); m_pos = pos;
return result; return result;
} }
...@@ -277,28 +305,24 @@ class string_deserializer : public deserializer { ...@@ -277,28 +305,24 @@ class string_deserializer : public deserializer {
m_open_objects.push(type_name); m_open_objects.push(type_name);
//++m_obj_count; //++m_obj_count;
skip_space_and_comma(); skip_space_and_comma();
// suppress leading parenthesis for builtin types
m_obj_had_left_parenthesis.push(try_consume('(')); m_obj_had_left_parenthesis.push(try_consume('('));
//consume('('); //consume('(');
} }
void end_object() { void end_object() {
if (m_obj_had_left_parenthesis.empty()) { if (m_open_objects.empty()) {
throw_malformed("missing begin_object()"); throw runtime_error("no object to end");
} }
else {
if (m_obj_had_left_parenthesis.top() == true) { if (m_obj_had_left_parenthesis.top() == true) {
consume(')'); consume(')');
} }
m_obj_had_left_parenthesis.pop();
}
if (m_open_objects.empty()) {
throw runtime_error("no object to end");
}
m_open_objects.pop(); m_open_objects.pop();
m_obj_had_left_parenthesis.pop();
if (m_open_objects.empty()) { if (m_open_objects.empty()) {
skip_space_and_comma(); skip_space_and_comma();
if (m_pos != m_str.end()) { if (m_pos != m_str.end()) {
throw_malformed("expected end of of string"); throw_malformed(string("expected end of of string, found: ") + *m_pos);
} }
} }
} }
...@@ -335,11 +359,18 @@ class string_deserializer : public deserializer { ...@@ -335,11 +359,18 @@ class string_deserializer : public deserializer {
if (ptype != pt_uint64) { if (ptype != pt_uint64) {
throw_malformed("expected read of pt_uint64 after @atom"); throw_malformed("expected read of pt_uint64 after @atom");
} }
auto str_val = get<string>(read_value(pt_u8string)); consume('\'');
if (str_val.size() > 10) { auto substr_end = find(m_pos, m_str.end(), '\'');
if (substr_end == m_str.end()) {
throw_malformed("couldn't find trailing ' for atom");
}
else if ((substr_end - m_pos) > 10) {
throw_malformed("atom string size > 10"); throw_malformed("atom string size > 10");
} }
return detail::atom_val(str_val.c_str()); string substr(m_pos, substr_end);
std::cout << "atom string: " << substr << std::endl;
m_pos += substr.size() + 1;
return detail::atom_val(substr.c_str(), 0xF);
} }
skip_space_and_comma(); skip_space_and_comma();
string::iterator substr_end; string::iterator substr_end;
......
...@@ -78,6 +78,10 @@ struct struct_b { ...@@ -78,6 +78,10 @@ struct struct_b {
list<int> ints; list<int> ints;
}; };
string to_string(const struct_b& what) {
return to_string(object::from(what));
}
bool operator==(const struct_b& lhs, const struct_b& rhs) { bool operator==(const struct_b& lhs, const struct_b& rhs) {
return lhs.a == rhs.a && lhs.z == rhs.z && lhs.ints == rhs.ints; return lhs.a == rhs.a && lhs.z == rhs.z && lhs.ints == rhs.ints;
} }
...@@ -101,7 +105,7 @@ bool operator!=(const struct_c& lhs, const struct_c& rhs) { ...@@ -101,7 +105,7 @@ bool operator!=(const struct_c& lhs, const struct_c& rhs) {
return !(lhs == rhs); return !(lhs == rhs);
} }
static const char* msg1str = u8R"__(@<> ( { @i32 ( 42 ), @str ( "Hello \"World\"!" ) } ))__"; static const char* msg1str = u8R"__({ @i32 ( 42 ), "Hello \"World\"!" })__";
struct raw_struct { struct raw_struct {
string str; string str;
...@@ -170,7 +174,7 @@ int main() { ...@@ -170,7 +174,7 @@ int main() {
raw_struct rs2; raw_struct rs2;
uniform_typeid<raw_struct>()->deserialize(&rs2, &bd); uniform_typeid<raw_struct>()->deserialize(&rs2, &bd);
CPPA_CHECK_EQUAL(rs.str, rs2.str); CPPA_CHECK_EQUAL(rs.str, rs2.str);
auto rsstr = to_string(object::from(rs)); auto rsstr = cppa::to_string(object::from(rs));
rs2.str = "foobar"; rs2.str = "foobar";
cout << "rs as string: " << rsstr << endl; cout << "rs as string: " << rsstr << endl;
rs2 = from_string<raw_struct>(rsstr); rs2 = from_string<raw_struct>(rsstr);
...@@ -266,7 +270,7 @@ int main() { ...@@ -266,7 +270,7 @@ int main() {
if (meta_int) { if (meta_int) {
auto o = meta_int->create(); auto o = meta_int->create();
get_ref<uint32_t>(o) = 42; get_ref<uint32_t>(o) = 42;
auto str = cppa::to_string(object::from(get<uint32_t>(o))); auto str = to_string(object::from(get<uint32_t>(o)));
CPPA_CHECK_EQUAL( "@u32 ( 42 )", str); CPPA_CHECK_EQUAL( "@u32 ( 42 )", str);
} }
} }
...@@ -285,7 +289,7 @@ int main() { ...@@ -285,7 +289,7 @@ int main() {
auto b1str = "struct_b ( struct_a ( 1, 2 ), 3, " auto b1str = "struct_b ( struct_a ( 1, 2 ), 3, "
"{ 4, 5, 6, 7, 8, 9, 10 } )"; "{ 4, 5, 6, 7, 8, 9, 10 } )";
// verify // verify
CPPA_CHECK_EQUAL((to_string(object::from(b1))), b1str); { CPPA_CHECK_EQUAL((to_string(b1)), b1str); {
// serialize b1 to buf // serialize b1 to buf
util::buffer wr_buf; util::buffer wr_buf;
binary_serializer bs(&wr_buf); binary_serializer bs(&wr_buf);
...@@ -299,7 +303,7 @@ int main() { ...@@ -299,7 +303,7 @@ int main() {
} }
// verify result of serialization / deserialization // verify result of serialization / deserialization
CPPA_CHECK(b1 == b2); CPPA_CHECK(b1 == b2);
CPPA_CHECK_EQUAL(to_string(object::from(b2)), b1str); CPPA_CHECK_EQUAL(to_string(b2), b1str);
{ // deserialize b3 from string { // deserialize b3 from string
object res = from_string(b1str); object res = from_string(b1str);
CPPA_CHECK_EQUAL(res.type()->name(), "struct_b"); CPPA_CHECK_EQUAL(res.type()->name(), "struct_b");
......
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