GCC Code Coverage Report


Directory: ./
File: pdserv/src/Config.cpp
Date: 2025-08-17 04:10:43
Exec Total Coverage
Lines: 82 113 72.6%
Branches: 56 104 53.8%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * Copyright 2010 Richard Hacker (lerichi at gmx dot net)
4 *
5 * This file is part of the pdserv library.
6 *
7 * The pdserv library is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation, either version 3 of the License, or (at
10 * your option) any later version.
11 *
12 * The pdserv library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with the pdserv library. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22 #include <cstring>
23 #include <cstdio>
24 #include <cerrno>
25
26 #include "Config.h"
27
28 #include <yaml.h>
29 using namespace PdServ;
30
31 /////////////////////////////////////////////////////////////////////////////
32 /////////////////////////////////////////////////////////////////////////////
33 static char error[100];
34
35 /////////////////////////////////////////////////////////////////////////////
36 /////////////////////////////////////////////////////////////////////////////
37 2900 Config::Config(): node(0)
38 {
39 2900 }
40
41 /////////////////////////////////////////////////////////////////////////////
42 30 Config::Config(const Config& other):
43 30 document(other.document), node(other.node)
44 {
45 30 }
46
47 /////////////////////////////////////////////////////////////////////////////
48 2042 Config::Config(yaml_document_t *d, yaml_node_t *n):
49 2042 document(d), node(n)
50 {
51 2042 }
52
53 /////////////////////////////////////////////////////////////////////////////
54 9944 Config::~Config()
55 {
56 4972 clear();
57 4972 }
58
59 /////////////////////////////////////////////////////////////////////////////
60 5127 void Config::clear()
61 {
62
2/2
✓ Branch 2 taken 155 times.
✓ Branch 3 taken 4972 times.
5127 if (!file.empty()) {
63 155 yaml_document_delete(document);
64 155 delete document;
65
66 155 file.clear();
67 }
68 5127 }
69
70 /////////////////////////////////////////////////////////////////////////////
71 const char * Config::reload()
72 {
73 std::string file(this->file);
74 return load(file.c_str());
75 }
76
77 /////////////////////////////////////////////////////////////////////////////
78 156 const char * Config::load(const char *filename)
79 {
80 struct Parser : yaml_parser_t
81 {
82 156 ~Parser() { yaml_parser_delete(this); }
83 312 } parser = {};
84 FILE *fh;
85
86 /* Initialize parser */
87
2/4
✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 156 times.
156 if(!yaml_parser_initialize(&parser)) {
88 ::snprintf(error, sizeof(error), "Could not initialize YAML parser");
89 return error;
90 }
91
92
1/2
✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
156 fh = ::fopen(filename, "r");
93
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 155 times.
156 if (!fh) {
94 1 ::snprintf(error, sizeof(error), "Could not open config file %s: %s",
95 1 filename, strerror(errno));
96 1 return error;
97 }
98
99 /* Set input file */
100
1/2
✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
155 yaml_parser_set_input_file(&parser, fh);
101
102
1/2
✓ Branch 2 taken 155 times.
✗ Branch 3 not taken.
155 clear();
103
1/2
✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
155 document = new yaml_document_t;
104
1/2
✓ Branch 2 taken 155 times.
✗ Branch 3 not taken.
155 this->file = filename;
105
106 /* START new code */
107
2/4
✓ Branch 2 taken 155 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 155 times.
155 if (!yaml_parser_load(&parser, document)) {
108 snprintf(error, sizeof(error), "YAML parser failure at line %zu: %s",
109 parser.problem_mark.line, parser.problem);
110 clear();
111 return error;
112 }
113
114 // Now finished with the file
115
1/2
✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
155 ::fclose(fh);
116
117
1/2
✓ Branch 2 taken 155 times.
✗ Branch 3 not taken.
155 node = yaml_document_get_root_node(document);
118
119 155 return 0;
120 }
121
122 /////////////////////////////////////////////////////////////////////////////
123 155 Config& Config::operator=(const Config& other)
124 {
125 155 document = other.document;
126 155 node = other.node;
127
128 155 return *this;
129 }
130
131 /////////////////////////////////////////////////////////////////////////////
132 4576 Config Config::operator[](const char *key) const
133 {
134
2/4
✓ Branch 4 taken 4576 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 4576 times.
✗ Branch 10 not taken.
4576 return this->operator[](std::string(key));
135 }
136
137 /////////////////////////////////////////////////////////////////////////////
138 1243 Config::operator bool() const
139 {
140 1243 return node != 0;
141 }
142
143 /////////////////////////////////////////////////////////////////////////////
144 4576 Config Config::operator[](const std::string& key) const
145 {
146
5/6
✓ Branch 1 taken 4458 times.
✓ Branch 2 taken 118 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4458 times.
✓ Branch 7 taken 24 times.
✓ Branch 8 taken 4434 times.
4576 if (!node or node->type != YAML_MAPPING_NODE)
147 142 return Config();
148
149 14837 for (yaml_node_pair_t *pair = node->data.mapping.pairs.start;
150
2/2
✓ Branch 2 taken 12427 times.
✓ Branch 3 taken 2410 times.
14837 pair != node->data.mapping.pairs.top; ++pair) {
151 12427 yaml_node_t *n = yaml_document_get_node(document, pair->key);
152
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 12427 times.
✓ Branch 3 taken 2024 times.
✓ Branch 4 taken 10403 times.
24854 if (n->type == YAML_SCALAR_NODE
153
2/2
✓ Branch 3 taken 2411 times.
✓ Branch 4 taken 10016 times.
12427 and key.size() == n->data.scalar.length
154
5/8
✓ Branch 0 taken 12427 times.
✗ Branch 1 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2411 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2411 times.
✓ Branch 9 taken 2024 times.
✓ Branch 10 taken 387 times.
17249 and !strncmp((char*)n->data.scalar.value,
155 2411 key.c_str(), n->data.scalar.length)) {
156 2024 return Config(document,
157 4048 yaml_document_get_node(document, pair->value));
158 }
159 }
160
161 2410 return Config();
162 }
163
164 /////////////////////////////////////////////////////////////////////////////
165 80 Config Config::operator[](size_t index) const
166 {
167
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
80 if (!node)
168 return Config();
169
170
3/6
✗ Branch 2 not taken.
✓ Branch 3 taken 80 times.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 56 times.
✗ Branch 7 not taken.
80 switch (node->type) {
171 24 case YAML_SEQUENCE_NODE:
172 {
173 24 yaml_node_item_t *n = node->data.sequence.items.start;
174 do {
175
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
24 if (!index--)
176 18 return Config(document,
177 36 yaml_document_get_node(document, *n));
178
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 } while (++n != node->data.sequence.items.top);
179 }
180 6 break;
181
182 case YAML_MAPPING_NODE:
183 {
184 yaml_node_pair_t *pair = node->data.mapping.pairs.start;
185 do {
186 if (!index--)
187 return Config(document,
188 yaml_document_get_node(document,
189 pair->key));
190 } while (++pair != node->data.mapping.pairs.top);
191 }
192 break;
193
194 56 case YAML_SCALAR_NODE:
195
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 28 times.
56 if (index == 0)
196 28 return *this;
197 28 break;
198
199 default:
200 break;
201 }
202
203 34 return Config();
204 }
205
206 /////////////////////////////////////////////////////////////////////////////
207 12 bool Config::isMapping() const
208 {
209
4/6
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 8 times.
✓ Branch 8 taken 4 times.
12 return node and node->type == YAML_MAPPING_NODE;
210 }
211
212 /////////////////////////////////////////////////////////////////////////////
213 2935 std::string Config::toString(const std::string& defaultString) const
214 {
215
4/6
✓ Branch 1 taken 1114 times.
✓ Branch 2 taken 1821 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1114 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1114 times.
2935 if (!node or node->type != YAML_SCALAR_NODE)
216 1821 return defaultString;
217
218 1114 return std::string((char*) node->data.scalar.value,
219
1/2
✓ Branch 5 taken 1114 times.
✗ Branch 6 not taken.
2228 node->data.scalar.length);
220 }
221
222 /////////////////////////////////////////////////////////////////////////////
223 namespace PdServ {
224 template <typename T>
225 bool Config::get(T &value) const
226 {
227 if (!*this)
228 return false;
229
230 value = *this;
231 return true;
232 }
233
234 template bool Config::get(int& value) const;
235 }
236
237 /////////////////////////////////////////////////////////////////////////////
238 int Config::toInt(int dflt) const
239 {
240 std::string sval(toString());
241 if (sval.empty())
242 return dflt;
243
244 return strtol(sval.c_str(), 0, 0);
245 }
246
247 /////////////////////////////////////////////////////////////////////////////
248 1086 unsigned int Config::toUInt(unsigned int dflt) const
249 {
250
1/2
✓ Branch 5 taken 1086 times.
✗ Branch 6 not taken.
2172 std::string sval(toString());
251
2/2
✓ Branch 1 taken 639 times.
✓ Branch 2 taken 447 times.
1086 if (sval.empty())
252 639 return dflt;
253
254
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 447 times.
447 return strtoul(sval.c_str(), 0, 0);
255 }
256