pbrt/src/utils/file.rs

72 lines
1.9 KiB
Rust

use shared::Float;
use std::fs;
use std::io::{self, BufReader, Error, ErrorKind, Read};
use std::path::{Path, PathBuf};
use std::sync::OnceLock;
static SEARCH_DIRECTORY: OnceLock<PathBuf> = OnceLock::new();
fn set_search_directory(filename: &str) {
let path = Path::new(filename);
let dir = if path.is_dir() {
path.to_path_buf()
} else {
path.parent().unwrap_or(Path::new("")).to_path_buf()
};
let _ = SEARCH_DIRECTORY.set(dir);
}
pub fn resolve_filename(filename: &str) -> String {
let search_directory = SEARCH_DIRECTORY
.get()
.map(|p| p.as_path())
.unwrap_or(Path::new(""));
if search_directory.as_os_str().is_empty()
|| filename.is_empty()
|| Path::new(filename).is_absolute()
{
return filename.to_string();
}
let filepath = search_directory.join(filename);
if filepath.exists() {
filepath
.canonicalize()
.unwrap_or_else(|_| filepath.to_path_buf())
.to_string_lossy()
.to_string()
} else {
filename.to_string()
}
}
pub fn read_float_file(filename: &str) -> io::Result<Vec<Float>> {
let content = fs::read_to_string(filename)?;
let mut values = Vec::new();
for (line_num, line) in content.lines().enumerate() {
// Strip comments
let cleaned = line.split('#').next().unwrap_or("");
for token in cleaned.split_whitespace() {
match token.parse::<Float>() {
Ok(val) => values.push(val),
Err(e) => {
return Err(Error::new(
ErrorKind::InvalidData,
format!(
"Failed to parse float '{}' at line {}: {}",
token,
line_num + 1,
e
),
));
}
}
}
}
Ok(values)
}