File indexing completed on 2024-05-12 11:47:18

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
0004     SPDX-FileCopyrightText: 1999-2000 Preston Brown <pbrown@kde.org>
0005     SPDX-FileCopyrightText: 1996-2000 Matthias Kalle Dalheimer <kalle@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #ifndef KCONFIGDATA_P_H
0011 #define KCONFIGDATA_P_H
0012 
0013 #include <QByteArray>
0014 #include <QDebug>
0015 #include <QMap>
0016 #include <QString>
0017 
0018 /**
0019  * map/dict/list config node entry.
0020  * @internal
0021  */
0022 struct KEntry {
0023     /** Constructor. @internal */
0024     KEntry()
0025         : mValue()
0026         , bDirty(false)
0027         , bGlobal(false)
0028         , bImmutable(false)
0029         , bDeleted(false)
0030         , bExpand(false)
0031         , bReverted(false)
0032         , bLocalizedCountry(false)
0033         , bNotify(false)
0034         , bOverridesGlobal(false)
0035     {
0036     }
0037     /** @internal */
0038     QByteArray mValue;
0039     /**
0040      * Must the entry be written back to disk?
0041      */
0042     bool bDirty : 1;
0043     /**
0044      * Entry should be written to the global config file
0045      */
0046     bool bGlobal : 1;
0047     /**
0048      * Entry can not be modified.
0049      */
0050     bool bImmutable : 1;
0051     /**
0052      * Entry has been deleted.
0053      */
0054     bool bDeleted : 1;
0055     /**
0056      * Whether to apply dollar expansion or not.
0057      */
0058     bool bExpand : 1;
0059     /**
0060      * Entry has been reverted to its default value (from a more global file).
0061      */
0062     bool bReverted : 1;
0063     /**
0064      * Entry is for a localized key. If @c false the value references just language e.g. "de",
0065      * if @c true the value references language and country, e.g. "de_DE".
0066      **/
0067     bool bLocalizedCountry : 1;
0068 
0069     bool bNotify : 1;
0070 
0071     /**
0072      * Entry will need to be written on a non global file even if it matches default value
0073      */
0074     bool bOverridesGlobal : 1;
0075 };
0076 
0077 Q_DECLARE_TYPEINFO(KEntry, Q_MOVABLE_TYPE);
0078 
0079 // These operators are used to check whether an entry which is about
0080 // to be written equals the previous value. As such, this intentionally
0081 // omits the dirty/notify flag from the comparison.
0082 inline bool operator==(const KEntry &k1, const KEntry &k2)
0083 {
0084     /* clang-format off */
0085     return k1.bGlobal == k2.bGlobal
0086         && k1.bImmutable == k2.bImmutable
0087         && k1.bDeleted == k2.bDeleted
0088         && k1.bExpand == k2.bExpand
0089         && k1.mValue == k2.mValue;
0090     /* clang-format on */
0091 }
0092 
0093 inline bool operator!=(const KEntry &k1, const KEntry &k2)
0094 {
0095     return !(k1 == k2);
0096 }
0097 
0098 /**
0099  * key structure holding both the actual key and the group
0100  * to which it belongs.
0101  * @internal
0102  */
0103 struct KEntryKey {
0104     /** Constructor. @internal */
0105     KEntryKey(const QByteArray &_group = QByteArray(), const QByteArray &_key = QByteArray(), bool isLocalized = false, bool isDefault = false)
0106         : mGroup(_group)
0107         , mKey(_key)
0108         , bLocal(isLocalized)
0109         , bDefault(isDefault)
0110         , bRaw(false)
0111     {
0112         ;
0113     }
0114     /**
0115      * The "group" to which this EntryKey belongs
0116      */
0117     QByteArray mGroup;
0118     /**
0119      * The _actual_ key of the entry in question
0120      */
0121     QByteArray mKey;
0122     /**
0123      * Entry is localised or not
0124      */
0125     bool bLocal : 1;
0126     /**
0127      * Entry indicates if this is a default value.
0128      */
0129     bool bDefault : 1;
0130     /** @internal
0131      * Key is a raw unprocessed key.
0132      * @warning this should only be set during merging, never for normal use.
0133      */
0134     bool bRaw : 1;
0135 };
0136 
0137 Q_DECLARE_TYPEINFO(KEntryKey, Q_MOVABLE_TYPE);
0138 
0139 /**
0140  * Compares two KEntryKeys (needed for QMap). The order is localized, localized-default,
0141  * non-localized, non-localized-default
0142  * @internal
0143  */
0144 inline bool operator<(const KEntryKey &k1, const KEntryKey &k2)
0145 {
0146     int result = k1.mGroup.compare(k2.mGroup);
0147     if (result != 0) {
0148         return result < 0;
0149     }
0150 
0151     result = k1.mKey.compare(k2.mKey);
0152     if (result != 0) {
0153         return result < 0;
0154     }
0155 
0156     if (k1.bLocal != k2.bLocal) {
0157         return k1.bLocal;
0158     }
0159     return (!k1.bDefault && k2.bDefault);
0160 }
0161 
0162 /**
0163  * Returns the minimum key that has @a mGroup == @p group.
0164  *
0165  * @note The returned "minimum key" is consistent with KEntryKey's operator<().
0166  *       The return value of this function can be passed to KEntryMap::lowerBound().
0167  */
0168 inline KEntryKey minimumGroupKey(const QByteArray &group)
0169 {
0170     return KEntryKey(group, QByteArray{}, true, false);
0171 }
0172 
0173 QDebug operator<<(QDebug dbg, const KEntryKey &key);
0174 QDebug operator<<(QDebug dbg, const KEntry &entry);
0175 
0176 /**
0177  * \relates KEntry
0178  * type specifying a map of entries (key,value pairs).
0179  * The keys are actually a key in a particular config file group together
0180  * with the group name.
0181  * @internal
0182  */
0183 class KEntryMap : public QMap<KEntryKey, KEntry>
0184 {
0185 public:
0186     enum SearchFlag {
0187         SearchDefaults = 1,
0188         SearchLocalized = 2,
0189     };
0190     Q_DECLARE_FLAGS(SearchFlags, SearchFlag)
0191 
0192     enum EntryOption {
0193         EntryDirty = 1,
0194         EntryGlobal = 2,
0195         EntryImmutable = 4,
0196         EntryDeleted = 8,
0197         EntryExpansion = 16,
0198         EntryRawKey = 32,
0199         EntryLocalizedCountry = 64,
0200         EntryNotify = 128,
0201         EntryDefault = (SearchDefaults << 16),
0202         EntryLocalized = (SearchLocalized << 16),
0203     };
0204     Q_DECLARE_FLAGS(EntryOptions, EntryOption)
0205 
0206     Iterator findExactEntry(const QByteArray &group, const QByteArray &key = QByteArray(), SearchFlags flags = SearchFlags());
0207 
0208     Iterator findEntry(const QByteArray &group, const QByteArray &key = QByteArray(), SearchFlags flags = SearchFlags());
0209 
0210     ConstIterator findEntry(const QByteArray &group, const QByteArray &key = QByteArray(), SearchFlags flags = SearchFlags()) const
0211     {
0212         return constFindEntry(group, key, flags);
0213     }
0214 
0215     ConstIterator constFindEntry(const QByteArray &group, const QByteArray &key = QByteArray(), SearchFlags flags = SearchFlags()) const;
0216 
0217     /**
0218      * Returns true if the entry gets dirtied or false in other case
0219      */
0220     bool setEntry(const QByteArray &group, const QByteArray &key, const QByteArray &value, EntryOptions options);
0221 
0222     void setEntry(const QByteArray &group, const QByteArray &key, const QString &value, EntryOptions options)
0223     {
0224         setEntry(group, key, value.toUtf8(), options);
0225     }
0226 
0227     QString getEntry(const QByteArray &group,
0228                      const QByteArray &key,
0229                      const QString &defaultValue = QString(),
0230                      SearchFlags flags = SearchFlags(),
0231                      bool *expand = nullptr) const;
0232 
0233     bool hasEntry(const QByteArray &group, const QByteArray &key = QByteArray(), SearchFlags flags = SearchFlags()) const;
0234 
0235     bool getEntryOption(const ConstIterator &it, EntryOption option) const;
0236     bool getEntryOption(const QByteArray &group, const QByteArray &key, SearchFlags flags, EntryOption option) const
0237     {
0238         return getEntryOption(findEntry(group, key, flags), option);
0239     }
0240 
0241     void setEntryOption(Iterator it, EntryOption option, bool bf);
0242     void setEntryOption(const QByteArray &group, const QByteArray &key, SearchFlags flags, EntryOption option, bool bf)
0243     {
0244         setEntryOption(findEntry(group, key, flags), option, bf);
0245     }
0246 
0247     bool revertEntry(const QByteArray &group, const QByteArray &key, EntryOptions options, SearchFlags flags = SearchFlags());
0248 
0249     template<typename ConstIteratorUser>
0250     void forEachEntryWhoseGroupStartsWith(const QByteArray &groupPrefix, ConstIteratorUser callback) const
0251     {
0252         for (auto it = lowerBound(minimumGroupKey(groupPrefix)), end = cend(); it != end && it.key().mGroup.startsWith(groupPrefix); ++it) {
0253             callback(it);
0254         }
0255     }
0256 
0257     template<typename ConstIteratorPredicate>
0258     bool anyEntryWhoseGroupStartsWith(const QByteArray &groupPrefix, ConstIteratorPredicate predicate) const
0259     {
0260         for (auto it = lowerBound(minimumGroupKey(groupPrefix)), end = cend(); it != end && it.key().mGroup.startsWith(groupPrefix); ++it) {
0261             if (predicate(it)) {
0262                 return true;
0263             }
0264         }
0265         return false;
0266     }
0267 };
0268 Q_DECLARE_OPERATORS_FOR_FLAGS(KEntryMap::SearchFlags)
0269 Q_DECLARE_OPERATORS_FOR_FLAGS(KEntryMap::EntryOptions)
0270 
0271 /**
0272  * \relates KEntry
0273  * type for iterating over keys in a KEntryMap in sorted order.
0274  * @internal
0275  */
0276 typedef QMap<KEntryKey, KEntry>::Iterator KEntryMapIterator;
0277 
0278 /**
0279  * \relates KEntry
0280  * type for iterating over keys in a KEntryMap in sorted order.
0281  * It is const, thus you cannot change the entries in the iterator,
0282  * only examine them.
0283  * @internal
0284  */
0285 typedef QMap<KEntryKey, KEntry>::ConstIterator KEntryMapConstIterator;
0286 
0287 #endif