summaryrefslogtreecommitdiff
path: root/chapter31/src/main/smp/sys/aryi64.smp
blob: b9f1fbed46c5ee47041a02eb86b7c34212a40775 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

// Ary/Vector of i64s
struct aryi64 {
    u32 !len = 0;
    i64[] !buf;

    new aryi64 = { i64[] b ->
        buf = b;
    };

    // Grow as needed
    val _grow = { u32 len2 ->
        if( len+len2 <= buf# ) return self;
        u32 newlen = ary.capacity(buf#,len+len2);
        if( !newlen ) libc._exit(1); // Length exceeds the array representation.
        i64[] !buf2 = new i64[newlen];
        for( u32 i=0; i<len; i++ )
            buf2[i] = buf[i];
        buf = buf2;
        self;
    };

    // Add an i64 to aryi64
    val add = { i64 c ->
        _grow(1).buf[len++] = c;
        self;
    };

    val get = { u32 index -> return buf[index]; };

    // Write the bracketed array-list form to aryu8.
    val str = { ->
        // TODO: clunky default constructor syntax
        var str = new aryu8().add('[');
        for( u32 i=0; i<len; i++ )
            str.num(buf[i]).add(',').add(' ');
        if( len ) str.undo(2);
        return str.add(']');
    };

    val swap = { u32 i, u32 j ->
        i64 tmp = buf[i];
        buf[i] = buf[j];
        buf[j] = tmp;
        self;
    };
};



// Parse a comma-separated list of numbers, wrapped with square brackets,
// with optional whitespace  e.g. "[ -17, 0,99,12456789   ]  ".
// parseAryI64 & aryi64.str are bijections modulo whitespace.
// Returns null if the parse failed, without giving a clue as to why.
val parseAryI64 = { u8[~] str ->
    !scan !s = new scan(str);
    if( !s.match('[') ) return null;
    // Array of parsed results
    var nums = new aryi64(new i64[1]);

    // Parse a list of numbers
    if( s.match(']') )          // Handle the empty list
        return nums;

    // Parse number commas "123, " until something else
    while( s.x < s.buf# ) {
        nums.add(s.number());
        if( s.bad ) return null;
        if( !s.match(',') )
            break;
    };
    // Close the list
    if( !s.match(']') ) return null;
    s.skip();
    return s.x == s.buf# ? nums : null;
};

val copy = { i64[] dst, u32 doff, i64[~] src, u32 soff, u32 len ->
    if( doff > dst# || soff > src# ) return dst;
    if( len > dst# - doff ) len = dst# - doff;
    if( len > src# - soff ) len = src# - soff;
    for( u32 i=0; i<len; i++ )
        dst[i+doff] = src[i+soff];
    return dst;
};