blob: e330849450341b38c31cdd3da545b1ac30e45045 [file] [log] [blame]
Nigel Tao03b046d2018-11-17 08:29:48 +11001// Copyright 2018 The Wuffs Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Nigel Tao788479d2021-08-22 10:52:51 +100015//go:build ignore
Nigel Tao03b046d2018-11-17 08:29:48 +110016// +build ignore
17
18package main
19
20// print-crc32-example.go prints the worked examples from std/crc32/README.md.
21//
22// Usage: go run print-crc32-example.go
23
24import (
25 "bytes"
26 "os"
27)
28
29func main() {
30 if err := main1(); err != nil {
31 os.Stderr.WriteString(err.Error() + "\n")
32 os.Exit(1)
33 }
34}
35
36func main1() error {
37 do(false, 4, 0xC, makeBinaryData("H"))
38 os.Stdout.WriteString("\n")
39 do(true, 32, 0xEDB88320, makeBinaryData("Hi\n"))
40 return nil
41}
42
43func bit(b bool) byte {
44 if b {
45 return '1'
46 }
47 return '0'
48}
49
50func hex(b []byte) byte {
51 x := byte(0)
52 x |= (b[0] - '0') << 0
53 x |= (b[1] - '0') << 1
54 x |= (b[2] - '0') << 2
55 x |= (b[3] - '0') << 3
56 if x < 10 {
57 return '0' + x
58 }
59 return 'A' + (x - 10)
60}
61
62func makeBinaryData(data string) []byte {
63 b := make([]byte, len(data)*8)
64 for i := range b {
65 mask := uint8(1) << uint(i&7)
66 b[i] = bit(data[i>>3]&mask != 0)
67 }
68 return b
69}
70
71func makePoly(n int, bits uint64) []byte {
72 b := make([]byte, n+1)
73 b[0] = '1'
74 for i := 0; i < n; i++ {
75 mask := uint64(1) << uint(i)
76 b[i+1] = bit(bits&mask != 0)
77 }
78 return b
79}
80
81func show(prefix string, indent int, binaryData []byte) {
82 const nineSpaces = " "
83 os.Stdout.WriteString(prefix)
84 for ; indent >= 8; indent -= 8 {
85 os.Stdout.WriteString(nineSpaces)
86 }
87 os.Stdout.WriteString(nineSpaces[:indent])
88 for {
89 b, remaining := binaryData, []byte(nil)
90 if len(b) > 8-indent {
91 b, remaining = b[:8-indent], b[8-indent:]
92 indent = 0
93 }
94 os.Stdout.WriteString(string(b))
95 if len(remaining) == 0 {
96 break
97 }
98 os.Stdout.WriteString(" ")
99 binaryData = remaining
100 }
101 os.Stdout.WriteString("\n")
102}
103
104func do(invert bool, polyN int, polyBits uint64, binaryData []byte) {
105 poly := makePoly(polyN, polyBits)
106
107 indent := 0
108 n := len(binaryData)
109 show("input ", 0, binaryData)
110 binaryData = append(binaryData, bytes.Repeat([]byte("0"), polyN)...)
111 show("pad ", 0, binaryData)
112
113 if invert {
114 for i := 0; i < polyN; i++ {
115 binaryData[i] ^= 1
116 }
117 show("invert ", 0, binaryData)
118 }
119
120 for {
121 indent = bytes.IndexByte(binaryData[:n], '1')
122 if indent < 0 {
123 break
124 }
125 show("divisor ", indent, poly)
126 for i := range poly {
127 binaryData[indent+i] = bit(binaryData[indent+i] != poly[i])
128 }
129 show("xor ", 0, binaryData)
130 }
131
132 for i := 0; i < n; i++ {
133 binaryData[i] = ' '
134 }
135 show("remain ", 0, binaryData)
136
137 if invert {
138 for i := 0; i < polyN; i++ {
139 binaryData[n+i] ^= 1
140 }
141 show("invert ", 0, binaryData)
142
143 if polyN&3 == 0 {
144 for i := 0; i < polyN; i += 4 {
145 h := hex(binaryData[n+i : n+i+4])
146 binaryData[n+i+0] = ' '
147 binaryData[n+i+1] = ' '
148 binaryData[n+i+2] = ' '
149 binaryData[n+i+3] = h
150 }
151 show("hex ", 0, binaryData)
152 }
153 }
154}