ChimeraTK-DeviceAccess  03.18.00
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 
10 namespace ChimeraTK {
11 
16  class RegisterPath {
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(); }
22  RegisterPath(const RegisterPath& _path) : path(_path.path), separator_alt(_path.separator_alt) {
24  }
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 {
94  path = separator;
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 */
ChimeraTK::RegisterPath::removeExtraSeparators
void removeExtraSeparators()
Search for duplicate separators (e.g.
Definition: RegisterPath.h:192
ChimeraTK::RegisterPath::getWithOtherSeparatorReplaced
std::string getWithOtherSeparatorReplaced(const std::string &otherSeparator) const
Return the path after replacing the given otherSeparator with the standard separator "/".
Definition: RegisterPath.h:208
ChimeraTK::RegisterPath::operator--
RegisterPath & operator--()
Cut-left operator, e.g. –registerPath.
Definition: RegisterPath.h:102
ChimeraTK::RegisterPath::operator--
RegisterPath & operator--(int)
Cut-right operator, e.g. registerPath–.
Definition: RegisterPath.h:84
ChimeraTK::RegisterPath::operator==
bool operator==(const std::string &rightHandSide) const
comparison with std::string
Definition: RegisterPath.h:123
ChimeraTK::RegisterPath::operator+
friend RegisterPath operator+(const RegisterPath &leftHandSide, const std::string &rightHandSide)
Definition: RegisterPath.cc:32
ChimeraTK::RegisterPath::operator/=
RegisterPath & operator/=(const std::string &rightHandSide)
/= operator: modify this object by adding a new element to this path
Definition: RegisterPath.h:59
ChimeraTK::RegisterPath::operator*
friend RegisterPath operator*(const RegisterPath &leftHandSide, int rightHandSide)
Definition: RegisterPath.cc:47
ChimeraTK::RegisterPath::setAltSeparator
void setAltSeparator(const std::string &altSeparator)
set alternative separator.
Definition: RegisterPath.h:37
ChimeraTK::RegisterPath::getWithAltSeparator
std::string getWithAltSeparator() const
obtain path with alternative separator character instead of "/".
Definition: RegisterPath.h:48
ChimeraTK::operator*
RegisterPath operator*(const RegisterPath &leftHandSide, int rightHandSide)
Definition: RegisterPath.cc:47
ChimeraTK::operator+
std::string operator+(const std::string &leftHandSide, const RegisterPath &rightHandSide)
non-member + operator for RegisterPath: concatenate with normal strings.
Definition: RegisterPath.cc:26
ChimeraTK::RegisterPath::endsWith
bool endsWith(const RegisterPath &compare) const
check if the register path ends with the given path component(s)
Definition: RegisterPath.h:149
ChimeraTK::RegisterPath::operator=
RegisterPath & operator=(const RegisterPath &_path)=default
ChimeraTK::RegisterPath::operator==
bool operator==(const char *rightHandSide) const
comparison with char*
Definition: RegisterPath.h:126
ChimeraTK::operator/
RegisterPath operator/(const RegisterPath &leftHandSide, const RegisterPath &rightHandSide)
non-member / operator: add a new element to the path.
Definition: RegisterPath.cc:15
ChimeraTK::RegisterPath::RegisterPath
RegisterPath(const std::string &_path)
Definition: RegisterPath.h:21
ChimeraTK::RegisterPath::operator!=
bool operator!=(const char *rightHandSide) const
comparison with char*
Definition: RegisterPath.h:135
ChimeraTK::RegisterPath::operator<<
friend std::ostream & operator<<(std::ostream &os, const RegisterPath &me)
streaming operator
Definition: RegisterPath.cc:56
ChimeraTK::RegisterPath::separator
static const char separator[]
separator character to separate the elements in the path
Definition: RegisterPath.h:185
ChimeraTK::RegisterPath::operator/
friend RegisterPath operator/(const RegisterPath &leftHandSide, const RegisterPath &rightHandSide)
non-member / operator: add a new element to the path.
Definition: RegisterPath.cc:15
ChimeraTK::RegisterPath::getCommonAltSeparator
std::string getCommonAltSeparator(const RegisterPath &otherPath) const
return common alternative separator for this RegisterPath and the specified other RegisterPath object...
Definition: RegisterPath.h:224
ChimeraTK::RegisterPath::startsWith
bool startsWith(const RegisterPath &compare) const
check if the register path starts with the given path
Definition: RegisterPath.h:141
ChimeraTK::RegisterPath::RegisterPath
RegisterPath()
Definition: RegisterPath.h:18
ChimeraTK::RegisterPath::operator<
bool operator<(const RegisterPath &rightHandSide) const
< operator: comparison used for sorting e.g. in std::map
Definition: RegisterPath.h:73
ChimeraTK::RegisterPath::length
size_t length() const
return the length of the path (including leading slash)
Definition: RegisterPath.h:138
ChimeraTK::RegisterPath::operator==
bool operator==(const RegisterPath &rightHandSide) const
comparison with other RegisterPath
Definition: RegisterPath.h:117
ChimeraTK::RegisterPath::RegisterPath
RegisterPath(const char *_path)
Definition: RegisterPath.h:29
ChimeraTK::RegisterPath::RegisterPath
RegisterPath(const RegisterPath &_path)
Definition: RegisterPath.h:22
ChimeraTK::RegisterPath::operator!=
bool operator!=(const std::string &rightHandSide) const
comparison with std::string
Definition: RegisterPath.h:132
ChimeraTK::RegisterPath
Class to store a register path name.
Definition: RegisterPath.h:16
ChimeraTK::RegisterPath::getComponents
std::vector< std::string > getComponents() const
split path into components
Definition: RegisterPath.h:158
ChimeraTK::operator<<
std::ostream & operator<<(std::ostream &stream, const DataDescriptor::FundamentalType &fundamentalType)
Definition: DataDescriptor.cpp:195
ChimeraTK::RegisterPath::operator!=
bool operator!=(const RegisterPath &rightHandSide) const
comparison with other RegisterPath
Definition: RegisterPath.h:129
ChimeraTK::RegisterPath::removeExtraSeparators
static std::string removeExtraSeparators(std::string string, const std::string &sep=separator)
Search for duplicate separators (e.g.
Definition: RegisterPath.h:197
ChimeraTK::RegisterPath::separator_alt
std::string separator_alt
altenative separator character
Definition: RegisterPath.h:188
Exception.h
ChimeraTK
Definition: DummyBackend.h:16
ChimeraTK::RegisterPath::path
std::string path
path in standardised notation
Definition: RegisterPath.h:182
ChimeraTK::RegisterPath::operator+=
RegisterPath & operator+=(const std::string &rightHandSide)
+= operator: just concatenate-assign like normal strings
Definition: RegisterPath.h:66
ChimeraTK::logic_error
Exception thrown when a logic error has occured.
Definition: Exception.h:51