os/util/
str.rs

1use core::ptr::{read_volatile, write_volatile};
2
3use alloc::{
4    string::{String, ToString},
5    vec::Vec,
6};
7
8use crate::config::MAX_ARGV;
9
10/// 向指定地址写入内容
11/// # 参数:
12/// * `addr` - 目标地址
13/// * `content` - 要写入的内容
14#[inline(always)]
15pub fn write<T>(addr: usize, content: T) {
16    let cell = (addr) as *mut T;
17    unsafe {
18        write_volatile(cell, content);
19    }
20}
21
22/// 从指定地址读取内容
23/// # 参数:
24/// * `addr` - 目标地址
25/// # 返回值:
26/// 读取到的内容
27#[inline(always)]
28pub fn read<T>(addr: usize) -> T {
29    let cell = (addr) as *const T;
30    unsafe { read_volatile(cell) }
31}
32
33/// 从以 NULL 结尾的 C 字符串指针拷贝并返回一个 owned String
34/// WARNING: 这个函数直接读取指针,调用者必须保证指针在内核可读
35pub unsafe fn copy_cstr_to_string(ptr: *const u8) -> Result<String, ()> {
36    const MAX_PATH_LEN: usize = 4096;
37    let mut buf: Vec<u8> = Vec::new();
38    let mut p = ptr;
39    for _ in 0..MAX_PATH_LEN {
40        // 直接读取内存字节(不安全)
41        let b = unsafe { core::ptr::read(p) };
42        if b == 0 {
43            return core::str::from_utf8(&buf)
44                .map(|s| s.to_string())
45                .map_err(|_| ());
46        }
47        buf.push(b);
48        p = unsafe { p.add(1) };
49    }
50    Err(())
51}
52
53/// 把 NULL 终止的指针数组拷贝为 `Vec<String>`
54/// WARNING: 这个函数直接读取指针,调用者必须保证指针在内核可读
55pub unsafe fn ptr_array_to_vec_strings(ptrs: *const *const u8) -> Result<Vec<String>, ()> {
56    let mut out: Vec<String> = Vec::new();
57    if ptrs.is_null() {
58        return Ok(out);
59    }
60    for i in 0..MAX_ARGV {
61        let p = unsafe { *ptrs.add(i) };
62        if p.is_null() {
63            break;
64        }
65        match unsafe { crate::util::copy_cstr_to_string(p) } {
66            Ok(s) => out.push(s),
67            Err(_) => return Err(()),
68        }
69    }
70    Ok(out)
71}
72
73/// 计算字符串的长度(不包括 NULL 终止符)
74/// # 参数:
75/// * `s` - 字符串指针
76/// # 返回值:
77/// 字符串长度
78pub unsafe fn cstr_len(s: *const u8) -> usize {
79    let mut len = 0;
80    let mut p = s;
81    while unsafe { core::ptr::read(p) } != 0 {
82        len += 1;
83        p = unsafe { p.add(1) };
84    }
85    len
86}
87
88/// 比较两个 C 字符串是否相等
89/// # 参数:
90/// * `s1` - 第一个字符串指针
91/// * `s2` - 第二个字符串指针
92/// # 返回值:
93/// 如果相等返回 true,否则返回 false
94pub unsafe fn cstr_equal(s1: *const u8, s2: *const u8) -> bool {
95    let mut p1 = s1;
96    let mut p2 = s2;
97    loop {
98        let b1 = unsafe { core::ptr::read(p1) };
99        let b2 = unsafe { core::ptr::read(p2) };
100        if b1 != b2 {
101            return false;
102        }
103        if b1 == 0 {
104            return true;
105        }
106        p1 = unsafe { p1.add(1) };
107        p2 = unsafe { p2.add(1) };
108    }
109}
110
111/// 从源指针拷贝 C 字符串到目标缓冲区
112/// # 参数:
113/// * `src` - 源字符串指针
114/// * `dest` - 目标缓冲区切片
115/// * `len` - 最大拷贝长度
116pub fn cstr_copy(src: *const u8, dest: &mut [u8], len: usize) {
117    for i in 0..len {
118        let b = unsafe { core::ptr::read(src.add(i)) };
119        dest[i] = b;
120        if b == 0 {
121            break;
122        }
123    }
124}