XRootD
XrdPfcPathParseTools.hh
Go to the documentation of this file.
1 #ifndef __XRDPFC_PATHPARSETOOLS_HH__
2 #define __XRDPFC_PATHPARSETOOLS_HH__
3 
4 #include <string>
5 #include <vector>
6 
7 #include <cstdio>
8 #include <cstring>
9 
10 namespace XrdPfc {
11 
13 {
14  char *f_str;
15  const char *f_delim;
16  char *f_state;
17 
18  SplitParser(const std::string &s, const char *d) :
19  f_str(strdup(s.c_str())), f_delim(d), f_state(f_str)
20  {}
21  ~SplitParser() { free(f_str); }
22 
23  bool is_first() const { return f_state == f_str; }
24 
25  const char* get_token()
26  {
27  if ( ! f_state) return 0;
28  // Skip leading delimiters, if any.
29  char *t = f_state + strspn(f_state, f_delim);
30  if (*t == (char) 0) { f_state = 0; return 0; }
31  // Advance state to the next delimeter, if any.
32  f_state = strpbrk(t, f_delim);
33  if (f_state) {
34  *f_state = (char) 0;
35  ++f_state;
36  }
37  return t;
38  }
39 
40  std::string get_token_as_string()
41  {
42  const char *t = get_token();
43  return std::string(t ? t : "");
44  }
45 
47  {
48  if (is_first()) { return f_str; }
49  else { *(f_state - 1) = f_delim[0]; return f_state - 1; }
50  }
51 
52  const char *get_reminder()
53  {
54  return f_state ? f_state : "";
55  }
56 
57  bool has_reminder()
58  {
59  return f_state && f_state[0] != 0;
60  }
61 
63  int n_tok = 0;
64  char *p = f_state;
65  while (*p) {
66  p += strspn(p, f_delim);
67  if (*p == (char) 0)
68  break;
69  ++n_tok;
70  p = strpbrk(p, f_delim);
71  if ( ! p)
72  break;
73  ++p;
74  }
75  return n_tok;
76  }
77 };
78 
79 struct PathTokenizer : private SplitParser
80 {
81  std::vector<const char*> m_dirs;
82  const char *m_reminder;
83  int m_n_dirs;
84 
85  PathTokenizer(const std::string &path, int max_depth, bool parse_as_lfn) :
86  SplitParser(path, "/"),
87  m_reminder (0),
88  m_n_dirs (0)
89  {
90  // max_depth - maximum number of directories to extract. If < 0, all path elements
91  // are extracted (well, up to 4096). The rest is in m_reminder.
92  // If parse_as_lfn is true store final token into m_reminder, regardless of maxdepth.
93  // This assumes the last token is a file name (and full path is lfn, including the file name).
94 
95  if (max_depth < 0)
96  max_depth = 4096;
97  m_dirs.reserve(std::min(pre_count_n_tokens(), max_depth));
98 
99  const char *t = 0;
100  for (int i = 0; i < max_depth; ++i)
101  {
102  t = get_token();
103  if (t == 0) break;
104  m_dirs.emplace_back(t);
105  }
106  if (parse_as_lfn && ! has_reminder() && ! m_dirs.empty())
107  {
108  m_reminder = m_dirs.back();
109  m_dirs.pop_back();
110  }
111  else
112  {
114  }
115  m_n_dirs = (int) m_dirs.size();
116  }
117 
119  {
120  return m_n_dirs;
121  }
122 
123  const char *get_dir(int pos)
124  {
125  if (pos >= m_n_dirs) return 0;
126  return m_dirs[pos];
127  }
128 
129  std::string make_path()
130  {
131  std::string res;
132  for (std::vector<const char*>::iterator i = m_dirs.begin(); i != m_dirs.end(); ++i)
133  {
134  res += "/";
135  res += *i;
136  }
137  if (m_reminder != 0)
138  {
139  res += "/";
140  res += m_reminder;
141  }
142  return res;
143  }
144 
145  void print_debug()
146  {
147  printf("PathTokenizer::print_debug size=%d\n", m_n_dirs);
148  for (int i = 0; i < m_n_dirs; ++i)
149  {
150  printf(" %2d: %s\n", i, m_dirs[i]);
151  }
152  printf(" rem: %s\n", m_reminder);
153  }
154 };
155 
156 }
157 
158 #endif
Definition: XrdPfc.hh:41
PathTokenizer(const std::string &path, int max_depth, bool parse_as_lfn)
std::vector< const char * > m_dirs
const char * get_dir(int pos)
SplitParser(const std::string &s, const char *d)
std::string get_token_as_string()
const char * get_reminder_with_delim()