From 4c84d5f5469ec469732a5656e3b601bd54c2d2a7 Mon Sep 17 00:00:00 2001 From: Gil Date: Tue, 5 Jun 2018 14:31:36 -0700 Subject: Add pathname manipulation utilities (#1376) --- .../src/firebase/firestore/util/CMakeLists.txt | 2 + Firestore/core/src/firebase/firestore/util/path.cc | 84 +++++++++++++++++ Firestore/core/src/firebase/firestore/util/path.h | 101 +++++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 Firestore/core/src/firebase/firestore/util/path.cc create mode 100644 Firestore/core/src/firebase/firestore/util/path.h (limited to 'Firestore/core/src') diff --git a/Firestore/core/src/firebase/firestore/util/CMakeLists.txt b/Firestore/core/src/firebase/firestore/util/CMakeLists.txt index 30589a0..b2c4195 100644 --- a/Firestore/core/src/firebase/firestore/util/CMakeLists.txt +++ b/Firestore/core/src/firebase/firestore/util/CMakeLists.txt @@ -184,6 +184,8 @@ cc_library( iterator_adaptors.h ordered_code.cc ordered_code.h + path.cc + path.h range.h secure_random.h status.cc diff --git a/Firestore/core/src/firebase/firestore/util/path.cc b/Firestore/core/src/firebase/firestore/util/path.cc new file mode 100644 index 0000000..940f12a --- /dev/null +++ b/Firestore/core/src/firebase/firestore/util/path.cc @@ -0,0 +1,84 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/core/src/firebase/firestore/util/path.h" + +namespace firebase { +namespace firestore { +namespace util { + +absl::string_view Path::Basename(absl::string_view pathname) { + size_t slash = pathname.find_last_of('/'); + + if (slash == absl::string_view::npos) { + // No path separator found => the whole string. + return pathname; + } + + // Otherwise everything after the slash is the basename (even if empty string) + return pathname.substr(slash + 1); +} + +absl::string_view Path::Dirname(absl::string_view pathname) { + size_t last_slash = pathname.find_last_of('/'); + + if (last_slash == absl::string_view::npos) { + // No path separator found => empty string. Conformance with POSIX would + // have us return "." here. + return pathname.substr(0, 0); + } + + // Collapse runs of slashes. + size_t nonslash = pathname.find_last_not_of('/', last_slash); + if (nonslash == absl::string_view::npos) { + // All characters preceding the last path separator are slashes + return pathname.substr(0, 1); + } + + last_slash = nonslash + 1; + + // Otherwise everything up to the slash is the parent directory + return pathname.substr(0, last_slash); +} + +bool Path::IsAbsolute(absl::string_view path) { +#if defined(_WIN32) +#error "Handle drive letters" + +#else + return !path.empty() && path.front() == '/'; +#endif +} + +void Path::JoinAppend(std::string* base, absl::string_view path) { + if (IsAbsolute(path)) { + base->assign(path.data(), path.size()); + + } else { + size_t nonslash = base->find_last_not_of('/'); + if (nonslash != std::string::npos) { + base->resize(nonslash + 1); + base->push_back('/'); + } + + // If path started with a slash we'd treat it as absolute above + base->append(path.data(), path.size()); + } +} + +} // namespace util +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/firebase/firestore/util/path.h b/Firestore/core/src/firebase/firestore/util/path.h new file mode 100644 index 0000000..3eda40a --- /dev/null +++ b/Firestore/core/src/firebase/firestore/util/path.h @@ -0,0 +1,101 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_PATH_H_ +#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_PATH_H_ + +#include +#include + +#include "absl/strings/string_view.h" + +namespace firebase { +namespace firestore { +namespace util { + +struct Path { + /** + * Returns the unqualified trailing part of the pathname, e.g. "c" for + * "/a/b/c". + */ + static absl::string_view Basename(absl::string_view pathname); + + /** + * Returns the parent directory name, e.g. "/a/b" for "/a/b/c". + * + * Note: + * * Trailing slashes are treated as a separator between an empty path + * segment and the dirname, so Dirname("/a/b/c/") is "/a/b/c". + * * Runs of more than one slash are treated as a single separator, so + * Dirname("/a/b//c") is "/a/b". + * * Paths are not canonicalized, so Dirname("/a//b//c") is "/a//b". + * * Presently only UNIX style paths are supported (but compilation + * intentionally fails on Windows to prompt implementation there). + */ + static absl::string_view Dirname(absl::string_view pathname); + + /** + * Returns true if the given `pathname` is an absolute path. + */ + static bool IsAbsolute(absl::string_view pathname); + + /** + * Returns the paths separated by path separators. + * + * @param base If base is of type std::string&& the result is moved from this + * value. Otherwise the first argument is copied. + * @param paths The rest of the path segments. + */ + template + static std::string Join(S1&& base, const SA&... paths) { + std::string result{std::forward(base)}; + JoinAppend(&result, paths...); + return result; + } + + /** + * Returns the paths separated by path separators. + */ + static std::string Join() { + return {}; + } + + private: + /** + * Joins the given base path with a suffix. If `path` is relative, appends it + * to the given base path. If `path` is absolute, replaces `base`. + */ + static void JoinAppend(std::string* base, absl::string_view path); + + template + static void JoinAppend(std::string* base, + absl::string_view path, + const S&... rest) { + JoinAppend(base, path); + JoinAppend(base, rest...); + } + + static void JoinAppend(std::string* base) { + // Recursive base case; nothing to do. + (void)base; + } +}; + +} // namespace util +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_PATH_H_ -- cgit v1.2.3