OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "nacl_io/path.h" | 5 #include "nacl_io/path.h" |
6 | 6 |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 #include <string.h> | 8 #include <string.h> |
9 #include <string> | 9 #include <string> |
10 | 10 |
11 #include "sdk_util/string_util.h" | 11 #include "sdk_util/string_util.h" |
12 | 12 |
13 namespace nacl_io { | 13 namespace nacl_io { |
14 | 14 |
15 Path::Path() {} | 15 Path::Path() { |
| 16 } |
16 | 17 |
17 Path::Path(const Path& path) { | 18 Path::Path(const Path& path) { |
18 paths_ = path.paths_; | 19 paths_ = path.paths_; |
19 } | 20 } |
20 | 21 |
21 Path::Path(const std::string& path) { | 22 Path::Path(const std::string& path) { |
22 Set(path); | 23 Set(path); |
23 } | 24 } |
24 | 25 |
25 Path::~Path() {} | 26 Path::~Path() { |
| 27 } |
26 | 28 |
27 bool Path::IsAbsolute() const { | 29 bool Path::IsAbsolute() const { |
28 return !paths_.empty() && paths_[0] == "/"; | 30 return !paths_.empty() && paths_[0] == "/"; |
29 } | 31 } |
30 | 32 |
31 const std::string& Path::Part(size_t index) const { | 33 const std::string& Path::Part(size_t index) const { |
32 return paths_[index]; | 34 return paths_[index]; |
33 } | 35 } |
34 | 36 |
35 size_t Path::Size() const { | 37 size_t Path::Size() const { |
36 return paths_.size(); | 38 return paths_.size(); |
37 } | 39 } |
38 | 40 |
39 bool Path::Top() const { | 41 bool Path::Top() const { |
40 return (paths_.size() == 0) || (paths_.size() == 1 && paths_[0] == "/"); | 42 return (paths_.size() == 0) || (paths_.size() == 1 && paths_[0] == "/"); |
41 } | 43 } |
42 | 44 |
43 Path& Path::Append(const std::string& path) { | 45 Path& Path::Append(const std::string& path) { |
44 StringArray_t paths = Split(path); | 46 StringArray_t paths = Split(path); |
45 | 47 |
46 for (size_t index = 0; index < paths.size(); index++) { | 48 for (size_t index = 0; index < paths.size(); index++) { |
47 // Skip ROOT | 49 // Skip ROOT |
48 if (paths_.size() && index == 0 && paths[0] == "/") continue; | 50 if (paths_.size() && index == 0 && paths[0] == "/") |
| 51 continue; |
49 paths_.push_back(paths[index]); | 52 paths_.push_back(paths[index]); |
50 } | 53 } |
51 | 54 |
52 paths_ = Normalize(paths_); | 55 paths_ = Normalize(paths_); |
53 return *this; | 56 return *this; |
54 } | 57 } |
55 | 58 |
56 Path& Path::Prepend(const std::string& path) { | 59 Path& Path::Prepend(const std::string& path) { |
57 StringArray_t paths = Split(path); | 60 StringArray_t paths = Split(path); |
58 | 61 |
59 for (size_t index = 0; index < paths_.size(); index++) { | 62 for (size_t index = 0; index < paths_.size(); index++) { |
60 // Skip ROOT | 63 // Skip ROOT |
61 if (index == 0 && paths_[0] == "/") continue; | 64 if (index == 0 && paths_[0] == "/") |
| 65 continue; |
62 paths.push_back(paths[index]); | 66 paths.push_back(paths[index]); |
63 } | 67 } |
64 paths_ = Normalize(paths); | 68 paths_ = Normalize(paths); |
65 return *this; | 69 return *this; |
66 } | 70 } |
67 | 71 |
68 Path& Path::Set(const std::string& path) { | 72 Path& Path::Set(const std::string& path) { |
69 StringArray_t paths = Split(path); | 73 StringArray_t paths = Split(path); |
70 paths_ = Normalize(paths); | 74 paths_ = Normalize(paths); |
71 return *this; | 75 return *this; |
72 } | 76 } |
73 | 77 |
74 Path Path::Parent() const { | 78 Path Path::Parent() const { |
75 Path out; | 79 Path out; |
76 out.paths_ = paths_; | 80 out.paths_ = paths_; |
77 if (out.paths_.size()) out.paths_.pop_back(); | 81 if (out.paths_.size()) |
| 82 out.paths_.pop_back(); |
78 return out; | 83 return out; |
79 } | 84 } |
80 | 85 |
81 std::string Path::Basename() const { | 86 std::string Path::Basename() const { |
82 if (paths_.size()) return paths_.back(); | 87 if (paths_.size()) |
| 88 return paths_.back(); |
83 return std::string(); | 89 return std::string(); |
84 } | 90 } |
85 | 91 |
86 std::string Path::Join() const { | 92 std::string Path::Join() const { |
87 return Range(paths_, 0, paths_.size()); | 93 return Range(paths_, 0, paths_.size()); |
88 } | 94 } |
89 | 95 |
90 std::string Path::Range(size_t start, size_t end) const { | 96 std::string Path::Range(size_t start, size_t end) const { |
91 return Range(paths_, start, end); | 97 return Range(paths_, start, end); |
92 } | 98 } |
93 | 99 |
94 StringArray_t Path::Split() const { | 100 StringArray_t Path::Split() const { |
95 return paths_; | 101 return paths_; |
96 } | 102 } |
97 | 103 |
98 // static | 104 // static |
99 StringArray_t Path::Normalize(const StringArray_t& paths) { | 105 StringArray_t Path::Normalize(const StringArray_t& paths) { |
100 StringArray_t path_out; | 106 StringArray_t path_out; |
101 | 107 |
102 for (size_t index = 0; index < paths.size(); index++) { | 108 for (size_t index = 0; index < paths.size(); index++) { |
103 const std::string &curr = paths[index]; | 109 const std::string& curr = paths[index]; |
104 | 110 |
105 // Check if '/' was used excessively in the path. | 111 // Check if '/' was used excessively in the path. |
106 // For example, in cd Desktop///// | 112 // For example, in cd Desktop///// |
107 if (curr == "/" && index != 0) continue; | 113 if (curr == "/" && index != 0) |
| 114 continue; |
108 | 115 |
109 // Check for '.' in the path and remove it | 116 // Check for '.' in the path and remove it |
110 if (curr == ".") continue; | 117 if (curr == ".") |
| 118 continue; |
111 | 119 |
112 // Check for '..' | 120 // Check for '..' |
113 if (curr == "..") { | 121 if (curr == "..") { |
114 // If the path is empty, or "..", then add ".." | 122 // If the path is empty, or "..", then add ".." |
115 if (path_out.empty() || path_out.back() == "..") { | 123 if (path_out.empty() || path_out.back() == "..") { |
116 path_out.push_back(curr); | 124 path_out.push_back(curr); |
117 continue; | 125 continue; |
118 } | 126 } |
119 | 127 |
120 // If the path is at root, "/.." = "/" | 128 // If the path is at root, "/.." = "/" |
121 if (path_out.back() == "/") { | 129 if (path_out.back() == "/") { |
122 continue; | 130 continue; |
123 } | 131 } |
124 | 132 |
125 // if we are already at root, then stay there (root/.. -> root) | 133 // if we are already at root, then stay there (root/.. -> root) |
126 if (path_out.back() == "/") { | 134 if (path_out.back() == "/") { |
127 continue; | 135 continue; |
128 } | 136 } |
129 | 137 |
130 // otherwise, pop off the top path component | 138 // otherwise, pop off the top path component |
131 path_out.pop_back(); | 139 path_out.pop_back(); |
132 continue; | 140 continue; |
133 } | 141 } |
134 | 142 |
135 // By now, we should have handled end cases so just append. | 143 // By now, we should have handled end cases so just append. |
136 path_out.push_back(curr); | 144 path_out.push_back(curr); |
137 } | 145 } |
138 | 146 |
139 // If the path was valid, but now it's empty, return self | 147 // If the path was valid, but now it's empty, return self |
140 if (path_out.size() == 0) path_out.push_back("."); | 148 if (path_out.size() == 0) |
| 149 path_out.push_back("."); |
141 | 150 |
142 return path_out; | 151 return path_out; |
143 } | 152 } |
144 | 153 |
145 // static | 154 // static |
146 std::string Path::Join(const StringArray_t& paths) { | 155 std::string Path::Join(const StringArray_t& paths) { |
147 return Range(paths, 0, paths.size()); | 156 return Range(paths, 0, paths.size()); |
148 } | 157 } |
149 | 158 |
150 // static | 159 // static |
151 std::string Path::Range(const StringArray_t& paths, size_t start, size_t end) { | 160 std::string Path::Range(const StringArray_t& paths, size_t start, size_t end) { |
152 std::string out_path; | 161 std::string out_path; |
153 size_t index = start; | 162 size_t index = start; |
154 | 163 |
155 if (end > paths.size()) end = paths.size(); | 164 if (end > paths.size()) |
| 165 end = paths.size(); |
156 | 166 |
157 // If this is an absolute path, paths[0] == "/". In this case, we don't want | 167 // If this is an absolute path, paths[0] == "/". In this case, we don't want |
158 // to add an additional / separator. | 168 // to add an additional / separator. |
159 if (start == 0 && end > 0 && paths[0] == "/") { | 169 if (start == 0 && end > 0 && paths[0] == "/") { |
160 out_path += "/"; | 170 out_path += "/"; |
161 index++; | 171 index++; |
162 } | 172 } |
163 | 173 |
164 for (; index < end; index++) { | 174 for (; index < end; index++) { |
165 out_path += paths[index]; | 175 out_path += paths[index]; |
166 if (index < end - 1) | 176 if (index < end - 1) |
167 out_path += "/"; | 177 out_path += "/"; |
168 } | 178 } |
169 | 179 |
170 return out_path; | 180 return out_path; |
171 } | 181 } |
172 | 182 |
173 // static | 183 // static |
174 StringArray_t Path::Split(const std::string& path) { | 184 StringArray_t Path::Split(const std::string& path) { |
175 StringArray_t path_split; | 185 StringArray_t path_split; |
176 StringArray_t components; | 186 StringArray_t components; |
177 | 187 |
178 sdk_util::SplitString(path, '/', &path_split); | 188 sdk_util::SplitString(path, '/', &path_split); |
179 | 189 |
180 if (path[0] == '/') | 190 if (path[0] == '/') |
181 components.push_back("/"); | 191 components.push_back("/"); |
182 | 192 |
183 // Copy path_split to components, removing empty path segments. | 193 // Copy path_split to components, removing empty path segments. |
184 for (StringArray_t::const_iterator it = path_split.begin(); | 194 for (StringArray_t::const_iterator it = path_split.begin(); |
185 it != path_split.end(); ++it) { | 195 it != path_split.end(); |
186 if (!it->empty()) components.push_back(*it); | 196 ++it) { |
| 197 if (!it->empty()) |
| 198 components.push_back(*it); |
187 } | 199 } |
188 return components; | 200 return components; |
189 } | 201 } |
190 | 202 |
191 Path& Path::operator =(const Path& p) { | 203 Path& Path::operator=(const Path& p) { |
192 paths_ = p.paths_; | 204 paths_ = p.paths_; |
193 return *this; | 205 return *this; |
194 } | 206 } |
195 | 207 |
196 Path& Path::operator =(const std::string& p) { | 208 Path& Path::operator=(const std::string& p) { |
197 return Set(p); | 209 return Set(p); |
198 } | 210 } |
199 | 211 |
200 } // namespace nacl_io | 212 } // namespace nacl_io |
201 | |
OLD | NEW |