GCC Code Coverage Report


Directory: ./
File: pdserv/src/Config.cpp
Date: 2024-12-15 04:08:34
Exec Total Coverage
Lines: 81 112 72.3%
Branches: 55 104 52.9%

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