predefined.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #-----------------------------------------------------------------------------
  2. # Copyright (c) 2010 Craig McQueen
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a copy
  5. # of this software and associated documentation files (the "Software"), to deal
  6. # in the Software without restriction, including without limitation the rights
  7. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. # copies of the Software, and to permit persons to whom the Software is
  9. # furnished to do so, subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be included in
  12. # all copies or substantial portions of the Software.
  13. #
  14. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. # SOFTWARE.
  21. #-----------------------------------------------------------------------------
  22. '''
  23. crcmod.predefined defines some well-known CRC algorithms.
  24. To use it, e.g.:
  25. import crcmod.predefined
  26. crc32func = crcmod.predefined.mkPredefinedCrcFun("crc-32")
  27. crc32class = crcmod.predefined.PredefinedCrc("crc-32")
  28. crcmod.predefined.Crc is an alias for crcmod.predefined.PredefinedCrc
  29. But if doing 'from crc.predefined import *', only PredefinedCrc is imported.
  30. '''
  31. # local imports
  32. import crcmod
  33. __all__ = [
  34. 'PredefinedCrc',
  35. 'mkPredefinedCrcFun',
  36. ]
  37. REVERSE = True
  38. NON_REVERSE = False
  39. # The following table defines the parameters of well-known CRC algorithms.
  40. # The "Check" value is the CRC for the ASCII byte sequence b"123456789". It
  41. # can be used for unit tests.
  42. _crc_definitions_table = [
  43. # Name Identifier-name, Poly Reverse Init-value XOR-out Check
  44. [ 'crc-8', 'Crc8', 0x107, NON_REVERSE, 0x00, 0x00, 0xF4, ],
  45. [ 'crc-8-darc', 'Crc8Darc', 0x139, REVERSE, 0x00, 0x00, 0x15, ],
  46. [ 'crc-8-i-code', 'Crc8ICode', 0x11D, NON_REVERSE, 0xFD, 0x00, 0x7E, ],
  47. [ 'crc-8-itu', 'Crc8Itu', 0x107, NON_REVERSE, 0x55, 0x55, 0xA1, ],
  48. [ 'crc-8-maxim', 'Crc8Maxim', 0x131, REVERSE, 0x00, 0x00, 0xA1, ],
  49. [ 'crc-8-rohc', 'Crc8Rohc', 0x107, REVERSE, 0xFF, 0x00, 0xD0, ],
  50. [ 'crc-8-wcdma', 'Crc8Wcdma', 0x19B, REVERSE, 0x00, 0x00, 0x25, ],
  51. [ 'crc-16', 'Crc16', 0x18005, REVERSE, 0x0000, 0x0000, 0xBB3D, ],
  52. [ 'crc-16-buypass', 'Crc16Buypass', 0x18005, NON_REVERSE, 0x0000, 0x0000, 0xFEE8, ],
  53. [ 'crc-16-dds-110', 'Crc16Dds110', 0x18005, NON_REVERSE, 0x800D, 0x0000, 0x9ECF, ],
  54. [ 'crc-16-dect', 'Crc16Dect', 0x10589, NON_REVERSE, 0x0001, 0x0001, 0x007E, ],
  55. [ 'crc-16-dnp', 'Crc16Dnp', 0x13D65, REVERSE, 0xFFFF, 0xFFFF, 0xEA82, ],
  56. [ 'crc-16-en-13757', 'Crc16En13757', 0x13D65, NON_REVERSE, 0xFFFF, 0xFFFF, 0xC2B7, ],
  57. [ 'crc-16-genibus', 'Crc16Genibus', 0x11021, NON_REVERSE, 0x0000, 0xFFFF, 0xD64E, ],
  58. [ 'crc-16-maxim', 'Crc16Maxim', 0x18005, REVERSE, 0xFFFF, 0xFFFF, 0x44C2, ],
  59. [ 'crc-16-mcrf4xx', 'Crc16Mcrf4xx', 0x11021, REVERSE, 0xFFFF, 0x0000, 0x6F91, ],
  60. [ 'crc-16-riello', 'Crc16Riello', 0x11021, REVERSE, 0x554D, 0x0000, 0x63D0, ],
  61. [ 'crc-16-t10-dif', 'Crc16T10Dif', 0x18BB7, NON_REVERSE, 0x0000, 0x0000, 0xD0DB, ],
  62. [ 'crc-16-teledisk', 'Crc16Teledisk', 0x1A097, NON_REVERSE, 0x0000, 0x0000, 0x0FB3, ],
  63. [ 'crc-16-usb', 'Crc16Usb', 0x18005, REVERSE, 0x0000, 0xFFFF, 0xB4C8, ],
  64. [ 'x-25', 'CrcX25', 0x11021, REVERSE, 0x0000, 0xFFFF, 0x906E, ],
  65. [ 'xmodem', 'CrcXmodem', 0x11021, NON_REVERSE, 0x0000, 0x0000, 0x31C3, ],
  66. [ 'modbus', 'CrcModbus', 0x18005, REVERSE, 0xFFFF, 0x0000, 0x4B37, ],
  67. # Note definitions of CCITT are disputable. See:
  68. # http://homepages.tesco.net/~rainstorm/crc-catalogue.htm
  69. # http://web.archive.org/web/20071229021252/http://www.joegeluso.com/software/articles/ccitt.htm
  70. [ 'kermit', 'CrcKermit', 0x11021, REVERSE, 0x0000, 0x0000, 0x2189, ],
  71. [ 'crc-ccitt-false', 'CrcCcittFalse', 0x11021, NON_REVERSE, 0xFFFF, 0x0000, 0x29B1, ],
  72. [ 'crc-aug-ccitt', 'CrcAugCcitt', 0x11021, NON_REVERSE, 0x1D0F, 0x0000, 0xE5CC, ],
  73. [ 'crc-24', 'Crc24', 0x1864CFB, NON_REVERSE, 0xB704CE, 0x000000, 0x21CF02, ],
  74. [ 'crc-24-flexray-a', 'Crc24FlexrayA', 0x15D6DCB, NON_REVERSE, 0xFEDCBA, 0x000000, 0x7979BD, ],
  75. [ 'crc-24-flexray-b', 'Crc24FlexrayB', 0x15D6DCB, NON_REVERSE, 0xABCDEF, 0x000000, 0x1F23B8, ],
  76. [ 'crc-32', 'Crc32', 0x104C11DB7, REVERSE, 0x00000000, 0xFFFFFFFF, 0xCBF43926, ],
  77. [ 'crc-32-bzip2', 'Crc32Bzip2', 0x104C11DB7, NON_REVERSE, 0x00000000, 0xFFFFFFFF, 0xFC891918, ],
  78. [ 'crc-32c', 'Crc32C', 0x11EDC6F41, REVERSE, 0x00000000, 0xFFFFFFFF, 0xE3069283, ],
  79. [ 'crc-32d', 'Crc32D', 0x1A833982B, REVERSE, 0x00000000, 0xFFFFFFFF, 0x87315576, ],
  80. [ 'crc-32-mpeg', 'Crc32Mpeg', 0x104C11DB7, NON_REVERSE, 0xFFFFFFFF, 0x00000000, 0x0376E6E7, ],
  81. [ 'posix', 'CrcPosix', 0x104C11DB7, NON_REVERSE, 0xFFFFFFFF, 0xFFFFFFFF, 0x765E7680, ],
  82. [ 'crc-32q', 'Crc32Q', 0x1814141AB, NON_REVERSE, 0x00000000, 0x00000000, 0x3010BF7F, ],
  83. [ 'jamcrc', 'CrcJamCrc', 0x104C11DB7, REVERSE, 0xFFFFFFFF, 0x00000000, 0x340BC6D9, ],
  84. [ 'xfer', 'CrcXfer', 0x1000000AF, NON_REVERSE, 0x00000000, 0x00000000, 0xBD0BE338, ],
  85. # 64-bit
  86. # Name Identifier-name, Poly Reverse Init-value XOR-out Check
  87. [ 'crc-64', 'Crc64', 0x1000000000000001B, REVERSE, 0x0000000000000000, 0x0000000000000000, 0x46A5A9388A5BEFFE, ],
  88. [ 'crc-64-we', 'Crc64We', 0x142F0E1EBA9EA3693, NON_REVERSE, 0x0000000000000000, 0xFFFFFFFFFFFFFFFF, 0x62EC59E3F1A4F00A, ],
  89. [ 'crc-64-jones', 'Crc64Jones', 0x1AD93D23594C935A9, REVERSE, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000, 0xCAA717168609F281, ],
  90. ]
  91. def _simplify_name(name):
  92. """
  93. Reduce CRC definition name to a simplified form:
  94. * lowercase
  95. * dashes removed
  96. * spaces removed
  97. * any initial "CRC" string removed
  98. """
  99. name = name.lower()
  100. name = name.replace('-', '')
  101. name = name.replace(' ', '')
  102. if name.startswith('crc'):
  103. name = name[len('crc'):]
  104. return name
  105. _crc_definitions_by_name = {}
  106. _crc_definitions_by_identifier = {}
  107. _crc_definitions = []
  108. _crc_table_headings = [ 'name', 'identifier', 'poly', 'reverse', 'init', 'xor_out', 'check' ]
  109. for table_entry in _crc_definitions_table:
  110. crc_definition = dict(zip(_crc_table_headings, table_entry))
  111. _crc_definitions.append(crc_definition)
  112. name = _simplify_name(table_entry[0])
  113. if name in _crc_definitions_by_name:
  114. raise Exception("Duplicate entry for '{0}' in CRC table".format(name))
  115. _crc_definitions_by_name[name] = crc_definition
  116. _crc_definitions_by_identifier[table_entry[1]] = crc_definition
  117. def _get_definition_by_name(crc_name):
  118. definition = _crc_definitions_by_name.get(_simplify_name(crc_name), None)
  119. if not definition:
  120. definition = _crc_definitions_by_identifier.get(crc_name, None)
  121. if not definition:
  122. raise KeyError("Unkown CRC name '{0}'".format(crc_name))
  123. return definition
  124. class PredefinedCrc(crcmod.Crc):
  125. def __init__(self, crc_name):
  126. definition = _get_definition_by_name(crc_name)
  127. super().__init__(poly=definition['poly'], initCrc=definition['init'], rev=definition['reverse'], xorOut=definition['xor_out'])
  128. # crcmod.predefined.Crc is an alias for crcmod.predefined.PredefinedCrc
  129. Crc = PredefinedCrc
  130. def mkPredefinedCrcFun(crc_name):
  131. definition = _get_definition_by_name(crc_name)
  132. return crcmod.mkCrcFun(poly=definition['poly'], initCrc=definition['init'], rev=definition['reverse'], xorOut=definition['xor_out'])
  133. # crcmod.predefined.mkCrcFun is an alias for crcmod.predefined.mkPredefinedCrcFun
  134. mkCrcFun = mkPredefinedCrcFun