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.
5 #include "nacl_io/path.h"
11 #include "sdk_util/string_util.h"
15 Path::Path(const Path
& path
) {
19 Path::Path(const std::string
& path
) {
23 bool Path::IsAbsolute() const {
24 return !paths_
.empty() && paths_
[0] == "/";
27 const std::string
& Path::Part(size_t index
) const {
31 size_t Path::Size() const {
35 bool Path::IsRoot() const {
36 return paths_
.empty() || (paths_
.size() == 1 && paths_
[0] == "/");
39 Path
& Path::MakeRelative() {
41 paths_
.erase(paths_
.begin());
46 Path
& Path::Append(const Path
& path
) {
47 // Appending an absolute path effectivly sets the path, ignoring
48 // the current contents.
49 if (path
.IsAbsolute()) {
52 for (size_t index
= 0; index
< path
.paths_
.size(); index
++) {
53 paths_
.push_back(path
.paths_
[index
]);
57 paths_
= Normalize(paths_
);
61 Path
& Path::Append(const std::string
& path
) {
62 return Append(Path(path
));
65 Path
& Path::Set(const StringArray_t path
) {
66 paths_
= Normalize(path
);
70 Path
& Path::Set(const std::string
& path
) {
71 return Set(Split(path
));
74 Path
Path::Parent() const {
77 if (out
.paths_
.size())
78 out
.paths_
.pop_back();
82 std::string
Path::Basename() const {
88 std::string
Path::Join() const {
89 return Range(paths_
, 0, paths_
.size());
92 std::string
Path::Range(size_t start
, size_t end
) const {
93 return Range(paths_
, start
, end
);
96 StringArray_t
Path::Split() const {
101 StringArray_t
Path::Normalize(const StringArray_t
& paths
) {
102 StringArray_t path_out
;
104 for (size_t index
= 0; index
< paths
.size(); index
++) {
105 const std::string
& curr
= paths
[index
];
107 // Check if '/' was used excessively in the path.
108 // For example, in cd Desktop/////
109 if (curr
== "/" && index
!= 0)
112 // Check for '.' in the path and remove it
118 // If the path is empty, or "..", then add ".."
119 if (path_out
.empty() || path_out
.back() == "..") {
120 path_out
.push_back(curr
);
124 // If the path is at root, "/.." = "/"
125 if (path_out
.back() == "/") {
129 // if we are already at root, then stay there (root/.. -> root)
130 if (path_out
.back() == "/") {
134 // otherwise, pop off the top path component
139 // By now, we should have handled end cases so just append.
140 path_out
.push_back(curr
);
143 // If the path was valid, but now it's empty, return self
144 if (path_out
.empty())
145 path_out
.push_back(".");
151 std::string
Path::Join(const StringArray_t
& paths
) {
152 return Range(paths
, 0, paths
.size());
156 std::string
Path::Range(const StringArray_t
& paths
, size_t start
, size_t end
) {
157 std::string out_path
;
158 size_t index
= start
;
160 if (end
> paths
.size())
163 // If this is an absolute path, paths[0] == "/". In this case, we don't want
164 // to add an additional / separator.
165 if (start
== 0 && end
> 0 && paths
[0] == "/") {
170 for (; index
< end
; index
++) {
171 out_path
+= paths
[index
];
180 StringArray_t
Path::Split(const std::string
& path
) {
181 StringArray_t path_split
;
182 StringArray_t components
;
184 sdk_util::SplitString(path
, '/', &path_split
);
187 components
.push_back("/");
189 // Copy path_split to components, removing empty path segments.
190 for (StringArray_t::const_iterator it
= path_split
.begin();
191 it
!= path_split
.end();
194 components
.push_back(*it
);
199 Path
& Path::operator=(const Path
& p
) {
204 Path
& Path::operator=(const std::string
& p
) {
208 } // namespace nacl_io