aboutsummaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/field/set.go86
-rw-r--r--pkg/field/set_test.go230
-rw-r--r--pkg/field/utils.go85
-rw-r--r--pkg/field/utils_test.go222
4 files changed, 316 insertions, 307 deletions
diff --git a/pkg/field/set.go b/pkg/field/set.go
new file mode 100644
index 0000000..5044898
--- /dev/null
+++ b/pkg/field/set.go
@@ -0,0 +1,86 @@
+package field
+
+func (f *Field) Set(x, y, v int) {
+ if v == ' ' {
+ f.Blank(x, y)
+ return
+ }
+ if y >= f.y {
+ if y < f.y+f.ly {
+ l := &f.lines[y-f.y]
+ if l.l == 0 {
+ // an empty line is a special case
+ l.x = x
+ l.l = 1
+ l.columns = append(l.columns, v)
+ } else if x >= l.x {
+ if x < l.x+l.l {
+ // just set the value
+ l.columns[x-l.x] = v
+ } else {
+ // append columns
+ newL := x - l.x + 1
+ for i := l.l; i < newL-1; i++ {
+ l.columns = append(l.columns, ' ')
+ }
+ l.columns = append(l.columns, v)
+ l.l = newL
+ if f.lx-f.x < l.l-l.x {
+ f.lx = l.l - l.x
+ }
+ }
+ } else {
+ // prepend columns
+ newL := l.l + l.x - x
+ c := make([]int, newL)
+ c[0] = v
+ for i := 1; i < l.x-x; i++ {
+ c[i] = ' '
+ }
+ for i := l.x - x; i < newL; i++ {
+ c[i] = l.columns[i-l.x+x]
+ }
+ l.columns = c
+ l.x = x
+ l.l = newL
+ if f.x > x {
+ f.lx = f.lx + f.x - x
+ f.x = x
+ }
+ }
+ } else {
+ // append lines
+ newLy := y - f.y + 1
+ for i := f.ly; i < newLy-1; i++ {
+ f.lines = append(f.lines, Line{})
+ }
+ f.lines = append(f.lines, Line{x: x, l: 1, columns: []int{v}})
+ f.ly = newLy
+ if f.x > x {
+ f.lx = f.lx + f.x - x
+ f.x = x
+ }
+ if f.lx-f.x < x {
+ f.lx = x - f.x
+ }
+ }
+ } else {
+ // prepend lines
+ newLy := f.ly + f.y - y
+ lines := make([]Line, newLy)
+ lines[0] = Line{x: x, l: 1, columns: []int{v}}
+ for j := f.y - y; j < newLy; j++ {
+ lines[j] = f.lines[j-f.y+y]
+ }
+ f.lines = lines
+ f.y = y
+ f.ly = newLy
+ if f.x > x {
+ f.lx = f.lx + f.x - x
+ f.x = x
+ }
+ if f.lx-f.x < x {
+ f.lx = x - f.x + 1
+ }
+ }
+}
diff --git a/pkg/field/set_test.go b/pkg/field/set_test.go
new file mode 100644
index 0000000..5b7f0ac
--- /dev/null
+++ b/pkg/field/set_test.go
@@ -0,0 +1,230 @@
+package field
+
+import (
+ "os"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestSetMinimalAppendOne(t *testing.T) {
+ hashField := Field{
+ x: 0,
+ y: 0,
+ lx: 1,
+ ly: 1,
+ lines: []Line{
+ Line{x: 0, l: 1, columns: []int{'#'}},
+ },
+ }
+ xAppendField := Field{
+ x: 0,
+ y: 0,
+ lx: 2,
+ ly: 1,
+ lines: []Line{
+ Line{x: 0, l: 2, columns: []int{'@', '#'}},
+ },
+ }
+ xPrependField := Field{
+ x: -1,
+ y: 0,
+ lx: 2,
+ ly: 1,
+ lines: []Line{
+ Line{x: -1, l: 2, columns: []int{'#', '@'}},
+ },
+ }
+ yAppendField := Field{
+ x: 0,
+ y: 0,
+ lx: 1,
+ ly: 2,
+ lines: []Line{
+ Line{x: 0, l: 1, columns: []int{'@'}},
+ Line{x: 0, l: 1, columns: []int{'#'}},
+ },
+ }
+ yPrependField := Field{
+ x: 0,
+ y: -1,
+ lx: 1,
+ ly: 2,
+ lines: []Line{
+ Line{x: 0, l: 1, columns: []int{'#'}},
+ Line{x: 0, l: 1, columns: []int{'@'}},
+ },
+ }
+ // Test cases
+ testCases := []struct {
+ name string
+ input string
+ inputX int
+ inputY int
+ inputV int
+ expected *Field
+ }{
+ {"simple", "test_data/minimal.b98", 0, 0, '#', &hashField},
+ {"xappend", "test_data/minimal.b98", 1, 0, '#', &xAppendField},
+ {"xprepend", "test_data/minimal.b98", -1, 0, '#', &xPrependField},
+ {"yappend", "test_data/minimal.b98", 0, 1, '#', &yAppendField},
+ {"yprepend", "test_data/minimal.b98", 0, -1, '#', &yPrependField},
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ file, err := os.Open(tc.input)
+ require.NoError(t, err, "Failed to open file")
+ defer file.Close()
+ field, err := Load(file)
+ field.Set(tc.inputX, tc.inputY, tc.inputV)
+ require.NoError(t, err)
+ require.Equal(t, tc.expected, field, "Invalid value")
+ })
+ }
+}
+
+func TestSetMinimalAppendTwo(t *testing.T) {
+ bottomRight := Field{
+ x: 0,
+ y: 0,
+ lx: 5,
+ ly: 3,
+ lines: []Line{
+ Line{x: 0, l: 1, columns: []int{'@'}},
+ Line{},
+ Line{x: 5, l: 1, columns: []int{'#'}},
+ },
+ }
+ bottomLeft := Field{
+ x: -5,
+ y: 0,
+ lx: 6,
+ ly: 4,
+ lines: []Line{
+ Line{x: 0, l: 1, columns: []int{'@'}},
+ Line{},
+ Line{},
+ Line{x: -5, l: 1, columns: []int{'#'}},
+ },
+ }
+ topRight := Field{
+ x: 0,
+ y: -3,
+ lx: 9,
+ ly: 4,
+ lines: []Line{
+ Line{x: 8, l: 1, columns: []int{'#'}},
+ Line{},
+ Line{},
+ Line{x: 0, l: 1, columns: []int{'@'}},
+ },
+ }
+ topLeft := Field{
+ x: -12,
+ y: -4,
+ lx: 13,
+ ly: 5,
+ lines: []Line{
+ Line{x: -12, l: 1, columns: []int{'#'}},
+ Line{},
+ Line{},
+ Line{},
+ Line{x: 0, l: 1, columns: []int{'@'}},
+ },
+ }
+ // Test cases
+ testCases := []struct {
+ name string
+ input string
+ inputX int
+ inputY int
+ inputV int
+ expected *Field
+ }{
+ {"bottomRight", "test_data/minimal.b98", 5, 2, '#', &bottomRight},
+ {"bottomLeft", "test_data/minimal.b98", -5, 3, '#', &bottomLeft},
+ {"topRight", "test_data/minimal.b98", 8, -3, '#', &topRight},
+ {"topLeft", "test_data/minimal.b98", -12, -4, '#', &topLeft},
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ file, err := os.Open(tc.input)
+ require.NoError(t, err, "Failed to open file")
+ defer file.Close()
+ field, err := Load(file)
+ field.Set(tc.inputX, tc.inputY, tc.inputV)
+ require.NoError(t, err)
+ require.Equal(t, tc.expected, field, "Invalid value")
+ })
+ }
+}
+
+func TestSetMinimalAppendThree(t *testing.T) {
+ xAppendField := Field{
+ x: 0,
+ y: 0,
+ lx: 4,
+ ly: 1,
+ lines: []Line{
+ Line{x: 0, l: 4, columns: []int{'@', ' ', ' ', '#'}},
+ },
+ }
+ xPrependField := Field{
+ x: -3,
+ y: 0,
+ lx: 4,
+ ly: 1,
+ lines: []Line{
+ Line{x: -3, l: 4, columns: []int{'#', ' ', ' ', '@'}},
+ },
+ }
+ yAppendField := Field{
+ x: 0,
+ y: 0,
+ lx: 1,
+ ly: 4,
+ lines: []Line{
+ Line{x: 0, l: 1, columns: []int{'@'}},
+ Line{},
+ Line{},
+ Line{x: 0, l: 1, columns: []int{'#'}},
+ },
+ }
+ yPrependField := Field{
+ x: 0,
+ y: -3,
+ lx: 1,
+ ly: 4,
+ lines: []Line{
+ Line{x: 0, l: 1, columns: []int{'#'}},
+ Line{},
+ Line{},
+ Line{x: 0, l: 1, columns: []int{'@'}},
+ },
+ }
+ // Test cases
+ testCases := []struct {
+ name string
+ input string
+ inputX int
+ inputY int
+ inputV int
+ expected *Field
+ }{
+ {"xappend", "test_data/minimal.b98", 3, 0, '#', &xAppendField},
+ {"xprepend", "test_data/minimal.b98", -3, 0, '#', &xPrependField},
+ {"yappend", "test_data/minimal.b98", 0, 3, '#', &yAppendField},
+ {"yprepend", "test_data/minimal.b98", 0, -3, '#', &yPrependField},
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ file, err := os.Open(tc.input)
+ require.NoError(t, err, "Failed to open file")
+ defer file.Close()
+ field, err := Load(file)
+ field.Set(tc.inputX, tc.inputY, tc.inputV)
+ require.NoError(t, err)
+ require.Equal(t, tc.expected, field, "Invalid value")
+ })
+ }
+}
diff --git a/pkg/field/utils.go b/pkg/field/utils.go
index c513d96..ab5ff7a 100644
--- a/pkg/field/utils.go
+++ b/pkg/field/utils.go
@@ -14,91 +14,6 @@ func (f Field) isIn(x, y int) bool {
return x >= f.x && x < f.x+f.lx && y >= f.y && y < f.y+f.ly
}
-func (f *Field) Set(x, y, v int) {
- if v == ' ' {
- f.Blank(x, y)
- return
- }
- if y >= f.y {
- if y < f.y+f.ly {
- l := &f.lines[y-f.y]
- if l.l == 0 {
- // an empty line is a special case
- l.x = x
- l.l = 1
- l.columns = append(l.columns, v)
- } else if x >= l.x {
- if x < l.x+l.l {
- // just set the value
- l.columns[x-l.x] = v
- } else {
- // append columns
- newL := x - l.x + 1
- for i := l.l; i < newL-1; i++ {
- l.columns = append(l.columns, ' ')
- }
- l.columns = append(l.columns, v)
- l.l = newL
- if f.lx-f.x < l.l-l.x {
- f.lx = l.l - l.x
- }
- }
- } else {
- // prepend columns
- newL := l.l + l.x - x
- c := make([]int, newL)
- c[0] = v
- for i := 1; i < l.x-x; i++ {
- c[i] = ' '
- }
- for i := l.x - x; i < newL; i++ {
- c[i] = l.columns[i-l.x+x]
- }
- l.columns = c
- l.x = x
- l.l = newL
- if f.x > x {
- f.lx = f.lx + f.x - x
- f.x = x
- }
- }
- } else {
- // append lines
- newLy := y - f.y + 1
- for i := f.ly; i < newLy-1; i++ {
- f.lines = append(f.lines, Line{})
- }
- f.lines = append(f.lines, Line{x: x, l: 1, columns: []int{v}})
- f.ly = newLy
- if f.x > x {
- f.lx = f.lx + f.x - x
- f.x = x
- }
- if f.lx-f.x < x {
- f.lx = x - f.x
- }
- }
- } else {
- // prepend lines
- newLy := f.ly + f.y - y
- lines := make([]Line, newLy)
- lines[0] = Line{x: x, l: 1, columns: []int{v}}
- for j := f.y - y; j < newLy; j++ {
- lines[j] = f.lines[j-f.y+y]
- }
- f.lines = lines
- f.y = y
- f.ly = newLy
- if f.x > x {
- f.lx = f.lx + f.x - x
- f.x = x
- }
- if f.lx-f.x < x {
- f.lx = x - f.x + 1
- }
- }
-}
-
func (f Field) Dump() (int, int, int, int) {
return f.x, f.y, f.lx, f.ly
}
diff --git a/pkg/field/utils_test.go b/pkg/field/utils_test.go
index 837f9fb..d1f4332 100644
--- a/pkg/field/utils_test.go
+++ b/pkg/field/utils_test.go
@@ -73,228 +73,6 @@ func TestIsIn(t *testing.T) {
}
}
-func TestSetMinimalAppendOne(t *testing.T) {
- hashField := Field{
- x: 0,
- y: 0,
- lx: 1,
- ly: 1,
- lines: []Line{
- Line{x: 0, l: 1, columns: []int{'#'}},
- },
- }
- xAppendField := Field{
- x: 0,
- y: 0,
- lx: 2,
- ly: 1,
- lines: []Line{
- Line{x: 0, l: 2, columns: []int{'@', '#'}},
- },
- }
- xPrependField := Field{
- x: -1,
- y: 0,
- lx: 2,
- ly: 1,
- lines: []Line{
- Line{x: -1, l: 2, columns: []int{'#', '@'}},
- },
- }
- yAppendField := Field{
- x: 0,
- y: 0,
- lx: 1,
- ly: 2,
- lines: []Line{
- Line{x: 0, l: 1, columns: []int{'@'}},
- Line{x: 0, l: 1, columns: []int{'#'}},
- },
- }
- yPrependField := Field{
- x: 0,
- y: -1,
- lx: 1,
- ly: 2,
- lines: []Line{
- Line{x: 0, l: 1, columns: []int{'#'}},
- Line{x: 0, l: 1, columns: []int{'@'}},
- },
- }
- // Test cases
- testCases := []struct {
- name string
- input string
- inputX int
- inputY int
- inputV int
- expected *Field
- }{
- {"simple", "test_data/minimal.b98", 0, 0, '#', &hashField},
- {"xappend", "test_data/minimal.b98", 1, 0, '#', &xAppendField},
- {"xprepend", "test_data/minimal.b98", -1, 0, '#', &xPrependField},
- {"yappend", "test_data/minimal.b98", 0, 1, '#', &yAppendField},
- {"yprepend", "test_data/minimal.b98", 0, -1, '#', &yPrependField},
- }
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- file, err := os.Open(tc.input)
- require.NoError(t, err, "Failed to open file")
- defer file.Close()
- field, err := Load(file)
- field.Set(tc.inputX, tc.inputY, tc.inputV)
- require.NoError(t, err)
- require.Equal(t, tc.expected, field, "Invalid value")
- })
- }
-}
-
-func TestSetMinimalAppendTwo(t *testing.T) {
- bottomRight := Field{
- x: 0,
- y: 0,
- lx: 5,
- ly: 3,
- lines: []Line{
- Line{x: 0, l: 1, columns: []int{'@'}},
- Line{},
- Line{x: 5, l: 1, columns: []int{'#'}},
- },
- }
- bottomLeft := Field{
- x: -5,
- y: 0,
- lx: 6,
- ly: 4,
- lines: []Line{
- Line{x: 0, l: 1, columns: []int{'@'}},
- Line{},
- Line{},
- Line{x: -5, l: 1, columns: []int{'#'}},
- },
- }
- topRight := Field{
- x: 0,
- y: -3,
- lx: 9,
- ly: 4,
- lines: []Line{
- Line{x: 8, l: 1, columns: []int{'#'}},
- Line{},
- Line{},
- Line{x: 0, l: 1, columns: []int{'@'}},
- },
- }
- topLeft := Field{
- x: -12,
- y: -4,
- lx: 13,
- ly: 5,
- lines: []Line{
- Line{x: -12, l: 1, columns: []int{'#'}},
- Line{},
- Line{},
- Line{},
- Line{x: 0, l: 1, columns: []int{'@'}},
- },
- }
- // Test cases
- testCases := []struct {
- name string
- input string
- inputX int
- inputY int
- inputV int
- expected *Field
- }{
- {"bottomRight", "test_data/minimal.b98", 5, 2, '#', &bottomRight},
- {"bottomLeft", "test_data/minimal.b98", -5, 3, '#', &bottomLeft},
- {"topRight", "test_data/minimal.b98", 8, -3, '#', &topRight},
- {"topLeft", "test_data/minimal.b98", -12, -4, '#', &topLeft},
- }
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- file, err := os.Open(tc.input)
- require.NoError(t, err, "Failed to open file")
- defer file.Close()
- field, err := Load(file)
- field.Set(tc.inputX, tc.inputY, tc.inputV)
- require.NoError(t, err)
- require.Equal(t, tc.expected, field, "Invalid value")
- })
- }
-}
-
-func TestSetMinimalAppendThree(t *testing.T) {
- xAppendField := Field{
- x: 0,
- y: 0,
- lx: 4,
- ly: 1,
- lines: []Line{
- Line{x: 0, l: 4, columns: []int{'@', ' ', ' ', '#'}},
- },
- }
- xPrependField := Field{
- x: -3,
- y: 0,
- lx: 4,
- ly: 1,
- lines: []Line{
- Line{x: -3, l: 4, columns: []int{'#', ' ', ' ', '@'}},
- },
- }
- yAppendField := Field{
- x: 0,
- y: 0,
- lx: 1,
- ly: 4,
- lines: []Line{
- Line{x: 0, l: 1, columns: []int{'@'}},
- Line{},
- Line{},
- Line{x: 0, l: 1, columns: []int{'#'}},
- },
- }
- yPrependField := Field{
- x: 0,
- y: -3,
- lx: 1,
- ly: 4,
- lines: []Line{
- Line{x: 0, l: 1, columns: []int{'#'}},
- Line{},
- Line{},
- Line{x: 0, l: 1, columns: []int{'@'}},
- },
- }
- // Test cases
- testCases := []struct {
- name string
- input string
- inputX int
- inputY int
- inputV int
- expected *Field
- }{
- {"xappend", "test_data/minimal.b98", 3, 0, '#', &xAppendField},
- {"xprepend", "test_data/minimal.b98", -3, 0, '#', &xPrependField},
- {"yappend", "test_data/minimal.b98", 0, 3, '#', &yAppendField},
- {"yprepend", "test_data/minimal.b98", 0, -3, '#', &yPrependField},
- }
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- file, err := os.Open(tc.input)
- require.NoError(t, err, "Failed to open file")
- defer file.Close()
- field, err := Load(file)
- field.Set(tc.inputX, tc.inputY, tc.inputV)
- require.NoError(t, err)
- require.Equal(t, tc.expected, field, "Invalid value")
- })
- }
-}
-
// get and put on an empty line
func TestGetAndSetOnEmptyLines(t *testing.T) {
f := Field{