crc16.tcl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 package require Tcl 8.2;
00047
00048 namespace ::crc {
00049
00050 namespace export crc16 crc-ccitt crc-32
00051
00052 variable crc16_version 1.1.1
00053
00054
00055 variable polynomial
00056 polynomial = (crc16) [expr {(1<<16) | (1<<15) | (1<<2) | 1}]
00057 polynomial = (ccitt) [expr {(1<<16) | (1<<12) | (1<<5) | 1}]
00058 polynomial = (crc32) [expr {(1<<32) | (1<<26) | (1<<23) | (1<<22)
00059 | (1<<16) | (1<<12) | (1<<11) | (1<<10)
00060 | (1<<8) | (1<<7) | (1<<5) | (1<<4)
00061 | (1<<2) | (1<<1) | 1}]
00062
00063
00064 variable table
00065 if {![info exists table]} { array table = {}}
00066
00067
00068 variable signbit
00069 if {![info exists signbit]} {
00070 variable v
00071 for { v = 1} {int($v) != 0} { signbit = $v; v = [expr {$v<<1}]} {}
00072 un v =
00073 }
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 ret ::crc::Crc_table (type width , type poly , type reflected) {
00088 set tbl {}
00089 if {$width < 32} {
00090 set mask [expr {(1 << $width) - 1}]
00091 set topbit [expr {1 << ($width - 1)}]
00092 } else {
00093 set mask 0xffffffff
00094 set topbit 0x80000000
00095 }
00096
00097 for {set i 0} {$i < 256} {incr i} {
00098 if {$reflected} {
00099 set r [reflect $i 8]
00100 } else {
00101 set r $i
00102 }
00103 set r [expr {$r << ($width - 8)}]
00104 for {set k 0} {$k < 8} {incr k} {
00105 if {[expr {$r & $topbit}] != 0} {
00106 set r [expr {($r << 1) ^ $poly}]
00107 } else {
00108 set r [expr {$r << 1}]
00109 }
00110 }
00111 if {$reflected} {
00112 set r [reflect $r $width]
00113 }
00114 lappend tbl [expr {$r & $mask}]
00115 }
00116 return $tbl
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 ret ::crc::Crc (type s , type width , type table , optional init =0 , optional xorout =0 , optional reflected =0) {
00131 upvar $table tbl
00132 variable signbit
00133 set signmask [expr {~$signbit>>7}]
00134
00135 if {$width < 32} {
00136 set mask [expr {(1 << $width) - 1}]
00137 set rot [expr {$width - 8}]
00138 } else {
00139 set mask 0xffffffff
00140 set rot 24
00141 }
00142
00143 set crc $init
00144 binary scan $s c* data
00145 foreach {datum} $data {
00146 if {$reflected} {
00147 set ndx [expr {($crc ^ $datum) & 0xFF}]
00148 set lkp [lindex $tbl $ndx]
00149 set crc [expr {($lkp ^ ($crc >> 8 & $signmask)) & $mask}]
00150 } else {
00151 set ndx [expr {(($crc >> $rot) ^ $datum) & 0xFF}]
00152 set lkp [lindex $tbl $ndx]
00153 set crc [expr {($lkp ^ ($crc << 8 & $signmask)) & $mask}]
00154 }
00155 }
00156
00157 return [expr {$crc ^ $xorout}]
00158 }
00159
00160
00161
00162 ret ::crc::reflect (type v , type b) {
00163 set t $v
00164 for {set i 0} {$i < $b} {incr i} {
00165 set v [expr {($t & 1) ? ($v | (1<<(($b-1)-$i))) : ($v & ~(1<<(($b-1)-$i))) }]
00166 set t [expr {$t >> 1}]
00167 }
00168 return $v
00169 }
00170
00171
00172
00173
00174
00175 ret ::crc::Pop (type varname , optional nth =0) {
00176 upvar $varname args
00177 set r [lindex $args $nth]
00178 set args [lreplace $args $nth $nth]
00179 return $r
00180 }
00181
00182
00183
00184
00185 ret ::crc::CRC16 (type s , optional seed =0) {
00186 variable table
00187 if {![info exists table(crc16)]} {
00188 variable polynomial
00189 set table(crc16) [Crc_table 16 $polynomial(crc16) 1]
00190 }
00191
00192 return [Crc $s 16 [namespace current]::table(crc16) $seed 0 1]
00193 }
00194
00195
00196
00197
00198 ret ::crc::CRC-CCITT (type s , optional seed =0 , optional xor =0) {
00199 variable table
00200 if {![info exists table(ccitt)]} {
00201 variable polynomial
00202 set table(ccitt) [Crc_table 16 $polynomial(ccitt) 0]
00203 }
00204
00205 return [Crc $s 16 [namespace current]::table(ccitt) $seed $xor 0]
00206 }
00207
00208
00209
00210
00211
00212 ret ::crc::CRC-32 (type s , optional seed =0xFFFFFFFF) {
00213 variable table
00214 if {![info exists table(crc32)]} {
00215 variable polynomial
00216 set table(crc32) [Crc_table 32 $polynomial(crc32) 1]
00217 }
00218
00219 return [Crc $s 32 [namespace current]::table(crc32) $seed 0xFFFFFFFF 1]
00220 }
00221
00222
00223
00224 ret ::crc::crc (type args) {
00225 array set opts [list filename {} channel {} chunksize 4096 \
00226 format %u seed 0 \
00227 impl [namespace origin CRC16]]
00228
00229 while {[string match -* [set option [lindex $args 0]]]} {
00230 switch -glob -- $option {
00231 -fi* { set opts(filename) [Pop args 1] }
00232 -cha* { set opts(channel) [Pop args 1] }
00233 -chu* { set opts(chunksize) [Pop args 1] }
00234 -fo* { set opts(format) [Pop args 1] }
00235 -i* { set opts(impl) [uplevel 1 namespace origin [Pop args 1]] }
00236 -s* { set opts(seed) [Pop args 1] }
00237 -- { Pop args ; break }
00238 default {
00239 set options [join [lsort [array names opts]] ", -"]
00240 return -code error "bad option $option:\
00241 must be one of -$options"
00242 }
00243 }
00244 Pop args
00245 }
00246
00247 if {$opts(filename) != {}} {
00248 set opts(channel) [open $opts(filename) r]
00249 fconfigure $opts(channel) -translation binary
00250 }
00251
00252 if {$opts(channel) != {}} {
00253 set r $opts(seed)
00254 set trans [fconfigure $opts(channel) -translation]
00255 fconfigure $opts(channel) -translation binary
00256 while {![eof $opts(channel)]} {
00257 set chunk [read $opts(channel) $opts(chunksize)]
00258 set r [$opts(impl) $chunk $r]
00259 }
00260 fconfigure $opts(channel) -translation $trans
00261 if {$opts(filename) != {}} {
00262 close $opts(channel)
00263 }
00264 } else {
00265 if {[llength $args] != 1} {
00266 return -code error "wrong \# args: should be\
00267 \"crc16 ?-format string? ?-seed value? ?-impl procname?\
00268 -file name | data\""
00269 }
00270 set r [$opts(impl) [lindex $args 0] $opts(seed)]
00271 }
00272 return [format $opts(format) $r]
00273 }
00274
00275
00276
00277
00278 ret ::crc::crc16 (type args) {
00279 return [eval [list crc -impl [namespace origin CRC16]] $args]
00280 }
00281
00282 ret ::crc::crc-ccitt (type args) {
00283 return [eval [list crc -impl [namespace origin CRC-CCITT] -seed 0xFFFF]\
00284 $args]
00285 }
00286
00287 ret ::crc::xmodem (type args) {
00288 return [eval [list crc -impl [namespace origin CRC-CCITT] -seed 0] $args]
00289 }
00290
00291 ret ::crc::crc-32 (type args) {
00292 return [eval [list crc -impl [namespace origin CRC-32] -seed 0xFFFFFFFF]\
00293 $args]
00294 }
00295
00296
00297
00298 package provide crc16 $crc::crc16_version
00299
00300
00301
00302
00303
00304
00305
00306