From 08ab9e6f4e748273bd090eca556412c70ceadc9b Mon Sep 17 00:00:00 2001 From: fwcd Date: Mon, 24 Feb 2020 23:58:55 +0100 Subject: [PATCH] Port QRCode.addECCAndInterleave to Swift --- swift/Sources/QRCodeGenerator/QRCode.swift | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/swift/Sources/QRCodeGenerator/QRCode.swift b/swift/Sources/QRCodeGenerator/QRCode.swift index 9221be2..bae32f5 100644 --- a/swift/Sources/QRCodeGenerator/QRCode.swift +++ b/swift/Sources/QRCodeGenerator/QRCode.swift @@ -399,4 +399,50 @@ struct QRCode { self[x, y] = isBlack isFunction[y * size + x] = true } + + /*---- Private helper methods for constructor: Codewords and masking ----*/ + + /// Returns a new byte string representing the given data with the appropriate error correction + /// codewords appended to it, based on this object's version and error correction level. + private func addECCAndInterleave(data: [UInt8]) -> [UInt8] { + let ver = version + let ecl = errorCorrectionLevel + assert(data.count == QRCode.getNumDataCodewords(version: ver, ecl: ecl), "Illegal argument") + + // Calculate parameter numbers + let numBlocks: UInt = QRCode.tableGet(numErrorCorrectionBlocks, version: ver, ecl: ecl) + let blockECCLen: UInt = QRCode.tableGet(eccCodewordsPerBlock, version: ver, ecl: ecl) + let rawCodeWords: UInt = QRCode.getNumRawDataModules(version: ver) / 8 + let numShortBlocks: UInt = numBlocks - rawCodeWords % numBlocks + let shortBlockLen: UInt = rawCodeWords / numBlocks + + // Split data into blocks and append ECC to each block + var blocks = [[UInt8]]() + let rsDiv: [UInt8] = QRCode.reedSolomonComputeDivisor(degree: blockECCLen) + var k: UInt = 0 + for i in 0..= numShortBlocks ? 1 : 0) + var dat = Array(d[k..<(k + datLen)]) + k += datLen + let ecc: [UInt8] = QRCode.reedSolomonComputeRemainder(data: dat, divisor: rsDiv) + if i < numShortBlocks { + dat.append(0) + } + dat += ecc + blocks.append(dat) + } + + // Interleave (not concatenate) the bytes from every block into a single sequence + var result = [UInt8]() + for i in 0...shortBlockLen { + for (j, block) in blocks.enumerated() { + // Skip the padding byte in short blocks + if i != shortBlockLen - blockECCLen || j >= numShortBlocks { + result.push(block[i]) + } + } + } + + return result + } }