GCC Code Coverage Report


Directory: ./
File: pdserv/src/Config.cpp
Date: 2023-11-12 04:06:57
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 1926 Config::Config(): node(0)
40 {
41 1926 }
42
43 /////////////////////////////////////////////////////////////////////////////
44 24 Config::Config(const Config& other):
45 24 document(other.document), node(other.node)
46 {
47 24 }
48
49 /////////////////////////////////////////////////////////////////////////////
50 1670 Config::Config(yaml_document_t *d, yaml_node_t *n):
51 1670 document(d), node(n)
52 {
53 1670 }
54
55 /////////////////////////////////////////////////////////////////////////////
56 7240 Config::~Config()
57 {
58 3620 clear();
59 3620 }
60
61 /////////////////////////////////////////////////////////////////////////////
62 3751 void Config::clear()
63 {
64
2/2
✓ Branch 2 taken 131 times.
✓ Branch 3 taken 3620 times.
3751 if (!file.empty()) {
65 131 yaml_document_delete(document);
66 131 delete document;
67
68 131 file.clear();
69 }
70 3751 }
71
72 /////////////////////////////////////////////////////////////////////////////
73 const char * Config::reload()
74 {
75 std::string file(this->file);
76 return load(file.c_str());
77 }
78
79 /////////////////////////////////////////////////////////////////////////////
80 132 const char * Config::load(const char *filename)
81 {
82 struct Parser : yaml_parser_t
83 {
84 132 ~Parser() { yaml_parser_delete(this); }
85 264 } parser = {};
86 FILE *fh;
87
88 /* Initialize parser */
89
2/4
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 132 times.
132 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 132 times.
✗ Branch 2 not taken.
132 fh = ::fopen(filename, "r");
95
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 131 times.
132 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 131 times.
✗ Branch 2 not taken.
131 yaml_parser_set_input_file(&parser, fh);
103
104
1/2
✓ Branch 2 taken 131 times.
✗ Branch 3 not taken.
131 clear();
105
1/2
✓ Branch 1 taken 131 times.
✗ Branch 2 not taken.
131 document = new yaml_document_t;
106
1/2
✓ Branch 2 taken 131 times.
✗ Branch 3 not taken.
131 this->file = filename;
107
108 /* START new code */
109
2/4
✓ Branch 2 taken 131 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 131 times.
131 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 131 times.
✗ Branch 2 not taken.
131 ::fclose(fh);
118
119
1/2
✓ Branch 2 taken 131 times.
✗ Branch 3 not taken.
131 node = yaml_document_get_root_node(document);
120
121 131 return 0;
122 }
123
124 /////////////////////////////////////////////////////////////////////////////
125 131 Config& Config::operator=(const Config& other)
126 {
127 131 document = other.document;
128 131 node = other.node;
129
130 131 return *this;
131 }
132
133 /////////////////////////////////////////////////////////////////////////////
134 3284 Config Config::operator[](const char *key) const
135 {
136
2/4
✓ Branch 4 taken 3284 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 3284 times.
✗ Branch 10 not taken.
3284 return this->operator[](std::string(key));
137 }
138
139 /////////////////////////////////////////////////////////////////////////////
140 1033 Config::operator bool() const
141 {
142 1033 return node != 0;
143 }
144
145 /////////////////////////////////////////////////////////////////////////////
146 3284 Config Config::operator[](const std::string& key) const
147 {
148
4/6
✓ Branch 1 taken 3184 times.
✓ Branch 2 taken 100 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3184 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3184 times.
3284 if (!node or node->type != YAML_MAPPING_NODE)
149 100 return Config();
150
151 9847 for (yaml_node_pair_t *pair = node->data.mapping.pairs.start;
152
2/2
✓ Branch 2 taken 8315 times.
✓ Branch 3 taken 1532 times.
9847 pair != node->data.mapping.pairs.top; ++pair) {
153 8315 yaml_node_t *n = yaml_document_get_node(document, pair->key);
154
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 8315 times.
✓ Branch 3 taken 1652 times.
✓ Branch 4 taken 6663 times.
16630 if (n->type == YAML_SCALAR_NODE
155
2/2
✓ Branch 3 taken 1973 times.
✓ Branch 4 taken 6342 times.
8315 and key.size() == n->data.scalar.length
156
5/8
✓ Branch 0 taken 8315 times.
✗ Branch 1 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1973 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1973 times.
✓ Branch 9 taken 1652 times.
✓ Branch 10 taken 321 times.
12261 and !strncmp((char*)n->data.scalar.value,
157 1973 key.c_str(), n->data.scalar.length)) {
158 1652 return Config(document,
159 3304 yaml_document_get_node(document, pair->value));
160 }
161 }
162
163 1532 return Config();
164 }
165
166 /////////////////////////////////////////////////////////////////////////////
167 68 Config Config::operator[](size_t index) const
168 {
169
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
68 if (!node)
170 return Config();
171
172
3/6
✗ Branch 2 not taken.
✓ Branch 3 taken 68 times.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 44 times.
✗ Branch 7 not taken.
68 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 44 case YAML_SCALAR_NODE:
197
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 22 times.
44 if (index == 0)
198 22 return *this;
199 22 break;
200
201 default:
202 break;
203 }
204
205 28 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 1925 std::string Config::toString(const std::string& defaultString) const
216 {
217
4/6
✓ Branch 1 taken 920 times.
✓ Branch 2 taken 1005 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 920 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 920 times.
1925 if (!node or node->type != YAML_SCALAR_NODE)
218 1005 return defaultString;
219
220
1/2
✓ Branch 7 taken 920 times.
✗ Branch 8 not taken.
920 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 787 unsigned int Config::toUInt(unsigned int dflt) const
250 {
251
1/2
✓ Branch 5 taken 787 times.
✗ Branch 6 not taken.
1574 std::string sval(toString());
252
2/2
✓ Branch 1 taken 412 times.
✓ Branch 2 taken 375 times.
787 if (sval.empty())
253 412 return dflt;
254
255
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 375 times.
375 return strtoul(sval.c_str(), 0, 0);
256 }
257