Browse Source

first 3 section test passing

Geoffrey J. Teale 6 years ago
parent
commit
da7fcd25e5
2 changed files with 195 additions and 43 deletions
  1. 106 27
      col.go
  2. 89 16
      col_test.go

+ 106 - 27
col.go

@@ -146,6 +146,33 @@ type colStoreNode struct {
 	Next *colStoreNode
 }
 
+//
+func (csn *colStoreNode) findNodeForColNum(num int) *colStoreNode {
+	switch {
+	case num >= csn.Col.Min && num <= csn.Col.Max:
+		return csn
+
+	case num < csn.Col.Min:
+		if csn.Prev == nil {
+			return nil
+		}
+		if csn.Prev.Col.Max < num {
+			return nil
+		}
+		return csn.Prev.findNodeForColNum(num)
+
+	case num > csn.Col.Max:
+		if csn.Next == nil {
+			return nil
+		}
+		if csn.Next.Col.Min > num {
+			return nil
+		}
+		return csn.Next.findNodeForColNum(num)
+	}
+	return nil
+}
+
 // ColStore is the working store of Col definitions, it will simplify all Cols added to it, to ensure there ar no overlapping definitions.
 type ColStore struct {
 	Root *colStoreNode
@@ -164,6 +191,45 @@ func (cs *ColStore) Add(col *Col) {
 	return
 }
 
+//
+func (cs *ColStore) findNodeForColNum(num int) *colStoreNode {
+	if cs.Root == nil {
+		return nil
+	}
+	return cs.Root.findNodeForColNum(num)
+}
+
+//
+func (cs *ColStore) removeNode(node *colStoreNode) {
+	if node.Prev != nil {
+		if node.Next != nil {
+			node.Prev.Next = node.Next
+		} else {
+			node.Prev.Next = nil
+		}
+
+	}
+	if node.Next != nil {
+		if node.Prev != nil {
+			node.Next.Prev = node.Prev
+		} else {
+			node.Next.Prev = nil
+		}
+	}
+	if cs.Root == node {
+		switch {
+		case node.Prev != nil:
+			cs.Root = node.Prev
+		case node.Next != nil:
+			cs.Root = node.Next
+		default:
+			cs.Root = nil
+		}
+	}
+	node.Next = nil
+	node.Prev = nil
+}
+
 // makeWay will adjust the Min and Max of this colStoreNode's Col to
 // make way for a new colStoreNode's Col. If necessary it will
 // generate an additional colStoreNode with a new Col covering the
@@ -178,7 +244,12 @@ func (cs *ColStore) makeWay(node1, node2 *colStoreNode) {
 		// Node1 |----|
 		// Node2        |----|
 		if node1.Next != nil {
-			cs.makeWay(node1.Next, node2)
+			next := node1.Next
+			if next.Col.Min >= node2.Col.Min {
+				node1.Next = node2
+				node2.Prev = node1
+			}
+			cs.makeWay(next, node2)
 			return
 		}
 		node1.Next = node2
@@ -191,7 +262,12 @@ func (cs *ColStore) makeWay(node1, node2 *colStoreNode) {
 		// Node1         |-----|
 		// Node2  |----|
 		if node1.Prev != nil {
-			cs.makeWay(node1.Prev, node2)
+			prev := node1.Prev
+			if prev.Col.Max <= node2.Col.Max {
+				node1.Prev = node2
+				node2.Next = node1
+			}
+			cs.makeWay(prev, node2)
 			return
 		}
 		node1.Prev = node2
@@ -203,42 +279,45 @@ func (cs *ColStore) makeWay(node1, node2 *colStoreNode) {
 		//
 		// Node1 |xxx|
 		// Node2 |---|
-		if node1.Prev != nil {
-			node1.Prev.Next = node2
-			node2.Prev = node1.Prev
-			node1.Prev = nil
+
+		prev := node1.Prev
+		next := node1.Next
+		cs.removeNode(node1)
+		if prev != nil {
+			prev.Next = node2
+			node2.Prev = prev
 		}
-		if node1.Next != nil {
-			node1.Next.Prev = node2
-			node2.Next = node1.Next
-			node1.Next = nil
+		if next != nil {
+			next.Prev = node2
+			node2.Next = next
 		}
-		if cs.Root == node1 {
+		// Remove node may have set the root to nil
+		if cs.Root == nil {
 			cs.Root = node2
 		}
+		return
+
 	case node1.Col.Min > node2.Col.Min && node1.Col.Max < node2.Col.Max:
 		// Node2 envelopes node1
 		//
 		// Node1  |xx|
 		// Node2 |----|
-		if cs.Root == node1 {
-			cs.Root = node2
+
+		prev := node1.Prev
+		next := node1.Next
+		cs.removeNode(node1)
+
+		if prev != nil {
+			prev.Next = nil
+			cs.makeWay(prev, node2)
 		}
-		if node1.Prev != nil {
-			node1.Prev.Next = nil
-			if node1.Next != nil {
-				node1.Prev.Next = node1.Next
-				node1.Next = nil
-			}
-			cs.makeWay(node1.Prev, node2)
-			node1.Prev = nil
-			return
+		if next != nil {
+			next.Prev = nil
+			cs.makeWay(next, node2)
 		}
-		if node1.Next != nil {
-			node1.Next.Prev = nil
-			cs.makeWay(node1.Next, node2)
-			node1.Next = nil
-			return
+
+		if cs.Root == nil {
+			cs.Root = node2
 		}
 
 	case node1.Col.Min < node2.Col.Min && node1.Col.Max > node2.Col.Max:

+ 89 - 16
col_test.go

@@ -147,6 +147,7 @@ func (css *ColStoreSuite) TestMakeWay(c *C) {
 	// Col2: |--|
 	assertWayMade([]*Col{&Col{Min: 0, Max: 1, Width: 40.1}, &Col{Min: 0, Max: 1, Width: 10.0}},
 		func(root *colStoreNode) {
+			c.Assert(root, NotNil)
 			c.Assert(root.Prev, IsNil)
 			c.Assert(root.Next, IsNil)
 			c.Assert(root.Col.Min, Equals, 0)
@@ -169,21 +170,93 @@ func (css *ColStoreSuite) TestMakeWay(c *C) {
 
 	// Col1: |--|
 	// Col2:          |--|
-	// Col3:     |
-	// assertWayMade([]*Col{&Col{Min: 0, Max: 7}, &Col{Min: 3, Max: 4}},
-	// 	func(root *colStoreNode) {
-	// 		c.Assert(root.Prev, IsNil)
-	// 		c.Assert(root.Next, NotNil)
-	// 		node2 := root.Next
-	// 		c.Assert(node2.Prev, Equals, root)
-	// 		c.Assert(node2.Col.Min, Equals, 3)
-	// 		c.Assert(node2.Col.Max, Equals, 4)
-	// 		c.Assert(node2.Next, NotNil)
-	// 		node3 := node2.Next
-	// 		c.Assert(node3.Prev, Equals, node2)
-	// 		c.Assert(node3.Next, IsNil)
-	// 		c.Assert(node3.Col.Min, Equals, 5)
-	// 		c.Assert(node3.Col.Max, Equals, 7)
-	// 	})
+	// Col3:     |--|
+	assertWayMade([]*Col{&Col{Min: 0, Max: 1}, &Col{Min: 9, Max: 10}, &Col{Min: 4, Max: 5}},
+		func(root *colStoreNode) {
+			c.Assert(root.Prev, IsNil)
+			c.Assert(root.Next, NotNil)
+			node2 := root.Next
+			c.Assert(node2.Prev, Equals, root)
+			c.Assert(node2.Col.Min, Equals, 4)
+			c.Assert(node2.Col.Max, Equals, 5)
+			c.Assert(node2.Next, NotNil)
+			node3 := node2.Next
+			c.Assert(node3.Prev, Equals, node2)
+			c.Assert(node3.Next, IsNil)
+			c.Assert(node3.Col.Min, Equals, 9)
+			c.Assert(node3.Col.Max, Equals, 10)
+		})
+
+}
+
+func (css *ColStoreSuite) TestFindNodeForCol(c *C) {
+
+	assertNodeFound := func(cs *ColStore, num int, col *Col) {
+		node := cs.findNodeForColNum(num)
+		if col == nil {
+			c.Assert(node, IsNil)
+			return
+		}
+		c.Assert(node, NotNil)
+		c.Assert(node.Col, Equals, col)
+	}
+
+	cs := &ColStore{}
+	col0 := &Col{Min: 0, Max: 0}
+	cs.Add(col0)
+	col1 := &Col{Min: 1, Max: 1}
+	cs.Add(col1)
+	col2 := &Col{Min: 2, Max: 2}
+	cs.Add(col2)
+	col3 := &Col{Min: 3, Max: 3}
+	cs.Add(col3)
+	col4 := &Col{Min: 4, Max: 4}
+	cs.Add(col4)
+	col5 := &Col{Min: 100, Max: 125}
+	cs.Add(col5)
+
+	assertNodeFound(cs, -1, nil)
+	assertNodeFound(cs, 0, col0)
+	assertNodeFound(cs, 1, col1)
+	assertNodeFound(cs, 2, col2)
+	assertNodeFound(cs, 3, col3)
+	assertNodeFound(cs, 4, col4)
+	assertNodeFound(cs, 5, nil)
+	assertNodeFound(cs, 99, nil)
+	assertNodeFound(cs, 100, col5)
+	assertNodeFound(cs, 110, col5)
+	assertNodeFound(cs, 125, col5)
+	assertNodeFound(cs, 126, nil)
+}
+
+func (css *ColStoreSuite) TestRemoveNode(c *C) {
+
+	assertChain := func(cs *ColStore, chain []*Col) {
+		node := cs.Root
+		for _, col := range chain {
+			c.Assert(node, NotNil)
+			c.Assert(node.Col.Min, Equals, col.Min)
+			c.Assert(node.Col.Max, Equals, col.Max)
+			node = node.Next
+		}
+		c.Assert(node, IsNil)
+	}
+
+	cs := &ColStore{}
+	col0 := &Col{Min: 0, Max: 0}
+	cs.Add(col0)
+	col1 := &Col{Min: 1, Max: 1}
+	cs.Add(col1)
+	col2 := &Col{Min: 2, Max: 2}
+	cs.Add(col2)
+	col3 := &Col{Min: 3, Max: 3}
+	cs.Add(col3)
+	col4 := &Col{Min: 4, Max: 4}
+	cs.Add(col4)
+
+	cs.removeNode(cs.findNodeForColNum(4))
+	assertChain(cs, []*Col{col0, col1, col2, col3})
 
+	cs.removeNode(cs.findNodeForColNum(0))
+	assertChain(cs, []*Col{col1, col2, col3})
 }