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
|
||