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 |
|
|
|