19#include <ossia/detail/algorithms.hpp>
34inline constexpr quint32 pluginCacheMagic = 0x53435043;
53QByteArray serializePluginCache(quint32 version,
const std::vector<T>& vec)
57 QDataStream str{&res, QIODevice::WriteOnly};
58 str << pluginCacheMagic << version << (quint32)vec.size();
59 for(
const auto& elt : vec)
63 QDataStream es{&blob, QIODevice::WriteOnly};
75std::optional<std::vector<T>>
76deserializePluginCache(quint32 version,
const QByteArray& data)
81 QDataStream str{data};
82 quint32 magic{}, ver{}, count{};
83 str >> magic >> ver >> count;
84 if(str.status() != QDataStream::Ok || magic != pluginCacheMagic || ver != version)
89 if(count > (quint32)data.size() / 4)
94 for(quint32 i = 0; i < count; i++)
98 if(str.status() != QDataStream::Ok)
101 QDataStream es{blob};
106 if(es.status() != QDataStream::Ok || !es.atEnd())
108 res.push_back(std::move(elt));
121std::vector<T> loadPluginCache(
122 quint32 version,
const QString& key,
const QString& legacyKey)
126 std::optional<std::vector<T>> versioned;
127 if(
const auto val = set.value(key); val.canConvert<QByteArray>())
128 versioned = deserializePluginCache<T>(version, val.toByteArray());
130 std::vector<T> legacy;
131 if(!legacyKey.isEmpty())
135 if(
const auto val = set.value(legacyKey); val.canConvert<std::vector<T>>())
136 legacy = val.value<std::vector<T>>();
141 set.remove(legacyKey);
144 return versioned ? *std::move(versioned) : legacy;
148void savePluginCache(quint32 version,
const QString& key,
const std::vector<T>& vec)
150 QSettings{}.setValue(key, serializePluginCache(version, vec));
155template <
typename T,
typename KeyFn>
156void deduplicate(std::vector<T>& vec, KeyFn&& key_of)
165 std::is_same_v<std::invoke_result_t<KeyFn&, const T&>, QString>,
166 "the key function must return QString: a deduced QStringBuilder return "
167 "type dangles past the end of the return statement");
169 ossia::remove_erase_if(vec, [&](
const T& elt) {
170 const QString k = key_of(elt);
181template <
typename T,
typename PathFn,
typename Val
idFn>
182void dropShadowedInvalidEntries(std::vector<T>& vec, PathFn&& path_of, ValidFn&& is_valid)
185 std::is_same_v<std::invoke_result_t<PathFn&, const T&>, QString>,
186 "the path function must return QString: see deduplicate()");
187 QSet<QString> valid_paths;
188 for(
const auto& elt : vec)
190 valid_paths.insert(path_of(elt));
192 ossia::remove_erase_if(vec, [&](
const T& elt) {
193 return !is_valid(elt) && valid_paths.contains(path_of(elt));
199template <
typename T,
typename KeyFn,
typename PathFn,
typename Val
idFn>
200void sanitizePluginCache(
201 std::vector<T>& vec, KeyFn&& key_of, PathFn&& path_of, ValidFn&& is_valid)
203 ossia::remove_erase_if(
204 vec, [&](
const T& elt) {
return path_of(elt).isEmpty(); });
205 dropShadowedInvalidEntries(vec, path_of, is_valid);
206 deduplicate(vec, key_of);