diff options
| author | Vexu <git@vexu.eu> | 2020-10-17 01:09:42 +0300 |
|---|---|---|
| committer | Vexu <git@vexu.eu> | 2020-10-30 15:58:13 +0200 |
| commit | 12e4c648ccc68f5190dd5076088b3959ebeee65d (patch) | |
| tree | e045157d9fba4648bb450510a4762f4937799308 /src/RangeSet.zig | |
| parent | 4155d2ae242d18c0bc280aa22f733bf7dcb6e1f0 (diff) | |
| download | zig-12e4c648ccc68f5190dd5076088b3959ebeee65d.tar.gz zig-12e4c648ccc68f5190dd5076088b3959ebeee65d.zip | |
stage2: implement switch validation for integers
Diffstat (limited to 'src/RangeSet.zig')
| -rw-r--r-- | src/RangeSet.zig | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/src/RangeSet.zig b/src/RangeSet.zig new file mode 100644 index 0000000000..5daacbbf08 --- /dev/null +++ b/src/RangeSet.zig @@ -0,0 +1,76 @@ +const std = @import("std"); +const Order = std.math.Order; +const Value = @import("value.zig").Value; +const RangeSet = @This(); + +ranges: std.ArrayList(Range), + +pub const Range = struct { + start: Value, + end: Value, + src: usize, +}; + +pub fn init(allocator: *std.mem.Allocator) RangeSet { + return .{ + .ranges = std.ArrayList(Range).init(allocator), + }; +} + +pub fn deinit(self: *RangeSet) void { + self.ranges.deinit(); +} + +pub fn add(self: *RangeSet, start: Value, end: Value, src: usize) !?usize { + for (self.ranges.items) |range| { + if ((start.compare(.gte, range.start) and start.compare(.lte, range.end)) or + (end.compare(.gte, range.start) and end.compare(.lte, range.end))) + { + // ranges overlap + return range.src; + } + } + try self.ranges.append(.{ + .start = start, + .end = end, + .src = src, + }); + return null; +} + +/// Assumes a and b do not overlap +fn lessThan(_: void, a: Range, b: Range) bool { + return a.start.compare(.lt, b.start); +} + +pub fn spans(self: *RangeSet, start: Value, end: Value) !bool { + std.sort.sort(Range, self.ranges.items, {}, lessThan); + + if (!self.ranges.items[0].start.eql(start) or + !self.ranges.items[self.ranges.items.len - 1].end.eql(end)) + { + return false; + } + + var space: Value.BigIntSpace = undefined; + + var counter = try std.math.big.int.Managed.init(self.ranges.allocator); + defer counter.deinit(); + + // look for gaps + for (self.ranges.items[1..]) |cur, i| { + // i starts counting from the second item. + const prev = self.ranges.items[i]; + + // prev.end + 1 == cur.start + try counter.copy(prev.end.toBigInt(&space)); + try counter.addScalar(counter.toConst(), 1); + + const cur_start_int = cur.start.toBigInt(&space); + if (!cur_start_int.eq(counter.toConst())) { + return false; + } + } + + return true; +} |
