Advertisement
MestreLion

cksum16 - CRC-16 checksum of a string

Aug 15th, 2011
829
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 2.91 KB | None | 0 0
  1. #!/bin/bash
  2. #
  3. # Calculates the CRC-16 checksum of a string
  4. # like cksum does for CRC32
  5. #
  6. # Copyright (C) 2011 Rodrigo Silva (MestreLion) <linux@rodrigosilva.com>
  7. # License: GPLv3 or later, at your choice. See <http://www.gnu.org/licenses/gpl>
  8. #
  9. # References:
  10. # 0x10 blog: <http://zeroxten.blogspot.com/search/label/crc16>
  11. # Wine's winemenubuilder: <http://source.winehq.org/git/wine.git>
  12. # The wise, friendly and helpful #bash gurus: <irc://irc.freenet.org/#bash>
  13. #
  14. # NOTE: Newlines are properly handled, but last newline is stripped off
  15. # NOTE: NUL chars are stripped off before computing
  16. # TODO: Test how non-ASCI chars are handled
  17. # FIXME: Decent usage explaining options and behaviour
  18.  
  19. self="${0##*/}"
  20.  
  21. error() {
  22.     local msg="$1"
  23.     printf "%s: %s\nTry '%s --help' for more information\n" \
  24.            "$self" "$msg" "$self" >&2
  25.     exit 1
  26. }
  27. usage() {
  28.     printf "Print CRC-16 checksum (and optionally the byte count) of STRING\n\n"
  29.     printf "Usage: %s [--hex|--dec|--format FORMAT] [--count] [STRING]\n\n" "$self"
  30.     printf "Default format is decimal. If no string or -, reads from stdin\n"
  31.     printf "NULs and last newline are ignored. Use for texts, not binary data.\n"
  32.     exit
  33. }
  34. crc16()
  35. (
  36.     export LC_ALL=C
  37.    
  38.     local string="$1"
  39.     local format="${2:-"%d"}"
  40.     local crc=0
  41.     local i j xor_poly
  42.    
  43.     for ((i=0; i<${#string}; i++)); do
  44.        
  45.         c=$(printf "%d" "'${string:i:1}")
  46.         for ((j=0; j<8; c>>=1, j++)); do
  47.  
  48.             (( xor_poly = (c ^ crc) & 1 ))
  49.             (( crc >>= 1 ))
  50.             (( xor_poly )) && (( crc ^= 0xA001 ))
  51.  
  52.         done
  53.     done
  54.     printf "$format" "$crc"
  55. )
  56.  
  57. while [[ $# -gt 0 ]]; do
  58.     arg="$1"; shift
  59.     case "$arg" in
  60.     -h|--help  ) usage                              ;;
  61.     -x|--hex   ) format="%04X"                      ;;
  62.     -d|--dec   ) format="%d"                        ;;
  63.     -f|--format) format="$1"; shift                 ;;
  64.     -c|--count ) count=1                            ;;
  65.     --         ) string="$1"                ; break ;;
  66.     -          ) string=$( cat )   ; done=1 ; break ;;
  67.     -*         ) error "unrecognized option '$arg'" ;;
  68.     *          ) string="$arg"     ; done=1 ; break ;;
  69.     esac
  70. done
  71.  
  72. [[ "$done" || "$string" ]] || string=$( cat )
  73.  
  74. # Expected command-line behaviour table:
  75. # <none>    => str = stdin
  76. # -         => str = stdin
  77. # something => str = something
  78. # -- <none> => str = stdin
  79. # -- someth => str = something
  80.  
  81. [[ "$string" ]] || error "missing string"
  82.  
  83. crc16 "$string" "$format"
  84. [[ "$count" ]] && printf " %d" "${#string}"
  85. printf "\n"
  86.  
  87. #Original function from winemenubuilder.c (for reference)
  88. #static unsigned short crc16(const char* string)
  89. #{
  90. #    unsigned short crc = 0;
  91. #    int i, j, xor_poly;
  92. #
  93. #    for (i = 0; string[i] != 0; i++)
  94. #    {
  95. #        char c = string[i];
  96. #        for (j = 0; j < 8; c >>= 1, j++)
  97. #        {
  98. #            xor_poly = (c ^ crc) & 1;
  99. #            crc >>= 1;
  100. #            if (xor_poly)
  101. #                crc ^= 0xa001;
  102. #        }
  103. #    }
  104. #    return crc;
  105. #}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement