rustr/
util.rs

1//! Utilities
2//!
3//!
4use ::rdll::*;
5use ::std::ffi::*;
6
7use ::protect::stackp::*;
8use traits::ToSEXP;
9
10pub unsafe extern "C" fn check_interrupt_fn(_ptr: *mut ::std::os::raw::c_void /* dummy */) {
11    R_CheckUserInterrupt();
12}
13
14/// For CString
15/// 
16#[macro_export]
17macro_rules! cstring {
18 	($x:expr) => (
19 	::std::ffi::CString::new($x).unwrap().as_ptr()
20 		)
21 }
22
23pub unsafe fn cstr_sym(x: &str) -> SEXP {
24    Rf_install(c_str(x).as_ptr())
25}
26
27#[inline]
28pub fn cstring_user<T: Into<Vec<u8>>>(string: T) -> Result<CString, NulError> {
29
30    ::std::ffi::CString::new(string)
31
32}
33
34pub fn check_user_interrupt() -> bool {
35    unsafe { R_ToplevelExec(Some(check_interrupt_fn), ::std::ptr::null_mut()) != Rboolean::TRUE }
36}
37
38#[inline]
39pub fn c_str(x: &str) -> CString {
40    match CString::new(x) {
41        Ok(some) => some,
42        Err(err) => {
43            unsafe {
44                Rf_warning(cstring!(format!("{:?} from string '{:?}': safe string \
45                                             transformation failed, use unknown",
46                                            err,
47                                            x)));
48            }
49            CString::new("unknown").unwrap()
50        }
51    }
52}
53
54
55#[inline]
56pub fn c_str2(x: &str, unknown: &str) -> CString {
57    CString::new(x).unwrap_or({
58        unsafe {
59            Rf_warning(cstring!("safe string transformation failed, use unknown"));
60        }
61        CString::new(unknown).unwrap()
62    })
63}
64
65#[inline]
66pub fn derives_from(cl: SEXP, clazz: CString) -> bool {
67    unsafe {
68        if cl == R_NilValue {
69            return false;
70        }
71        let sstring = clazz;
72        // simple test for exact match
73        if sstring == CStr::from_ptr(R_CHAR(STRING_ELT(cl, 0))).to_owned() {
74            return true;
75        }
76        let contains_sym = cstr_sym("contains");
77        let contains = Shield::new(R_do_slot(R_getClassDef(R_CHAR(Rf_asChar(cl))), contains_sym));
78        let res = Rf_getAttrib(contains.s(), R_NamesSymbol);
79        if res == R_NilValue {
80            return false;
81        }
82        for ii in 0..Rf_xlength(res) + 1 {
83
84            if CStr::from_ptr(R_CHAR(*VECTOR_PTR(res).offset(ii as isize))).to_owned() == sstring {
85                return true;
86            }
87        }
88    }
89    false
90}
91
92pub fn rprint<T: ToSEXP>(s: T) {
93    unsafe {
94        Rf_PrintValue(s.s());
95    }
96
97}