1 //----------------------------------------------------------------------------- 2 // Low level CRC functions for use by crcmod. This version is the C 3 // implementation that corresponds to the Python module _crcfunpy. This module 4 // will be used by crcmod if it is built for the target platform. Otherwise, 5 // the Python module is used. 6 // 7 // Copyright (c) 2004 Raymond L. Buvel 8 // 9 // Permission is hereby granted, free of charge, to any person obtaining a copy 10 // of this software and associated documentation files (the "Software"), to 11 // deal in the Software without restriction, including without limitation the 12 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 13 // sell copies of the Software, and to permit persons to whom the Software is 14 // furnished to do so, subject to the following conditions: 15 // 16 // The above copyright notice and this permission notice shall be included in 17 // all copies or substantial portions of the Software. 18 // 19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 25 // IN THE SOFTWARE. 26 //----------------------------------------------------------------------------- 27 28 // Force Py_ssize_t to be used for s# conversions. 29 #define PY_SSIZE_T_CLEAN 30 #include <Python.h> 31 32 // Make compatible with previous Python versions 33 #if PY_VERSION_HEX < 0x02050000 34 typedef int Py_ssize_t; 35 #define PY_SSIZE_T_MAX INT_MAX 36 #define PY_SSIZE_T_MIN INT_MIN 37 #endif 38 39 // Note: the type declarations are set up to work on 32-bit platforms using the 40 // GNU C compiler. They will need to be adjusted for other platforms. In 41 // particular, the Microsoft Windows compiler uses _int64 instead of long long. 42 43 // Define a few types to make it easier to port to other platforms. 44 typedef unsigned char UINT8; 45 typedef unsigned short UINT16; 46 typedef unsigned int UINT32; 47 typedef unsigned long long UINT64; 48 49 // Define some macros for the data format strings. The INPUT strings are for 50 // decoding the input parameters to the function which are (data, crc, table). 51 52 // Note: these format strings use codes that are new in Python 2.3 so it would 53 // be necessary to rewrite the code for versions earlier than 2.3. 54 55 #define INPUT8 "s#Bs#" 56 #define INPUT16 "s#Hs#" 57 #define INPUT32 "s#Is#" 58 #define INPUT64 "s#Ks#" 59 60 // Define some macros that extract the specified byte from an integral value in 61 // what should be a platform independent manner. 62 #define BYTE0(x) ((UINT8)(x)) 63 #define BYTE1(x) ((UINT8)((x) >> 8)) 64 #define BYTE2(x) ((UINT8)((x) >> 16)) 65 #define BYTE3(x) ((UINT8)((x) >> 24)) 66 #define BYTE7(x) ((UINT8)((x) >> 56)) 67 68 //----------------------------------------------------------------------------- 69 // Compute a 8-bit crc over the input data. 70 // Inputs: 71 // data - string containing the data 72 // crc - unsigned integer containing the initial crc 73 // table - string containing the 8-bit table corresponding to the generator 74 // polynomial. 75 // Returns: 76 // crc - unsigned integer containing the resulting crc 77 78 static PyObject* 79 _crc8(PyObject* self, PyObject* args) 80 { 81 UINT8 crc; 82 UINT8* data; 83 Py_ssize_t dataLen; 84 UINT8* table; 85 Py_ssize_t tableLen; 86 87 if (!PyArg_ParseTuple(args, INPUT8, &data, &dataLen, &crc, 88 &table, &tableLen)) 89 { 90 return NULL; 91 } 92 93 if (tableLen != 256) 94 { 95 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); 96 return NULL; 97 } 98 99 while (dataLen--) 100 { 101 crc = table[*data ^ crc]; 102 data++; 103 } 104 105 return PyInt_FromLong((long)crc); 106 } 107 108 //----------------------------------------------------------------------------- 109 // Compute a 8-bit crc over the input data. The data stream is bit reversed 110 // during the computation. 111 // Inputs: 112 // data - string containing the data 113 // crc - unsigned integer containing the initial crc 114 // table - string containing the 8-bit table corresponding to the generator 115 // polynomial. 116 // Returns: 117 // crc - unsigned integer containing the resulting crc 118 119 static PyObject* 120 _crc8r(PyObject* self, PyObject* args) 121 { 122 UINT8 crc; 123 UINT8* data; 124 Py_ssize_t dataLen; 125 UINT8* table; 126 Py_ssize_t tableLen; 127 128 if (!PyArg_ParseTuple(args, INPUT8, &data, &dataLen, &crc, 129 &table, &tableLen)) 130 { 131 return NULL; 132 } 133 134 if (tableLen != 256) 135 { 136 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); 137 return NULL; 138 } 139 140 while (dataLen--) 141 { 142 crc = table[*data ^ crc]; 143 data++; 144 } 145 146 return PyInt_FromLong((long)crc); 147 } 148 149 //----------------------------------------------------------------------------- 150 // Compute a 16-bit crc over the input data. 151 // Inputs: 152 // data - string containing the data 153 // crc - unsigned integer containing the initial crc 154 // table - string containing the 16-bit table corresponding to the generator 155 // polynomial. 156 // Returns: 157 // crc - unsigned integer containing the resulting crc 158 159 static PyObject* 160 _crc16(PyObject* self, PyObject* args) 161 { 162 UINT16 crc; 163 UINT8* data; 164 Py_ssize_t dataLen; 165 UINT16* table; 166 Py_ssize_t tableLen; 167 168 if (!PyArg_ParseTuple(args, INPUT16, &data, &dataLen, &crc, 169 &table, &tableLen)) 170 { 171 return NULL; 172 } 173 174 if (tableLen != 256*2) 175 { 176 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); 177 return NULL; 178 } 179 180 while (dataLen--) 181 { 182 crc = table[*data ^ BYTE1(crc)] ^ (crc << 8); 183 data++; 184 } 185 186 return PyInt_FromLong((long)crc); 187 } 188 189 //----------------------------------------------------------------------------- 190 // Compute a 16-bit crc over the input data. The data stream is bit reversed 191 // during the computation. 192 // Inputs: 193 // data - string containing the data 194 // crc - unsigned integer containing the initial crc 195 // table - string containing the 16-bit table corresponding to the generator 196 // polynomial. 197 // Returns: 198 // crc - unsigned integer containing the resulting crc 199 200 static PyObject* 201 _crc16r(PyObject* self, PyObject* args) 202 { 203 UINT16 crc; 204 UINT8* data; 205 Py_ssize_t dataLen; 206 UINT16* table; 207 Py_ssize_t tableLen; 208 209 if (!PyArg_ParseTuple(args, INPUT16, &data, &dataLen, &crc, 210 &table, &tableLen)) 211 { 212 return NULL; 213 } 214 215 if (tableLen != 256*2) 216 { 217 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); 218 return NULL; 219 } 220 221 while (dataLen--) 222 { 223 crc = table[*data ^ BYTE0(crc)] ^ (crc >> 8); 224 data++; 225 } 226 227 return PyInt_FromLong((long)crc); 228 } 229 230 //----------------------------------------------------------------------------- 231 // Compute a 24-bit crc over the input data. 232 // Inputs: 233 // data - string containing the data 234 // crc - unsigned integer containing the initial crc 235 // table - string containing the 24-bit table corresponding to the generator 236 // polynomial. 237 // Returns: 238 // crc - unsigned integer containing the resulting crc 239 240 static PyObject* 241 _crc24(PyObject* self, PyObject* args) 242 { 243 UINT32 crc; 244 UINT8* data; 245 Py_ssize_t dataLen; 246 UINT32* table; 247 Py_ssize_t tableLen; 248 249 if (!PyArg_ParseTuple(args, INPUT32, &data, &dataLen, &crc, 250 &table, &tableLen)) 251 { 252 return NULL; 253 } 254 255 if (tableLen != 256*4) 256 { 257 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); 258 return NULL; 259 } 260 261 while (dataLen--) 262 { 263 crc = table[*data ^ BYTE2(crc)] ^ (crc << 8); 264 data++; 265 } 266 267 return PyInt_FromLong((long)(crc & 0xFFFFFFU)); 268 } 269 270 //----------------------------------------------------------------------------- 271 // Compute a 24-bit crc over the input data. The data stream is bit reversed 272 // during the computation. 273 // Inputs: 274 // data - string containing the data 275 // crc - unsigned integer containing the initial crc 276 // table - string containing the 24-bit table corresponding to the generator 277 // polynomial. 278 // Returns: 279 // crc - unsigned integer containing the resulting crc 280 281 static PyObject* 282 _crc24r(PyObject* self, PyObject* args) 283 { 284 UINT32 crc; 285 UINT8* data; 286 Py_ssize_t dataLen; 287 UINT32* table; 288 Py_ssize_t tableLen; 289 290 if (!PyArg_ParseTuple(args, INPUT32, &data, &dataLen, &crc, 291 &table, &tableLen)) 292 { 293 return NULL; 294 } 295 296 if (tableLen != 256*4) 297 { 298 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); 299 return NULL; 300 } 301 302 crc = crc & 0xFFFFFFU; 303 while (dataLen--) 304 { 305 crc = table[*data ^ BYTE0(crc)] ^ (crc >> 8); 306 data++; 307 } 308 309 return PyInt_FromLong((long)crc); 310 } 311 312 //----------------------------------------------------------------------------- 313 // Compute a 32-bit crc over the input data. 314 // Inputs: 315 // data - string containing the data 316 // crc - unsigned integer containing the initial crc 317 // table - string containing the 32-bit table corresponding to the generator 318 // polynomial. 319 // Returns: 320 // crc - unsigned integer containing the resulting crc 321 322 static PyObject* 323 _crc32(PyObject* self, PyObject* args) 324 { 325 UINT32 crc; 326 UINT8* data; 327 Py_ssize_t dataLen; 328 UINT32* table; 329 Py_ssize_t tableLen; 330 331 if (!PyArg_ParseTuple(args, INPUT32, &data, &dataLen, &crc, 332 &table, &tableLen)) 333 { 334 return NULL; 335 } 336 337 if (tableLen != 256*4) 338 { 339 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); 340 return NULL; 341 } 342 343 while (dataLen--) 344 { 345 crc = table[*data ^ BYTE3(crc)] ^ (crc << 8); 346 data++; 347 } 348 349 return PyLong_FromUnsignedLong(crc); 350 } 351 352 //----------------------------------------------------------------------------- 353 // Compute a 32-bit crc over the input data. The data stream is bit reversed 354 // during the computation. 355 // Inputs: 356 // data - string containing the data 357 // crc - unsigned integer containing the initial crc 358 // table - string containing the 32-bit table corresponding to the generator 359 // polynomial. 360 // Returns: 361 // crc - unsigned integer containing the resulting crc 362 363 static PyObject* 364 _crc32r(PyObject* self, PyObject* args) 365 { 366 UINT32 crc; 367 UINT8* data; 368 Py_ssize_t dataLen; 369 UINT32* table; 370 Py_ssize_t tableLen; 371 372 if (!PyArg_ParseTuple(args, INPUT32, &data, &dataLen, &crc, 373 &table, &tableLen)) 374 { 375 return NULL; 376 } 377 378 if (tableLen != 256*4) 379 { 380 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); 381 return NULL; 382 } 383 384 while (dataLen--) 385 { 386 crc = table[*data ^ BYTE0(crc)] ^ (crc >> 8); 387 data++; 388 } 389 390 return PyLong_FromUnsignedLong(crc); 391 } 392 393 //----------------------------------------------------------------------------- 394 // Compute a 64-bit crc over the input data. 395 // Inputs: 396 // data - string containing the data 397 // crc - unsigned integer containing the initial crc 398 // table - string containing the 64-bit table corresponding to the generator 399 // polynomial. 400 // Returns: 401 // crc - unsigned integer containing the resulting crc 402 403 static PyObject* 404 _crc64(PyObject* self, PyObject* args) 405 { 406 UINT64 crc; 407 UINT8* data; 408 Py_ssize_t dataLen; 409 UINT64* table; 410 Py_ssize_t tableLen; 411 412 if (!PyArg_ParseTuple(args, INPUT64, &data, &dataLen, &crc, 413 &table, &tableLen)) 414 { 415 return NULL; 416 } 417 418 if (tableLen != 256*8) 419 { 420 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); 421 return NULL; 422 } 423 424 while (dataLen--) 425 { 426 crc = table[*data ^ BYTE7(crc)] ^ (crc << 8); 427 data++; 428 } 429 430 return PyLong_FromUnsignedLongLong(crc); 431 } 432 433 //----------------------------------------------------------------------------- 434 // Compute a 64-bit crc over the input data. The data stream is bit reversed 435 // during the computation. 436 // Inputs: 437 // data - string containing the data 438 // crc - unsigned integer containing the initial crc 439 // table - string containing the 64-bit table corresponding to the generator 440 // polynomial. 441 // Returns: 442 // crc - unsigned integer containing the resulting crc 443 444 static PyObject* 445 _crc64r(PyObject* self, PyObject* args) 446 { 447 UINT64 crc; 448 UINT8* data; 449 Py_ssize_t dataLen; 450 UINT64* table; 451 Py_ssize_t tableLen; 452 453 if (!PyArg_ParseTuple(args, INPUT64, &data, &dataLen, &crc, 454 &table, &tableLen)) 455 { 456 return NULL; 457 } 458 459 if (tableLen != 256*8) 460 { 461 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); 462 return NULL; 463 } 464 465 while (dataLen--) 466 { 467 crc = table[*data ^ BYTE0(crc)] ^ (crc >> 8); 468 data++; 469 } 470 471 return PyLong_FromUnsignedLongLong(crc); 472 } 473 474 //----------------------------------------------------------------------------- 475 static PyMethodDef methodTable[] = { 476 {"_crc8", _crc8, METH_VARARGS}, 477 {"_crc8r", _crc8r, METH_VARARGS}, 478 {"_crc16", _crc16, METH_VARARGS}, 479 {"_crc16r", _crc16r, METH_VARARGS}, 480 {"_crc24", _crc24, METH_VARARGS}, 481 {"_crc24r", _crc24r, METH_VARARGS}, 482 {"_crc32", _crc32, METH_VARARGS}, 483 {"_crc32r", _crc32r, METH_VARARGS}, 484 {"_crc64", _crc64, METH_VARARGS}, 485 {"_crc64r", _crc64r, METH_VARARGS}, 486 {NULL, NULL} 487 }; 488 489 //----------------------------------------------------------------------------- 490 void init_crcfunext(void) 491 { 492 PyObject *m; 493 494 if ((sizeof(UINT8) != 1) || (sizeof(UINT16) != 2) || 495 (sizeof(UINT32) != 4) || (sizeof(UINT64) != 8)) 496 { 497 Py_FatalError("crcfunext: One of the data types is invalid"); 498 } 499 m = Py_InitModule("_crcfunext", methodTable); 500 } 501 502