blob: 7c090f4bcbe5eb9165d14966603eccef6d6d5652 [file] [log] [blame]
// Copyright 2018 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build ignore
package main
// print-crc32-example.go prints the worked examples from std/crc32/README.md.
//
// Usage: go run print-crc32-example.go
import (
"bytes"
"os"
)
func main() {
if err := main1(); err != nil {
os.Stderr.WriteString(err.Error() + "\n")
os.Exit(1)
}
}
func main1() error {
do(false, 4, 0xC, makeBinaryData("H"))
os.Stdout.WriteString("\n")
do(true, 32, 0xEDB88320, makeBinaryData("Hi\n"))
return nil
}
func bit(b bool) byte {
if b {
return '1'
}
return '0'
}
func hex(b []byte) byte {
x := byte(0)
x |= (b[0] - '0') << 0
x |= (b[1] - '0') << 1
x |= (b[2] - '0') << 2
x |= (b[3] - '0') << 3
if x < 10 {
return '0' + x
}
return 'A' + (x - 10)
}
func makeBinaryData(data string) []byte {
b := make([]byte, len(data)*8)
for i := range b {
mask := uint8(1) << uint(i&7)
b[i] = bit(data[i>>3]&mask != 0)
}
return b
}
func makePoly(n int, bits uint64) []byte {
b := make([]byte, n+1)
b[0] = '1'
for i := 0; i < n; i++ {
mask := uint64(1) << uint(i)
b[i+1] = bit(bits&mask != 0)
}
return b
}
func show(prefix string, indent int, binaryData []byte) {
const nineSpaces = " "
os.Stdout.WriteString(prefix)
for ; indent >= 8; indent -= 8 {
os.Stdout.WriteString(nineSpaces)
}
os.Stdout.WriteString(nineSpaces[:indent])
for {
b, remaining := binaryData, []byte(nil)
if len(b) > 8-indent {
b, remaining = b[:8-indent], b[8-indent:]
indent = 0
}
os.Stdout.WriteString(string(b))
if len(remaining) == 0 {
break
}
os.Stdout.WriteString(" ")
binaryData = remaining
}
os.Stdout.WriteString("\n")
}
func do(invert bool, polyN int, polyBits uint64, binaryData []byte) {
poly := makePoly(polyN, polyBits)
indent := 0
n := len(binaryData)
show("input ", 0, binaryData)
binaryData = append(binaryData, bytes.Repeat([]byte("0"), polyN)...)
show("pad ", 0, binaryData)
if invert {
for i := 0; i < polyN; i++ {
binaryData[i] ^= 1
}
show("invert ", 0, binaryData)
}
for {
indent = bytes.IndexByte(binaryData[:n], '1')
if indent < 0 {
break
}
show("divisor ", indent, poly)
for i := range poly {
binaryData[indent+i] = bit(binaryData[indent+i] != poly[i])
}
show("xor ", 0, binaryData)
}
for i := 0; i < n; i++ {
binaryData[i] = ' '
}
show("remain ", 0, binaryData)
if invert {
for i := 0; i < polyN; i++ {
binaryData[n+i] ^= 1
}
show("invert ", 0, binaryData)
if polyN&3 == 0 {
for i := 0; i < polyN; i += 4 {
h := hex(binaryData[n+i : n+i+4])
binaryData[n+i+0] = ' '
binaryData[n+i+1] = ' '
binaryData[n+i+2] = ' '
binaryData[n+i+3] = h
}
show("hex ", 0, binaryData)
}
}
}