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