scm: improve store->alist
Include all non-internal properties in the output alist. Clean up some of the type-conversion (using concepts) Fix conversion to bool
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2025 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
** Copyright (C) 2025-2026 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the GNU General Public License as published by the
|
||||
@ -50,16 +50,11 @@ subr_cc_store_alist(SCM store_scm) try {
|
||||
|
||||
for (const auto& prop: Mu::Config::properties) {
|
||||
|
||||
// don't expose internal values & values that may change during
|
||||
// runtime
|
||||
if (any_of(prop.flags &
|
||||
(MuConfig::Flags::Internal | MuConfig::Flags::Runtime)))
|
||||
// don't expose internal/system values
|
||||
if (any_of(prop.flags & (MuConfig::Flags::Internal|MuConfig::Flags::System)))
|
||||
continue;
|
||||
|
||||
const auto str{conf.as_display_string(prop)};
|
||||
if (str.empty())
|
||||
continue;
|
||||
|
||||
const auto name{make_symbol(prop.name)};
|
||||
const auto val = std::invoke([&]() {
|
||||
switch (prop.type) {
|
||||
|
||||
@ -96,9 +96,19 @@ namespace Mu::Scm {
|
||||
// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2593r0.html
|
||||
template<typename T> struct always_false : std::false_type {};
|
||||
|
||||
template<typename T> constexpr bool is_char_array_v =
|
||||
std::is_array_v<T> &&
|
||||
std::is_same_v<std::remove_extent_t<T>, char>;
|
||||
template <typename T>
|
||||
concept IsCharArray =
|
||||
std::is_array_v<T> && std::is_same_v<std::remove_extent_t<T>, char>;
|
||||
/**< Is this is a char-array? */
|
||||
|
||||
template <typename T>
|
||||
concept IsSignedIntegral = std::is_integral_v<T> && std::is_signed_v<T>;
|
||||
/**< Is this a signed integral type? */
|
||||
|
||||
template <typename T>
|
||||
concept IsUnsignedIntegral =
|
||||
std::is_integral_v<T> && std::is_unsigned_v<T>;
|
||||
/**< Is this an unsigned integral type? */
|
||||
|
||||
|
||||
/**
|
||||
@ -158,11 +168,11 @@ namespace Mu::Scm {
|
||||
*/
|
||||
template<typename T>
|
||||
SCM make_symbol(const T& val){
|
||||
using Type = std::remove_const_t<T>; // *not* std::remove_const
|
||||
using Type = std::remove_cvref_t<T>;
|
||||
if constexpr (std::is_same_v<Type, std::string> ||
|
||||
std::is_same_v<Type, std::string_view>)
|
||||
return scm_from_utf8_symboln(val.data(), val.size());
|
||||
else if constexpr (is_char_array_v<Type>|| std::is_same_v<Type, const char*>)
|
||||
else if constexpr (IsCharArray<T> || std::is_same_v<Type, const char*>)
|
||||
return scm_from_utf8_symbol(val);
|
||||
else {
|
||||
static_assert(always_false<Type>::value, "source type not supported");
|
||||
@ -184,15 +194,17 @@ namespace Mu::Scm {
|
||||
*/
|
||||
template<typename T>
|
||||
T from_scm(SCM ARG, const char *func, int pos) {
|
||||
const auto ensure=[&](bool pred, SCM ARG, const char *expected) {
|
||||
const auto ensure = [&](bool pred, SCM ARG, const char *expected) {
|
||||
if (!pred)
|
||||
throw ScmError{ScmError::Id::WrongType, func, pos, ARG, expected};
|
||||
};
|
||||
// note: use the C predicates (scm_is_string etc.); the Scheme
|
||||
// predicates (scm_string_p etc.) return an SCM boolean, which
|
||||
// is truthy as a C++ bool even when it is #f.
|
||||
using Type = std::remove_const_t<T>; // *not* std::remove_const
|
||||
if constexpr (std::is_same_v<Type, std::string>) {
|
||||
using Type = std::remove_cvref_t<T>;
|
||||
if constexpr (std::is_same_v<Type, SCM>) {
|
||||
return ARG;
|
||||
} else if constexpr (std::is_same_v<Type, std::string>) {
|
||||
ensure(scm_is_string(ARG), ARG, "string");
|
||||
size_t len{};
|
||||
auto str{scm_to_utf8_stringn(ARG, &len)};
|
||||
@ -205,23 +217,23 @@ namespace Mu::Scm {
|
||||
} else if constexpr (std::is_same_v<Type, bool>) {
|
||||
ensure(scm_is_bool(ARG), ARG, "bool");
|
||||
return scm_to_bool(ARG);
|
||||
} else if constexpr (std::is_same_v<Type, int>) {
|
||||
ensure(scm_is_signed_integer(ARG, std::numeric_limits<int>::min(),
|
||||
std::numeric_limits<int>::max()),
|
||||
ARG, "integer");
|
||||
} else if constexpr (IsSignedIntegral<Type>) {
|
||||
ensure(scm_is_signed_integer(ARG, std::numeric_limits<Type>::min(),
|
||||
std::numeric_limits<Type>::max()),
|
||||
ARG, "integer");
|
||||
return scm_to_int(ARG);
|
||||
} else if constexpr (std::is_same_v<Type, uint>) {
|
||||
ensure(scm_is_unsigned_integer(ARG, std::numeric_limits<uint>::min(),
|
||||
std::numeric_limits<uint>::max()),
|
||||
ARG, "unsigned");
|
||||
} else if constexpr (IsUnsignedIntegral<Type>) {
|
||||
ensure(scm_is_unsigned_integer(ARG, std::numeric_limits<Type>::min(),
|
||||
std::numeric_limits<Type>::max()),
|
||||
ARG, "unsigned");
|
||||
return scm_to_uint(ARG);
|
||||
} else if constexpr (std::is_same_v<Type, SCM>) {
|
||||
return ARG;
|
||||
} else {
|
||||
} else {
|
||||
static_assert(always_false<Type>::value, "target type not supported");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Like from_SCM, but if ARG is boolean false, return default value.
|
||||
*
|
||||
@ -245,11 +257,11 @@ namespace Mu::Scm {
|
||||
*/
|
||||
template<typename T>
|
||||
SCM to_scm(const T& val) {
|
||||
using Type = std::remove_const_t<T>;
|
||||
using Type = std::remove_cvref_t<T>;
|
||||
if constexpr (std::is_same_v<Type, std::string> ||
|
||||
std::is_same_v<Type, std::string_view>)
|
||||
return scm_from_utf8_stringn(val.data(), val.size());
|
||||
else if constexpr (is_char_array_v<Type>|| std::is_same_v<Type, const char*>)
|
||||
else if constexpr (IsCharArray<Type>|| std::is_same_v<Type, const char*>)
|
||||
return scm_from_utf8_string(val);
|
||||
else if constexpr (std::is_same_v<Type, std::vector<std::string>>) {
|
||||
SCM lst{SCM_EOL};
|
||||
|
||||
@ -478,6 +478,11 @@ Example:
|
||||
(root-maildir . "/home/user/Maildir") (schema-version . 500))
|
||||
@end lisp
|
||||
|
||||
Some of the fields are constant for the lifetime of the store, while others such
|
||||
as the @code{last-change} may change between calls.
|
||||
|
||||
All date fields are encoded as Unix seconds-since-epoch.
|
||||
|
||||
More fields may be added.
|
||||
|
||||
@deffn {Scheme Procedure} root-maildir
|
||||
|
||||
Reference in New Issue
Block a user