@@ -4931,13 +4931,14 @@ enc_find_basename(const char *name, long *baselen, long *alllen, bool mb_enc, rb
49314931 root = name ;
49324932#endif
49334933
4934- while (isdirsep (* name )) {
4934+ while (name < end && isdirsep (* name )) {
49354935 name ++ ;
49364936 }
49374937
4938- if (! * name ) {
4938+ if (name == end ) {
49394939 p = name - 1 ;
49404940 f = 1 ;
4941+ n = 1 ;
49414942#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
49424943 if (name != root ) {
49434944 /* has slashes */
@@ -5048,9 +5049,7 @@ rb_file_s_basename(int argc, VALUE *argv, VALUE _)
50485049 f = n ;
50495050 }
50505051 else {
5051- const char * fp ;
5052- fp = StringValueCStr (fext );
5053- if (!(f = rmext (p , f , n , fp , RSTRING_LEN (fext ), enc ))) {
5052+ if (!(f = rmext (p , f , n , RSTRING_PTR (fext ), RSTRING_LEN (fext ), enc ))) {
50545053 f = n ;
50555054 }
50565055 RB_GC_GUARD (fext );
@@ -5064,6 +5063,7 @@ rb_file_s_basename(int argc, VALUE *argv, VALUE _)
50645063}
50655064
50665065static VALUE rb_file_dirname_n (VALUE fname , int n );
5066+ static VALUE dirname_part (const char * * namep , const char * end , bool mb_enc , rb_encoding * enc , int n );
50675067
50685068/*
50695069 * call-seq:
@@ -5103,15 +5103,22 @@ rb_file_dirname(VALUE fname)
51035103static VALUE
51045104rb_file_dirname_n (VALUE fname , int n )
51055105{
5106- const char * name , * root , * p , * end ;
5107- VALUE dirname ;
5106+ const char * name ;
51085107
51095108 if (n < 0 ) rb_raise (rb_eArgError , "negative level: %d" , n );
51105109 CheckPath (fname , name );
5111- end = name + RSTRING_LEN (fname );
51125110
5113- bool mb_enc = !rb_str_enc_fastpath (fname );
5114- rb_encoding * enc = rb_str_enc_get (fname );
5111+ int encidx = ENCODING_GET_INLINED (fname );
5112+ bool mb_enc = !rb_str_encindex_fastpath (encidx );
5113+ rb_encoding * enc = rb_enc_from_index (encidx );
5114+ return dirname_part (& name , name + RSTRING_LEN (fname ), mb_enc , enc , n );
5115+ }
5116+
5117+ static VALUE
5118+ dirname_part (const char * * namep , const char * end , bool mb_enc , rb_encoding * enc , int n )
5119+ {
5120+ VALUE dirname ;
5121+ const char * name = * namep , * root , * p ;
51155122
51165123 root = skiproot (name , end );
51175124#ifdef DOSISH_UNC
@@ -5135,6 +5142,7 @@ rb_file_dirname_n(VALUE fname, int n)
51355142 }
51365143 }
51375144
5145+ * namep = p == root && p > name ? p - 1 : p ;
51385146 if (p == name ) {
51395147 return rb_enc_str_new ("." , 1 , enc );
51405148 }
@@ -5314,10 +5322,43 @@ rb_file_s_path(VALUE klass, VALUE fname)
53145322 */
53155323
53165324static VALUE
5317- rb_file_s_split (VALUE klass , VALUE path )
5325+ rb_file_s_split (int argc , VALUE * argv , VALUE klass )
53185326{
5319- FilePathStringValue (path ); /* get rid of converting twice */
5320- return rb_assoc_new (rb_file_dirname (path ), rb_file_s_basename (1 ,& path ,Qundef ));
5327+ const char * name , * suffix = 0 ;
5328+ long sufflen = 0 ;
5329+ VALUE path , dir , fext = Qnil ;
5330+ rb_encoding * enc ;
5331+ argc = rb_check_arity (argc , 1 , 2 );
5332+ path = argv [0 ];
5333+ CheckPath (path , name );
5334+ if (argc > 1 && !NIL_P (fext = argv [1 ])) {
5335+ suffix = StringValueCStr (fext );
5336+ sufflen = RSTRING_LEN (fext );
5337+ if (!(enc = rb_enc_compatible (path , fext ))) {
5338+ enc = rb_str_enc_get (path );
5339+ suffix = 0 ;
5340+ }
5341+ }
5342+ else {
5343+ enc = rb_str_enc_get (path );
5344+ }
5345+ const char * base = name ;
5346+ const char * end = name + RSTRING_LEN (path );
5347+ bool mb_enc = !rb_str_encindex_fastpath (rb_enc_to_index (enc ));
5348+ dir = dirname_part (& base , end , mb_enc , enc , 1 );
5349+ long f = 0 , n = (long )(end - base );
5350+ base = enc_find_basename (base , & f , & n , mb_enc , enc );
5351+ if (!suffix ) {
5352+ return rb_assoc_new (dir , rb_enc_str_new (base , n , enc ));
5353+ }
5354+ else {
5355+ long b = rmext (base , f , n , suffix , sufflen , enc );
5356+ if (!b ) b = n ;
5357+ RB_GC_GUARD (fext );
5358+ VALUE basename = rb_enc_str_new (base , b , enc );
5359+ VALUE ext = rb_enc_str_new (base + f , n - b , enc );
5360+ return rb_ary_new_from_args (3 , dir , basename , ext );
5361+ }
53215362}
53225363
53235364static VALUE rb_file_join_ary (VALUE ary );
@@ -7721,7 +7762,7 @@ Init_File(void)
77217762 rb_define_const (rb_cFile , "Separator" , separator );
77227763 /* separates directory parts in path */
77237764 rb_define_const (rb_cFile , "SEPARATOR" , separator );
7724- rb_define_singleton_method (rb_cFile , "split" , rb_file_s_split , 1 );
7765+ rb_define_singleton_method (rb_cFile , "split" , rb_file_s_split , - 1 );
77257766 rb_define_singleton_method (rb_cFile , "join" , rb_file_s_join , -1 );
77267767
77277768#ifdef DOSISH
0 commit comments