replaced direct scanning of directories with a two-step approach (first: create filename list, second: scan)

Tue, 21 May 2013 13:19:37 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 21 May 2013 13:19:37 +0200
changeset 41
c2e73e175341
parent 40
5938a9b74e8e
child 42
0402b9b41b0a

replaced direct scanning of directories with a two-step approach (first: create filename list, second: scan)

gcc.mk file | annotate | diff | comparison | revisions
mingw.mk file | annotate | diff | comparison | revisions
src/scanner.c file | annotate | diff | comparison | revisions
--- a/gcc.mk	Fri May 17 14:41:44 2013 +0200
+++ b/gcc.mk	Tue May 21 13:19:37 2013 +0200
@@ -27,5 +27,5 @@
 
 CC = gcc
 LD = gcc
-CFLAGS = -Wall -std=gnu99 -O
+CFLAGS = -Wall -std=gnu99 -O2
 LDFLAGS = 
--- a/mingw.mk	Fri May 17 14:41:44 2013 +0200
+++ b/mingw.mk	Tue May 21 13:19:37 2013 +0200
@@ -27,5 +27,5 @@
 
 CC = gcc
 LD = gcc
-CFLAGS = -Wall -std=gnu99 -O
+CFLAGS = -Wall -std=gnu99 -O2
 LDFLAGS = -static -lregex
--- a/src/scanner.c	Fri May 17 14:41:44 2013 +0200
+++ b/src/scanner.c	Tue May 21 13:19:37 2013 +0200
@@ -36,16 +36,24 @@
 #include "regex_parser.h"
 #include <sys/stat.h>
 
-int scanDirectory(scanner_t scanner, settings_t* settings) {
+typedef struct filelist filelist_t;
 
+struct filelist {
+  char *displayname;
+  int displayname_len;
+  char *filename;
+  int st_mode;
+  filelist_t *next;
+};
+
+filelist_t *buildFileList(scanner_t scanner, settings_t* settings,
+    filelist_t* list) {
+  
   DIR *dirf;
   struct dirent *entry;
-  int entrynamelen;
-  int lines, a;
-  int lineSum = 0;
-  bool bfile;
   struct stat statbuf;
-
+  filelist_t *listentry = list;
+  
   if ((dirf = opendir(scanner.dir)) == NULL) {
     printf("%s", scanner.dir);
     perror("  Directory access failed");
@@ -54,31 +62,74 @@
 
   while ((entry = readdir(dirf)) != NULL) {
     if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
+      
+      /* Create new filelist entry */
+      filelist_t *newentry = (filelist_t*) malloc(sizeof(filelist_t));
+      // TODO: don't just append - create a sorted list!
+      if (listentry) {
+        listentry->next = newentry;
+      }
+      listentry = newentry;
+      if (!list) {
+        list = listentry;
+      }
+      
+      listentry->next = NULL;
+      
+      listentry->displayname_len = strlen(entry->d_name);
+      listentry->displayname = (char*) malloc(listentry->displayname_len+1);
+      memcpy(listentry->displayname, entry->d_name, listentry->displayname_len);
+      listentry->displayname[listentry->displayname_len] = 0;
+      
+      listentry->st_mode = 0;
+      
       /* Construct absolute pathname string */
-      entrynamelen = strlen(entry->d_name);
-      char filename[(1+strlen(scanner.dir)+entrynamelen)];
-      strcpy(filename, scanner.dir);
-      strncat(filename, &settings->fileSeparator, 1);
-      strcat(filename, entry->d_name);
+      size_t dirnamelen = strlen(scanner.dir);
+      char *filename = (char*) malloc(2+dirnamelen+listentry->displayname_len);
+      memcpy(filename, scanner.dir, dirnamelen);
+      filename[dirnamelen] = settings->fileSeparator;
+      memcpy(filename+dirnamelen+1, entry->d_name, listentry->displayname_len);
+      filename[1+dirnamelen+listentry->displayname_len] = 0;
+      listentry->filename = filename;
 
       /* Check for subdirectory */
       if (stat(filename, &statbuf) == 0) {
-        if (!(statbuf.st_mode & S_IFREG)) {
-          printf("%*s\n", entrynamelen+scanner.spaces, entry->d_name);
-          if (settings->recursive && (statbuf.st_mode & S_IFDIR)) {
-            lineSum += scanDirectory(
-                (scanner_t) {filename, scanner.spaces+1}, settings);
-          }
-          continue;
-        }
+        listentry->st_mode = statbuf.st_mode;
       } else {
         perror("  Error in stat call");
         continue;
       }
+    }
+  }
+  
+  closedir(dirf);
+  
+  return list;
+}
 
+int scanDirectory(scanner_t scanner, settings_t* settings) {
+
+  int lines, a;
+  int lineSum = 0;
+  bool bfile;
+
+  filelist_t *filelist = buildFileList(scanner, settings, NULL);
+
+  while (filelist != NULL) {
+
+    /* Scan subdirectories */
+    if (!(filelist->st_mode & S_IFREG)) {
+      printf("%*s\n", filelist->displayname_len+scanner.spaces,
+          filelist->displayname);
+      if (settings->recursive && (filelist->st_mode & S_IFDIR)) {
+        scanDirectory((scanner_t) {filelist->filename, scanner.spaces+1},
+            settings);
+      }
+    } else {
       if ((settings->includeSuffixes->count == 0
-          || testSuffix(filename, settings->includeSuffixes))
-          && !testSuffix(filename, settings->excludeSuffixes)) {
+        || testSuffix(filelist->displayname, settings->includeSuffixes))
+        && !testSuffix(filelist->displayname, settings->excludeSuffixes)) {
+
         /* Count lines */
         lines = 0;
         bfile = false;
@@ -86,66 +137,70 @@
         char line_buffer[REGEX_MAX_LINELENGTH];
         int line_buffer_offset = 0;
 
-        FILE *file = fopen(filename, "r");
+        FILE *file = fopen(filelist->filename, "r");
         if (file == NULL) {
-          printf("%*s", entrynamelen+scanner.spaces, entry->d_name);
+          printf("%*s", filelist->displayname_len+scanner.spaces,
+              filelist->displayname);
           perror("  File acces failed");
-          continue;
-        }
+        } else {
+          do {
+            a = fgetc(file);
+
+            bfile = bfile_check(settings->bfileHeuristics, a);
 
-        do {
-          a = fgetc(file);
-
-          bfile = bfile_check(settings->bfileHeuristics, a);
+            if (a == 10 || a == EOF) {
+              line_buffer[line_buffer_offset] = 0;
+              if (regex_parser_do(settings->regex, line_buffer) == 0) {
+                /* Only subtract lines when matching has finished */
+                if (!regex_parser_matching(settings->regex)) {
+                  lines -= settings->regex->matched_lines;
+                }
+              }
 
-          if (a == 10 || a == EOF) {
-            line_buffer[line_buffer_offset] = 0;
-            if (regex_parser_do(settings->regex, line_buffer) == 0) {
-              /* Only subtract lines when matching has finished */
-              if (!regex_parser_matching(settings->regex)) {
-                lines -= settings->regex->matched_lines;
+              line_buffer_offset = 0;
+              lines++;
+            } else {
+              if (line_buffer_offset < REGEX_MAX_LINELENGTH) {
+                line_buffer[line_buffer_offset] = a;
+                line_buffer_offset++;
+              } else {
+                line_buffer[line_buffer_offset-1] = 0;
+                settings->confusing_lnlen = true;
               }
             }
+          } while (!bfile && a != EOF);
+          fclose(file);
 
-            line_buffer_offset = 0;
-            lines++;
+          /* Print and sum line count */
+          if (bfile) {
+            if (!settings->matchesOnly) {
+              printf("%*s%*s%19s\n", filelist->displayname_len+scanner.spaces,
+                  filelist->displayname,
+                  60-filelist->displayname_len-scanner.spaces, "", "binary");
+            }
           } else {
-            if (line_buffer_offset < REGEX_MAX_LINELENGTH) {
-              line_buffer[line_buffer_offset] = a;
-              line_buffer_offset++;
-            } else {
-              line_buffer[line_buffer_offset-1] = 0;
-              settings->confusing_lnlen = true;
-            }
+            lineSum += lines;
+            printf("%*s%*s%13d lines\n",
+                filelist->displayname_len+scanner.spaces, filelist->displayname,
+                60-filelist->displayname_len-scanner.spaces, "", lines);
           }
-        } while (!bfile && a != EOF);
-        fclose(file);
-
-        /* Print and sum line count */
-        if (bfile) {
-          if (!settings->matchesOnly) {
-            printf("%*s%*s%19s\n",
-                entrynamelen+scanner.spaces, entry->d_name,
-                60-entrynamelen-scanner.spaces, "", "binary");
-          }
-        } else {
-          lineSum += lines;
-          printf("%*s%*s%13d lines\n",
-              entrynamelen+scanner.spaces, entry->d_name,
-              60-entrynamelen-scanner.spaces, "", lines);
         }
       } else {
         if (!settings->matchesOnly) {
           /* Print hint */
           printf("%*s%*s%19s\n",
-              entrynamelen+scanner.spaces, entry->d_name,
-              60-entrynamelen-scanner.spaces, "", "no match");
+              filelist->displayname_len+scanner.spaces, filelist->displayname,
+              60-filelist->displayname_len-scanner.spaces, "", "no match");
         }
       }
     }
+    
+    free(filelist->filename);
+    free(filelist->displayname);
+    filelist_t *freethis = filelist;
+    filelist = filelist->next;
+    free(freethis);
   }
 
-  closedir(dirf);
-
   return lineSum;
 }

mercurial