]> git.seodisparate.com - SimpleArchiver/commitdiff
Split "rel-path-from-abs-paths" into function
authorStephen Seo <seo.disparate@gmail.com>
Wed, 2 Oct 2024 04:15:30 +0000 (13:15 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Wed, 2 Oct 2024 06:11:23 +0000 (15:11 +0900)
CMakeLists.txt
src/archiver.c
src/archiver.h
src/test.c

index 6bed693ff1c24b881a57aceae3f45e4fef873fc8..4b53330feb855738ee19aabd5c6ed1c65c68af83 100644 (file)
@@ -83,6 +83,7 @@ add_executable(test_simplearchiver
     src/test.c
     src/parser.c
     src/helpers.c
+    src/archiver.c
     src/algorithms/linear_congruential_gen.c
     src/data_structures/linked_list.c
     src/data_structures/hash_map.c
index b50a8b88f54a160a8a07ba64aa71a64fc3deb4b8..b151dca234f1527297fe62d57679d49048049c62 100644 (file)
@@ -767,46 +767,8 @@ int write_files_fn(void *data, void *ud) {
         // fprintf(stderr, "DEBUG: abs_path: %s\nDEBUG: link_abs_path: %s\n",
         //                 (char*)abs_path, (char*)link_abs_path);
 
-        // Compare paths to get relative path.
-        // Get first non-common char.
-        size_t idx;
-        size_t last_slash;
-        for (idx = 0, last_slash = 0;
-             idx < strlen(abs_path) && idx < strlen(link_abs_path); ++idx) {
-          if (((const char *)abs_path)[idx] !=
-              ((const char *)link_abs_path)[idx]) {
-            break;
-          } else if (((const char *)abs_path)[idx] == '/') {
-            last_slash = idx + 1;
-          }
-        }
-        // Get substrings of both paths.
-        char *link_substr = (char *)link_abs_path + last_slash;
-        char *dest_substr = (char *)abs_path + last_slash;
-        rel_path = malloc(strlen(dest_substr) + 1);
-        strncpy(rel_path, dest_substr, strlen(dest_substr) + 1);
-        // fprintf(stderr, "DEBUG: link_substr: %s\nDEBUG: dest_substr: %s\n",
-        //         link_substr, dest_substr);
-
-        // Generate the relative path.
-        int_fast8_t has_slash = 0;
-        idx = 0;
-        do {
-          for (; link_substr[idx] != '/' && link_substr[idx] != 0; ++idx);
-          if (link_substr[idx] == 0) {
-            has_slash = 0;
-          } else {
-            has_slash = 1;
-            char *new_rel_path = malloc(strlen(rel_path) + 1 + 3);
-            new_rel_path[0] = '.';
-            new_rel_path[1] = '.';
-            new_rel_path[2] = '/';
-            strncpy(new_rel_path + 3, rel_path, strlen(rel_path) + 1);
-            free(rel_path);
-            rel_path = new_rel_path;
-            ++idx;
-          }
-        } while (has_slash);
+        rel_path =
+            simple_archiver_filenames_to_relative_path(link_abs_path, abs_path);
       }
     }
 
@@ -3015,3 +2977,53 @@ int simple_archiver_de_compress(int pipe_fd_in[2], int pipe_fd_out[2],
   return 1;
 #endif
 }
+
+char *simple_archiver_filenames_to_relative_path(const char *from_abs,
+                                                 const char *to_abs) {
+  if (!from_abs || !to_abs) {
+    return NULL;
+  }
+
+  // Get first non-common char and last slash before it.
+  uint_fast32_t idx;
+  uint_fast32_t last_slash;
+  for (idx = 0, last_slash = 0; idx < strlen(from_abs) && idx < strlen(to_abs);
+       ++idx) {
+    if (((const char *)to_abs)[idx] != ((const char *)from_abs)[idx]) {
+      break;
+    } else if (((const char *)to_abs)[idx] == '/') {
+      last_slash = idx + 1;
+    }
+  }
+
+  // Get substrings of both paths.
+  char *link_substr = (char *)from_abs + last_slash;
+  char *dest_substr = (char *)to_abs + last_slash;
+  char *rel_path = malloc(strlen(dest_substr) + 1);
+  strncpy(rel_path, dest_substr, strlen(dest_substr) + 1);
+
+  // fprintf(stderr, "DEBUG: link_substr \"%s\", dest_substr \"%s\"\n",
+  //     link_substr, dest_substr);
+
+  // Get the relative path finally.
+  int_fast8_t has_slash = 0;
+  idx = 0;
+  do {
+    for (; link_substr[idx] != '/' && link_substr[idx] != 0; ++idx);
+    if (link_substr[idx] == 0) {
+      has_slash = 0;
+    } else {
+      has_slash = 1;
+      char *new_rel_path = malloc(strlen(rel_path) + 1 + 3);
+      new_rel_path[0] = '.';
+      new_rel_path[1] = '.';
+      new_rel_path[2] = '/';
+      strncpy(new_rel_path + 3, rel_path, strlen(rel_path) + 1);
+      free(rel_path);
+      rel_path = new_rel_path;
+      ++idx;
+    }
+  } while (has_slash);
+
+  return rel_path;
+}
index 2b8fbf21cabca6b7f372a5a145d6fc26bd7b80cf..6039852939e0d22c270dfe5d676164fedb39b92a 100644 (file)
@@ -88,4 +88,8 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
 int simple_archiver_de_compress(int pipe_fd_in[2], int pipe_fd_out[2],
                                 const char *cmd, void *pid_out);
 
+/// If returns non-NULL, must be free'd.
+char *simple_archiver_filenames_to_relative_path(const char *from_abs,
+                                                 const char *to_abs);
+
 #endif
index 869816f826bd539d088126d78245a43d12c8ea7e..13caba92f5845d8707b97e7fba6b06f09826037b 100644 (file)
@@ -23,6 +23,7 @@
 #include <string.h>
 
 // Local includes.
+#include "archiver.h"
 #include "helpers.h"
 #include "parser_internal.h"
 
@@ -241,6 +242,21 @@ int main(void) {
     free(out);
   }
 
+  // Test archiver.
+  {
+    __attribute__((
+        cleanup(simple_archiver_helper_cleanup_c_string))) char *rel_path =
+        simple_archiver_filenames_to_relative_path(
+            "/one/two/three/four/five", "/one/two/branch/other/path");
+    CHECK_STREQ(rel_path, "../../branch/other/path");
+    simple_archiver_helper_cleanup_c_string(&rel_path);
+
+    rel_path = simple_archiver_filenames_to_relative_path(
+        "/one/two/three/four/five", "/one/two/three/other/dir/");
+    CHECK_STREQ(rel_path, "../other/dir/");
+    simple_archiver_helper_cleanup_c_string(&rel_path);
+  }
+
   printf("Checks checked: %u\n", checks_checked);
   printf("Checks passed:  %u\n", checks_passed);
   return checks_passed == checks_checked ? 0 : 1;