summaryrefslogtreecommitdiffstats
path: root/lib/libcxx/src/filesystem/operations.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libcxx/src/filesystem/operations.cpp')
-rw-r--r--lib/libcxx/src/filesystem/operations.cpp109
1 files changed, 92 insertions, 17 deletions
diff --git a/lib/libcxx/src/filesystem/operations.cpp b/lib/libcxx/src/filesystem/operations.cpp
index c9396b59cae..b4106188872 100644
--- a/lib/libcxx/src/filesystem/operations.cpp
+++ b/lib/libcxx/src/filesystem/operations.cpp
@@ -206,8 +206,20 @@ public:
return *this;
}
+ bool atEnd() const noexcept {
+ return State == PS_AtEnd;
+ }
+
+ bool inRootDir() const noexcept {
+ return State == PS_InRootDir;
+ }
+
+ bool inRootName() const noexcept {
+ return State == PS_InRootName;
+ }
+
bool inRootPath() const noexcept {
- return State == PS_InRootDir || State == PS_InRootName;
+ return inRootName() || inRootDir();
}
private:
@@ -427,7 +439,8 @@ file_status posix_lstat(path const& p, error_code* ec) {
return posix_lstat(p, path_stat, ec);
}
-bool posix_ftruncate(const FileDescriptor& fd, size_t to_size, error_code& ec) {
+// http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
+bool posix_ftruncate(const FileDescriptor& fd, off_t to_size, error_code& ec) {
if (::ftruncate(fd.fd, to_size) == -1) {
ec = capture_errno();
return true;
@@ -1294,7 +1307,19 @@ string_view_t path::__root_path_raw() const {
return {};
}
+static bool ConsumeRootName(PathParser *PP) {
+ static_assert(PathParser::PS_BeforeBegin == 1 &&
+ PathParser::PS_InRootName == 2,
+ "Values for enums are incorrect");
+ while (PP->State <= PathParser::PS_InRootName)
+ ++(*PP);
+ return PP->State == PathParser::PS_AtEnd;
+}
+
static bool ConsumeRootDir(PathParser* PP) {
+ static_assert(PathParser::PS_BeforeBegin == 1 &&
+ PathParser::PS_InRootName == 2 &&
+ PathParser::PS_InRootDir == 3, "Values for enums are incorrect");
while (PP->State <= PathParser::PS_InRootDir)
++(*PP);
return PP->State == PathParser::PS_AtEnd;
@@ -1454,7 +1479,7 @@ static int DetermineLexicalElementCount(PathParser PP) {
auto Elem = *PP;
if (Elem == "..")
--Count;
- else if (Elem != ".")
+ else if (Elem != "." && Elem != "")
++Count;
}
return Count;
@@ -1468,8 +1493,7 @@ path path::lexically_relative(const path& base) const {
return PP.State != PPBase.State &&
(PP.inRootPath() || PPBase.inRootPath());
};
- if (PP.State == PathParser::PS_InRootName &&
- PPBase.State == PathParser::PS_InRootName) {
+ if (PP.inRootName() && PPBase.inRootName()) {
if (*PP != *PPBase)
return {};
} else if (CheckIterMismatchAtBase())
@@ -1501,6 +1525,10 @@ path path::lexically_relative(const path& base) const {
if (ElemCount < 0)
return {};
+ // if n == 0 and (a == end() || a->empty()), returns path("."); otherwise
+ if (ElemCount == 0 && (PP.atEnd() || *PP == ""))
+ return ".";
+
// return a path constructed with 'n' dot-dot elements, followed by the the
// elements of '*this' after the mismatch.
path Result;
@@ -1514,21 +1542,68 @@ path path::lexically_relative(const path& base) const {
////////////////////////////////////////////////////////////////////////////
// path.comparisons
-int path::__compare(string_view_t __s) const {
- auto PP = PathParser::CreateBegin(__pn_);
- auto PP2 = PathParser::CreateBegin(__s);
- while (PP && PP2) {
- int res = (*PP).compare(*PP2);
- if (res != 0)
+static int CompareRootName(PathParser *LHS, PathParser *RHS) {
+ if (!LHS->inRootName() && !RHS->inRootName())
+ return 0;
+
+ auto GetRootName = [](PathParser *Parser) -> string_view_t {
+ return Parser->inRootName() ? **Parser : "";
+ };
+ int res = GetRootName(LHS).compare(GetRootName(RHS));
+ ConsumeRootName(LHS);
+ ConsumeRootName(RHS);
+ return res;
+}
+
+static int CompareRootDir(PathParser *LHS, PathParser *RHS) {
+ if (!LHS->inRootDir() && RHS->inRootDir())
+ return -1;
+ else if (LHS->inRootDir() && !RHS->inRootDir())
+ return 1;
+ else {
+ ConsumeRootDir(LHS);
+ ConsumeRootDir(RHS);
+ return 0;
+ }
+}
+
+static int CompareRelative(PathParser *LHSPtr, PathParser *RHSPtr) {
+ auto &LHS = *LHSPtr;
+ auto &RHS = *RHSPtr;
+
+ int res;
+ while (LHS && RHS) {
+ if ((res = (*LHS).compare(*RHS)) != 0)
return res;
- ++PP;
- ++PP2;
+ ++LHS;
+ ++RHS;
}
- if (PP.State == PP2.State && !PP)
- return 0;
- if (!PP)
+ return 0;
+}
+
+static int CompareEndState(PathParser *LHS, PathParser *RHS) {
+ if (LHS->atEnd() && !RHS->atEnd())
return -1;
- return 1;
+ else if (!LHS->atEnd() && RHS->atEnd())
+ return 1;
+ return 0;
+}
+
+int path::__compare(string_view_t __s) const {
+ auto LHS = PathParser::CreateBegin(__pn_);
+ auto RHS = PathParser::CreateBegin(__s);
+ int res;
+
+ if ((res = CompareRootName(&LHS, &RHS)) != 0)
+ return res;
+
+ if ((res = CompareRootDir(&LHS, &RHS)) != 0)
+ return res;
+
+ if ((res = CompareRelative(&LHS, &RHS)) != 0)
+ return res;
+
+ return CompareEndState(&LHS, &RHS);
}
////////////////////////////////////////////////////////////////////////////