forked from cculianu/Fulcrum
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOptions.cpp
168 lines (154 loc) · 5.27 KB
/
Options.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//
// Fulcrum - A fast & nimble SPV Server for Bitcoin Cash
// Copyright (C) 2019-2020 Calin A. Culianu <calin.culianu@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program (see LICENSE.txt). If not, see
// <https://www.gnu.org/licenses/>.
//
#include "Options.h"
#include <QFile>
#include <QIODevice>
#include <QTextStream>
std::optional<QString> ConfigFile::optValue(const QString &name, Qt::CaseSensitivity cs) const
{
std::optional<QString> ret;
if (cs == Qt::CaseSensitive) {
if (auto it = map.find(name); it != map.end())
ret = it.value();
} else {
for (auto it = map.begin(); it != map.end(); ++it) {
if (it.key().compare(name, cs) == 0) {
ret = it.value();
break;
}
}
}
return ret;
}
int ConfigFile::remove(const QString &name, Qt::CaseSensitivity cs)
{
if (cs == Qt::CaseSensitive) {
return map.remove(name);
} else {
int ctr = 0;
for (auto it = map.begin(), next = it; it != map.end(); it = next) {
if (it.key().compare(name, cs) == 0) {
next = map.erase(it);
++ctr;
} else
++next;
}
return ctr;
}
}
bool ConfigFile::hasValue(const QString &name, Qt::CaseSensitivity cs) const
{
return optValue(name, cs).has_value();
}
QString ConfigFile::value(const QString &name, const QString & def, Qt::CaseSensitivity cs) const
{
return optValue(name, cs).value_or(def);
}
QStringList ConfigFile::values(const QString &name, Qt::CaseSensitivity cs) const
{
QStringList ret;
if (cs == Qt::CaseSensitive) {
ret = map.values(name);
} else {
for (auto it = map.begin(); it != map.end(); ++it) {
if (it.key().compare(name, cs) == 0)
ret.push_back(it.value());
}
}
return ret;
}
bool ConfigFile::open(const QString &filePath)
{
static const QChar comment('#'), eq('='), bracket('[');
clear();
QList<QByteArray> lines;
{
QFile f(filePath);
if (!f.exists() || !f.open(QIODevice::ReadOnly|QIODevice::Text))
return false;
auto fileData = f.read(1024*1024*1); // read up to 1 MB
if (fileData.isEmpty())
return f.error() == QFile::FileError::NoError;
lines = fileData.split('\n');
}
for (const auto & lineData : lines) {
QString line = QString::fromUtf8(lineData).trimmed();
if (!line.isEmpty() && line.at(0) == bracket)
continue; // ignore "[section]" headers in case the user thinks we support these
if (const int cpos = line.indexOf(comment); cpos > -1) // find and throw away comments (everything after '#' char)
line = line.left(cpos).trimmed();
if (line.isEmpty())
continue;
QString name, value;
if (const int eqpos = line.indexOf(eq); eqpos > -1) {
name = line.left(eqpos).trimmed();
if (name.isEmpty())
continue;
value = line.mid(eqpos+1).trimmed();
} else
// a name by itself on a line with no equal sign, becomes name=(emptystring), which might be useful to
// indicate the name was present (can act like a bool flag if present)
name = line;
// save item
map.insertMulti(name, value);
}
map.squeeze();
return true;
}
bool ConfigFile::boolValue(const QString & name, bool def, bool *parsedOk, Qt::CaseSensitivity cs) const
{
bool dummy;
bool & ok ( parsedOk ? *parsedOk : dummy );
ok = false;
const auto opt = optValue(name, cs);
if (!opt.has_value())
return def;
const auto val = opt.value().toLower();
if (val == "true" || val == "yes" || val == "on" || val.isEmpty() /* "" means true! */) { ok = true; return true; }
else if (val == "false" || val == "no" || val == "off") { ok = true; return false; }
bool ret = val.toInt(&ok);
if (!ok) ret = def;
return ret;
}
int ConfigFile::intValue(const QString & name, int def, bool *parsedOk, Qt::CaseSensitivity cs) const
{
bool dummy;
bool & ok ( parsedOk ? *parsedOk : dummy );
ok = false;
const auto opt = optValue(name, cs);
if (!opt.has_value())
return def;
const auto val = opt.value().toLower();
int ret = val.toInt(&ok);
if (!ok) ret = def;
return ret;
}
double ConfigFile::doubleValue(const QString & name, double def, bool *parsedOk, Qt::CaseSensitivity cs) const
{
bool dummy;
bool & ok ( parsedOk ? *parsedOk : dummy );
ok = false;
const auto opt = optValue(name, cs);
if (!opt.has_value())
return def;
const auto val = opt.value().toLower();
double ret = val.toDouble(&ok);
if (!ok) ret = def;
return ret;
}