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  bool f_first;
18 
19  SplitParser(const std::string &s, const char *d) :
20  f_str(strdup(s.c_str())), f_delim(d), f_state(0), f_first(true)
21  {}
22  ~SplitParser() { free(f_str); }
23 
24  char* get_token()
25  {
26  if (f_first) { f_first = false; return strtok_r(f_str, f_delim, &f_state); }
27  else { return strtok_r(0, f_delim, &f_state); }
28  }
29 
30  std::string get_token_as_string()
31  {
32  char *t = get_token();
33  return std::string(t ? t : "");
34  }
35 
37  {
38  if (f_first) { return f_str; }
39  else { *(f_state - 1) = f_delim[0]; return f_state - 1; }
40  }
41 
42  char *get_reminder()
43  {
44  return f_first ? f_str : f_state;
45  }
46 
47  bool has_reminder()
48  {
49  char *r = get_reminder();
50  return r && r[0] != 0;
51  }
52 
53  int fill_argv(std::vector<char*> &argv)
54  {
55  if (!f_first) return 0;
56  int dcnt = 0; { char *p = f_str; while (*p) { if (*(p++) == f_delim[0]) ++dcnt; } }
57  argv.reserve(dcnt + 1);
58  int argc = 0;
59  char *i = strtok_r(f_str, f_delim, &f_state);
60  while (i)
61  {
62  ++argc;
63  argv.push_back(i);
64  // printf(" arg %d : '%s'\n", argc, i);
65  i = strtok_r(0, f_delim, &f_state);
66  }
67  return argc;
68  }
69 };
70 
71 struct PathTokenizer : private SplitParser
72 {
73  std::vector<const char*> m_dirs;
74  const char *m_reminder;
75  int m_n_dirs;
76 
77  PathTokenizer(const std::string &path, int max_depth, bool parse_as_lfn) :
78  SplitParser(path, "/"),
79  m_reminder (0),
80  m_n_dirs (0)
81  {
82  // max_depth - maximum number of directories to extract. If < 0, all path elements
83  // are extracted (well, up to 4096). The rest is in m_reminder.
84  // If parse_as_lfn is true store final token into m_reminder, regardless of maxdepth.
85  // This assumes the last token is a file name (and full path is lfn, including the file name).
86 
87  if (max_depth < 0)
88  max_depth = 4096;
89  m_dirs.reserve(std::min(8, max_depth));
90 
91  char *t = 0;
92  for (int i = 0; i < max_depth; ++i)
93  {
94  t = get_token();
95  if (t == 0) break;
96  m_dirs.emplace_back(t);
97  }
98  if (parse_as_lfn && (get_reminder() == 0 || *get_reminder() == 0) && ! m_dirs.empty())
99  {
100  m_reminder = m_dirs.back();
101  m_dirs.pop_back();
102  }
103  else
104  {
106  }
107  m_n_dirs = (int) m_dirs.size();
108  }
109 
111  {
112  return m_n_dirs;
113  }
114 
115  const char *get_dir(int pos)
116  {
117  if (pos >= m_n_dirs) return 0;
118  return m_dirs[pos];
119  }
120 
121  std::string make_path()
122  {
123  std::string res;
124  for (std::vector<const char*>::iterator i = m_dirs.begin(); i != m_dirs.end(); ++i)
125  {
126  res += "/";
127  res += *i;
128  }
129  if (m_reminder != 0)
130  {
131  res += "/";
132  res += m_reminder;
133  }
134  return res;
135  }
136 
137  void print_debug()
138  {
139  printf("PathTokenizer::print_debug size=%d\n", m_n_dirs);
140  for (int i = 0; i < m_n_dirs; ++i)
141  {
142  printf(" %2d: %s\n", i, m_dirs[i]);
143  }
144  printf(" rem: %s\n", m_reminder);
145  }
146 };
147 
148 }
149 
150 #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()
int fill_argv(std::vector< char * > &argv)