GCC Code Coverage Report


Directory: ./
File: pdserv/src/msrproto/DirectoryNode.cpp
Date: 2024-12-15 04:08:34
Exec Total Coverage
Lines: 104 139 74.8%
Branches: 124 254 48.8%

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