seq_runtime/string_ops/
conversion.rs1use crate::error::set_runtime_error;
4use crate::seqstring::global_string;
5use crate::stack::{Stack, pop, push};
6use crate::value::Value;
7
8#[unsafe(no_mangle)]
11pub unsafe extern "C" fn patch_seq_symbol_equal(stack: Stack) -> Stack {
12 assert!(!stack.is_null(), "symbol_equal: stack is empty");
13
14 let (stack, sym2_val) = unsafe { pop(stack) };
15 assert!(!stack.is_null(), "symbol_equal: need two symbols");
16 let (stack, sym1_val) = unsafe { pop(stack) };
17
18 match (sym1_val, sym2_val) {
19 (Value::Symbol(s1), Value::Symbol(s2)) => {
20 let equal = if s1.is_interned() && s2.is_interned() {
22 s1.as_ptr() == s2.as_ptr()
23 } else {
24 s1.as_str() == s2.as_str()
26 };
27 unsafe { push(stack, Value::Bool(equal)) }
28 }
29 _ => panic!("symbol_equal: expected two symbols on stack"),
30 }
31}
32
33#[unsafe(no_mangle)]
50pub unsafe extern "C" fn patch_seq_json_escape(stack: Stack) -> Stack {
51 assert!(!stack.is_null(), "json_escape: stack is empty");
52
53 let (stack, value) = unsafe { pop(stack) };
54
55 match value {
56 Value::String(s) => {
57 let input = s.as_str();
58 let mut result = String::with_capacity(input.len() + 16);
59
60 for ch in input.chars() {
61 match ch {
62 '"' => result.push_str("\\\""),
63 '\\' => result.push_str("\\\\"),
64 '\n' => result.push_str("\\n"),
65 '\r' => result.push_str("\\r"),
66 '\t' => result.push_str("\\t"),
67 '\x08' => result.push_str("\\b"), '\x0C' => result.push_str("\\f"), c if c.is_control() => {
72 result.push_str(&format!("\\u{:04X}", c as u32));
73 }
74 c => result.push(c),
75 }
76 }
77
78 unsafe { push(stack, Value::String(global_string(result))) }
79 }
80 _ => panic!("json_escape: expected String on stack"),
81 }
82}
83
84#[unsafe(no_mangle)]
97pub unsafe extern "C" fn patch_seq_string_to_int(stack: Stack) -> Stack {
98 if stack.is_null() {
99 set_runtime_error("string->int: stack is empty");
100 return stack;
101 }
102 let (stack, val) = unsafe { pop(stack) };
103
104 match val {
105 Value::String(s) => match s.as_str().trim().parse::<i64>() {
106 Ok(i) => {
107 let stack = unsafe { push(stack, Value::Int(i)) };
108 unsafe { push(stack, Value::Bool(true)) }
109 }
110 Err(_) => {
111 let stack = unsafe { push(stack, Value::Int(0)) };
112 unsafe { push(stack, Value::Bool(false)) }
113 }
114 },
115 _ => {
116 set_runtime_error("string->int: expected String on stack");
117 let stack = unsafe { push(stack, Value::Int(0)) };
118 unsafe { push(stack, Value::Bool(false)) }
119 }
120 }
121}