| // Copyright 2011 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package bzip2 |
| |
| // moveToFrontDecoder implements a move-to-front list. Such a list is an |
| // efficient way to transform a string with repeating elements into one with |
| // many small valued numbers, which is suitable for entropy encoding. It works |
| // by starting with an initial list of symbols and references symbols by their |
| // index into that list. When a symbol is referenced, it's moved to the front |
| // of the list. Thus, a repeated symbol ends up being encoded with many zeros, |
| // as the symbol will be at the front of the list after the first access. |
| type moveToFrontDecoder struct { |
| // Rather than actually keep the list in memory, the symbols are stored |
| // as a circular, double linked list with the symbol indexed by head |
| // at the front of the list. |
| symbols []byte |
| next []uint8 |
| prev []uint8 |
| head uint8 |
| } |
| |
| // newMTFDecoder creates a move-to-front decoder with an explicit initial list |
| // of symbols. |
| func newMTFDecoder(symbols []byte) *moveToFrontDecoder { |
| if len(symbols) > 256 { |
| panic("too many symbols") |
| } |
| |
| m := &moveToFrontDecoder{ |
| symbols: symbols, |
| next: make([]uint8, len(symbols)), |
| prev: make([]uint8, len(symbols)), |
| } |
| |
| m.threadLinkedList() |
| return m |
| } |
| |
| // newMTFDecoderWithRange creates a move-to-front decoder with an initial |
| // symbol list of 0...n-1. |
| func newMTFDecoderWithRange(n int) *moveToFrontDecoder { |
| if n > 256 { |
| panic("newMTFDecoderWithRange: cannot have > 256 symbols") |
| } |
| |
| m := &moveToFrontDecoder{ |
| symbols: make([]uint8, n), |
| next: make([]uint8, n), |
| prev: make([]uint8, n), |
| } |
| |
| for i := 0; i < n; i++ { |
| m.symbols[i] = byte(i) |
| } |
| |
| m.threadLinkedList() |
| return m |
| } |
| |
| // threadLinkedList creates the initial linked-list pointers. |
| func (m *moveToFrontDecoder) threadLinkedList() { |
| if len(m.symbols) == 0 { |
| return |
| } |
| |
| m.prev[0] = uint8(len(m.symbols) - 1) |
| |
| for i := 0; i < len(m.symbols)-1; i++ { |
| m.next[i] = uint8(i + 1) |
| m.prev[i+1] = uint8(i) |
| } |
| |
| m.next[len(m.symbols)-1] = 0 |
| } |
| |
| func (m *moveToFrontDecoder) Decode(n int) (b byte) { |
| // Most of the time, n will be zero so it's worth dealing with this |
| // simple case. |
| if n == 0 { |
| return m.symbols[m.head] |
| } |
| |
| i := m.head |
| for j := 0; j < n; j++ { |
| i = m.next[i] |
| } |
| b = m.symbols[i] |
| |
| m.next[m.prev[i]] = m.next[i] |
| m.prev[m.next[i]] = m.prev[i] |
| m.next[i] = m.head |
| m.prev[i] = m.prev[m.head] |
| m.next[m.prev[m.head]] = i |
| m.prev[m.head] = i |
| m.head = i |
| |
| return |
| } |
| |
| // First returns the symbol at the front of the list. |
| func (m *moveToFrontDecoder) First() byte { |
| return m.symbols[m.head] |
| } |