mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Use Rust Filename comparisons for C++ Filename operators
To prevent inconsistencies between implementations. This means allocating new boxed Filenames for each comparison, but an extra string copy is avoided by making the C++ operators friends of the C++ class (which is ABI-safe).
This commit is contained in:
@@ -9,7 +9,6 @@ cxx = { version = "1.0", features = ["c++17"] }
|
||||
delegate = "0.13.2"
|
||||
libloot = { path = ".." }
|
||||
libloot-ffi-errors = { path = "../ffi-errors" }
|
||||
unicase = "2.8.1"
|
||||
|
||||
[build-dependencies]
|
||||
cxx-build = "1.0"
|
||||
|
||||
@@ -54,6 +54,10 @@ public:
|
||||
|
||||
private:
|
||||
std::string filename_;
|
||||
|
||||
LOOT_API friend bool operator==(const Filename& lhs, const Filename& rhs);
|
||||
|
||||
LOOT_API friend bool operator<(const Filename& lhs, const Filename& rhs);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,7 +35,8 @@ Filename::Filename(std::string_view filename) : filename_(filename) {}
|
||||
Filename::operator std::string() const { return filename_; }
|
||||
|
||||
bool operator==(const Filename& lhs, const Filename& rhs) {
|
||||
return loot::rust::compare_filenames(std::string(lhs), std::string(rhs)) == 0;
|
||||
return loot::rust::new_filename(lhs.filename_)
|
||||
->eq(*loot::rust::new_filename(rhs.filename_));
|
||||
}
|
||||
|
||||
bool operator!=(const Filename& lhs, const Filename& rhs) {
|
||||
@@ -43,7 +44,8 @@ bool operator!=(const Filename& lhs, const Filename& rhs) {
|
||||
}
|
||||
|
||||
bool operator<(const Filename& lhs, const Filename& rhs) {
|
||||
return loot::rust::compare_filenames(std::string(lhs), std::string(rhs)) < 0;
|
||||
return loot::rust::new_filename(lhs.filename_)
|
||||
->lt(*loot::rust::new_filename(rhs.filename_));
|
||||
}
|
||||
|
||||
bool operator>(const Filename& lhs, const Filename& rhs) { return rhs < lhs; }
|
||||
|
||||
+12
-11
@@ -119,7 +119,6 @@ use std::{
|
||||
ffi::{CString, c_char, c_uchar, c_uint, c_void},
|
||||
sync::{Mutex, atomic::AtomicPtr},
|
||||
};
|
||||
use unicase::UniCase;
|
||||
|
||||
use libloot::set_logging_callback;
|
||||
pub use libloot::{is_compatible, libloot_revision, libloot_version};
|
||||
@@ -181,14 +180,6 @@ pub type OptionalPluginMetadata = Optional<PluginMetadata>;
|
||||
|
||||
pub type OptionalCrc = Optional<u32>;
|
||||
|
||||
fn compare_filenames(lhs: &str, rhs: &str) -> i8 {
|
||||
match UniCase::new(lhs).cmp(&UniCase::new(rhs)) {
|
||||
std::cmp::Ordering::Less => -1,
|
||||
std::cmp::Ordering::Equal => 0,
|
||||
std::cmp::Ordering::Greater => 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_log_level(level: ffi::LogLevel) -> Result<(), VerboseError> {
|
||||
libloot::set_log_level(level.try_into()?);
|
||||
Ok(())
|
||||
@@ -295,8 +286,6 @@ mod ffi {
|
||||
contents: &[MessageContent],
|
||||
language: &str,
|
||||
) -> OptionalMessageContentRef;
|
||||
|
||||
fn compare_filenames(lhs: &str, rhs: &str) -> i8;
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
@@ -633,6 +622,18 @@ mod ffi {
|
||||
pub fn as_str(&self) -> &str;
|
||||
|
||||
pub fn boxed_clone(&self) -> Box<Filename>;
|
||||
|
||||
pub fn eq(&self, other: &Filename) -> bool;
|
||||
|
||||
pub fn ne(&self, other: &Filename) -> bool;
|
||||
|
||||
pub fn lt(&self, other: &Filename) -> bool;
|
||||
|
||||
pub fn le(&self, other: &Filename) -> bool;
|
||||
|
||||
pub fn gt(&self, other: &Filename) -> bool;
|
||||
|
||||
pub fn ge(&self, other: &Filename) -> bool;
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
|
||||
+1
-1
@@ -446,7 +446,7 @@ impl From<Box<File>> for libloot::metadata::File {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
||||
#[repr(transparent)]
|
||||
pub struct Filename(libloot::metadata::Filename);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user