path.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 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) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path::Path() {} 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path::Path(const Path& path) { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = path.paths_; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path::Path(const std::string& path) { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Set(path); 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path::~Path() {} 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Path::IsAbsolute() const { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !paths_.empty() && paths_[0] == "/"; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string& Path::Part(size_t index) const { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return paths_[index]; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t Path::Size() const { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return paths_.size(); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Path::Top() const { 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (paths_.size() == 0) || (paths_.size() == 1 && paths_[0] == "/"); 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path& Path::Append(const std::string& path) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t paths = Split(path); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t index = 0; index < paths.size(); index++) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip ROOT 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (paths_.size() && index == 0 && paths[0] == "/") continue; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_.push_back(paths[index]); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = Normalize(paths_); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path& Path::Prepend(const std::string& path) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t paths = Split(path); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t index = 0; index < paths_.size(); index++) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip ROOT 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index == 0 && paths_[0] == "/") continue; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths.push_back(paths[index]); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = Normalize(paths); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path& Path::Set(const std::string& path) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t paths = Split(path); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = Normalize(paths); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path Path::Parent() const { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Path out; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.paths_ = paths_; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (out.paths_.size()) out.paths_.pop_back(); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return out; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Basename() const { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (paths_.size()) return paths_.back(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Join() const { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Range(paths_, 0, paths_.size()); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Range(size_t start, size_t end) const { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Range(paths_, start, end); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StringArray_t Path::Split() const { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return paths_; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StringArray_t Path::Normalize(const StringArray_t& paths) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t path_out; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t index = 0; index < paths.size(); index++) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string &curr = paths[index]; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if '/' was used excessively in the path. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For example, in cd Desktop///// 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (curr == "/" && index != 0) continue; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for '.' in the path and remove it 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (curr == ".") continue; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for '..' 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (curr == "..") { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the path is empty, or "..", then add ".." 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_out.empty() || path_out.back() == "..") { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_out.push_back(curr); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the path is at root, "/.." = "/" 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_out.back() == "/") { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if we are already at root, then stay there (root/.. -> root) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_out.back() == "/") { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // otherwise, pop off the top path component 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_out.pop_back(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // By now, we should have handled end cases so just append. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_out.push_back(curr); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the path was valid, but now it's empty, return self 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_out.size() == 0) path_out.push_back("."); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path_out; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Join(const StringArray_t& paths) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Range(paths, 0, paths.size()); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Range(const StringArray_t& paths, size_t start, size_t end) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string out_path; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index = start; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (end > paths.size()) end = paths.size(); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If this is an absolute path, paths[0] == "/". In this case, we don't want 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to add an additional / separator. 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (start == 0 && end > 0 && paths[0] == "/") { 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) out_path += "/"; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index++; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; index < end; index++) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out_path += paths[index]; 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (index < end - 1) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) out_path += "/"; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return out_path; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StringArray_t Path::Split(const std::string& path) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t components; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t offs = 0; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t next = 0; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path[0] == '/') { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offs = 1; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) components.push_back("/"); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (next != std::string::npos) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next = path.find('/', offs); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Remove extra separators 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next == offs) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++offs; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string part = path.substr(offs, next - offs); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!part.empty()) components.push_back(part); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offs = next + 1; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return components; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path& Path::operator =(const Path& p) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = p.paths_; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path& Path::operator =(const std::string& p) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Set(p); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 205