Squashed 'third_party/pycrc/' content from commit cb91196b9

Change-Id: Iaed6f7d683e3c11395f10f0724f973363aad2cdb
git-subtree-dir: third_party/pycrc
git-subtree-split: cb91196b920d1f892c05941ed470c7a80cba7596
diff --git a/pycrc/main.py b/pycrc/main.py
new file mode 100644
index 0000000..d446362
--- /dev/null
+++ b/pycrc/main.py
@@ -0,0 +1,241 @@
+#!/usr/bin/env python
+
+#  pycrc -- parameterisable CRC calculation utility and C source code generator
+#
+#  Copyright (c) 2006-2017  Thomas Pircher  <tehpeh-web@tty1.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 parameterisable 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 __future__ import print_function
+from pycrc import progname, version, url
+from pycrc.opt import Options
+from pycrc.algorithms import Crc
+import pycrc.codegen as cg
+import binascii
+import sys
+
+
+
+def print_parameters(opt):
+    """
+    Generate a string with the options pretty-printed (used in the --verbose mode).
+    """
+    return str(cg.ParamBlock(opt, ''))
+
+
+def check_string(opt):
+    """
+    Return the calculated CRC sum of a string.
+    """
+    error = False
+    if opt.undefined_crc_parameters:
+        sys.stderr.write("{0:s}: error: undefined parameters\n".format(progname))
+        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.reflect_in, xor_in=opt.xor_in,
+        reflect_out=opt.reflect_out, xor_out=opt.xor_out,
+        table_idx_width=opt.tbl_idx_width)
+
+    crc = None
+    if opt.algorithm & opt.algo_bit_by_bit:
+        bbb_crc = alg.bit_by_bit(opt.check_string)
+        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.check_string)
+        if crc != None and bbf_crc != crc:
+            error = True
+        crc = bbf_crc
+    if opt.algorithm & opt.algo_table_driven:
+        # no point making the python implementation slower by using less than 8 bits as index.
+        opt.tbl_idx_width = 8
+        tbl_crc = alg.table_driven(opt.check_string)
+        if crc != None and tbl_crc != crc:
+            error = True
+        crc = tbl_crc
+
+    if error:
+        sys.stderr.write("{0:s}: error: different checksums!\n".format(progname))
+        if opt.algorithm & opt.algo_bit_by_bit:
+            sys.stderr.write("       bit-by-bit:        {0:#x}\n".format(bbb_crc))
+        if opt.algorithm & opt.algo_bit_by_bit_fast:
+            sys.stderr.write("       bit-by-bit-fast:   {0:#x}\n".format(bbf_crc))
+        if opt.algorithm & opt.algo_table_driven:
+            sys.stderr.write("       table_driven:      {0:#x}\n".format(tbl_crc))
+        sys.exit(1)
+    return crc
+
+
+def check_hexstring(opt):
+    """
+    Return the calculated CRC sum of a hex string.
+    """
+    if opt.undefined_crc_parameters:
+        sys.stderr.write("{0:s}: error: undefined parameters\n".format(progname))
+        sys.exit(1)
+    if len(opt.check_string) % 2 != 0:
+        opt.check_string = "0" + opt.check_string
+    if sys.version_info >= (3, 0):
+        opt.check_string = bytes(opt.check_string, 'utf_8')
+    try:
+        check_str = bytearray(binascii.unhexlify(opt.check_string))
+    except TypeError:
+        sys.stderr.write(
+            "{0:s}: error: invalid hex string {1:s}\n".format(progname, opt.check_string))
+        sys.exit(1)
+
+    opt.check_string = check_str
+    return check_string(opt)
+
+
+def crc_file_update(alg, register, check_bytes):
+    """
+    Update the CRC using the bit-by-bit-fast CRC algorithm.
+    """
+    # If the input data is a string, convert to bytes.
+    if isinstance(check_bytes, str):
+        check_bytes = bytearray(check_bytes, 'utf_8')
+
+    for octet in check_bytes:
+        if alg.reflect_in:
+            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
+
+
+def check_file(opt):
+    """
+    Calculate the CRC of a file.
+    This algorithm uses the table_driven CRC algorithm.
+    """
+    if opt.undefined_crc_parameters:
+        sys.stderr.write("{0:s}: error: undefined parameters\n".format(progname))
+        sys.exit(1)
+    alg = Crc(
+        width=opt.width, poly=opt.poly,
+        reflect_in=opt.reflect_in, xor_in=opt.xor_in,
+        reflect_out=opt.reflect_out, xor_out=opt.xor_out,
+        table_idx_width=opt.tbl_idx_width)
+
+    if not opt.reflect_in:
+        register = opt.xor_in
+    else:
+        register = alg.reflect(opt.xor_in, opt.width)
+
+    try:
+        with open(opt.check_file, 'rb') as f:
+            check_bytes = bytearray(f.read(1024))
+            while check_bytes != b"":
+                register = crc_file_update(alg, register, check_bytes)
+                check_bytes = bytearray(f.read(1024))
+    except IOError:
+        sys.stderr.write(
+            "{0:s}: error: can't open file {1:s}\n".format(progname, opt.check_file))
+        sys.exit(1)
+
+    if opt.reflect_out:
+        register = alg.reflect(register, opt.width)
+    register = register ^ opt.xor_out
+    return register
+
+
+def write_file(filename, out_str):
+    """
+    Write the content of out_str to filename.
+    """
+    try:
+        out_file = open(filename, "w")
+        out_file.write(out_str)
+        out_file.close()
+    except IOError:
+        sys.stderr.write("{0:s}: error: cannot write to file {1:s}\n".format(progname, filename))
+        sys.exit(1)
+
+
+def main():
+    """
+    Main function.
+    """
+    opt = Options(progname, version, url)
+    opt.parse(sys.argv[1:])
+    if opt.verbose:
+        print(print_parameters(opt))
+    if opt.action == opt.action_check_str:
+        crc = check_string(opt)
+        print("{0:#x}".format(crc))
+    if opt.action == opt.action_check_hex_str:
+        crc = check_hexstring(opt)
+        print("{0:#x}".format(crc))
+    if opt.action == opt.action_check_file:
+        crc = check_file(opt)
+        print("{0:#x}".format(crc))
+    if opt.action in set([
+            opt.action_generate_h, opt.action_generate_c, opt.action_generate_c_main,
+            opt.action_generate_table]):
+        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(
+                "{0:s}: error: unknown action. Please file a bug report!\n".format(progname))
+            sys.exit(1)
+        out = str(cg.File(opt, ''))
+        if opt.output_file == None:
+            print(out)
+        else:
+            write_file(opt.output_file, out)
+    return 0
+
+
+if __name__ == "__main__":
+    sys.exit(main())