base.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. from typing import NamedTuple
  2. from qrcode import constants
  3. EXP_TABLE = list(range(256))
  4. LOG_TABLE = list(range(256))
  5. for i in range(8):
  6. EXP_TABLE[i] = 1 << i
  7. for i in range(8, 256):
  8. EXP_TABLE[i] = (
  9. EXP_TABLE[i - 4] ^ EXP_TABLE[i - 5] ^ EXP_TABLE[i - 6] ^ EXP_TABLE[i - 8]
  10. )
  11. for i in range(255):
  12. LOG_TABLE[EXP_TABLE[i]] = i
  13. RS_BLOCK_OFFSET = {
  14. constants.ERROR_CORRECT_L: 0,
  15. constants.ERROR_CORRECT_M: 1,
  16. constants.ERROR_CORRECT_Q: 2,
  17. constants.ERROR_CORRECT_H: 3,
  18. }
  19. RS_BLOCK_TABLE = (
  20. # L
  21. # M
  22. # Q
  23. # H
  24. # 1
  25. (1, 26, 19),
  26. (1, 26, 16),
  27. (1, 26, 13),
  28. (1, 26, 9),
  29. # 2
  30. (1, 44, 34),
  31. (1, 44, 28),
  32. (1, 44, 22),
  33. (1, 44, 16),
  34. # 3
  35. (1, 70, 55),
  36. (1, 70, 44),
  37. (2, 35, 17),
  38. (2, 35, 13),
  39. # 4
  40. (1, 100, 80),
  41. (2, 50, 32),
  42. (2, 50, 24),
  43. (4, 25, 9),
  44. # 5
  45. (1, 134, 108),
  46. (2, 67, 43),
  47. (2, 33, 15, 2, 34, 16),
  48. (2, 33, 11, 2, 34, 12),
  49. # 6
  50. (2, 86, 68),
  51. (4, 43, 27),
  52. (4, 43, 19),
  53. (4, 43, 15),
  54. # 7
  55. (2, 98, 78),
  56. (4, 49, 31),
  57. (2, 32, 14, 4, 33, 15),
  58. (4, 39, 13, 1, 40, 14),
  59. # 8
  60. (2, 121, 97),
  61. (2, 60, 38, 2, 61, 39),
  62. (4, 40, 18, 2, 41, 19),
  63. (4, 40, 14, 2, 41, 15),
  64. # 9
  65. (2, 146, 116),
  66. (3, 58, 36, 2, 59, 37),
  67. (4, 36, 16, 4, 37, 17),
  68. (4, 36, 12, 4, 37, 13),
  69. # 10
  70. (2, 86, 68, 2, 87, 69),
  71. (4, 69, 43, 1, 70, 44),
  72. (6, 43, 19, 2, 44, 20),
  73. (6, 43, 15, 2, 44, 16),
  74. # 11
  75. (4, 101, 81),
  76. (1, 80, 50, 4, 81, 51),
  77. (4, 50, 22, 4, 51, 23),
  78. (3, 36, 12, 8, 37, 13),
  79. # 12
  80. (2, 116, 92, 2, 117, 93),
  81. (6, 58, 36, 2, 59, 37),
  82. (4, 46, 20, 6, 47, 21),
  83. (7, 42, 14, 4, 43, 15),
  84. # 13
  85. (4, 133, 107),
  86. (8, 59, 37, 1, 60, 38),
  87. (8, 44, 20, 4, 45, 21),
  88. (12, 33, 11, 4, 34, 12),
  89. # 14
  90. (3, 145, 115, 1, 146, 116),
  91. (4, 64, 40, 5, 65, 41),
  92. (11, 36, 16, 5, 37, 17),
  93. (11, 36, 12, 5, 37, 13),
  94. # 15
  95. (5, 109, 87, 1, 110, 88),
  96. (5, 65, 41, 5, 66, 42),
  97. (5, 54, 24, 7, 55, 25),
  98. (11, 36, 12, 7, 37, 13),
  99. # 16
  100. (5, 122, 98, 1, 123, 99),
  101. (7, 73, 45, 3, 74, 46),
  102. (15, 43, 19, 2, 44, 20),
  103. (3, 45, 15, 13, 46, 16),
  104. # 17
  105. (1, 135, 107, 5, 136, 108),
  106. (10, 74, 46, 1, 75, 47),
  107. (1, 50, 22, 15, 51, 23),
  108. (2, 42, 14, 17, 43, 15),
  109. # 18
  110. (5, 150, 120, 1, 151, 121),
  111. (9, 69, 43, 4, 70, 44),
  112. (17, 50, 22, 1, 51, 23),
  113. (2, 42, 14, 19, 43, 15),
  114. # 19
  115. (3, 141, 113, 4, 142, 114),
  116. (3, 70, 44, 11, 71, 45),
  117. (17, 47, 21, 4, 48, 22),
  118. (9, 39, 13, 16, 40, 14),
  119. # 20
  120. (3, 135, 107, 5, 136, 108),
  121. (3, 67, 41, 13, 68, 42),
  122. (15, 54, 24, 5, 55, 25),
  123. (15, 43, 15, 10, 44, 16),
  124. # 21
  125. (4, 144, 116, 4, 145, 117),
  126. (17, 68, 42),
  127. (17, 50, 22, 6, 51, 23),
  128. (19, 46, 16, 6, 47, 17),
  129. # 22
  130. (2, 139, 111, 7, 140, 112),
  131. (17, 74, 46),
  132. (7, 54, 24, 16, 55, 25),
  133. (34, 37, 13),
  134. # 23
  135. (4, 151, 121, 5, 152, 122),
  136. (4, 75, 47, 14, 76, 48),
  137. (11, 54, 24, 14, 55, 25),
  138. (16, 45, 15, 14, 46, 16),
  139. # 24
  140. (6, 147, 117, 4, 148, 118),
  141. (6, 73, 45, 14, 74, 46),
  142. (11, 54, 24, 16, 55, 25),
  143. (30, 46, 16, 2, 47, 17),
  144. # 25
  145. (8, 132, 106, 4, 133, 107),
  146. (8, 75, 47, 13, 76, 48),
  147. (7, 54, 24, 22, 55, 25),
  148. (22, 45, 15, 13, 46, 16),
  149. # 26
  150. (10, 142, 114, 2, 143, 115),
  151. (19, 74, 46, 4, 75, 47),
  152. (28, 50, 22, 6, 51, 23),
  153. (33, 46, 16, 4, 47, 17),
  154. # 27
  155. (8, 152, 122, 4, 153, 123),
  156. (22, 73, 45, 3, 74, 46),
  157. (8, 53, 23, 26, 54, 24),
  158. (12, 45, 15, 28, 46, 16),
  159. # 28
  160. (3, 147, 117, 10, 148, 118),
  161. (3, 73, 45, 23, 74, 46),
  162. (4, 54, 24, 31, 55, 25),
  163. (11, 45, 15, 31, 46, 16),
  164. # 29
  165. (7, 146, 116, 7, 147, 117),
  166. (21, 73, 45, 7, 74, 46),
  167. (1, 53, 23, 37, 54, 24),
  168. (19, 45, 15, 26, 46, 16),
  169. # 30
  170. (5, 145, 115, 10, 146, 116),
  171. (19, 75, 47, 10, 76, 48),
  172. (15, 54, 24, 25, 55, 25),
  173. (23, 45, 15, 25, 46, 16),
  174. # 31
  175. (13, 145, 115, 3, 146, 116),
  176. (2, 74, 46, 29, 75, 47),
  177. (42, 54, 24, 1, 55, 25),
  178. (23, 45, 15, 28, 46, 16),
  179. # 32
  180. (17, 145, 115),
  181. (10, 74, 46, 23, 75, 47),
  182. (10, 54, 24, 35, 55, 25),
  183. (19, 45, 15, 35, 46, 16),
  184. # 33
  185. (17, 145, 115, 1, 146, 116),
  186. (14, 74, 46, 21, 75, 47),
  187. (29, 54, 24, 19, 55, 25),
  188. (11, 45, 15, 46, 46, 16),
  189. # 34
  190. (13, 145, 115, 6, 146, 116),
  191. (14, 74, 46, 23, 75, 47),
  192. (44, 54, 24, 7, 55, 25),
  193. (59, 46, 16, 1, 47, 17),
  194. # 35
  195. (12, 151, 121, 7, 152, 122),
  196. (12, 75, 47, 26, 76, 48),
  197. (39, 54, 24, 14, 55, 25),
  198. (22, 45, 15, 41, 46, 16),
  199. # 36
  200. (6, 151, 121, 14, 152, 122),
  201. (6, 75, 47, 34, 76, 48),
  202. (46, 54, 24, 10, 55, 25),
  203. (2, 45, 15, 64, 46, 16),
  204. # 37
  205. (17, 152, 122, 4, 153, 123),
  206. (29, 74, 46, 14, 75, 47),
  207. (49, 54, 24, 10, 55, 25),
  208. (24, 45, 15, 46, 46, 16),
  209. # 38
  210. (4, 152, 122, 18, 153, 123),
  211. (13, 74, 46, 32, 75, 47),
  212. (48, 54, 24, 14, 55, 25),
  213. (42, 45, 15, 32, 46, 16),
  214. # 39
  215. (20, 147, 117, 4, 148, 118),
  216. (40, 75, 47, 7, 76, 48),
  217. (43, 54, 24, 22, 55, 25),
  218. (10, 45, 15, 67, 46, 16),
  219. # 40
  220. (19, 148, 118, 6, 149, 119),
  221. (18, 75, 47, 31, 76, 48),
  222. (34, 54, 24, 34, 55, 25),
  223. (20, 45, 15, 61, 46, 16),
  224. )
  225. def glog(n):
  226. if n < 1: # pragma: no cover
  227. raise ValueError(f"glog({n})")
  228. return LOG_TABLE[n]
  229. def gexp(n):
  230. return EXP_TABLE[n % 255]
  231. class Polynomial:
  232. def __init__(self, num, shift):
  233. if not num: # pragma: no cover
  234. raise Exception(f"{len(num)}/{shift}")
  235. offset = 0
  236. for offset in range(len(num)):
  237. if num[offset] != 0:
  238. break
  239. self.num = num[offset:] + [0] * shift
  240. def __getitem__(self, index):
  241. return self.num[index]
  242. def __iter__(self):
  243. return iter(self.num)
  244. def __len__(self):
  245. return len(self.num)
  246. def __mul__(self, other):
  247. num = [0] * (len(self) + len(other) - 1)
  248. for i, item in enumerate(self):
  249. for j, other_item in enumerate(other):
  250. num[i + j] ^= gexp(glog(item) + glog(other_item))
  251. return Polynomial(num, 0)
  252. def __mod__(self, other):
  253. difference = len(self) - len(other)
  254. if difference < 0:
  255. return self
  256. ratio = glog(self[0]) - glog(other[0])
  257. num = [
  258. item ^ gexp(glog(other_item) + ratio)
  259. for item, other_item in zip(self, other)
  260. ]
  261. if difference:
  262. num.extend(self[-difference:])
  263. # recursive call
  264. return Polynomial(num, 0) % other
  265. class RSBlock(NamedTuple):
  266. total_count: int
  267. data_count: int
  268. def rs_blocks(version, error_correction):
  269. if error_correction not in RS_BLOCK_OFFSET: # pragma: no cover
  270. raise Exception(
  271. "bad rs block @ version: %s / error_correction: %s"
  272. % (version, error_correction)
  273. )
  274. offset = RS_BLOCK_OFFSET[error_correction]
  275. rs_block = RS_BLOCK_TABLE[(version - 1) * 4 + offset]
  276. blocks = []
  277. for i in range(0, len(rs_block), 3):
  278. count, total_count, data_count = rs_block[i : i + 3]
  279. for _ in range(count):
  280. blocks.append(RSBlock(total_count, data_count))
  281. return blocks