[前][次][番号順一覧][スレッド一覧]

ruby-changes:46764

From: nobu <ko1@a...>
Date: Thu, 25 May 2017 11:50:27 +0900 (JST)
Subject: [ruby-changes:46764] nobu:r58879 (trunk): dir.c: Dir.each_child and Dir.children

nobu	2017-05-25 11:50:21 +0900 (Thu, 25 May 2017)

  New Revision: 58879

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=58879

  Log:
    dir.c: Dir.each_child and Dir.children
    
    * dir.c (dir_s_each_child, dir_s_children): Dir.each_child and
      Dir.children which are similar to Dir.foreach and Dir.entries
      respectively, except to exclude "."  and "..".  [Feature #11302]

  Modified files:
    trunk/NEWS
    trunk/dir.c
    trunk/test/ruby/test_dir.rb
Index: NEWS
===================================================================
--- NEWS	(revision 58878)
+++ NEWS	(revision 58879)
@@ -28,7 +28,9 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L28
 * Dir
 
   * Dir.glob provides new optional keyword argument, :base.
-    [Feature#13056]
+    [Feature #13056]
+  * Dir.children  [Feature #11302]
+  * Dir.each_child  [Feature #11302]
 
 * Integer
 
Index: dir.c
===================================================================
--- dir.c	(revision 58878)
+++ dir.c	(revision 58879)
@@ -774,7 +774,7 @@ dir_read(VALUE dir) https://github.com/ruby/ruby/blob/trunk/dir.c#L774
     }
 }
 
-static VALUE dir_each_entry(VALUE, VALUE (*)(VALUE, VALUE), VALUE);
+static VALUE dir_each_entry(VALUE, VALUE (*)(VALUE, VALUE), VALUE, int);
 
 static VALUE
 dir_yield(VALUE arg, VALUE path)
@@ -806,11 +806,11 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/dir.c#L806
 dir_each(VALUE dir)
 {
     RETURN_ENUMERATOR(dir, 0, 0);
-    return dir_each_entry(dir, dir_yield, Qnil);
+    return dir_each_entry(dir, dir_yield, Qnil, FALSE);
 }
 
 static VALUE
-dir_each_entry(VALUE dir, VALUE (*each)(VALUE, VALUE), VALUE arg)
+dir_each_entry(VALUE dir, VALUE (*each)(VALUE, VALUE), VALUE arg, int children_only)
 {
     struct dir_data *dirp;
     struct dirent *dp;
@@ -823,6 +823,11 @@ dir_each_entry(VALUE dir, VALUE (*each)( https://github.com/ruby/ruby/blob/trunk/dir.c#L823
 	const char *name = dp->d_name;
 	size_t namlen = NAMLEN(dp);
 	VALUE path;
+
+	if (children_only && name[0] == '.') {
+	    if (namlen == 1) continue; /* current directory */
+	    if (namlen == 2 && name[1] == '.') continue; /* parent directory */
+	}
 #if NORMALIZE_UTF8PATH
 	if (norm_p && has_nonascii(name, namlen) &&
 	    !NIL_P(path = rb_str_normalize_ospath(name, namlen))) {
@@ -2628,7 +2633,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/dir.c#L2633
 dir_collect(VALUE dir)
 {
     VALUE ary = rb_ary_new();
-    dir_each_entry(dir, rb_ary_push, ary);
+    dir_each_entry(dir, rb_ary_push, ary, FALSE);
     return ary;
 }
 
@@ -2656,6 +2661,76 @@ dir_entries(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/dir.c#L2661
     return rb_ensure(dir_collect, dir, dir_close, dir);
 }
 
+static VALUE
+dir_each_child(VALUE dir)
+{
+    return dir_each_entry(dir, dir_yield, Qnil, TRUE);
+}
+
+/*
+ *  call-seq:
+ *     Dir.each_child( dirname ) {| filename | block }                 -> nil
+ *     Dir.each_child( dirname, encoding: enc ) {| filename | block }  -> nil
+ *     Dir.each_child( dirname )                                       -> an_enumerator
+ *     Dir.each_child( dirname, encoding: enc )                        -> an_enumerator
+ *
+ *  Calls the block once for each entry except for "." and ".." in the
+ *  named directory, passing the filename of each entry as a parameter
+ *  to the block.
+ *
+ *  If no block is given, an enumerator is returned instead.
+ *
+ *     Dir.foreach("testdir") {|x| puts "Got #{x}" }
+ *
+ *  <em>produces:</em>
+ *
+ *     Got config.h
+ *     Got main.rb
+ *
+ */
+static VALUE
+dir_s_each_child(int argc, VALUE *argv, VALUE io)
+{
+    VALUE dir;
+
+    RETURN_ENUMERATOR(io, argc, argv);
+    dir = dir_open_dir(argc, argv);
+    rb_ensure(dir_each_child, dir, dir_close, dir);
+    return Qnil;
+}
+
+static VALUE
+dir_collect_children(VALUE dir)
+{
+    VALUE ary = rb_ary_new();
+    dir_each_entry(dir, rb_ary_push, ary, TRUE);
+    return ary;
+}
+
+/*
+ *  call-seq:
+ *     Dir.children( dirname )                -> array
+ *     Dir.children( dirname, encoding: enc ) -> array
+ *
+ *  Returns an array containing all of the filenames except for "."
+ *  and ".." in the given directory. Will raise a
+ *  <code>SystemCallError</code> if the named directory doesn't exist.
+ *
+ *  The optional <i>encoding</i> keyword argument specifies the encoding of the
+ *  directory. If not specified, the filesystem encoding is used.
+ *
+ *     Dir.entries("testdir")   #=> ["config.h", "main.rb"]
+ *
+ */
+static VALUE
+dir_s_children(int argc, VALUE *argv, VALUE io)
+{
+    VALUE dir;
+
+    dir = dir_open_dir(argc, argv);
+    return rb_ensure(dir_collect_children, dir, dir_close, dir);
+}
+
 static int
 fnmatch_brace(const char *pattern, VALUE val, void *enc)
 {
@@ -2954,6 +3029,8 @@ Init_Dir(void) https://github.com/ruby/ruby/blob/trunk/dir.c#L3029
     rb_define_singleton_method(rb_cDir, "open", dir_s_open, -1);
     rb_define_singleton_method(rb_cDir, "foreach", dir_foreach, -1);
     rb_define_singleton_method(rb_cDir, "entries", dir_entries, -1);
+    rb_define_singleton_method(rb_cDir, "each_child", dir_s_each_child, -1);
+    rb_define_singleton_method(rb_cDir, "children", dir_s_children, -1);
 
     rb_define_method(rb_cDir,"initialize", dir_initialize, -1);
     rb_define_method(rb_cDir,"fileno", dir_fileno, 0);
Index: test/ruby/test_dir.rb
===================================================================
--- test/ruby/test_dir.rb	(revision 58878)
+++ test/ruby/test_dir.rb	(revision 58879)
@@ -214,9 +214,11 @@ class TestDir < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_dir.rb#L214
     assert_equal(files, Dir.open(@root) {|d| Dir.glob("*/*.c", base: d)}.sort)
   end
 
-  def assert_entries(entries)
+  def assert_entries(entries, children = false)
     entries.sort!
-    assert_equal(%w(. ..) + ("a".."z").to_a, entries)
+    expected = ("a".."z").to_a
+    expected = %w(. ..) + expected unless children
+    assert_equal(expected, entries)
   end
 
   def test_entries
@@ -228,6 +230,14 @@ class TestDir < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_dir.rb#L230
     assert_entries(Dir.foreach(@root).to_a)
   end
 
+  def test_children
+    assert_entries(Dir.children(@root), true)
+  end
+
+  def test_each_child
+    assert_entries(Dir.each_child(@root).to_a, true)
+  end
+
   def test_dir_enc
     dir = Dir.open(@root, encoding: "UTF-8")
     begin

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]