Permalink
Browse files

Encoding-related fixes for Dir.

  • Loading branch information...
1 parent 44efdef commit 4dafe807b3689e584cc85f497df0feafd3287dc7 @brixen brixen committed Feb 24, 2014
Showing with 47 additions and 9 deletions.
  1. +15 −4 kernel/bootstrap/dir.rb
  2. +2 −2 kernel/common/dir.rb
  3. +11 −2 vm/builtin/dir.cpp
  4. +4 −1 vm/builtin/dir.hpp
  5. +14 −0 vm/builtin/encoding.cpp
  6. +1 −0 vm/builtin/encoding.hpp
View
19 kernel/bootstrap/dir.rb
@@ -4,9 +4,17 @@ def self.allocate
raise PrimitiveFailure, "Dir.allocate primitive failed"
end
- def initialize(path)
+ def initialize(path, options=undefined)
path = Rubinius::Type.coerce_to_path path
- Rubinius.invoke_primitive :dir_open, self, path
+
+ if options.equal? undefined
+ enc = nil
+ else
+ options = Rubinius::Type.coerce_to options, Hash, :to_hash
+ enc = Rubinius::Type.coerce_to_encoding options[:encoding]
+ end
+
+ Rubinius.invoke_primitive :dir_open, self, path, enc
end
private :initialize
@@ -22,8 +30,11 @@ def closed?
end
def read
- Rubinius.primitive :dir_read
- raise PrimitiveFailure, "Dir#read primitive failed"
+ entry = Rubinius.invoke_primitive :dir_read, self
+ return unless entry
+
+ enc = Encoding.default_internal
+ enc ? entry.encode(enc) : entry
end
def control(kind, pos)
View
4 kernel/common/dir.rb
@@ -8,7 +8,7 @@ class Dir
FFI = Rubinius::FFI
def self.open(path, options=undefined)
- dir = new path
+ dir = new path, options
if block_given?
begin
value = yield dir
@@ -25,7 +25,7 @@ def self.open(path, options=undefined)
def self.entries(path, options=undefined)
ret = []
- open(path) do |dir|
+ open(path, options) do |dir|
while s = dir.read
ret << s
end
View
13 vm/builtin/dir.cpp
@@ -1,6 +1,7 @@
#include "builtin/dir.hpp"
#include "builtin/array.hpp"
#include "builtin/class.hpp"
+#include "builtin/encoding.hpp"
#include "builtin/exception.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/string.hpp"
@@ -46,7 +47,7 @@ namespace rubinius {
}
}
- Object* Dir::open(STATE, String* path) {
+ Object* Dir::open(STATE, String* path, Object* enc) {
if(os_) closedir(os_);
os_ = opendir(path->c_str_null_safe(state));
@@ -58,6 +59,14 @@ namespace rubinius {
this->path(state, path);
+ Encoding* encoding = 0;
+ if(enc->nil_p()) {
+ encoding = Encoding::filesystem_encoding(state);
+ } else {
+ encoding = as<Encoding>(enc);
+ }
+ this->encoding(state, encoding);
+
return cTrue;
}
@@ -88,7 +97,7 @@ namespace rubinius {
if(!entp) return cNil;
String* str = String::create(state, ent.d_name);
- str->encoding(state, Encoding::default_external(state));
+ str->encoding(state, encoding());
return str;
}
View
5 vm/builtin/dir.hpp
@@ -6,6 +6,7 @@
namespace rubinius {
class String;
+ class Encoding;
class Dir : public Object {
public:
@@ -14,10 +15,12 @@ namespace rubinius {
private:
DIR *os_;
String *path_; // slot
+ Encoding* encoding_; // slot
public:
attr_accessor(path, String);
+ attr_accessor(encoding, Encoding);
/* interface */
@@ -31,7 +34,7 @@ namespace rubinius {
static Dir* allocate(STATE, Object* self);
// Rubinius.primitive :dir_open
- Object* open(STATE, String *path);
+ Object* open(STATE, String *path, Object* enc);
// Rubinius.primitive :dir_close
Object* close(STATE);
View
14 vm/builtin/encoding.cpp
@@ -56,6 +56,7 @@ namespace rubinius {
G(encoding)->set_ivar(state, state->symbol("@default_external"), G(undefined));
G(encoding)->set_ivar(state, state->symbol("@default_internal"), G(undefined));
+ G(encoding)->set_ivar(state, state->symbol("@filesystem_encoding"), G(undefined));
Encoding* binary = create_bootstrap(state, "ASCII-8BIT", eBinary, ONIG_ENCODING_ASCII);
Encoding* utf8 = create_bootstrap(state, "UTF-8", eUtf8, ONIG_ENCODING_UTF_8);
@@ -230,6 +231,19 @@ namespace rubinius {
return enc;
}
+ Encoding* Encoding::filesystem_encoding(STATE) {
+ Encoding* enc;
+ Symbol* filesystem_encoding = state->symbol("filesystem_encoding");
+ Object* obj = G(encoding)->get_ivar(state, filesystem_encoding);
+
+ if(!(enc = try_as<Encoding>(obj))) {
+ enc = Encoding::find(state, "filesystem");
+ G(encoding)->set_ivar(state, filesystem_encoding, enc);
+ }
+
+ return enc;
+ }
+
Encoding* Encoding::get_object_encoding(STATE, Object* obj) {
if(String* str = try_as<String>(obj)) {
return str->encoding(state);
View
1 vm/builtin/encoding.hpp
@@ -72,6 +72,7 @@ namespace rubinius {
static Encoding* default_external(STATE);
static Encoding* default_internal(STATE);
+ static Encoding* filesystem_encoding(STATE);
static Encoding* create_bootstrap(STATE, const char* name,
Index index, OnigEncodingType* enc);

0 comments on commit 4dafe80

Please sign in to comment.