Bug #13167 » 0001-dir.c-performance-fix-with-braces-using-cache.patch
dir.c | ||
---|---|---|
# error not implemented
|
||
#endif
|
||
#if defined HAVE_GETATTRLIST || defined _WIN32
|
||
struct real_path {
|
||
char *path;
|
||
rb_pathtype_t type;
|
||
};
|
||
static char *
|
||
replace_real_basename_with_cache(char *path, long base, rb_encoding *enc, int norm_p, int flags,
|
||
rb_pathtype_t *type, st_table *cached_paths)
|
||
{
|
||
struct real_path *real_path;
|
||
st_data_t key = (st_data_t)path;
|
||
if (cached_paths && st_lookup(cached_paths, key, (st_data_t *)&real_path)) {
|
||
path = ruby_strdup(real_path->path);
|
||
*type = real_path->type;
|
||
}
|
||
else {
|
||
path = replace_real_basename(path, base, enc, norm_p, flags, type);
|
||
if (cached_paths) {
|
||
real_path = GLOB_ALLOC(struct real_path);
|
||
real_path->path = ruby_strdup(path);
|
||
real_path->type = *type;
|
||
st_insert(cached_paths, key, (st_data_t)real_path);
|
||
}
|
||
}
|
||
return path;
|
||
}
|
||
#endif
|
||
#ifndef S_ISDIR
|
||
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||
#endif
|
||
... | ... | |
int flags,
|
||
const ruby_glob_funcs_t *funcs,
|
||
VALUE arg,
|
||
st_table *cached_paths,
|
||
rb_encoding *enc)
|
||
{
|
||
struct stat st;
|
||
... | ... | |
}
|
||
status = glob_helper(fd, buf, baselen, name - buf - baselen + namlen, 1,
|
||
new_pathtype, new_beg, new_end,
|
||
flags, funcs, arg, enc);
|
||
new_pathtype, new_beg, new_end, flags, funcs,
|
||
arg, cached_paths, enc);
|
||
GLOB_FREE(buf);
|
||
GLOB_FREE(new_beg);
|
||
if (status) break;
|
||
... | ... | |
#if USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME
|
||
if ((*cur)->type == ALPHA) {
|
||
long base = pathlen + (dirsep != 0);
|
||
buf = replace_real_basename(buf, base, enc, IF_NORMALIZE_UTF8PATH(1)+0,
|
||
flags, &new_pathtype);
|
||
buf = replace_real_basename_with_cache(buf, base, enc,
|
||
IF_NORMALIZE_UTF8PATH(1)+0,
|
||
flags, &new_pathtype,
|
||
cached_paths);
|
||
if (!buf) break;
|
||
}
|
||
#endif
|
||
status = glob_helper(fd, buf, baselen,
|
||
namelen + strlen(buf + pathlen), 1,
|
||
new_pathtype, new_beg, new_end,
|
||
flags, funcs, arg, enc);
|
||
flags, funcs, arg, cached_paths, enc);
|
||
GLOB_FREE(buf);
|
||
GLOB_FREE(new_beg);
|
||
if (status) break;
|
||
... | ... | |
static int
|
||
ruby_glob0(const char *path, int fd, const char *base, int flags,
|
||
const ruby_glob_funcs_t *funcs, VALUE arg,
|
||
rb_encoding *enc)
|
||
st_table *cached_paths, rb_encoding *enc)
|
||
{
|
||
struct glob_pattern *list;
|
||
const char *root, *start;
|
||
... | ... | |
}
|
||
status = glob_helper(fd, buf, baselen, n-baselen, dirsep,
|
||
path_unknown, &list, &list + 1,
|
||
flags, funcs, arg, enc);
|
||
flags, funcs, arg, cached_paths, enc);
|
||
glob_free_pattern(list);
|
||
GLOB_FREE(buf);
|
||
... | ... | |
funcs.match = func;
|
||
funcs.error = NULL;
|
||
return ruby_glob0(path, AT_FDCWD, 0, flags & ~GLOB_VERBOSE,
|
||
&funcs, arg, rb_ascii8bit_encoding());
|
||
&funcs, arg, NULL, rb_ascii8bit_encoding());
|
||
}
|
||
static int
|
||
... | ... | |
args.enc = rb_ascii8bit_encoding();
|
||
status = ruby_glob0(path, AT_FDCWD, 0, GLOB_VERBOSE, &rb_glob_funcs,
|
||
(VALUE)&args, args.enc);
|
||
(VALUE)&args, NULL, args.enc);
|
||
if (status) GLOB_JUMP_TAG(status);
|
||
}
|
||
... | ... | |
{
|
||
struct brace_args *arg = (struct brace_args *)val;
|
||
return ruby_glob0(path, AT_FDCWD, 0, arg->flags, &arg->funcs, arg->value, enc);
|
||
return ruby_glob0(path, AT_FDCWD, 0, arg->flags, &arg->funcs, arg->value, NULL, enc);
|
||
}
|
||
int
|
||
... | ... | |
struct glob_args glob;
|
||
int flags;
|
||
int fd;
|
||
st_table *cached_paths;
|
||
};
|
||
static int
|
||
... | ... | |
struct push_glob_args *arg = (struct push_glob_args *)val;
|
||
return ruby_glob0(path, arg->fd, arg->glob.base, arg->flags, &rb_glob_funcs,
|
||
(VALUE)&arg->glob, enc);
|
||
(VALUE)&arg->glob, arg->cached_paths, enc);
|
||
}
|
||
#if defined HAVE_GETATTRLIST || defined _WIN32
|
||
static int
|
||
free_cached_paths(st_data_t key, st_data_t val, st_data_t arg)
|
||
{
|
||
GLOB_FREE((struct real_path *)val);
|
||
return ST_DELETE;
|
||
}
|
||
#endif
|
||
static int
|
||
push_glob(VALUE ary, VALUE str, VALUE base, int flags)
|
||
{
|
||
struct push_glob_args args;
|
||
rb_encoding *enc = rb_enc_get(str);
|
||
int status;
|
||
#if defined _WIN32 || defined __APPLE__
|
||
str = rb_str_encode_ospath(str);
|
||
... | ... | |
enc = rb_utf8_encoding();
|
||
#endif
|
||
return ruby_brace_expand(RSTRING_PTR(str), flags,
|
||
push_caller, (VALUE)&args, enc, str);
|
||
#if defined HAVE_GETATTRLIST || defined _WIN32
|
||
args.cached_paths = st_init_strtable();
|
||
#endif
|
||
status = ruby_brace_expand(RSTRING_PTR(str), flags,
|
||
push_caller, (VALUE)&args, enc, str);
|
||
#if defined HAVE_GETATTRLIST || defined _WIN32
|
||
st_foreach(args.cached_paths, free_cached_paths, 0);
|
||
st_free_table(args.cached_paths);
|
||
#endif
|
||
return status;
|
||
}
|
||
static VALUE
|