[Bf-blender-cvs] [fb2c646] asset-experiments: Rework job multi-level listing - factorize even more and avoid recursion.
Bastien Montagne
noreply at git.blender.org
Fri Feb 13 22:29:43 CET 2015
Commit: fb2c646deeb917a6fac8a7d0e697dc518a8df3ec
Author: Bastien Montagne
Date: Fri Feb 13 22:28:36 2015 +0100
Branches: asset-experiments
https://developer.blender.org/rBfb2c646deeb917a6fac8a7d0e697dc518a8df3ec
Rework job multi-level listing - factorize even more and avoid recursion.
This is much cleaner than previous code...
===================================================================
M source/blender/editors/include/UI_interface_icons.h
M source/blender/editors/space_file/filelist.c
M source/blender/makesrna/intern/rna_ID.c
===================================================================
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 549ee99..c721af1 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -34,6 +34,7 @@
struct bContext;
struct ID;
+struct Scene;
struct Image;
struct ImBuf;
struct World;
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index ec5991a..b08a010 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -37,10 +37,10 @@
#include <string.h>
#ifndef WIN32
-#include <unistd.h>
+# include <unistd.h>
#else
-#include <io.h>
-#include <direct.h>
+# include <io.h>
+# include <direct.h>
#endif
#include "MEM_guardedalloc.h"
@@ -49,6 +49,7 @@
#include "BLI_fnmatch.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
+#include "BLI_stack.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
@@ -1229,7 +1230,9 @@ int ED_file_extension_icon(const char *path)
return ICON_FILE_BLANK;
}
-static void filelist_setfiletypes(const char *root, struct direntry *files, const int numfiles, const char *filter_glob)
+static void filelist_setfiletypes(
+ const char *root, struct direntry *files, const int numfiles, const char *filter_glob,
+ const bool do_lib, const char *main_name)
{
struct direntry *file;
int num;
@@ -1252,6 +1255,19 @@ static void filelist_setfiletypes(const char *root, struct direntry *files, cons
else {
file->flags = file_extension_type(root, file->relname);
}
+
+ /* If we are considering .blend files as libs, promote them to directory status! */
+ if (do_lib && BLO_has_bfile_extension(file->relname)) {
+ char name[FILE_MAX];
+
+ BLI_join_dirfile(name, sizeof(name), root, file->relname);
+
+ /* prevent current file being used as acceptable dir */
+ if (BLI_path_cmp(main_name, name) != 0) {
+ file->type &= ~S_IFMT;
+ file->type |= S_IFDIR;
+ }
+ }
}
}
@@ -1354,13 +1370,20 @@ static unsigned int groupname_to_filter_id(const char *group)
* and main one (used by UI among other things).
*/
+typedef struct TodoDir {
+ int level;
+ char *dir;
+} TodoDir;
+
/* This helper is highly specialized for our needs, it 'transfers' most data (strings/pointers) from subfiles to
* filelist_buff. Only dirname->relname is actually duplicated.
+ * It also detects new sub-directories we want to list too, and add them to todo_dirs stack.
*/
static void filelist_readjob_merge_sublist(
- struct direntry **filelist_buff, int *filelist_buff_size, int *filelist_used_size,
- const char *root, const char *subdir, struct direntry *subfiles, const int num_subfiles,
- const bool ignore_currpar)
+ struct direntry **filelist_buff, int *filelist_buff_size, int *filelist_used_size, const char *main_name,
+ const char *root, const char *subdir, struct direntry *subfiles, const int num_subfiles, int *done_files,
+ const bool is_lib, const bool ignore_currpar, const int recursion_level, const int max_recursion,
+ BLI_Stack *todo_dirs)
{
if (num_subfiles) {
struct direntry *f;
@@ -1380,7 +1403,7 @@ static void filelist_readjob_merge_sublist(
*filelist_buff = new_filelist;
}
for (i = *filelist_used_size, j = 0, f = subfiles; j < num_subfiles; j++, f++) {
- if (ignore_currpar&& FILENAME_IS_CURRPAR(f->relname)) {
+ if (ignore_currpar && FILENAME_IS_CURRPAR(f->relname)) {
/* Ignore 'inner' curr/parent! */
new_numfiles--;
continue;
@@ -1390,6 +1413,32 @@ static void filelist_readjob_merge_sublist(
BLI_path_rel(dir, root);
(*filelist_buff)[i] = *f;
(*filelist_buff)[i].relname = BLI_strdup(dir + 2); /* + 2 to remove '//' added by BLI_path_rel */
+ (*done_files)++;
+
+ /* Here we decide whether current filedirentry is to be listed too, or not. */
+ /* Not a loop, just to be able to break. */
+ while (max_recursion && (is_lib || (recursion_level <= max_recursion))) {
+ TodoDir *td_dir;
+
+ if ((f->type & S_IFDIR) == 0) {
+ break;
+ }
+ else if (!is_lib && (recursion_level >= max_recursion) &&
+ !ELEM(f->flags, FILE_TYPE_BLENDER, FILE_TYPE_BLENDER_BACKUP))
+ {
+ /* Do not recurse in real directories in this case, only in .blend libs. */
+ break;
+ }
+
+ /* We have a directory we want to list, add it to todo list! */
+ BLI_join_dirfile(dir, sizeof(dir), root, (*filelist_buff)[i].relname);
+ BLI_cleanup_dir(main_name, dir);
+ td_dir = BLI_stack_push_r(todo_dirs);
+ td_dir->level = recursion_level + 1;
+ td_dir->dir = BLI_strdup(dir);
+ break;
+ }
+
/* those pointers are given to new_filelist... */
f->path = NULL;
f->poin = NULL;
@@ -1437,9 +1486,9 @@ static void filelist_readjob_list_lib(const char *root, struct direntry **files,
BLO_blendhandle_close(libfiledata);
+ BLI_assert(*files == NULL);
*num_files = nnames + 1;
- *files = malloc(*num_files * sizeof(**files));
- memset(*files, 0, *num_files * sizeof(**files));
+ *files = calloc(*num_files, sizeof(**files));
(*files)[nnames].relname = BLI_strdup(FILENAME_PARENT);
(*files)[nnames].type |= S_IFDIR;
@@ -1640,101 +1689,60 @@ static void filelist_readjob_main_rec(struct FileList *filelist)
}
#endif
-static void filelist_readjob_dir_lib_rec(
+static void filelist_readjob_dir_lib(
const bool do_lib, const char *main_name,
- FileList *filelist, int *filelist_buffsize, const char *dir, const char *filter_glob, const int recursion_level,
+ FileList *filelist, int *filelist_buffsize, BLI_Stack *todo_dirs, const char *filter_glob,
short *stop, short *do_update, float *progress, int *done_files, ThreadMutex *lock)
{
- /* only used if recursing, will contain all non-immediate children then. */
- struct direntry *file, *files = NULL;
- bool is_lib = do_lib;
- int num_files = 0;
- int i;
-
- if (!filelist) {
- return;
- }
-
- if (do_lib) {
- filelist_readjob_list_lib(dir, &files, &num_files);
- }
- if (!files) {
- is_lib = false;
- num_files = BLI_filelist_dir_contents(dir, &files);
- }
-
- if (!files) {
- return;
- }
-
- /* We only set filtypes for our own level, sub ones will be set by subcalls. */
- filelist_setfiletypes(dir, files, num_files, filter_glob);
+ while (!BLI_stack_is_empty(todo_dirs) && !(*stop)) {
+ /* only used if recursing, will contain all non-immediate children then. */
+ struct direntry *files = NULL;
+ TodoDir td_dir;
+ bool is_lib = do_lib;
+ int num_files = 0;
- if (do_lib) {
- /* Promote blend files from mere file status to prestigious directory one! */
- for (i = 0, file = files; i < num_files; i++, file++) {
- if (BLO_has_bfile_extension(file->relname)) {
- char name[FILE_MAX];
+ BLI_stack_pop(todo_dirs, &td_dir);
- BLI_join_dirfile(name, sizeof(name), dir, file->relname);
-
- /* prevent current file being used as acceptable dir */
- if (BLI_path_cmp(main_name, name) != 0) {
- file->type &= ~S_IFMT;
- file->type |= S_IFDIR;
- }
- }
+ if (do_lib) {
+ filelist_readjob_list_lib(td_dir.dir, &files, &num_files);
+ }
+ if (!files) {
+ is_lib = false;
+ num_files = BLI_filelist_dir_contents(td_dir.dir, &files);
}
- }
-
- BLI_mutex_lock(lock);
- filelist_readjob_merge_sublist(&filelist->filelist, filelist_buffsize, &filelist->numfiles, filelist->dir,
- dir, files, num_files, recursion_level > 1);
+ if (!files) {
+ continue;
+ }
- (*done_files)++;
- *progress = (float)(*done_files) / filelist->numfiles;
+ /* We only set filtypes for our own level, sub ones will be set by later iterations. */
+ filelist_setfiletypes(td_dir.dir, files, num_files, filter_glob, do_lib, main_name);
- //~ printf("%f (%d / %d)\n", *progress, *done_files, filelist->numfiles);
+ BLI_mutex_lock(lock);
- BLI_mutex_unlock(lock);
+ filelist_readjob_merge_sublist(&filelist->filelist, filelist_buffsize, &filelist->numfiles,
+ main_name, filelist->dir, td_dir.dir, files, num_files, done_files,
+ is_lib, td_dir.level > 1, td_dir.level, filelist->max_recursion, todo_dirs);
- *do_update = true;
+ *progress = (float)(*done_files) / filelist->numfiles;
- /* in case it's a lib we don't care anymore about max recursion level... */
- if (!*stop && filelist->max_recursion && (do_lib || (recursion_level < filelist->max_recursion))) {
- for (i = 0, file = files; i < num_files && !*stop; i++, file++) {
- char subdir[FILE_MAX];
+ //~ printf("%f (%d / %d)\n", *progress, *done_files, filelist->numfiles);
- if (FILENAME_IS_CURRPAR(file->relname)) {
- /* do not increase done_files here, we completly ignore those. */
- continue;
- }
- else if ((file->type & S_IFDIR) == 0) {
- (*done_files)++;
- continue;
- }
- else if (!is_lib && (recursion_level >= filelist->max_recursion) &&
- !ELEM(file->flags, FILE_TYPE_BLENDER, FILE_TYPE_BLENDER_BACKUP))
- {
- /* Do not recurse in real directories in this case, only in .blend libs. */
- continue;
- }
+ BLI_mutex_unlock(lock);
- BLI_join_dirfile(subdir, sizeof(subdir), dir, file->relname);
- BLI_cleanup_dir(main_name, subdir);
- filelist_readjob_dir_lib_rec(do_lib, main_name,
- filelist, filelist_buffsize, subdir, filter_glob, recursion_level + 1,
- stop, do_update, progress, done_files, lock);
- }
+ *do_update = true;
+ BLI_filelist_free(files, num_files, NULL);
+ MEM_freeN(td_dir.dir);
}
- BLI_filelist_free(files, num_files, NULL);
}
-static void filelist_readjob_dir(
+static void filelist_readjob_do(
+ const bool is_lib,
FileList *filelist, const char *main_name, short *stop, short *do_update, float *progress, ThreadMutex *lock)
{
- char dir[FILE_MAX];
+ BLI_Stack *todo_dirs;
+ TodoDir *td_dir;
+ char dir[FILE_MAX_LIBEXTRA];
char filter_glob[64]; /* TODO should be define! */
int filelist_buffsize = 0;
int done_files = 0;
@@ -1742,6 +1750,10 @@ static void filelist_readjob_dir(
BLI_asser
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list