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_bytes() == s2.as_bytes()
31 };
32 unsafe { push(stack, Value::Bool(equal)) }
33 }
34 _ => panic!("symbol_equal: expected two symbols on stack"),
35 }
36}
37
38#[unsafe(no_mangle)]
55pub unsafe extern "C" fn patch_seq_json_escape(stack: Stack) -> Stack {
56 assert!(!stack.is_null(), "json_escape: stack is empty");
57
58 let (stack, value) = unsafe { pop(stack) };
59
60 match value {
61 Value::String(s) => {
62 let input = s.as_str_or_empty();
63 let mut result = String::with_capacity(input.len() + 16);
64
65 for ch in input.chars() {
66 match ch {
67 '"' => result.push_str("\\\""),
68 '\\' => result.push_str("\\\\"),
69 '\n' => result.push_str("\\n"),
70 '\r' => result.push_str("\\r"),
71 '\t' => result.push_str("\\t"),
72 '\x08' => result.push_str("\\b"), '\x0C' => result.push_str("\\f"), c if c.is_control() => {
77 result.push_str(&format!("\\u{:04X}", c as u32));
78 }
79 c => result.push(c),
80 }
81 }
82
83 unsafe { push(stack, Value::String(global_string(result))) }
84 }
85 _ => panic!("json_escape: expected String on stack"),
86 }
87}
88
89#[unsafe(no_mangle)]
102pub unsafe extern "C" fn patch_seq_string_to_int(stack: Stack) -> Stack {
103 if stack.is_null() {
104 set_runtime_error("string->int: stack is empty");
105 return stack;
106 }
107 let (stack, val) = unsafe { pop(stack) };
108
109 match val {
110 Value::String(s) => match s.as_str_or_empty().trim().parse::<i64>() {
111 Ok(i) => {
112 let stack = unsafe { push(stack, Value::Int(i)) };
113 unsafe { push(stack, Value::Bool(true)) }
114 }
115 Err(_) => {
116 let stack = unsafe { push(stack, Value::Int(0)) };
117 unsafe { push(stack, Value::Bool(false)) }
118 }
119 },
120 _ => {
121 set_runtime_error("string->int: expected String on stack");
122 let stack = unsafe { push(stack, Value::Int(0)) };
123 unsafe { push(stack, Value::Bool(false)) }
124 }
125 }
126}