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
0029 char *t = f_state + strspn(f_state, f_delim);
0030 if (*t == (char) 0) { f_state = 0; return 0; }
0031
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
0091
0092
0093
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