GCC Code Coverage Report


Directory: ./
File: src/msrproto/DirNode.cpp
Date: 2024-03-27 13:09:52
Exec Total Coverage
Lines: 63 79 79.7%
Branches: 90 152 59.2%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * Copyright (C) 2015-2016 Richard Hacker (lerichi at gmx dot net)
4 *
5 * This file is part of the PdCom library.
6 *
7 * The PdCom 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 by
9 * the Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * The PdCom 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 PdCom library. If not, see <http://www.gnu.org/licenses/>.
19 *
20 *****************************************************************************/
21
22 #include "DirNode.h"
23
24 #include "../Debug.h"
25
26 #include <algorithm> // std::copy
27 #include <cstring> // strchr()
28 #include <iterator> // back_inserter
29
30 using namespace PdCom::impl::MsrProto;
31
32 namespace {
33 ///////////////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////////////
35 class DirectoryPathIterator
36 {
37 public:
38 240 DirectoryPathIterator(const char *path) { pathPtr = path; }
39
40 506 std::string next()
41 {
42 506 const char *p = pathPtr;
43
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 506 times.
506 pathPtr = strchr(pathPtr, dirSeparator);
44
12/22
✓ Branch 1 taken 291 times.
✓ Branch 2 taken 215 times.
✓ Branch 8 taken 291 times.
✗ Branch 9 not taken.
✓ Branch 13 taken 215 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 215 times.
✓ Branch 16 taken 291 times.
✓ Branch 18 taken 215 times.
✓ Branch 19 taken 291 times.
✓ Branch 21 taken 291 times.
✓ Branch 22 taken 215 times.
✓ Branch 24 taken 291 times.
✓ Branch 25 taken 215 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
506 return pathPtr ? std::string(p, skip() - p) : p;
45 }
46
47
3/4
✓ Branch 1 taken 449 times.
✓ Branch 2 taken 107 times.
✓ Branch 5 taken 449 times.
✗ Branch 6 not taken.
556 bool hasNext() const { return pathPtr and *pathPtr; }
48
49 private:
50 const char *pathPtr;
51
52 static const char dirSeparator;
53
54 291 const char *skip()
55 {
56 291 const char *p = pathPtr;
57
58
3/4
✓ Branch 2 taken 582 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 291 times.
✓ Branch 7 taken 291 times.
873 while (*pathPtr and *pathPtr == dirSeparator)
59 291 ++pathPtr;
60
61 291 return p;
62 }
63 };
64
65 } // namespace
66 const char DirectoryPathIterator::dirSeparator = '/';
67
68 ///////////////////////////////////////////////////////////////////////////
69 ///////////////////////////////////////////////////////////////////////////
70 133 DirNode::DirNode(bool isDir)
71 {
72 133 m_parent = this;
73 133 directory = isDir;
74 133 }
75
76 ///////////////////////////////////////////////////////////////////////////
77 242 std::string DirNode::path() const
78 {
79
13/24
✓ Branch 3 taken 104 times.
✓ Branch 4 taken 138 times.
✓ Branch 13 taken 138 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 138 times.
✗ Branch 18 not taken.
✓ Branch 22 taken 138 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 138 times.
✓ Branch 25 taken 104 times.
✓ Branch 27 taken 138 times.
✓ Branch 28 taken 104 times.
✓ Branch 30 taken 138 times.
✓ Branch 31 taken 104 times.
✓ Branch 33 taken 138 times.
✓ Branch 34 taken 104 times.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
242 return m_parent == this ? std::string() : (m_parent->path() + '/' + m_name);
80 }
81
82 ///////////////////////////////////////////////////////////////////////////
83 57 void DirNode::insert(std::shared_ptr<DirNode> child, const char *cpath)
84 {
85 57 DirectoryPathIterator path(cpath);
86
1/2
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
114 std::shared_ptr<DirNode> parent = shared_from_this();
87
88
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (!path.hasNext()) {
89 return;
90 }
91
92 while (true) {
93
4/5
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 57 times.
✓ Branch 8 taken 57 times.
138 std::string name = path.next();
94
95
2/2
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 69 times.
183 if (name.empty()) {
96 // Find root node
97
1/2
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
57 parent = getRootNode();
98 57 continue;
99 }
100
101 69 NodeVector::iterator it = std::lower_bound(
102 207 parent->children.begin(), parent->children.end(), name,
103
4/5
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 12 times.
✓ Branch 10 taken 57 times.
✓ Branch 11 taken 57 times.
288 LessThan());
104
105 // Insert a new node if it exists
106
8/10
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 67 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 69 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 69 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 68 times.
✓ Branch 21 taken 1 times.
69 if (it == parent->children.end() or (*it)->m_name != name)
107
1/2
✓ Branch 8 taken 68 times.
✗ Branch 9 not taken.
68 it = parent->children.insert(it, 0);
108 69 std::shared_ptr<DirNode> &node = *it;
109
110
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 57 times.
69 if (path.hasNext()) {
111
2/2
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1 times.
12 if (!node) {
112
2/4
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
11 node.reset(new DirNode);
113 11 node->m_parent = parent.get();
114
1/2
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
11 node->m_name = name;
115 }
116 12 parent = node;
117 }
118 else {
119
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 57 times.
57 if (node) {
120 // Node exists. This can happen, when a deep node has
121 // been discovered before the current node. An example is a
122 // signal that has parameters as children
123 std::swap(node->children, child->children);
124 child->directory = true;
125 for (auto &cchild : child->children)
126 cchild->m_parent = child.get();
127
128 node.reset();
129 }
130
131 57 child->m_parent = parent.get();
132
1/2
✓ Branch 3 taken 57 times.
✗ Branch 4 not taken.
57 child->m_name = name;
133 57 node = std::move(child);
134
135
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 57 times.
57 return;
136 }
137 69 }
138 }
139
140 ///////////////////////////////////////////////////////////////////////////
141 1 std::string DirNode::name() const
142 {
143 1 return m_name;
144 }
145
146 ///////////////////////////////////////////////////////////////////////////
147 183 std::shared_ptr<DirNode> DirNode::find(const std::string &pathStr)
148 {
149
1/2
✓ Branch 2 taken 183 times.
✗ Branch 3 not taken.
366 std::shared_ptr<DirNode> node = shared_from_this();
150 183 DirectoryPathIterator path(pathStr.c_str());
151
152
2/2
✓ Branch 1 taken 380 times.
✓ Branch 2 taken 50 times.
677 while (path.hasNext()) {
153
4/5
✓ Branch 2 taken 380 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 64 times.
✓ Branch 7 taken 183 times.
✓ Branch 8 taken 133 times.
444 std::string name = path.next();
154
155
2/2
✓ Branch 1 taken 183 times.
✓ Branch 2 taken 197 times.
563 if (name.empty()) {
156 // Find root node
157
1/2
✓ Branch 2 taken 183 times.
✗ Branch 3 not taken.
183 node = getRootNode();
158 183 continue;
159 }
160
161 197 NodeVector::iterator it = std::lower_bound(
162
4/5
✓ Branch 8 taken 197 times.
✗ Branch 9 not taken.
✓ Branch 16 taken 64 times.
✓ Branch 17 taken 183 times.
✓ Branch 18 taken 133 times.
261 node->children.begin(), node->children.end(), name, LessThan());
163
164
8/10
✓ Branch 5 taken 67 times.
✓ Branch 6 taken 130 times.
✓ Branch 12 taken 3 times.
✓ Branch 13 taken 64 times.
✓ Branch 14 taken 197 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 197 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 133 times.
✓ Branch 21 taken 64 times.
197 if (it == node->children.end() or name != (*it)->m_name)
165 133 return nullptr;
166
167
2/2
✓ Branch 4 taken 64 times.
✓ Branch 5 taken 133 times.
64 node = *it;
168 }
169
170 50 return node;
171 }
172
173 ///////////////////////////////////////////////////////////////////////////
174 void DirNode::getChildren(List &list) const
175 {
176 for (const auto &child : children)
177 list.push_back(child);
178 }
179
180 ///////////////////////////////////////////////////////////////////////////
181 void DirNode::getAllChildren(List &list) const
182 {
183 for (const auto &child : children) {
184 list.push_back(child);
185 child->getAllChildren(list);
186 }
187 }
188
189 ///////////////////////////////////////////////////////////////////////////
190 bool DirNode::hasChildren() const
191 {
192 return directory or !children.empty();
193 }
194
195 /////////////////////////////////////////////////////////////////////////////
196 240 std::shared_ptr<DirNode> DirNode::getRootNode()
197 {
198 240 DirNode *n = this;
199
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 240 times.
240 while (n->m_parent != n)
200 n = n->m_parent;
201 240 return n->shared_from_this();
202 }
203