summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2026-05-06 18:12:01 +0900
committerNobuyoshi Nakada <nobu.nakada@gmail.com>2026-05-13 17:37:48 +0900
commit7c5c967fca7c873414b1eed56d662dc4118123dd (patch)
treee6dc94810c4c84276d059e06065203e04db2f88c
parentd8e6bf63edf8941d968ed7657c418133c47ae344 (diff)
pathname: Define has_separator? instead of SEPARATOR_PAT
-rw-r--r--depend2
-rw-r--r--pathname.c32
-rw-r--r--pathname_builtin.rb8
3 files changed, 38 insertions, 4 deletions
diff --git a/depend b/depend
index 33249a03be..7faf59f5a4 100644
--- a/depend
+++ b/depend
@@ -11146,6 +11146,7 @@ pathname.$(OBJEXT): $(top_srcdir)/internal/compilers.h
pathname.$(OBJEXT): $(top_srcdir)/internal/file.h
pathname.$(OBJEXT): $(top_srcdir)/internal/serial.h
pathname.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+pathname.$(OBJEXT): $(top_srcdir)/internal/string.h
pathname.$(OBJEXT): $(top_srcdir)/internal/vm.h
pathname.$(OBJEXT): $(top_srcdir)/internal/warnings.h
pathname.$(OBJEXT): {$(VPATH)}assert.h
@@ -11162,6 +11163,7 @@ pathname.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
pathname.$(OBJEXT): {$(VPATH)}builtin.h
pathname.$(OBJEXT): {$(VPATH)}config.h
pathname.$(OBJEXT): {$(VPATH)}defines.h
+pathname.$(OBJEXT): {$(VPATH)}encindex.h
pathname.$(OBJEXT): {$(VPATH)}encoding.h
pathname.$(OBJEXT): {$(VPATH)}intern.h
pathname.$(OBJEXT): {$(VPATH)}internal.h
diff --git a/pathname.c b/pathname.c
index e8959bb976..72930ff473 100644
--- a/pathname.c
+++ b/pathname.c
@@ -1,6 +1,7 @@
#include "ruby.h"
#include "internal.h"
#include "internal/file.h"
+#include "internal/string.h"
#include "internal/vm.h"
#if defined __CYGWIN__ || defined DOSISH
@@ -18,6 +19,14 @@ static ID id_at_path;
static ID id_sub;
static VALUE
+check_strpath(VALUE path)
+{
+ Check_Type(path, T_STRING);
+ rb_get_path_check_no_convert(path);
+ return path;
+}
+
+static VALUE
get_strpath(VALUE obj)
{
VALUE strpath;
@@ -156,6 +165,27 @@ path_absolute_p(VALUE self)
return RBOOL(isdirsep(ptr[0]));
}
+/* :nodoc: */
+static VALUE
+has_separator_p(VALUE self, VALUE path)
+{
+ const char *ptr = RSTRING_PTR(check_strpath(path));
+ const char *end = RSTRING_END(path);
+ if (alt_separator) {
+ rb_encoding *enc = rb_enc_get(path);
+ bool mb = !rb_str_enc_fastpath(path);
+ while (ptr < end) {
+ if (isdirsep(*ptr)) return Qtrue;
+ ptr += (mb ? rb_enc_mbclen(ptr, end, enc) : 1);
+ }
+ }
+ else {
+ /* assume '/' will never be trailing bytes */
+ if (memchr(ptr, '/', end - ptr)) return Qtrue;
+ }
+ return Qfalse;
+}
+
#include "pathname_builtin.rbinc"
static void init_ids(void);
@@ -180,6 +210,8 @@ InitVM_pathname(void)
rb_define_method(rb_cPathname, "root?", path_root_p, 0);
rb_define_method(rb_cPathname, "absolute?", path_absolute_p, 0);
+ rb_define_private_method(rb_cPathname, "has_separator?", has_separator_p, 1);
+
rb_provide("pathname.so");
}
diff --git a/pathname_builtin.rb b/pathname_builtin.rb
index a38e28de8a..5bab73ea49 100644
--- a/pathname_builtin.rb
+++ b/pathname_builtin.rb
@@ -383,7 +383,7 @@ class Pathname
def prepend_prefix(prefix, relpath) # :nodoc:
if relpath.empty?
File.dirname(prefix)
- elsif SEPARATOR_PAT.match?(prefix)
+ elsif has_separator?(prefix)
prefix = File.dirname(prefix)
prefix = File.join(prefix, "") if File.basename(prefix + 'a') != 'a'
prefix + relpath
@@ -524,7 +524,7 @@ class Pathname
end
end
pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
- if SEPARATOR_PAT.match?(File.basename(pre))
+ if has_separator?(File.basename(pre))
names.shift while names[0] == '..'
end
self.class.new(prepend_prefix(pre, File.join(*names)))
@@ -573,7 +573,7 @@ class Pathname
names.unshift base if base != '.'
end
pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
- if SEPARATOR_PAT.match?(File.basename(pre))
+ if has_separator?(File.basename(pre))
names.shift while names[0] == '..'
end
if names.empty?
@@ -800,7 +800,7 @@ class Pathname
basename_list2.shift
end
r1 = chop_basename(prefix1)
- if !r1 && (r1 = SEPARATOR_PAT.match?(File.basename(prefix1)))
+ if !r1 && (r1 = has_separator?(File.basename(prefix1)))
while !basename_list2.empty? && basename_list2.first == '..'
index_list2.shift
basename_list2.shift