path.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file. 4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/path.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "sdk_util/string_util.h" 1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace nacl_io { 14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Path::Path() { 1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path::Path(const Path& path) { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = path.paths_; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path::Path(const std::string& path) { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Set(path); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Path::~Path() { 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Path::IsAbsolute() const { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !paths_.empty() && paths_[0] == "/"; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string& Path::Part(size_t index) const { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return paths_[index]; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t Path::Size() const { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return paths_.size(); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Path::Top() const { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (paths_.size() == 0) || (paths_.size() == 1 && paths_[0] == "/"); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path& Path::Append(const std::string& path) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t paths = Split(path); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t index = 0; index < paths.size(); index++) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip ROOT 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (paths_.size() && index == 0 && paths[0] == "/") 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_.push_back(paths[index]); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = Normalize(paths_); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path& Path::Prepend(const std::string& path) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t paths = Split(path); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t index = 0; index < paths_.size(); index++) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip ROOT 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (index == 0 && paths_[0] == "/") 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths.push_back(paths[index]); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = Normalize(paths); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path& Path::Set(const std::string& path) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t paths = Split(path); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = Normalize(paths); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path Path::Parent() const { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Path out; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.paths_ = paths_; 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (out.paths_.size()) 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) out.paths_.pop_back(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return out; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Basename() const { 8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (paths_.size()) 8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return paths_.back(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Join() const { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Range(paths_, 0, paths_.size()); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Range(size_t start, size_t end) const { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Range(paths_, start, end); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StringArray_t Path::Split() const { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return paths_; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StringArray_t Path::Normalize(const StringArray_t& paths) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t path_out; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t index = 0; index < paths.size(); index++) { 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& curr = paths[index]; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if '/' was used excessively in the path. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For example, in cd Desktop///// 11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (curr == "/" && index != 0) 11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for '.' in the path and remove it 11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (curr == ".") 11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for '..' 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (curr == "..") { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the path is empty, or "..", then add ".." 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_out.empty() || path_out.back() == "..") { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_out.push_back(curr); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the path is at root, "/.." = "/" 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_out.back() == "/") { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if we are already at root, then stay there (root/.. -> root) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_out.back() == "/") { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // otherwise, pop off the top path component 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_out.pop_back(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // By now, we should have handled end cases so just append. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_out.push_back(curr); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the path was valid, but now it's empty, return self 14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (path_out.size() == 0) 14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) path_out.push_back("."); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path_out; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Join(const StringArray_t& paths) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Range(paths, 0, paths.size()); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Range(const StringArray_t& paths, size_t start, size_t end) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string out_path; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index = start; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (end > paths.size()) 16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) end = paths.size(); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If this is an absolute path, paths[0] == "/". In this case, we don't want 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to add an additional / separator. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (start == 0 && end > 0 && paths[0] == "/") { 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) out_path += "/"; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index++; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; index < end; index++) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out_path += paths[index]; 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (index < end - 1) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) out_path += "/"; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return out_path; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StringArray_t Path::Split(const std::string& path) { 18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) StringArray_t path_split; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t components; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) sdk_util::SplitString(path, '/', &path_split); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (path[0] == '/') 19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) components.push_back("/"); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Copy path_split to components, removing empty path segments. 19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) for (StringArray_t::const_iterator it = path_split.begin(); 19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != path_split.end(); 19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ++it) { 19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!it->empty()) 19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) components.push_back(*it); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return components; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Path& Path::operator=(const Path& p) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = p.paths_; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Path& Path::operator=(const std::string& p) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Set(p); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 212ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} // namespace nacl_io 213