diff --git a/.depend b/.depend index fbe203d..519fa70 100644 --- a/.depend +++ b/.depend @@ -1,7 +1,8 @@ .plugin.o: plugin.cpp plugin.hh config.hh deps/fmt/include/fmt/core.h \ - account.hh pgp.hh omemo.hh /usr/include/signal/signal_protocol.h \ - /usr/include/signal/ratchet.h \ + config/file.hh config/breadcrumb.hh config/section.hh config/account.hh \ + config/option.hh account.hh pgp.hh omemo.hh \ + /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/session_record.h \ /usr/include/signal/session_pre_key.h \ @@ -14,6 +15,11 @@ plugin.hh: config.hh: deps/fmt/include/fmt/core.h: +config/file.hh: +config/breadcrumb.hh: +config/section.hh: +config/account.hh: +config/option.hh: account.hh: pgp.hh: omemo.hh: @@ -59,7 +65,8 @@ completion.hh: /usr/include/libxml2/libxml/SAX2.h \ /usr/include/libxml2/libxml/xmlmemory.h \ /usr/include/libxml2/libxml/threads.h plugin.hh xmpp/stanza.hh config.hh \ - input.hh omemo.hh /usr/include/signal/signal_protocol.h \ + config/file.hh config/breadcrumb.hh config/section.hh config/account.hh \ + config/option.hh input.hh omemo.hh /usr/include/signal/signal_protocol.h \ /usr/include/signal/ratchet.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/session_record.h \ @@ -94,6 +101,11 @@ deps/fmt/include/fmt/core.h: plugin.hh: xmpp/stanza.hh: config.hh: +config/file.hh: +config/breadcrumb.hh: +config/section.hh: +config/account.hh: +config/option.hh: input.hh: omemo.hh: /usr/include/signal/signal_protocol.h: @@ -128,8 +140,10 @@ buffer.hh: /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ /usr/include/signal/session_cipher.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h config.hh channel.hh connection.hh \ - xmpp/ns.hh strophe.hh user.hh buffer.hh + /usr/include/signal/curve.h config.hh config/file.hh \ + config/breadcrumb.hh config/section.hh config/account.hh \ + config/option.hh channel.hh connection.hh xmpp/ns.hh strophe.hh user.hh \ + buffer.hh plugin.hh: account.hh: deps/fmt/include/fmt/core.h: @@ -150,6 +164,11 @@ signal.hh: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: config.hh: +config/file.hh: +config/breadcrumb.hh: +config/section.hh: +config/account.hh: +config/option.hh: channel.hh: connection.hh: xmpp/ns.hh: @@ -166,10 +185,12 @@ buffer.hh: /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ /usr/include/signal/session_cipher.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h config.hh channel.hh connection.hh \ - xmpp/ns.hh strophe.hh user.hh input.hh buffer.hh util.hh xmpp/node.hh \ - xmpp/xep-0027.inl xmpp/xep-0030.inl xmpp/xep-0045.inl xmpp/xep-0049.inl \ - xmpp/xep-0115.inl xmpp/xep-0280.inl xmpp/xep-0319.inl xmpp/rfc-6121.inl + /usr/include/signal/curve.h config.hh config/file.hh \ + config/breadcrumb.hh config/section.hh config/account.hh \ + config/option.hh channel.hh connection.hh xmpp/ns.hh strophe.hh user.hh \ + input.hh buffer.hh util.hh xmpp/node.hh xmpp/xep-0027.inl \ + xmpp/xep-0030.inl xmpp/xep-0045.inl xmpp/xep-0049.inl xmpp/xep-0115.inl \ + xmpp/xep-0280.inl xmpp/xep-0319.inl xmpp/rfc-6121.inl deps/fmt/include/fmt/core.h: plugin.hh: account.hh: @@ -190,6 +211,11 @@ signal.hh: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: config.hh: +config/file.hh: +config/breadcrumb.hh: +config/section.hh: +config/account.hh: +config/option.hh: channel.hh: connection.hh: xmpp/ns.hh: @@ -217,9 +243,11 @@ xmpp/rfc-6121.inl: /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ /usr/include/signal/session_cipher.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h config.hh channel.hh connection.hh \ - xmpp/ns.hh strophe.hh user.hh buffer.hh message.hh command.hh \ - sexp/driver.hh sexp/scanner.hh sexp/parser.tab.hh sexp/location.hh + /usr/include/signal/curve.h config.hh config/file.hh \ + config/breadcrumb.hh config/section.hh config/account.hh \ + config/option.hh channel.hh connection.hh xmpp/ns.hh strophe.hh user.hh \ + buffer.hh message.hh command.hh sexp/driver.hh sexp/scanner.hh \ + sexp/parser.tab.hh sexp/location.hh plugin.hh: account.hh: deps/fmt/include/fmt/core.h: @@ -240,6 +268,11 @@ signal.hh: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: config.hh: +config/file.hh: +config/breadcrumb.hh: +config/section.hh: +config/account.hh: +config/option.hh: channel.hh: connection.hh: xmpp/ns.hh: @@ -253,8 +286,10 @@ sexp/scanner.hh: sexp/parser.tab.hh: sexp/location.hh: .completion.o: completion.cpp plugin.hh config.hh \ - deps/fmt/include/fmt/core.h account.hh pgp.hh omemo.hh \ - /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ + deps/fmt/include/fmt/core.h config/file.hh config/breadcrumb.hh \ + config/section.hh config/account.hh config/option.hh account.hh pgp.hh \ + omemo.hh /usr/include/signal/signal_protocol.h \ + /usr/include/signal/ratchet.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/session_record.h \ /usr/include/signal/session_pre_key.h \ @@ -267,6 +302,11 @@ sexp/location.hh: plugin.hh: config.hh: deps/fmt/include/fmt/core.h: +config/file.hh: +config/breadcrumb.hh: +config/section.hh: +config/account.hh: +config/option.hh: account.hh: pgp.hh: omemo.hh: @@ -301,8 +341,9 @@ completion.hh: /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ /usr/include/signal/session_cipher.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h config.hh channel.hh connection.hh \ - xmpp/ns.hh strophe.hh user.hh + /usr/include/signal/curve.h config.hh config/file.hh \ + config/breadcrumb.hh config/section.hh config/account.hh \ + config/option.hh channel.hh connection.hh xmpp/ns.hh strophe.hh user.hh plugin.hh: account.hh: deps/fmt/include/fmt/core.h: @@ -323,6 +364,11 @@ signal.hh: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: config.hh: +config/file.hh: +config/breadcrumb.hh: +config/section.hh: +config/account.hh: +config/option.hh: channel.hh: connection.hh: xmpp/ns.hh: @@ -350,9 +396,10 @@ user.hh: /usr/include/libxml2/libxml/xmlIO.h /usr/include/libxml2/libxml/SAX2.h \ plugin.hh xmpp/node.hh xmpp/xep-0027.inl xmpp/ns.hh xmpp/xep-0030.inl \ xmpp/xep-0045.inl xmpp/xep-0049.inl xmpp/xep-0115.inl xmpp/xep-0280.inl \ - xmpp/xep-0319.inl xmpp/rfc-6121.inl xmpp/stanza.hh config.hh account.hh \ - pgp.hh omemo.hh /usr/include/signal/signal_protocol.h \ - /usr/include/signal/ratchet.h \ + xmpp/xep-0319.inl xmpp/rfc-6121.inl xmpp/stanza.hh config.hh \ + config/file.hh config/breadcrumb.hh config/section.hh config/account.hh \ + config/option.hh account.hh pgp.hh omemo.hh \ + /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/session_record.h \ /usr/include/signal/session_pre_key.h \ @@ -399,6 +446,11 @@ xmpp/xep-0319.inl: xmpp/rfc-6121.inl: xmpp/stanza.hh: config.hh: +config/file.hh: +config/breadcrumb.hh: +config/section.hh: +config/account.hh: +config/option.hh: account.hh: pgp.hh: omemo.hh: @@ -432,8 +484,10 @@ deps/diff/diff.h: /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ /usr/include/signal/session_cipher.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h config.hh channel.hh connection.hh \ - xmpp/ns.hh strophe.hh user.hh buffer.hh message.hh input.hh + /usr/include/signal/curve.h config.hh config/file.hh \ + config/breadcrumb.hh config/section.hh config/account.hh \ + config/option.hh channel.hh connection.hh xmpp/ns.hh strophe.hh user.hh \ + buffer.hh message.hh input.hh plugin.hh: account.hh: deps/fmt/include/fmt/core.h: @@ -454,6 +508,11 @@ signal.hh: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: config.hh: +config/file.hh: +config/breadcrumb.hh: +config/section.hh: +config/account.hh: +config/option.hh: channel.hh: connection.hh: xmpp/ns.hh: @@ -472,8 +531,10 @@ input.hh: /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ /usr/include/signal/session_cipher.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h config.hh channel.hh connection.hh \ - xmpp/ns.hh strophe.hh user.hh message.hh + /usr/include/signal/curve.h config.hh config/file.hh \ + config/breadcrumb.hh config/section.hh config/account.hh \ + config/option.hh channel.hh connection.hh xmpp/ns.hh strophe.hh user.hh \ + message.hh plugin.hh: account.hh: deps/fmt/include/fmt/core.h: @@ -494,6 +555,11 @@ signal.hh: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: config.hh: +config/file.hh: +config/breadcrumb.hh: +config/section.hh: +config/account.hh: +config/option.hh: channel.hh: connection.hh: xmpp/ns.hh: @@ -783,8 +849,10 @@ message.hh: /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ /usr/include/signal/session_cipher.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h config.hh channel.hh connection.hh \ - xmpp/ns.hh strophe.hh user.hh gcrypt.hh util.hh + /usr/include/signal/curve.h config.hh config/file.hh \ + config/breadcrumb.hh config/section.hh config/account.hh \ + config/option.hh channel.hh connection.hh xmpp/ns.hh strophe.hh user.hh \ + gcrypt.hh util.hh deps/fmt/include/fmt/core.h: deps/range-v3/include/range/v3/all.hpp: deps/range-v3/include/range/v3/action.hpp: @@ -1079,6 +1147,11 @@ signal.hh: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: config.hh: +config/file.hh: +config/breadcrumb.hh: +config/section.hh: +config/account.hh: +config/option.hh: channel.hh: connection.hh: xmpp/ns.hh: @@ -1100,8 +1173,9 @@ pgp.hh: /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ /usr/include/signal/session_cipher.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h config.hh channel.hh connection.hh \ - xmpp/ns.hh strophe.hh user.hh + /usr/include/signal/curve.h config.hh config/file.hh \ + config/breadcrumb.hh config/section.hh config/account.hh \ + config/option.hh channel.hh connection.hh xmpp/ns.hh strophe.hh user.hh plugin.hh: account.hh: deps/fmt/include/fmt/core.h: @@ -1122,6 +1196,11 @@ signal.hh: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: config.hh: +config/file.hh: +config/breadcrumb.hh: +config/section.hh: +config/account.hh: +config/option.hh: channel.hh: connection.hh: xmpp/ns.hh: @@ -1130,6 +1209,194 @@ user.hh: .util.o: util.cpp plugin.hh util.hh plugin.hh: util.hh: +config/.breadcrumb.o: config/breadcrumb.cpp config/breadcrumb.hh \ + deps/fmt/include/fmt/core.h config/./.plugin.hh +config/breadcrumb.hh: +deps/fmt/include/fmt/core.h: +config/./.plugin.hh: +config/.file.o: config/file.cpp config/../plugin.hh config/../account.hh \ + deps/fmt/include/fmt/core.h config/./.pgp.hh config/../omemo.hh \ + /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ + /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ + /usr/include/signal/session_record.h \ + /usr/include/signal/session_pre_key.h \ + /usr/include/signal/sender_key_record.h config/./.signal.hh \ + /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ + /usr/include/signal/session_cipher.h \ + /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ + /usr/include/signal/curve.h config/./.config.hh config/../config/file.hh \ + config/./.config/breadcrumb.hh config/../config/section.hh \ + config/./.config/account.hh config/../config/option.hh \ + config/./.channel.hh config/../connection.hh config/../xmpp/ns.hh \ + config/./.strophe.hh config/../user.hh +config/./.plugin.hh: +config/./.account.hh: +deps/fmt/include/fmt/core.h: +config/./.pgp.hh: +config/./.omemo.hh: +/usr/include/signal/signal_protocol.h: +/usr/include/signal/ratchet.h: +/usr/include/signal/signal_protocol_types.h: +/usr/include/signal/curve.h: +/usr/include/signal/session_record.h: +/usr/include/signal/session_pre_key.h: +/usr/include/signal/sender_key_record.h: +config/./.signal.hh: +/usr/include/signal/key_helper.h: +/usr/include/signal/session_builder.h: +/usr/include/signal/session_cipher.h: +/usr/include/signal/session_pre_key.h: +/usr/include/signal/protocol.h: +/usr/include/signal/curve.h: +config/./.config.hh: +config/./.config/file.hh: +config/./.config/breadcrumb.hh: +config/./.config/section.hh: +config/./.config/account.hh: +config/./.config/option.hh: +config/./.channel.hh: +config/./.connection.hh: +config/./.xmpp/ns.hh: +config/./.strophe.hh: +config/./.user.hh: +config/.section.o: config/section.cpp config/../plugin.hh \ + config/./.account.hh deps/fmt/include/fmt/core.h config/../pgp.hh \ + config/./.omemo.hh /usr/include/signal/signal_protocol.h \ + /usr/include/signal/ratchet.h \ + /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ + /usr/include/signal/session_record.h \ + /usr/include/signal/session_pre_key.h \ + /usr/include/signal/sender_key_record.h config/./.signal.hh \ + /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ + /usr/include/signal/session_cipher.h \ + /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ + /usr/include/signal/curve.h config/./.config.hh config/../config/file.hh \ + config/./.config/breadcrumb.hh config/../config/section.hh \ + config/./.config/account.hh config/../config/option.hh \ + config/./.channel.hh config/../connection.hh config/../xmpp/ns.hh \ + config/./.strophe.hh config/../user.hh +config/./.plugin.hh: +config/./.account.hh: +deps/fmt/include/fmt/core.h: +config/./.pgp.hh: +config/./.omemo.hh: +/usr/include/signal/signal_protocol.h: +/usr/include/signal/ratchet.h: +/usr/include/signal/signal_protocol_types.h: +/usr/include/signal/curve.h: +/usr/include/signal/session_record.h: +/usr/include/signal/session_pre_key.h: +/usr/include/signal/sender_key_record.h: +config/./.signal.hh: +/usr/include/signal/key_helper.h: +/usr/include/signal/session_builder.h: +/usr/include/signal/session_cipher.h: +/usr/include/signal/session_pre_key.h: +/usr/include/signal/protocol.h: +/usr/include/signal/curve.h: +config/./.config.hh: +config/./.config/file.hh: +config/./.config/breadcrumb.hh: +config/./.config/section.hh: +config/./.config/account.hh: +config/./.config/option.hh: +config/./.channel.hh: +config/./.connection.hh: +config/./.xmpp/ns.hh: +config/./.strophe.hh: +config/./.user.hh: +config/.account.o: config/account.cpp config/../plugin.hh \ + config/./.account.hh deps/fmt/include/fmt/core.h config/../pgp.hh \ + config/./.omemo.hh /usr/include/signal/signal_protocol.h \ + /usr/include/signal/ratchet.h \ + /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ + /usr/include/signal/session_record.h \ + /usr/include/signal/session_pre_key.h \ + /usr/include/signal/sender_key_record.h config/./.signal.hh \ + /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ + /usr/include/signal/session_cipher.h \ + /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ + /usr/include/signal/curve.h config/./.config.hh config/../config/file.hh \ + config/./.config/breadcrumb.hh config/../config/section.hh \ + config/./.config/account.hh config/../config/option.hh \ + config/./.channel.hh config/../connection.hh config/../xmpp/ns.hh \ + config/./.strophe.hh config/../user.hh +config/./.plugin.hh: +config/./.account.hh: +deps/fmt/include/fmt/core.h: +config/./.pgp.hh: +config/./.omemo.hh: +/usr/include/signal/signal_protocol.h: +/usr/include/signal/ratchet.h: +/usr/include/signal/signal_protocol_types.h: +/usr/include/signal/curve.h: +/usr/include/signal/session_record.h: +/usr/include/signal/session_pre_key.h: +/usr/include/signal/sender_key_record.h: +config/./.signal.hh: +/usr/include/signal/key_helper.h: +/usr/include/signal/session_builder.h: +/usr/include/signal/session_cipher.h: +/usr/include/signal/session_pre_key.h: +/usr/include/signal/protocol.h: +/usr/include/signal/curve.h: +config/./.config.hh: +config/./.config/file.hh: +config/./.config/breadcrumb.hh: +config/./.config/section.hh: +config/./.config/account.hh: +config/./.config/option.hh: +config/./.channel.hh: +config/./.connection.hh: +config/./.xmpp/ns.hh: +config/./.strophe.hh: +config/./.user.hh: +config/.option.o: config/option.cpp config/../plugin.hh \ + config/./.account.hh deps/fmt/include/fmt/core.h config/../pgp.hh \ + config/./.omemo.hh /usr/include/signal/signal_protocol.h \ + /usr/include/signal/ratchet.h \ + /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ + /usr/include/signal/session_record.h \ + /usr/include/signal/session_pre_key.h \ + /usr/include/signal/sender_key_record.h config/./.signal.hh \ + /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ + /usr/include/signal/session_cipher.h \ + /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ + /usr/include/signal/curve.h config/./.config.hh config/../config/file.hh \ + config/./.config/breadcrumb.hh config/../config/section.hh \ + config/./.config/account.hh config/../config/option.hh \ + config/./.channel.hh config/../connection.hh config/../xmpp/ns.hh \ + config/./.strophe.hh config/../user.hh +config/./.plugin.hh: +config/./.account.hh: +deps/fmt/include/fmt/core.h: +config/./.pgp.hh: +config/./.omemo.hh: +/usr/include/signal/signal_protocol.h: +/usr/include/signal/ratchet.h: +/usr/include/signal/signal_protocol_types.h: +/usr/include/signal/curve.h: +/usr/include/signal/session_record.h: +/usr/include/signal/session_pre_key.h: +/usr/include/signal/sender_key_record.h: +config/./.signal.hh: +/usr/include/signal/key_helper.h: +/usr/include/signal/session_builder.h: +/usr/include/signal/session_cipher.h: +/usr/include/signal/session_pre_key.h: +/usr/include/signal/protocol.h: +/usr/include/signal/curve.h: +config/./.config.hh: +config/./.config/file.hh: +config/./.config/breadcrumb.hh: +config/./.config/section.hh: +config/./.config/account.hh: +config/./.config/option.hh: +config/./.channel.hh: +config/./.connection.hh: +config/./.xmpp/ns.hh: +config/./.strophe.hh: +config/./.user.hh: xmpp/.presence.o: xmpp/presence.cpp xmpp/stanza.hh xmpp/stanza.hh: xmpp/.iq.o: xmpp/iq.cpp xmpp/stanza.hh diff --git a/config.cpp b/config.cpp index b49c8d4..29cf83f 100644 --- a/config.cpp +++ b/config.cpp @@ -7,8 +7,8 @@ #include #include #include +#include -#include "strophe.h" #include "plugin.hh" #include "account.hh" #include "config.hh" @@ -121,20 +121,6 @@ bool config_reload(weechat::config_file &file) return weechat_config_reload(file); } -bool weechat::config_account::write() -{ - if (!option_jid.write()) return false; - if (!option_password.write()) return false; - if (!option_tls.write()) return false; - if (!option_nickname.write()) return false; - if (!option_autoconnect.write()) return false; - if (!option_resource.write()) return false; - if (!option_status.write()) return false; - if (!option_pgp_path.write()) return false; - if (!option_pgp_keyid.write()) return false; - return true; -} - weechat::config::config() : file{*this, "xmpp", &config_reload} , section_account_default{file, "account_default", 0, 0, {}, {}, {}, {}, {}} diff --git a/config.hh b/config.hh index 793c749..cca9c5b 100644 --- a/config.hh +++ b/config.hh @@ -14,349 +14,18 @@ #include "fmt/core.h" #include "plugin.hh" -using namespace std::placeholders; +#include "config/file.hh" +#include "config/section.hh" +#include "config/account.hh" +#include "config/option.hh" namespace weechat { - enum class tls_policy - { - disable = 0, - normal, - trust, - }; - class config; struct config_file; struct config_section; struct config_option; - struct config_breadcrumb { - config_breadcrumb(std::string name) - : name(name), parent(std::nullopt) {} - - config_breadcrumb(std::string name, config_breadcrumb& parent) - : name(name), parent(parent) {} - - std::string name; - std::optional> parent; - }; - - struct config_free { void operator() (struct t_config_file *ptr) { weechat_config_free(ptr); } }; - struct config_file : public std::unique_ptr, public config_breadcrumb { - config_file(struct t_config_file *ptr, config& config, std::string name) - : std::unique_ptr(ptr) - , config_breadcrumb(name) - , configuration(config) { - if (ptr == nullptr) throw std::runtime_error("weechat_config_new"); - } - config_file(config& config, std::string name, std::function cb_reload) - : config_file(weechat_config_new( - name.data(), - [](const void *, void *data, struct t_config_file *config_file) { - auto& file = *reinterpret_cast(data); - if (file != config_file) throw std::invalid_argument("file != config_file"); - if (!file.reload) return 1; - return file.reload() ? 1 : 0; - // WEECHAT_CONFIG_READ_OK == 0 - // WEECHAT_CONFIG_READ_MEMORY_ERROR == -1 - // WEECHAT_CONFIG_READ_FILE_NOT_FOUND == -2 - }, nullptr, this), config, name) { - this->reload = std::bind(cb_reload, std::ref(*this)); - } - operator struct t_config_file *() { return get(); } - std::function reload; - config& configuration; - std::unordered_map sections; - bool read() { return weechat_config_read(*this); } - bool write() { return weechat_config_write(*this); } - }; - - struct config_section_free { void operator() (struct t_config_section *ptr) { weechat_config_section_free(ptr); } }; - struct config_section : public std::unique_ptr, public config_breadcrumb { - config_section(struct t_config_section *ptr, config_file& file, std::string name) - : std::unique_ptr(ptr) - , config_breadcrumb(name) - , file(file) { - if (ptr == nullptr) throw std::runtime_error("weechat_config_new_section"); - } - config_section(config_file& config_file, std::string name, - bool user_can_add_options, bool user_can_delete_options, - std::function cb_read, - std::function cb_write, - std::function cb_write_default, - std::function cb_create_option, - std::function cb_delete_option) - : config_section(weechat_config_new_section( - config_file, name.data(), user_can_add_options, user_can_delete_options, - [](const void *, void *data, struct t_config_file *config_file, - struct t_config_section *sect, const char *option_name, const char *value) { - auto& section = *reinterpret_cast(data); - if (section != sect) throw std::invalid_argument("section != sect"); - if (section.file != config_file) throw std::invalid_argument("section.file != config_file"); - if (!section.read) return 1; - return section.read(option_name, value) ? 2 : 0; - /// dev manual indicates: - // WEECHAT_CONFIG_READ_OK == 0 - // WEECHAT_CONFIG_READ_MEMORY_ERROR == -1 - // WEECHAT_CONFIG_READ_FILE_NOT_FOUND == -2 - /// code indicates: - // WEECHAT_CONFIG_OPTION_SET_OK_CHANGED == 2 - // WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE == 1 - // WEECHAT_CONFIG_OPTION_SET_ERROR == 0 - // WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND == -1 - }, nullptr, this, - [](const void *, void *data, struct t_config_file *config_file, - const char *section_name) { - auto& section = *reinterpret_cast(data); - if (section.file != config_file) throw std::invalid_argument("section.file != config_file"); - if (!section.write) return 0; - return section.write(section_name) ? 0 : -1; - // WEECHAT_CONFIG_WRITE_OK == 0 - // WEECHAT_CONFIG_WRITE_ERROR == -1 - // WEECHAT_CONFIG_WRITE_FILE_NOT_FOUND == -2 - }, nullptr, this, - [](const void *, void *data, struct t_config_file *config_file, - const char *section_name) { - auto& section = *reinterpret_cast(data); - if (section.file != config_file) throw std::invalid_argument("section.file != config_file"); - if (!section.write_default) return 0; - return section.write_default(section_name) ? 0 : -1; - // WEECHAT_CONFIG_WRITE_OK == 0 - // WEECHAT_CONFIG_WRITE_ERROR == -1 - // WEECHAT_CONFIG_WRITE_FILE_NOT_FOUND == -2 - }, nullptr, this, - [](const void *, void *data, struct t_config_file *config_file, - struct t_config_section *sect, const char *option_name, const char *value) { - auto& section = *reinterpret_cast(data); - if (section != sect) throw std::invalid_argument("section != sect"); - if (section.file != config_file) throw std::invalid_argument("section.file != config_file"); - if (!section.create_option) return 1; - return section.create_option(option_name, value) ? 2 : 0; - // WEECHAT_CONFIG_OPTION_SET_OK_CHANGED == 2 - // WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE == 1 - // WEECHAT_CONFIG_OPTION_SET_ERROR == 0 - // WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND == -1 - }, nullptr, this, - [](const void *, void *data, struct t_config_file *config_file, - struct t_config_section *sect, struct t_config_option *opt) { - auto& section = *reinterpret_cast(data); - if (section != sect) throw std::invalid_argument("section != sect"); - if (section.file != config_file) throw std::invalid_argument("section.file != config_file"); - if (!section.delete_option) return 0; - auto option = section.options.find(opt); - if (option == section.options.end()) throw std::invalid_argument("unknown option"); - return section.delete_option(option->second) ? 1 : -1; - // WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET == 0 - // WEECHAT_CONFIG_OPTION_UNSET_OK_RESET == 1 - // WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED == 2 - // WEECHAT_CONFIG_OPTION_UNSET_ERROR == -1 - }, nullptr, this), config_file, name) { - if (cb_read) - this->read = std::bind(cb_read, std::ref(*this), _1, _2); - if (cb_write) - this->write = std::bind(cb_write, std::ref(*this), _1); - if (cb_write_default) - this->write_default = std::bind(cb_write_default, std::ref(*this), _1); - if (cb_create_option) - this->create_option = std::bind(cb_create_option, std::ref(*this), _1, _2); - if (cb_delete_option) - this->delete_option = std::bind(cb_delete_option, std::ref(*this), _1); - } - operator struct t_config_section *() { return get(); } - std::function read; - std::function write; - std::function write_default; - std::function create_option; - std::function delete_option; - config_file& file; - std::unordered_map options; - }; - - struct config_option_free { void operator() (struct t_config_option *ptr) { /* weechat_config_option_free(ptr); */ } }; - struct config_option : public std::unique_ptr, public config_breadcrumb { - config_option(struct t_config_option *ptr, config_section& section, std::string name) - : std::unique_ptr(ptr) - , config_breadcrumb(name, section) - , section(section) { - if (ptr == nullptr) throw std::runtime_error("weechat_config_new_option"); - } - config_option(config_file& config_file, config_section& section, - std::string name, const char *type, const char *description, const char *string_values, - int min, int max, const char *default_value, const char *value, bool null_value_allowed, - std::function cb_check_value, - std::function cb_change, - std::function cb_delete) - : config_option(weechat_config_new_option( - config_file, section, - name.data(), type, description, string_values, - min, max, default_value, value, null_value_allowed, - [](const void *, void *data, struct t_config_option *opt, const char *value) { - auto& option = *reinterpret_cast(data); - if (option != opt) throw std::invalid_argument("option != opt"); - if (!option.check_value) return 1; - return option.check_value(value) ? 1 : 0; - }, nullptr, this, - [](const void *, void *data, struct t_config_option *opt) { - auto& option = *reinterpret_cast(data); - if (option != opt) throw std::invalid_argument("option != opt"); - if (option.on_changed) option.on_changed(); - }, nullptr, this, - [](const void *, void *data, struct t_config_option *opt) { - auto& option = *reinterpret_cast(data); - if (option != opt) throw std::invalid_argument("option != opt"); - if (option.on_deleted) option.on_deleted(); - }, nullptr, this), section, name) { - if (cb_check_value) - this->check_value = std::bind(cb_check_value, std::ref(*this), _1); - if (cb_change) - this->on_changed = std::bind(cb_change, std::ref(*this)); - if (cb_delete) - this->on_deleted = std::bind(cb_delete, std::ref(*this)); - } - operator struct t_config_option *() { return get(); } - std::function check_value; - std::function on_changed; - std::function on_deleted; - config_section& section; - int operator =(std::string value) { return weechat_config_option_set(*this, value.data(), 1); } - int clear() { return weechat_config_option_set(*this, nullptr, 1); } - std::string_view string() { return weechat_config_string(*this); } - int integer() { return weechat_config_integer(*this); } - bool boolean() { return weechat_config_boolean(*this); } - bool write() { return weechat_config_write_option(section.file, *this); } - }; - - class config_account { - public: - config_account(config_file& config_file, config_section& section_account, const char *name) - : section(section_account) - , option_jid(config_file, section_account, - fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "jid"), - "string", "XMPP Account JID", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_password(config_file, section_account, - fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "password"), - "string", "XMPP Account Password", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_tls(config_file, section_account, - fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "tls"), - "integer", "XMPP Server TLS Policy", "disable|normal|trust", 0, 0, - "normal", "normal", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_nickname(config_file, section_account, - fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "nickname"), - "string", "XMPP Account Nickname", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_autoconnect(config_file, section_account, - fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "autoconnect"), - "boolean", "Autoconnect XMPP Account", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_resource(config_file, section_account, - fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "resource"), - "string", "XMPP Account Resource", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_status(config_file, section_account, - fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "status"), - "string", "XMPP Account Login Status", nullptr, 0, 0, - "probably about to segfault", "probably about to segfault", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_pgp_path(config_file, section_account, - fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "pgp_path"), - "string", "XMPP Account PGP Keyring Dir", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_pgp_keyid(config_file, section_account, - fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "pgp_keyid"), - "string", "XMPP Account PGP Key ID", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - { - } - - config_account(config_file& config_file, config_section& section_account_default) - : section(section_account_default) - , option_jid(config_file, section_account_default, - "jid", "string", "XMPP Account JID", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_password(config_file, section_account_default, - "password", "string", "XMPP Account Password", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_tls(config_file, section_account_default, - "tls", "integer", "XMPP Server TLS Policy", "disable|normal|trust", 0, 0, - "normal", "normal", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_nickname(config_file, section_account_default, - "nickname", "string", "XMPP Account Nickname", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_autoconnect(config_file, section_account_default, - "autoconnect", "boolean", "Autoconnect XMPP Account", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_resource(config_file, section_account_default, - "resource", "string", "XMPP Account Resource", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_status(config_file, section_account_default, - "status", "string", "XMPP Account Login Status", nullptr, 0, 0, - "probably about to segfault", "probably about to segfault", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_pgp_path(config_file, section_account_default, - "pgp_path", "string", "XMPP Account PGP Keyring Dir", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - , option_pgp_keyid(config_file, section_account_default, - "pgp_keyid", "string", "XMPP Account PGP Key ID", nullptr, 0, 0, "", "", false, - [&](config_option&, const char *) { return true; }, - [&](config_option&) {}, - [&](config_option&) {}) - { - } - - config_section& section; - - config_option option_jid; - config_option option_password; - config_option option_tls; - config_option option_nickname; - config_option option_autoconnect; - config_option option_resource; - config_option option_status; - config_option option_pgp_path; - config_option option_pgp_keyid; - - bool read(const char *, const char *); - bool write(); - }; - class config { public: enum class nick_completion diff --git a/config/account.cpp b/config/account.cpp new file mode 100644 index 0000000..18d94fd --- /dev/null +++ b/config/account.cpp @@ -0,0 +1,24 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, version 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include +#include + +#include "../plugin.hh" +#include "../account.hh" +#include "account.hh" + +bool weechat::config_account::write() +{ + if (!option_jid.write()) return false; + if (!option_password.write()) return false; + if (!option_tls.write()) return false; + if (!option_nickname.write()) return false; + if (!option_autoconnect.write()) return false; + if (!option_resource.write()) return false; + if (!option_status.write()) return false; + if (!option_pgp_path.write()) return false; + if (!option_pgp_keyid.write()) return false; + return true; +} diff --git a/config/account.hh b/config/account.hh new file mode 100644 index 0000000..1aaf316 --- /dev/null +++ b/config/account.hh @@ -0,0 +1,162 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, version 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "fmt/core.h" +#include "../plugin.hh" +#include "section.hh" +#include "option.hh" + +namespace weechat +{ + enum class tls_policy + { + disable = 0, + normal, + trust, + }; + + struct config_file; + struct config_section; + struct config_option; + + class config_account { + public: + config_account(config_file& config_file, config_section& section_account, const char *name) + : section(section_account) + , option_jid(config_file, section_account, + fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "jid"), + "string", "XMPP Account JID", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_password(config_file, section_account, + fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "password"), + "string", "XMPP Account Password", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_tls(config_file, section_account, + fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "tls"), + "integer", "XMPP Server TLS Policy", "disable|normal|trust", 0, 0, + "normal", "normal", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_nickname(config_file, section_account, + fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "nickname"), + "string", "XMPP Account Nickname", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_autoconnect(config_file, section_account, + fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "autoconnect"), + "boolean", "Autoconnect XMPP Account", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_resource(config_file, section_account, + fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "resource"), + "string", "XMPP Account Resource", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_status(config_file, section_account, + fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "status"), + "string", "XMPP Account Login Status", nullptr, 0, 0, + "probably about to segfault", "probably about to segfault", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_pgp_path(config_file, section_account, + fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "pgp_path"), + "string", "XMPP Account PGP Keyring Dir", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_pgp_keyid(config_file, section_account, + fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "pgp_keyid"), + "string", "XMPP Account PGP Key ID", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + { + } + + config_account(config_file& config_file, config_section& section_account_default) + : section(section_account_default) + , option_jid(config_file, section_account_default, + "jid", "string", "XMPP Account JID", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_password(config_file, section_account_default, + "password", "string", "XMPP Account Password", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_tls(config_file, section_account_default, + "tls", "integer", "XMPP Server TLS Policy", "disable|normal|trust", 0, 0, + "normal", "normal", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_nickname(config_file, section_account_default, + "nickname", "string", "XMPP Account Nickname", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_autoconnect(config_file, section_account_default, + "autoconnect", "boolean", "Autoconnect XMPP Account", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_resource(config_file, section_account_default, + "resource", "string", "XMPP Account Resource", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_status(config_file, section_account_default, + "status", "string", "XMPP Account Login Status", nullptr, 0, 0, + "probably about to segfault", "probably about to segfault", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_pgp_path(config_file, section_account_default, + "pgp_path", "string", "XMPP Account PGP Keyring Dir", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + , option_pgp_keyid(config_file, section_account_default, + "pgp_keyid", "string", "XMPP Account PGP Key ID", nullptr, 0, 0, "", "", false, + [&](config_option&, const char *) { return true; }, + [&](config_option&) {}, + [&](config_option&) {}) + { + } + + config_section& section; + + config_option option_jid; + config_option option_password; + config_option option_tls; + config_option option_nickname; + config_option option_autoconnect; + config_option option_resource; + config_option option_status; + config_option option_pgp_path; + config_option option_pgp_keyid; + + bool read(const char *, const char *); + bool write(); + }; +} diff --git a/config/breadcrumb.cpp b/config/breadcrumb.cpp new file mode 100644 index 0000000..f580922 --- /dev/null +++ b/config/breadcrumb.cpp @@ -0,0 +1,7 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, version 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include "breadcrumb.hh" diff --git a/config/breadcrumb.hh b/config/breadcrumb.hh new file mode 100644 index 0000000..73960f1 --- /dev/null +++ b/config/breadcrumb.hh @@ -0,0 +1,29 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, version 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "fmt/core.h" +#include "../plugin.hh" + +namespace weechat +{ + struct config_breadcrumb { + config_breadcrumb(std::string name) + : name(name), parent(std::nullopt) {} + + config_breadcrumb(std::string name, config_breadcrumb& parent) + : name(name), parent(parent) {} + + std::string name; + std::optional> parent; + }; +} diff --git a/config/file.cpp b/config/file.cpp new file mode 100644 index 0000000..8809437 --- /dev/null +++ b/config/file.cpp @@ -0,0 +1,9 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, version 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include "../plugin.hh" +#include "../account.hh" +#include "file.hh" diff --git a/config/file.hh b/config/file.hh new file mode 100644 index 0000000..e34d1d5 --- /dev/null +++ b/config/file.hh @@ -0,0 +1,53 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, version 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "fmt/core.h" +#include "../plugin.hh" +#include "breadcrumb.hh" + +namespace weechat +{ + class config; + struct config_file; + struct config_section; + + struct config_free { void operator() (struct t_config_file *ptr) { weechat_config_free(ptr); } }; + struct config_file : public std::unique_ptr, public config_breadcrumb { + config_file(struct t_config_file *ptr, config& config, std::string name) + : std::unique_ptr(ptr) + , config_breadcrumb(name) + , configuration(config) { + if (ptr == nullptr) throw std::runtime_error("weechat_config_new"); + } + config_file(config& config, std::string name, std::function cb_reload) + : config_file(weechat_config_new( + name.data(), + [](const void *, void *data, struct t_config_file *config_file) { + auto& file = *reinterpret_cast(data); + if (file != config_file) throw std::invalid_argument("file != config_file"); + if (!file.reload) return 1; + return file.reload() ? 1 : 0; + // WEECHAT_CONFIG_READ_OK == 0 + // WEECHAT_CONFIG_READ_MEMORY_ERROR == -1 + // WEECHAT_CONFIG_READ_FILE_NOT_FOUND == -2 + }, nullptr, this), config, name) { + this->reload = std::bind(cb_reload, std::ref(*this)); + } + operator struct t_config_file *() { return get(); } + std::function reload; + config& configuration; + std::unordered_map sections; + bool read() { return weechat_config_read(*this); } + bool write() { return weechat_config_write(*this); } + }; +} diff --git a/config/option.cpp b/config/option.cpp new file mode 100644 index 0000000..1925eb3 --- /dev/null +++ b/config/option.cpp @@ -0,0 +1,9 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, version 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include "../plugin.hh" +#include "../account.hh" +#include "option.hh" diff --git a/config/option.hh b/config/option.hh new file mode 100644 index 0000000..8d0c2b2 --- /dev/null +++ b/config/option.hh @@ -0,0 +1,78 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, version 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "fmt/core.h" +#include "../plugin.hh" +#include "breadcrumb.hh" + +using namespace std::placeholders; + +namespace weechat +{ + struct config_file; + struct config_section; + + struct config_option_free { void operator() (struct t_config_option *ptr) { /* weechat_config_option_free(ptr); */ } }; + struct config_option : public std::unique_ptr, public config_breadcrumb { + config_option(struct t_config_option *ptr, config_section& section, std::string name) + : std::unique_ptr(ptr) + , config_breadcrumb(name, section) + , section(section) { + if (ptr == nullptr) throw std::runtime_error("weechat_config_new_option"); + } + config_option(config_file& config_file, config_section& section, + std::string name, const char *type, const char *description, const char *string_values, + int min, int max, const char *default_value, const char *value, bool null_value_allowed, + std::function cb_check_value, + std::function cb_change, + std::function cb_delete) + : config_option(weechat_config_new_option( + config_file, section, + name.data(), type, description, string_values, + min, max, default_value, value, null_value_allowed, + [](const void *, void *data, struct t_config_option *opt, const char *value) { + auto& option = *reinterpret_cast(data); + if (option != opt) throw std::invalid_argument("option != opt"); + if (!option.check_value) return 1; + return option.check_value(value) ? 1 : 0; + }, nullptr, this, + [](const void *, void *data, struct t_config_option *opt) { + auto& option = *reinterpret_cast(data); + if (option != opt) throw std::invalid_argument("option != opt"); + if (option.on_changed) option.on_changed(); + }, nullptr, this, + [](const void *, void *data, struct t_config_option *opt) { + auto& option = *reinterpret_cast(data); + if (option != opt) throw std::invalid_argument("option != opt"); + if (option.on_deleted) option.on_deleted(); + }, nullptr, this), section, name) { + if (cb_check_value) + this->check_value = std::bind(cb_check_value, std::ref(*this), _1); + if (cb_change) + this->on_changed = std::bind(cb_change, std::ref(*this)); + if (cb_delete) + this->on_deleted = std::bind(cb_delete, std::ref(*this)); + } + operator struct t_config_option *() { return get(); } + std::function check_value; + std::function on_changed; + std::function on_deleted; + config_section& section; + int operator =(std::string value) { return weechat_config_option_set(*this, value.data(), 1); } + int clear() { return weechat_config_option_set(*this, nullptr, 1); } + std::string_view string() { return weechat_config_string(*this); } + int integer() { return weechat_config_integer(*this); } + bool boolean() { return weechat_config_boolean(*this); } + bool write() { return weechat_config_write_option(section.file, *this); } + }; +} diff --git a/config/section.cpp b/config/section.cpp new file mode 100644 index 0000000..5b0b565 --- /dev/null +++ b/config/section.cpp @@ -0,0 +1,9 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, version 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include "../plugin.hh" +#include "../account.hh" +#include "section.hh" diff --git a/config/section.hh b/config/section.hh new file mode 100644 index 0000000..b40fbec --- /dev/null +++ b/config/section.hh @@ -0,0 +1,127 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, version 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "fmt/core.h" +#include "../plugin.hh" +#include "breadcrumb.hh" + +using namespace std::placeholders; + +namespace weechat +{ + class config; + struct config_file; + struct config_section; + struct config_option; + + struct config_section_free { void operator() (struct t_config_section *ptr) { weechat_config_section_free(ptr); } }; + struct config_section : public std::unique_ptr, public config_breadcrumb { + config_section(struct t_config_section *ptr, config_file& file, std::string name) + : std::unique_ptr(ptr) + , config_breadcrumb(name) + , file(file) { + if (ptr == nullptr) throw std::runtime_error("weechat_config_new_section"); + } + config_section(config_file& config_file, std::string name, + bool user_can_add_options, bool user_can_delete_options, + std::function cb_read, + std::function cb_write, + std::function cb_write_default, + std::function cb_create_option, + std::function cb_delete_option) + : config_section(weechat_config_new_section( + config_file, name.data(), user_can_add_options, user_can_delete_options, + [](const void *, void *data, struct t_config_file *config_file, + struct t_config_section *sect, const char *option_name, const char *value) { + auto& section = *reinterpret_cast(data); + if (section != sect) throw std::invalid_argument("section != sect"); + if (section.file != config_file) throw std::invalid_argument("section.file != config_file"); + if (!section.read) return 1; + return section.read(option_name, value) ? 2 : 0; + /// dev manual indicates: + // WEECHAT_CONFIG_READ_OK == 0 + // WEECHAT_CONFIG_READ_MEMORY_ERROR == -1 + // WEECHAT_CONFIG_READ_FILE_NOT_FOUND == -2 + /// code indicates: + // WEECHAT_CONFIG_OPTION_SET_OK_CHANGED == 2 + // WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE == 1 + // WEECHAT_CONFIG_OPTION_SET_ERROR == 0 + // WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND == -1 + }, nullptr, this, + [](const void *, void *data, struct t_config_file *config_file, + const char *section_name) { + auto& section = *reinterpret_cast(data); + if (section.file != config_file) throw std::invalid_argument("section.file != config_file"); + if (!section.write) return 0; + return section.write(section_name) ? 0 : -1; + // WEECHAT_CONFIG_WRITE_OK == 0 + // WEECHAT_CONFIG_WRITE_ERROR == -1 + // WEECHAT_CONFIG_WRITE_FILE_NOT_FOUND == -2 + }, nullptr, this, + [](const void *, void *data, struct t_config_file *config_file, + const char *section_name) { + auto& section = *reinterpret_cast(data); + if (section.file != config_file) throw std::invalid_argument("section.file != config_file"); + if (!section.write_default) return 0; + return section.write_default(section_name) ? 0 : -1; + // WEECHAT_CONFIG_WRITE_OK == 0 + // WEECHAT_CONFIG_WRITE_ERROR == -1 + // WEECHAT_CONFIG_WRITE_FILE_NOT_FOUND == -2 + }, nullptr, this, + [](const void *, void *data, struct t_config_file *config_file, + struct t_config_section *sect, const char *option_name, const char *value) { + auto& section = *reinterpret_cast(data); + if (section != sect) throw std::invalid_argument("section != sect"); + if (section.file != config_file) throw std::invalid_argument("section.file != config_file"); + if (!section.create_option) return 1; + return section.create_option(option_name, value) ? 2 : 0; + // WEECHAT_CONFIG_OPTION_SET_OK_CHANGED == 2 + // WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE == 1 + // WEECHAT_CONFIG_OPTION_SET_ERROR == 0 + // WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND == -1 + }, nullptr, this, + [](const void *, void *data, struct t_config_file *config_file, + struct t_config_section *sect, struct t_config_option *opt) { + auto& section = *reinterpret_cast(data); + if (section != sect) throw std::invalid_argument("section != sect"); + if (section.file != config_file) throw std::invalid_argument("section.file != config_file"); + if (!section.delete_option) return 0; + auto option = section.options.find(opt); + if (option == section.options.end()) throw std::invalid_argument("unknown option"); + return section.delete_option(option->second) ? 1 : -1; + // WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET == 0 + // WEECHAT_CONFIG_OPTION_UNSET_OK_RESET == 1 + // WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED == 2 + // WEECHAT_CONFIG_OPTION_UNSET_ERROR == -1 + }, nullptr, this), config_file, name) { + if (cb_read) + this->read = std::bind(cb_read, std::ref(*this), _1, _2); + if (cb_write) + this->write = std::bind(cb_write, std::ref(*this), _1); + if (cb_write_default) + this->write_default = std::bind(cb_write_default, std::ref(*this), _1); + if (cb_create_option) + this->create_option = std::bind(cb_create_option, std::ref(*this), _1, _2); + if (cb_delete_option) + this->delete_option = std::bind(cb_delete_option, std::ref(*this), _1); + } + operator struct t_config_section *() { return get(); } + std::function read; + std::function write; + std::function write_default; + std::function create_option; + std::function delete_option; + config_file& file; + std::unordered_map options; + }; +} diff --git a/makefile b/makefile index 152eb4d..3a6a858 100644 --- a/makefile +++ b/makefile @@ -66,6 +66,11 @@ HDRS=plugin.hh \ pgp.hh \ user.hh \ util.hh \ + config/breadcrumb.hh \ + config/file.hh \ + config/section.hh \ + config/account.hh \ + config/option.hh \ xmpp/stanza.hh \ xmpp/ns.hh \ xmpp/node.hh \ @@ -84,6 +89,11 @@ SRCS=plugin.cpp \ pgp.cpp \ user.cpp \ util.cpp \ + config/breadcrumb.cpp \ + config/file.cpp \ + config/section.cpp \ + config/account.cpp \ + config/option.cpp \ xmpp/presence.cpp \ xmpp/iq.cpp \ xmpp/node.cpp \ @@ -92,8 +102,8 @@ DEPS=deps/diff/libdiff.a \ deps/fmt/libfmt.a \ sexp/sexp.a \ -OBJS=$(patsubst %.cpp,.%.o,$(patsubst %.c,.%.o,$(patsubst xmpp/%.cpp,xmpp/.%.o,$(SRCS)))) -COVS=$(patsubst %.cpp,.%.cov.o,$(patsubst xmpp/%.cpp,xmpp/.%.cov.o,$(SRCS))) +OBJS=$(patsubst %.cpp,.%.o,$(patsubst %.c,.%.o,$(patsubst config/%.cpp,config/.%.o,$(patsubst xmpp/%.cpp,xmpp/.%.o,$(SRCS))))) +COVS=$(patsubst %.cpp,.%.cov.o,$(patsubst config/%.cpp,config/.%.cov.o,$(patsubst xmpp/%.cpp,xmpp/.%.cov.o,$(SRCS)))) SUFFIX=$(shell date +%s) @@ -138,6 +148,12 @@ sexp/driver.o: sexp/driver.cpp .%.cov.o: %.cpp @$(CXX) --coverage $(CPPFLAGS) -O0 -c $< -o $@ +config/.%.o: config/%.cpp + $(CXX) $(CPPFLAGS) -c $< -o $@ + +config/.%.cov.o: config/%.cpp + @$(CXX) --coverage $(CPPFLAGS) -O0 -c $< -o $@ + xmpp/.%.o: xmpp/%.cpp $(CXX) $(CPPFLAGS) -c $< -o $@ @@ -169,7 +185,7 @@ test: tests/run .PHONY: coverage coverage: tests/run - gcov -m -abcfu -rqk -i .*.gcda xmpp/.*.gcda + gcov -m -abcfu -rqk -i .*.gcda config/.*.gcda xmpp/.*.gcda .PHONY: debug debug: xmpp.so