Also do the comperty comparison in C++

This commit is contained in:
Olivier Goffart 2020-10-31 14:36:38 +01:00
parent 2ece3817cc
commit 1eb7203ec8
6 changed files with 82 additions and 4 deletions

View file

@ -37,6 +37,23 @@ public:
{ {
} }
friend bool operator==(const PathData &a, const PathData &b) {
if (a.data.tag != b.data.tag)
return false;
switch (a.data.tag) {
case cbindgen_private::types::PathData::Tag::Elements:
return a.data.elements._0 == b.data.elements._0;
case cbindgen_private::types::PathData::Tag::Events:
return a.data.events._0 == b.data.events._0 && b.data.events._0 == b.data.events._0;
case cbindgen_private::types::PathData::Tag::None:
return true;
}
}
friend bool operator!=(const PathData &a, const PathData &b) {
return !(a == b);
}
private: private:
static SharedArray<PathElement> elements_from_array(const PathElement *firstElement, static SharedArray<PathElement> elements_from_array(const PathElement *firstElement,
size_t count) size_t count)

View file

@ -41,8 +41,10 @@ struct Property
void set(const T &value) const void set(const T &value) const
{ {
this->value = value; if (this->value != value) {
cbindgen_private::sixtyfps_property_set_changed(&inner, &this->value); this->value = value;
cbindgen_private::sixtyfps_property_set_changed(&inner, &this->value);
}
} }
const T &get() const const T &get() const

View file

@ -17,12 +17,19 @@ namespace sixtyfps {
struct Resource struct Resource
{ {
public: public:
using Tag = cbindgen_private::types::Resource::Tag;
Resource() : data(Data::None()) { } Resource() : data(Data::None()) { }
Resource(const SharedString &file_path) : data(Data::AbsoluteFilePath(file_path)) { } Resource(const SharedString &file_path) : data(Data::AbsoluteFilePath(file_path)) { }
friend bool operator==(const Resource &a, const Resource &b) {
return a.data == b.data;
}
friend bool operator!=(const Resource &a, const Resource &b) {
return a.data != b.data;
}
private: private:
using Tag = cbindgen_private::types::Resource::Tag;
using Data = cbindgen_private::types::Resource; using Data = cbindgen_private::types::Resource;
Data data; Data data;
}; };

View file

@ -10,6 +10,7 @@ LICENSE END */
#pragma once #pragma once
#include "sixtyfps_sharedarray_internal.h" #include "sixtyfps_sharedarray_internal.h"
#include <atomic> #include <atomic>
#include <algorithm>
namespace sixtyfps { namespace sixtyfps {
@ -95,6 +96,16 @@ struct SharedArray
inner->size++; inner->size++;
} }
friend bool operator==(const SharedArray &a, const SharedArray &b) {
if (a.size() != a.size())
return false;
return std::equal(a.cbegin(), a.cend(), b.cbegin());
}
friend bool operator!=(const SharedArray &a, const SharedArray &b) {
return !(a == b);
}
private: private:
void detach(std::size_t expected_capacity) { void detach(std::size_t expected_capacity) {
if (inner->refcount == 1 && expected_capacity <= inner->capacity) { if (inner->refcount == 1 && expected_capacity <= inner->capacity) {
@ -142,4 +153,15 @@ private:
explicit SharedArray(SharedArrayHeader *inner) : inner(inner) {} explicit SharedArray(SharedArrayHeader *inner) : inner(inner) {}
#endif #endif
}; };
template<typename T>
bool operator==(cbindgen_private::Slice<T> a, cbindgen_private::Slice<T> b) {
if (a.len != b.len) return false;
return std::equal(a.ptr, a.ptr + a.len, b.ptr);
}
template<typename T>
bool operator!=(cbindgen_private::Slice<T> a, cbindgen_private::Slice<T> b) {
return !(a != b);
}
} }

View file

@ -108,6 +108,7 @@ mod cpp_ast {
signature: f.signature.clone(), signature: f.signature.clone(),
is_constructor_or_destructor: f.is_constructor_or_destructor, is_constructor_or_destructor: f.is_constructor_or_destructor,
is_static: false, is_static: false,
is_friend: false,
statements: f.statements.take(), statements: f.statements.take(),
template_parameters: f.template_parameters.clone(), template_parameters: f.template_parameters.clone(),
})) }))
@ -126,6 +127,7 @@ mod cpp_ast {
/// The function does not have return type /// The function does not have return type
pub is_constructor_or_destructor: bool, pub is_constructor_or_destructor: bool,
pub is_static: bool, pub is_static: bool,
pub is_friend: bool,
/// The list of statement instead the function. When None, this is just a function /// The list of statement instead the function. When None, this is just a function
/// declaration without the definition /// declaration without the definition
pub statements: Option<Vec<String>>, pub statements: Option<Vec<String>>,
@ -142,6 +144,9 @@ mod cpp_ast {
if self.is_static { if self.is_static {
write!(f, "static ")?; write!(f, "static ")?;
} }
if self.is_friend {
write!(f, "friend ")?;
}
// all functions are inlines because we are in a header // all functions are inlines because we are in a header
write!(f, "inline ")?; write!(f, "inline ")?;
if !self.is_constructor_or_destructor { if !self.is_constructor_or_destructor {
@ -540,9 +545,12 @@ fn generate_struct(
fields: &BTreeMap<String, Type>, fields: &BTreeMap<String, Type>,
diag: &mut BuildDiagnostics, diag: &mut BuildDiagnostics,
) { ) {
let mut operator_eq = String::new();
let mut members = fields let mut members = fields
.iter() .iter()
.map(|(name, t)| { .map(|(name, t)| {
use std::fmt::Write;
write!(operator_eq, " && a.{0} == b.{0}", name).unwrap();
( (
Access::Public, Access::Public,
Declaration::Var(Var { Declaration::Var(Var {
@ -563,6 +571,26 @@ fn generate_struct(
(Declaration::Var(a), Declaration::Var(b)) => a.name.cmp(&b.name), (Declaration::Var(a), Declaration::Var(b)) => a.name.cmp(&b.name),
_ => unreachable!(), _ => unreachable!(),
}); });
members.push((
Access::Public,
Declaration::Function(Function {
name: "operator==".to_owned(),
signature: format!("(const {0} &a, const {0} &b) -> bool", name),
is_friend: true,
statements: Some(vec![format!("return true{};", operator_eq)]),
..Function::default()
}),
));
members.push((
Access::Public,
Declaration::Function(Function {
name: "operator!=".to_owned(),
signature: format!("(const {0} &a, const {0} &b) -> bool", name),
is_friend: true,
statements: Some(vec!["return !(a == b);".into()]),
..Function::default()
}),
));
file.declarations.push(Declaration::Struct(Struct { file.declarations.push(Declaration::Struct(Struct {
name: name.into(), name: name.into(),
members, members,

View file

@ -160,6 +160,8 @@ fn gen_corelib(include_dir: &Path) -> anyhow::Result<()> {
private_default_tagged_enum_constructor: true, private_default_tagged_enum_constructor: true,
..Default::default() ..Default::default()
}; };
special_config.structure.derive_eq = true;
special_config.structure.derive_neq = true;
// Put the rust type in a deeper "types" namespace, so the use of same type in for example generated // Put the rust type in a deeper "types" namespace, so the use of same type in for example generated
// Property<> fields uses the public `sixtyfps::Blah` type // Property<> fields uses the public `sixtyfps::Blah` type
special_config.namespaces = special_config.namespaces =