[ruby-list:44916] Re: Dir.entriesのエンコーディング (was Re: Ruby 1.9のARGVのエンコーディング)
From:
"NARUSE, Yui" <naruse@...>
Date:
2008-05-11 22:17:42 UTC
List:
ruby-list #44916
成瀬です。 とりあえず異論がなさそうな範囲を実装してみたパッチです。 わたしはとりあえず、なかむらさんの提案に対して、 * ディレクトリのパスが戻り値のリストのエンコーディングが異なる場合、 :list_encoding を用いるのを第一とする * fallback 系の引数を取れるようにする を加えればよいように感じています。 -- NARUSE, Yui <naruse@airemix.jp>
Attachments (1)
encoding_of_dir_entries.patch
(4.31 KB, text/x-diff)
--- dir.c (revision 16336)
+++ dir.c (working copy)
@@ -12,6 +12,7 @@
**********************************************************************/
#include "ruby/ruby.h"
+#include "ruby/encoding.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -350,6 +351,7 @@ VALUE rb_cDir;
struct dir_data {
DIR *dir;
char *path;
+ rb_encoding *enc;
};
static void
@@ -372,6 +374,7 @@ dir_s_alloc(VALUE klass)
dirp->dir = NULL;
dirp->path = NULL;
+ dirp->enc = NULL;
return obj;
}
@@ -386,9 +389,25 @@ static VALUE
dir_initialize(VALUE dir, VALUE dirname)
{
struct dir_data *dp;
+ int dirname_encidx = rb_enc_get_index(dirname);
+ rb_encoding *fs_enc = rb_locale_encoding();
+ int fs_encidx = rb_enc_to_index(fs_enc);
- FilePathValue(dirname);
Data_Get_Struct(dir, struct dir_data, dp);
+ if (rb_usascii_encindex() == dirname_encidx ||
+ rb_ascii8bit_encindex() == dirname_encidx) {
+ dp->enc = rb_locale_encoding();
+ }
+ else if (fs_encidx == dirname_encidx) {
+ dp->enc = fs_enc;
+ }
+ else {
+ rb_raise(rb_eNotImpError, "dirname must equal filesystem encoding now");
+ /* dp->enc = rb_enc_from_index(dirname_encidx); */
+ /* transode dirname from dirname_encidx to fs_enc */
+ }
+ FilePathValue(dirname);
+
if (dp->dir) closedir(dp->dir);
if (dp->path) free(dp->path);
dp->dir = NULL;
@@ -491,7 +510,7 @@ dir_path(VALUE dir)
Data_Get_Struct(dir, struct dir_data, dirp);
if (!dirp->path) return Qnil;
- return rb_str_new2(dirp->path);
+ return rb_enc_str_new2(dirp->path, dirp->enc);
}
/*
@@ -516,7 +535,7 @@ dir_read(VALUE dir)
errno = 0;
dp = readdir(dirp->dir);
if (dp) {
- return rb_tainted_str_new(dp->d_name, NAMLEN(dp));
+ return rb_tainted_enc_str_new(dp->d_name, NAMLEN(dp), dirp->enc);
}
else if (errno == 0) { /* end of stream */
return Qnil;
@@ -554,7 +573,7 @@ dir_each(VALUE dir)
GetDIR(dir, dirp);
rewinddir(dirp->dir);
for (dp = readdir(dirp->dir); dp != NULL; dp = readdir(dirp->dir)) {
- rb_yield(rb_tainted_str_new(dp->d_name, NAMLEN(dp)));
+ rb_yield(rb_tainted_enc_str_new(dp->d_name, NAMLEN(dp), dirp->enc));
if (dirp->dir == NULL) dir_closed();
}
return dir;
--- encoding.c (revision 16336)
+++ encoding.c (working copy)
@@ -934,7 +934,13 @@ rb_ascii8bit_encoding(void)
if (!enc_table.list) {
rb_enc_init();
}
- return enc_table.list[0].enc;
+ return enc_table.list[ENCINDEX_ASCII].enc;
+}
+
+int
+rb_ascii8bit_encindex(void)
+{
+ return ENCINDEX_ASCII;
}
rb_encoding *
--- include/ruby/encoding.h (revision 16336)
+++ include/ruby/encoding.h (working copy)
@@ -90,6 +90,9 @@ int rb_enc_internal_get_index(VALUE obj)
void rb_enc_internal_set_index(VALUE obj, int encindex);
VALUE rb_enc_str_new(const char*, long, rb_encoding*);
+VALUE rb_enc_str_new2(const char*, rb_encoding *);
+VALUE rb_tainted_enc_str_new(const char*, long, rb_encoding *);
+VALUE rb_tainted_enc_str_new2(const char*, rb_encoding *);
VALUE rb_enc_reg_new(const char*, long, rb_encoding*, int);
PRINTF_ARGS(VALUE rb_enc_sprintf(rb_encoding *, const char*, ...), 2, 3);
VALUE rb_enc_vsprintf(rb_encoding *, const char*, va_list);
@@ -173,6 +176,7 @@ rb_encoding *rb_usascii_encoding(void);
rb_encoding *rb_locale_encoding(void);
rb_encoding *rb_default_external_encoding(void);
int rb_usascii_encindex(void);
+int rb_ascii8bit_encindex(void);
VALUE rb_enc_default_external(void);
void rb_enc_set_default_external(VALUE encoding);
VALUE rb_locale_charmap(VALUE klass);
--- string.c (revision 16336)
+++ string.c (working copy)
@@ -410,6 +410,15 @@ rb_str_new2(const char *ptr)
}
VALUE
+rb_enc_str_new2(const char *ptr, rb_encoding *enc)
+{
+ if (!ptr) {
+ rb_raise(rb_eArgError, "NULL pointer given");
+ }
+ return rb_enc_str_new(ptr, strlen(ptr), enc);
+}
+
+VALUE
rb_usascii_str_new2(const char *ptr)
{
if (!ptr) {
@@ -436,6 +445,24 @@ rb_tainted_str_new2(const char *ptr)
return str;
}
+VALUE
+rb_tainted_enc_str_new(const char *ptr, long len, rb_encoding *enc)
+{
+ VALUE str = rb_enc_str_new(ptr, len, enc);
+
+ OBJ_TAINT(str);
+ return str;
+}
+
+VALUE
+rb_tainted_enc_str_new2(const char *ptr, rb_encoding *enc)
+{
+ VALUE str = rb_enc_str_new2(ptr, enc);
+
+ OBJ_TAINT(str);
+ return str;
+}
+
static VALUE
str_replace_shared(VALUE str2, VALUE str)
{