codekingpro/portable-devtools
114k
1from typing import NamedTuple2from qrcode import constants3 4EXP_TABLE = list(range(256))5 6LOG_TABLE = list(range(256))7 8for i in range(8):9 EXP_TABLE[i] = 1 << i10 11for i in range(8, 256):12 EXP_TABLE[i] = (13 EXP_TABLE[i - 4] ^ EXP_TABLE[i - 5] ^ EXP_TABLE[i - 6] ^ EXP_TABLE[i - 8]14 )15 16for i in range(255):17 LOG_TABLE[EXP_TABLE[i]] = i18 19RS_BLOCK_OFFSET = {20 constants.ERROR_CORRECT_L: 0,21 constants.ERROR_CORRECT_M: 1,22 constants.ERROR_CORRECT_Q: 2,23 constants.ERROR_CORRECT_H: 3,24}25 26RS_BLOCK_TABLE = (27 # L28 # M29 # Q30 # H31 # 132 (1, 26, 19),33 (1, 26, 16),34 (1, 26, 13),35 (1, 26, 9),36 # 237 (1, 44, 34),38 (1, 44, 28),39 (1, 44, 22),40 (1, 44, 16),41 # 342 (1, 70, 55),43 (1, 70, 44),44 (2, 35, 17),45 (2, 35, 13),46 # 447 (1, 100, 80),48 (2, 50, 32),49 (2, 50, 24),50 (4, 25, 9),51 # 552 (1, 134, 108),53 (2, 67, 43),54 (2, 33, 15, 2, 34, 16),55 (2, 33, 11, 2, 34, 12),56 # 657 (2, 86, 68),58 (4, 43, 27),59 (4, 43, 19),60 (4, 43, 15),61 # 762 (2, 98, 78),63 (4, 49, 31),64 (2, 32, 14, 4, 33, 15),65 (4, 39, 13, 1, 40, 14),66 # 867 (2, 121, 97),68 (2, 60, 38, 2, 61, 39),69 (4, 40, 18, 2, 41, 19),70 (4, 40, 14, 2, 41, 15),71 # 972 (2, 146, 116),73 (3, 58, 36, 2, 59, 37),74 (4, 36, 16, 4, 37, 17),75 (4, 36, 12, 4, 37, 13),76 # 1077 (2, 86, 68, 2, 87, 69),78 (4, 69, 43, 1, 70, 44),79 (6, 43, 19, 2, 44, 20),80 (6, 43, 15, 2, 44, 16),81 # 1182 (4, 101, 81),83 (1, 80, 50, 4, 81, 51),84 (4, 50, 22, 4, 51, 23),85 (3, 36, 12, 8, 37, 13),86 # 1287 (2, 116, 92, 2, 117, 93),88 (6, 58, 36, 2, 59, 37),89 (4, 46, 20, 6, 47, 21),90 (7, 42, 14, 4, 43, 15),91 # 1392 (4, 133, 107),93 (8, 59, 37, 1, 60, 38),94 (8, 44, 20, 4, 45, 21),95 (12, 33, 11, 4, 34, 12),96 # 1497 (3, 145, 115, 1, 146, 116),98 (4, 64, 40, 5, 65, 41),99 (11, 36, 16, 5, 37, 17),100 (11, 36, 12, 5, 37, 13),101 # 15102 (5, 109, 87, 1, 110, 88),103 (5, 65, 41, 5, 66, 42),104 (5, 54, 24, 7, 55, 25),105 (11, 36, 12, 7, 37, 13),106 # 16107 (5, 122, 98, 1, 123, 99),108 (7, 73, 45, 3, 74, 46),109 (15, 43, 19, 2, 44, 20),110 (3, 45, 15, 13, 46, 16),111 # 17112 (1, 135, 107, 5, 136, 108),113 (10, 74, 46, 1, 75, 47),114 (1, 50, 22, 15, 51, 23),115 (2, 42, 14, 17, 43, 15),116 # 18117 (5, 150, 120, 1, 151, 121),118 (9, 69, 43, 4, 70, 44),119 (17, 50, 22, 1, 51, 23),120 (2, 42, 14, 19, 43, 15),121 # 19122 (3, 141, 113, 4, 142, 114),123 (3, 70, 44, 11, 71, 45),124 (17, 47, 21, 4, 48, 22),125 (9, 39, 13, 16, 40, 14),126 # 20127 (3, 135, 107, 5, 136, 108),128 (3, 67, 41, 13, 68, 42),129 (15, 54, 24, 5, 55, 25),130 (15, 43, 15, 10, 44, 16),131 # 21132 (4, 144, 116, 4, 145, 117),133 (17, 68, 42),134 (17, 50, 22, 6, 51, 23),135 (19, 46, 16, 6, 47, 17),136 # 22137 (2, 139, 111, 7, 140, 112),138 (17, 74, 46),139 (7, 54, 24, 16, 55, 25),140 (34, 37, 13),141 # 23142 (4, 151, 121, 5, 152, 122),143 (4, 75, 47, 14, 76, 48),144 (11, 54, 24, 14, 55, 25),145 (16, 45, 15, 14, 46, 16),146 # 24147 (6, 147, 117, 4, 148, 118),148 (6, 73, 45, 14, 74, 46),149 (11, 54, 24, 16, 55, 25),150 (30, 46, 16, 2, 47, 17),151 # 25152 (8, 132, 106, 4, 133, 107),153 (8, 75, 47, 13, 76, 48),154 (7, 54, 24, 22, 55, 25),155 (22, 45, 15, 13, 46, 16),156 # 26157 (10, 142, 114, 2, 143, 115),158 (19, 74, 46, 4, 75, 47),159 (28, 50, 22, 6, 51, 23),160 (33, 46, 16, 4, 47, 17),161 # 27162 (8, 152, 122, 4, 153, 123),163 (22, 73, 45, 3, 74, 46),164 (8, 53, 23, 26, 54, 24),165 (12, 45, 15, 28, 46, 16),166 # 28167 (3, 147, 117, 10, 148, 118),168 (3, 73, 45, 23, 74, 46),169 (4, 54, 24, 31, 55, 25),170 (11, 45, 15, 31, 46, 16),171 # 29172 (7, 146, 116, 7, 147, 117),173 (21, 73, 45, 7, 74, 46),174 (1, 53, 23, 37, 54, 24),175 (19, 45, 15, 26, 46, 16),176 # 30177 (5, 145, 115, 10, 146, 116),178 (19, 75, 47, 10, 76, 48),179 (15, 54, 24, 25, 55, 25),180 (23, 45, 15, 25, 46, 16),181 # 31182 (13, 145, 115, 3, 146, 116),183 (2, 74, 46, 29, 75, 47),184 (42, 54, 24, 1, 55, 25),185 (23, 45, 15, 28, 46, 16),186 # 32187 (17, 145, 115),188 (10, 74, 46, 23, 75, 47),189 (10, 54, 24, 35, 55, 25),190 (19, 45, 15, 35, 46, 16),191 # 33192 (17, 145, 115, 1, 146, 116),193 (14, 74, 46, 21, 75, 47),194 (29, 54, 24, 19, 55, 25),195 (11, 45, 15, 46, 46, 16),196 # 34197 (13, 145, 115, 6, 146, 116),198 (14, 74, 46, 23, 75, 47),199 (44, 54, 24, 7, 55, 25),200 (59, 46, 16, 1, 47, 17),201 # 35202 (12, 151, 121, 7, 152, 122),203 (12, 75, 47, 26, 76, 48),204 (39, 54, 24, 14, 55, 25),205 (22, 45, 15, 41, 46, 16),206 # 36207 (6, 151, 121, 14, 152, 122),208 (6, 75, 47, 34, 76, 48),209 (46, 54, 24, 10, 55, 25),210 (2, 45, 15, 64, 46, 16),211 # 37212 (17, 152, 122, 4, 153, 123),213 (29, 74, 46, 14, 75, 47),214 (49, 54, 24, 10, 55, 25),215 (24, 45, 15, 46, 46, 16),216 # 38217 (4, 152, 122, 18, 153, 123),218 (13, 74, 46, 32, 75, 47),219 (48, 54, 24, 14, 55, 25),220 (42, 45, 15, 32, 46, 16),221 # 39222 (20, 147, 117, 4, 148, 118),223 (40, 75, 47, 7, 76, 48),224 (43, 54, 24, 22, 55, 25),225 (10, 45, 15, 67, 46, 16),226 # 40227 (19, 148, 118, 6, 149, 119),228 (18, 75, 47, 31, 76, 48),229 (34, 54, 24, 34, 55, 25),230 (20, 45, 15, 61, 46, 16),231)232 233 234def glog(n):235 if n < 1: # pragma: no cover236 raise ValueError(f"glog({n})")237 return LOG_TABLE[n]238 239 240def gexp(n):241 return EXP_TABLE[n % 255]242 243 244class Polynomial:245 def __init__(self, num, shift):246 if not num: # pragma: no cover247 raise Exception(f"{len(num)}/{shift}")248 249 offset = 0250 for offset in range(len(num)):251 if num[offset] != 0:252 break253 254 self.num = num[offset:] + [0] * shift255 256 def __getitem__(self, index):257 return self.num[index]258 259 def __iter__(self):260 return iter(self.num)261 262 def __len__(self):263 return len(self.num)264 265 def __mul__(self, other):266 num = [0] * (len(self) + len(other) - 1)267 268 for i, item in enumerate(self):269 for j, other_item in enumerate(other):270 num[i + j] ^= gexp(glog(item) + glog(other_item))271 272 return Polynomial(num, 0)273 274 def __mod__(self, other):275 difference = len(self) - len(other)276 if difference < 0:277 return self278 279 ratio = glog(self[0]) - glog(other[0])280 281 num = [282 item ^ gexp(glog(other_item) + ratio)283 for item, other_item in zip(self, other)284 ]285 if difference:286 num.extend(self[-difference:])287 288 # recursive call289 return Polynomial(num, 0) % other290 291 292class RSBlock(NamedTuple):293 total_count: int294 data_count: int295 296 297def rs_blocks(version, error_correction):298 if error_correction not in RS_BLOCK_OFFSET: # pragma: no cover299 raise Exception(300 "bad rs block @ version: %s / error_correction: %s"301 % (version, error_correction)302 )303 offset = RS_BLOCK_OFFSET[error_correction]304 rs_block = RS_BLOCK_TABLE[(version - 1) * 4 + offset]305 306 blocks = []307 308 for i in range(0, len(rs_block), 3):309 count, total_count, data_count = rs_block[i : i + 3]310 for _ in range(count):311 blocks.append(RSBlock(total_count, data_count))312 313 return blocks314 