山本です。 dir.c と win32\dir.h と win32\win32.c にパッチを当てます。 変更点 1. _findfirst は同時にディレクトリ情報を得られるので、それを使う ことで大幅に高速化 2. direntを拡張し、d_isdirフィールドを追加。 DIR,opendir,readdir,rewinddir,closedirに、これに伴うコード追加。 dir.cが美しくなくなるので心苦しいのですが、 速度は全然違うので、是非取り込んで欲しいです。 # 他の環境でも同様に高速化できれば、罪悪感も減るんですけど。。。 ////////////////////////////////////////////// // dir.c # 先ほどの[ruby-dev:22449]に対するパッチです。 # ifndef が美しくない・・・ --- dir.c-22449 Mon Dec 29 21:15:52 2003 +++ dir.c Mon Dec 29 22:11:22 2003 @@ -1072,4 +1072,8 @@ glob_helper(path, sub, separator, flags, is_dir = no; +#ifndef _WIN32 if (do_lstat(buf, &st) == 0) { if (S_ISDIR(st.st_mode)) { +#else + if (dp->d_isdir) { +#endif strcpy(buf+n2, "/**/"); @@ -1078,2 +1082,3 @@ glob_helper(path, sub, separator, flags, is_dir = ok; +#ifndef _WIN32 } @@ -1082,2 +1087,3 @@ glob_helper(path, sub, separator, flags, } +#endif } @@ -1100,3 +1106,7 @@ glob_helper(path, sub, separator, flags, } +#ifndef _WIN32 else { +#else + else if (dp->d_isdir) { +#endif tmp = ALLOC(struct d_link); ////////////////////////////////////////////// // win32/dir.h --- win32/dir.h Tue Jun 11 15:58:56 2002 +++ win32/dir.h Mon Dec 29 17:00:38 2003 @@ -12,2 +12,3 @@ struct direct char d_name[256]; + char d_isdir; }; @@ -19,2 +20,4 @@ typedef struct { struct direct dirstr; + char *bits; + long bitpos; } DIR; ////////////////////////////////////////////// // win32/win32.c --- win32/win32.c Thu Nov 27 18:16:48 2003 +++ win32/win32.c Mon Dec 29 17:09:28 2003 @@ -1386,2 +1386,4 @@ rb_w32_opendir(const char *filename) strcpy(p->start, fd.name); + p->bits = ALLOC_N(char, 1); + p->bits[0] = fd.attrib & _A_SUBDIR ? 1 : 0; p->nfiles++; @@ -1409,2 +1411,14 @@ rb_w32_opendir(const char *filename) strcpy(&p->start[idx], fd.name); + + if (p->nfiles % 8 == 0) { + Renew (p->bits, p->nfiles / 8 + 1, char); + if (p->bits == NULL) { + rb_fatal ("opendir: malloc failed!\n"); + } + p->bits[p->nfiles / 8] = 0; + } + if (fd.attrib & _A_SUBDIR) { + p->bits[p->nfiles / 8] |= (1 << p->nfiles % 8); + } + p->nfiles++; @@ -1446,2 +1460,8 @@ rb_w32_readdir(DIR *dirp) // + // Directory flag + // + dirp->dirstr.d_isdir = dirp->bits[dirp->bitpos / 8] & (1 << dirp->bitpos % 8); + dirp->bitpos++; + + // // Now set up for the next call to readdir @@ -1488,2 +1508,3 @@ rb_w32_rewinddir(DIR *dirp) dirp->curr = dirp->start; + dirp->bitpos = 0; } @@ -1498,2 +1519,3 @@ rb_w32_closedir(DIR *dirp) free(dirp->start); + free(dirp->bits); free(dirp);