Slide 95
Slide 95 text
RUST C
// Rust Code
extern crate libc;
use std::{ptr, slice};
use std::marker::PhantomData;
#[repr(C)]
#[allow(raw_pointer_derive)]
#[derive(Copy, Clone)]
pub struct Buf<'a> {
ptr: *mut u8,
len: usize,
marker: PhantomData<&'a ()>,
}
impl<'a> Buf<'a> {
pub fn as_slice(self) -> &'a str {
unsafe {
let s = slice::from_raw_parts(self.ptr as *const u8, self.len);
std::str::from_utf8_unchecked(s)
}
}
}
#[no_mangle]
pub extern "C" fn fast_blank(buf: Buf) -> bool {
buf.as_slice().unwrap().chars().all(|c| c.is_whitespace())
}
// C Code
#include
#include
typedef struct {
void* data;
size_t len;
} fast_blank_buf_t;
static inline fast_blank_buf_t
STR2BUF(VALUE str) {
return (fast_blank_buf_t) {
.data = RSTRING_PTR(str),
.len = RSTRING_LEN(str),
};
}
int fast_blank(fast_blank_buf_t);
static VALUE
rb_string_blank_p(VALUE str) {
return fast_blank(STR2BUF(str)) ? Qtrue : Qfalse;
}
void Init_fast_blank()
{
rb_define_method(rb_cString, "blank?", rb_string_blank_p, 0);
}
#include
#include
#include
#include
#define STR_ENC_GET(str) rb_enc_from_index(ENCODING_GET(str))
static VALUE
rb_string_blank(VALUE str)
{
rb_encoding *enc;
char *s, *e;
enc = STR_ENC_GET(str);
s = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return Qtrue;
e = RSTRING_END(str);
while (s < e) {
int n;
unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
switch (cc) {
case 9:
case 0xa:
case 0xb:
case 0xc:
case 0xd:
case 0x20:
case 0x85:
case 0xa0:
case 0x1680:
case 0x2000:
case 0x2001:
case 0x2002:
case 0x2003:
case 0x2004:
case 0x2005:
case 0x2006:
case 0x2007:
case 0x2008:
case 0x2009:
case 0x200a:
case 0x2028:
case 0x2029:
case 0x202f:
case 0x205f:
case 0x3000:
break;
default:
return Qfalse;
}
s += n;
}
return Qtrue;
}
void Init_fast_blank()
{
rb_define_method(rb_cString, "blank?", rb_string_blank, 0);
}