lib/std/mem.rad 2.3 KiB raw
1
/// Memory error.
2
union MemoryError: Copy {
3
    /// Buffer is too small.
4
    BufferTooSmall,
5
}
6
7
/// Copy bytes between two slices. Returns the number of bytes copied.
8
export fn copy(into: &mut [u8], from: &[u8]) -> u32 throws (MemoryError) {
9
    if into.len < from.len {
10
        throw MemoryError::BufferTooSmall;
11
    }
12
    for x, i in from {
13
        set into[i] = x;
14
    }
15
    return from.len;
16
}
17
18
/// Strip a byte-level prefix from the input, and return the suffix.
19
/// Returns `nil` if the prefix wasn't found.
20
export fn stripPrefix(prefix: &[u8], input: *[u8]) -> ?*[u8] {
21
    if prefix.len == 0 {
22
        return input;
23
    }
24
    if prefix.len > input.len {
25
        return nil;
26
    }
27
    for i in 0..prefix.len {
28
        if prefix[i] <> input[i] {
29
            return nil;
30
        }
31
    }
32
    return &input[prefix.len..];
33
}
34
35
/// Align value up to alignment boundary.
36
export fn alignUp(value: u32, alignment: u32) -> u32 {
37
    return (value + alignment - 1) & ~(alignment - 1);
38
}
39
40
/// Align signed value up to alignment boundary.
41
export fn alignUpI32(value: i32, alignment: i32) -> i32 {
42
    return (value + alignment - 1) & ~(alignment - 1);
43
}
44
45
/// Count number of set bits in a 32-bit value.
46
export fn popCount(x: u32) -> i32 {
47
    let mut n = x;
48
    let mut count: i32 = 0;
49
    while n <> 0 {
50
        set count += (n & 1) as i32;
51
        set n >>= 1;
52
    }
53
    return count;
54
}
55
56
/// Check whether two byte slices have the same length and contents.
57
export fn eq(a: &[u8], b: &[u8]) -> bool {
58
    if a.len <> b.len {
59
        return false;
60
    }
61
    unsafe {
62
        if a.ptr == b.ptr {
63
            return true;
64
        }
65
    }
66
    for i in 0..a.len {
67
        if a[i] <> b[i] {
68
            return false;
69
        }
70
    }
71
    return true;
72
}
73
74
/// Compare two byte slices lexicographically.
75
///
76
/// Returns `-1` when `a < b`, `1` when `a > b`, and `0` when equal.
77
export fn cmp(a: &[u8], b: &[u8]) -> i32 {
78
    let aLen = a.len;
79
    let bLen = b.len;
80
81
    let common = bLen if bLen < aLen else aLen;
82
    for i in 0..common {
83
        let aByte = a[i];
84
        let bByte = b[i];
85
        if aByte < bByte {
86
            return -1;
87
        }
88
        if aByte > bByte {
89
            return 1;
90
        }
91
    }
92
    if aLen < bLen {
93
        return -1;
94
    }
95
    if aLen > bLen {
96
        return 1;
97
    }
98
    return 0;
99
}