GCC Code Coverage Report


Directory: ./
File: pdcom5/src/msrproto/DirNode.cpp
Date: 2024-12-15 04:08:34
Exec Total Coverage
Lines: 79 81 97.5%
Branches: 104 152 68.4%

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 960 DirectoryPathIterator(const char *path) { pathPtr = path; }
39
40 3202 std::string next()
41 {
42 3202 const char *p = pathPtr;
43
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3202 times.
3202 pathPtr = strchr(pathPtr, dirSeparator);
44
12/22
✓ Branch 1 taken 2451 times.
✓ Branch 2 taken 751 times.
✓ Branch 8 taken 2451 times.
✗ Branch 9 not taken.
✓ Branch 13 taken 751 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 751 times.
✓ Branch 16 taken 2451 times.
✓ Branch 18 taken 751 times.
✓ Branch 19 taken 2451 times.
✓ Branch 21 taken 2451 times.
✓ Branch 22 taken 751 times.
✓ Branch 24 taken 2451 times.
✓ Branch 25 taken 751 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.
3202 return pathPtr ? std::string(p, skip() - p) : p;
45 }
46
47
3/4
✓ Branch 1 taken 2820 times.
✓ Branch 2 taken 474 times.
✓ Branch 5 taken 2820 times.
✗ Branch 6 not taken.
3294 bool hasNext() const { return pathPtr and *pathPtr; }
48
49 private:
50 const char *pathPtr;
51
52 static const char dirSeparator;
53
54 2451 const char *skip()
55 {
56 2451 const char *p = pathPtr;
57
58
3/4
✓ Branch 2 taken 4902 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2451 times.
✓ Branch 7 taken 2451 times.
7353 while (*pathPtr and *pathPtr == dirSeparator)
59 2451 ++pathPtr;
60
61 2451 return p;
62 }
63 };
64
65 } // namespace
66 const char DirectoryPathIterator::dirSeparator = '/';
67
68 ///////////////////////////////////////////////////////////////////////////
69 ///////////////////////////////////////////////////////////////////////////
70 709 DirNode::DirNode(bool isDir)
71 {
72 709 m_parent = this;
73 709 directory = isDir;
74 709 }
75
76 ///////////////////////////////////////////////////////////////////////////
77 1779 std::string DirNode::path() const
78 {
79
13/24
✓ Branch 3 taken 481 times.
✓ Branch 4 taken 1298 times.
✓ Branch 13 taken 1298 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 1298 times.
✗ Branch 18 not taken.
✓ Branch 22 taken 1298 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1298 times.
✓ Branch 25 taken 481 times.
✓ Branch 27 taken 1298 times.
✓ Branch 28 taken 481 times.
✓ Branch 30 taken 1298 times.
✓ Branch 31 taken 481 times.
✓ Branch 33 taken 1298 times.
✓ Branch 34 taken 481 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.
1779 return m_parent == this ? std::string() : (m_parent->path() + '/' + m_name);
80 }
81
82 ///////////////////////////////////////////////////////////////////////////
83 382 void DirNode::insert(std::shared_ptr<DirNode> child, const char *cpath)
84 {
85 382 DirectoryPathIterator path(cpath);
86
1/2
✓ Branch 2 taken 382 times.
✗ Branch 3 not taken.
764 std::shared_ptr<DirNode> parent = shared_from_this();
87
88
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 382 times.
382 if (!path.hasNext()) {
89 return;
90 }
91
92 while (true) {
93
4/5
✓ Branch 2 taken 1436 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 672 times.
✓ Branch 7 taken 382 times.
✓ Branch 8 taken 382 times.
2108 std::string name = path.next();
94
95
2/2
✓ Branch 1 taken 382 times.
✓ Branch 2 taken 1054 times.
1818 if (name.empty()) {
96 // Find root node
97
1/2
✓ Branch 2 taken 382 times.
✗ Branch 3 not taken.
382 parent = getRootNode();
98 382 continue;
99 }
100
101 1054 NodeVector::iterator it = std::lower_bound(
102 3162 parent->children.begin(), parent->children.end(), name,
103
4/5
✓ Branch 4 taken 1054 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 672 times.
✓ Branch 10 taken 382 times.
✓ Branch 11 taken 382 times.
4888 LessThan());
104
105 // Insert a new node if it exists
106
8/10
✓ Branch 5 taken 617 times.
✓ Branch 6 taken 437 times.
✓ Branch 12 taken 113 times.
✓ Branch 13 taken 504 times.
✓ Branch 14 taken 1054 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1054 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 550 times.
✓ Branch 21 taken 504 times.
1054 if (it == parent->children.end() or (*it)->m_name != name)
107
1/2
✓ Branch 8 taken 550 times.
✗ Branch 9 not taken.
550 it = parent->children.insert(it, 0);
108 1054 std::shared_ptr<DirNode> &node = *it;
109
110
2/2
✓ Branch 1 taken 672 times.
✓ Branch 2 taken 382 times.
1054 if (path.hasNext()) {
111
2/2
✓ Branch 2 taken 170 times.
✓ Branch 3 taken 502 times.
672 if (!node) {
112
2/4
✓ Branch 2 taken 170 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 170 times.
✗ Branch 8 not taken.
170 node.reset(new DirNode);
113 170 node->m_parent = parent.get();
114
1/2
✓ Branch 4 taken 170 times.
✗ Branch 5 not taken.
170 node->m_name = name;
115 }
116 672 parent = node;
117 }
118 else {
119
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 380 times.
382 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 2 std::swap(node->children, child->children);
124 2 child->directory = true;
125
2/2
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 2 times.
4 for (auto &cchild : child->children)
126 2 cchild->m_parent = child.get();
127
128 2 node.reset();
129 }
130
131 382 child->m_parent = parent.get();
132
1/2
✓ Branch 3 taken 382 times.
✗ Branch 4 not taken.
382 child->m_name = name;
133 382 node = std::move(child);
134
135
2/2
✓ Branch 1 taken 672 times.
✓ Branch 2 taken 382 times.
382 return;
136 }
137 1054 }
138 }
139
140 ///////////////////////////////////////////////////////////////////////////
141 5 std::string DirNode::name() const
142 {
143 5 return m_name;
144 }
145
146 ///////////////////////////////////////////////////////////////////////////
147 578 std::shared_ptr<DirNode> DirNode::find(const std::string &pathStr)
148 {
149
1/2
✓ Branch 2 taken 578 times.
✗ Branch 3 not taken.
1156 std::shared_ptr<DirNode> node = shared_from_this();
150 578 DirectoryPathIterator path(pathStr.c_str());
151
152
2/2
✓ Branch 1 taken 1766 times.
✓ Branch 2 taken 92 times.
3138 while (path.hasNext()) {
153
4/5
✓ Branch 2 taken 1766 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 702 times.
✓ Branch 7 taken 578 times.
✓ Branch 8 taken 486 times.
2468 std::string name = path.next();
154
155
2/2
✓ Branch 1 taken 578 times.
✓ Branch 2 taken 1188 times.
2344 if (name.empty()) {
156 // Find root node
157
1/2
✓ Branch 2 taken 578 times.
✗ Branch 3 not taken.
578 node = getRootNode();
158 578 continue;
159 }
160
161 1188 NodeVector::iterator it = std::lower_bound(
162
4/5
✓ Branch 8 taken 1188 times.
✗ Branch 9 not taken.
✓ Branch 16 taken 702 times.
✓ Branch 17 taken 578 times.
✓ Branch 18 taken 486 times.
1890 node->children.begin(), node->children.end(), name, LessThan());
163
164
8/10
✓ Branch 5 taken 816 times.
✓ Branch 6 taken 372 times.
✓ Branch 12 taken 114 times.
✓ Branch 13 taken 702 times.
✓ Branch 14 taken 1188 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1188 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 486 times.
✓ Branch 21 taken 702 times.
1188 if (it == node->children.end() or name != (*it)->m_name)
165 486 return nullptr;
166
167
2/2
✓ Branch 4 taken 702 times.
✓ Branch 5 taken 486 times.
702 node = *it;
168 }
169
170 92 return node;
171 }
172
173 ///////////////////////////////////////////////////////////////////////////
174 12 void DirNode::getChildren(List &list) const
175 {
176
2/2
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 12 times.
30 for (const auto &child : children)
177
1/2
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
18 list.push_back(child);
178 12 }
179
180 ///////////////////////////////////////////////////////////////////////////
181 264 void DirNode::getAllChildren(List &list) const
182 {
183
2/2
✓ Branch 6 taken 258 times.
✓ Branch 7 taken 264 times.
522 for (const auto &child : children) {
184
1/2
✓ Branch 3 taken 258 times.
✗ Branch 4 not taken.
258 list.push_back(child);
185
1/2
✓ Branch 6 taken 258 times.
✗ Branch 7 not taken.
258 child->getAllChildren(list);
186 }
187 264 }
188
189 ///////////////////////////////////////////////////////////////////////////
190 18 bool DirNode::hasChildren() const
191 {
192
4/6
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
18 return directory or !children.empty();
193 }
194
195 /////////////////////////////////////////////////////////////////////////////
196 960 std::shared_ptr<DirNode> DirNode::getRootNode()
197 {
198 960 DirNode *n = this;
199
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 960 times.
960 while (n->m_parent != n)
200 n = n->m_parent;
201 960 return n->shared_from_this();
202 }
203