From 9134ba21079bc4b681fb5f3caaa00bbf162064d1 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Sat, 21 Feb 2026 04:57:39 +0100 Subject: [PATCH] nihav_hlblocks: split out template formatting into separate module --- nihav-hlblocks/Cargo.toml | 4 +- nihav-hlblocks/src/imgseqdec.rs | 90 +--------------------------- nihav-hlblocks/src/lib.rs | 3 + nihav-hlblocks/src/template.rs | 101 ++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 89 deletions(-) create mode 100644 nihav-hlblocks/src/template.rs diff --git a/nihav-hlblocks/Cargo.toml b/nihav-hlblocks/Cargo.toml index ee09e9a..b931778 100644 --- a/nihav-hlblocks/Cargo.toml +++ b/nihav-hlblocks/Cargo.toml @@ -14,4 +14,6 @@ path = "../nihav-registry" default = [] demuxer = [] -imgseq_dec = [] +imgseq_dec = ["template"] + +template = [] diff --git a/nihav-hlblocks/src/imgseqdec.rs b/nihav-hlblocks/src/imgseqdec.rs index a580655..abab728 100644 --- a/nihav-hlblocks/src/imgseqdec.rs +++ b/nihav-hlblocks/src/imgseqdec.rs @@ -6,93 +6,7 @@ use nihav_core::demuxers::*; use std::fs::File; use std::io::BufReader; use std::io::Read; - -struct TemplateName { - prefix: String, - pad_size: usize, - suffix: String, - single: bool, -} - -trait Deescape { - fn deescape(&mut self); -} - -impl Deescape for String { - fn deescape(&mut self) { - while let Some(idx) = self.find("%%") { - self.remove(idx + 1); - } - } -} - -impl TemplateName { - fn new(name: &str) -> Self { - let mut off = 0; - let mut tmpl_start = 0; - let mut tmpl_end = 0; - let mut pad_size = 0; - 'parse_loop: - while let Some(idx) = name[off..].find('%') { - let idx = idx + off; - if idx + 1 == name.len() { - break; - } - if name[idx + 1..].starts_with('%') { // escape, skip it - off += 1; - } - if name[idx + 1..].starts_with('0') { - if let Some(end_idx) = name[idx + 2..].find('d') { - if let Ok(val) = name[idx + 2..][..end_idx].parse::() { - if val <= 32 { - tmpl_start = idx; - pad_size = val; - tmpl_end = idx + 2 + end_idx + 1; - } - } - break 'parse_loop; - } - } - if name[idx + 1..].starts_with('d') { - tmpl_start = idx; - tmpl_end = idx + 2; - break; - } - off += idx; - } - - if tmpl_end == 0 { - let mut prefix = name.to_owned(); - prefix.deescape(); - Self { - prefix, - pad_size: 0, - suffix: String::new(), - single: true, - } - } else { - let mut prefix = name[..tmpl_start].to_string(); - prefix.deescape(); - let mut suffix = name[tmpl_end..].to_string(); - suffix.deescape(); - Self { - prefix, suffix, pad_size, - single: false, - } - } - } - fn format(&self, id: T) -> String { - let mut number = id.to_string(); - while number.len() < self.pad_size { - number.insert(0, '0'); - } - let mut fname = String::with_capacity(self.prefix.len() + number.len() + self.suffix.len()); - fname.push_str(&self.prefix); - fname.push_str(&number); - fname.push_str(&self.suffix); - fname - } -} +use crate::template::*; /// Image sequence demuxer /// @@ -126,7 +40,7 @@ impl ImgSeqDemuxer { } /// Demuxes a packet. pub fn get_frame(&mut self) -> DemuxerResult { - if self.cur_frame > 0 && self.template.single { + if self.cur_frame > 0 && self.template.is_single() { return Err(DemuxerError::EOF); } let fname = self.template.format(self.cur_frame); diff --git a/nihav-hlblocks/src/lib.rs b/nihav-hlblocks/src/lib.rs index e440eb4..1d232b0 100644 --- a/nihav-hlblocks/src/lib.rs +++ b/nihav-hlblocks/src/lib.rs @@ -6,3 +6,6 @@ pub mod demux; #[cfg(feature="imgseq_dec")] pub mod imgseqdec; +#[cfg(feature="template")] +pub mod template; + diff --git a/nihav-hlblocks/src/template.rs b/nihav-hlblocks/src/template.rs new file mode 100644 index 0000000..c9af951 --- /dev/null +++ b/nihav-hlblocks/src/template.rs @@ -0,0 +1,101 @@ +//! Simple `printf`-like template formatting. + +/// Template for formatting names using a provided pattern. +/// +/// Supported template formats are: +/// * `%d` for simple number substitution e.g. `out%d.ppm` -> `out9.ppm`, `out10.ppm` +/// * `%Nd` for space-padded number substitution e.g. `out%4d.ppm` -> `out 99.ppm` +/// * `%0Nd` for zero-padded number substitution e.g. `out%04d.ppm` -> `out0099.ppm` +/// * and of course `%%` can be used to output single percent sign. +pub struct TemplateName { + prefix: String, + pad_size: usize, + suffix: String, + single: bool, +} + +trait Deescape { + fn deescape(&mut self); +} + +impl Deescape for String { + fn deescape(&mut self) { + while let Some(idx) = self.find("%%") { + self.remove(idx + 1); + } + } +} + +impl TemplateName { + /// Creates a new instance of `TemplateName` from the provided pattern. + pub fn new(name: &str) -> Self { + let mut off = 0; + let mut tmpl_start = 0; + let mut tmpl_end = 0; + let mut pad_size = 0; + 'parse_loop: + while let Some(idx) = name[off..].find('%') { + let idx = idx + off; + if idx + 1 == name.len() { + break; + } + if name[idx + 1..].starts_with('%') { // escape, skip it + off += 1; + } + if name[idx + 1..].starts_with('0') { + if let Some(end_idx) = name[idx + 2..].find('d') { + if let Ok(val) = name[idx + 2..][..end_idx].parse::() { + if val <= 32 { + tmpl_start = idx; + pad_size = val; + tmpl_end = idx + 2 + end_idx + 1; + } + } + break 'parse_loop; + } + } + if name[idx + 1..].starts_with('d') { + tmpl_start = idx; + tmpl_end = idx + 2; + break; + } + off += idx; + } + + if tmpl_end == 0 { + let mut prefix = name.to_owned(); + prefix.deescape(); + Self { + prefix, + pad_size: 0, + suffix: String::new(), + single: true, + } + } else { + let mut prefix = name[..tmpl_start].to_string(); + prefix.deescape(); + let mut suffix = name[tmpl_end..].to_string(); + suffix.deescape(); + Self { + prefix, suffix, pad_size, + single: false, + } + } + } + /// Reports whether template has no substitutions e.g. "output" vs. "output%d" + pub fn is_single(&self) -> bool { self.single } + /// Returns a string formatted using initial pattern and provided argument. + /// + /// If the initial pattern had no formatting specifier, this pattern will be returned instead. + pub fn format(&self, id: T) -> String { + let mut number = id.to_string(); + while number.len() < self.pad_size { + number.insert(0, '0'); + } + let mut fname = String::with_capacity(self.prefix.len() + number.len() + self.suffix.len()); + fname.push_str(&self.prefix); + fname.push_str(&number); + fname.push_str(&self.suffix); + fname + } +} -- 2.39.5