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

ruby-changes:25406

From: nobu <ko1@a...>
Date: Sun, 4 Nov 2012 10:19:43 +0900 (JST)
Subject: [ruby-changes:25406] nobu:r37463 (trunk): dir.c: FNM_EXTGLOB

nobu	2012-11-04 10:19:11 +0900 (Sun, 04 Nov 2012)

  New Revision: 37463

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=37463

  Log:
    dir.c: FNM_EXTGLOB
    
    * dir.c (file_s_fnmatch): match with expanding braces if FNM_EXTGLOB
      is set.  [ruby-core:40037] [Feature #5422]

  Modified files:
    trunk/ChangeLog
    trunk/NEWS
    trunk/dir.c
    trunk/test/ruby/envutil.rb
    trunk/test/ruby/test_fnmatch.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 37462)
+++ ChangeLog	(revision 37463)
@@ -1,3 +1,8 @@
+Sun Nov  4 10:19:03 2012  Nobuyoshi Nakada  <nobu@r...>
+
+	* dir.c (file_s_fnmatch): match with expanding braces if FNM_EXTGLOB
+	  is set.  [ruby-core:40037] [Feature #5422]
+
 Sat Nov  3 23:38:15 2012  Tadayoshi Funaba  <tadf@d...>
 
 	* complex.c: modified doc.
Index: dir.c
===================================================================
--- dir.c	(revision 37462)
+++ dir.c	(revision 37463)
@@ -85,6 +85,7 @@
 #define FNM_PATHNAME	0x02
 #define FNM_DOTMATCH	0x04
 #define FNM_CASEFOLD	0x08
+#define FNM_EXTGLOB	0x10
 #if CASEFOLD_FILESYSTEM
 #define FNM_SYSCASE	FNM_CASEFOLD
 #else
@@ -1912,6 +1913,15 @@
     return rb_ensure(rb_Array, dir, dir_close, dir);
 }
 
+static int
+fnmatch_brace(const char *pattern, VALUE val, void *enc)
+{
+    struct brace_args *arg = (struct brace_args *)val;
+    VALUE path = arg->value;
+
+    return (fnmatch(pattern, enc, RSTRING_PTR(path), arg->flags) == 0);
+}
+
 /*
  *  call-seq:
  *     File.fnmatch( pattern, path, [flags] ) -> (true or false)
@@ -2008,10 +2018,22 @@
     StringValue(pattern);
     FilePathStringValue(path);
 
-    if (fnmatch(RSTRING_PTR(pattern), rb_enc_get(pattern), RSTRING_PTR(path),
-		flags) == 0)
-	return Qtrue;
+    if (flags & FNM_EXTGLOB) {
+	struct brace_args args;
 
+	args.value = path;
+	args.flags = flags;
+	if (ruby_brace_expand(RSTRING_PTR(pattern), flags, fnmatch_brace,
+			      (VALUE)&args, rb_enc_get(pattern)) > 0)
+	    return Qtrue;
+    }
+    else {
+	if (fnmatch(RSTRING_PTR(pattern), rb_enc_get(pattern), RSTRING_PTR(path),
+		    flags) == 0)
+	    return Qtrue;
+    }
+    RB_GC_GUARD(pattern);
+
     return Qfalse;
 }
 
@@ -2111,5 +2133,6 @@
     rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME));
     rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH));
     rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD));
+    rb_file_const("FNM_EXTGLOB", INT2FIX(FNM_EXTGLOB));
     rb_file_const("FNM_SYSCASE", INT2FIX(FNM_SYSCASE));
 }
Index: NEWS
===================================================================
--- NEWS	(revision 37462)
+++ NEWS	(revision 37463)
@@ -31,6 +31,11 @@
     * aliased method:
       * ENV.to_h is a new alias for ENV.to_hash
 
+  * File:
+    * extended method:
+      * File.fnmatch? now expands braces in the pattern if
+        File::FNM_EXTGLOB option is given.
+
   * Hash
     * added method:
       * added Hash#to_h as explicit conversion method, like Array#to_a.
Index: test/ruby/test_fnmatch.rb
===================================================================
--- test/ruby/test_fnmatch.rb	(revision 37462)
+++ test/ruby/test_fnmatch.rb	(revision 37463)
@@ -1,4 +1,5 @@
 require 'test/unit'
+require_relative 'envutil'
 
 class TestFnmatch < Test::Unit::TestCase
 
@@ -103,4 +104,9 @@
     assert(File.fnmatch('**/foo', 'c:/root/foo', File::FNM_PATHNAME))
   end
 
+  def test_extglob
+    feature5422 = '[ruby-core:40037]'
+    assert_file.for(feature5422).not_fnmatch?( "{.g,t}*", ".gem")
+    assert_file.for(feature5422).fnmatch?("{.g,t}*", ".gem", File::FNM_EXTGLOB)
+  end
 end
Index: test/ruby/envutil.rb
===================================================================
--- test/ruby/envutil.rb	(revision 37462)
+++ test/ruby/envutil.rb	(revision 37463)
@@ -229,7 +229,7 @@
         AssertFile
       end
 
-      class << (AssertFile = Object.new)
+      class << (AssertFile = Struct.new(:message).new)
         include Assertions
         def assert_file_predicate(predicate, *args)
           if /\Anot_/ =~ predicate
@@ -241,9 +241,14 @@
           mesg = "Expected file " << args.shift.inspect
           mesg << mu_pp(args) unless args.empty?
           mesg << "#{neg} to be #{predicate}"
+          mesg << " #{message}" if message
           assert(result, mesg)
         end
         alias method_missing assert_file_predicate
+
+        def for(message)
+          clone.tap {|a| a.message = message}
+        end
       end
     end
   end

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

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