GCC Code Coverage Report


Directory: ./
File: pdserv-1.1.0/src/Config.cpp
Date: 2024-12-29 04:08:32
Exec Total Coverage
Lines: 8 92 8.7%
Branches: 1 89 1.1%

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 10 Config::Config(): node(0)
40 {
41 10 }
42
43 /////////////////////////////////////////////////////////////////////////////
44 Config::Config(yaml_document_t *d, yaml_node_t *n): document(d), node(n)
45 {
46 }
47
48 /////////////////////////////////////////////////////////////////////////////
49 20 Config::~Config()
50 {
51 10 clear();
52 10 }
53
54 /////////////////////////////////////////////////////////////////////////////
55 10 void Config::clear()
56 {
57
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (!file.empty()) {
58 yaml_document_delete(document);
59 delete document;
60
61 file.clear();
62 }
63 10 }
64
65 /////////////////////////////////////////////////////////////////////////////
66 const char * Config::load(const char *file)
67 {
68 yaml_parser_t parser;
69 FILE *fh;
70
71 /* Initialize parser */
72 if(!yaml_parser_initialize(&parser)) {
73 ::snprintf(error, sizeof(error), "Could not initialize YAML parser");
74 return error;
75 }
76
77 fh = ::fopen(file, "r");
78 if (!fh) {
79 ::snprintf(error, sizeof(error), "Could not open config file %s: %s",
80 file, strerror(errno));
81 return error;
82 }
83
84 /* Set input file */
85 yaml_parser_set_input_file(&parser, fh);
86
87 clear();
88 document = new yaml_document_t;
89 this->file = file;
90
91 /* START new code */
92 if (!yaml_parser_load(&parser, document)) {
93 snprintf(error, sizeof(error), "YAML parser failure at line %zu: %s",
94 parser.problem_mark.line, parser.problem);
95 return error;
96 }
97
98 // Now finished with the file
99 ::fclose(fh);
100
101 node = yaml_document_get_root_node(document);
102
103 return 0;
104 }
105
106 /////////////////////////////////////////////////////////////////////////////
107 Config Config::operator[](const char *key) const
108 {
109 return this->operator[](std::string(key));
110 }
111
112 /////////////////////////////////////////////////////////////////////////////
113 Config::operator bool() const
114 {
115 return node != 0;
116 }
117
118 /////////////////////////////////////////////////////////////////////////////
119 Config Config::operator[](const std::string& key) const
120 {
121 if (!node or node->type != YAML_MAPPING_NODE)
122 return Config();
123
124 for (yaml_node_pair_t *pair = node->data.mapping.pairs.start;
125 pair != node->data.mapping.pairs.top; ++pair) {
126 yaml_node_t *n = yaml_document_get_node(document, pair->key);
127 if (n->type == YAML_SCALAR_NODE
128 and key.size() == n->data.scalar.length
129 and !strncmp((char*)n->data.scalar.value,
130 key.c_str(), n->data.scalar.length)) {
131 return Config(document,
132 yaml_document_get_node(document, pair->value));
133 }
134 }
135
136 return Config();
137 }
138
139 /////////////////////////////////////////////////////////////////////////////
140 Config Config::operator[](size_t index) const
141 {
142 if (!node)
143 return Config();
144
145 switch (node->type) {
146 case YAML_SEQUENCE_NODE:
147 {
148 yaml_node_item_t *n = node->data.sequence.items.start;
149 do {
150 if (!index--)
151 return Config(document,
152 yaml_document_get_node(document, *n));
153 } while (++n != node->data.sequence.items.top);
154 }
155 break;
156
157 case YAML_MAPPING_NODE:
158 {
159 yaml_node_pair_t *pair = node->data.mapping.pairs.start;
160 do {
161 if (!index--)
162 return Config(document,
163 yaml_document_get_node(document,
164 pair->key));
165 } while (++pair != node->data.mapping.pairs.top);
166 }
167 break;
168
169 default:
170 break;
171 }
172
173 return Config();
174 }
175
176 /////////////////////////////////////////////////////////////////////////////
177 std::string Config::toString(const std::string& defaultString) const
178 {
179 if (!node or node->type != YAML_SCALAR_NODE)
180 return defaultString;
181
182 return std::string((char*)node->data.scalar.value, node->data.scalar.length);
183 }
184
185 /////////////////////////////////////////////////////////////////////////////
186 namespace PdServ {
187 template <typename T>
188 bool Config::get(T &value) const
189 {
190 if (!*this)
191 return false;
192
193 value = *this;
194 return true;
195 }
196
197 template bool Config::get(int& value) const;
198 }
199
200 /////////////////////////////////////////////////////////////////////////////
201 int Config::toInt() const
202 {
203 std::string sval(toString());
204 if (sval.empty())
205 return 0;
206
207 return strtol(sval.c_str(), 0, 0);
208 }
209
210 /////////////////////////////////////////////////////////////////////////////
211 unsigned int Config::toUInt() const
212 {
213 std::string sval(toString());
214 if (sval.empty())
215 return 0;
216
217 return strtoul(sval.c_str(), 0, 0);
218 }
219