Author: hbelusca
Date: Fri Jan  8 18:43:46 2016
New Revision: 70552

URL: http://svn.reactos.org/svn/reactos?rev=70552&view=rev
Log:
[CDMAKE]
- Optimize splitting paths (merge chop_dirname and chop_filename functions).
- Make the code working as expected for the following testcases (you can test 
these by adding the following lines into e.g. bootcd.lst):
testdir1   --> create "testdir1" in the root directory.
testdir2/  --> create "testdir2" in the root directory. No no-named 
subdirectory is created.
testdir3// --> create "testdir3" in the root directory. No no-named 
subdirectory is created.
dir1//\/dir14///\//\//   --> create "dir1" in the root directory, and "dir14" 
inside dir1. No no-named subdirectory is created.
EFI/ReactOS/Boot/Fonts//chs_boot.ttf=C:/somepath/chs_boot.ttf --> create the 
directories "EFI/ReactOS/Boot/Fonts", no no-named subdirectory is created, and 
create in the Fonts directory the file "chs_boot.ttf".

Before those changes, empty no-named (therefore, invalid) subdirectories were 
created in the second, third and fourth testcases, and an obscure error was 
returned in the fifth testcase.

Modified:
    trunk/reactos/tools/cdmake/dirhash.c

Modified: trunk/reactos/tools/cdmake/dirhash.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/cdmake/dirhash.c?rev=70552&r1=70551&r2=70552&view=diff
==============================================================================
--- trunk/reactos/tools/cdmake/dirhash.c        [iso-8859-1] (original)
+++ trunk/reactos/tools/cdmake/dirhash.c        [iso-8859-1] Fri Jan  8 
18:43:46 2016
@@ -5,12 +5,15 @@
  * PURPOSE:         CD-ROM Premastering Utility - Directory names hashing
  * PROGRAMMERS:     Art Yerkes
  */
+
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include "config.h"
 #include "dirhash.h"
 
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
 /* This is the famous DJB hash */
 static unsigned int
 djb_hash(const char *name)
@@ -26,59 +29,33 @@
     return val;
 }
 
-static const char *
-chop_filename(const char *target)
-{
-    char *last_slash = strrchr(target, '/');
-    if (!last_slash)
-        last_slash = strrchr(target, '\\');
-    if (last_slash)
-        return last_slash + 1;
+static void
+split_path(const char *path, char **dirname, char **filename /* OPTIONAL */)
+{
+    const char *result;
+
+    /* Retrieve the file name */
+    char *last_slash_1 = strrchr(path, '/');
+    char *last_slash_2 = strrchr(path, '\\');
+
+    if (last_slash_1 || last_slash_2)
+        result = max(last_slash_1, last_slash_2) + 1;
     else
-        return target;
-}
-
-static void
-chop_dirname(const char *name, char **dirname)
-{
-    char *last_slash = strrchr(name, '/');
-    if (!last_slash)
-        last_slash = strrchr(name, '\\');
-    if (!last_slash)
-    {
-        *dirname = malloc(1);
-        **dirname = 0;
-    }
-    else
-    {
-        char *newdata = malloc(last_slash - name + 1);
-        memcpy(newdata, name, last_slash - name);
-        newdata[last_slash - name] = 0;
-        *dirname = newdata;
-    }
-}
-
-static struct target_dir_entry *
-get_entry_by_normname(struct target_dir_hash *dh, const char *norm)
-{
-    unsigned int hashcode;
-    struct target_dir_entry *de;
-    hashcode = djb_hash(norm);
-    de = dh->buckets[hashcode % NUM_DIR_HASH_BUCKETS];
-    while (de && strcmp(de->normalized_name, norm))
-        de = de->next_dir_hash_entry;
-    return de;
-}
-
-static void
-delete_entry(struct target_dir_hash *dh, struct target_dir_entry *de)
-{
-    struct target_dir_entry **ent;
-    ent = &dh->buckets[de->hashcode % NUM_DIR_HASH_BUCKETS];
-    while (*ent && ((*ent) != de))
-        ent = &(*ent)->next_dir_hash_entry;
-    if (*ent)
-        *ent = (*ent)->next_dir_hash_entry;
+        result = path;
+
+    /* Duplicate the file name for the user if needed */
+    if (filename)
+        *filename = strdup(result);
+
+    /* Remove any trailing directory separators */
+    while (result > path && (*(result-1) == '/' || *(result-1) == '\\'))
+        result--;
+
+    /* Retrieve and duplicate the directory */
+    *dirname = malloc(result - path + 1);
+    if (result > path)
+        memcpy(*dirname, path, result - path);
+    (*dirname)[result - path] = '\0'; // NULL-terminate
 }
 
 void normalize_dirname(char *filename)
@@ -109,20 +86,39 @@
             }
         }
     }
-    filename[tgt] = 0;
-
-    while (tgt && (filename[--tgt] == DIR_SEPARATOR_CHAR))
-    {
-        filename[tgt] = 0;
-    }
+    filename[tgt] = '\0'; // NULL-terminate
+}
+
+static struct target_dir_entry *
+get_entry_by_normname(struct target_dir_hash *dh, const char *norm)
+{
+    unsigned int hashcode;
+    struct target_dir_entry *de;
+    hashcode = djb_hash(norm);
+    de = dh->buckets[hashcode % NUM_DIR_HASH_BUCKETS];
+    while (de && strcmp(de->normalized_name, norm))
+        de = de->next_dir_hash_entry;
+    return de;
+}
+
+static void
+delete_entry(struct target_dir_hash *dh, struct target_dir_entry *de)
+{
+    struct target_dir_entry **ent;
+    ent = &dh->buckets[de->hashcode % NUM_DIR_HASH_BUCKETS];
+    while (*ent && ((*ent) != de))
+        ent = &(*ent)->next_dir_hash_entry;
+    if (*ent)
+        *ent = (*ent)->next_dir_hash_entry;
 }
 
 struct target_dir_entry *
 dir_hash_create_dir(struct target_dir_hash *dh, const char *casename, const 
char *targetnorm)
 {
     struct target_dir_entry *de, *parent_de;
+    char *parentcase = NULL;
+    char *case_name  = NULL;
     char *parentname = NULL;
-    char *parentcase = NULL;
     struct target_dir_entry **ent;
 
     if (!dh->root.normalized_name)
@@ -133,20 +129,32 @@
         dh->buckets[dh->root.hashcode % NUM_DIR_HASH_BUCKETS] = &dh->root;
     }
 
+    /* Check whether the directory was already created and just return it if 
so */
     de = get_entry_by_normname(dh, targetnorm);
     if (de)
         return de;
 
-    chop_dirname(targetnorm, &parentname);
-    chop_dirname(casename, &parentcase);
+    /*
+     * If *case_name == '\0' after the following call to split_path(...),
+     * for example in the case where casename == "subdir/dir/", then just
+     * create the directories "subdir" and "dir" by a recursive call to
+     * dir_hash_create_dir(...) and return 'parent_de' instead (see after).
+     * We do not (and we never) create a no-name directory inside it.
+     */
+    split_path(casename, &parentcase, &case_name);
+    split_path(targetnorm, &parentname, NULL);
     parent_de = dir_hash_create_dir(dh, parentcase, parentname);
     free(parentname);
     free(parentcase);
 
+    /* See the remark above */
+    if (!*case_name) return parent_de;
+
+    /* Now create the directory */
     de = calloc(1, sizeof(*de));
     de->parent = parent_de;
     de->normalized_name = strdup(targetnorm);
-    de->case_name = strdup(chop_filename(casename));
+    de->case_name = case_name;
     de->hashcode = djb_hash(targetnorm);
 
     de->next = parent_de->child;
@@ -154,9 +162,7 @@
 
     ent = &dh->buckets[de->hashcode % NUM_DIR_HASH_BUCKETS];
     while (*ent)
-    {
         ent = &(*ent)->next_dir_hash_entry;
-    }
     *ent = de;
 
     return de;
@@ -166,21 +172,24 @@
 {
     struct target_file *tf;
     struct target_dir_entry *de;
-    char *targetdir = NULL;
+    char *targetdir  = NULL;
+    char *targetfile = NULL;
     char *targetnorm;
 
-    chop_dirname(target, &targetdir);
+    /* Create first the directory */
+    split_path(target, &targetdir, &targetfile);
     targetnorm = strdup(targetdir);
     normalize_dirname(targetnorm);
     de = dir_hash_create_dir(dh, targetdir, targetnorm);
     free(targetnorm);
     free(targetdir);
 
+    /* Now add the file */
     tf = calloc(1, sizeof(*tf));
     tf->next = de->head;
     de->head = tf;
     tf->source_name = strdup(source);
-    tf->target_name = strdup(chop_filename(target));
+    tf->target_name = targetfile;
 }
 
 static void


Reply via email to