summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2026-05-06 20:08:02 +0900
committerNobuyoshi Nakada <nobu.nakada@gmail.com>2026-05-13 17:37:48 +0900
commit488b8e58bc90b29655bd9f85611abcebc58bb11f (patch)
tree92b688a274f367edc028a249bb2d11ec02da9bcb
parent9021799650021684e5586215f00f0b701d6160ab (diff)
pathname: Move root? to pathname.c
-rw-r--r--file.c5
-rw-r--r--internal/file.h1
-rw-r--r--pathname.c19
-rw-r--r--pathname_builtin.rb11
4 files changed, 25 insertions, 11 deletions
diff --git a/file.c b/file.c
index db29642ac2..b045e8e899 100644
--- a/file.c
+++ b/file.c
@@ -3767,6 +3767,11 @@ skipprefixroot(const char *path, const char *end, rb_encoding *enc)
#endif
}
+char *
+rb_enc_path_skip_prefix_root(const char *path, const char *end, rb_encoding *enc)
+{
+ return skipprefixroot(path, end, enc);
+}
static char *
enc_path_last_separator(const char *path, const char *end, bool mb_enc, rb_encoding *enc)
diff --git a/internal/file.h b/internal/file.h
index 29e9cdf4b9..1aa4c67043 100644
--- a/internal/file.h
+++ b/internal/file.h
@@ -25,6 +25,7 @@ VALUE rb_get_path_check_to_string(VALUE);
VALUE rb_get_path_check_convert(VALUE);
VALUE rb_get_path_check_no_convert(VALUE);
int ruby_is_fd_loadable(int fd);
+char *rb_enc_path_skip_prefix_root(const char *path, const char *end, rb_encoding *enc);
RUBY_SYMBOL_EXPORT_BEGIN
/* file.c (export) */
diff --git a/pathname.c b/pathname.c
index 87382dd804..e8959bb976 100644
--- a/pathname.c
+++ b/pathname.c
@@ -112,6 +112,24 @@ path_sub(int argc, VALUE *argv, VALUE self)
}
/*
+ * Predicate method for root directories. Returns +true+ if the
+ * pathname consists of consecutive slashes.
+ *
+ * It doesn't access the filesystem. So it may return +false+ for some
+ * pathnames which points to roots such as <tt>/usr/..</tt>.
+ */
+static VALUE
+path_root_p(VALUE self)
+{
+ VALUE path = get_strpath(self);
+ if (RSTRING_LEN(path) == 0) return Qfalse;
+ const char *ptr = RSTRING_PTR(path), *end = RSTRING_END(path);
+ rb_encoding *enc = rb_enc_get(path);
+ const char *base = rb_enc_path_skip_prefix_root(ptr, end, enc);
+ return RBOOL(base == end);
+}
+
+/*
* call-seq:
* absolute? -> true or false
*
@@ -159,6 +177,7 @@ InitVM_pathname(void)
rb_cPathname = rb_define_class("Pathname", rb_cObject);
rb_define_method(rb_cPathname, "<=>", path_cmp, 1);
rb_define_method(rb_cPathname, "sub", path_sub, -1);
+ rb_define_method(rb_cPathname, "root?", path_root_p, 0);
rb_define_method(rb_cPathname, "absolute?", path_absolute_p, 0);
rb_provide("pathname.so");
diff --git a/pathname_builtin.rb b/pathname_builtin.rb
index b9cba0260f..cab20678db 100644
--- a/pathname_builtin.rb
+++ b/pathname_builtin.rb
@@ -621,17 +621,6 @@ class Pathname
end
end
- #
- # Predicate method for root directories. Returns +true+ if the
- # pathname consists of consecutive slashes.
- #
- # It doesn't access the filesystem. So it may return +false+ for some
- # pathnames which points to roots such as <tt>/usr/..</tt>.
- #
- def root?
- chop_basename(@path) == nil && SEPARATOR_PAT.match?(@path)
- end
-
# The opposite of Pathname#absolute?
#
# It returns +false+ if the pathname begins with a slash.