-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
crc-8, crc-16 and crc-32 implementations
- Loading branch information
Showing
26 changed files
with
749 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// | ||
// CRC16.swift | ||
// | ||
// Copyright © 2020 QuickBird Studios. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
let crc16 = CRC16() | ||
|
||
crc16.currentValue // initial value is 0 | ||
crc16.append(1.0) | ||
crc16.append(1) // we are passing integer (If you want to pass UInt8, see the line below) | ||
crc16.append(UInt8(1)) | ||
crc16.append([1, 20]) // We are passing [UInt8] (because that is the only type of array the append method accepts) | ||
|
||
// get the current crc value | ||
crc16.currentValue | ||
|
||
// append more | ||
crc16.append(5.6) | ||
crc16.append(225) | ||
|
||
// get the current crc value | ||
crc16.currentValue | ||
|
||
// reset the crc value | ||
crc16.reset() | ||
|
||
crc16.currentValue // value is 0 after reset | ||
|
||
|
||
// CRC16's lookup table | ||
crc16.lookupTable | ||
|
||
// CRC16's lookup table (hexadecimal representation) | ||
let lookupTableHexa = crc16.lookupTable.map { String($0, radix: 16) } | ||
lookupTableHexa |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// | ||
// CRC.swift | ||
// | ||
// Copyright © 2020 QuickBird Studios. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
public protocol CRC { | ||
associatedtype Size | ||
|
||
var currentValue: Size { get } | ||
|
||
func append(_ bytes: [UInt8]) | ||
|
||
func reset() | ||
} | ||
|
||
extension CRC { | ||
public func append(_ byte: UInt8) { | ||
append([byte]) | ||
} | ||
|
||
public func append<T: FixedWidthInteger>(_ integer: T) { | ||
append(integer.bigEndianBytes) | ||
} | ||
|
||
public func append<T: BinaryFloatingPoint>(_ floatingPoint: T) { | ||
append(floatingPoint.bigEndianBytes) | ||
} | ||
} | ||
|
||
extension FixedWidthInteger { | ||
public var bigEndianBytes: [UInt8] { | ||
[UInt8](withUnsafeBytes(of: self.bigEndian) { Data($0) }) | ||
} | ||
} | ||
|
||
// Please keep in mind that Float has different representations and you need to make sure | ||
// you are using the same representation as the system you are communicating with | ||
extension BinaryFloatingPoint { | ||
public var bigEndianBytes: [UInt8] { | ||
[UInt8](withUnsafeBytes(of: self) { Data($0) }).reversed() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// | ||
// CRC16.swift | ||
// | ||
// Copyright © 2020 QuickBird Studios. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Class to conveniently calculate CRC-16. It uses the CRC16-CCITT polynomial (0x1021) by default | ||
public class CRC16: CRC { | ||
|
||
/// The table that stores the precomputed remainders for all possible divisions for 1 byte | ||
/// This table is used as a lookup (to speed up the calculation) | ||
public let lookupTable: [UInt16] | ||
|
||
private(set) public var currentValue: UInt16 = 0 | ||
|
||
/// Creates the instance for calculating CRC | ||
/// - Parameter polynomial: The polynomial to use. It uses CRC16-CCITT's polynomial (0x1021) by default | ||
public init(polynomial: UInt16 = 0x1021) { | ||
/// Generates the lookup table (make sure to generate it only once) | ||
self.lookupTable = (0...255).map { Self.crc16(for: UInt8($0), polynomial: polynomial) } | ||
} | ||
|
||
public func append(_ bytes: [UInt8]) { | ||
currentValue = crc16(for: bytes, initialValue: currentValue) | ||
} | ||
|
||
public func reset() { | ||
currentValue = 0 | ||
} | ||
} | ||
|
||
/// Same code as the blog article | ||
extension CRC16 { | ||
/// Caculates CRC-16 of an array of Bytes (UInt8) | ||
private func crc16(for inputs: [UInt8], initialValue: UInt16 = 0) -> UInt16 { | ||
inputs.reduce(initialValue) { remainder, byte in | ||
let bigEndianInput = UInt16(byte).bigEndian | ||
let index = (bigEndianInput ^ remainder) >> 8 | ||
return lookupTable[Int(index)] ^ (remainder << 8) | ||
} | ||
} | ||
|
||
/// Calculates the CRC-16 of 1 Byte | ||
private static func crc16(for input: UInt8, polynomial: UInt16) -> UInt16 { | ||
var result = UInt16(input).bigEndian | ||
for _ in 0..<8 { | ||
let isMostSignificantBitOne = result & 0x8000 != 0 | ||
|
||
result = result << 1 | ||
|
||
if isMostSignificantBitOne { | ||
result = result ^ polynomial | ||
} | ||
} | ||
|
||
return result | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
<playground version='5.0' target-platform='ios' buildActiveScheme='true'> | ||
<timeline fileName='timeline.xctimeline'/> | ||
</playground> |
7 changes: 7 additions & 0 deletions
7
Playgrounds/CRC16.playground/playground.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
8 changes: 8 additions & 0 deletions
8
Playgrounds/CRC16.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>IDEDidComputeMac32BitWarning</key> | ||
<true/> | ||
</dict> | ||
</plist> |
16 changes: 16 additions & 0 deletions
16
Playgrounds/CRC16.playground/xcuserdata/nasir.xcuserdatad/xcschemes/xcschememanagement.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>SchemeUserState</key> | ||
<dict> | ||
<key>CRC16 (Playground).xcscheme</key> | ||
<dict> | ||
<key>isShown</key> | ||
<false/> | ||
<key>orderHint</key> | ||
<integer>0</integer> | ||
</dict> | ||
</dict> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// | ||
// CRC32.playground | ||
// | ||
// Copyright © 2020 QuickBird Studios. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
let crc32 = CRC32() | ||
|
||
crc32.currentValue // initial value is 0 | ||
crc32.append(1.0) | ||
crc32.append(1) // we are passing integer (If you want to pass UInt8, see the line below) | ||
crc32.append(UInt8(1)) | ||
crc32.append([1, 20]) // We are passing [UInt8] (because that is the only type of array the append method accepts) | ||
|
||
// get the current crc value | ||
crc32.currentValue | ||
|
||
// append more | ||
crc32.append(5.6) | ||
crc32.append(225) | ||
|
||
// get the current crc value | ||
crc32.currentValue | ||
|
||
// reset the crc value | ||
crc32.reset() | ||
|
||
crc32.currentValue // value is 0 after reset | ||
|
||
|
||
// CRC32's lookup table | ||
crc32.lookupTable | ||
|
||
// CRC32's lookup table (hexadecimal representation) | ||
let lookupTableHexa = crc32.lookupTable.map { String($0, radix: 16) } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// | ||
// CRC.swift | ||
// | ||
// Copyright © 2020 QuickBird Studios. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
public protocol CRC { | ||
associatedtype Size | ||
|
||
var currentValue: Size { get } | ||
|
||
func append(_ bytes: [UInt8]) | ||
|
||
func reset() | ||
} | ||
|
||
extension CRC { | ||
public func append(_ byte: UInt8) { | ||
append([byte]) | ||
} | ||
|
||
public func append<T: FixedWidthInteger>(_ integer: T) { | ||
append(integer.bigEndianBytes) | ||
} | ||
|
||
public func append<T: BinaryFloatingPoint>(_ floatingPoint: T) { | ||
append(floatingPoint.bigEndianBytes) | ||
} | ||
} | ||
|
||
// MARK: - Convenience Extension Methods | ||
|
||
extension FixedWidthInteger { | ||
public var bigEndianBytes: [UInt8] { | ||
[UInt8](withUnsafeBytes(of: self.bigEndian) { Data($0) }) | ||
} | ||
} | ||
|
||
// `BinaryFloatingPoint` conforms to 754-2008 - IEEE Standard for Floating-Point Arithmetic (https://ieeexplore.ieee.org/document/4610935) | ||
// If you target system is using a different floating point representation, you need to adapt accordingly | ||
extension BinaryFloatingPoint { | ||
public var bigEndianBytes: [UInt8] { | ||
[UInt8](withUnsafeBytes(of: self) { Data($0) }).reversed() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// | ||
// CRC32.swift | ||
// | ||
// Copyright © 2020 QuickBird Studios. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Class to conveniently calculate CRC-32 It uses the CRC32 polynomial (0x04C11DB7) by default | ||
public class CRC32: CRC { | ||
|
||
/// The table that stores the precomputed remainders for all possible divisions for 1 byte | ||
/// This table is used as a lookup (to speed up the calculation) | ||
public let lookupTable: [UInt32] | ||
|
||
private(set) public var currentValue: UInt32 = 0 | ||
|
||
/// Creates the instance for calculating CRC | ||
/// - Parameter polynomial: The polynomial to use. It uses CRC32's polynomial (0x04C11DB7) by default | ||
public init(polynomial: UInt32 = 0x04C11DB7) { | ||
/// Generates the lookup table (make sure to generate it only once) | ||
self.lookupTable = (0...255).map { Self.crc32(for: UInt8($0), polynomial: polynomial) } | ||
} | ||
|
||
public func append(_ bytes: [UInt8]) { | ||
currentValue = crc32(for: bytes, initialValue: currentValue) | ||
} | ||
|
||
public func reset() { | ||
currentValue = 0 | ||
} | ||
} | ||
|
||
extension CRC32 { | ||
/// Caculates CRC-32 of an array of Bytes (UInt8) | ||
private func crc32(for inputs: [UInt8], initialValue: UInt32 = 0) -> UInt32 { | ||
inputs.reduce(initialValue) { remainder, byte in | ||
let bigEndianInput = UInt32(byte).bigEndian | ||
let index = (bigEndianInput ^ remainder) >> 24 | ||
return lookupTable[Int(index)] ^ (remainder << 8) | ||
} | ||
} | ||
|
||
/// Calculates the CRC-32 of 1 Byte | ||
private static func crc32(for input: UInt8, polynomial: UInt32) -> UInt32 { | ||
var result = UInt32(input).bigEndian | ||
for _ in 0..<8 { | ||
let isMostSignificantBitOne = result & 0x80000000 != 0 | ||
|
||
result = result << 1 | ||
|
||
if isMostSignificantBitOne { | ||
result = result ^ polynomial | ||
} | ||
} | ||
|
||
return result | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
<playground version='5.0' target-platform='ios' buildActiveScheme='true'> | ||
<timeline fileName='timeline.xctimeline'/> | ||
</playground> |
7 changes: 7 additions & 0 deletions
7
Playgrounds/CRC32.playground/playground.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
8 changes: 8 additions & 0 deletions
8
Playgrounds/CRC32.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>IDEDidComputeMac32BitWarning</key> | ||
<true/> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// | ||
// CRC8.playground | ||
// | ||
// Copyright © 2020 QuickBird Studios. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
let crc8 = CRC8() | ||
|
||
crc8.currentValue // initial value is 0 | ||
crc8.append(1.0) | ||
crc8.append(1) // we are passing integer (If you want to pass UInt8, see the line below) | ||
crc8.append(UInt8(1)) | ||
crc8.append([1, 20]) // We are passing [UInt8] (because that is the only type of array the append method accepts) | ||
|
||
// get the current crc value | ||
crc8.currentValue | ||
|
||
// append more | ||
crc8.append(5.6) | ||
crc8.append(225) | ||
|
||
// get the current crc value | ||
crc8.currentValue | ||
|
||
// reset the crc value | ||
crc8.reset() | ||
|
||
crc8.currentValue // value is 0 after reset | ||
|
||
|
||
// CRC8's lookup table | ||
crc8.lookupTable | ||
|
||
// CRC8's lookup table (hexadecimal representation) | ||
let lookupTableHexa = crc8.lookupTable.map { String($0, radix: 16) } | ||
lookupTableHexa |
Oops, something went wrong.