From 05410d240f4c5146f1236e33504baf8bf437efdc Mon Sep 17 00:00:00 2001 From: fwcd Date: Tue, 25 Feb 2020 01:39:06 +0100 Subject: [PATCH] Fix compilation issues --- swift/Sources/QRCodeGenerator/BitBuffer.swift | 4 +- swift/Sources/QRCodeGenerator/QRCode.swift | 98 ++++++++++--------- .../QRCodeGenerator/QRCodeMiscellaneous.swift | 4 +- swift/Sources/QRCodeGenerator/QRSegment.swift | 27 ++--- 4 files changed, 69 insertions(+), 64 deletions(-) diff --git a/swift/Sources/QRCodeGenerator/BitBuffer.swift b/swift/Sources/QRCodeGenerator/BitBuffer.swift index ea648e2..52afed9 100644 --- a/swift/Sources/QRCodeGenerator/BitBuffer.swift +++ b/swift/Sources/QRCodeGenerator/BitBuffer.swift @@ -26,7 +26,7 @@ public struct BitBuffer { public var bits: [Bool] public var count: UInt { UInt(bits.count) } - public init(bits: [Bool]) { + public init(_ bits: [Bool] = []) { self.bits = bits } @@ -35,6 +35,6 @@ public struct BitBuffer { /// Requires len ≤ 31 and val < 2len. public mutating func appendBits(_ value: UInt32, _ length: Int) { assert(length <= 31 && (value >> length) == 0, "Value out of range") - bits.append((0.. Self { - let segs = [QRSegment.make(bytes: data)] + let segs = [QRSegment.makeBytes(data)] return try QRCode.encode(segments: segs, ecl: ecl) } @@ -111,13 +111,14 @@ struct QRCode { /// long to fit in any version in the given range at the given ECC level. public static func encodeAdvanced(segments: [QRSegment], ecl: QRCodeECC, minVersion: QRCodeVersion, maxVersion: QRCodeVersion, mask: QRCodeMask? = nil, boostECL: Bool) throws -> Self { assert(minVersion <= maxVersion, "Invalid value") + var mutECL = ecl // Find the minimal version number to use var version = minVersion var dataUsedBits: UInt! while true { // Number of data bits available - let dataCapacityBits: UInt = QRCode.getNumDataCodewords(version: version, ecl: ecl) * 8 + let dataCapacityBits: UInt = QRCode.getNumDataCodewords(version: version, ecl: mutECL) * 8 let dataUsed: UInt? = QRSegment.getTotalBits(segments: segments, version: version) if let used = dataUsed, used <= dataCapacityBits { // The version number is found to be suitable @@ -130,6 +131,7 @@ struct QRCode { } else { msg = "Segment too long" } + throw QRCodeError.dataTooLong(msg) } else { version = QRCodeVersion(version.value + 1) } @@ -138,34 +140,34 @@ struct QRCode { // Increase error correction level while the data still fits in the current version number for newECL in [QRCodeECC.medium, QRCodeECC.quartile, QRCodeECC.high] { if boostECL && dataUsedBits <= QRCode.getNumDataCodewords(version: version, ecl: newECL) * 8 { - ecl = newECL + mutECL = newECL } } // Concatenate all segments to create the data bit string var bb = BitBuffer() for seg in segments { - bb.appendBits(seg.mode.modeBits(), 4) - bb.appendBits(UInt32(seg.numChars), seg.mode.numCharCountBits(version: version)) - bb.values += seg.data + bb.appendBits(seg.mode.modeBits, 4) + bb.appendBits(UInt32(seg.numChars), Int(seg.mode.numCharCountBits(version: version))) + bb.bits += seg.data } assert(bb.count == dataUsedBits) // Add terminator and pad up to a byte if applicable - let dataCapacityBits: UInt = QRCode.getNumDataCodewords(version: version, ecl: ecl) + let dataCapacityBits: UInt = QRCode.getNumDataCodewords(version: version, ecl: mutECL) assert(bb.count <= dataCapacityBits) var numZeroBits = min(4, dataCapacityBits - bb.count) - bb.appendBits(0, UInt8(numZeroBits)) + bb.appendBits(0, Int(numZeroBits)) numZeroBits = (0 &- bb.count) & 7 - bb.appendBits(0, UInt8(numZeroBits)) + bb.appendBits(0, Int(numZeroBits)) assert(bb.count % 8 == 0) // Pad with alternating bytes until data capacity is reached let padBytes = [0xEC, 0x11] var i = 0 while bb.count < dataCapacityBits { - bb.appendBits(padBytes[i], 8) + bb.appendBits(UInt32(padBytes[i]), 8) i += 1 if i >= padBytes.count { i = 0 @@ -173,13 +175,13 @@ struct QRCode { } // Pack bits into bytes in big endian - var dataCodeWords = [UInt8](repeating: 0, bb.count / 8) - for (i, bit) in bb.values.enumerated() { - dataCodeWords[i >> 3] |= UInt8(bit) << (7 - (i & 7)) + var dataCodeWords = [UInt8](repeating: 0, count: Int(bb.count / 8)) + for (i, bit) in bb.bits.enumerated() { + dataCodeWords[i >> 3] |= (bit ? 1 : 0) << (7 - (i & 7)) } // Create the QRCode object - return QRCode.encodeCodewords(version: version, ecl: ecl, dataCodeWords: dataCodeWords, mask: mask) + return QRCode.encodeCodewords(version: version, ecl: mutECL, dataCodeWords: dataCodeWords, mask: mask) } /*---- Constructor (low level) ----*/ @@ -197,25 +199,25 @@ struct QRCode { var result = Self( version: version, size: Int(size), - mask: QRCodeMask(0), // Dummy value errorCorrectionLevel: ecl, - modules: Array(repeating: false, count: size * size), // Initially all white - isFunction: Array(repeating: false, count: size * size) + mask: QRCodeMask(0), // Dummy value + modules: Array(repeating: false, count: Int(size * size)), // Initially all white + isFunction: Array(repeating: false, count: Int(size * size)) ) // Compute ECC, draw modules result.drawFunctionPatterns() - let allCodeWords = result.addECCAndInterleave(dataCodeWords: dataCodeWords) + let allCodeWords = result.addECCAndInterleave(data: dataCodeWords) result.drawCodewords(data: allCodeWords) // Do masking - if mask == nil { // Automatically choose best mask + if mutMask == nil { // Automatically choose best mask var minPenalty = Int32.max for i in UInt8(0)..<8 { let newMask = QRCodeMask(i) result.apply(mask: newMask) result.drawFormatBits(mask: newMask) - let penalty = result.getPenaltyScore() + let penalty = Int32(result.getPenaltyScore()) if penalty < minPenalty { mutMask = newMask minPenalty = penalty @@ -223,10 +225,10 @@ struct QRCode { result.apply(mask: newMask) // Undoes mask due to XOR } } - let mask: QRCodeMask = mask! - result.mask = mask - result.apply(mask: mask) // Apply the final choice of mask - result.drawFormatBits(mask: mask) + let resMask: QRCodeMask = mutMask! + result.mask = resMask + result.apply(mask: resMask) // Apply the final choice of mask + result.drawFormatBits(mask: resMask) result.isFunction = [] return result @@ -265,7 +267,7 @@ struct QRCode { : "" } } - var result = """ + return """ @@ -274,7 +276,6 @@ struct QRCode { """ - return result } /*---- Private helper methods for constructor: Drawing function modules ----*/ @@ -315,30 +316,30 @@ struct QRCode { // Calculate error correction code and pack bits // Error correction level is uint2, mask is uint3 - let data: UInt32 = errorCorrectionLevel.formatBits() << 3 | UInt32(mask.value) + let data: UInt32 = errorCorrectionLevel.formatBits << 3 | UInt32(mask.value) var rem: UInt32 = data for _ in 0..<10 { - rem = (rem << 1) ^ ((rem > 9) * 0x537) + rem = (rem << 1) ^ ((rem >> 9) * 0x537) } let bits: UInt32 = (data << 10 | rem) ^ 0x5412 // uint15 // Draw first copy for i in 0..<6 { - setFunctionModule(x: 8, y: i, isBlack: getBit(bits, i)) + setFunctionModule(x: 8, y: i, isBlack: getBit(bits, Int32(i))) } setFunctionModule(x: 8, y: 7, isBlack: getBit(bits, 6)) setFunctionModule(x: 8, y: 8, isBlack: getBit(bits, 7)) setFunctionModule(x: 7, y: 8, isBlack: getBit(bits, 8)) for i in 9..<15 { - setFunctionModule(x: 14 - i, y: 8, isBlack: getBit(bits, i)) + setFunctionModule(x: 14 - i, y: 8, isBlack: getBit(bits, Int32(i))) } // Draw second copy for i in 0..<8 { - setFunctionModule(x: size - 1 - i, y: 8, isBlack: getBit(bits, i)) + setFunctionModule(x: size - 1 - i, y: 8, isBlack: getBit(bits, Int32(i))) } for i in 0..<15 { - setFunctionModule(x: 8, y: size - 15 + i, isBlack: getBit(bits, i)) + setFunctionModule(x: 8, y: size - 15 + i, isBlack: getBit(bits, Int32(i))) } setFunctionModule(x: 8, y: size - 8, isBlack: true) // Always black } @@ -359,7 +360,7 @@ struct QRCode { // Draw two copies for i in 0..<18 { - let bit = getBit(bits, i) + let bit = getBit(bits, Int32(i)) let a: Int = size - 11 + i % 3 let b: Int = i / 3 setFunctionModule(x: a, y: b, isBlack: bit) @@ -421,7 +422,7 @@ struct QRCode { var k: UInt = 0 for i in 0..= numShortBlocks ? 1 : 0) - var dat = Array(d[k..<(k + datLen)]) + var dat = Array(data[Int(k)..= numShortBlocks { - result.push(block[i]) + result.append(block[Int(i)]) } } } @@ -493,8 +494,9 @@ struct QRCode { case 5: invert = x * y % 2 + x * y % 3 == 0 case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0 case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0 + default: fatalError("Unreachable") } - self[x, y] ^= invert & !isFunction[y * size + x] + self[x, y] = self[x, y] != (invert && !isFunction[y * size + x]) } } } @@ -565,7 +567,7 @@ struct QRCode { } // Balance of black and white modules - let black: Int = modules.map(Int.init).sum() + let black: Int = modules.map { $0 ? 1 : 0 }.reduce(0, +) let total: Int = size * size // Note that size is odd, so black/total != 1/2 // Compute the smallest integer k >= 0 such that (45 - 5k)% <= black/total <= (55+5k)% let k: Int = (abs(black * 20 - total * 10) + total - 1) / total - 1 @@ -595,7 +597,7 @@ struct QRCode { /// Returns the number of data bits that can be stored in a QR Code of the given version number, after /// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. /// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. - private func getNumRawDataModules(version: QRCodeVersion) -> UInt { + private static func getNumRawDataModules(version: QRCodeVersion) -> UInt { let ver = UInt(version.value) var result: UInt = (16 * ver + 128) * ver + 64 if ver >= 2 { @@ -612,15 +614,15 @@ struct QRCode { /// Returns the number of 8-bit data (i.e. not error correction) codewords contained in any /// QR Code of the given version number and error correction level, with remainder bits discarded. /// This stateless pure function could be implemented as a (40*4)-cell lookup table. - private func getNumDataCodewords(version: QRCodeVersion, ecc: QRCodeECC) -> UInt { - QRCode.getNumRawDataModules(version: ver) / 8 - - QRCode.tableGet(eccCodewordsPerBlock, version: version, ecc: ecc) - * QRCode.tableGet(numErrorCorrectionBlocks, version: version, ecc: ecc) + private static func getNumDataCodewords(version: QRCodeVersion, ecl: QRCodeECC) -> UInt { + QRCode.getNumRawDataModules(version: version) / 8 + - QRCode.tableGet(eccCodewordsPerBlock, version: version, ecl: ecl) + * QRCode.tableGet(numErrorCorrectionBlocks, version: version, ecl: ecl) } /// Returns an entry from the given table based on the given values. - private func table_get(_ table: [[Int]], version: QRCodeVersion, ecl: QRCodeECC) -> UInt { - UInt(table[ecl.ordinal][Int(version.value)]) + private static func tableGet(_ table: [[Int]], version: QRCodeVersion, ecl: QRCodeECC) -> UInt { + UInt(table[Int(ecl.ordinal)][Int(version.value)]) } /// Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials. @@ -637,7 +639,7 @@ struct QRCode { var root: UInt8 = 1 for _ in 0.. [UInt8] { var result = [UInt8](repeating: 0, count: divisor.count) for b in data { // Polynomial divison - let factor: UInt8 = b ^ result.popFirst()! + let factor: UInt8 = b ^ result[...].popFirst()! result.append(0) for (i, y) in divisor.enumerated() { result[i] = QRCode.reedSolomonMultiply(x: y, y: factor) @@ -678,7 +680,7 @@ struct QRCode { private struct FinderPenalty { let qrSize: Int - let runHistory: [Int] + var runHistory: [Int] init(_ qrSize: Int) { self.qrSize = qrSize @@ -716,7 +718,7 @@ struct QRCode { } currentRunLength += qrSize // Add white border to final run addHistory(runLength: currentRunLength) - countPatterns() + return countPatterns() } } } diff --git a/swift/Sources/QRCodeGenerator/QRCodeMiscellaneous.swift b/swift/Sources/QRCodeGenerator/QRCodeMiscellaneous.swift index 34c1439..b35801c 100644 --- a/swift/Sources/QRCodeGenerator/QRCodeMiscellaneous.swift +++ b/swift/Sources/QRCodeGenerator/QRCodeMiscellaneous.swift @@ -25,7 +25,7 @@ public struct QRCodeVersion: Hashable, Comparable { public let value: UInt8 - public init(value: UInt8) { + public init(_ value: UInt8) { assert(1 <= value && value <= 40, "Version number out of range") self.value = value } @@ -39,7 +39,7 @@ public struct QRCodeVersion: Hashable, Comparable { public struct QRCodeMask: Hashable { public let value: UInt8 - public init(value: UInt8) { + public init(_ value: UInt8) { assert(value <= 7, "Mask value out of range") self.value = value } diff --git a/swift/Sources/QRCodeGenerator/QRSegment.swift b/swift/Sources/QRCodeGenerator/QRSegment.swift index 40caf3d..d110c6a 100644 --- a/swift/Sources/QRCodeGenerator/QRSegment.swift +++ b/swift/Sources/QRCodeGenerator/QRSegment.swift @@ -21,6 +21,8 @@ * Software. */ +import Foundation + /// The set of all legal characters in alphanumeric mode, /// where each character value maps to the index in the string. fileprivate let alphanumericCharset: [Character] = [ @@ -61,23 +63,24 @@ public struct QRSegment: Hashable { /// /// Any text string can be converted to UTF-8 bytes and encoded as a byte mode segment. public static func makeBytes(_ data: [UInt8]) -> Self { - var bb = BitBuffer([]) + var bb = BitBuffer() for b in data { bb.appendBits(UInt32(b), 8) } - return QRSegment(mode: .byte, numChars: data.count, data: bb.bits) + return QRSegment(mode: .byte, numChars: UInt(data.count), data: bb.bits) } /// Returns a segment representing the given string of decimal digits encoded in numeric mode. /// /// Panics if the string contains non-digit characters. public static func makeNumeric(_ text: [Character]) -> Self { - var bb = BitBuffer([]) + var bb = BitBuffer() var accumData: UInt32 = 0 var accumCount: UInt8 = 0 for c in text { assert(c.isNumber && c.isASCII, "String contains non-numeric characters") - accumData = accumData * 10 + (UInt32(c.asciiValue!) - UInt32("0".asciiValue!)) + let zero: Character = "0" + accumData = accumData * 10 + (UInt32(c.asciiValue!) - UInt32(zero.asciiValue!)) accumCount += 1 if accumCount == 3 { bb.appendBits(accumData, 10) @@ -86,9 +89,9 @@ public struct QRSegment: Hashable { } } if accumCount > 0 { // 1 or 2 digits remaining - bb.appendBits(accumData, accumCount * 3 + 1) + bb.appendBits(accumData, Int(accumCount * 3 + 1)) } - return QRSegment(mode: .numeric, numChars: text.count, data: bb.bits) + return QRSegment(mode: .numeric, numChars: UInt(text.count), data: bb.bits) } /// Returns a segment representing the given text string encoded in alphanumeric mode. @@ -98,7 +101,7 @@ public struct QRSegment: Hashable { /// /// Panics if the string contains non-encodable characters. public static func makeAlphanumeric(_ text: [Character]) -> Self { - var bb = BitBuffer([]) + var bb = BitBuffer() var accumData: UInt32 = 0 var accumCount: UInt32 = 0 for c in text { @@ -116,14 +119,14 @@ public struct QRSegment: Hashable { if accumCount > 0 { // 1 character remaining bb.appendBits(accumData, 6) } - return QRSegment(mode: .alphanumeric, numChars: text.count, data: bb.bits) + return QRSegment(mode: .alphanumeric, numChars: UInt(text.count), data: bb.bits) } /// Returns a list of zero or more segments to represent the given Unicode text string. /// /// The result may use various segment modes and switch /// modes to optimize the length of the bit stream. - public static func makeSegments(_ text: [Character]) -> Self { + public static func makeSegments(_ text: [Character]) -> [Self] { if text.isEmpty { return [] } else if QRSegment.isNumeric(text) { @@ -139,7 +142,7 @@ public struct QRSegment: Hashable { /// Returns a segment representing an Extended Channel Interpretation /// (ECI) designator with the given assignment value. public static func makeECI(assignVal: UInt32) -> Self { - var bb = BitBuffer([]) + var bb = BitBuffer() if assignVal < (1 << 7) { bb.appendBits(assignVal, 8) } else if assignVal < (1 << 14) { @@ -178,7 +181,7 @@ public struct QRSegment: Hashable { guard seg.numChars < (1 << ccBits) else { return nil // The segment"s length doesn't fit the field's bit width } - result += 4 + UInt(ccBits) + seg.data.count + result += 4 + UInt(ccBits) + UInt(seg.data.count) } return result } @@ -227,7 +230,7 @@ public struct QRSegment: Hashable { case .kanji: v = [8, 10, 12] case .eci: v = [0, 0, 0] } - return v[(version.value + 7) / 17] + return v[(Int(version.value) + 7) / 17] } } }