1
/****************************************************************************
2
**
3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the QtCore module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** No Commercial Usage
11
** This file contains pre-release code and may not be distributed.
12
** You may use this file in accordance with the terms and conditions
13
** contained in the Technology Preview License Agreement accompanying
14
** this package.
15
**
16
** GNU Lesser General Public License Usage
17
** Alternatively, this file may be used under the terms of the GNU Lesser
18
** General Public License version 2.1 as published by the Free Software
19
** Foundation and appearing in the file LICENSE.LGPL included in the
20
** packaging of this file.  Please review the following information to
21
** ensure the GNU Lesser General Public License version 2.1 requirements
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23
**
24
** In addition, as a special exception, Nokia gives you certain additional
25
** rights.  These rights are described in the Nokia Qt LGPL Exception
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27
**
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
30
**
31
**
32
**
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
#ifndef QSETTINGS_P_H
43
#define QSETTINGS_P_H
44
45
//
46
//  W A R N I N G
47
//  -------------
48
//
49
// This file is not part of the Qt API.  It exists purely as an
50
// implementation detail.  This header file may change from version to
51
// version without notice, or even be removed.
52
//
53
// We mean it.
54
//
55
56
#include "QtCore/qdatetime.h"
57
#include "QtCore/qmap.h"
58
#include "QtCore/qmutex.h"
59
#include "QtCore/qiodevice.h"
60
#include "QtCore/qstack.h"
61
#include "QtCore/qstringlist.h"
62
#ifndef QT_NO_QOBJECT
63
#include "private/qobject_p.h"
64
#endif
65
66
#ifdef Q_OS_WIN
67
#include "QtCore/qt_windows.h"
68
#endif
69
70
QT_BEGIN_NAMESPACE
71
72
#if defined(Q_WS_QWS)
73
#define QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER
74
#endif
75
76
// used in testing framework
77
#define QSETTINGS_P_H_VERSION 3
78
79
#ifdef QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER
80
static const Qt::CaseSensitivity IniCaseSensitivity = Qt::CaseSensitive;
81
82
class QSettingsKey : public QString
83
{
84
public:
85
    inline QSettingsKey(const QString &key, Qt::CaseSensitivity cs, int /* position */ = -1)
86
        : QString(key) { Q_ASSERT(cs == Qt::CaseSensitive); Q_UNUSED(cs); }
87
88
    inline QString originalCaseKey() const { return *this; }
89
    inline int originalKeyPosition() const { return -1; }
90
};
91
#else
92
static const Qt::CaseSensitivity IniCaseSensitivity = Qt::CaseInsensitive;
93
94
class QSettingsKey : public QString
95
{
96
public:
97
    inline QSettingsKey(const QString &key, Qt::CaseSensitivity cs, int position = -1)
98
         : QString(key), theOriginalKey(key), theOriginalKeyPosition(position)
99
    {
100
        if (cs == Qt::CaseInsensitive)
101
            QString::operator=(toLower());
102
    }
103
104
    inline QString originalCaseKey() const { return theOriginalKey; }
105
    inline int originalKeyPosition() const { return theOriginalKeyPosition; }
106
107
private:
108
    QString theOriginalKey;
109
    int theOriginalKeyPosition;
110
};
111
#endif
112
113
typedef QMap<QSettingsKey, QByteArray> UnparsedSettingsMap;
114
typedef QMap<QSettingsKey, QVariant> ParsedSettingsMap;
115
116
class QSettingsGroup
117
{
118
public:
119
    inline QSettingsGroup()
120
        : num(-1), maxNum(-1) {}
121
    inline QSettingsGroup(const QString &s)
122
        : str(s), num(-1), maxNum(-1) {}
123
    inline QSettingsGroup(const QString &s, bool guessArraySize)
124
        : str(s), num(0), maxNum(guessArraySize ? 0 : -1) {}
125
126
    inline QString name() const { return str; }
127
    inline QString toString() const;
128
    inline bool isArray() const { return num != -1; }
129
    inline int arraySizeGuess() const { return maxNum; }
130
    inline void setArrayIndex(int i)
131
    { num = i + 1; if (maxNum != -1 && num > maxNum) maxNum = num; }
132
133
    QString str;
134
    int num;
135
    int maxNum;
136
};
137
138
inline QString QSettingsGroup::toString() const
139
{
140
    QString result;
141
    result = str;
142
    if (num > 0) {
143
        result += QLatin1Char('/');
144
        result += QString::number(num);
145
    }
146
    return result;
147
}
148
149
class Q_CORE_EXPORT QConfFile
150
{
151
public:
152
    ParsedSettingsMap mergedKeyMap() const;
153
    bool isWritable() const;
154
155
    static QConfFile *fromName(const QString &name, bool _userPerms);
156
    static void clearCache();
157
158
    QString name;
159
    QDateTime timeStamp;
160
    qint64 size;
161
    UnparsedSettingsMap unparsedIniSections;
162
    ParsedSettingsMap originalKeys;
163
    ParsedSettingsMap addedKeys;
164
    ParsedSettingsMap removedKeys;
165
    QAtomicInt ref;
166
    QMutex mutex;
167
    bool userPerms;
168
169
private:
170
#ifdef Q_DISABLE_COPY
171
    QConfFile(const QConfFile &);
172
    QConfFile &operator=(const QConfFile &);
173
#endif
174
    QConfFile(const QString &name, bool _userPerms);
175
176
    friend class QConfFile_createsItself; // silences compiler warning
177
};
178
179
class Q_AUTOTEST_EXPORT QSettingsPrivate
180
#ifndef QT_NO_QOBJECT
181
    : public QObjectPrivate
182
#endif
183
{
184
#ifdef QT_NO_QOBJECT
185
    QSettings *q_ptr;
186
#endif
187
    Q_DECLARE_PUBLIC(QSettings)
188
189
public:
190
    QSettingsPrivate(QSettings::Format format);
191
    QSettingsPrivate(QSettings::Format format, QSettings::Scope scope,
192
                     const QString &organization, const QString &application);
193
    virtual ~QSettingsPrivate();
194
195
    virtual void remove(const QString &key) = 0;
196
    virtual void set(const QString &key, const QVariant &value) = 0;
197
    virtual bool get(const QString &key, QVariant *value) const = 0;
198
199
    enum ChildSpec { AllKeys, ChildKeys, ChildGroups };
200
    virtual QStringList children(const QString &prefix, ChildSpec spec) const = 0;
201
202
    virtual void clear() = 0;
203
    virtual void sync() = 0;
204
    virtual void flush() = 0;
205
    virtual bool isWritable() const = 0;
206
    virtual QString fileName() const = 0;
207
208
    QString actualKey(const QString &key) const;
209
    void beginGroupOrArray(const QSettingsGroup &group);
210
    void setStatus(QSettings::Status status) const;
211
    void requestUpdate();
212
    void update();
213
214
    static QString normalizedKey(const QString &key);
215
    static QSettingsPrivate *create(QSettings::Format format, QSettings::Scope scope,
216
                                        const QString &organization, const QString &application);
217
    static QSettingsPrivate *create(const QString &fileName, QSettings::Format format);
218
219
    static void processChild(QString key, ChildSpec spec, QMap<QString, QString> &result);
220
221
    // Variant streaming functions
222
    static QStringList variantListToStringList(const QVariantList &l);
223
    static QVariant stringListToVariantList(const QStringList &l);
224
225
    // parser functions
226
    static QString variantToString(const QVariant &v);
227
    static QVariant stringToVariant(const QString &s);
228
    static void iniEscapedKey(const QString &key, QByteArray &result);
229
    static bool iniUnescapedKey(const QByteArray &key, int from, int to, QString &result);
230
    static void iniEscapedString(const QString &str, QByteArray &result, QTextCodec *codec);
231
    static void iniEscapedStringList(const QStringList &strs, QByteArray &result, QTextCodec *codec);
232
    static bool iniUnescapedStringList(const QByteArray &str, int from, int to,
233
                                       QString &stringResult, QStringList &stringListResult,
234
                                       QTextCodec *codec);
235
    static QStringList splitArgs(const QString &s, int idx);
236
237
    /*
238
    The numeric values of these enums define their search order. For example,
239
    F_User | F_Organization is searched before F_System | F_Application,
240
    because their values are respectively 1 and 2.
241
    */
242
    enum {
243
       F_Application = 0x0,
244
       F_Organization = 0x1,
245
       F_User = 0x0,
246
       F_System = 0x2,
247
       NumConfFiles = 4
248
    };
249
250
    QSettings::Format format;
251
    QSettings::Scope scope;
252
    QString organizationName;
253
    QString applicationName;
254
    QTextCodec *iniCodec;
255
256
protected:
257
    QStack<QSettingsGroup> groupStack;
258
    QString groupPrefix;
259
    int spec;
260
    bool fallbacks;
261
    bool pendingChanges;
262
    mutable QSettings::Status status;
263
};
264
265
class QConfFileSettingsPrivate : public QSettingsPrivate
266
{
267
public:
268
    QConfFileSettingsPrivate(QSettings::Format format, QSettings::Scope scope,
269
                             const QString &organization, const QString &application);
270
    QConfFileSettingsPrivate(const QString &fileName, QSettings::Format format);
271
    ~QConfFileSettingsPrivate();
272
273
    void remove(const QString &key);
274
    void set(const QString &key, const QVariant &value);
275
    bool get(const QString &key, QVariant *value) const;
276
277
    QStringList children(const QString &prefix, ChildSpec spec) const;
278
279
    void clear();
280
    void sync();
281
    void flush();
282
    bool isWritable() const;
283
    QString fileName() const;
284
285
    static bool readIniFile(const QByteArray &data, UnparsedSettingsMap *unparsedIniSections);
286
    static bool readIniSection(const QSettingsKey &section, const QByteArray &data,
287
                               ParsedSettingsMap *settingsMap, QTextCodec *codec);
288
    static bool readIniLine(const QByteArray &data, int &dataPos, int &lineStart, int &lineLen,
289
                            int &equalsPos);
290
291
private:
292
    void initFormat();
293
    void initAccess();
294
    void syncConfFile(int confFileNo);
295
    bool writeIniFile(QIODevice &device, const ParsedSettingsMap &map);
296
#ifdef Q_OS_MAC
297
    bool readPlistFile(const QString &fileName, ParsedSettingsMap *map) const;
298
    bool writePlistFile(const QString &fileName, const ParsedSettingsMap &map) const;
299
#endif
300
    void ensureAllSectionsParsed(QConfFile *confFile) const;
301
    void ensureSectionParsed(QConfFile *confFile, const QSettingsKey &key) const;
302
303
    QConfFile *confFiles[NumConfFiles];
304
    QSettings::ReadFunc readFunc;
305
    QSettings::WriteFunc writeFunc;
306
    QString extension;
307
    Qt::CaseSensitivity caseSensitivity;
308
    int nextPosition;
309
};
310
311
QT_END_NAMESPACE
312
313
#endif // QSETTINGS_P_H