Added pycrc library (MIT License) for CRC calculations to the repository.
This commit is contained in:
parent
c35e26f025
commit
3233dc96b1
24 changed files with 6136 additions and 0 deletions
253
pycrc/pycrc.py
Normal file
253
pycrc/pycrc.py
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: Latin-1 -*-
|
||||
|
||||
# pycrc -- parametrisable CRC calculation utility and C source code generator
|
||||
#
|
||||
# Copyright (c) 2006-2012 Thomas Pircher <tehpeh@gmx.net>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
# IN THE SOFTWARE.
|
||||
|
||||
|
||||
"""
|
||||
pycrc is a fully parametrisable Cyclic Redundancy Check (CRC) calculation
|
||||
utility and C source code generator written in Python.
|
||||
|
||||
It can:
|
||||
- generate the checksum of a string
|
||||
- generate the checksum of a file
|
||||
- generate the C header file and source of any of the algorithms below
|
||||
|
||||
It supports the following CRC algorithms:
|
||||
- bit-by-bit the basic algorithm which operates bit by bit on the
|
||||
augmented message
|
||||
- bit-by-bit-fast a variation of the simple bit-by-bit algorithm
|
||||
- table-driven the standard table driven algorithm
|
||||
"""
|
||||
|
||||
from crc_opt import Options
|
||||
from crc_algorithms import Crc
|
||||
from crc_parser import MacroParser
|
||||
import binascii
|
||||
import sys
|
||||
|
||||
|
||||
# function print_parameters
|
||||
###############################################################################
|
||||
def print_parameters(opt):
|
||||
"""
|
||||
Generate a string with the options pretty-printed (used in the --verbose mode).
|
||||
"""
|
||||
in_str = ""
|
||||
in_str += "Width = $crc_width\n"
|
||||
in_str += "Poly = $crc_poly\n"
|
||||
in_str += "ReflectIn = $crc_reflect_in\n"
|
||||
in_str += "XorIn = $crc_xor_in\n"
|
||||
in_str += "ReflectOut = $crc_reflect_out\n"
|
||||
in_str += "XorOut = $crc_xor_out\n"
|
||||
in_str += "Algorithm = $crc_algorithm\n"
|
||||
|
||||
mp = MacroParser(opt)
|
||||
mp.parse(in_str)
|
||||
return mp.out_str
|
||||
|
||||
|
||||
# function check_string
|
||||
###############################################################################
|
||||
def check_string(opt):
|
||||
"""
|
||||
Return the calculated CRC sum of a string.
|
||||
"""
|
||||
error = False
|
||||
if opt.UndefinedCrcParameters:
|
||||
sys.stderr.write("%s: error: undefined parameters\n" % sys.argv[0])
|
||||
sys.exit(1)
|
||||
if opt.Algorithm == 0:
|
||||
opt.Algorithm = opt.Algo_Bit_by_Bit | opt.Algo_Bit_by_Bit_Fast | opt.Algo_Table_Driven
|
||||
|
||||
alg = Crc(width = opt.Width, poly = opt.Poly,
|
||||
reflect_in = opt.ReflectIn, xor_in = opt.XorIn,
|
||||
reflect_out = opt.ReflectOut, xor_out = opt.XorOut,
|
||||
table_idx_width = opt.TableIdxWidth)
|
||||
crc = None
|
||||
if opt.Algorithm & opt.Algo_Bit_by_Bit:
|
||||
bbb_crc = alg.bit_by_bit(opt.CheckString)
|
||||
if crc != None and bbb_crc != crc:
|
||||
error = True
|
||||
crc = bbb_crc
|
||||
if opt.Algorithm & opt.Algo_Bit_by_Bit_Fast:
|
||||
bbf_crc = alg.bit_by_bit_fast(opt.CheckString)
|
||||
if crc != None and bbf_crc != crc:
|
||||
error = True
|
||||
crc = bbf_crc
|
||||
if opt.Algorithm & opt.Algo_Table_Driven:
|
||||
opt.TableIdxWidth = 8 # no point making the python implementation slower by using less than 8 bits as index.
|
||||
tbl_crc = alg.table_driven(opt.CheckString)
|
||||
if crc != None and tbl_crc != crc:
|
||||
error = True
|
||||
crc = tbl_crc
|
||||
|
||||
if error:
|
||||
sys.stderr.write("%s: error: different checksums!\n" % sys.argv[0])
|
||||
if opt.Algorithm & opt.Algo_Bit_by_Bit:
|
||||
sys.stderr.write(" bit-by-bit: 0x%x\n" % bbb_crc)
|
||||
if opt.Algorithm & opt.Algo_Bit_by_Bit_Fast:
|
||||
sys.stderr.write(" bit-by-bit-fast: 0x%x\n" % bbf_crc)
|
||||
if opt.Algorithm & opt.Algo_Table_Driven:
|
||||
sys.stderr.write(" table_driven: 0x%x\n" % tbl_crc)
|
||||
sys.exit(1)
|
||||
return crc
|
||||
|
||||
|
||||
# function check_hexstring
|
||||
###############################################################################
|
||||
def check_hexstring(opt):
|
||||
"""
|
||||
Return the calculated CRC sum of a hex string.
|
||||
"""
|
||||
if opt.UndefinedCrcParameters:
|
||||
sys.stderr.write("%s: error: undefined parameters\n" % sys.argv[0])
|
||||
sys.exit(1)
|
||||
if len(opt.CheckString) % 2 != 0:
|
||||
opt.CheckString = "0" + opt.CheckString
|
||||
try:
|
||||
check_str = binascii.unhexlify(opt.CheckString)
|
||||
except TypeError:
|
||||
sys.stderr.write("%s: error: invalid hex string %s\n" % (sys.argv[0], opt.CheckString))
|
||||
sys.exit(1)
|
||||
|
||||
opt.CheckString = check_str
|
||||
return check_string(opt)
|
||||
|
||||
|
||||
# function crc_file_update
|
||||
###############################################################################
|
||||
def crc_file_update(alg, register, check_str):
|
||||
"""
|
||||
Update the CRC using the bit-by-bit-fast CRC algorithm.
|
||||
"""
|
||||
for i in range(len(check_str)):
|
||||
octet = ord(check_str[i])
|
||||
if alg.ReflectIn:
|
||||
octet = alg.reflect(octet, 8)
|
||||
for j in range(8):
|
||||
bit = register & alg.MSB_Mask
|
||||
register <<= 1
|
||||
if octet & (0x80 >> j):
|
||||
bit ^= alg.MSB_Mask
|
||||
if bit:
|
||||
register ^= alg.Poly
|
||||
register &= alg.Mask
|
||||
return register
|
||||
|
||||
|
||||
# function check_file
|
||||
###############################################################################
|
||||
def check_file(opt):
|
||||
"""
|
||||
Calculate the CRC of a file.
|
||||
This algorithm uses the table_driven CRC algorithm.
|
||||
"""
|
||||
if opt.UndefinedCrcParameters:
|
||||
sys.stderr.write("%s: error: undefined parameters\n" % sys.argv[0])
|
||||
sys.exit(1)
|
||||
alg = Crc(width = opt.Width, poly = opt.Poly,
|
||||
reflect_in = opt.ReflectIn, xor_in = opt.XorIn,
|
||||
reflect_out = opt.ReflectOut, xor_out = opt.XorOut,
|
||||
table_idx_width = opt.TableIdxWidth)
|
||||
|
||||
try:
|
||||
in_file = open(opt.CheckFile, 'rb')
|
||||
except IOError:
|
||||
sys.stderr.write("%s: error: can't open file %s\n" % (sys.argv[0], opt.CheckFile))
|
||||
sys.exit(1)
|
||||
|
||||
if not opt.ReflectIn:
|
||||
register = opt.XorIn
|
||||
else:
|
||||
register = alg.reflect(opt.XorIn, opt.Width)
|
||||
try:
|
||||
check_str = in_file.read()
|
||||
except IOError:
|
||||
sys.stderr.write("%s: error: can't open read %s\n" % (sys.argv[0], opt.CheckFile))
|
||||
sys.exit(1)
|
||||
while len(check_str):
|
||||
register = crc_file_update(alg, register, check_str)
|
||||
try:
|
||||
check_str = in_file.read()
|
||||
except IOError:
|
||||
sys.stderr.write("%s: error: can't open read %s\n" % (sys.argv[0], opt.CheckFile))
|
||||
sys.exit(1)
|
||||
in_file.close()
|
||||
|
||||
if opt.ReflectOut:
|
||||
register = alg.reflect(register, opt.Width)
|
||||
register = register ^ opt.XorOut
|
||||
return register
|
||||
|
||||
|
||||
# main function
|
||||
###############################################################################
|
||||
def main():
|
||||
"""
|
||||
Main function.
|
||||
"""
|
||||
opt = Options()
|
||||
opt.parse(sys.argv[1:])
|
||||
if opt.Verbose:
|
||||
print(print_parameters(opt))
|
||||
if opt.Action == opt.Action_Check_String:
|
||||
crc = check_string(opt)
|
||||
print("0x%x" % crc)
|
||||
if opt.Action == opt.Action_Check_Hex_String:
|
||||
crc = check_hexstring(opt)
|
||||
print("0x%x" % crc)
|
||||
if opt.Action == opt.Action_Check_File:
|
||||
crc = check_file(opt)
|
||||
print("0x%x" % crc)
|
||||
if opt.Action == opt.Action_Generate_H or opt.Action == opt.Action_Generate_C or opt.Action == opt.Action_Generate_C_Main or opt.Action == opt.Action_Generate_Table:
|
||||
mp = MacroParser(opt)
|
||||
if opt.Action == opt.Action_Generate_H:
|
||||
in_str = "$h_template"
|
||||
elif opt.Action == opt.Action_Generate_C:
|
||||
in_str = "$c_template"
|
||||
elif opt.Action == opt.Action_Generate_C_Main:
|
||||
in_str = "$c_template\n\n$main_template"
|
||||
elif opt.Action == opt.Action_Generate_Table:
|
||||
in_str = "$crc_table_init"
|
||||
else:
|
||||
sys.stderr.write("%s: error: unknown action. Please file a bug report!\n" % sys.argv[0])
|
||||
sys.exit(1)
|
||||
mp.parse(in_str)
|
||||
if opt.OutputFile == None:
|
||||
print(mp.out_str)
|
||||
else:
|
||||
try:
|
||||
out_file = open(opt.OutputFile, "w")
|
||||
out_file.write(mp.out_str)
|
||||
out_file.close()
|
||||
except IOError:
|
||||
sys.stderr.write("%s: error: cannot write to file %s\n" % (sys.argv[0], opt.OutputFile))
|
||||
sys.exit(1)
|
||||
return 0
|
||||
|
||||
|
||||
# program entry point
|
||||
###############################################################################
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue