@@ -409,3 +409,80 @@ int qe_rename(struct q_entry *e, const char *new, uint flags)
409409 ffmem_free ((char * )new );
410410 return rc ;
411411}
412+
413+ /** All printable, plus SPACE, except: ", *, /, :, <, >, ?, \, | */
414+ static const uint _ffpath_charmask_filename [] = {
415+ 0 ,
416+ // ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"!
417+ 0x2bff7bfb , // 0010 1011 1111 1111 0111 1011 1111 1011
418+ // _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@
419+ 0xefffffff , // 1110 1111 1111 1111 1111 1111 1111 1111
420+ // ~}| {zyx wvut srqp onml kjih gfed cba`
421+ 0x6fffffff , // 0110 1111 1111 1111 1111 1111 1111 1111
422+ 0xffffffff ,
423+ 0xffffffff ,
424+ 0xffffffff ,
425+ 0xffffffff
426+ };
427+
428+ static void q_rename_first_close (void * f , phi_track * t )
429+ {
430+ struct q_entry * e = t -> qent ;
431+ ffstr s , val , dir , ext ;
432+ ffvec buf = {};
433+
434+ // Extract file meta components to prepare the target file name
435+ ffstr out = FFSTR_INITZ (e -> q -> rename_pattern );
436+ while (out .len ) {
437+ if ('v' == ffstr_var_next (& out , & s , '@' )) {
438+ ffstr_shift (& s , 1 );
439+ core -> metaif -> find (& t -> meta , s , & val , 0 );
440+ ffvec_grow (& buf , val .len , 1 );
441+ buf .len += ffpath_makename (ffslice_end (& buf , 1 ), -1 , val , '_' , _ffpath_charmask_filename );
442+
443+ } else {
444+ ffvec_addstr (& buf , & s );
445+ }
446+ }
447+
448+ ffpath_split3_str (FFSTR_Z (t -> conf .ifile .name ), & dir , NULL , & ext );
449+ if (dir .len )
450+ dir .len ++ ; // "dir" -> "dir/"
451+ if (ext .len )
452+ ext .ptr -- , ext .len ++ ; // "ext" -> ".ext"
453+ char * fn = ffsz_allocfmt ("%S%S%S" , & dir , & buf , & ext );
454+ qe_rename (t -> qent , fn , PHI_QRN_ACQUIRE );
455+
456+ qe_unref (e );
457+ core -> metaif -> destroy (& t -> meta );
458+ ffvec_free (& buf );
459+ q_rename_next (e -> q );
460+ }
461+
462+ static int q_rename_first_process (void * f , phi_track * t )
463+ {
464+ return PHI_DONE ;
465+ }
466+
467+ static const phi_filter q_rename_first = {
468+ NULL , q_rename_first_close , q_rename_first_process ,
469+ "q-rename-first"
470+ };
471+
472+ void qe_rename_start (struct q_entry * e )
473+ {
474+ struct phi_track_conf c = {
475+ .ifile .name = e -> pub .url ,
476+ .info_only = 1 ,
477+ };
478+ phi_track * t = core -> track -> create (& c );
479+
480+ core -> track -> filter (t , e -> q -> conf .first_filter , 0 );
481+ core -> track -> filter (t , & q_rename_first , 0 );
482+ core -> track -> filter (t , core -> mod ("core.auto-input" ), 0 );
483+ core -> track -> filter (t , core -> mod ("format.detect" ), 0 );
484+
485+ e -> used ++ ;
486+ t -> qent = & e -> pub ;
487+ core -> track -> start (t );
488+ }
0 commit comments