fluent interface for stanza generation

master
bqv 2 years ago
parent 44f17b80da
commit b5c0417f14
No known key found for this signature in database
GPG Key ID: 9E2FF3BDEBDFC910

@ -13,6 +13,7 @@
#include <string_view>
#include <vector>
#include <chrono>
#include <variant>
#include <fmt/core.h>
#include <strophe.h>
@ -101,6 +102,86 @@ namespace xml {
}
};
namespace builder {
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
class spec {
protected:
explicit spec(std::string_view tag): tag(tag) {}
void child(spec& ch) {
children.push_back(ch);
}
void attr(std::string k, std::string_view v) {
attributes[k] = v;
}
inline void text(std::string_view s) {
children.push_back(std::string(s));
}
private:
const std::string tag;
std::map<std::string, std::string> attributes;
std::vector<std::variant<spec, std::string>> children;
public:
std::shared_ptr<xmpp_stanza_t> build(xmpp_ctx_t *context) {
auto stanza = xmpp_stanza_new(context);
xmpp_stanza_set_name(stanza, tag.data());
for (auto& at : attributes) {
xmpp_stanza_set_attribute(stanza, at.first.data(), at.second.data());
}
for (auto& ch : children) {
std::visit(overloaded {
[&](spec& child) {
xmpp_stanza_add_child(stanza, child.build(context).get());
},
[&](std::string s) {
auto child = xmpp_stanza_new(context);
xmpp_stanza_set_text(child, s.data());
xmpp_stanza_add_child(stanza, child);
xmpp_stanza_release(child);
}
}, ch);
}
return { stanza, &xmpp_stanza_release };
}
};
struct body : public spec {
body() : body("") {}
body(std::string_view s) : spec("body") {
text(s);
}
};
struct message : public spec {
message() : spec("message") {}
message& id(std::string_view s) { attr("id", s); return *this; }
message& from(std::string_view s) { attr("from", s); return *this; }
message& to(std::string_view s) { attr("to", s); return *this; }
message& type(std::string_view s) { attr("type", s); return *this; }
message& body(builder::body b) { child(b); return *this; }
message& body(std::string_view s) { return body(builder::body(s)); }
};
struct presence : public spec {
presence() : spec("presence") {}
};
struct iq : public spec {
iq() : spec("iq") {}
};
struct error : public spec {
error() : spec("error") {}
};
}
}
#include "xep-0027.inl"

Loading…
Cancel
Save