| 299 | |
| 300 | |
| 301 | std::vector<uint8_t> qrcodegen::QrCode::appendErrorCorrection(const std::vector<uint8_t> &data) const { |
| 302 | if (data.size() != static_cast<unsigned int>(getNumDataCodewords(version, errorCorrectionLevel))) |
| 303 | throw "Invalid argument"; |
| 304 | |
| 305 | // Calculate parameter numbers |
| 306 | int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[errorCorrectionLevel.ordinal][version]; |
| 307 | int totalEcc = NUM_ERROR_CORRECTION_CODEWORDS[errorCorrectionLevel.ordinal][version]; |
| 308 | if (totalEcc % numBlocks != 0) |
| 309 | throw "Assertion error"; |
| 310 | int blockEccLen = totalEcc / numBlocks; |
| 311 | int numShortBlocks = numBlocks - getNumRawDataModules(version) / 8 % numBlocks; |
| 312 | int shortBlockLen = getNumRawDataModules(version) / 8 / numBlocks; |
| 313 | |
| 314 | // Split data into blocks and append ECC to each block |
| 315 | std::vector<std::vector<uint8_t> > blocks; |
| 316 | const ReedSolomonGenerator rs(blockEccLen); |
| 317 | for (int i = 0, k = 0; i < numBlocks; i++) { |
| 318 | std::vector<uint8_t> dat; |
| 319 | dat.insert(dat.begin(), data.begin() + k, data.begin() + (k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1))); |
| 320 | k += dat.size(); |
| 321 | const std::vector<uint8_t> ecc(rs.getRemainder(dat)); |
| 322 | if (i < numShortBlocks) |
| 323 | dat.push_back(0); |
| 324 | dat.insert(dat.end(), ecc.begin(), ecc.end()); |
| 325 | blocks.push_back(dat); |
| 326 | } |
| 327 | |
| 328 | // Interleave (not concatenate) the bytes from every block into a single sequence |
| 329 | std::vector<uint8_t> result; |
| 330 | for (int i = 0; static_cast<unsigned int>(i) < blocks.at(0).size(); i++) { |
| 331 | for (int j = 0; static_cast<unsigned int>(j) < blocks.size(); j++) { |
| 332 | // Skip the padding byte in short blocks |
| 333 | if (i != shortBlockLen - blockEccLen || j >= numShortBlocks) |
| 334 | result.push_back(blocks.at(j).at(i)); |
| 335 | } |
| 336 | } |
| 337 | if (result.size() != static_cast<unsigned int>(getNumRawDataModules(version) / 8)) |
| 338 | throw "Assertion error"; |
| 339 | return result; |
| 340 | } |
| 341 | |
| 342 | |
| 343 | void qrcodegen::QrCode::drawCodewords(const std::vector<uint8_t> &data) { |
nothing calls this directly
no test coverage detected