blob: cd0f0108bd45b864aa6bd12f507086b1f788b9db [file] [log] [blame]
William A. Kennington III226bc422021-05-05 17:08:36 -07001#include <sdbusplus/message/native_types.hpp>
William A. Kennington III226bc422021-05-05 17:08:36 -07002
3#include <array>
William A. Kennington III285f78b2021-05-01 18:35:11 -07004#include <cctype>
William A. Kennington III226bc422021-05-05 17:08:36 -07005
6namespace sdbusplus
7{
8namespace message
9{
10namespace details
11{
12
William A. Kennington III285f78b2021-05-01 18:35:11 -070013constexpr std::array<char, 16> hex{'0', '1', '2', '3', '4', '5', '6', '7',
14 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
15
16constexpr std::array<char, 256> unhex = [] {
17 std::array<char, 256> ret;
18 for (size_t i = 0; i < ret.size(); ++i)
19 {
20 ret[i] = -1;
21 }
22 for (char i = 0; i < 10; ++i)
23 {
24 ret['0' + i] = i;
25 }
26 for (char i = 0; i < 6; ++i)
27 {
28 ret['A' + i] = i + 10;
29 ret['a' + i] = i + 10;
30 }
31 return ret;
32}();
33
34inline bool pathShouldEscape(char c)
35{
36 return !std::isalnum(c);
37}
38
39inline void pathAppendEscape(std::string& s, char c)
40{
41 s.append(1, '_');
42 s.append(1, hex[(c >> 4) & 0xf]);
43 s.append(1, hex[c & 0xf]);
44}
45
William A. Kennington III226bc422021-05-05 17:08:36 -070046std::string string_path_wrapper::filename() const
47{
William A. Kennington III285f78b2021-05-01 18:35:11 -070048 std::string_view strv(str);
49 size_t firstIndex = strv.rfind('/');
William A. Kennington III226bc422021-05-05 17:08:36 -070050
51 // Dbus paths must start with /, if we don't find one, it's an error
52 if (firstIndex == std::string::npos)
53 {
54 return "";
55 }
William A. Kennington III285f78b2021-05-01 18:35:11 -070056 auto filename = strv.substr(firstIndex + 1);
57
William A. Kennington III226bc422021-05-05 17:08:36 -070058 // If we don't see that this was encoded by sdbusplus, return the naive
59 // version of the filename path.
William A. Kennington III285f78b2021-05-01 18:35:11 -070060 if (filename[0] != '_')
William A. Kennington III226bc422021-05-05 17:08:36 -070061 {
62 return std::string(filename);
63 }
64
William A. Kennington III285f78b2021-05-01 18:35:11 -070065 std::string out;
66 out.reserve(filename.size());
67 for (size_t i = 0; i < filename.size(); ++i)
William A. Kennington III226bc422021-05-05 17:08:36 -070068 {
William A. Kennington III285f78b2021-05-01 18:35:11 -070069 if (filename[i] != '_')
70 {
71 out.append(1, filename[i]);
72 continue;
73 }
74 if (i + 2 >= filename.size())
75 {
76 return "";
77 }
78 auto ch = unhex[filename[i + 1]];
79 auto cl = unhex[filename[i + 2]];
80 if (ch == -1 || cl == -1)
81 {
82 return "";
83 }
84 out.append(1, (ch << 4) | cl);
85 i += 2;
William A. Kennington III226bc422021-05-05 17:08:36 -070086 }
William A. Kennington III285f78b2021-05-01 18:35:11 -070087 return out;
William A. Kennington III226bc422021-05-05 17:08:36 -070088}
89
90string_path_wrapper string_path_wrapper::parent_path() const
91{
92 auto index = str.rfind('/');
93 if (index == std::string::npos)
94 {
95 return string_path_wrapper("/");
96 }
97 if (index <= 1)
98 {
99 return string_path_wrapper("/");
100 }
101
102 return str.substr(0, index);
103}
104
William A. Kennington III285f78b2021-05-01 18:35:11 -0700105string_path_wrapper string_path_wrapper::operator/(std::string_view extId) const
William A. Kennington III226bc422021-05-05 17:08:36 -0700106{
107 string_path_wrapper out;
William A. Kennington III285f78b2021-05-01 18:35:11 -0700108 out.str.reserve(str.size() + 1 + extId.size() * 3);
109 out.str.append(str);
110 return out /= extId;
William A. Kennington III226bc422021-05-05 17:08:36 -0700111}
112
William A. Kennington III285f78b2021-05-01 18:35:11 -0700113string_path_wrapper& string_path_wrapper::operator/=(std::string_view extId)
William A. Kennington III226bc422021-05-05 17:08:36 -0700114{
William A. Kennington III285f78b2021-05-01 18:35:11 -0700115 str.reserve(str.size() + 1 + extId.size() * 3);
116 if (!str.empty() && str[str.size() - 1] != '/')
117 {
118 str.append(1, '/');
119 }
120 if (extId.empty())
121 {
122 return *this;
123 }
124 pathAppendEscape(str, extId[0]);
125 for (auto c : extId.substr(1))
126 {
127 if (pathShouldEscape(c))
128 {
129 pathAppendEscape(str, c);
130 }
131 else
132 {
133 str.append(1, c);
134 }
135 }
William A. Kennington III226bc422021-05-05 17:08:36 -0700136 return *this;
137}
138
139} // namespace details
140} // namespace message
141} // namespace sdbusplus