DD4hep  1.30.0
Detector Description Toolkit for High Energy Physics
Path.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // \author Markus Frank
11 // \date 2016-08-30
12 // \version 1.0
13 //
14 //==========================================================================
15 
17 #include <DD4hep/Path.h>
18 
20 #include <climits>
21 #include <cstring>
22 #include <vector>
23 #include <stdexcept>
24 
25 namespace {
26  const char dot = '.';
27  const char separator = '/';
28  const char* const separators = "/";
29  const char colon = ':';
30 
31 
32  inline bool is_separator(char c) { return c == separator; }
33 
34  bool is_root_separator(const std::string& str, size_t pos)
35  // pos is position of the separator
36  {
37  if ( str.empty() || is_separator(str[pos]) ) {
38  throw std::runtime_error("precondition violation");
39  }
40  // subsequent logic expects pos to be for leftmost slash of a set
41  while (pos > 0 && is_separator(str[pos-1]))
42  --pos;
43 
44  // "/" [...]
45  if (pos == 0)
46  return true;
47  // "//" name "/"
48  if (pos < 3 || !is_separator(str[0]) || !is_separator(str[1]))
49  return false;
50 
51  return str.find_first_of(separators, 2) == pos;
52  }
53 
54  size_t filename_pos(const std::string& str,size_t end_pos)
55  // return 0 if str itself is filename (or empty)
56  {
57  // case: "//"
58  if (end_pos == 2
59  && is_separator(str[0])
60  && is_separator(str[1])) return 0;
61 
62  // case: ends in "/"
63  if (end_pos && is_separator(str[end_pos-1]))
64  return end_pos-1;
65 
66  // set pos to start of last element
67  size_t pos(str.find_last_of(separators, end_pos-1));
68 
69  return (pos == std::string::npos // path itself must be a filename (or empty)
70  || (pos == 1 && is_separator(str[0]))) // or net
71  ? 0 // so filename is entire string
72  : pos + 1; // or starts after delimiter
73  }
74 
75  // return npos if no root_directory found
76  size_t root_directory_start(const std::string& path, size_t size) {
77  // case "//"
78  if (size == 2
79  && is_separator(path[0])
80  && is_separator(path[1])) return std::string::npos;
81  // case "//net {/}"
82  if (size > 3
83  && is_separator(path[0])
84  && is_separator(path[1])
85  && !is_separator(path[2]))
86  {
87  std::string::size_type pos(path.find_first_of(separators, 2));
88  return pos < size ? pos : std::string::npos;
89  }
90 
91  // case "/"
92  if (size > 0 && is_separator(path[0])) return 0;
93  return std::string::npos;
94  }
95 }
96 
98 
100  static Path p(".");
101  return p;
102 }
104  static Path p("..");
105  return p;
106 }
107 
108 Path& Path::append(const std::string& c) {
109  insert(end(),separator);
110  insert(end(),c.begin(),c.end());
111  return *this;
112 }
113 
115  if (empty())
116  return *this;
117 
118  std::vector<std::string> pathes;
119  char tmp[PATH_MAX];
120  ::strncpy(tmp, string_data(), sizeof(tmp));
121  tmp[sizeof(tmp)-1] = 0;
122  char *token, *save=0;
123  token = ::strtok_r(tmp,separators,&save);
124  while(token) {
125  pathes.emplace_back(token);
126  token = ::strtok_r(0,separators,&save);
127  }
128  Path temp;
129  std::vector<std::string>::const_iterator start(pathes.begin());
130  std::vector<std::string>::const_iterator last(pathes.end());
131  std::vector<std::string>::const_iterator stop(last--);
132  for (std::vector<std::string>::const_iterator itr(start); itr != stop; ++itr) {
133  // ignore "." except at start and last
134  Path itr_path(*itr);
135  if (itr_path.native().size() == 1
136  && (itr_path.native())[0] == dot
137  && itr != start
138  && itr != last) continue;
139 
140  // ignore a name and following ".."
141  if ( temp.empty() && itr_path.find(colon) != std::string::npos ) {
142  temp = std::move(itr_path);
143  continue;
144  }
145  else if (!temp.empty()
146  && itr_path.native().size() == 2
147  && (itr_path.native())[0] == dot
148  && (itr_path.native())[1] == dot) // dot dot
149  {
150  std::string lf(temp.filename().native());
151  if (lf.size() > 0
152  && (lf.size() != 1 || (lf[0] != dot && lf[0] != separator))
153  && (lf.size() != 2 || (lf[0] != dot && lf[1] != dot)) )
154  {
155  temp.remove_filename();
157  //if (temp.native().size() > 0
158  // && temp.native()[temp.native().size()-1]
159  // == separator)
160  //{
161  // string::size_type rds(
162  // root_directory_start(temp.native(), temp.native().size()));
163  // if (rds == string::npos
164  // || rds != temp.native().size()-1)
165  // {
166  // temp.m_pathname.erase(temp.native().size()-1);
167  // }
168  //}
169 
170  std::vector<std::string>::const_iterator next(itr);
171  if (temp.empty() && ++next != stop && next == last && *last == detail::dot_path()) {
172  temp /= detail::dot_path();
173  }
174  continue;
175  }
176  }
177  temp /= *itr;
178  };
179 
180  if (temp.empty())
181  temp /= detail::dot_path();
182  return temp;
183 }
184 
185 size_t Path::parent_path_end() const {
186  size_t end_pos(filename_pos(native(),this->size()));
187  bool filename_was_separator(this->size() && is_separator(at(end_pos)));
188 
189  // skip separators unless root directory
190  size_t root_dir_pos(root_directory_start(native(), end_pos));
191  for (; end_pos > 0
192  && (end_pos-1) != root_dir_pos
193  && is_separator(this->at(end_pos-1))
194  ;
195  --end_pos) {}
196 
197  return (end_pos == 1 && root_dir_pos == 0 && filename_was_separator) ? std::string::npos : end_pos;
198 }
199 
200 
202  this->erase(this->parent_path_end());
203  return *this;
204 }
205 
207  size_t end_pos(parent_path_end());
208  return end_pos == std::string::npos ? Path() : Path(string_data(), string_data() + end_pos);
209 }
210 
212 {
213  size_t pos(filename_pos(native(), native().size()));
214  return (native().size()
215  && pos
216  && is_separator(at(pos))
217  && !is_root_separator(native(), pos))
218  ? detail::dot_path()
219  : Path(string_data() + pos);
220 }
221 
223  size_t pos(filename_pos(native(), native().size()));
224  return (native().size()
225  && pos
226  && is_separator(at(pos))
227  && !is_root_separator(native(), pos))
228  ? detail::dot_path()
229  : Path(string_data() + pos);
230 }
Path
dd4hep::Path Path
Definition: Path.cpp:97
dd4hep::Path::append
Path & append(const std::string &copy)
Append operation.
Definition: Path.cpp:108
Path.h
dd4hep::Path::detail::dot_dot_path
static const Path & dot_dot_path()
Path representing "..".
Definition: Path.cpp:103
dd4hep::Path::remove_filename
Path & remove_filename()
Manipulator: remove the file name part. Leaves the parent path.
Definition: Path.cpp:201
dd4hep::Path::native
const std::string & native() const
String representation of thre Path object.
Definition: Path.h:104
dd4hep::Path::filename
Path filename() const
The file name of the path.
Definition: Path.cpp:211
dd4hep::Path::file_path
Path file_path() const
The full file path of the object.
Definition: Path.cpp:222
dd4hep::Path::normalize
Path normalize() const
Normalize path name.
Definition: Path.cpp:114
dd4hep::Path::parent_path_end
size_t parent_path_end() const
Index of the parent's path end.
Definition: Path.cpp:185
dd4hep::Path::string_data
const char * string_data() const
String representation of thre Path object.
Definition: Path.h:106
dd4hep::Path::Path
Path()
Default constructor.
Definition: Path.h:48
dd4hep::Path::detail::dot_path
static const Path & dot_path()
Path representing ".".
Definition: Path.cpp:99
dd4hep::Path
Path handling class.
Definition: Path.h:45
dd4hep::Path::parent_path
Path parent_path() const
Parent's path.
Definition: Path.cpp:206