From: "H.Yamamoto" Date: 2005-11-18T20:20:51+09:00 Subject: [ruby-dev:27751] Re: FNM_CASEFOLD on case-sensitive system nobuyoshi nakada wrote: (2005/11/18 18:45) >なかだです。 > >At Fri, 18 Nov 2005 15:31:33 +0900, >H.Yamamoto wrote in [ruby-dev:27741]: >> >ずいぶん前の実装で、私も良く覚えていないのですが、確か >> >ファイルシステムの case sensitivity と fnmatch の >> >case sensitivity は一致してることを前提にした実装だった >> >と思います。 >> >> 何か、だんだん思い出してきたので、後で BeOS で試してみます。 >> 要するに、"a" とかワイルドカードを含まないパターン要素は >> 特別扱いして高速化を図っているのですが、Unix + FNM_CASEFOLD >> のときは PLAIN に行かずに MAGIC に行けばいいのです。 >> (つまり、すべてワイルドカード扱い) > >なるほど。 期待通りに動いているようでした。ただ、大文字小文字の区別は Compare で抽象化しているので、 >+#if !defined DOSISH /* case-sensitive system */ >+ default: >+ if (ISALPHA(c) && nocase) >+ return 1; >+#endif > } というのはあまりしたくありません。ISALPHA は高速化のためのハック だと思うのですが、もし Windows のように全角文字の大文字・小文字も 区別しないような非DOSISH環境があった場合に動かないので、私なら こうしてしまうと思います。 Index: dir.c =================================================================== RCS file: /src/ruby/dir.c,v retrieving revision 1.148 diff -u -w -b -p -r1.148 dir.c --- dir.c 16 Sep 2005 13:46:03 -0000 1.148 +++ dir.c 18 Nov 2005 11:13:31 -0000 @@ -931,10 +931,15 @@ static int has_magic(const char *s, int flags) { const int escape = !(flags & FNM_NOESCAPE); + const int nocase = (flags & FNM_CASEFOLD); register const char *p = s; register char c; +#ifndef DOSISH + if (nocase) return *p; +#endif + while (c = *p++) { switch (c) { case '*': @@ -1298,8 +1303,6 @@ ruby_glob0(const char *path, int flags, #if defined DOSISH flags |= FNM_CASEFOLD; root = rb_path_skip_prefix(root); -#else - flags &= ~FNM_CASEFOLD; #endif if (root && *root == '/') root++; @@ -1342,9 +1345,11 @@ rb_glob2(const char *path, int flags, vo args.func = func; args.value = arg; +#ifdef DOSISH if (flags & FNM_CASEFOLD) { - rb_warn("Dir.glob() ignores File::FNM_CASEFOLD"); + rb_warning("Dir.glob() ignores File::FNM_CASEFOLD"); } +#endif return ruby_glob0(path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args); } Dir.glob("../../../*") とかで無駄が多い気がしますが、/local/bin/hoge もどうせ ワイルドカードとして扱ってしまうので、あまり気にしてもしかたような気もします。 速度が全然違ってどうしても必要な場合は、せめて >+#if !defined DOSISH /* case-sensitive system */ >+ default: >+ if (ISALPHA(c) && nocase) /* CAUTION: only alphabet behaves as wildcard */ >+ return 1; >+#endif > } として、将来のためにコメントで注意を促しておきたいです。