GCC Code Coverage Report


Directory: ./
File: pdserv/src/msrproto/DirectoryNode.cpp
Date: 2025-08-17 04:10:43
Exec Total Coverage
Lines: 104 139 74.8%
Branches: 124 254 48.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 "config.h"
23
24 #include "DirectoryNode.h"
25 #include "HyperDirNode.h"
26 #include "XmlElement.h"
27 #include "Parameter.h"
28 #include "Channel.h"
29 #include "XmlParser.h"
30 #include "../Debug.h"
31 #include "../Parameter.h"
32
33 #include <locale>
34 #include <sstream>
35 #include <iostream>
36
37 using namespace MsrProto;
38
39 /////////////////////////////////////////////////////////////////////////////
40 /////////////////////////////////////////////////////////////////////////////
41 6776 DirectoryNode::DirectoryNode(DirectoryNode* parent, const std::string& name):
42 6776 parent(this)
43 {
44
2/2
✓ Branch 0 taken 1386 times.
✓ Branch 1 taken 5390 times.
6776 if (parent)
45
1/2
✓ Branch 4 taken 1386 times.
✗ Branch 5 not taken.
1386 parent->adopt(this, name);
46 6776 }
47
48 /////////////////////////////////////////////////////////////////////////////
49 14938 DirectoryNode::~DirectoryNode()
50 {
51 13398 for (ChildMap::iterator it = children.begin();
52
2/2
✓ Branch 6 taken 6622 times.
✓ Branch 7 taken 6776 times.
13398 it != children.end(); ++it)
53
1/2
✓ Branch 2 taken 6622 times.
✗ Branch 3 not taken.
6622 delete it->second;
54 8162 }
55
56 /////////////////////////////////////////////////////////////////////////////
57 8316 DirectoryNode* DirectoryNode::create(const std::string& name)
58 {
59 8316 DirectoryNode* dir = children[name];
60
3/4
✓ Branch 0 taken 1386 times.
✓ Branch 1 taken 6930 times.
✓ Branch 5 taken 1386 times.
✗ Branch 6 not taken.
8316 return dir ? dir : new DirectoryNode(this, name);
61 }
62
63 /////////////////////////////////////////////////////////////////////////////
64 5236 void DirectoryNode::insert(DirectoryNode* node, const std::string& name)
65 {
66 5236 DirectoryNode* dir = children[name];
67
68 // log_debug("%s %p", name.c_str(), dir);
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5236 times.
5236 if (dir)
70 dir->insertLeaf(node);
71 else
72 5236 adopt(node, name);
73 5236 }
74
75 /////////////////////////////////////////////////////////////////////////////
76 4004 void DirectoryNode::traditionalPathInsert(Variable* var,
77 const std::string& path, char& hidden, char& persistent)
78 {
79
1/2
✓ Branch 2 taken 4004 times.
✗ Branch 3 not taken.
8008 DirQ dirQ;
80 4004 size_t pos = 0;
81
82 4004 hidden = 0;
83
2/2
✓ Branch 0 taken 15708 times.
✓ Branch 1 taken 4004 times.
35420 while (pos != path.npos) {
84
85
3/4
✓ Branch 2 taken 15708 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 11704 times.
✓ Branch 6 taken 4004 times.
27412 std::string name = split(path, pos);
86
2/2
✓ Branch 1 taken 4004 times.
✓ Branch 2 taken 11704 times.
15708 if (name.empty())
87 4004 continue;
88
89 11704 size_t nameEnd = name.find('<');
90
91
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11704 times.
11704 if (nameEnd != name.npos) {
92 std::stringbuf buf(name);
93 XmlParser parser;
94 parser.read(&buf);
95
96 if (parser) {
97 const char *value;
98 if (parser.isTrue("hide"))
99 hidden = 1;
100 else if (parser.find("hide", &value))
101 hidden = *value;
102
103 if (parser.isTrue("unhide"))
104 hidden = 0;
105
106 if (parser.find("persistent"))
107 persistent = parser.isTrue("persistent");
108
109 while (nameEnd
110 and std::isspace(name[nameEnd-1],
111 std::locale::classic()))
112 nameEnd--;
113 }
114 else
115 nameEnd = name.npos;
116 }
117
118
3/6
✓ Branch 1 taken 11704 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 11704 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11704 times.
11704 if (name.empty() or !nameEnd)
119 continue;
120
121
4/6
✓ Branch 2 taken 11704 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 11704 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 11704 times.
✓ Branch 12 taken 4004 times.
11704 dirQ.push(std::string(name, 0, nameEnd));
122 }
123
124
1/2
✓ Branch 4 taken 4004 times.
✗ Branch 5 not taken.
4004 insert(var, dirQ);
125 4004 }
126
127 /////////////////////////////////////////////////////////////////////////////
128 11704 void DirectoryNode::insert(Variable* var, DirQ& dirQ)
129 {
130
2/4
✓ Branch 3 taken 11704 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 11704 times.
✗ Branch 8 not taken.
23408 std::string name = dirQ.front();
131
1/2
✓ Branch 2 taken 11704 times.
✗ Branch 3 not taken.
11704 dirQ.pop();
132
133
2/2
✓ Branch 2 taken 4004 times.
✓ Branch 3 taken 7700 times.
11704 if (dirQ.empty())
134
1/2
✓ Branch 4 taken 4004 times.
✗ Branch 5 not taken.
4004 return insert(var, name);
135
136
2/4
✓ Branch 4 taken 7700 times.
✗ Branch 5 not taken.
✓ Branch 10 taken 7700 times.
✗ Branch 11 not taken.
7700 return create(name)->insert(var, dirQ);
137 }
138
139
140 /////////////////////////////////////////////////////////////////////////////
141 void DirectoryNode::pathInsert(Variable* var, const std::string& path)
142 {
143 DirQ dirQ;
144 size_t pos = 0;
145
146 while (pos != path.npos) {
147
148 std::string name = split(path, pos);
149 if (!name.empty())
150 dirQ.push(name);
151 }
152
153 insert(var, dirQ);
154 }
155
156 /////////////////////////////////////////////////////////////////////////////
157 16104 std::string DirectoryNode::split(const std::string& path, size_t& pos)
158 {
159 // Find path separator
160 16104 size_t slash = path.find('/', pos);
161
162 16104 const size_t begin = pos;
163
164 // Place pos to point just after the next '/'
165 16104 pos = slash;
166
4/6
✓ Branch 3 taken 11910 times.
✓ Branch 4 taken 4194 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 11910 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 16104 times.
16104 while (pos < path.size() and path[++pos] == '/');
167
168 16104 return std::string(path, begin, slash - begin);
169 }
170
171 /////////////////////////////////////////////////////////////////////////////
172 void DirectoryNode::insertLeaf (DirectoryNode *node)
173 {
174 // This is a normal directory node. Insert a HyperDirNode to cope with
175 // nodes that have the same name
176 HyperDirNode *dir = new HyperDirNode(parent, name);
177 dir->insertLeaf(this);
178 dir->insertLeaf(node);
179 }
180
181 /////////////////////////////////////////////////////////////////////////////
182 6622 void DirectoryNode::adopt (DirectoryNode *child, const std::string& name)
183 {
184 // log_debug("%s %p", name.c_str(), child);
185
186 6622 children[name] = child;
187 6622 child->rename(&children.find(name)->first, this);
188 6622 }
189
190 /////////////////////////////////////////////////////////////////////////////
191 1137 bool DirectoryNode::isRoot() const
192 {
193 1137 return parent == this;
194 }
195
196 /////////////////////////////////////////////////////////////////////////////
197 6622 void DirectoryNode::rename (const std::string* name, DirectoryNode *parent)
198 {
199 6622 this->parent = parent;
200 6622 this->name = name;
201 6622 }
202
203 /////////////////////////////////////////////////////////////////////////////
204 30 void DirectoryNode::list( PdServ::Session *session, XmlElement& parent,
205 const std::string& path, size_t pos, bool hex, bool derived) const
206 {
207
2/2
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 20 times.
40 std::string name;
208
2/2
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 20 times.
40 ChildMap::const_iterator it;
209
210
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 if (pos != path.npos) {
211 10 do {
212
1/2
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
30 name = split(path, pos);
213
5/6
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 20 times.
30 } while (name.empty() and pos != name.npos);
214
215
1/2
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 it = children.find(name);
216
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 if (!name.empty()) {
217
1/2
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
20 if (it != children.end())
218
1/2
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
20 it->second->list(session, parent, path, pos, hex, derived);
219 20 return;
220 }
221 }
222
223
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 const Variable *var = dynamic_cast<const Variable *>(this);
224
4/4
✓ Branch 12 taken 15 times.
✓ Branch 13 taken 10 times.
✓ Branch 16 taken 10 times.
✓ Branch 17 taken 20 times.
25 for (it = children.begin(); it != children.end(); ++it) {
225 15 const DirectoryNode* node = it->second;
226
227
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 const Parameter *param = dynamic_cast<const Parameter *>(node);
228
4/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
15 if (param and !param->hidden
229
2/6
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
5 and (derived or (!var or var->variable != param->variable))) {
230
1/2
✗ Branch 12 not taken.
✓ Branch 13 taken 5 times.
5 char buf[param->mainParam->memSize];
231 5 struct timespec ts;
232
233
1/2
✓ Branch 24 taken 5 times.
✗ Branch 25 not taken.
5 param->mainParam->getValue(session, buf, &ts);
234
235
1/2
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
10 XmlElement xml(parent.createChild("parameter"));
236
1/2
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
10 param->setXmlAttributes(xml, buf, ts, 0, hex, derived, 16);
237 }
238
239
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 const Channel *chan = dynamic_cast<const Channel *>(node);
240
4/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
15 if (chan and !chan->hidden
241
2/6
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
5 and (derived or (!var or var->variable != chan->variable))) {
242
1/2
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
10 XmlElement xml(parent.createChild("channel"));
243
1/2
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
5 chan->setXmlAttributes(xml, 0, hex, derived, 0, 0, 0);
244 }
245
246 // If there are children, report this node as a directory
247
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 10 times.
25 if (!chan and !param
248
5/8
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
20 and (derived or node->hasChildren(var))) {
249
1/2
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
10 XmlElement el(parent.createChild("dir"));
250
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
10 XmlElement::Attribute(el, "path")
251
4/8
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 17 not taken.
✓ Branch 20 taken 5 times.
✗ Branch 21 not taken.
10 .setEscaped(this->path() + '/' + it->first);
252 }
253 }
254 }
255
256 /////////////////////////////////////////////////////////////////////////////
257 231 bool DirectoryNode::hasChildren(const Variable* var) const
258 {
259
4/4
✓ Branch 4 taken 221 times.
✓ Branch 5 taken 10 times.
✓ Branch 7 taken 221 times.
✓ Branch 8 taken 10 times.
419 for (ChildMap::const_iterator it = children.begin();
260
2/2
✓ Branch 6 taken 198 times.
✓ Branch 7 taken 221 times.
419 it != children.end(); ++it)
261
3/4
✓ Branch 8 taken 198 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 10 times.
✓ Branch 11 taken 188 times.
198 if (it->second->hasChildren(var))
262 10 return true;
263
264 221 return false;
265 }
266
267 /////////////////////////////////////////////////////////////////////////////
268 1137 std::string DirectoryNode::path() const
269 {
270 // log_debug("this=%p parent=%p", this, parent);
271
13/24
✓ Branch 4 taken 316 times.
✓ Branch 5 taken 821 times.
✓ Branch 20 taken 821 times.
✗ Branch 21 not taken.
✓ Branch 24 taken 821 times.
✗ Branch 25 not taken.
✓ Branch 29 taken 821 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 821 times.
✓ Branch 32 taken 316 times.
✓ Branch 34 taken 821 times.
✓ Branch 35 taken 316 times.
✓ Branch 37 taken 821 times.
✓ Branch 38 taken 316 times.
✓ Branch 40 taken 821 times.
✓ Branch 41 taken 316 times.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
1137 return isRoot() ? std::string() : parent->path() + '/' + *name;
272 }
273
274 /////////////////////////////////////////////////////////////////////////////
275 366 const DirectoryNode *DirectoryNode::find(
276 const std::string& path, size_t pos) const
277 {
278
1/2
✓ Branch 2 taken 366 times.
✗ Branch 3 not taken.
732 std::string name = split(path, pos);
279
280
1/2
✓ Branch 2 taken 366 times.
✗ Branch 3 not taken.
732 ChildMap::const_iterator it = children.find(name);
281
2/2
✓ Branch 6 taken 16 times.
✓ Branch 7 taken 350 times.
366 if (it == children.end())
282 16 return 0;
283
284 350 return pos < path.size()
285
3/4
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 166 times.
✓ Branch 8 taken 184 times.
✗ Branch 9 not taken.
516 ? it->second->find(path, pos)
286 516 : it->second;
287 }
288
289 /////////////////////////////////////////////////////////////////////////////
290 void DirectoryNode::dump() const
291 {
292 // log_debug("%s", path().c_str());
293 for (ChildMap::const_iterator it = children.begin();
294 it != children.end(); ++it) {
295 it->second->dump();
296 }
297 9 }
298