path.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Remove extra seperators
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)}
204