blob: 7c090f4bcbe5eb9165d14966603eccef6d6d5652 [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
15// +build ignore
16
17package main
18
19// print-crc32-example.go prints the worked examples from std/crc32/README.md.
20//
21// Usage: go run print-crc32-example.go
22
23import (
24 "bytes"
25 "os"
26)
27
28func main() {
29 if err := main1(); err != nil {
30 os.Stderr.WriteString(err.Error() + "\n")
31 os.Exit(1)
32 }
33}
34
35func main1() error {
36 do(false, 4, 0xC, makeBinaryData("H"))
37 os.Stdout.WriteString("\n")
38 do(true, 32, 0xEDB88320, makeBinaryData("Hi\n"))
39 return nil
40}
41
42func bit(b bool) byte {
43 if b {
44 return '1'
45 }
46 return '0'
47}
48
49func hex(b []byte) byte {
50 x := byte(0)
51 x |= (b[0] - '0') << 0
52 x |= (b[1] - '0') << 1
53 x |= (b[2] - '0') << 2
54 x |= (b[3] - '0') << 3
55 if x < 10 {
56 return '0' + x
57 }
58 return 'A' + (x - 10)
59}
60
61func makeBinaryData(data string) []byte {
62 b := make([]byte, len(data)*8)
63 for i := range b {
64 mask := uint8(1) << uint(i&7)
65 b[i] = bit(data[i>>3]&mask != 0)
66 }
67 return b
68}
69
70func makePoly(n int, bits uint64) []byte {
71 b := make([]byte, n+1)
72 b[0] = '1'
73 for i := 0; i < n; i++ {
74 mask := uint64(1) << uint(i)
75 b[i+1] = bit(bits&mask != 0)
76 }
77 return b
78}
79
80func show(prefix string, indent int, binaryData []byte) {
81 const nineSpaces = " "
82 os.Stdout.WriteString(prefix)
83 for ; indent >= 8; indent -= 8 {
84 os.Stdout.WriteString(nineSpaces)
85 }
86 os.Stdout.WriteString(nineSpaces[:indent])
87 for {
88 b, remaining := binaryData, []byte(nil)
89 if len(b) > 8-indent {
90 b, remaining = b[:8-indent], b[8-indent:]
91 indent = 0
92 }
93 os.Stdout.WriteString(string(b))
94 if len(remaining) == 0 {
95 break
96 }
97 os.Stdout.WriteString(" ")
98 binaryData = remaining
99 }
100 os.Stdout.WriteString("\n")
101}
102
103func do(invert bool, polyN int, polyBits uint64, binaryData []byte) {
104 poly := makePoly(polyN, polyBits)
105
106 indent := 0
107 n := len(binaryData)
108 show("input ", 0, binaryData)
109 binaryData = append(binaryData, bytes.Repeat([]byte("0"), polyN)...)
110 show("pad ", 0, binaryData)
111
112 if invert {
113 for i := 0; i < polyN; i++ {
114 binaryData[i] ^= 1
115 }
116 show("invert ", 0, binaryData)
117 }
118
119 for {
120 indent = bytes.IndexByte(binaryData[:n], '1')
121 if indent < 0 {
122 break
123 }
124 show("divisor ", indent, poly)
125 for i := range poly {
126 binaryData[indent+i] = bit(binaryData[indent+i] != poly[i])
127 }
128 show("xor ", 0, binaryData)
129 }
130
131 for i := 0; i < n; i++ {
132 binaryData[i] = ' '
133 }
134 show("remain ", 0, binaryData)
135
136 if invert {
137 for i := 0; i < polyN; i++ {
138 binaryData[n+i] ^= 1
139 }
140 show("invert ", 0, binaryData)
141
142 if polyN&3 == 0 {
143 for i := 0; i < polyN; i += 4 {
144 h := hex(binaryData[n+i : n+i+4])
145 binaryData[n+i+0] = ' '
146 binaryData[n+i+1] = ' '
147 binaryData[n+i+2] = ' '
148 binaryData[n+i+3] = h
149 }
150 show("hex ", 0, binaryData)
151 }
152 }
153}