XRootD
Loading...
Searching...
No Matches
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
10namespace 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
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
79struct PathTokenizer : private SplitParser
80{
81 std::vector<const char*> m_dirs;
82 const char *m_reminder;
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
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
const char * get_dir(int pos)
PathTokenizer(const std::string &path, int max_depth, bool parse_as_lfn)
std::vector< const char * > m_dirs
SplitParser(const std::string &s, const char *d)
const char * get_reminder_with_delim()
std::string get_token_as_string()