[Bf-blender-cvs] [65e4d169baa] master: BLI_path: skip "/./" and "/." in BLI_path_name_at_index

Campbell Barton noreply at git.blender.org
Thu Nov 3 05:33:32 CET 2022


Commit: 65e4d169baa95e5f2dfbd65e5b4e995851a857df
Author: Campbell Barton
Date:   Thu Nov 3 15:28:01 2022 +1100
Branches: master
https://developer.blender.org/rB65e4d169baa95e5f2dfbd65e5b4e995851a857df

BLI_path: skip "/./" and "/." in BLI_path_name_at_index

This avoids having to run BLI_path_normalize before calling
BLI_path_name_at_index.

===================================================================

M	source/blender/blenlib/BLI_path_util.h
M	source/blender/blenlib/intern/path_util.c
M	source/blender/blenlib/tests/BLI_path_util_test.cc

===================================================================

diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index 1b723ab038d..4ea059391b6 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -202,7 +202,10 @@ const char *BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_
  * - 1 or -2: `path`
  * - 2 or -1: `file.txt`
  *
- * Ignores multiple slashes at any point in the path (including start/end).
+ * Ignored elements in the path:
+ * - Multiple slashes at any point in the path (including start/end).
+ * - Single '.' in the path: `/./` except for the beginning of the path
+ *   where it's used to signify a $PWD relative path.
  */
 bool BLI_path_name_at_index(const char *__restrict path,
                             int index,
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 3a87b39a446..179a1a305d1 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -1597,39 +1597,47 @@ const char *BLI_path_basename(const char *path)
   return filename ? filename + 1 : path;
 }
 
-bool BLI_path_name_at_index(const char *__restrict path,
-                            const int index,
-                            int *__restrict r_offset,
-                            int *__restrict r_len)
+static bool path_name_at_index_forward(const char *__restrict path,
+                                       const int index,
+                                       int *__restrict r_offset,
+                                       int *__restrict r_len)
 {
-  if (index >= 0) {
-    int index_step = 0;
-    int prev = -1;
-    int i = 0;
-    while (true) {
-      const char c = path[i];
-      if (ELEM(c, SEP, '\0')) {
-        if (prev + 1 != i) {
-          prev += 1;
+  BLI_assert(index >= 0);
+  int index_step = 0;
+  int prev = -1;
+  int i = 0;
+  while (true) {
+    const char c = path[i];
+    if (ELEM(c, SEP, '\0')) {
+      if (prev + 1 != i) {
+        prev += 1;
+        /* Skip '/./' (behave as if they don't exist). */
+        if (!((i - prev == 1) && (prev != 0) && (path[prev] == '.'))) {
           if (index_step == index) {
             *r_offset = prev;
             *r_len = i - prev;
-            // printf("!!! %d %d\n", start, end);
             return true;
           }
           index_step += 1;
         }
-        if (c == '\0') {
-          break;
-        }
-        prev = i;
       }
-      i += 1;
+      if (c == '\0') {
+        break;
+      }
+      prev = i;
     }
-    return false;
+    i += 1;
   }
+  return false;
+}
 
-  /* negative number, reverse where -1 is the last element */
+static bool path_name_at_index_backward(const char *__restrict path,
+                                        const int index,
+                                        int *__restrict r_offset,
+                                        int *__restrict r_len)
+{
+  /* Negative number, reverse where -1 is the last element. */
+  BLI_assert(index < 0);
   int index_step = -1;
   int prev = strlen(path);
   int i = prev - 1;
@@ -1638,12 +1646,15 @@ bool BLI_path_name_at_index(const char *__restrict path,
     if (ELEM(c, SEP, '\0')) {
       if (prev - 1 != i) {
         i += 1;
-        if (index_step == index) {
-          *r_offset = i;
-          *r_len = prev - i;
-          return true;
+        /* Skip '/./' (behave as if they don't exist). */
+        if (!((prev - i == 1) && (i != 0) && (path[i] == '.'))) {
+          if (index_step == index) {
+            *r_offset = i;
+            *r_len = prev - i;
+            return true;
+          }
+          index_step -= 1;
         }
-        index_step -= 1;
       }
       if (c == '\0') {
         break;
@@ -1655,6 +1666,15 @@ bool BLI_path_name_at_index(const char *__restrict path,
   return false;
 }
 
+bool BLI_path_name_at_index(const char *__restrict path,
+                            const int index,
+                            int *__restrict r_offset,
+                            int *__restrict r_len)
+{
+  return (index >= 0) ? path_name_at_index_forward(path, index, r_offset, r_len) :
+                        path_name_at_index_backward(path, index, r_offset, r_len);
+}
+
 bool BLI_path_contains(const char *container_path, const char *containee_path)
 {
   char container_native[PATH_MAX];
diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc
index 293d353efcc..9d5422d62ff 100644
--- a/source/blender/blenlib/tests/BLI_path_util_test.cc
+++ b/source/blender/blenlib/tests/BLI_path_util_test.cc
@@ -259,6 +259,64 @@ TEST(path_util, NameAtIndex_MiscNeg)
   AT_INDEX("/how/now/brown/cow/", 4, nullptr);
 }
 
+#define TEST_STR "./a/./b/./c/."
+
+TEST(path_util, NameAtIndex_SingleDot)
+{
+  AT_INDEX(TEST_STR, 0, ".");
+  AT_INDEX(TEST_STR, 1, "a");
+  AT_INDEX(TEST_STR, 2, "b");
+  AT_INDEX(TEST_STR, 3, "c");
+  AT_INDEX(TEST_STR, 4, nullptr);
+}
+
+TEST(path_util, NameAtIndex_SingleDotNeg)
+{
+  AT_INDEX(TEST_STR, -5, nullptr);
+  AT_INDEX(TEST_STR, -4, ".");
+  AT_INDEX(TEST_STR, -3, "a");
+  AT_INDEX(TEST_STR, -2, "b");
+  AT_INDEX(TEST_STR, -1, "c");
+}
+
+#undef TEST_STR
+
+#define TEST_STR ".//a//.//b//.//c//.//"
+
+TEST(path_util, NameAtIndex_SingleDotDoubleSlash)
+{
+  AT_INDEX(TEST_STR, 0, ".");
+  AT_INDEX(TEST_STR, 1, "a");
+  AT_INDEX(TEST_STR, 2, "b");
+  AT_INDEX(TEST_STR, 3, "c");
+  AT_INDEX(TEST_STR, 4, nullptr);
+}
+
+TEST(path_util, NameAtIndex_SingleDotDoubleSlashNeg)
+{
+  AT_INDEX(TEST_STR, -5, nullptr);
+  AT_INDEX(TEST_STR, -4, ".");
+  AT_INDEX(TEST_STR, -3, "a");
+  AT_INDEX(TEST_STR, -2, "b");
+  AT_INDEX(TEST_STR, -1, "c");
+}
+
+#undef TEST_STR
+
+TEST(path_util, NameAtIndex_SingleDotSeries)
+{
+  AT_INDEX("abc/././/././xyz", 0, "abc");
+  AT_INDEX("abc/././/././xyz", 1, "xyz");
+  AT_INDEX("abc/././/././xyz", 2, nullptr);
+}
+
+TEST(path_util, NameAtIndex_SingleDotSeriesNeg)
+{
+  AT_INDEX("abc/././/././xyz", -3, nullptr);
+  AT_INDEX("abc/././/././xyz", -2, "abc");
+  AT_INDEX("abc/././/././xyz", -1, "xyz");
+}
+
 TEST(path_util, NameAtIndex_MiscComplex)
 {
   AT_INDEX("how//now/brown/cow", 0, "how");



More information about the Bf-blender-cvs mailing list