mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-28 21:04:47 +00:00
Fix number to string conversion in C++
This commit is contained in:
parent
486b2ab8f8
commit
5580b5112f
5 changed files with 90 additions and 59 deletions
|
@ -31,7 +31,11 @@ struct SharedString
|
||||||
operator std::string_view() const { return internal::sixtyfps_shared_string_bytes(this); }
|
operator std::string_view() const { return internal::sixtyfps_shared_string_bytes(this); }
|
||||||
auto data() const -> const char * { return internal::sixtyfps_shared_string_bytes(this); }
|
auto data() const -> const char * { return internal::sixtyfps_shared_string_bytes(this); }
|
||||||
|
|
||||||
|
static SharedString from_number(double n) { return SharedString(n); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// Use SharedString::from_number
|
||||||
|
explicit SharedString(double n) { internal::sixtyfps_shared_string_from_number(this, n); }
|
||||||
void *inner; // opaque
|
void *inner; // opaque
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ Hello := Rectangle {
|
||||||
button_text: "+";
|
button_text: "+";
|
||||||
}
|
}
|
||||||
property<int32> counter;
|
property<int32> counter;
|
||||||
counter_label := Text { x: 100; y: 300; text: "0"; color: black; }
|
counter_label := Text { x: 100; y: 300; text: counter; color: black; }
|
||||||
ButtonRectangle {
|
ButtonRectangle {
|
||||||
color: 4289374890;
|
color: 4289374890;
|
||||||
x: 50;
|
x: 50;
|
||||||
|
|
|
@ -11,17 +11,11 @@ int main() {
|
||||||
component.plus_clicked.set_handler([](auto...){
|
component.plus_clicked.set_handler([](auto...){
|
||||||
auto &counter = component.counter;
|
auto &counter = component.counter;
|
||||||
counter.set(counter.get() + 1);
|
counter.set(counter.get() + 1);
|
||||||
// FIXME: this _13 is an internal detail and should be private anyway. We muse use some
|
|
||||||
// alias or way to expose the property (same for the _ before signals)
|
|
||||||
component.counter_label_11.text.set(std::string_view(std::to_string(counter.get())));
|
|
||||||
std::cout << "PLUS: " << std::string_view(component.counter_label_11.text.get()) << std::endl;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
component.minus_clicked.set_handler([](auto...){
|
component.minus_clicked.set_handler([](auto...){
|
||||||
auto &counter = component.counter;
|
auto &counter = component.counter;
|
||||||
counter.set(counter.get() - 1);
|
counter.set(counter.get() - 1);
|
||||||
component.counter_label_11.text.set(std::string_view(std::to_string(counter.get())));
|
|
||||||
std::cout << "MINUS: " << std::string_view(component.counter_label_11.text.get()) << std::endl;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
sixtyfps::run(&component);
|
sixtyfps::run(&component);
|
||||||
|
|
|
@ -162,7 +162,7 @@ fn handle_item(
|
||||||
|
|
||||||
let id = &item.id;
|
let id = &item.id;
|
||||||
init.extend(item.bindings.iter().map(|(s, i)| {
|
init.extend(item.bindings.iter().map(|(s, i)| {
|
||||||
use crate::expression_tree::{Expression, Expression::*};
|
use crate::expression_tree::Expression;
|
||||||
match i {
|
match i {
|
||||||
Expression::SignalReference { component:_, element:_, name } => {
|
Expression::SignalReference { component:_, element:_, name } => {
|
||||||
let signal_accessor_prefix = if item.signals_declaration.contains(s) {
|
let signal_accessor_prefix = if item.signals_declaration.contains(s) {
|
||||||
|
@ -183,14 +183,7 @@ fn handle_item(
|
||||||
format!("{id}.", id = id.clone())
|
format!("{id}.", id = id.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
let init = match &i {
|
let init = compile_expression(i);
|
||||||
StringLiteral(s) => {
|
|
||||||
format!(r#"sixtyfps::SharedString("{}")"#, s.escape_default())
|
|
||||||
}
|
|
||||||
NumberLiteral(n) => n.to_string(),
|
|
||||||
PropertyReference { name, .. } => format!(r#"{}.get()"#, name),
|
|
||||||
_ => format!("\n#error: unsupported expression {:?}\n", i),
|
|
||||||
};
|
|
||||||
format!(
|
format!(
|
||||||
"{accessor_prefix}{cpp_prop}.set({init});",
|
"{accessor_prefix}{cpp_prop}.set({init});",
|
||||||
accessor_prefix = accessor_prefix,
|
accessor_prefix = accessor_prefix,
|
||||||
|
@ -298,18 +291,28 @@ pub fn generate(component: &Component, diag: &mut Diagnostics) -> Option<impl st
|
||||||
init: Some("{ nullptr, sixtyfps::dummy_destory, tree_fn }".to_owned()),
|
init: Some("{ nullptr, sixtyfps::dummy_destory, tree_fn }".to_owned()),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
/*x.declarations.push(Declaration::Function(Function {
|
|
||||||
name: "main".into(),
|
|
||||||
signature: "() -> int".to_owned(),
|
|
||||||
statements: Some(vec![
|
|
||||||
format!("static {} component;", component.id),
|
|
||||||
format!("sixtyfps::run(&component);"),
|
|
||||||
]),
|
|
||||||
..Default::default()
|
|
||||||
}));*/
|
|
||||||
if diag.has_error() {
|
if diag.has_error() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(x)
|
Some(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compile_expression(e: &crate::expression_tree::Expression) -> String {
|
||||||
|
use crate::expression_tree::Expression::*;
|
||||||
|
match e {
|
||||||
|
StringLiteral(s) => format!(r#"sixtyfps::SharedString("{}")"#, s.escape_default()),
|
||||||
|
NumberLiteral(n) => n.to_string(),
|
||||||
|
PropertyReference { name, .. } => format!(r#"{}.get()"#, name),
|
||||||
|
Cast { from, to } => {
|
||||||
|
let f = compile_expression(&*from);
|
||||||
|
match (from.ty(), to) {
|
||||||
|
(Type::Float32, Type::String) | (Type::Int32, Type::String) => {
|
||||||
|
format!("sixtyfps::SharedString::from_number({})", f)
|
||||||
|
}
|
||||||
|
_ => f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => format!("\n#error: unsupported expression {:?}\n", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -228,40 +228,6 @@ where
|
||||||
|
|
||||||
impl Eq for SharedString {}
|
impl Eq for SharedString {}
|
||||||
|
|
||||||
/// for cbingen.
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
type c_char = u8;
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn sixtyfps_shared_string_bytes(ss: &SharedString) -> *const c_char {
|
|
||||||
ss.as_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
/// Destroy the shared string
|
|
||||||
pub unsafe extern "C" fn sixtyfps_shared_string_drop(ss: *const SharedString) {
|
|
||||||
core::ptr::read(ss);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
/// Increment the reference count of the string.
|
|
||||||
/// the resulting structure must be passed to sixtyfps_shared_string_drop
|
|
||||||
pub unsafe extern "C" fn sixtyfps_shared_string_clone(out: *mut SharedString, ss: &SharedString) {
|
|
||||||
core::ptr::write(out, ss.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
/// Safety: bytes must be a valid utf-8 string of size len wihout null inside.
|
|
||||||
/// the resulting structure must be passed to sixtyfps_shared_string_drop
|
|
||||||
pub unsafe extern "C" fn sixtyfps_shared_string_from_bytes(
|
|
||||||
out: *mut SharedString,
|
|
||||||
bytes: *const c_char,
|
|
||||||
len: usize,
|
|
||||||
) {
|
|
||||||
let str = core::str::from_utf8_unchecked(core::slice::from_raw_parts(bytes, len));
|
|
||||||
core::ptr::write(out, SharedString::from(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn simple_test() {
|
fn simple_test() {
|
||||||
let x = SharedString::from("hello world!");
|
let x = SharedString::from("hello world!");
|
||||||
|
@ -279,3 +245,67 @@ fn simple_test() {
|
||||||
&*std::ffi::CString::new("hello world!").unwrap()
|
&*std::ffi::CString::new("hello world!").unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// for cbingen.
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
type c_char = u8;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn sixtyfps_shared_string_bytes(ss: &SharedString) -> *const c_char {
|
||||||
|
ss.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
/// Destroy the shared string
|
||||||
|
pub unsafe extern "C" fn sixtyfps_shared_string_drop(ss: *const SharedString) {
|
||||||
|
core::ptr::read(ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
/// Increment the reference count of the string.
|
||||||
|
/// The resulting structure must be passed to sixtyfps_shared_string_drop
|
||||||
|
pub unsafe extern "C" fn sixtyfps_shared_string_clone(out: *mut SharedString, ss: &SharedString) {
|
||||||
|
core::ptr::write(out, ss.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
/// Safety: bytes must be a valid utf-8 string of size len wihout null inside.
|
||||||
|
/// The resulting structure must be passed to sixtyfps_shared_string_drop
|
||||||
|
pub unsafe extern "C" fn sixtyfps_shared_string_from_bytes(
|
||||||
|
out: *mut SharedString,
|
||||||
|
bytes: *const c_char,
|
||||||
|
len: usize,
|
||||||
|
) {
|
||||||
|
let str = core::str::from_utf8_unchecked(core::slice::from_raw_parts(bytes, len));
|
||||||
|
core::ptr::write(out, SharedString::from(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a string from a number.
|
||||||
|
/// The resulting structure must be passed to sixtyfps_shared_string_drop
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn sixtyfps_shared_string_from_number(out: *mut SharedString, n: f64) {
|
||||||
|
// TODO: implement Write for SharedString so this can be done without alocation
|
||||||
|
let str = format!("{}", n);
|
||||||
|
core::ptr::write(out, SharedString::from(str.as_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sixtyfps_shared_string_from_number() {
|
||||||
|
unsafe {
|
||||||
|
let mut s = core::mem::MaybeUninit::uninit();
|
||||||
|
sixtyfps_shared_string_from_number(s.as_mut_ptr(), 45.);
|
||||||
|
assert_eq!(s.assume_init(), "45");
|
||||||
|
|
||||||
|
let mut s = core::mem::MaybeUninit::uninit();
|
||||||
|
sixtyfps_shared_string_from_number(s.as_mut_ptr(), 45.12);
|
||||||
|
assert_eq!(s.assume_init(), "45.12");
|
||||||
|
|
||||||
|
let mut s = core::mem::MaybeUninit::uninit();
|
||||||
|
sixtyfps_shared_string_from_number(s.as_mut_ptr(), -1325466.);
|
||||||
|
assert_eq!(s.assume_init(), "-1325466");
|
||||||
|
|
||||||
|
let mut s = core::mem::MaybeUninit::uninit();
|
||||||
|
sixtyfps_shared_string_from_number(s.as_mut_ptr(), -0.);
|
||||||
|
assert_eq!(s.assume_init(), "0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue