summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2026-05-02 17:02:48 +0900
committerNobuyoshi Nakada <nobu.nakada@gmail.com>2026-05-13 17:37:48 +0900
commit820554c8d219089cae4fa71af4586e139c593ae7 (patch)
tree8797ae595bab17e0d9d7ad1b4dbfa59fe5299a53
parent7c5c967fca7c873414b1eed56d662dc4118123dd (diff)
pathname: Move sub_ext to pathname.c
Including platform depending code.
-rw-r--r--pathname.c28
-rw-r--r--pathname_builtin.rb20
2 files changed, 28 insertions, 20 deletions
diff --git a/pathname.c b/pathname.c
index 72930ff473..aec9fb3d00 100644
--- a/pathname.c
+++ b/pathname.c
@@ -186,6 +186,33 @@ has_separator_p(VALUE self, VALUE path)
return Qfalse;
}
+/*
+ * Return a pathname with +repl+ added as a suffix to the basename.
+ *
+ * If self has no extension part, +repl+ is appended.
+ *
+ * Pathname.new('/usr/bin/shutdown').sub_ext('.rb')
+ * #=> #<Pathname:/usr/bin/shutdown.rb>
+ */
+static VALUE
+path_sub_ext(VALUE self, VALUE repl)
+{
+ VALUE path = get_strpath(self);
+ long len = RSTRING_LEN(path);
+ const char *ptr = RSTRING_PTR(path);
+ const char *ext = ruby_enc_find_extname(ptr, &len, rb_enc_get(path));
+ if (len > 0) {
+ RUBY_ASSERT(ext, "should point the last dot");
+ path = rb_str_subseq(path, 0, ext - ptr);
+ }
+ else {
+ /* no dot or dotted file */
+ path = rb_str_dup(path);
+ }
+ path = rb_str_append(path, repl);
+ return rb_class_new_instance(1, &path, rb_obj_class(self));
+}
+
#include "pathname_builtin.rbinc"
static void init_ids(void);
@@ -207,6 +234,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, "sub_ext", path_sub_ext, 1);
rb_define_method(rb_cPathname, "root?", path_root_p, 0);
rb_define_method(rb_cPathname, "absolute?", path_absolute_p, 0);
diff --git a/pathname_builtin.rb b/pathname_builtin.rb
index 5bab73ea49..26f7f4025f 100644
--- a/pathname_builtin.rb
+++ b/pathname_builtin.rb
@@ -298,26 +298,6 @@ class Pathname
"#<#{self.class}:#{@path}>"
end
- # Return a pathname with +repl+ added as a suffix to the basename.
- #
- # If self has no extension part, +repl+ is appended.
- #
- # Pathname.new('/usr/bin/shutdown').sub_ext('.rb')
- # #=> #<Pathname:/usr/bin/shutdown.rb>
- def sub_ext(repl)
- ext = File.extname(@path)
-
- # File.extname("foo.bar:stream") returns ".bar" on NTFS and not ".bar:stream"
- # (see ruby_enc_find_extname()).
- # The behavior of Pathname#sub_ext is to replace everything
- # from the start of the extname until the end of the path with repl.
- unless @path.end_with?(ext)
- ext = @path[@path.rindex(ext)..]
- end
-
- self.class.new(@path.chomp(ext) + repl)
- end
-
if File::ALT_SEPARATOR
# Separator list string.
separator_list = Regexp.quote "#{File::ALT_SEPARATOR}#{File::SEPARATOR}"