ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
RegisterPath.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3#pragma once
4
5#include "Exception.h"
6
7#include <string>
8#include <vector>
9
10namespace ChimeraTK {
11
17 public:
19 // Yes, we want implicit construction. Turn off the linter.
20 // NOLINTNEXTLINE(hicpp-explicit-conversions, google-explicit-constructor)
21 RegisterPath(const std::string& _path) : path(std::string(separator + _path)) { removeExtraSeparators(); }
25 // we can use the default assignment operator but have to declare this because we have an explicit copy constructor
26 RegisterPath& operator=(const RegisterPath& _path) = default;
27 // Yes, we want implicit construction. Turn off the linter.
28 // NOLINTNEXTLINE(hicpp-explicit-conversions, google-explicit-constructor)
29 RegisterPath(const char* _path) : path(std::string(separator) + _path) { removeExtraSeparators(); }
30
32 // This is an implicit conversion operator. Turn off the linter warning to make it explicit.
33 // NOLINTNEXTLINE(hicpp-explicit-conversions, google-explicit-constructor)
34 operator std::string() const { return getWithOtherSeparatorReplaced(separator_alt); }
35
37 void setAltSeparator(const std::string& altSeparator) {
38 if(altSeparator == separator) {
39 separator_alt = "";
40 }
41 else {
42 separator_alt = altSeparator;
43 }
44 }
45
48 [[nodiscard]] std::string getWithAltSeparator() const {
49 if(separator_alt.length() == 0) return path.substr(1);
50 std::size_t pos;
51 std::string path_alt = path.substr(1);
52 while((pos = path_alt.find(std::string(separator))) != std::string::npos) {
53 path_alt.replace(pos, 1, separator_alt);
54 }
55 return removeExtraSeparators(path_alt, separator_alt);
56 }
57
59 RegisterPath& operator/=(const std::string& rightHandSide) {
60 path += std::string(separator) + rightHandSide;
62 return *this;
63 }
64
66 RegisterPath& operator+=(const std::string& rightHandSide) {
67 path += rightHandSide;
69 return *this;
70 }
71
73 bool operator<(const RegisterPath& rightHandSide) const {
74 std::string sepalt = getCommonAltSeparator(rightHandSide);
75 return getWithOtherSeparatorReplaced(sepalt) < rightHandSide.getWithOtherSeparatorReplaced(sepalt);
76 }
77
85 auto found = path.find_last_of(std::string(separator));
86 if(separator_alt.length() != 0) {
87 auto found_alt = path.find_last_of(std::string(separator_alt));
88 if(found_alt != std::string::npos) found = std::max(found, found_alt);
89 }
90 if(found != std::string::npos && found > 0) { // don't find the leading separator...
91 path = path.substr(0, found);
92 }
93 else {
95 }
96 return *this;
97 }
98
103 std::size_t found = path.find_first_of(std::string(separator), 1); // don't find the leading separator...
104 if(separator_alt.length() != 0) {
105 found = std::min(found, path.find_first_of(std::string(separator_alt)));
106 }
107 if(found != std::string::npos) {
108 path = std::string(separator) + path.substr(found + 1);
109 }
110 else {
111 path = separator;
112 }
113 return *this;
114 }
115
117 bool operator==(const RegisterPath& rightHandSide) const {
118 std::string sepalt = getCommonAltSeparator(rightHandSide);
119 return getWithOtherSeparatorReplaced(sepalt) == rightHandSide.getWithOtherSeparatorReplaced(sepalt);
120 }
121
123 bool operator==(const std::string& rightHandSide) const { return operator==(RegisterPath(rightHandSide)); }
124
126 bool operator==(const char* rightHandSide) const { return operator==(RegisterPath(rightHandSide)); }
127
129 bool operator!=(const RegisterPath& rightHandSide) const { return !operator==(rightHandSide); }
130
132 bool operator!=(const std::string& rightHandSide) const { return operator!=(RegisterPath(rightHandSide)); }
133
135 bool operator!=(const char* rightHandSide) const { return operator!=(RegisterPath(rightHandSide)); }
136
138 [[nodiscard]] size_t length() const { return path.length(); }
139
141 [[nodiscard]] bool startsWith(const RegisterPath& compare) const {
142 std::string sepalt = getCommonAltSeparator(compare);
143 std::string pathConverted(getWithOtherSeparatorReplaced(sepalt));
144 std::string otherPathConverted(compare.getWithOtherSeparatorReplaced(sepalt));
145 return pathConverted.substr(0, compare.length()) == otherPathConverted;
146 }
147
149 [[nodiscard]] bool endsWith(const RegisterPath& compare) const {
150 std::string sepalt = getCommonAltSeparator(compare);
151 std::string pathConverted(getWithOtherSeparatorReplaced(sepalt));
152 std::string otherPathConverted(compare.getWithOtherSeparatorReplaced(sepalt));
153 if(pathConverted.size() < compare.length()) return false;
154 return pathConverted.substr(pathConverted.size() - compare.length()) == otherPathConverted;
155 }
156
158 [[nodiscard]] std::vector<std::string> getComponents() const {
159 std::vector<std::string> components;
160 if(path.length() <= 1) return components;
161 size_t pos = 0;
162 while(pos != std::string::npos) {
163 size_t npos = path.find_first_of(separator, pos + 1);
164 if(separator_alt.length() != 0) {
165 size_t npos_alt = path.find_first_of(separator_alt, pos + 1);
166 if(npos_alt != std::string::npos && npos_alt < npos) npos = npos_alt;
167 }
168 components.push_back(path.substr(pos + 1, npos - pos - 1));
169 pos = npos;
170 }
171 return components;
172 }
173
174 friend RegisterPath operator/(const RegisterPath& leftHandSide, const RegisterPath& rightHandSide);
175 friend RegisterPath operator+(const RegisterPath& leftHandSide, const std::string& rightHandSide);
176 friend RegisterPath operator/(const RegisterPath& leftHandSide, int rightHandSide);
177 friend RegisterPath operator*(const RegisterPath& leftHandSide, int rightHandSide);
178 friend std::ostream& operator<<(std::ostream& os, const RegisterPath& me);
179
180 protected:
182 std::string path;
183
185 static const char separator[];
186
188 std::string separator_alt;
189
193
197 [[nodiscard]] static std::string removeExtraSeparators(std::string string, const std::string& sep = separator) {
198 std::size_t pos;
199 while((pos = string.find(std::string(sep) + sep)) != std::string::npos) {
200 string.erase(pos, 1);
201 }
202 if(string.length() > 1 && string.substr(string.length() - 1, 1) == sep) string.erase(string.length() - 1, 1);
203 return string;
204 }
205
208 [[nodiscard]] std::string getWithOtherSeparatorReplaced(const std::string& otherSeparator) const {
209 // no replacement needed, of other separator is empty
210 if(otherSeparator.length() == 0) return path;
211 // replace all occurrences of otherSeparator with separator
212 std::string path_other = path;
213 size_t pos = 0;
214 while((pos = path_other.find(otherSeparator)) != std::string::npos) {
215 path_other.replace(pos, 1, std::string(separator));
216 }
217 // replace duplicate separators and remove one of them. Also remove a
218 // trailing separator, if present.
219 return removeExtraSeparators(path_other);
220 }
221
224 [[nodiscard]] std::string getCommonAltSeparator(const RegisterPath& otherPath) const {
225 std::string sepalt = separator_alt;
226 if(otherPath.separator_alt.length() > 0) {
227 if(sepalt.length() == 0) {
228 sepalt = otherPath.separator_alt;
229 }
230 else {
231 if(sepalt != otherPath.separator_alt) {
232 throw ChimeraTK::logic_error("RegisterPath objects do not compare "
233 "when both have different alternative "
234 "separators set.");
235 }
236 }
237 }
238 return sepalt;
239 }
240 };
241
245 RegisterPath operator/(const RegisterPath& leftHandSide, const RegisterPath& rightHandSide);
246
248 std::string operator+(const std::string& leftHandSide, const RegisterPath& rightHandSide);
249 RegisterPath operator+(const RegisterPath& leftHandSide, const std::string& rightHandSide);
250
252 RegisterPath operator/(const RegisterPath& leftHandSide, int rightHandSide);
253 RegisterPath operator*(const RegisterPath& leftHandSide, int rightHandSide);
254
256 std::ostream& operator<<(std::ostream& os, const RegisterPath& me);
257
258} /* namespace ChimeraTK */
Class to store a register path name.
RegisterPath(const char *_path)
RegisterPath & operator--(int)
Cut-right operator, e.g. registerPath--.
bool endsWith(const RegisterPath &compare) const
check if the register path ends with the given path component(s)
friend RegisterPath operator/(const RegisterPath &leftHandSide, const RegisterPath &rightHandSide)
non-member / operator: add a new element to the path.
bool operator!=(const char *rightHandSide) const
comparison with char*
bool operator==(const RegisterPath &rightHandSide) const
comparison with other RegisterPath
std::vector< std::string > getComponents() const
split path into components
static std::string removeExtraSeparators(std::string string, const std::string &sep=separator)
Search for duplicate separators (e.g.
std::string path
path in standardised notation
RegisterPath & operator--()
Cut-left operator, e.g. --registerPath.
std::string getWithOtherSeparatorReplaced(const std::string &otherSeparator) const
Return the path after replacing the given otherSeparator with the standard separator "/".
bool operator==(const std::string &rightHandSide) const
comparison with std::string
bool operator==(const char *rightHandSide) const
comparison with char*
bool startsWith(const RegisterPath &compare) const
check if the register path starts with the given path
RegisterPath & operator+=(const std::string &rightHandSide)
+= operator: just concatenate-assign like normal strings
RegisterPath(const RegisterPath &_path)
static const char separator[]
separator character to separate the elements in the path
std::string getWithAltSeparator() const
obtain path with alternative separator character instead of "/".
void setAltSeparator(const std::string &altSeparator)
set alternative separator.
RegisterPath & operator=(const RegisterPath &_path)=default
bool operator!=(const RegisterPath &rightHandSide) const
comparison with other RegisterPath
std::string getCommonAltSeparator(const RegisterPath &otherPath) const
return common alternative separator for this RegisterPath and the specified other RegisterPath object...
operator std::string() const
type conversion operators into std::string
friend RegisterPath operator*(const RegisterPath &leftHandSide, int rightHandSide)
bool operator!=(const std::string &rightHandSide) const
comparison with std::string
RegisterPath & operator/=(const std::string &rightHandSide)
/= operator: modify this object by adding a new element to this path
RegisterPath(const std::string &_path)
bool operator<(const RegisterPath &rightHandSide) const
< operator: comparison used for sorting e.g. in std::map
size_t length() const
return the length of the path (including leading slash)
void removeExtraSeparators()
Search for duplicate separators (e.g.
friend std::ostream & operator<<(std::ostream &os, const RegisterPath &me)
streaming operator
friend RegisterPath operator+(const RegisterPath &leftHandSide, const std::string &rightHandSide)
std::string separator_alt
altenative separator character
Exception thrown when a logic error has occured.
Definition Exception.h:51
std::string operator+(const std::string &leftHandSide, const RegisterPath &rightHandSide)
non-member + operator for RegisterPath: concatenate with normal strings.
RegisterPath operator/(const RegisterPath &leftHandSide, const RegisterPath &rightHandSide)
non-member / operator: add a new element to the path.
std::ostream & operator<<(std::ostream &stream, const DataDescriptor::FundamentalType &fundamentalType)
RegisterPath operator*(const RegisterPath &leftHandSide, int rightHandSide)
STL namespace.