GCC Code Coverage Report


Directory: ./
File: pdserv-1.1.0/src/msrproto/DirectoryNode.cpp
Date: 2024-12-15 04:08:34
Exec Total Coverage
Lines: 1 121 0.8%
Branches: 0 216 0.0%

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