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