aboutsummaryrefslogtreecommitdiff
path: root/src/field.zig
diff options
context:
space:
mode:
authorJulien Dessaux2022-02-20 23:22:12 +0100
committerJulien Dessaux2022-02-20 23:22:12 +0100
commit79fe123c367b59cd41f956405afa28e3be77e0f1 (patch)
tree22396231fe7603f9ce3baaecd3440aa2938d6574 /src/field.zig
parentSimplified the stack stack code (diff)
downloadzigfunge98-79fe123c367b59cd41f956405afa28e3be77e0f1.tar.gz
zigfunge98-79fe123c367b59cd41f956405afa28e3be77e0f1.tar.bz2
zigfunge98-79fe123c367b59cd41f956405afa28e3be77e0f1.zip
Began implementing the funge Field
Diffstat (limited to 'src/field.zig')
-rw-r--r--src/field.zig178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/field.zig b/src/field.zig
new file mode 100644
index 0000000..4f7bcea
--- /dev/null
+++ b/src/field.zig
@@ -0,0 +1,178 @@
+const std = @import("std");
+
+const Line = struct {
+ x: i64 = 0,
+ data: std.ArrayList(i64),
+ pub fn blank(l: *Line, x: i64) void {
+ const lx = @intCast(i64, l.data.items.len);
+ if (x > l.x and x < l.x + lx - 1) { // just set the value
+ l.data.items[@intCast(usize, x - l.x)] = ' ';
+ } else if (lx == 1) { // this was the last character on the line
+ l.data.items.len = 0;
+ } else if (x == l.x) { // we need to remove leading spaces
+ var i: usize = 1;
+ while (l.data.items[i] == ' ') : (i += 1) {}
+ l.x += @intCast(i64, i);
+ std.mem.copy(i64, l.data.items[0 .. l.data.items.len - i], l.data.items[i..]);
+ l.data.items.len -= i;
+ } else if (x == l.x + lx - 1) { // we need to remove trailing spaces
+ var i: usize = l.data.items.len - 1;
+ while (l.data.items[i - 1] == ' ') : (i -= 1) {}
+ l.data.items.len = i;
+ }
+ }
+ test "blank" {
+ var l = Line.init(std.testing.allocator);
+ defer l.deinit();
+ const initial = [_]i64{ 'b', 'a', '@', 'c', 'd', 'e', 'f' };
+ try l.data.appendSlice(initial[0..]);
+ l.x = -2;
+ l.blank(-3);
+ try std.testing.expectEqualSlices(i64, l.data.items, initial[0..]);
+ l.blank(8);
+ try std.testing.expectEqualSlices(i64, l.data.items, initial[0..]);
+ l.blank(0);
+ const zero = [_]i64{ 'b', 'a', ' ', 'c', 'd', 'e', 'f' };
+ try std.testing.expectEqual(l.x, -2);
+ try std.testing.expectEqualSlices(i64, l.data.items, zero[0..]);
+ l.blank(-2);
+ const moins2 = [_]i64{ 'a', ' ', 'c', 'd', 'e', 'f' };
+ try std.testing.expectEqual(l.x, -1);
+ try std.testing.expectEqualSlices(i64, l.data.items, moins2[0..]);
+ l.blank(-1);
+ const moins1 = [_]i64{ 'c', 'd', 'e', 'f' };
+ try std.testing.expectEqual(l.x, 1);
+ try std.testing.expectEqualSlices(i64, l.data.items, moins1[0..]);
+ l.blank(4);
+ const plus4 = [_]i64{ 'c', 'd', 'e' };
+ try std.testing.expectEqual(l.x, 1);
+ try std.testing.expectEqualSlices(i64, l.data.items, plus4[0..]);
+ l.blank(2);
+ const plus2 = [_]i64{ 'c', ' ', 'e' };
+ try std.testing.expectEqual(l.x, 1);
+ try std.testing.expectEqualSlices(i64, l.data.items, plus2[0..]);
+ l.blank(3);
+ const plus3 = [_]i64{'c'};
+ try std.testing.expectEqual(l.x, 1);
+ try std.testing.expectEqualSlices(i64, l.data.items, plus3[0..]);
+ l.blank(1);
+ try std.testing.expectEqual(l.data.items.len, 0);
+ }
+ pub fn deinit(self: *Line) void {
+ self.data.deinit();
+ }
+ pub fn init(allocator: std.mem.Allocator) Line {
+ const c = std.ArrayList(i64).init(allocator);
+ return Line{
+ .data = c,
+ };
+ }
+ pub fn set(l: *Line, x: i64, v: i64) !void {
+ if (l.data.items.len == 0) { // this is en empty line
+ l.x = x;
+ try l.data.append(v);
+ return;
+ }
+ const lx = @intCast(i64, l.data.items.len);
+ if (x >= l.x and x < l.x + lx) { // just set the value
+ l.data.items[@intCast(usize, x - l.x)] = v;
+ } else if (x < l.x) { // we need to shift right and add leading spaces
+ const oldLen = l.data.items.len;
+ l.data.items.len += @intCast(usize, l.x - x);
+ try l.data.ensureUnusedCapacity(l.data.items.len);
+ std.mem.copyBackwards(i64, l.data.items[@intCast(usize, l.x - x)..], l.data.items[0..oldLen]);
+ l.data.items[0] = v;
+ var i: usize = 1;
+ while (i < @intCast(usize, l.x - x)) : (i += 1) {
+ l.data.items[i] = ' ';
+ }
+ l.x = x;
+ } else { // we need to add trailing spaces
+ var i: usize = l.data.items.len;
+ while (i < x - l.x) : (i += 1) {
+ try l.data.append(' ');
+ }
+ try l.data.append(v);
+ }
+ }
+ test "set" {
+ var l = Line.init(std.testing.allocator);
+ defer l.deinit();
+ try l.set(-1, '@');
+ const zero = [_]i64{'@'};
+ try std.testing.expectEqual(l.x, -1);
+ try std.testing.expectEqualSlices(i64, l.data.items, zero[0..]);
+ try l.set(-1, 'a');
+ const a = [_]i64{'a'};
+ try std.testing.expectEqual(l.x, -1);
+ try std.testing.expectEqualSlices(i64, l.data.items, a[0..]);
+ try l.set(0, 'b');
+ const b = [_]i64{ 'a', 'b' };
+ try std.testing.expectEqual(l.x, -1);
+ try std.testing.expectEqualSlices(i64, l.data.items, b[0..]);
+ try l.set(2, 'c');
+ const c = [_]i64{ 'a', 'b', ' ', 'c' };
+ try std.testing.expectEqual(l.x, -1);
+ try std.testing.expectEqualSlices(i64, l.data.items, c[0..]);
+ try l.set(-2, 'd');
+ const d = [_]i64{ 'd', 'a', 'b', ' ', 'c' };
+ try std.testing.expectEqual(l.x, -2);
+ try std.testing.expectEqualSlices(i64, l.data.items, d[0..]);
+ try l.set(-4, 'e');
+ const e = [_]i64{ 'e', ' ', 'd', 'a', 'b', ' ', 'c' };
+ try std.testing.expectEqual(l.x, -4);
+ try std.testing.expectEqualSlices(i64, l.data.items, e[0..]);
+ }
+};
+
+const Field = struct {
+ allocator: std.mem.Allocator,
+ x: i64 = 0,
+ y: i64 = 0,
+ lines: std.ArrayList(Line),
+ lx: usize = 0,
+ pub fn blank(f: *Field, x: i64, y: i64) void {
+ const ly = @intCast(i64, f.lines.items.len);
+ if (y < f.y or y > f.y + ly) return; // outside the field
+ var l = &f.lines.items[@intCast(usize, y - f.y)];
+ if (l.data.items.len == 0) return; // the line is already empty
+ l.blank(x);
+ return; // TODO
+ }
+ pub fn deinit(self: *Field) void {
+ for (self.lines.items) |*l| {
+ l.deinit();
+ }
+ self.lines.deinit();
+ }
+ pub fn init(allocator: std.mem.Allocator) !Field {
+ var lines = std.ArrayList(Line).init(allocator);
+ var line = try lines.addOne();
+ line.* = Line.init(allocator);
+ try line.set(0, '@');
+ return Field{
+ .allocator = allocator,
+ .lines = lines,
+ };
+ }
+ //pub fn load(self: *Field, reader: std.io.Reader) {
+ // var br = std.io.bufferedReader(reader);
+ // var leadingSpaces:u64 = 0;
+ // var trailingSpaces:u64 = 0;
+ // var lastReadIsCR: bool = false;
+ //}
+ //pub fn set(self: *Field, x: i64, y: i64, v: i64) !void {
+ // if (v == ' ') return self.blank(x, y);
+ // return; // TODO
+ //}
+
+ //test "minimal" {
+ // var f = try Field.init(std.testing.allocator);
+ // defer f.deinit();
+ // f.blank(0, 0);
+ //}
+};
+
+test "all" {
+ std.testing.refAllDecls(@This());
+}