Skip to main content

seq_runtime/string_ops/
case.rs

1//! Case conversion and whitespace trimming.
2
3use crate::seqstring::global_string;
4use crate::stack::{Stack, pop, push};
5use crate::value::Value;
6
7/// # Safety
8/// Stack must have the expected values on top for this operation.
9#[unsafe(no_mangle)]
10pub unsafe extern "C" fn patch_seq_string_trim(stack: Stack) -> Stack {
11    assert!(!stack.is_null(), "string_trim: stack is empty");
12
13    let (stack, str_val) = unsafe { pop(stack) };
14
15    match str_val {
16        Value::String(s) => {
17            let trimmed = s.as_str().trim();
18            unsafe { push(stack, Value::String(global_string(trimmed.to_owned()))) }
19        }
20        _ => panic!("string_trim: expected String on stack"),
21    }
22}
23
24/// Convert a string to uppercase
25///
26/// Stack effect: ( str -- upper )
27///
28/// # Safety
29/// Stack must have a String value on top
30#[unsafe(no_mangle)]
31pub unsafe extern "C" fn patch_seq_string_to_upper(stack: Stack) -> Stack {
32    assert!(!stack.is_null(), "string_to_upper: stack is empty");
33
34    let (stack, str_val) = unsafe { pop(stack) };
35
36    match str_val {
37        Value::String(s) => {
38            let upper = s.as_str().to_uppercase();
39            unsafe { push(stack, Value::String(global_string(upper))) }
40        }
41        _ => panic!("string_to_upper: expected String on stack"),
42    }
43}
44
45/// Convert a string to lowercase
46///
47/// Stack effect: ( str -- lower )
48///
49/// # Safety
50/// Stack must have a String value on top
51#[unsafe(no_mangle)]
52pub unsafe extern "C" fn patch_seq_string_to_lower(stack: Stack) -> Stack {
53    assert!(!stack.is_null(), "string_to_lower: stack is empty");
54
55    let (stack, str_val) = unsafe { pop(stack) };
56
57    match str_val {
58        Value::String(s) => {
59            let lower = s.as_str().to_lowercase();
60            unsafe { push(stack, Value::String(global_string(lower))) }
61        }
62        _ => panic!("string_to_lower: expected String on stack"),
63    }
64}
65
66/// Check if two strings are equal
67///
68/// Stack effect: ( str1 str2 -- bool )
69///
70/// # Safety
71/// Stack must have two String values on top
72#[unsafe(no_mangle)]
73pub unsafe extern "C" fn patch_seq_string_chomp(stack: Stack) -> Stack {
74    assert!(!stack.is_null(), "string_chomp: stack is empty");
75
76    let (stack, str_val) = unsafe { pop(stack) };
77
78    match str_val {
79        Value::String(s) => {
80            let mut result = s.as_str().to_owned();
81            if result.ends_with('\n') {
82                result.pop();
83                if result.ends_with('\r') {
84                    result.pop();
85                }
86            }
87            unsafe { push(stack, Value::String(global_string(result))) }
88        }
89        _ => panic!("string_chomp: expected String on stack"),
90    }
91}