Appends error correction bytes to each block of the given data array, then interleaves bytes from the blocks and stores them in the result array. data[0 : rawCodewords - totalEcc] contains the input data. data[rawCodewords - totalEcc : rawCodewords] is used as a temporary work area and will be clobbered by this function. The final answer is stored in result[0 : rawCodewords].
| 196 | // the input data. data[rawCodewords - totalEcc : rawCodewords] is used as a temporary work area |
| 197 | // and will be clobbered by this function. The final answer is stored in result[0 : rawCodewords]. |
| 198 | testable void appendErrorCorrection(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]) { |
| 199 | // Calculate parameter numbers |
| 200 | assert(0 <= (int)ecl && (int)ecl < 4 && qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); |
| 201 | int numBlocks = c_read8(&NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version]); |
| 202 | int blockEccLen = c_read8(&ECC_CODEWORDS_PER_BLOCK[(int)ecl][version]); |
| 203 | int rawCodewords = getNumRawDataModules(version) / 8; |
| 204 | int dataLen = rawCodewords - blockEccLen * numBlocks; |
| 205 | int numShortBlocks = numBlocks - rawCodewords % numBlocks; |
| 206 | int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen; |
| 207 | |
| 208 | // Split data into blocks and append ECC after all data |
| 209 | uint8_t generator[30]; |
| 210 | calcReedSolomonGenerator(blockEccLen, generator); |
| 211 | for (int i = 0, j = dataLen, k = 0; i < numBlocks; i++) { |
| 212 | int blockLen = shortBlockDataLen; |
| 213 | if (i >= numShortBlocks) |
| 214 | blockLen++; |
| 215 | calcReedSolomonRemainder(&data[k], blockLen, generator, blockEccLen, &data[j]); |
| 216 | j += blockEccLen; |
| 217 | k += blockLen; |
| 218 | } |
| 219 | |
| 220 | // Interleave (not concatenate) the bytes from every block into a single sequence |
| 221 | for (int i = 0, k = 0; i < numBlocks; i++) { |
| 222 | for (int j = 0, l = i; j < shortBlockDataLen; j++, k++, l += numBlocks) |
| 223 | result[l] = data[k]; |
| 224 | if (i >= numShortBlocks) |
| 225 | k++; |
| 226 | } |
| 227 | for (int i = numShortBlocks, k = (numShortBlocks + 1) * shortBlockDataLen, l = numBlocks * shortBlockDataLen; |
| 228 | i < numBlocks; i++, k += shortBlockDataLen + 1, l++) |
| 229 | result[l] = data[k]; |
| 230 | for (int i = 0, k = dataLen; i < numBlocks; i++) { |
| 231 | for (int j = 0, l = dataLen + i; j < blockEccLen; j++, k++, l += numBlocks) |
| 232 | result[l] = data[k]; |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | |
| 237 | // Returns the number of 8-bit codewords that can be used for storing data (not ECC), |
no test coverage detected