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::Append(const std::string
& path
) {
40 StringArray_t paths
= Split(path
);
44 for (size_t index
= 0; index
< paths
.size(); index
++) {
46 if (paths_
.size() && index
== 0 && paths
[0] == "/")
48 paths_
.push_back(paths
[index
]);
51 paths_
= Normalize(paths_
);
55 Path
& Path::Prepend(const std::string
& path
) {
56 StringArray_t paths
= Split(path
);
60 for (size_t index
= 0; index
< paths_
.size(); index
++) {
62 if (index
== 0 && paths_
[0] == "/")
64 paths
.push_back(paths_
[index
]);
67 paths_
= Normalize(paths
);
71 Path
& Path::Set(const std::string
& path
) {
72 StringArray_t paths
= Split(path
);
73 paths_
= Normalize(paths
);
77 Path
Path::Parent() const {
80 if (out
.paths_
.size())
81 out
.paths_
.pop_back();
85 std::string
Path::Basename() const {
91 std::string
Path::Join() const {
92 return Range(paths_
, 0, paths_
.size());
95 std::string
Path::Range(size_t start
, size_t end
) const {
96 return Range(paths_
, start
, end
);
99 StringArray_t
Path::Split() const {
104 StringArray_t
Path::Normalize(const StringArray_t
& paths
) {
105 StringArray_t path_out
;
107 for (size_t index
= 0; index
< paths
.size(); index
++) {
108 const std::string
& curr
= paths
[index
];
110 // Check if '/' was used excessively in the path.
111 // For example, in cd Desktop/////
112 if (curr
== "/" && index
!= 0)
115 // Check for '.' in the path and remove it
121 // If the path is empty, or "..", then add ".."
122 if (path_out
.empty() || path_out
.back() == "..") {
123 path_out
.push_back(curr
);
127 // If the path is at root, "/.." = "/"
128 if (path_out
.back() == "/") {
132 // if we are already at root, then stay there (root/.. -> root)
133 if (path_out
.back() == "/") {
137 // otherwise, pop off the top path component
142 // By now, we should have handled end cases so just append.
143 path_out
.push_back(curr
);
146 // If the path was valid, but now it's empty, return self
147 if (path_out
.empty())
148 path_out
.push_back(".");
154 std::string
Path::Join(const StringArray_t
& paths
) {
155 return Range(paths
, 0, paths
.size());
159 std::string
Path::Range(const StringArray_t
& paths
, size_t start
, size_t end
) {
160 std::string out_path
;
161 size_t index
= start
;
163 if (end
> paths
.size())
166 // If this is an absolute path, paths[0] == "/". In this case, we don't want
167 // to add an additional / separator.
168 if (start
== 0 && end
> 0 && paths
[0] == "/") {
173 for (; index
< end
; index
++) {
174 out_path
+= paths
[index
];
183 StringArray_t
Path::Split(const std::string
& path
) {
184 StringArray_t path_split
;
185 StringArray_t components
;
187 sdk_util::SplitString(path
, '/', &path_split
);
190 components
.push_back("/");
192 // Copy path_split to components, removing empty path segments.
193 for (StringArray_t::const_iterator it
= path_split
.begin();
194 it
!= path_split
.end();
197 components
.push_back(*it
);
202 Path
& Path::operator=(const Path
& p
) {
207 Path
& Path::operator=(const std::string
& p
) {
211 } // namespace nacl_io