1 /*
2     This file is part of the KDE libraries
3     SPDX-FileCopyrightText: 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
4     SPDX-FileCopyrightText: 1999-2000 Preston Brown <pbrown@kde.org>
5     SPDX-FileCopyrightText: 1996-2000 Matthias Kalle Dalheimer <kalle@kde.org>
6 
7     SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9 
10 #ifndef KCONFIGDATA_P_H
11 #define KCONFIGDATA_P_H
12 
13 #include <QByteArray>
14 #include <QDebug>
15 #include <QMap>
16 #include <QString>
17 
18 /**
19  * map/dict/list config node entry.
20  * @internal
21  */
22 struct KEntry {
23     /** Constructor. @internal */
KEntryKEntry24     KEntry()
25         : mValue()
26         , bDirty(false)
27         , bGlobal(false)
28         , bImmutable(false)
29         , bDeleted(false)
30         , bExpand(false)
31         , bReverted(false)
32         , bLocalizedCountry(false)
33         , bNotify(false)
34         , bOverridesGlobal(false)
35     {
36     }
37     /** @internal */
38     QByteArray mValue;
39     /**
40      * Must the entry be written back to disk?
41      */
42     bool bDirty : 1;
43     /**
44      * Entry should be written to the global config file
45      */
46     bool bGlobal : 1;
47     /**
48      * Entry can not be modified.
49      */
50     bool bImmutable : 1;
51     /**
52      * Entry has been deleted.
53      */
54     bool bDeleted : 1;
55     /**
56      * Whether to apply dollar expansion or not.
57      */
58     bool bExpand : 1;
59     /**
60      * Entry has been reverted to its default value (from a more global file).
61      */
62     bool bReverted : 1;
63     /**
64      * Entry is for a localized key. If @c false the value references just language e.g. "de",
65      * if @c true the value references language and country, e.g. "de_DE".
66      **/
67     bool bLocalizedCountry : 1;
68 
69     bool bNotify : 1;
70 
71     /**
72      * Entry will need to be written on a non global file even if it matches default value
73      */
74     bool bOverridesGlobal : 1;
75 };
76 
77 // These operators are used to check whether an entry which is about
78 // to be written equals the previous value. As such, this intentionally
79 // omits the dirty/notify flag from the comparison.
80 inline bool operator==(const KEntry &k1, const KEntry &k2)
81 {
82     /* clang-format off */
83     return k1.bGlobal == k2.bGlobal
84         && k1.bImmutable == k2.bImmutable
85         && k1.bDeleted == k2.bDeleted
86         && k1.bExpand == k2.bExpand
87         && k1.mValue == k2.mValue;
88     /* clang-format on */
89 }
90 
91 inline bool operator!=(const KEntry &k1, const KEntry &k2)
92 {
93     return !(k1 == k2);
94 }
95 
96 /**
97  * key structure holding both the actual key and the group
98  * to which it belongs.
99  * @internal
100  */
101 struct KEntryKey {
102     /** Constructor. @internal */
103     KEntryKey(const QByteArray &_group = QByteArray(), const QByteArray &_key = QByteArray(), bool isLocalized = false, bool isDefault = false)
mGroupKEntryKey104         : mGroup(_group)
105         , mKey(_key)
106         , bLocal(isLocalized)
107         , bDefault(isDefault)
108         , bRaw(false)
109     {
110         ;
111     }
112     /**
113      * The "group" to which this EntryKey belongs
114      */
115     QByteArray mGroup;
116     /**
117      * The _actual_ key of the entry in question
118      */
119     QByteArray mKey;
120     /**
121      * Entry is localised or not
122      */
123     bool bLocal : 1;
124     /**
125      * Entry indicates if this is a default value.
126      */
127     bool bDefault : 1;
128     /** @internal
129      * Key is a raw unprocessed key.
130      * @warning this should only be set during merging, never for normal use.
131      */
132     bool bRaw : 1;
133 };
134 
135 /**
136  * Compares two KEntryKeys (needed for QMap). The order is localized, localized-default,
137  * non-localized, non-localized-default
138  * @internal
139  */
140 inline bool operator<(const KEntryKey &k1, const KEntryKey &k2)
141 {
142     int result = k1.mGroup.compare(k2.mGroup);
143     if (result != 0) {
144         return result < 0;
145     }
146 
147     result = k1.mKey.compare(k2.mKey);
148     if (result != 0) {
149         return result < 0;
150     }
151 
152     if (k1.bLocal != k2.bLocal) {
153         return k1.bLocal;
154     }
155     return (!k1.bDefault && k2.bDefault);
156 }
157 
158 QDebug operator<<(QDebug dbg, const KEntryKey &key);
159 QDebug operator<<(QDebug dbg, const KEntry &entry);
160 
161 /**
162  * \relates KEntry
163  * type specifying a map of entries (key,value pairs).
164  * The keys are actually a key in a particular config file group together
165  * with the group name.
166  * @internal
167  */
168 class KEntryMap : public QMap<KEntryKey, KEntry>
169 {
170 public:
171     enum SearchFlag {
172         SearchDefaults = 1,
173         SearchLocalized = 2,
174     };
175     Q_DECLARE_FLAGS(SearchFlags, SearchFlag)
176 
177     enum EntryOption {
178         EntryDirty = 1,
179         EntryGlobal = 2,
180         EntryImmutable = 4,
181         EntryDeleted = 8,
182         EntryExpansion = 16,
183         EntryRawKey = 32,
184         EntryLocalizedCountry = 64,
185         EntryNotify = 128,
186         EntryDefault = (SearchDefaults << 16),
187         EntryLocalized = (SearchLocalized << 16),
188     };
189     Q_DECLARE_FLAGS(EntryOptions, EntryOption)
190 
191     Iterator findExactEntry(const QByteArray &group, const QByteArray &key = QByteArray(), SearchFlags flags = SearchFlags());
192 
193     Iterator findEntry(const QByteArray &group, const QByteArray &key = QByteArray(), SearchFlags flags = SearchFlags());
194 
195     ConstIterator findEntry(const QByteArray &group, const QByteArray &key = QByteArray(), SearchFlags flags = SearchFlags()) const
196     {
197         return constFindEntry(group, key, flags);
198     }
199 
200     ConstIterator constFindEntry(const QByteArray &group, const QByteArray &key = QByteArray(), SearchFlags flags = SearchFlags()) const;
201 
202     /**
203      * Returns true if the entry gets dirtied or false in other case
204      */
205     bool setEntry(const QByteArray &group, const QByteArray &key, const QByteArray &value, EntryOptions options);
206 
setEntry(const QByteArray & group,const QByteArray & key,const QString & value,EntryOptions options)207     void setEntry(const QByteArray &group, const QByteArray &key, const QString &value, EntryOptions options)
208     {
209         setEntry(group, key, value.toUtf8(), options);
210     }
211 
212     QString getEntry(const QByteArray &group,
213                      const QByteArray &key,
214                      const QString &defaultValue = QString(),
215                      SearchFlags flags = SearchFlags(),
216                      bool *expand = nullptr) const;
217 
218     bool hasEntry(const QByteArray &group, const QByteArray &key = QByteArray(), SearchFlags flags = SearchFlags()) const;
219 
220     bool getEntryOption(const ConstIterator &it, EntryOption option) const;
getEntryOption(const QByteArray & group,const QByteArray & key,SearchFlags flags,EntryOption option)221     bool getEntryOption(const QByteArray &group, const QByteArray &key, SearchFlags flags, EntryOption option) const
222     {
223         return getEntryOption(findEntry(group, key, flags), option);
224     }
225 
226     void setEntryOption(Iterator it, EntryOption option, bool bf);
setEntryOption(const QByteArray & group,const QByteArray & key,SearchFlags flags,EntryOption option,bool bf)227     void setEntryOption(const QByteArray &group, const QByteArray &key, SearchFlags flags, EntryOption option, bool bf)
228     {
229         setEntryOption(findEntry(group, key, flags), option, bf);
230     }
231 
232     bool revertEntry(const QByteArray &group, const QByteArray &key, EntryOptions options, SearchFlags flags = SearchFlags());
233 };
234 Q_DECLARE_OPERATORS_FOR_FLAGS(KEntryMap::SearchFlags)
235 Q_DECLARE_OPERATORS_FOR_FLAGS(KEntryMap::EntryOptions)
236 
237 /**
238  * \relates KEntry
239  * type for iterating over keys in a KEntryMap in sorted order.
240  * @internal
241  */
242 typedef QMap<KEntryKey, KEntry>::Iterator KEntryMapIterator;
243 
244 /**
245  * \relates KEntry
246  * type for iterating over keys in a KEntryMap in sorted order.
247  * It is const, thus you cannot change the entries in the iterator,
248  * only examine them.
249  * @internal
250  */
251 typedef QMap<KEntryKey, KEntry>::ConstIterator KEntryMapConstIterator;
252 
253 #endif
254