diff --git a/common/spans.go b/common/spans.go new file mode 100644 index 0000000..10d1cbb --- /dev/null +++ b/common/spans.go @@ -0,0 +1,89 @@ +// Copyright 2014 by Sascha L. Teichmann +// Use of this source code is governed by the MIT license +// that can be found in the LICENSE file. + +package common + +const chunkSize = 1024 + +type Span struct { + Value int32 + From int32 + To int32 + Next *Span +} + +type SpanPool struct { + freeList *Span +} + +func NewSpanPool() *SpanPool { + return &SpanPool{} +} + +func (sp *SpanPool) Alloc() *Span { + if sp.freeList != nil { + next := sp.freeList + sp.freeList = next.Next + return next + } + + spans := make([]Span, chunkSize) + + for i := chunkSize - 1; i > 0; i-- { + spans[i].Next = sp.freeList + sp.freeList = &spans[i] + } + + return &spans[0] +} + +func (sp *SpanPool) Free(s *Span) { + if s != nil { + s.Next = sp.freeList + sp.freeList = s + } +} + +func (sp *SpanPool) FreeAll(s *Span) { + if s == nil { + return + } + head, prev := s, s + for ; s != nil; s = s.Next { + prev = s + } + prev.Next = sp.freeList + sp.freeList = head +} + +func (sp *SpanPool) Insert(s *Span, pos, value int32) *Span { + + if s == nil { + s = sp.Alloc() + s.From = pos + s.To = pos + s.Value = value + s.Next = nil + return s + } + + if pos < s.From { + // Same value and directly neighbored -> extend head. + if value == s.Value && pos == s.From-1 { + s.From-- + return s + } + // Disjunct -> create new. + prev := sp.Alloc() + prev.From = pos + prev.To = pos + prev.Value = value + prev.Next = s + return prev + } + + // TODO: Implement the more complicated cases. + + return nil +}