Directory: | ./ |
---|---|
File: | src/msrproto/DirNode.cpp |
Date: | 2024-11-05 15:23:15 |
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 |