summaryrefslogtreecommitdiff
path: root/chapter25/src/main/smp/sys/aryi64.smp
blob: c2bc394f866659f8df0d29fecaad4f7c449e4ffa (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
// -*- mode: java;  -*-

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

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

    // Grow as needed
    val _grow = { int len2 ->
        if( len+len2 < buf# ) return self;
        int newlen = buf# * 2;
        while( len+len2 >= newlen ) newlen *= 2;
        i64[] !buf2 = new i64[newlen];
        for( int i=0; i<buf#; i++ )
            buf2[i] = buf[i];
        buf = buf2;
        self;
    };

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

    // Write to aryu8
    val str = { ->
        // TODO: clunky default constructor syntax
        var str = new aryu8(new u8[1]).add('[');
        for( int i=0; i<len; i++ )
            str.num(buf[i]).add(',').add(' ');
        str.undo(2).add(']');
    };

    // Comma-separated form used by command-line examples.
    val csv = { ->
        var str = new aryu8(new u8[1]);
        for( int i=0; i<len; i++ )
            str.num(buf[i]).add(',').add(' ');
        str.undo(2).add('\n');
    };

    val swap = { int i, int 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;
};