swift
valuecache.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2015 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #ifndef SWIFT_MISC_VALUECACHE_H
7 #define SWIFT_MISC_VALUECACHE_H
8 
9 #include <cstddef>
10 #include <memory>
11 #include <stdexcept>
12 #include <tuple>
13 #include <utility>
14 
15 #include <QChar>
16 #include <QDBusArgument>
17 #include <QDateTime>
18 #include <QFile>
19 #include <QJsonObject>
20 #include <QMap>
21 #include <QMetaType>
22 #include <QMutex>
23 #include <QObject>
24 #include <QSet>
25 #include <QSharedPointer>
26 #include <QString>
27 #include <QStringList>
28 #include <QThread>
29 #include <QVariant>
30 #include <QtGlobal>
31 
32 #include "misc/dictionary.h"
33 #include "misc/identifier.h"
34 #include "misc/metaclass.h"
37 #include "misc/mixin/mixindbus.h"
39 #include "misc/propertyindexref.h"
40 #include "misc/range.h"
41 #include "misc/slot.h"
42 #include "misc/statusmessagelist.h"
43 #include "misc/swiftmiscexport.h"
44 #include "misc/valuecacheprivate.h"
45 #include "misc/variantmap.h"
46 
47 namespace swift::misc
48 {
49  class CLogCategoryList;
50 
56  SWIFT_MISC_EXPORT void setMockCacheRootDirectory(const QString &path);
57 
62  public CDictionary<QString, std::pair<CVariant, qint64>, QMap>,
63  public mixin::MetaType<CValueCachePacket>,
64  public mixin::DBusByMetaClass<CValueCachePacket>,
65  public mixin::DataStreamByMetaClass<CValueCachePacket>,
66  public mixin::EqualsByMetaClass<CValueCachePacket>
67  {
68  public:
71 
72 
74 
76  CValueCachePacket(bool saved = false, bool valuesChanged = true)
77  : m_saved(saved), m_valuesChanged(valuesChanged)
78  {}
79 
81  CValueCachePacket(const CVariantMap &values, qint64 timestamp, bool saved = false, bool valuesChanged = true);
82 
84  bool valuesChanged() const { return m_valuesChanged; }
85 
88  bool isSaved() const { return m_saved; }
89  void setSaved(bool saved = true) { m_saved = saved; }
91 
93  void insert(const QString &key, const CVariant &value, qint64 timestamp);
94 
96  void insert(const CVariantMap &values, qint64 timestamp);
97 
99  void insert(const CValueCachePacket &other) { CDictionary::insert(other); }
100 
103 
106 
108  QString toTimestampMapString(const QStringList &keys) const;
109 
112 
114  CValueCachePacket takeByKey(const QString &key);
115 
117  static void registerMetadata();
118 
120  struct const_iterator : public CDictionary::const_iterator
121  {
122  using value_type = CVariant;
123  using pointer = const value_type *;
124  using reference = const value_type &;
125  const_iterator(CDictionary::const_iterator base) : CDictionary::const_iterator(base) {}
126  reference value() const { return CDictionary::const_iterator::value().first; }
127  reference operator*() const { return value(); }
128  pointer operator->() const { return &value(); }
129  qint64 timestamp() const { return CDictionary::const_iterator::value().second; }
130  };
131 
134  const_iterator cbegin() const { return CDictionary::cbegin(); }
135  const_iterator cend() const { return CDictionary::cend(); }
136  const_iterator begin() const { return CDictionary::cbegin(); }
137  const_iterator end() const { return CDictionary::cend(); }
139 
140  private:
141  bool m_saved = false;
142  bool m_valuesChanged = true;
143 
146  SWIFT_METAMEMBER(saved),
147  SWIFT_METAMEMBER(valuesChanged));
148  };
149 
153  class SWIFT_MISC_EXPORT CValueCache : public QObject
154  {
155  Q_OBJECT
156 
157  public:
158  class BatchGuard;
159 
161  static const QStringList &getLogCategories();
162 
164  explicit CValueCache(int fileSplitDepth, QObject *parent = nullptr);
165 
169  swift::misc::CVariantMap getAllValues(const QString &keyPrefix = {}) const;
170 
173  swift::misc::CVariantMap getAllValues(const QStringList &keys) const;
174 
177  swift::misc::CValueCachePacket getAllValuesWithTimestamps(const QString &keyPrefix = {}) const;
178 
181  QStringList getAllUnsavedKeys(const QString &keyPrefix = {}) const;
182 
187 
191  QJsonObject saveToJson(const QString &keyPrefix = {}) const;
192 
197  void loadFromJson(const QJsonObject &json);
198 
201  CStatusMessageList loadFromJsonNoThrow(const QJsonObject &json, const CLogCategoryList &categories,
202  const QString &prefix);
203 
207  CStatusMessage saveToFiles(const QString &directory, const QString &keyPrefix = {});
208 
211  CStatusMessage saveToFiles(const QString &directory, const QStringList &keys);
212 
216  CStatusMessage loadFromFiles(const QString &directory);
217 
221  QString filenameForKey(const QString &key) const;
222 
226  QStringList enumerateFiles(const QString &directory) const;
227 
230  void clearAllValues(const QString &keyPrefix = {});
231 
233  QString getHumanReadableName(const QString &key) const;
234 
236  QString getHumanReadableWithKey(const QString &key) const;
237 
239  void setHumanReadableName(const QString &key, const QString &name);
240 
248  BatchGuard batchChanges(QObject *owner);
249 
250  public slots:
256  const swift::misc::CIdentifier &originator);
257 
258  signals:
264 
268 
269  protected:
272  auto elementsStartingWith(const QString &keyPrefix)
273  {
274  return makeRange(m_elements.lowerBound(keyPrefix),
275  m_elements.lowerBound(keyPrefix + QChar(QChar::LastValidCodePoint)));
276  }
277  auto elementsStartingWith(const QString &keyPrefix) const
278  {
279  return makeRange(m_elements.lowerBound(keyPrefix),
280  m_elements.lowerBound(keyPrefix + QChar(QChar::LastValidCodePoint)));
281  }
283 
286  CStatusMessage saveToFiles(const QString &directory, const CVariantMap &values,
287  const QString &keysMessage = {}) const;
288 
291  CStatusMessage loadFromFiles(const QString &directory, const QSet<QString> &keys, const CVariantMap &current,
292  CValueCachePacket &o_values, const QString &keysMessage = {},
293  bool keysOnly = false) const;
294 
297  void markAllAsSaved(const QString &keyPrefix);
298 
301  void markAllAsSaved(const QStringList &keys);
302 
304  mutable QRecursiveMutex m_mutex;
305 
308  CVariant getValueSync(const QString &key) { return std::get<0>(getValue(key)); }
309 
312  qint64 getTimestampSync(const QString &key) { return std::get<1>(getValue(key)); }
313 
315  static const QString &getCacheRootDirectory();
316 
317  private:
318  friend class private_ns::CValuePage;
319  struct Element;
320 
321  using ElementPtr = QSharedPointer<Element>; // QMap doesn't support move-only types
322 
323  QMap<QString, ElementPtr> m_elements;
324  QMap<QString, QString> m_humanReadable;
325  const int m_fileSplitDepth = 1;
326 
327  Element &getElement(const QString &key);
328  Element &getElement(const QString &key, QMap<QString, ElementPtr>::const_iterator pos);
329  std::tuple<CVariant, qint64, bool> getValue(const QString &key);
330  void backupFile(QFile &file) const;
331 
332  virtual void connectPage(private_ns::CValuePage *page);
333 
334  // only used by CValuePage::createElement
335  QSet<QString> m_warnedKeys;
336  QMutex m_warnedKeysMutex;
337 
338  signals:
340  void valuesChanged(const swift::misc::CValueCachePacket &values, QObject *changedBy);
341 
342  protected slots:
344  void changeValues(const swift::misc::CValueCachePacket &values);
345  };
346 
351  template <typename T>
352  class CCached
353  {
354  public:
360  template <typename U>
361  CCached(CValueCache *cache, const QString &key, const QString &name, U *owner)
362  : CCached(cache, key, name, nullptr, T {}, owner)
363  {}
364 
372  template <typename U, typename F>
373  CCached(CValueCache *cache, const QString &key, const QString &name, F validator, const T &defaultValue,
374  U *owner)
375  : m_page(&private_ns::CValuePage::getPageFor(owner, cache)),
376  m_element(
377  &m_page->createElement(key, name, qMetaTypeId<T>(), wrap(validator), CVariant::from(defaultValue)))
378  {
379  if (isInitialized()) { cache->setHumanReadableName(getKey(), name); }
380  }
381 
383  template <typename F>
384  void setNotifySlot(F slot)
385  {
386  if (!isInitialized())
387  {
388  onOwnerNameChanged([this, slot] { setNotifySlot(slot); });
389  return;
390  }
391  using U = typename private_ns::TClassOfPointerToMember<F>::type;
392  Q_ASSERT_X(m_page->parent()->metaObject()->inherits(&U::staticMetaObject), Q_FUNC_INFO,
393  "Slot is member function of wrong class");
394  m_page->setNotifySlot(
395  *m_element,
396  { [slot](QObject *obj) { private_ns::invokeSlot(slot, static_cast<U *>(obj)); }, makeId(slot) });
397  }
398 
400  const T &getThreadLocal() const
401  {
402  static const T empty {};
403  return *(isValid() ? static_cast<const T *>(getVariant().data()) : &empty);
404  }
405 
408  T get() const { return isValid() ? getVariantCopy().template value<T>() : T {}; }
409 
411  CStatusMessage set(const T &value, qint64 timestamp = 0)
412  {
413  return m_page->setValue(*m_element, CVariant::from(value), timestamp);
414  }
415 
417  CStatusMessage setAndSave(const T &value, qint64 timestamp = 0)
418  {
419  return m_page->setValue(*m_element, CVariant::from(value), timestamp, true);
420  }
421 
423  CStatusMessage save() { return m_page->setValue(*m_element, {}, 0, true); }
424 
426  CStatusMessage setProperty(CPropertyIndexRef index, const CVariant &value, qint64 timestamp = 0)
427  {
428  auto v = get();
429  v.setPropertyByIndex(index, value);
430  return set(v, timestamp);
431  }
432 
434  CStatusMessage setAndSaveProperty(CPropertyIndexRef index, const CVariant &value, qint64 timestamp = 0)
435  {
436  auto v = get();
437  v.setPropertyByIndex(index, value);
438  return setAndSave(v, timestamp);
439  }
440 
442  bool isOwnerThread() const { return QThread::currentThread() == m_page->thread(); }
443 
445  const QString &getKey() const { return m_page->getKey(*m_element); }
446 
449  QDateTime getTimestamp() const { return QDateTime::fromMSecsSinceEpoch(m_page->getTimestamp(*m_element)); }
450 
453  qint64 getTimestampMsSinceEpoch() const { return this->getTimestamp().toMSecsSinceEpoch(); }
454 
456  qint64 lastUpdatedAge() const { return QDateTime::currentMSecsSinceEpoch() - this->getTimestampMsSinceEpoch(); }
457 
459  bool isSaved() const { return m_page->isSaved(*m_element); }
460 
462  bool isSaving() const { return m_page->isSaving(*m_element); }
463 
465  bool isInitialized() const { return m_page->isInitialized(*m_element); }
466 
468  CCached(const CCached &) = delete;
469 
471  CCached &operator=(const CCached &) = delete;
472 
473  private:
474  template <typename F>
475  static private_ns::CValuePage::Validator wrap(F func)
476  {
477  return [func](const CVariant &value, QString &reason) -> bool { return func(value.to<T>(), reason); };
478  }
479  static private_ns::CValuePage::Validator wrap(std::nullptr_t) { return {}; }
480 
481  template <typename F>
482  static auto makeId(F &&)
483  {
484  return nullptr;
485  }
486  template <typename U, typename M>
487  static auto makeId(M U::*slot)
488  {
489  return static_cast<std::tuple_element_t<1, private_ns::CValuePage::NotifySlot>>(slot);
490  }
491 
492  const QVariant &getVariant() const { return m_page->getValue(*m_element).getQVariant(); }
493  QVariant getVariantCopy() const { return m_page->getValueCopy(*m_element).getQVariant(); }
494  bool isValid() const { return m_page->isValid(*m_element, qMetaTypeId<T>()); }
495 
496  protected:
498  void onOwnerNameChanged(const std::function<void()> &function)
499  {
500  connectOnce(m_page->parent(), &QObject::objectNameChanged, [function](const QString &) { function(); });
501  }
502 
503  private_ns::CValuePage *m_page = (throw std::logic_error("Uninitialized member"), nullptr);
504  private_ns::CValuePage::Element *m_element =
505  (throw std::logic_error("Uninitialized member"), nullptr);
506  };
507 
511  class SWIFT_MISC_EXPORT CValueCache::BatchGuard
512  {
513  public:
516 
518  BatchGuard(const BatchGuard &) = delete;
519 
521  BatchGuard &operator=(const BatchGuard &) = delete;
522 
524  BatchGuard(BatchGuard &&other) noexcept : m_page(other.m_page) { other.m_page = nullptr; }
525 
527  BatchGuard &operator=(BatchGuard &&other) noexcept
528  {
529  std::swap(m_page, other.m_page);
530  return *this;
531  }
532 
533  private:
534  friend class CValueCache;
535  BatchGuard(private_ns::CValuePage &page) : m_page(&page) {}
536  private_ns::CValuePage *m_page;
537  };
538 
539 } // namespace swift::misc
540 
541 Q_DECLARE_METATYPE(swift::misc::CValueCachePacket)
542 
543 #endif // SWIFT_MISC_VALUECACHE_H
Provides access to one of the values stored in a CValueCache.
Definition: valuecache.h:353
CStatusMessage setProperty(CPropertyIndexRef index, const CVariant &value, qint64 timestamp=0)
Write a property of the value. Must be called from the thread in which the owner lives.
Definition: valuecache.h:426
bool isSaving() const
Return true if this value is currently saving.
Definition: valuecache.h:462
bool isInitialized() const
Can be false if key contains OwnerName% and owner's objectName was empty.
Definition: valuecache.h:465
CStatusMessage save()
Save using the currently set value. Must be called from the thread in which the owner lives.
Definition: valuecache.h:423
CCached(const CCached &)=delete
Deleted copy constructor.
qint64 getTimestampMsSinceEpoch() const
Return the time when this value was updated.
Definition: valuecache.h:453
CStatusMessage setAndSave(const T &value, qint64 timestamp=0)
Write and save in the same step. Must be called from the thread in which the owner lives.
Definition: valuecache.h:417
CCached(CValueCache *cache, const QString &key, const QString &name, F validator, const T &defaultValue, U *owner)
Constructor.
Definition: valuecache.h:373
CStatusMessage set(const T &value, qint64 timestamp=0)
Write a new value. Must be called from the thread in which the owner lives.
Definition: valuecache.h:411
CCached(CValueCache *cache, const QString &key, const QString &name, U *owner)
Constructor.
Definition: valuecache.h:361
CCached & operator=(const CCached &)=delete
Deleted copy assignment operator.
const QString & getKey() const
Get the key string of this value.
Definition: valuecache.h:445
void setNotifySlot(F slot)
Set a callback to be called when the value is changed by another source.
Definition: valuecache.h:384
bool isOwnerThread() const
Is current thread the owner thread, so CCached::set is safe.
Definition: valuecache.h:442
qint64 lastUpdatedAge() const
How old is that cache (ms)?
Definition: valuecache.h:456
QDateTime getTimestamp() const
Return the time when this value was updated.
Definition: valuecache.h:449
bool isSaved() const
Return true if this value was already saved.
Definition: valuecache.h:459
const T & getThreadLocal() const
Read the current value.
Definition: valuecache.h:400
T get() const
Get a copy of the current value.
Definition: valuecache.h:408
CStatusMessage setAndSaveProperty(CPropertyIndexRef index, const CVariant &value, qint64 timestamp=0)
Write a property and save in the same step. Must be called from the thread in which the owner lives.
Definition: valuecache.h:434
Associative container with value semantics, chooses a sensible default implementation container type.
Definition: dictionary.h:83
std::pair< CVariant, qint64 > value_type
STL compatibility.
Definition: dictionary.h:100
const_iterator cbegin() const
Returns const iterator at the beginning of the dictionary.
Definition: dictionary.h:302
iterator insert(const Key &key, const Value &value)
Insert new item with key and value.
Definition: dictionary.h:374
std::pair< CVariant, qint64 > & reference
STL compatibility.
Definition: dictionary.h:103
const_iterator cend() const
Returns const iterator at the end of the dictionary.
Definition: dictionary.h:311
Impl< Key, Value >::const_iterator const_iterator
STL compatibility.
Definition: dictionary.h:115
Value object encapsulating information identifying a component of a modular distributed swift process...
Definition: identifier.h:29
A sequence of log categories.
Non-owning reference to a CPropertyIndex with a subset of its features.
Streamable status message, e.g.
Status messages, e.g. from Core -> GUI.
Manages a map of { QString, CVariant } pairs, which can be distributed among multiple processes.
Definition: valuecache.h:154
void changeValuesFromRemote(const swift::misc::CValueCachePacket &values, const swift::misc::CIdentifier &originator)
Notify this cache that values have been changed by one of the duplicate caches in the multi-process e...
auto elementsStartingWith(const QString &keyPrefix) const
Returns a range referring to all elements which start with the given prefix.
Definition: valuecache.h:277
static const QStringList & getLogCategories()
Log categories.
swift::misc::CVariantMap getAllValues(const QString &keyPrefix={}) const
Return map containing all values in the cache. If prefix is provided then only those values whose key...
BatchGuard & operator=(const BatchGuard &)=delete
Deleted copy assignment operator. Class is move-only.
QString getHumanReadableName(const QString &key) const
Return the human readable name of the given key, or the raw key string if there is none.
BatchGuard(BatchGuard &&other) noexcept
Move constructor.
Definition: valuecache.h:524
QStringList enumerateFiles(const QString &directory) const
List the Json files which are (or would be) used to save the current values. The files may or may not...
QString filenameForKey(const QString &key) const
Return the (relative) filename that may is (or would be) used to save the value with the given key....
CStatusMessage loadFromFiles(const QString &directory, const QSet< QString > &keys, const CVariantMap &current, CValueCachePacket &o_values, const QString &keysMessage={}, bool keysOnly=false) const
Load from Json files in a given directory any values which differ from the current ones,...
void markAllAsSaved(const QStringList &keys)
Mark all values with given keys as having been saved.
BatchGuard batchChanges(QObject *owner)
Begins a batch of changes to be made through CCached instances owned by owner.
CVariant getValueSync(const QString &key)
Synchronously return a current value.
Definition: valuecache.h:308
CStatusMessage saveToFiles(const QString &directory, const QStringList &keys)
Save values to Json files in a given directory.
CValueCache(int fileSplitDepth, QObject *parent=nullptr)
Constructor.
QRecursiveMutex m_mutex
Mutex protecting operations which are critical on m_elements.
Definition: valuecache.h:304
void clearAllValues(const QString &keyPrefix={})
Clear all values from the cache.
CStatusMessage saveToFiles(const QString &directory, const CVariantMap &values, const QString &keysMessage={}) const
Save specific values to Json files in a given directory.
swift::misc::CValueCachePacket getAllValuesWithTimestamps(const QString &keyPrefix={}) const
Return map containing all values in the cache, and timestamps when they were modified.
QJsonObject saveToJson(const QString &keyPrefix={}) const
Save values in Json format. If prefix is provided then only those values whose keys start with that p...
void markAllAsSaved(const QString &keyPrefix)
Mark all values with keys that start with the given prefix as having been saved.
BatchGuard(const BatchGuard &)=delete
Deleted copy constructor. Class is move-only.
void insertValues(const swift::misc::CValueCachePacket &values)
Add some values to the cache. Values already in the cache will remain in the cache unless they are ov...
BatchGuard & operator=(BatchGuard &&other) noexcept
Move assignment operator.
Definition: valuecache.h:527
QString getHumanReadableWithKey(const QString &key) const
Return the human readable name of the given key, with the raw key string appended.
void valuesSaveRequested(const swift::misc::CValueCachePacket &values)
Emitted when this cache has ratified a change which included a request to save (i....
CStatusMessage loadFromFiles(const QString &directory)
Load all values from Json files in a given directory. Values already in the cache will remain in the ...
~BatchGuard()
Destructor. Applies deferred changes.
void valuesChangedByLocal(const swift::misc::CValueCachePacket &values)
Emitted when values in the cache are changed by an object in this very process. The interprocess comm...
swift::misc::CVariantMap getAllValues(const QStringList &keys) const
Return map containing all given values in the cache.
void loadFromJson(const QJsonObject &json)
Load all values in Json format. Values already in the cache will remain in the cache unless they are ...
QStringList getAllUnsavedKeys(const QString &keyPrefix={}) const
Return keys of all values which have been changed but not saved.
CStatusMessageList loadFromJsonNoThrow(const QJsonObject &json, const CLogCategoryList &categories, const QString &prefix)
Call loadFromJson, catch any CJsonException that are thrown and return them as CStatusMessage.
qint64 getTimestampSync(const QString &key)
Synchronously return a current timestamp.
Definition: valuecache.h:312
CStatusMessage saveToFiles(const QString &directory, const QString &keyPrefix={})
Save values to Json files in a given directory. If prefix is provided then only those values whose ke...
auto elementsStartingWith(const QString &keyPrefix)
Returns a range referring to all elements which start with the given prefix.
Definition: valuecache.h:272
Value class used for signalling changed values in the cache.
Definition: valuecache.h:67
const_iterator begin() const
Iterators.
Definition: valuecache.h:136
QMap< QString, qint64 > toTimestampMap() const
Discard values and return as map of timestamps.
void setTimestamps(const QMap< QString, qint64 > &)
Change the timestamps of values.
void setSaved(bool saved=true)
Values are to be saved.
Definition: valuecache.h:89
void insert(const CVariantMap &values, qint64 timestamp)
Insert a CVariantMap with a timestamp.
QString toTimestampMapString(const QStringList &keys) const
Return map of timestamps converted to string.
void insert(const QString &key, const CVariant &value, qint64 timestamp)
Insert a key/value pair with a timestamp.
void insert(const CValueCachePacket &other)
Insert values from another packet.
Definition: valuecache.h:99
CValueCachePacket takeByKey(const QString &key)
Remove value matching the given key, and return it in a separate packet.
const_iterator cend() const
Iterators.
Definition: valuecache.h:135
const_iterator end() const
Iterators.
Definition: valuecache.h:137
static void registerMetadata()
Register metadata.
bool valuesChanged() const
Values have been changed.
Definition: valuecache.h:84
CValueCachePacket(const CVariantMap &values, qint64 timestamp, bool saved=false, bool valuesChanged=true)
Construct from CVariantMap and a timestamp.
bool isSaved() const
Values are to be saved.
Definition: valuecache.h:88
CVariantMap toVariantMap() const
Discard timestamps and return as variant map.
const_iterator cbegin() const
Iterators.
Definition: valuecache.h:134
Wrapper around QVariant which provides transparent access to CValueObject methods of the contained ob...
Definition: variant.h:66
T to() const
Synonym for value().
Definition: variant.h:176
static CVariant from(T &&value)
Synonym for fromValue().
Definition: variant.h:147
Map of { QString, CVariant } pairs.
Definition: variantmap.h:35
CRTP class template from which a derived class can inherit common methods dealing with marshalling in...
Definition: mixindbus.h:71
CRTP class template to generate QDataStream marshalling methods using CMetaClass.
CRTP class template from which a derived class can inherit operator== implemented by metaclass.
Definition: mixincompare.h:46
CRTP class template from which a derived class can inherit common methods dealing with the metatype o...
Definition: mixinmetatype.h:29
#define SWIFT_METAMEMBER(MEMBER,...)
Macro to define an element within a metaclass.
Definition: metaclass.h:73
#define SWIFT_METACLASS(CLASS,...)
Macro to define a nested metaclass that describes the attributes of its enclosing class.
Definition: metaclass.h:53
#define SWIFT_MISC_DECLARE_USING_MIXIN_DATASTREAM(DERIVED)
When a derived class and a base class both inherit from mixin::DataStreamByMetaClass,...
#define SWIFT_MISC_DECLARE_USING_MIXIN_DBUS(DERIVED,...)
When a derived class and a base class both inherit from mixin::DBusByTuple, the derived class uses th...
Definition: mixindbus.h:182
Free functions in swift::misc.
QMetaObject::Connection connectOnce(T *sender, F signal, U *receiver, G &&slot, Qt::ConnectionType type=Qt::AutoConnection)
Wrapper around QObject::connect which disconnects after the signal has been emitted once.
Definition: slot.h:27
auto makeRange(I begin, I2 end) -> CRange< I >
Returns a CRange constructed from begin and end iterators of deduced types.
Definition: range.h:316
SWIFT_MISC_EXPORT void setMockCacheRootDirectory(const QString &path)
Overwrite the default root directory for cache and settings, for testing purposes.
void swap(Optional< T > &a, Optional< T > &b) noexcept(std::is_nothrow_swappable_v< T >)
Efficient swap for two Optional objects.
Definition: optional.h:132
#define SWIFT_MISC_EXPORT
Export a class or function from the library.