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
|
** 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
|
** 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) {
|
for (const auto& prop: Mu::Config::properties) {
|
||||||
|
|
||||||
// don't expose internal values & values that may change during
|
// don't expose internal/system values
|
||||||
// runtime
|
if (any_of(prop.flags & (MuConfig::Flags::Internal|MuConfig::Flags::System)))
|
||||||
if (any_of(prop.flags &
|
|
||||||
(MuConfig::Flags::Internal | MuConfig::Flags::Runtime)))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto str{conf.as_display_string(prop)};
|
const auto str{conf.as_display_string(prop)};
|
||||||
if (str.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const auto name{make_symbol(prop.name)};
|
const auto name{make_symbol(prop.name)};
|
||||||
const auto val = std::invoke([&]() {
|
const auto val = std::invoke([&]() {
|
||||||
switch (prop.type) {
|
switch (prop.type) {
|
||||||
|
|||||||
@ -96,9 +96,19 @@ namespace Mu::Scm {
|
|||||||
// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2593r0.html
|
// 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> struct always_false : std::false_type {};
|
||||||
|
|
||||||
template<typename T> constexpr bool is_char_array_v =
|
template <typename T>
|
||||||
std::is_array_v<T> &&
|
concept IsCharArray =
|
||||||
std::is_same_v<std::remove_extent_t<T>, char>;
|
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>
|
template<typename T>
|
||||||
SCM make_symbol(const T& val){
|
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> ||
|
if constexpr (std::is_same_v<Type, std::string> ||
|
||||||
std::is_same_v<Type, std::string_view>)
|
std::is_same_v<Type, std::string_view>)
|
||||||
return scm_from_utf8_symboln(val.data(), val.size());
|
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);
|
return scm_from_utf8_symbol(val);
|
||||||
else {
|
else {
|
||||||
static_assert(always_false<Type>::value, "source type not supported");
|
static_assert(always_false<Type>::value, "source type not supported");
|
||||||
@ -184,15 +194,17 @@ namespace Mu::Scm {
|
|||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T from_scm(SCM ARG, const char *func, int pos) {
|
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)
|
if (!pred)
|
||||||
throw ScmError{ScmError::Id::WrongType, func, pos, ARG, expected};
|
throw ScmError{ScmError::Id::WrongType, func, pos, ARG, expected};
|
||||||
};
|
};
|
||||||
// note: use the C predicates (scm_is_string etc.); the Scheme
|
// note: use the C predicates (scm_is_string etc.); the Scheme
|
||||||
// predicates (scm_string_p etc.) return an SCM boolean, which
|
// predicates (scm_string_p etc.) return an SCM boolean, which
|
||||||
// is truthy as a C++ bool even when it is #f.
|
// is truthy as a C++ bool even when it is #f.
|
||||||
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>) {
|
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");
|
ensure(scm_is_string(ARG), ARG, "string");
|
||||||
size_t len{};
|
size_t len{};
|
||||||
auto str{scm_to_utf8_stringn(ARG, &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>) {
|
} else if constexpr (std::is_same_v<Type, bool>) {
|
||||||
ensure(scm_is_bool(ARG), ARG, "bool");
|
ensure(scm_is_bool(ARG), ARG, "bool");
|
||||||
return scm_to_bool(ARG);
|
return scm_to_bool(ARG);
|
||||||
} else if constexpr (std::is_same_v<Type, int>) {
|
} else if constexpr (IsSignedIntegral<Type>) {
|
||||||
ensure(scm_is_signed_integer(ARG, std::numeric_limits<int>::min(),
|
ensure(scm_is_signed_integer(ARG, std::numeric_limits<Type>::min(),
|
||||||
std::numeric_limits<int>::max()),
|
std::numeric_limits<Type>::max()),
|
||||||
ARG, "integer");
|
ARG, "integer");
|
||||||
return scm_to_int(ARG);
|
return scm_to_int(ARG);
|
||||||
} else if constexpr (std::is_same_v<Type, uint>) {
|
} else if constexpr (IsUnsignedIntegral<Type>) {
|
||||||
ensure(scm_is_unsigned_integer(ARG, std::numeric_limits<uint>::min(),
|
ensure(scm_is_unsigned_integer(ARG, std::numeric_limits<Type>::min(),
|
||||||
std::numeric_limits<uint>::max()),
|
std::numeric_limits<Type>::max()),
|
||||||
ARG, "unsigned");
|
ARG, "unsigned");
|
||||||
return scm_to_uint(ARG);
|
return scm_to_uint(ARG);
|
||||||
} else if constexpr (std::is_same_v<Type, SCM>) {
|
} else {
|
||||||
return ARG;
|
|
||||||
} else {
|
|
||||||
static_assert(always_false<Type>::value, "target type not supported");
|
static_assert(always_false<Type>::value, "target type not supported");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like from_SCM, but if ARG is boolean false, return default value.
|
* Like from_SCM, but if ARG is boolean false, return default value.
|
||||||
*
|
*
|
||||||
@ -245,11 +257,11 @@ namespace Mu::Scm {
|
|||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
SCM to_scm(const T& val) {
|
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> ||
|
if constexpr (std::is_same_v<Type, std::string> ||
|
||||||
std::is_same_v<Type, std::string_view>)
|
std::is_same_v<Type, std::string_view>)
|
||||||
return scm_from_utf8_stringn(val.data(), val.size());
|
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);
|
return scm_from_utf8_string(val);
|
||||||
else if constexpr (std::is_same_v<Type, std::vector<std::string>>) {
|
else if constexpr (std::is_same_v<Type, std::vector<std::string>>) {
|
||||||
SCM lst{SCM_EOL};
|
SCM lst{SCM_EOL};
|
||||||
|
|||||||
@ -478,6 +478,11 @@ Example:
|
|||||||
(root-maildir . "/home/user/Maildir") (schema-version . 500))
|
(root-maildir . "/home/user/Maildir") (schema-version . 500))
|
||||||
@end lisp
|
@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.
|
More fields may be added.
|
||||||
|
|
||||||
@deffn {Scheme Procedure} root-maildir
|
@deffn {Scheme Procedure} root-maildir
|
||||||
|
|||||||
Reference in New Issue
Block a user