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 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path::Path(const Path& path) { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = path.paths_; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path::Path(const std::string& path) { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Set(path); 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 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) 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool Path::IsRoot() const { 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return paths_.empty() || (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); 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (paths.empty()) 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return *this; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t index = 0; index < paths.size(); index++) { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip ROOT 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (paths_.size() && index == 0 && paths[0] == "/") 4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_.push_back(paths[index]); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = Normalize(paths_); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path& Path::Prepend(const std::string& path) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t paths = Split(path); 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (paths.empty()) 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return *this; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t index = 0; index < paths_.size(); index++) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip ROOT 6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (index == 0 && paths_[0] == "/") 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) paths.push_back(paths_[index]); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = Normalize(paths); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path& Path::Set(const std::string& path) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t paths = Split(path); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = Normalize(paths); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Path Path::Parent() const { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Path out; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.paths_ = paths_; 8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (out.paths_.size()) 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) out.paths_.pop_back(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return out; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Basename() const { 8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (paths_.size()) 8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return paths_.back(); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Join() const { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Range(paths_, 0, paths_.size()); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Range(size_t start, size_t end) const { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Range(paths_, start, end); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StringArray_t Path::Split() const { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return paths_; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StringArray_t Path::Normalize(const StringArray_t& paths) { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t path_out; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t index = 0; index < paths.size(); index++) { 10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& curr = paths[index]; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if '/' was used excessively in the path. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For example, in cd Desktop///// 11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (curr == "/" && index != 0) 11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for '.' in the path and remove it 11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (curr == ".") 11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for '..' 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (curr == "..") { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the path is empty, or "..", then add ".." 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_out.empty() || path_out.back() == "..") { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_out.push_back(curr); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the path is at root, "/.." = "/" 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_out.back() == "/") { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if we are already at root, then stay there (root/.. -> root) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_out.back() == "/") { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // otherwise, pop off the top path component 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_out.pop_back(); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // By now, we should have handled end cases so just append. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_out.push_back(curr); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the path was valid, but now it's empty, return self 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (path_out.empty()) 14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) path_out.push_back("."); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path_out; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Join(const StringArray_t& paths) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Range(paths, 0, paths.size()); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Path::Range(const StringArray_t& paths, size_t start, size_t end) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string out_path; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index = start; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (end > paths.size()) 16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) end = paths.size(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If this is an absolute path, paths[0] == "/". In this case, we don't want 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to add an additional / separator. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (start == 0 && end > 0 && paths[0] == "/") { 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) out_path += "/"; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index++; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; index < end; index++) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out_path += paths[index]; 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (index < end - 1) 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) out_path += "/"; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return out_path; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StringArray_t Path::Split(const std::string& path) { 18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) StringArray_t path_split; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringArray_t components; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) sdk_util::SplitString(path, '/', &path_split); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (path[0] == '/') 19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) components.push_back("/"); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Copy path_split to components, removing empty path segments. 19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) for (StringArray_t::const_iterator it = path_split.begin(); 19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != path_split.end(); 19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ++it) { 19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!it->empty()) 19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) components.push_back(*it); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return components; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Path& Path::operator=(const Path& p) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_ = p.paths_; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Path& Path::operator=(const std::string& p) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Set(p); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 211ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} // namespace nacl_io 212