Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:13:56

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 //  \author  Markus Frank
0011 //  \date    2016-08-30
0012 //  \version 1.0
0013 //
0014 //==========================================================================
0015 
0016 /// Framework include files
0017 #include <DD4hep/Path.h>
0018 
0019 /// C/C++ include files
0020 #include <climits>
0021 #include <cstring>
0022 #include <vector>
0023 #include <stdexcept>
0024 
0025 namespace {
0026   const char dot = '.';
0027   const char separator = '/';
0028   const char* const separators = "/";
0029   const char colon = ':';
0030 
0031   
0032   inline bool is_separator(char c)  { return c == separator;  }
0033 
0034   bool is_root_separator(const std::string& str, size_t pos)
0035   // pos is position of the separator
0036   {
0037     if ( str.empty() || is_separator(str[pos]) ) {
0038       throw std::runtime_error("precondition violation");
0039     }
0040     // subsequent logic expects pos to be for leftmost slash of a set
0041     while (pos > 0 && is_separator(str[pos-1]))
0042       --pos;
0043 
0044     //  "/" [...]
0045     if (pos == 0)  
0046       return true;
0047     //  "//" name "/"
0048     if (pos < 3 || !is_separator(str[0]) || !is_separator(str[1]))
0049       return false;
0050 
0051     return str.find_first_of(separators, 2) == pos;
0052   }
0053 
0054   size_t filename_pos(const std::string& str,size_t end_pos)
0055   // return 0 if str itself is filename (or empty)
0056   {
0057     // case: "//"
0058     if (end_pos == 2 
0059         && is_separator(str[0])
0060         && is_separator(str[1])) return 0;
0061 
0062     // case: ends in "/"
0063     if (end_pos && is_separator(str[end_pos-1]))
0064       return end_pos-1;
0065     
0066     // set pos to start of last element
0067     size_t pos(str.find_last_of(separators, end_pos-1));
0068 
0069     return (pos == std::string::npos // path itself must be a filename (or empty)
0070             || (pos == 1 && is_separator(str[0]))) // or net
0071       ? 0 // so filename is entire string
0072       : pos + 1; // or starts after delimiter
0073   }
0074 
0075   // return npos if no root_directory found
0076   size_t root_directory_start(const std::string& path, size_t size)  {
0077     // case "//"
0078     if (size == 2
0079         && is_separator(path[0])
0080         && is_separator(path[1])) return std::string::npos;
0081     // case "//net {/}"
0082     if (size > 3
0083         && is_separator(path[0])
0084         && is_separator(path[1])
0085         && !is_separator(path[2]))
0086     {
0087       std::string::size_type pos(path.find_first_of(separators, 2));
0088       return pos < size ? pos : std::string::npos;
0089     }
0090     
0091     // case "/"
0092     if (size > 0 && is_separator(path[0])) return 0;
0093     return std::string::npos;
0094   }
0095 }
0096 
0097 using Path = dd4hep::Path;
0098 
0099 const Path& Path::detail::dot_path()   {
0100   static Path p(".");
0101   return p;
0102 }
0103 const Path& Path::detail::dot_dot_path()  {
0104   static Path p("..");
0105   return p;
0106 }
0107 
0108 Path& Path::append(const std::string& c)   {
0109   insert(end(),separator);
0110   insert(end(),c.begin(),c.end());
0111   return *this;
0112 }
0113 
0114 Path Path::normalize()  const {
0115   if (empty())
0116     return *this;
0117 
0118   std::vector<std::string> pathes;
0119   char tmp[PATH_MAX];
0120   ::strncpy(tmp, string_data(), sizeof(tmp));
0121   tmp[sizeof(tmp)-1] = 0;
0122   char *token, *save=0;
0123   token = ::strtok_r(tmp,separators,&save);
0124   while(token)  {
0125     pathes.emplace_back(token);
0126     token = ::strtok_r(0,separators,&save);
0127   }
0128   Path temp;
0129   std::vector<std::string>::const_iterator start(pathes.begin());
0130   std::vector<std::string>::const_iterator last(pathes.end());
0131   std::vector<std::string>::const_iterator stop(last--);
0132   for (std::vector<std::string>::const_iterator itr(start); itr != stop; ++itr)  {
0133     // ignore "." except at start and last
0134     Path itr_path(*itr);
0135     if (itr_path.native().size() == 1
0136         && (itr_path.native())[0] == dot
0137         && itr != start
0138         && itr != last) continue;
0139 
0140     // ignore a name and following ".."
0141     if ( temp.empty() && itr_path.find(colon) != std::string::npos )  {
0142       temp = std::move(itr_path);
0143       continue;
0144     }
0145     else if (!temp.empty()
0146         && itr_path.native().size() == 2
0147         && (itr_path.native())[0] == dot
0148         && (itr_path.native())[1] == dot) // dot dot
0149     {
0150       std::string lf(temp.filename().native());  
0151       if (lf.size() > 0
0152           && (lf.size() != 1 || (lf[0] != dot && lf[0] != separator))
0153           && (lf.size() != 2 || (lf[0] != dot && lf[1] != dot))   )
0154       {
0155         temp.remove_filename();
0156         //// if not root directory, must also remove "/" if any
0157         //if (temp.native().size() > 0
0158         //  && temp.native()[temp.native().size()-1]
0159         //    == separator)
0160         //{
0161         //  string::size_type rds(
0162         //    root_directory_start(temp.native(), temp.native().size()));
0163         //  if (rds == string::npos
0164         //    || rds != temp.native().size()-1) 
0165         //  {
0166         //    temp.m_pathname.erase(temp.native().size()-1);
0167         //  }
0168         //}
0169 
0170         std::vector<std::string>::const_iterator next(itr);
0171         if (temp.empty() && ++next != stop && next == last && *last == detail::dot_path())  {
0172           temp /= detail::dot_path();
0173         }
0174         continue;
0175       }
0176     }
0177     temp /= *itr;
0178   };
0179 
0180   if (temp.empty())
0181     temp /= detail::dot_path();
0182   return temp;
0183 }
0184 
0185 size_t Path::parent_path_end() const  {
0186   size_t end_pos(filename_pos(native(),this->size()));
0187   bool filename_was_separator(this->size() && is_separator(at(end_pos)));
0188 
0189   // skip separators unless root directory
0190   size_t root_dir_pos(root_directory_start(native(), end_pos));
0191   for (; end_pos > 0
0192          && (end_pos-1) != root_dir_pos
0193          && is_separator(this->at(end_pos-1))
0194          ;
0195        --end_pos) {}
0196 
0197   return (end_pos == 1 && root_dir_pos == 0 && filename_was_separator) ? std::string::npos : end_pos;
0198 }
0199 
0200 
0201 Path& Path::remove_filename()   {
0202   this->erase(this->parent_path_end());
0203   return *this;
0204 }
0205 
0206 Path  Path::parent_path() const  {
0207   size_t end_pos(parent_path_end());
0208   return end_pos == std::string::npos ? Path() : Path(string_data(), string_data() + end_pos);
0209 }
0210 
0211 Path Path::filename() const
0212 {
0213   size_t pos(filename_pos(native(), native().size()));
0214   return (native().size()
0215           && pos
0216           && is_separator(at(pos))
0217           && !is_root_separator(native(), pos))
0218     ? detail::dot_path()
0219     : Path(string_data() + pos);
0220 }
0221 
0222 Path  Path::file_path() const  {
0223   size_t pos(filename_pos(native(), native().size()));
0224   return (native().size()
0225           && pos
0226           && is_separator(at(pos))
0227           && !is_root_separator(native(), pos))
0228     ? detail::dot_path()
0229     : Path(string_data() + pos);
0230 }