| //go:build !amd64 || appengine || !gc || noasm | |
| package zstd | |
| import ( | |
| "errors" | |
| "fmt" | |
| ) | |
| // buildDtable will build the decoding table. | |
| func (s *fseDecoder) buildDtable() error { | |
| tableSize := uint32(1 << s.actualTableLog) | |
| highThreshold := tableSize - 1 | |
| symbolNext := s.stateTable[:256] | |
| // Init, lay down lowprob symbols | |
| { | |
| for i, v := range s.norm[:s.symbolLen] { | |
| if v == -1 { | |
| s.dt[highThreshold].setAddBits(uint8(i)) | |
| highThreshold-- | |
| v = 1 | |
| } | |
| symbolNext[i] = uint16(v) | |
| } | |
| } | |
| // Spread symbols | |
| { | |
| tableMask := tableSize - 1 | |
| step := tableStep(tableSize) | |
| position := uint32(0) | |
| for ss, v := range s.norm[:s.symbolLen] { | |
| for i := 0; i < int(v); i++ { | |
| s.dt[position].setAddBits(uint8(ss)) | |
| for { | |
| // lowprob area | |
| position = (position + step) & tableMask | |
| if position <= highThreshold { | |
| break | |
| } | |
| } | |
| } | |
| } | |
| if position != 0 { | |
| // position must reach all cells once, otherwise normalizedCounter is incorrect | |
| return errors.New("corrupted input (position != 0)") | |
| } | |
| } | |
| // Build Decoding table | |
| { | |
| tableSize := uint16(1 << s.actualTableLog) | |
| for u, v := range s.dt[:tableSize] { | |
| symbol := v.addBits() | |
| nextState := symbolNext[symbol] | |
| symbolNext[symbol] = nextState + 1 | |
| nBits := s.actualTableLog - byte(highBits(uint32(nextState))) | |
| s.dt[u&maxTableMask].setNBits(nBits) | |
| newState := (nextState << nBits) - tableSize | |
| if newState > tableSize { | |
| return fmt.Errorf("newState (%d) outside table size (%d)", newState, tableSize) | |
| } | |
| if newState == uint16(u) && nBits == 0 { | |
| // Seems weird that this is possible with nbits > 0. | |
| return fmt.Errorf("newState (%d) == oldState (%d) and no bits", newState, u) | |
| } | |
| s.dt[u&maxTableMask].setNewState(newState) | |
| } | |
| } | |
| return nil | |
| } |