aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/deferred_failure.hpp18
-rw-r--r--src/main.cpp24
-rw-r--r--src/optional.hpp43
-rw-r--r--src/setting.cpp105
-rw-r--r--src/setting.hpp154
-rw-r--r--src/type_wrapper.hpp24
-rw-r--r--src/variant.cpp17
-rw-r--r--src/variant.hpp47
8 files changed, 298 insertions, 134 deletions
diff --git a/src/deferred_failure.hpp b/src/deferred_failure.hpp
new file mode 100644
index 0000000..54adb97
--- /dev/null
+++ b/src/deferred_failure.hpp
@@ -0,0 +1,18 @@
+/**
+ * @file deferred_failure.hpp
+ * @author Felix Morgner (felix.morgner@gmail.com)
+ * @since 1.0.0
+ */
+
+#ifndef WANDA_DEFERRED_FAILURE_HPP
+#define WANDA_DEFERRED_FAILURE_HPP
+
+#include <type_traits>
+
+namespace
+{
+template <typename...>
+using deferred_failure = std::false_type;
+} // namespace
+
+#endif \ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index fb2e0bf..38fdf7f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -4,13 +4,25 @@
#include <iostream>
#include <string>
-int main() {
+#include <typeinfo>
+
+int main()
+{
using namespace wanda::literals;
using namespace wanda::std_ext;
+ using namespace std::string_literals;
- with("org.gnome.desktop.background"_setting, [](auto & setting){
- with(setting.template get<std::string>("picture-uri"_key), [](auto & value){
- std::cout << value << '\n';
- }) || []{ std::cerr << "No such key!\n"; };
- }) || []{ std::cerr << "No such setting!\n"; };
+ with("org.gnome.desktop.background"_setting, [](auto &setting) {
+ with(setting["picture-uri"_key], [](auto &value) {
+ std::visit([](auto &&value) {
+ using ValueType = std::decay_t<decltype(value)>;
+ if constexpr (std::is_same_v<ValueType, std::string>)
+ {
+ std::cout << value << '\n';
+ }
+ },
+ *value);
+ std::cout << (value = "file:///"s) << '\n';
+ }) || [] { std::cerr << "No such key!\n"; };
+ }) || [] { std::cerr << "No such setting!\n"; };
}
diff --git a/src/optional.hpp b/src/optional.hpp
index c178d59..5e1c630 100644
--- a/src/optional.hpp
+++ b/src/optional.hpp
@@ -1,36 +1,47 @@
+/**
+ * @file optional.hpp
+ * @author Felix Morgner (felix.morgner@gmail.com)
+ * @since 1.0.0
+ */
+
#ifndef WANDA_OPTIONAL_HPP
#define WANDA_OPTIONAL_HPP
#include <optional>
-namespace wanda::std_ext {
-
-struct failable {
+namespace wanda::std_ext
+{
+struct failable
+{
constexpr static auto success() { return failable{false}; }
constexpr static auto failure() { return failable{true}; }
- template<typename Handler>
- constexpr auto operator ||(Handler handler) const {
- if(m_failed) {
+ template <typename Handler>
+ constexpr auto operator||(Handler handler) const
+ {
+ if (m_failed)
+ {
handler();
}
}
-private:
- constexpr explicit failable(bool failed) : m_failed{failed} { };
+ private:
+ constexpr explicit failable(bool failed) : m_failed{failed} {};
bool const m_failed;
};
-template<typename ObjectType, typename HandlerType>
-auto with(std::optional<ObjectType> && object, HandlerType handler) {
- if(object) {
- handler(object.value());
- return failable::success();
- }
- return failable::failure();
+template <typename ObjectType, typename HandlerType>
+auto with(std::optional<ObjectType> &&object, HandlerType handler)
+{
+ if (object)
+ {
+ handler(object.value());
+ return failable::success();
+ }
+ return failable::failure();
}
-}
+} // namespace wanda::std_ext
#endif \ No newline at end of file
diff --git a/src/setting.cpp b/src/setting.cpp
index 9ddbfe8..39ae248 100644
--- a/src/setting.cpp
+++ b/src/setting.cpp
@@ -1,29 +1,102 @@
#include "setting.hpp"
-namespace wanda {
+#include <algorithm>
+#include <type_traits>
-namespace literals {
- key operator""_key(char const * str, std::size_t len) {
- return key{{str, len}};
+namespace wanda
+{
+
+// UDL implementations
+
+key literals::operator""_key(char const *str, std::size_t len)
+{
+ return key{{str, len}};
+}
+
+std::optional<setting> literals::operator""_setting(char const *str, std::size_t len)
+{
+ auto source = g_settings_schema_source_get_default();
+ if (!source)
+ {
+ return std::nullopt;
}
- std::optional<setting> operator""_setting(char const * str, std::size_t len) {
- auto source = g_settings_schema_source_get_default();
- auto schema = g_settings_schema_source_lookup(source, str, true);
- if(schema) {
- g_settings_schema_unref(schema);
- return setting{::wanda::schema{{str, len}}};
- }
+ auto schema = g_settings_schema_source_lookup(source, str, true);
+ if (!schema)
+ {
return std::nullopt;
}
+
+ return setting{schema};
}
-setting::setting(schema schema) : m_value{g_settings_new(schema.get().c_str())} { }
+// 'setting' implementation
+
+setting::setting(GSettingsSchema *schema)
+ : m_schema{schema, &g_settings_schema_unref}
+{
+}
+
+std::optional<setting::entry> setting::operator[](key key) const
+{
+ if (!g_settings_schema_has_key(m_schema.get(), key.get().c_str()))
+ {
+ return std::nullopt;
+ }
+
+ return setting::entry{*this, std::move(key)};
+}
-setting::setting(setting const & other) : m_value{reinterpret_cast<GSettings *>(g_object_ref(other.m_value))} { }
+// 'setting::entry' implementation
+
+setting::entry::entry(setting const &setting, key key)
+ : m_settings{g_settings_new(g_settings_schema_get_id(setting.m_schema.get())), &g_object_unref}, m_key{key.get()}
+{
+}
+
+setting::entry::value_type setting::entry::operator*() const
+{
+ auto value = std::unique_ptr<GVariant, decltype(&g_variant_unref)>{g_settings_get_value(m_settings.get(), m_key.get().c_str()), &g_variant_unref};
+ auto raw = value.get();
+
+ if (g_variant_is_of_type(raw, G_VARIANT_TYPE_BOOLEAN))
+ {
+ return static_cast<bool>(g_variant_get_boolean(raw));
+ }
+ else if (g_variant_is_of_type(raw, G_VARIANT_TYPE_INT32))
+ {
+ return static_cast<std::int32_t>(g_variant_get_int32(raw));
+ }
+ else if (g_variant_is_of_type(raw, G_VARIANT_TYPE_INT64))
+ {
+ return static_cast<std::int64_t>(g_variant_get_int64(raw));
+ }
+ else if (g_variant_is_of_type(raw, G_VARIANT_TYPE_UINT32))
+ {
+ return static_cast<std::uint32_t>(g_variant_get_uint32(raw));
+ }
+ else if (g_variant_is_of_type(raw, G_VARIANT_TYPE_UINT64))
+ {
+ return static_cast<std::uint64_t>(g_variant_get_uint64(raw));
+ }
+ else if (g_variant_is_of_type(raw, G_VARIANT_TYPE_DOUBLE))
+ {
+ return static_cast<double>(g_variant_get_double(raw));
+ }
+ else if (g_variant_is_of_type(raw, G_VARIANT_TYPE_STRING))
+ {
+ auto size = gsize{};
+ auto string = g_variant_get_string(raw, &size);
+ return std::string{string, size};
+ }
+ else if (g_variant_is_of_type(raw, G_VARIANT_TYPE_STRING_ARRAY))
+ {
+ auto length = gsize{};
+ auto data = g_variant_get_strv(raw, &length);
+ return std::vector<std::string>{data, data + length};
+ }
-setting::~setting() {
- g_clear_object(&m_value);
+ return {};
}
-} \ No newline at end of file
+} // namespace wanda \ No newline at end of file
diff --git a/src/setting.hpp b/src/setting.hpp
index 6293dd3..6e10a8a 100644
--- a/src/setting.hpp
+++ b/src/setting.hpp
@@ -1,48 +1,154 @@
+/**
+ * @file setting.hpp
+ * @author Felix Morgner (felix.morgner@gmail.com)
+ * @since 1.0.0
+ */
+
#ifndef WANDA_setting_HPP
#define WANDA_setting_HPP
+#include "deferred_failure.hpp"
+#include "type_wrapper.hpp"
+
#include <gio/gio.h>
+#include <algorithm>
#include <cstddef>
+#include <cstdint>
+#include <memory>
#include <optional>
#include <string>
-#include <type_traits>
+#include <variant>
+#include <vector>
-#include "type_wrapper.hpp"
-#include "variant.hpp"
-#include <iostream>
-
-namespace wanda {
+namespace wanda
+{
struct setting;
-using schema = type_wrapper<std::string, struct SchemaTag>;
+
+/**
+ * @brief A convenience type to represent setting keys
+ */
using key = type_wrapper<std::string, struct KeyTag>;
-namespace literals {
-key operator""_key(char const * str, std::size_t len);
-std::optional<setting> operator""_setting(char const * str, std::size_t len);
-}
+namespace literals
+{
+/**
+ * @brief UDL to create setting keys
+ */
+key operator""_key(char const *str, std::size_t len);
+
+/**
+ * @brief UDL to create setting schemas
+ */
+std::optional<setting> operator""_setting(char const *str, std::size_t lent);
+} // namespace literals
+
+/**
+ * @brief A simple wrapper for GSettings Schemas
+ */
+struct setting
+{
+ struct entry
+ {
+
+ using value_type = std::variant<std::monostate, bool, std::int32_t, std::int64_t, std::uint32_t, std::uint64_t, double, std::string, std::vector<std::string>>;
+
+ value_type operator*() const;
+
+ template <typename Type>
+ bool operator=(Type value)
+ {
+ struct setting_applier
+ {
+ setting_applier(GSettings *setting, gchar const *key, Type value) noexcept
+ : m_result{[&] {
+ if constexpr (std::is_same_v<Type, bool>)
+ {
+ return g_settings_set_boolean(setting, key, value);
+ }
+ else if constexpr (std::is_same_v<Type, std::int32_t>)
+ {
+ return g_settings_set_int(setting, key, value);
+ }
+ else if constexpr (std::is_same_v<Type, std::int64_t>)
+ {
+ return g_settings_set_int64(setting, key, value);
+ }
+ else if constexpr (std::is_same_v<Type, std::uint32_t>)
+ {
+ return g_settings_set_uint(setting, key, value);
+ }
+ else if constexpr (std::is_same_v<Type, std::uint64_t>)
+ {
+ return g_settings_set_uint64(setting, key, value);
+ }
+ else if constexpr (std::is_same_v<Type, double>)
+ {
+ return g_settings_set_double(setting, key, value);
+ }
+ else if constexpr (std::is_same_v<Type, std::string>)
+ {
+ return g_settings_set_string(setting, key, value.c_str());
+ }
+ else if constexpr (std::is_same_v<Type, std::vector<std::string>>)
+ {
+ auto temp = std::vector<gchar const *>{value.size() + 1};
+ std::transform(value.begin(), value.end(), temp.begin(), [](auto const &str) { return str.c_str(); });
+ return g_settings_set_strv(setting, key, temp.data());
+ }
+ else
+ {
+ static_assert(deferred_failure<Type>{}, "Invalid argument type!");
+ }
+ }()}
+ {
+ }
+
+ ~setting_applier()
+ {
+ g_settings_sync();
+ }
+
+ operator bool() const
+ {
+ return m_result;
+ }
+
+ private:
+ gboolean const m_result;
+ };
+
+ return setting_applier{m_settings.get(), m_key.get().c_str(), value};
+ }
-struct setting {
- ~setting();
+ private:
+ entry(setting const &schema, key key);
- setting(setting const & other);
+ std::unique_ptr<GSettings, decltype(&g_object_unref)> m_settings;
- template<typename TargetType> std::optional<TargetType> get(key key) const {
- auto value = variant{g_settings_get_value(m_value, key.get().c_str())};
- return value.get<TargetType>();
- }
+ key m_key;
-private:
- explicit setting(schema schema);
+ friend setting;
+ };
- GSettings * m_value;
+ /**
+ * @brief Get the entry for the given key
+ *
+ * @return An <code>std::optional</code> wrapping the entry associated with
+ * the given key, or an empty <code>std::optional</code> if the desired key
+ * does not exist in the setting's schema.
+ */
+ std::optional<entry> operator[](key key) const;
- friend std::optional<setting> literals::operator""_setting(char const *, std::size_t);
-};
+private:
+ explicit setting(GSettingsSchema *schema);
+ std::unique_ptr<GSettingsSchema, decltype(&g_settings_schema_unref)> m_schema;
-}
+ friend std::optional<setting> literals::operator""_setting(char const *, std::size_t);
+};
+} // namespace wanda
#endif \ No newline at end of file
diff --git a/src/type_wrapper.hpp b/src/type_wrapper.hpp
index d3bf694..f14497a 100644
--- a/src/type_wrapper.hpp
+++ b/src/type_wrapper.hpp
@@ -1,23 +1,31 @@
+/**
+ * @file type_wrapper.hpp
+ * @author Felix Morgner (felix.morgner@gmail.com)
+ * @since 1.0.0
+ */
+
#ifndef WANDA_TYPE_WRAPPER_HPP
#define WANDA_TYPE_WRAPPER_HPP
#include <utility>
-namespace wanda {
+namespace wanda
+{
-template<typename InnerType, typename TagType>
-struct type_wrapper {
+template <typename InnerType, typename TagType>
+struct type_wrapper
+{
- explicit type_wrapper(InnerType value) : m_value{std::move(value)} { }
+ explicit type_wrapper(InnerType value) : m_value{std::move(value)} {}
- constexpr explicit operator InnerType const & () const { return get(); }
+ constexpr explicit operator InnerType const &() const { return get(); }
- constexpr InnerType const & get() const { return m_value; }
+ constexpr InnerType const &get() const { return m_value; }
-private:
+ private:
InnerType const m_value;
};
-}
+} // namespace wanda
#endif \ No newline at end of file
diff --git a/src/variant.cpp b/src/variant.cpp
deleted file mode 100644
index 54e484e..0000000
--- a/src/variant.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "variant.hpp"
-
-namespace wanda {
-
-variant::variant(GVariant * value) : m_value{value} { }
-
-variant::~variant() {
- if(m_value) {
- g_variant_unref(m_value);
- }
-}
-
-bool variant::is_of_type(GVariantType const * const type) const {
- return g_variant_is_of_type(m_value, type);
-}
-
-} \ No newline at end of file
diff --git a/src/variant.hpp b/src/variant.hpp
deleted file mode 100644
index 8a5fb03..0000000
--- a/src/variant.hpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef WANDA_VARIANT_HPP
-#define WANDA_VARIANT_HPP
-
-#include <gio/gio.h>
-
-#include <optional>
-#include <string>
-#include <type_traits>
-
-namespace wanda {
-
-struct variant {
-
- explicit variant(GVariant * variant);
-
- ~variant();
-
- template<typename Type> std::optional<Type> get() const {
- if(!m_value) {
- return std::nullopt;
- }
-
- if constexpr(std::is_same_v<Type, bool>) {
- if(is_of_type(G_VARIANT_TYPE_BOOLEAN)) {
- return static_cast<bool>(g_variant_get_boolean(m_value));
- }
- } else if constexpr(std::is_same_v<Type, std::string>) {
- if(is_of_type(G_VARIANT_TYPE_STRING)) {
- auto length = gsize{};
- auto value = g_variant_get_string(m_value, &length);
- return std::string(value, static_cast<std::size_t>(length));
- }
- }
-
- return std::nullopt;
- }
-
-
-private:
- bool is_of_type(GVariantType const * const type) const;
-
- GVariant * const m_value;
-};
-
-}
-
-#endif \ No newline at end of file