11package com.eignex.kencode
22
3+ /* *
4+ * Shared CRC digest engine parameterized by width (up to 32 bits).
5+ * Uses Long arithmetic throughout to handle both 16-bit and 32-bit cases uniformly.
6+ */
7+ private class CrcEngine (
8+ poly : Int ,
9+ init : Int ,
10+ private val refin : Boolean ,
11+ private val refout : Boolean ,
12+ xorOut : Int ,
13+ private val width : Int
14+ ) {
15+ private val mask: Long = if (width == 32 ) 0xFFFFFFFFL else (1L shl width) - 1L
16+ private val refPoly: Long = poly.reverseBits(width).toLong() and mask
17+ private val refInit: Long = init .reverseBits(width).toLong() and mask
18+ private val xorOutL: Long = xorOut.toLong() and mask
19+
20+ val size: Int = (width + 7 ) / 8
21+
22+ fun digest (data : ByteArray ): ByteArray {
23+ var crc = refInit
24+ for (b in data) {
25+ val raw = b.toInt() and 0xFF
26+ val byte = if (refin) raw else raw.reverseBits8()
27+ crc = crc xor byte.toLong()
28+ repeat(8 ) {
29+ crc = if ((crc and 1L ) != 0L ) (crc ushr 1 ) xor refPoly else crc ushr 1
30+ }
31+ crc = crc and mask
32+ }
33+ var finalCrc = if (refout) crc else crc.toInt().reverseBits(width).toLong() and mask
34+ finalCrc = (finalCrc xor xorOutL) and mask
35+ return ByteArray (size) { i ->
36+ val shift = 8 * (size - 1 - i)
37+ ((finalCrc ushr shift) and 0xFFL ).toByte()
38+ }
39+ }
40+ }
41+
42+ /* *
43+ * CRC-8 implementation with configurable polynomial and parameters.
44+ *
45+ * Default configuration implements CRC-8/SMBUS.
46+ *
47+ * Parameters:
48+ * @param poly generator polynomial (high bit implicit).
49+ * @param init initial CRC register value.
50+ * @param refin whether to reflect bits of each input byte.
51+ * @param refout whether to reflect the final CRC value.
52+ * @param xorOut final XOR mask.
53+ *
54+ * Output:
55+ * - Returned as a single-byte array.
56+ */
57+ open class Crc8 (
58+ poly : Int = 0x07 ,
59+ init : Int = 0x00 ,
60+ refin : Boolean = false ,
61+ refout : Boolean = false ,
62+ xorOut : Int = 0x00
63+ ) : Checksum {
64+
65+ companion object Default : Crc8()
66+
67+ private val engine = CrcEngine (poly, init , refin, refout, xorOut, width = 8 )
68+
69+ override val size: Int get() = engine.size
70+
71+ override fun digest (data : ByteArray ): ByteArray = engine.digest(data)
72+ }
73+
374/* *
475 * CRC-16 implementation with configurable polynomial and parameters.
576 *
@@ -20,54 +91,19 @@ package com.eignex.kencode
2091open class Crc16 (
2192 poly : Int = 0x1021 ,
2293 init : Int = 0xFFFF ,
23- private val refin : Boolean = true ,
24- private val refout : Boolean = true ,
25- private val xorOut : Int = 0xFFFF ,
26- private val width : Int = 16
94+ refin : Boolean = true ,
95+ refout : Boolean = true ,
96+ xorOut : Int = 0xFFFF ,
97+ width : Int = 16
2798) : Checksum {
2899
29100 companion object Default : Crc16()
30101
31- private val mask = (1 shl width) - 1
32-
33- // Internal representation is reflected (LSB-first),
34- // so pre-reflect poly and init.
35- private val refPoly: Int = poly.reverseBits(width)
36- private val refInit: Int = init .reverseBits(width)
37-
38- override val size: Int = (width + 7 ) / 8
39-
40- override fun digest (data : ByteArray ): ByteArray {
41- var crc = refInit and mask
42-
43- for (i in data.indices) {
44- val raw = data[i].toInt() and 0xFF
45- val b = if (refin) raw else raw.reverseBits8()
46-
47- crc = crc xor b
48- repeat(8 ) {
49- crc = if ((crc and 1 ) != 0 ) {
50- (crc ushr 1 ) xor refPoly
51- } else {
52- crc ushr 1
53- }
54- }
55- crc = crc and mask
56- }
57-
58- // Convert from internal reflected form to requested output form.
59- crc = if (refout) crc else crc.reverseBits(width)
102+ private val engine = CrcEngine (poly, init , refin, refout, xorOut, width)
60103
61- crc = (crc xor xorOut) and mask
104+ override val size : Int get() = engine.size
62105
63- // Output big-endian (high byte first).
64- val out = ByteArray (size)
65- for (i in 0 until size) {
66- val shift = 8 * (size - 1 - i)
67- out [i] = ((crc ushr shift) and 0xFF ).toByte()
68- }
69- return out
70- }
106+ override fun digest (data : ByteArray ): ByteArray = engine.digest(data)
71107}
72108
73109/* *
@@ -88,58 +124,21 @@ open class Crc16(
88124 * - Internal representation uses reflected form.
89125 */
90126open class Crc32 (
91- poly : Int = 0x04C11DB7 , // canonical CRC-32 poly
127+ poly : Int = 0x04C11DB7 ,
92128 init : Int = 0xFFFFFFFF .toInt(),
93- private val refin : Boolean = true ,
94- private val refout : Boolean = true ,
95- private val xorOut : Int = 0xFFFFFFFF .toInt(),
96- private val width : Int = 32
129+ refin : Boolean = true ,
130+ refout : Boolean = true ,
131+ xorOut : Int = 0xFFFFFFFF .toInt(),
132+ width : Int = 32
97133) : Checksum {
98134
99135 companion object Default : Crc32()
100136
101- private val mask: Long = if (width == 32 ) 0xFFFFFFFFL
102- else (1L shl width) - 1L
103-
104- // Internal representation: reflected
105- private val refPoly: Long = poly.reverseBits(width).toLong() and mask
106- private val refInit: Long = init .reverseBits(width).toLong() and mask
107-
108- override val size: Int = (width + 7 ) / 8
109-
110- override fun digest (data : ByteArray ): ByteArray {
111- var crc = refInit
112-
113- for (i in data.indices) {
114- val raw = data[i].toInt() and 0xFF
115- val b = if (refin) raw else raw.reverseBits8()
116-
117- crc = crc xor (b.toLong() and 0xFFL )
118- repeat(8 ) {
119- crc = if ((crc and 1L ) != 0L ) {
120- (crc ushr 1 ) xor refPoly
121- } else {
122- crc ushr 1
123- }
124- }
125- crc = crc and mask
126- }
127-
128- var finalCrc = if (refout) {
129- crc
130- } else {
131- crc.toInt().reverseBits(width).toLong() and mask
132- }
137+ private val engine = CrcEngine (poly, init , refin, refout, xorOut, width)
133138
134- finalCrc = (finalCrc xor (xorOut.toLong() and mask)) and mask
139+ override val size : Int get() = engine.size
135140
136- val out = ByteArray (size)
137- for (i in 0 until size) {
138- val shift = 8 * (size - 1 - i)
139- out [i] = ((finalCrc ushr shift) and 0xFFL ).toByte()
140- }
141- return out
142- }
141+ override fun digest (data : ByteArray ): ByteArray = engine.digest(data)
143142}
144143
145144/* * Bit helpers */
0 commit comments