GCC Code Coverage Report


Directory: ./
File: pdcom5/src/msrproto/DirNode.cpp
Date: 2023-11-12 04:06:57
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 824 DirectoryPathIterator(const char *path) { pathPtr = path; }
39
40 2840 std::string next()
41 {
42 2840 const char *p = pathPtr;
43
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2840 times.
2840 pathPtr = strchr(pathPtr, dirSeparator);
44
12/22
✓ Branch 1 taken 2179 times.
✓ Branch 2 taken 661 times.
✓ Branch 8 taken 2179 times.
✗ Branch 9 not taken.
✓ Branch 13 taken 661 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 661 times.
✓ Branch 16 taken 2179 times.
✓ Branch 18 taken 661 times.
✓ Branch 19 taken 2179 times.
✓ Branch 21 taken 2179 times.
✓ Branch 22 taken 661 times.
✓ Branch 24 taken 2179 times.
✓ Branch 25 taken 661 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.
2840 return pathPtr ? std::string(p, skip() - p) : p;
45 }
46
47
3/4
✓ Branch 1 taken 2504 times.
✓ Branch 2 taken 414 times.
✓ Branch 5 taken 2504 times.
✗ Branch 6 not taken.
2918 bool hasNext() const { return pathPtr and *pathPtr; }
48
49 private:
50 const char *pathPtr;
51
52 static const char dirSeparator;
53
54 2179 const char *skip()
55 {
56 2179 const char *p = pathPtr;
57
58
3/4
✓ Branch 2 taken 4358 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2179 times.
✓ Branch 7 taken 2179 times.
6537 while (*pathPtr and *pathPtr == dirSeparator)
59 2179 ++pathPtr;
60
61 2179 return p;
62 }
63 };
64
65 } // namespace
66 const char DirectoryPathIterator::dirSeparator = '/';
67
68 ///////////////////////////////////////////////////////////////////////////
69 ///////////////////////////////////////////////////////////////////////////
70 615 DirNode::DirNode(bool isDir)
71 {
72 615 m_parent = this;
73 615 directory = isDir;
74 615 }
75
76 ///////////////////////////////////////////////////////////////////////////
77 1647 std::string DirNode::path() const
78 {
79
13/24
✓ Branch 3 taken 437 times.
✓ Branch 4 taken 1210 times.
✓ Branch 13 taken 1210 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 1210 times.
✗ Branch 18 not taken.
✓ Branch 22 taken 1210 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1210 times.
✓ Branch 25 taken 437 times.
✓ Branch 27 taken 1210 times.
✓ Branch 28 taken 437 times.
✓ Branch 30 taken 1210 times.
✓ Branch 31 taken 437 times.
✓ Branch 33 taken 1210 times.
✓ Branch 34 taken 437 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.
1647 return m_parent == this ? std::string() : (m_parent->path() + '/' + m_name);
80 }
81
82 ///////////////////////////////////////////////////////////////////////////
83 336 void DirNode::insert(std::shared_ptr<DirNode> child, const char *cpath)
84 {
85 336 DirectoryPathIterator path(cpath);
86
1/2
✓ Branch 2 taken 336 times.
✗ Branch 3 not taken.
672 std::shared_ptr<DirNode> parent = shared_from_this();
87
88
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 336 times.
336 if (!path.hasNext()) {
89 return;
90 }
91
92 while (true) {
93
4/5
✓ Branch 2 taken 1298 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 626 times.
✓ Branch 7 taken 336 times.
✓ Branch 8 taken 336 times.
1924 std::string name = path.next();
94
95
2/2
✓ Branch 1 taken 336 times.
✓ Branch 2 taken 962 times.
1634 if (name.empty()) {
96 // Find root node
97
1/2
✓ Branch 2 taken 336 times.
✗ Branch 3 not taken.
336 parent = getRootNode();
98 336 continue;
99 }
100
101 962 NodeVector::iterator it = std::lower_bound(
102 2886 parent->children.begin(), parent->children.end(), name,
103
4/5
✓ Branch 4 taken 962 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 626 times.
✓ Branch 10 taken 336 times.
✓ Branch 11 taken 336 times.
4474 LessThan());
104
105 // Insert a new node if it exists
106
8/10
✓ Branch 5 taken 587 times.
✓ Branch 6 taken 375 times.
✓ Branch 12 taken 106 times.
✓ Branch 13 taken 481 times.
✓ Branch 14 taken 962 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 962 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 481 times.
✓ Branch 21 taken 481 times.
962 if (it == parent->children.end() or (*it)->m_name != name)
107
1/2
✓ Branch 8 taken 481 times.
✗ Branch 9 not taken.
481 it = parent->children.insert(it, 0);
108 962 std::shared_ptr<DirNode> &node = *it;
109
110
2/2
✓ Branch 1 taken 626 times.
✓ Branch 2 taken 336 times.
962 if (path.hasNext()) {
111
2/2
✓ Branch 2 taken 147 times.
✓ Branch 3 taken 479 times.
626 if (!node) {
112
2/4
✓ Branch 2 taken 147 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 147 times.
✗ Branch 8 not taken.
147 node.reset(new DirNode);
113 147 node->m_parent = parent.get();
114
1/2
✓ Branch 4 taken 147 times.
✗ Branch 5 not taken.
147 node->m_name = name;
115 }
116 626 parent = node;
117 }
118 else {
119
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 334 times.
336 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 336 child->m_parent = parent.get();
132
1/2
✓ Branch 3 taken 336 times.
✗ Branch 4 not taken.
336 child->m_name = name;
133 336 node = std::move(child);
134
135
2/2
✓ Branch 1 taken 626 times.
✓ Branch 2 taken 336 times.
336 return;
136 }
137 962 }
138 }
139
140 ///////////////////////////////////////////////////////////////////////////
141 5 std::string DirNode::name() const
142 {
143 5 return m_name;
144 }
145
146 ///////////////////////////////////////////////////////////////////////////
147 488 std::shared_ptr<DirNode> DirNode::find(const std::string &pathStr)
148 {
149
1/2
✓ Branch 2 taken 488 times.
✗ Branch 3 not taken.
976 std::shared_ptr<DirNode> node = shared_from_this();
150 488 DirectoryPathIterator path(pathStr.c_str());
151
152
2/2
✓ Branch 1 taken 1542 times.
✓ Branch 2 taken 78 times.
2752 while (path.hasNext()) {
153
4/5
✓ Branch 2 taken 1542 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 644 times.
✓ Branch 7 taken 488 times.
✓ Branch 8 taken 410 times.
2186 std::string name = path.next();
154
155
2/2
✓ Branch 1 taken 488 times.
✓ Branch 2 taken 1054 times.
2030 if (name.empty()) {
156 // Find root node
157
1/2
✓ Branch 2 taken 488 times.
✗ Branch 3 not taken.
488 node = getRootNode();
158 488 continue;
159 }
160
161 1054 NodeVector::iterator it = std::lower_bound(
162
4/5
✓ Branch 8 taken 1054 times.
✗ Branch 9 not taken.
✓ Branch 16 taken 644 times.
✓ Branch 17 taken 488 times.
✓ Branch 18 taken 410 times.
1698 node->children.begin(), node->children.end(), name, LessThan());
163
164
8/10
✓ Branch 5 taken 752 times.
✓ Branch 6 taken 302 times.
✓ Branch 12 taken 108 times.
✓ Branch 13 taken 644 times.
✓ Branch 14 taken 1054 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1054 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 410 times.
✓ Branch 21 taken 644 times.
1054 if (it == node->children.end() or name != (*it)->m_name)
165 410 return nullptr;
166
167
2/2
✓ Branch 4 taken 644 times.
✓ Branch 5 taken 410 times.
644 node = *it;
168 }
169
170 78 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 252 void DirNode::getAllChildren(List &list) const
182 {
183
2/2
✓ Branch 6 taken 246 times.
✓ Branch 7 taken 252 times.
498 for (const auto &child : children) {
184
1/2
✓ Branch 3 taken 246 times.
✗ Branch 4 not taken.
246 list.push_back(child);
185
1/2
✓ Branch 6 taken 246 times.
✗ Branch 7 not taken.
246 child->getAllChildren(list);
186 }
187 252 }
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 824 std::shared_ptr<DirNode> DirNode::getRootNode()
197 {
198 824 DirNode *n = this;
199
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 824 times.
824 while (n->m_parent != n)
200 n = n->m_parent;
201 824 return n->shared_from_this();
202 }
203