Eager Gesture Recognition on Aura
[chromium-blink-merge.git] / native_client_sdk / src / libraries / nacl_io / path.cc
blob10c93a96ee815b95511a99951bb6bc2b30b2113d
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.
5 #include "nacl_io/path.h"
7 #include <stdio.h>
8 #include <string.h>
9 #include <string>
11 #include "sdk_util/string_util.h"
13 namespace nacl_io {
15 Path::Path(const Path& path) {
16 paths_ = path.paths_;
19 Path::Path(const std::string& path) {
20 Set(path);
23 bool Path::IsAbsolute() const {
24 return !paths_.empty() && paths_[0] == "/";
27 const std::string& Path::Part(size_t index) const {
28 return paths_[index];
31 size_t Path::Size() const {
32 return paths_.size();
35 bool Path::IsRoot() const {
36 return paths_.empty() || (paths_.size() == 1 && paths_[0] == "/");
39 Path& Path::Append(const std::string& path) {
40 StringArray_t paths = Split(path);
41 if (paths.empty())
42 return *this;
44 for (size_t index = 0; index < paths.size(); index++) {
45 // Skip ROOT
46 if (paths_.size() && index == 0 && paths[0] == "/")
47 continue;
48 paths_.push_back(paths[index]);
51 paths_ = Normalize(paths_);
52 return *this;
55 Path& Path::Prepend(const std::string& path) {
56 StringArray_t paths = Split(path);
57 if (paths.empty())
58 return *this;
60 for (size_t index = 0; index < paths_.size(); index++) {
61 // Skip ROOT
62 if (index == 0 && paths_[0] == "/")
63 continue;
64 paths.push_back(paths_[index]);
67 paths_ = Normalize(paths);
68 return *this;
71 Path& Path::Set(const std::string& path) {
72 StringArray_t paths = Split(path);
73 paths_ = Normalize(paths);
74 return *this;
77 Path Path::Parent() const {
78 Path out;
79 out.paths_ = paths_;
80 if (out.paths_.size())
81 out.paths_.pop_back();
82 return out;
85 std::string Path::Basename() const {
86 if (paths_.size())
87 return paths_.back();
88 return std::string();
91 std::string Path::Join() const {
92 return Range(paths_, 0, paths_.size());
95 std::string Path::Range(size_t start, size_t end) const {
96 return Range(paths_, start, end);
99 StringArray_t Path::Split() const {
100 return paths_;
103 // static
104 StringArray_t Path::Normalize(const StringArray_t& paths) {
105 StringArray_t path_out;
107 for (size_t index = 0; index < paths.size(); index++) {
108 const std::string& curr = paths[index];
110 // Check if '/' was used excessively in the path.
111 // For example, in cd Desktop/////
112 if (curr == "/" && index != 0)
113 continue;
115 // Check for '.' in the path and remove it
116 if (curr == ".")
117 continue;
119 // Check for '..'
120 if (curr == "..") {
121 // If the path is empty, or "..", then add ".."
122 if (path_out.empty() || path_out.back() == "..") {
123 path_out.push_back(curr);
124 continue;
127 // If the path is at root, "/.." = "/"
128 if (path_out.back() == "/") {
129 continue;
132 // if we are already at root, then stay there (root/.. -> root)
133 if (path_out.back() == "/") {
134 continue;
137 // otherwise, pop off the top path component
138 path_out.pop_back();
139 continue;
142 // By now, we should have handled end cases so just append.
143 path_out.push_back(curr);
146 // If the path was valid, but now it's empty, return self
147 if (path_out.empty())
148 path_out.push_back(".");
150 return path_out;
153 // static
154 std::string Path::Join(const StringArray_t& paths) {
155 return Range(paths, 0, paths.size());
158 // static
159 std::string Path::Range(const StringArray_t& paths, size_t start, size_t end) {
160 std::string out_path;
161 size_t index = start;
163 if (end > paths.size())
164 end = paths.size();
166 // If this is an absolute path, paths[0] == "/". In this case, we don't want
167 // to add an additional / separator.
168 if (start == 0 && end > 0 && paths[0] == "/") {
169 out_path += "/";
170 index++;
173 for (; index < end; index++) {
174 out_path += paths[index];
175 if (index < end - 1)
176 out_path += "/";
179 return out_path;
182 // static
183 StringArray_t Path::Split(const std::string& path) {
184 StringArray_t path_split;
185 StringArray_t components;
187 sdk_util::SplitString(path, '/', &path_split);
189 if (path[0] == '/')
190 components.push_back("/");
192 // Copy path_split to components, removing empty path segments.
193 for (StringArray_t::const_iterator it = path_split.begin();
194 it != path_split.end();
195 ++it) {
196 if (!it->empty())
197 components.push_back(*it);
199 return components;
202 Path& Path::operator=(const Path& p) {
203 paths_ = p.paths_;
204 return *this;
207 Path& Path::operator=(const std::string& p) {
208 return Set(p);
211 } // namespace nacl_io