From a82d20f14b12f54373b7cfd852367edb6dd4b4ac Mon Sep 17 00:00:00 2001 From: "Sascha L. Teichmann" Date: Tue, 21 Oct 2014 12:08:01 +0200 Subject: [PATCH] Complete code of insert into span buffer. Looks complicated and needs testing. --- common/spans.go | 105 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 4 deletions(-) diff --git a/common/spans.go b/common/spans.go index 10d1cbb..b192de2 100644 --- a/common/spans.go +++ b/common/spans.go @@ -59,6 +59,7 @@ func (sp *SpanPool) FreeAll(s *Span) { func (sp *SpanPool) Insert(s *Span, pos, value int32) *Span { + // No head -> create. if s == nil { s = sp.Alloc() s.From = pos @@ -71,10 +72,10 @@ func (sp *SpanPool) Insert(s *Span, pos, value int32) *Span { if pos < s.From { // Same value and directly neighbored -> extend head. if value == s.Value && pos == s.From-1 { - s.From-- + s.From = pos return s } - // Disjunct -> create new. + // Disjunct -> create new head. prev := sp.Alloc() prev.From = pos prev.To = pos @@ -83,7 +84,103 @@ func (sp *SpanPool) Insert(s *Span, pos, value int32) *Span { return prev } - // TODO: Implement the more complicated cases. + head := s + for prev := s; s != nil; s = s.Next { + switch { + case pos < s.From: // before span + if pos == s.From-1 && value == s.Value { // directly neighbored + s.From = pos + // Check if a gap has to be closed. + if prev.To == s.From-1 && value == prev.Value { + prev.To = s.To + prev.Next = s.Next + sp.Free(s) + return head + } + } + // Extend prev? + if prev.To == pos-1 && value == prev.Value { + prev.To = pos + return head + } + // New between prev and current. + sn := sp.Alloc() + sn.From = pos + sn.To = pos + sn.Value = value + sn.Next = s + prev.Next = sn + return head - return nil + case pos > s.To: // after span + if pos == s.To+1 && value == s.Value { // directly neighbored + s.To = pos + // Check if a gap has to be closed + next := s.Next + if next != nil { + if next.From == s.To-1 && value == next.Value { + s.To = next.To + s.Next = next.Next + sp.Free(next) + return head + } + // Extend next? + if pos == next.From-1 && value == next.Value { + next.From = pos + return head + } + // Before next -> New between current and next + if pos < next.From { + sn := sp.Alloc() + sn.From = pos + sn.To = pos + sn.Value = value + sn.Next = next + s.Next = sn + return head + } + } else { // No next -> new at tail + sn := sp.Alloc() + sn.From = pos + sn.To = pos + sn.Value = value + sn.Next = nil + s.Next = sn + return head + } + } else { // Not directly connected and/or values do not match. + next := s.Next + if next != nil { + if pos == next.From-1 && value == next.Value { + next.From = pos + return head + } + // Before next -> New between current and next + if pos < next.From { + sn := sp.Alloc() + sn.From = pos + sn.To = pos + sn.Value = value + sn.Next = next + s.Next = sn + return head + } + } else { // No next -> new at tail + sn := sp.Alloc() + sn.From = pos + sn.To = pos + sn.Value = value + sn.Next = nil + s.Next = sn + return head + } + } + + default: // pos in span -> do not modify. + return head + } + prev = s + } + + return head }