Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-01-08 10:33:39

0001 #ifndef __XRDPFC_PATHPARSETOOLS_HH__
0002 #define __XRDPFC_PATHPARSETOOLS_HH__
0003 
0004 #include <string>
0005 #include <vector>
0006 
0007 #include <cstdio>
0008 #include <cstring>
0009 
0010 namespace XrdPfc {
0011 
0012 struct SplitParser
0013 {
0014    char       *f_str;
0015    const char *f_delim;
0016    char       *f_state;
0017 
0018    SplitParser(const std::string &s, const char *d) :
0019       f_str(strdup(s.c_str())), f_delim(d), f_state(f_str)
0020    {}
0021    ~SplitParser() { free(f_str); }
0022 
0023    bool is_first() const { return f_state == f_str; }
0024 
0025    const char* get_token()
0026    {
0027       if ( ! f_state) return 0;
0028       // Skip leading delimiters, if any.
0029       char *t = f_state + strspn(f_state, f_delim);
0030       if (*t == (char) 0) { f_state = 0; return 0; }
0031       // Advance state to the next delimeter, if any.
0032       f_state = strpbrk(t, f_delim);
0033       if (f_state) {
0034           *f_state = (char) 0;
0035           ++f_state;
0036       }
0037       return t;
0038    }
0039 
0040    std::string get_token_as_string()
0041    {
0042       const char *t = get_token();
0043       return std::string(t ? t : "");
0044    }
0045 
0046    const char* get_reminder_with_delim()
0047    {
0048       if (is_first()) { return f_str; }
0049       else            { *(f_state - 1) = f_delim[0]; return f_state - 1; }
0050    }
0051 
0052    const char *get_reminder()
0053    {
0054       return f_state ? f_state : "";
0055    }
0056 
0057    bool has_reminder()
0058    {
0059       return f_state && f_state[0] != 0;
0060    }
0061 
0062    int pre_count_n_tokens() {
0063       int n_tok = 0;
0064       char *p = f_state;
0065       while (*p) {
0066          p += strspn(p, f_delim);
0067          if (*p == (char) 0)
0068             break;
0069          ++n_tok;
0070          p = strpbrk(p, f_delim);
0071          if ( ! p)
0072             break;
0073          ++p;
0074       }
0075       return n_tok;
0076    }
0077 };
0078 
0079 struct PathTokenizer : private SplitParser
0080 {
0081    std::vector<const char*>  m_dirs;
0082    const char               *m_reminder;
0083    int                       m_n_dirs;
0084 
0085    PathTokenizer(const std::string &path, int max_depth, bool parse_as_lfn) :
0086       SplitParser(path, "/"),
0087       m_reminder (0),
0088       m_n_dirs   (0)
0089    {
0090       // max_depth - maximum number of directories to extract. If < 0, all path elements
0091       //             are extracted (well, up to 4096). The rest is in m_reminder.
0092       // If parse_as_lfn is true store final token into m_reminder, regardless of maxdepth.
0093       // This assumes the last token is a file name (and full path is lfn, including the file name).
0094 
0095       if (max_depth < 0)
0096          max_depth = 4096;
0097       m_dirs.reserve(std::min(pre_count_n_tokens(), max_depth));
0098 
0099       const char *t = 0;
0100       for (int i = 0; i < max_depth; ++i)
0101       {
0102          t = get_token();
0103          if (t == 0) break;
0104          m_dirs.emplace_back(t);
0105       }
0106       if (parse_as_lfn && ! has_reminder() && ! m_dirs.empty())
0107       {
0108          m_reminder = m_dirs.back();
0109          m_dirs.pop_back();
0110       }
0111       else
0112       {
0113          m_reminder = get_reminder();
0114       }
0115       m_n_dirs = (int) m_dirs.size();
0116    }
0117 
0118    int get_n_dirs()
0119    {
0120       return m_n_dirs;
0121    }
0122 
0123    const char *get_dir(int pos)
0124    {
0125       if (pos >= m_n_dirs) return 0;
0126       return m_dirs[pos];
0127    }
0128 
0129    std::string make_path()
0130    {
0131       std::string res;
0132       for (std::vector<const char*>::iterator i = m_dirs.begin(); i != m_dirs.end(); ++i)
0133       {
0134          res += "/";
0135          res += *i;
0136       }
0137       if (m_reminder != 0)
0138       {
0139          res += "/";
0140          res += m_reminder;
0141       }
0142       return res;
0143    }
0144 
0145    void print_debug()
0146    {
0147       printf("PathTokenizer::print_debug size=%d\n", m_n_dirs);
0148       for (int i = 0; i < m_n_dirs; ++i)
0149       {
0150          printf("   %2d: %s\n", i, m_dirs[i]);
0151       }
0152       printf("  rem: %s\n", m_reminder);
0153    }
0154 };
0155 
0156 }
0157 
0158 #endif