From 0a6209dfd5f5061b3f93d5b053f090d143217c44 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Wed, 11 Oct 2023 13:00:50 -0400 Subject: [PATCH] Add tests for ConfigFile, fix writing and add modification functions --- resources/tests/FFXIV.cfg | Bin 0 -> 4492 bytes resources/tests/FFXIV.modified.cfg | Bin 0 -> 4492 bytes src/cfg.rs | 97 +++++++++++++++++++++++++---- 3 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 resources/tests/FFXIV.cfg create mode 100644 resources/tests/FFXIV.modified.cfg diff --git a/resources/tests/FFXIV.cfg b/resources/tests/FFXIV.cfg new file mode 100644 index 0000000000000000000000000000000000000000..70c734f793da6931916b88e9c6d559ffca74c4c8 GIT binary patch literal 4492 zcmb7IZExE)5Z+e>$bZNW*oMSu+6E{F$ab7~b7IeOl5SrDMmpPEWm2Q4xM{KfzUN3u zrt$_f1rps0?~cdgbI0!QeHx9g;>p1%zFNe|Uk9JZHwOc)mU4A4k~#ghzqh~l>4r=x zwE}To$*iWLljDzvCx^$qcl&#OMI-3#?@feSRboZa(f;0?R#+SzI#X95UB|*ZFJQ80H>a@&_(p&uqAJ0X4g>o$nM;V z3zDm~jXv~R&ZW+X!x>e1?sdXdJ8rmgPD?}O+6YV0dtO_VoP=0e8Rt@zNDkAZSu$2} zYUM+n%TizJs-&S2PVR_lK@+)=*5^vC63QvHNp;VRbFtZo=mcNavM)+XQjt@HGa9Ug z5fir;C%nL?7lOp8pBquEWm<+AT+mlr8A53whksTgm-dlu)%;k=Qd^@7nKnY$N|JcW zdpXaAah`EB7Ke?hxW)Dj8yHey*VE-lQl7EyTx3$@{k$?v-N=>l1>@`(QI?H;c5Z|! z^C~4}8!mfYi%f5CWGU|@hq-txoO91l^wRn-$A^!a@*7O#H|h!oqD)0b16?WGn40LU zRkDV}28ZStaDPsUjL4gS;9#1jdByi=fHJ9%*E^j|hrF-Z`msd58YLci7ZBqMu)$ioUj>S4dYDo{qW}>`Um$u5o1+U4su4?q%~$nf=-|3;%l4QRPpr-~h*uIt?AkP%KIR-o~4Mu9*%VgIwYff~;I8!4qG+29~t90GmVs~w7 z#-K8#Hc0^>apOv(=WDFdBiV^E6gU9+DYffUf=0=L>pWh+~IQDVI>GmnC zSEtM?G4ZYj%Ff!O=tA3jVeasxzw>|>$`?ig12M1vUTum{ zFpwq%+Yfvlfzf3dG0qg7C=+ZQ???1}#Bm?4@N;5xaXmy3{J`i4dAC?4)j;DVtg=uz zNg~`3x@$oq6wVVw$I$(_F literal 0 HcmV?d00001 diff --git a/resources/tests/FFXIV.modified.cfg b/resources/tests/FFXIV.modified.cfg new file mode 100644 index 0000000000000000000000000000000000000000..78e2dadef44ca9f5d9ea45e4dea2b520e4a136cb GIT binary patch literal 4492 zcmb7IZExE)5Z+e>$bZNW*oMSu+6E{F$ab7~b7IeOl5SrDMmpPEWm2Q4xM{KfzUN3u zrt$_f1rps0?~cdgbI0!QeHx9g;>p1%zFNe|Uk9JZHwOc)mU4A4k~#ghzqh~l>4r=x zwE}To$*iWLljDzvCx^$qcl&#OMI-3#?@feSRboZa(f;0?R#+SzI#X95UB|*ZFJQ80H>a@&_(p&uqAJ0X4g>o$nM;V z3zDm~jXv~R&ZW+X!x>e1?sdXdJ8rmgPD?}O+6YV0dtO_VoP=0e8Rt@zNDkAZSu$2} zYUM+n%TizJs-&S2PVR_lK@+)=*5^vC63QvHNp;VRbFtZo=mcNavM)+XQjt@HGa9Ug z5fir;C%nL?7lOp8pBquEWm<+AT+mlr8A53whksTgm-dlu)%;k=Qd^@7nKnY$N|JcW zdpXaAah`EB7Ke?hxW)Dj8yHey*VE-lQl7EyTx3$@{k$?v-N=>l1>@`(QI?H;c5Z|! z^C~4}8!mfYi%f5CWGU|@hq-txoO91l^wRn-$A^!a@*7O#H|h!oqD)0b16?WGn40LU zRkDV}28ZStaDPsUjL4gS;9#1jdByi=fHJ9%*E^j|hrF-Z`msd58YLci7ZBqMu)$ioUj>S4dYDo{qW}>`Um$u5o1+U4su4?q%~$nf=-|3;%l4QRPpr-~h*uIt?AkP%KIR-o~4Mu9*%VgIwYff~;I8!4qG+29~t90GmVs~w7 z#-K8#Hc0^>apOv(=WDFdBiV^E6gU9+DYffUf=0=L>pWh+~IQDVI>GmnC zS;B|v<(QY;hcQ%g`W*vqGFUOWQSTc6F7e>pwz+;b7-`F|(mmgi<$Tas62hz-!9;U)70L<1{IO#>7FZvEC z?-GlLfg8(e;oJ)yUOtyjj-nb9?`ojztUZb@w7nPR4o~_!4|t(`VI(jR^ZM`ArU(TC zX;QHLz}FENU6v8!Owoxl!PfD9M9)VY_u&dZCq@_7Lj=JOjE<0Zi&at$G+x3g3x$&; z!VRIj79>L9JVA5}-7kwL$I(QmU(h#U^e(}FYjjM{kDJwu{Hf~%{<>Z#i|OUTV0twg PpI^`8#dvxJZ2IYc(&44Q literal 0 HcmV?d00001 diff --git a/src/cfg.rs b/src/cfg.rs index e8841b6..16a09a2 100644 --- a/src/cfg.rs +++ b/src/cfg.rs @@ -10,7 +10,7 @@ use crate::gamedata::MemoryBuffer; #[derive(Debug)] pub struct ConfigMap { /// A map of setting name to value. - pub keys: HashMap, + pub keys: Vec<(String, String)>, } /// Represents a config file, which is made up of categories and settings. Categories may have zero to one settings. @@ -36,20 +36,17 @@ impl ConfigFile { let mut current_category: Option = None; for (_, line) in reader.lines().enumerate() { - // now parse the line! - let unwrap = line.unwrap(); - if !unwrap.is_empty() { + if !unwrap.is_empty() && unwrap != "\0" { if unwrap.contains('<') || unwrap.contains('>') { let name = &unwrap[1..unwrap.len() - 1]; - println!("{}", name); current_category = Some(String::from(name)); cfg.categories.push(String::from(name)); } else { let parts = unwrap.split_once('\t').unwrap(); - cfg.settings.entry(current_category.clone().unwrap()).or_insert_with(|| ConfigMap{ keys: HashMap::new() }); + cfg.settings.entry(current_category.clone().unwrap()).or_insert_with(|| ConfigMap{ keys: Vec::new() }); - cfg.settings.get_mut(¤t_category.clone().unwrap()).unwrap().keys.insert(parts.0.to_string(), parts.1.to_string()); + cfg.settings.get_mut(¤t_category.clone().unwrap()).unwrap().keys.push((parts.0.to_string(), parts.1.to_string())); } } } @@ -66,18 +63,96 @@ impl ConfigFile { let mut writer = BufWriter::new(cursor); for category in &self.categories { - writer.write_all(format!("\n<{}>", category).as_ref()).ok()?; + writer.write_all(format!("\r\n<{}>\r\n", category).as_ref()).ok()?; if self.settings.contains_key(category) { for key in &self.settings[category].keys { - writer.write_all(format!("\n{}\t{}", key.0, key.1).as_ref()).ok()?; + writer.write_all(format!("{}\t{}\r\n", key.0, key.1).as_ref()).ok()?; } } - - writer.write_all(b"\n").ok()?; } + + writer.write_all(b"\0").ok()?; } + Some(buffer) } + + pub fn has_key(&self, select_key: &str) -> bool { + for (category, keys) in &self.settings { + for (key, value) in &keys.keys { + if select_key == key { + return true; + } + } + } + + false + } + + pub fn has_category(&self, select_category: &str) -> bool { + for (category, keys) in &self.settings { + if select_category == category { + return true; + } + } + + false + } + + pub fn set_value(&mut self, select_key: &str, new_value: &str) { + for (category, keys) in &mut self.settings { + for (key, value) in &mut keys.keys { + if select_key == key { + *value = new_value.to_string(); + } + } + } + } +} + + +#[cfg(test)] +mod tests { + use std::fs::{read, write}; + use std::path::PathBuf; + + use super::*; + + fn common_setup() -> ConfigFile { + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push("resources/tests"); + d.push("FFXIV.cfg"); + + ConfigFile::from_existing(&read(d).unwrap()).unwrap() + } + + fn common_setup_modified() -> MemoryBuffer { + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push("resources/tests"); + d.push("FFXIV.modified.cfg"); + + read(d).unwrap() + } + + #[test] + fn basic_parsing() { + let cfg = common_setup(); + + assert!(cfg.has_key("TextureFilterQuality")); + assert!(cfg.has_category("Cutscene Settings")); + } + + #[test] + fn basic_writing() { + let mut cfg = common_setup(); + let modified_cfg = common_setup_modified(); + + cfg.set_value("CutsceneMovieOpening", "1"); + + let cfg_buffer = cfg.write_to_buffer().unwrap(); + + assert_eq!(modified_cfg, cfg_buffer); + } }