| 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 |