]> Kevux Git Server - fll/commitdiff
Update: add path expode using normal order
authorKevin Day <thekevinday@gmail.com>
Sun, 17 May 2020 03:42:49 +0000 (22:42 -0500)
committerKevin Day <thekevinday@gmail.com>
Sun, 17 May 2020 03:42:49 +0000 (22:42 -0500)
Oops.

For reasons unknown to me, I seem to have written the path explode in reverse order.
The path is intended to be processed from left to right.

Rename the old functions appending _reverse to their name.

level_0/f_path/c/path.c
level_0/f_path/c/path.h

index c5aae1c9fac1c72faff598ee1bbdd0cfb7f03f34..6b2e988509586a906c443de1ed7a4f9e0e7163ef 100644 (file)
@@ -15,8 +15,207 @@ extern "C" {
     const f_string_length length = strnlen(path, PATH_MAX);
 
     if (length == 0) {
-      // When PATH is "", this is actually a valid search path for CWD.
-      // Therefore append an equivalent representation of CWD (string used length is 0).
+      // When PATH is "", this is actually a valid search path for PWD.
+      // Therefore append an equivalent representation of PWD (string used length is 0).
+      if (paths->used + 1 > paths->size) {
+        if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
+          if (paths->size + 1 > f_array_length_size) {
+            return f_status_set_error(f_buffer_too_large);
+          }
+
+          f_macro_string_dynamics_resize(status, (*paths), paths->used + 1);
+          if (f_status_is_error(status)) return status;
+        }
+        else {
+          f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step);
+          if (f_status_is_error(status)) return status;
+        }
+      }
+
+      f_macro_string_dynamic_clear(paths->array[paths->used]);
+      paths->used++;
+
+      return f_none;
+    }
+
+    f_string_length i = length;
+    f_string_length first = 0;
+    f_string_length total = 0;
+
+    for (i = 0; i <= length; i++) {
+      if (i == length || path[i] == f_path_separator_variable[0]) {
+        if (paths->used + 1 > paths->size) {
+          if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
+            if (paths->size + 1 > f_array_length_size) {
+              return f_status_set_error(f_buffer_too_large);
+            }
+
+            f_macro_string_dynamics_resize(status, (*paths), paths->used + 1);
+            if (f_status_is_error(status)) return status;
+          }
+          else {
+            f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step);
+            if (f_status_is_error(status)) return status;
+          }
+        }
+
+        if (i == 0) {
+          f_macro_string_dynamic_clear(paths->array[paths->used]);
+          paths->used++;
+
+          first = 1;
+          continue;
+        }
+
+        f_string_dynamic part = f_string_dynamic_initialize;
+
+        total = i - first;
+
+        if (total > 0) {
+          if (path[i - 1] == f_path_separator[0]) {
+            f_macro_string_dynamic_new(status, part, total);
+            if (f_status_is_error(status)) return status;
+
+            part.used = total;
+          }
+          else {
+            f_macro_string_dynamic_new(status, part, total + 1);
+            if (f_status_is_error(status)) return status;
+
+            part.string[total] = f_path_separator[0];
+            part.used = total + 1;
+          }
+
+          memcpy(part.string, path + first, total);
+        }
+
+        paths->array[paths->used].string = part.string;
+        paths->array[paths->used].used = part.used;
+        paths->array[paths->used].size = part.size;
+        paths->used++;
+
+        first = i + 1;
+      }
+    } // for
+
+    return f_none;
+  }
+#endif // _di_f_path_explode_
+
+#ifndef _di_f_path_explode_dynamic_
+  f_return_status f_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths) {
+    #ifndef _di_level_0_parameter_checking_
+      if (path.used > path.size) return f_status_set_error(f_invalid_parameter);
+      if (paths == 0) return f_status_set_error(f_invalid_parameter);
+      if (paths->used > paths->size) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    f_status status = f_none;
+
+    if (path.used == 0) {
+      // When PATH is "", this is actually a valid search path for PWD.
+      // Therefore append an equivalent representation of PWD (string used length is 0).
+      if (paths->used + 1 > paths->size) {
+        if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
+          if (paths->size + 1 > f_array_length_size) {
+            return f_status_set_error(f_buffer_too_large);
+          }
+
+          f_macro_string_dynamics_resize(status, (*paths), paths->used + 1);
+          if (f_status_is_error(status)) return status;
+        }
+        else {
+          f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step);
+          if (f_status_is_error(status)) return status;
+        }
+      }
+
+      f_macro_string_dynamic_clear(paths->array[paths->used]);
+      paths->used++;
+
+      return f_none;
+    }
+
+    f_string_length i = 0;
+    f_string_length j = 0;
+    f_string_length first = 0;
+    f_string_length total = 0;
+
+    f_string_dynamic part = f_string_dynamic_initialize;
+
+    for (i = 0; i <= path.used; i++) {
+      if (i == path.used || path.string[i] == f_path_separator_variable[0]) {
+        if (paths->used + 1 > paths->size) {
+          if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
+            if (paths->size + 1 > f_array_length_size) {
+              return f_status_set_error(f_buffer_too_large);
+            }
+
+            f_macro_string_dynamics_resize(status, (*paths), paths->used + 1);
+            if (f_status_is_error(status)) return status;
+          }
+          else {
+            f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step);
+            if (f_status_is_error(status)) return status;
+          }
+        }
+
+        if (i == 0) {
+          f_macro_string_dynamic_clear(paths->array[paths->used]);
+          paths->used++;
+
+          first = 1;
+          continue;
+        }
+
+        total = i - first;
+
+        if (total > 0) {
+          f_macro_string_dynamic_new(status, part, total);
+          if (f_status_is_error(status)) return status;
+
+          for (j = 0; j < total; j++) {
+            if (path.string[first + j] == 0) continue;
+
+            part.string[part.used] = path.string[first + j];
+            part.used++;
+          } // for
+
+          if (part.string[part.used - 1] != f_path_separator[0]) {
+            f_macro_string_dynamic_resize(status, part, total + 1);
+            if (f_status_is_error(status)) return status;
+
+            part.string[part.used] = f_path_separator[0];
+            part.used++;
+          }
+        }
+
+        paths->array[paths->used].string = part.string;
+        paths->array[paths->used].used = part.used;
+        paths->array[paths->used].size = part.size;
+        paths->used++;
+
+        first = i + 1;
+      }
+    } // for
+
+    return f_none;
+  }
+#endif // _di_f_path_explode_dynamic_
+
+#ifndef _di_f_path_explode_reverse_
+  f_return_status f_path_explode_reverse(const f_string path, f_string_dynamics *paths) {
+    #ifndef _di_level_0_parameter_checking_
+      if (paths == 0) return f_status_set_error(f_invalid_parameter);
+      if (paths->used > paths->size) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    f_status status = f_none;
+    const f_string_length length = strnlen(path, PATH_MAX);
+
+    if (length == 0) {
+      // When PATH is "", this is actually a valid search path for PWD.
+      // Therefore append an equivalent representation of PWD (string used length is 0).
       if (paths->used + 1 > paths->size) {
         if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
           if (paths->size + 1 > f_array_length_size) {
@@ -45,6 +244,8 @@ extern "C" {
     f_string_length last = length;
     f_string_length total = 0;
 
+    f_string_dynamic part = f_string_dynamic_initialize;
+
     for (; i > 0; i--) {
       j--;
 
@@ -64,8 +265,6 @@ extern "C" {
           }
         }
 
-        f_string_dynamic part = f_string_dynamic_initialize;
-
         if (path[j] == f_path_separator_variable[0]) {
           total = last - i;
 
@@ -121,10 +320,10 @@ extern "C" {
 
     return f_none;
   }
-#endif // _di_f_path_explode_
+#endif // _di_f_path_explode_reverse_
 
-#ifndef _di_f_path_explode_dynamic_
-  f_return_status f_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths) {
+#ifndef _di_f_path_explode_reverse_dynamic_
+  f_return_status f_path_explode_reverse_dynamic(const f_string_static path, f_string_dynamics *paths) {
     #ifndef _di_level_0_parameter_checking_
       if (path.used > path.size) return f_status_set_error(f_invalid_parameter);
       if (paths == 0) return f_status_set_error(f_invalid_parameter);
@@ -134,8 +333,8 @@ extern "C" {
     f_status status = f_none;
 
     if (path.used == 0) {
-      // When PATH is "", this is actually a valid search path for CWD.
-      // Therefore append an equivalent representation of CWD (string used length is 0).
+      // When PATH is "", this is actually a valid search path for PWD.
+      // Therefore append an equivalent representation of PWD (string used length is 0).
       if (paths->used + 1 > paths->size) {
         if (paths->size + f_memory_default_allocation_step > f_array_length_size) {
           if (paths->size + 1 > f_array_length_size) {
@@ -151,9 +350,7 @@ extern "C" {
         }
       }
 
-      paths->array[paths->used].string = 0;
-      paths->array[paths->used].used = 0;
-      paths->array[paths->used].size = 0;
+      f_macro_string_dynamic_clear(paths->array[paths->used]);
       paths->used++;
 
       return f_none;
@@ -165,6 +362,8 @@ extern "C" {
     f_string_length last = path.used;
     f_string_length total = 0;
 
+    f_string_dynamic part = f_string_dynamic_initialize;
+
     for (; i > 0; i--) {
       j--;
 
@@ -184,13 +383,11 @@ extern "C" {
           }
         }
 
-        f_string_dynamic part = f_string_dynamic_initialize;
-
         if (path.string[j] == f_path_separator_variable[0]) {
           total = last - i;
 
           if (total > 0) {
-            f_macro_string_dynamic_new(status, part, total + 1);
+            f_macro_string_dynamic_new(status, part, total);
             if (f_status_is_error(status)) return status;
 
             for (k = 0; k < total; k++) {
@@ -201,6 +398,9 @@ extern "C" {
             } // for
 
             if (part.string[part.used - 1] != f_path_separator[0]) {
+              f_macro_string_dynamic_resize(status, part, total + 1);
+              if (f_status_is_error(status)) return status;
+
               part.string[part.used] = f_path_separator[0];
               part.used++;
             }
@@ -212,7 +412,7 @@ extern "C" {
           // when j = 0, the total is actually the entire length to max.
           total = last - j;
 
-          f_macro_string_dynamic_new(status, part, total + 1);
+          f_macro_string_dynamic_new(status, part, total);
           if (f_status_is_error(status)) return status;
 
           for (k = 0; k < total; k++) {
@@ -223,6 +423,9 @@ extern "C" {
           } // for
 
           if (part.string[part.used - 1] != f_path_separator[0]) {
+            f_macro_string_dynamic_resize(status, part, total + 1);
+            if (f_status_is_error(status)) return status;
+
             part.string[part.used - 1] = f_path_separator[0];
             part.used++;
           }
@@ -237,7 +440,7 @@ extern "C" {
 
     return f_none;
   }
-#endif // _di_f_path_explode_dynamic_
+#endif // _di_f_path_explode_reverse_dynamic_
 
 #ifdef __cplusplus
 } // extern "C"
index 149a91a7c6ddbfa24e0ea7950942ec7e860f35c4..481c8f535bfc3be5affb657a3afb43bcf0dda3e1 100644 (file)
@@ -100,6 +100,58 @@ extern "C" {
   extern f_return_status f_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths);
 #endif // _di_f_path_explode_dynamic_
 
+/**
+ * Separate a given PATH-style string into multiple separate paths.
+ *
+ * The paths are created in reverse order.
+ *
+ * @param path
+ *   The string to process that is expected to follow the traditional Linux standard PATH environment variable.
+ *   Each seperate path is separated by a single ':'.
+ *   Must not contain NULLs except for the terminating NULL.
+ *   Must be NULL terminated.
+ * @param paths
+ *   All of the strings exploded from PATH.
+ *   Each exploded path, when not empty, is guaranteed to have a trailing '/'.
+ *   Each exploded path is not NULL terminated.
+ *
+ * @return
+ *   f_none on success.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_reallocation (with error bit) on reallocation error.
+ *   f_error_allocation (with error bit) on allocation error.
+ *   f_buffer_too_large (with error bit) if paths array is too large for further addressing.
+ */
+#ifndef _di_f_path_explode_reverse_
+  extern f_return_status f_path_explode_reverse(const f_string path, f_string_dynamics *paths);
+#endif // _di_f_path_explode_reverse_
+
+/**
+ * Separate a given PATH-style string into multiple separate paths.
+ *
+ * The paths are created in reverse order.
+ *
+ * @param path
+ *   The string to process that is expected to follow the traditional Linux standard PATH environment variable.
+ *   Each seperate path is separated by a single ':'.
+ *   Need not be NULL terminated.
+ *   NULLs are ignored and are not copied into the exploded paths.
+ * @param paths
+ *   All of the strings exploded from PATH.
+ *   Each exploded path, when not empty, is guaranteed to have a trailing '/'.
+ *   Each exploded path is not NULL terminated.
+ *
+ * @return
+ *   f_none on success.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_reallocation (with error bit) on reallocation error.
+ *   f_error_allocation (with error bit) on allocation error.
+ *   f_buffer_too_large (with error bit) if paths array is too large for further addressing.
+ */
+#ifndef _di_f_path_explode_reverse_dynamic_
+  extern f_return_status f_path_explode_reverse_dynamic(const f_string_static path, f_string_dynamics *paths);
+#endif // _di_f_path_explode_reverse_dynamic_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif