diff --git a/configure.ac b/configure.ac index 678537d6..eb562969 100644 --- a/configure.ac +++ b/configure.ac @@ -146,14 +146,6 @@ glib_version="$($PKG_CONFIG --modversion glib-2.0)" PKG_CHECK_MODULES(GMIME,gmime-3.0) gmime_version="$($PKG_CONFIG --modversion gmime-3.0)" -# gmime, version 3.0 or higher -PKG_CHECK_MODULES(JSON_GLIB,json-glib-1.0 >= 1.4,[have_json_glib=yes],[have_json_glib=no]) -AS_IF([test "x$have_json_glib" = "xyes"],[ - json_glib_version="$($PKG_CONFIG --modversion json-glib-1.0)" - AC_DEFINE(HAVE_JSON_GLIB,[1], [Do we support json-glib?]) -]) -AM_CONDITIONAL(HAVE_JSON_GLIB,[test "x$have_json_glib" = "xyes"]) - # xapian checking - we need 1.4 at least PKG_CHECK_MODULES(XAPIAN,xapian-core >= 1.4,[ have_xapian=yes @@ -296,10 +288,6 @@ echo "Xapian version : $xapian_version" echo "GLib version : $glib_version" echo "GMime version : $gmime_version" -AM_COND_IF([HAVE_JSON_GLIB],[ -echo "Json-Glib version : $json_glib_version" -]) - AM_COND_IF([BUILD_GUI],[ echo "GTK+ version : $gtk_version" echo "Webkit2/GTK+ version : $webkit_version" diff --git a/lib/Makefile.am b/lib/Makefile.am index 29116f39..f21561a9 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -20,13 +20,6 @@ include $(top_srcdir)/gtest.mk SUBDIRS= utils query index -if HAVE_JSON_GLIB -json_srcs= \ - mu-msg-json.c \ - mu-msg-json.h -json_flag="-DHAVE_JSON_GLIB" -endif - TESTDEFS= \ -DMU_TESTMAILDIR=\"${abs_srcdir}/testdir\" \ -DMU_TESTMAILDIR2=\"${abs_srcdir}/testdir2\" \ diff --git a/lib/mu-msg-sexp.cc b/lib/mu-msg-sexp.cc index 694b6799..77c74017 100644 --- a/lib/mu-msg-sexp.cc +++ b/lib/mu-msg-sexp.cc @@ -478,5 +478,14 @@ mu_msg_to_sexp (MuMsg *msg, unsigned docid, const MuMsgIterThreadInfo *ti, MuMsgOptions opts) { return g_strdup (Mu::msg_to_sexp (msg, docid, ti, opts) - .to_string().c_str()); + .to_sexp_string().c_str()); +} + + +char* +mu_msg_to_json (MuMsg *msg, unsigned docid, const MuMsgIterThreadInfo *ti, + MuMsgOptions opts) +{ + return g_strdup (Mu::msg_to_sexp (msg, docid, ti, opts) + .to_json_string().c_str()); } diff --git a/lib/mu-msg.h b/lib/mu-msg.h index 8b337ecd..a77652be 100644 --- a/lib/mu-msg.h +++ b/lib/mu-msg.h @@ -595,10 +595,6 @@ char* mu_str_flags (MuFlags flags) struct _MuMsgIterThreadInfo; -#ifdef HAVE_JSON_GLIB - -struct _JsonNode; /* forward declaration */ - /** * convert the msg to json * @@ -612,13 +608,11 @@ struct _JsonNode; /* forward declaration */ * - MU_MSG_OPTION_EXTRACT_IMAGES: extract image attachments as temporary * files and include links to those in the sexp * - * @return a string with the sexp (free with g_free) or NULL in case of error + * @return a string with the json (free with g_free) or NULL in case of error */ -struct _JsonNode* mu_msg_to_json (MuMsg *msg, unsigned docid, +char* mu_msg_to_json (MuMsg *msg, unsigned docid, const struct _MuMsgIterThreadInfo *ti, MuMsgOptions ops) G_GNUC_WARN_UNUSED_RESULT; -#endif /*HAVE_JSON_GLIB*/ - /** * convert the msg to a Lisp symbolic expression (for further processing in diff --git a/lib/utils/mu-command-parser.cc b/lib/utils/mu-command-parser.cc index eb422d10..bf4193d9 100644 --- a/lib/utils/mu-command-parser.cc +++ b/lib/utils/mu-command-parser.cc @@ -33,7 +33,7 @@ Command::invoke(const Command::CommandMap& cmap, const Sexp& call) if (!call.is_call()) { throw Mu::Error{Error::Code::Command, "expected call-sexpr but got %s", - call.to_string().c_str()}; + call.to_sexp_string().c_str()}; } const auto& params{call.list()}; @@ -41,7 +41,7 @@ Command::invoke(const Command::CommandMap& cmap, const Sexp& call) if (cmd_it == cmap.end()) throw Mu::Error{Error::Code::Command, "unknown command in call %s", - call.to_string().c_str()}; + call.to_sexp_string().c_str()}; const auto& cinfo{cmd_it->second}; @@ -67,7 +67,7 @@ Command::invoke(const Command::CommandMap& cmap, const Sexp& call) if (arginfo.required) throw Mu::Error{Error::Code::Command, "missing required parameter %s in call %s", - argname.c_str(), call.to_string().c_str()}; + argname.c_str(), call.to_sexp_string().c_str()}; continue; // not required } @@ -78,7 +78,7 @@ Command::invoke(const Command::CommandMap& cmap, const Sexp& call) "parameter %s expects type %s, but got %s in call %s", argname.c_str(), to_string(arginfo.type).c_str(), to_string(param_it->type()).c_str(), - call.to_string().c_str()}; + call.to_sexp_string().c_str()}; } // all passed parameters must be known @@ -87,7 +87,7 @@ Command::invoke(const Command::CommandMap& cmap, const Sexp& call) [&](auto&& arg) {return params.at(i).value() == arg.first;})) throw Mu::Error{Error::Code::Command, "unknown parameter %s in call %s", - params.at(i).value().c_str(), call.to_string().c_str()}; + params.at(i).value().c_str(), call.to_sexp_string().c_str()}; } if (cinfo.handler) diff --git a/lib/utils/mu-sexp.cc b/lib/utils/mu-sexp.cc index 031cf0af..f07230ec 100644 --- a/lib/utils/mu-sexp.cc +++ b/lib/utils/mu-sexp.cc @@ -179,7 +179,7 @@ Sexp::make_parse (const std::string& expr) std::string -Sexp::to_string () const +Sexp::to_sexp_string () const { std::stringstream sstrm; @@ -188,7 +188,7 @@ Sexp::to_string () const sstrm << '('; bool first{true}; for (auto&& child : list()) { - sstrm << (first ? "" : " ") << child.to_string(); + sstrm << (first ? "" : " ") << child.to_sexp_string(); first = false; } sstrm << ')'; @@ -206,3 +206,55 @@ Sexp::to_string () const return sstrm.str(); } + + +std::string +Sexp::to_json_string () const +{ + std::stringstream sstrm; + + switch (type()) { + case Type::List: { + // property-lists become JSON objects + if (is_prop_list()) { + sstrm << "{"; + auto it{list().begin()}; + bool first{true}; + while (it != list().end()) { + sstrm << (first?"":",") << quote(it->value()) << ":"; + ++it; + sstrm << it->to_json_string(); + ++it; + first = false; + } + sstrm << "}"; + } else { // other lists become arrays. + sstrm << '['; + bool first{true}; + for (auto&& child : list()) { + sstrm << (first ? "" : ", ") << child.to_json_string(); + first = false; + } + sstrm << ']'; + } + break; + } + case Type::String: + sstrm << quote(value()); + break; + case Type::Symbol: + if (is_nil()) + sstrm << "false"; + else if (is_t()) + sstrm << "true"; + else + sstrm << quote(value()); + break; + case Type::Number: + case Type::Empty: + default: + sstrm << value(); + } + + return sstrm.str(); +} diff --git a/lib/utils/mu-sexp.hh b/lib/utils/mu-sexp.hh index f0aa27db..a4f90022 100644 --- a/lib/utils/mu-sexp.hh +++ b/lib/utils/mu-sexp.hh @@ -104,11 +104,19 @@ struct Sexp { } /** - * Convert a Sexp::Node to its string representation + * Convert a Sexp::Node to its S-expression string representation * * @return the string representation */ - std::string to_string() const; + std::string to_sexp_string() const; + + + /** + * Convert a Sexp::Node to its JSON string representation + * + * @return the string representation + */ + std::string to_json_string() const; /** * Return the type of this Node. @@ -341,7 +349,7 @@ operator<<(std::ostream& os, Sexp::Type id) static inline std::ostream& operator<<(std::ostream& os, const Sexp& sexp) { - os << sexp.to_string(); + os << sexp.to_sexp_string(); return os; } diff --git a/lib/utils/test-sexp.cc b/lib/utils/test-sexp.cc index 8012cb28..0e2d5b28 100644 --- a/lib/utils/test-sexp.cc +++ b/lib/utils/test-sexp.cc @@ -63,17 +63,17 @@ test_list() const auto nstr{Sexp::make_string("foo")}; g_assert_true(nstr.value() == "foo"); g_assert_true(nstr.type() == Sexp::Type::String); - assert_equal(nstr.to_string(), "\"foo\""); + assert_equal(nstr.to_sexp_string(), "\"foo\""); const auto nnum{Sexp::make_number(123)}; g_assert_true(nnum.value() == "123"); g_assert_true(nnum.type() == Sexp::Type::Number); - assert_equal(nnum.to_string(), "123"); + assert_equal(nnum.to_sexp_string(), "123"); const auto nsym{Sexp::make_symbol("blub")}; g_assert_true(nsym.value() == "blub"); g_assert_true(nsym.type() == Sexp::Type::Symbol); - assert_equal(nsym.to_string(), "blub"); + assert_equal(nsym.to_sexp_string(), "blub"); Sexp::List list; list .add(Sexp::make_string("foo")) @@ -85,7 +85,7 @@ test_list() g_assert_true(nlst.type() == Sexp::Type::List); g_assert_true(nlst.list().at(1).value() == "123"); - assert_equal(nlst.to_string(),"(\"foo\" 123 blub)"); + assert_equal(nlst.to_sexp_string(),"(\"foo\" 123 blub)"); } @@ -95,7 +95,7 @@ test_prop_list() Sexp::List l1; l1.add_prop(":foo", Sexp::make_string("bar")); Sexp s2{Sexp::make_list(std::move(l1))}; - assert_equal(s2.to_string(), "(:foo \"bar\")"); + assert_equal(s2.to_sexp_string(), "(:foo \"bar\")"); Sexp::List l2; @@ -105,7 +105,7 @@ test_prop_list() Sexp::List l3; l3.add_prop(":cuux", Sexp::make_list(std::move(l2))); Sexp s3{Sexp::make_list(std::move(l3))}; - assert_equal(s3.to_string(), "(:cuux (:foo \"bar\" :bar 77))"); + assert_equal(s3.to_sexp_string(), "(:cuux (:foo \"bar\" :bar 77))"); } static void @@ -122,7 +122,7 @@ test_props() ":flub", Sexp::make_symbol("fnord"), ":boo", std::move(sexp2)); - assert_equal(sexp.to_string(), + assert_equal(sexp.to_sexp_string(), "(:foo \"b\303\244r\" :cuux 123 :flub fnord :boo (\"foo\" 123 blub))"); } diff --git a/mu/mu-cmd-find.cc b/mu/mu-cmd-find.cc index 2a0cb6c7..af07ca20 100644 --- a/mu/mu-cmd-find.cc +++ b/mu/mu-cmd-find.cc @@ -42,10 +42,6 @@ #include "mu-cmd.hh" #include "mu-threader.h" -#ifdef HAVE_JSON_GLIB -#include -#endif /*HAVE_JSON_GLIB*/ - using namespace Mu; typedef gboolean (OutputFunc) (MuMsg *msg, MuMsgIter *iter, @@ -539,7 +535,6 @@ to_string (const Mu::Sexp& sexp, bool color, size_t level = 0) } - static gboolean output_sexp (MuMsg *msg, MuMsgIter *iter, const MuConfig *opts, GError **err) { @@ -555,21 +550,15 @@ output_sexp (MuMsg *msg, MuMsgIter *iter, const MuConfig *opts, GError **err) static gboolean output_json (MuMsg *msg, MuMsgIter *iter, const MuConfig *opts, GError **err) { -#ifdef HAVE_JSON_GLIB - JsonNode *node; const MuMsgIterThreadInfo *ti; char *s; if (mu_msg_iter_is_first(iter)) g_print ("[\n"); - ti = opts->threads ? mu_msg_iter_get_thread_info (iter) : NULL; - node = mu_msg_to_json (msg, mu_msg_iter_get_docid (iter), - ti, MU_MSG_OPTION_HEADERS_ONLY); - - s = json_to_string (node, TRUE); - json_node_free (node); - + ti = opts->threads ? mu_msg_iter_get_thread_info (iter) : NULL; + s = mu_msg_to_json (msg, mu_msg_iter_get_docid (iter), + ti, MU_MSG_OPTION_HEADERS_ONLY); fputs (s, stdout); g_free (s); @@ -579,12 +568,6 @@ output_json (MuMsg *msg, MuMsgIter *iter, const MuConfig *opts, GError **err) fputs (",\n", stdout); return TRUE; -#else - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_IN_PARAMETERS, - "this mu was built without json support"); - return FALSE; -#endif /*HAVE_JSON_GLIB*/ - } static void diff --git a/mu/mu-cmd-server.cc b/mu/mu-cmd-server.cc index 1ea4260a..c52095da 100644 --- a/mu/mu-cmd-server.cc +++ b/mu/mu-cmd-server.cc @@ -147,7 +147,7 @@ print_expr (const char* frm, ...) static void print_expr (const Sexp& sexp) { - print_expr ("%s", sexp.to_string().c_str()); + print_expr ("%s", sexp.to_sexp_string().c_str()); } static void