GCC Code Coverage Report


Directory: ./
File: src/msrproto/DirNode.cpp
Date: 2024-06-11 13:26:06
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 248 DirectoryPathIterator(const char *path) { pathPtr = path; }
39
40 522 std::string next()
41 {
42 522 const char *p = pathPtr;
43
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 522 times.
522 pathPtr = strchr(pathPtr, dirSeparator);
44
12/22
✓ Branch 1 taken 299 times.
✓ Branch 2 taken 223 times.
✓ Branch 8 taken 299 times.
✗ Branch 9 not taken.
✓ Branch 13 taken 223 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 223 times.
✓ Branch 16 taken 299 times.
✓ Branch 18 taken 223 times.
✓ Branch 19 taken 299 times.
✓ Branch 21 taken 299 times.
✓ Branch 22 taken 223 times.
✓ Branch 24 taken 299 times.
✓ Branch 25 taken 223 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.
522 return pathPtr ? std::string(p, skip() - p) : p;
45 }
46
47
3/4
✓ Branch 1 taken 463 times.
✓ Branch 2 taken 111 times.
✓ Branch 5 taken 463 times.
✗ Branch 6 not taken.
574 bool hasNext() const { return pathPtr and *pathPtr; }
48
49 private:
50 const char *pathPtr;
51
52 static const char dirSeparator;
53
54 299 const char *skip()
55 {
56 299 const char *p = pathPtr;
57
58
3/4
✓ Branch 2 taken 598 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 299 times.
✓ Branch 7 taken 299 times.
897 while (*pathPtr and *pathPtr == dirSeparator)
59 299 ++pathPtr;
60
61 299 return p;
62 }
63 };
64
65 } // namespace
66 const char DirectoryPathIterator::dirSeparator = '/';
67
68 ///////////////////////////////////////////////////////////////////////////
69 ///////////////////////////////////////////////////////////////////////////
70 137 DirNode::DirNode(bool isDir)
71 {
72 137 m_parent = this;
73 137 directory = isDir;
74 137 }
75
76 ///////////////////////////////////////////////////////////////////////////
77 258 std::string DirNode::path() const
78 {
79
13/24
✓ Branch 3 taken 112 times.
✓ Branch 4 taken 146 times.
✓ Branch 13 taken 146 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 146 times.
✗ Branch 18 not taken.
✓ Branch 22 taken 146 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 146 times.
✓ Branch 25 taken 112 times.
✓ Branch 27 taken 146 times.
✓ Branch 28 taken 112 times.
✓ Branch 30 taken 146 times.
✓ Branch 31 taken 112 times.
✓ Branch 33 taken 146 times.
✓ Branch 34 taken 112 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.
258 return m_parent == this ? std::string() : (m_parent->path() + '/' + m_name);
80 }
81
82 ///////////////////////////////////////////////////////////////////////////
83 59 void DirNode::insert(std::shared_ptr<DirNode> child, const char *cpath)
84 {
85 59 DirectoryPathIterator path(cpath);
86
1/2
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
118 std::shared_ptr<DirNode> parent = shared_from_this();
87
88
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
59 if (!path.hasNext()) {
89 return;
90 }
91
92 while (true) {
93
4/5
✓ Branch 2 taken 130 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 59 times.
✓ Branch 8 taken 59 times.
142 std::string name = path.next();
94
95
2/2
✓ Branch 1 taken 59 times.
✓ Branch 2 taken 71 times.
189 if (name.empty()) {
96 // Find root node
97
1/2
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
59 parent = getRootNode();
98 59 continue;
99 }
100
101 71 NodeVector::iterator it = std::lower_bound(
102 213 parent->children.begin(), parent->children.end(), name,
103
4/5
✓ Branch 4 taken 71 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 12 times.
✓ Branch 10 taken 59 times.
✓ Branch 11 taken 59 times.
296 LessThan());
104
105 // Insert a new node if it exists
106
8/10
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 69 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 71 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 71 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 70 times.
✓ Branch 21 taken 1 times.
71 if (it == parent->children.end() or (*it)->m_name != name)
107
1/2
✓ Branch 8 taken 70 times.
✗ Branch 9 not taken.
70 it = parent->children.insert(it, 0);
108 71 std::shared_ptr<DirNode> &node = *it;
109
110
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 59 times.
71 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 59 times.
59 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 59 child->m_parent = parent.get();
132
1/2
✓ Branch 3 taken 59 times.
✗ Branch 4 not taken.
59 child->m_name = name;
133 59 node = std::move(child);
134
135
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 59 times.
59 return;
136 }
137 71 }
138 }
139
140 ///////////////////////////////////////////////////////////////////////////
141 1 std::string DirNode::name() const
142 {
143 1 return m_name;
144 }
145
146 ///////////////////////////////////////////////////////////////////////////
147 189 std::shared_ptr<DirNode> DirNode::find(const std::string &pathStr)
148 {
149
1/2
✓ Branch 2 taken 189 times.
✗ Branch 3 not taken.
378 std::shared_ptr<DirNode> node = shared_from_this();
150 189 DirectoryPathIterator path(pathStr.c_str());
151
152
2/2
✓ Branch 1 taken 392 times.
✓ Branch 2 taken 52 times.
699 while (path.hasNext()) {
153
4/5
✓ Branch 2 taken 392 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 66 times.
✓ Branch 7 taken 189 times.
✓ Branch 8 taken 137 times.
458 std::string name = path.next();
154
155
2/2
✓ Branch 1 taken 189 times.
✓ Branch 2 taken 203 times.
581 if (name.empty()) {
156 // Find root node
157
1/2
✓ Branch 2 taken 189 times.
✗ Branch 3 not taken.
189 node = getRootNode();
158 189 continue;
159 }
160
161 203 NodeVector::iterator it = std::lower_bound(
162
4/5
✓ Branch 8 taken 203 times.
✗ Branch 9 not taken.
✓ Branch 16 taken 66 times.
✓ Branch 17 taken 189 times.
✓ Branch 18 taken 137 times.
269 node->children.begin(), node->children.end(), name, LessThan());
163
164
8/10
✓ Branch 5 taken 69 times.
✓ Branch 6 taken 134 times.
✓ Branch 12 taken 3 times.
✓ Branch 13 taken 66 times.
✓ Branch 14 taken 203 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 203 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 137 times.
✓ Branch 21 taken 66 times.
203 if (it == node->children.end() or name != (*it)->m_name)
165 137 return nullptr;
166
167
2/2
✓ Branch 4 taken 66 times.
✓ Branch 5 taken 137 times.
66 node = *it;
168 }
169
170 52 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 248 std::shared_ptr<DirNode> DirNode::getRootNode()
197 {
198 248 DirNode *n = this;
199
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 248 times.
248 while (n->m_parent != n)
200 n = n->m_parent;
201 248 return n->shared_from_this();
202 }
203