OLD | NEW |
(Empty) | |
| 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) 2010 Raymond L. Buvel |
| 8 // Copyright (c) 2010 Craig McQueen |
| 9 // |
| 10 // Permission is hereby granted, free of charge, to any person obtaining a copy |
| 11 // of this software and associated documentation files (the "Software"), to |
| 12 // deal in the Software without restriction, including without limitation the |
| 13 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
| 14 // sell copies of the Software, and to permit persons to whom the Software is |
| 15 // furnished to do so, subject to the following conditions: |
| 16 // |
| 17 // The above copyright notice and this permission notice shall be included in |
| 18 // all copies or substantial portions of the Software. |
| 19 // |
| 20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 25 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 26 // IN THE SOFTWARE. |
| 27 //----------------------------------------------------------------------------- |
| 28 |
| 29 #define PY_SSIZE_T_CLEAN |
| 30 #include <Python.h> |
| 31 |
| 32 // Note: the type declarations are set up to work on 32-bit and 64-bit |
| 33 // platforms using the GNU C compiler. They may need to be adjusted for other |
| 34 // platforms. |
| 35 |
| 36 // Define a few types to make it easier to port to other platforms. |
| 37 typedef unsigned char UINT8; |
| 38 typedef unsigned short UINT16; |
| 39 typedef unsigned int UINT32; |
| 40 typedef unsigned long long UINT64; |
| 41 |
| 42 // Define some macros for the data format strings. The INPUT strings are for |
| 43 // decoding the input parameters to the function which are (data, crc, table). |
| 44 |
| 45 #define INPUT8 "OBs#" |
| 46 #define INPUT16 "OHs#" |
| 47 #define INPUT32 "OIs#" |
| 48 #define INPUT64 "OKs#" |
| 49 |
| 50 // The following macro is taken from hashlib.h in the Python 3.1 code, |
| 51 // providing "Common code for use by all hashlib related modules". |
| 52 |
| 53 // Given a PyObject* obj, fill in the Py_buffer* viewp with the result |
| 54 // of PyObject_GetBuffer. Sets an exception and issues a return NULL |
| 55 // on any errors. |
| 56 #define GET_BUFFER_VIEW_OR_ERROUT(obj, viewp) do { \ |
| 57 if (PyUnicode_Check((obj))) { \ |
| 58 PyErr_SetString(PyExc_TypeError, \ |
| 59 "Unicode-objects must be encoded before calculating
a CRC");\ |
| 60 return NULL; \ |
| 61 } \ |
| 62 if (!PyObject_CheckBuffer((obj))) { \ |
| 63 PyErr_SetString(PyExc_TypeError, \ |
| 64 "object supporting the buffer API required"); \ |
| 65 return NULL; \ |
| 66 } \ |
| 67 if (PyObject_GetBuffer((obj), (viewp), PyBUF_SIMPLE) == -1) { \ |
| 68 return NULL; \ |
| 69 } \ |
| 70 if ((viewp)->ndim > 1) { \ |
| 71 PyErr_SetString(PyExc_BufferError, \ |
| 72 "Buffer must be single dimension"); \ |
| 73 PyBuffer_Release((viewp)); \ |
| 74 return NULL; \ |
| 75 } \ |
| 76 } while(0); |
| 77 |
| 78 // Define some macros that extract the specified byte from an integral value in |
| 79 // what should be a platform independent manner. |
| 80 #define BYTE0(x) ((UINT8)(x)) |
| 81 #define BYTE1(x) ((UINT8)((x) >> 8)) |
| 82 #define BYTE2(x) ((UINT8)((x) >> 16)) |
| 83 #define BYTE3(x) ((UINT8)((x) >> 24)) |
| 84 #define BYTE7(x) ((UINT8)((x) >> 56)) |
| 85 |
| 86 //----------------------------------------------------------------------------- |
| 87 // Compute a 8-bit crc over the input data. |
| 88 // Inputs: |
| 89 // data - string containing the data |
| 90 // crc - unsigned integer containing the initial crc |
| 91 // table - string containing the 8-bit table corresponding to the generator |
| 92 // polynomial. |
| 93 // Returns: |
| 94 // crc - unsigned integer containing the resulting crc |
| 95 |
| 96 static PyObject* |
| 97 _crc8(PyObject* self, PyObject* args) |
| 98 { |
| 99 PyObject *obj; |
| 100 Py_buffer buf; |
| 101 UINT8 crc; |
| 102 UINT8* data; |
| 103 Py_ssize_t dataLen; |
| 104 UINT8* table; |
| 105 Py_ssize_t tableLen; |
| 106 |
| 107 if (!PyArg_ParseTuple(args, INPUT8, &obj, &crc, |
| 108 &table, &tableLen)) |
| 109 { |
| 110 return NULL; |
| 111 } |
| 112 |
| 113 if (tableLen != 256) |
| 114 { |
| 115 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); |
| 116 return NULL; |
| 117 } |
| 118 |
| 119 GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); |
| 120 data = buf.buf; |
| 121 dataLen = buf.len; |
| 122 |
| 123 while (dataLen--) |
| 124 { |
| 125 crc = table[*data ^ crc]; |
| 126 data++; |
| 127 } |
| 128 |
| 129 PyBuffer_Release(&buf); |
| 130 |
| 131 return PyLong_FromLong((long)crc); |
| 132 } |
| 133 |
| 134 //----------------------------------------------------------------------------- |
| 135 // Compute a 8-bit crc over the input data. The data stream is bit reversed |
| 136 // during the computation. |
| 137 // Inputs: |
| 138 // data - string containing the data |
| 139 // crc - unsigned integer containing the initial crc |
| 140 // table - string containing the 8-bit table corresponding to the generator |
| 141 // polynomial. |
| 142 // Returns: |
| 143 // crc - unsigned integer containing the resulting crc |
| 144 |
| 145 static PyObject* |
| 146 _crc8r(PyObject* self, PyObject* args) |
| 147 { |
| 148 PyObject *obj; |
| 149 Py_buffer buf; |
| 150 UINT8 crc; |
| 151 UINT8* data; |
| 152 Py_ssize_t dataLen; |
| 153 UINT8* table; |
| 154 Py_ssize_t tableLen; |
| 155 |
| 156 if (!PyArg_ParseTuple(args, INPUT8, &obj, &crc, |
| 157 &table, &tableLen)) |
| 158 { |
| 159 return NULL; |
| 160 } |
| 161 |
| 162 if (tableLen != 256) |
| 163 { |
| 164 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); |
| 165 return NULL; |
| 166 } |
| 167 |
| 168 GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); |
| 169 data = buf.buf; |
| 170 dataLen = buf.len; |
| 171 |
| 172 while (dataLen--) |
| 173 { |
| 174 crc = table[*data ^ crc]; |
| 175 data++; |
| 176 } |
| 177 |
| 178 PyBuffer_Release(&buf); |
| 179 |
| 180 return PyLong_FromLong((long)crc); |
| 181 } |
| 182 |
| 183 //----------------------------------------------------------------------------- |
| 184 // Compute a 16-bit crc over the input data. |
| 185 // Inputs: |
| 186 // data - string containing the data |
| 187 // crc - unsigned integer containing the initial crc |
| 188 // table - string containing the 16-bit table corresponding to the generator |
| 189 // polynomial. |
| 190 // Returns: |
| 191 // crc - unsigned integer containing the resulting crc |
| 192 |
| 193 static PyObject* |
| 194 _crc16(PyObject* self, PyObject* args) |
| 195 { |
| 196 PyObject *obj; |
| 197 Py_buffer buf; |
| 198 UINT16 crc; |
| 199 UINT8* data; |
| 200 Py_ssize_t dataLen; |
| 201 UINT16* table; |
| 202 Py_ssize_t tableLen; |
| 203 |
| 204 if (!PyArg_ParseTuple(args, INPUT16, &obj, &crc, |
| 205 &table, &tableLen)) |
| 206 { |
| 207 return NULL; |
| 208 } |
| 209 |
| 210 if (tableLen != 256*2) |
| 211 { |
| 212 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); |
| 213 return NULL; |
| 214 } |
| 215 |
| 216 GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); |
| 217 data = buf.buf; |
| 218 dataLen = buf.len; |
| 219 |
| 220 while (dataLen--) |
| 221 { |
| 222 crc = table[*data ^ BYTE1(crc)] ^ (crc << 8); |
| 223 data++; |
| 224 } |
| 225 |
| 226 PyBuffer_Release(&buf); |
| 227 |
| 228 return PyLong_FromLong((long)crc); |
| 229 } |
| 230 |
| 231 //----------------------------------------------------------------------------- |
| 232 // Compute a 16-bit crc over the input data. The data stream is bit reversed |
| 233 // during the computation. |
| 234 // Inputs: |
| 235 // data - string containing the data |
| 236 // crc - unsigned integer containing the initial crc |
| 237 // table - string containing the 16-bit table corresponding to the generator |
| 238 // polynomial. |
| 239 // Returns: |
| 240 // crc - unsigned integer containing the resulting crc |
| 241 |
| 242 static PyObject* |
| 243 _crc16r(PyObject* self, PyObject* args) |
| 244 { |
| 245 PyObject *obj; |
| 246 Py_buffer buf; |
| 247 UINT16 crc; |
| 248 UINT8* data; |
| 249 Py_ssize_t dataLen; |
| 250 UINT16* table; |
| 251 Py_ssize_t tableLen; |
| 252 |
| 253 if (!PyArg_ParseTuple(args, INPUT16, &obj, &crc, |
| 254 &table, &tableLen)) |
| 255 { |
| 256 return NULL; |
| 257 } |
| 258 |
| 259 if (tableLen != 256*2) |
| 260 { |
| 261 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); |
| 262 return NULL; |
| 263 } |
| 264 |
| 265 GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); |
| 266 data = buf.buf; |
| 267 dataLen = buf.len; |
| 268 |
| 269 while (dataLen--) |
| 270 { |
| 271 crc = table[*data ^ BYTE0(crc)] ^ (crc >> 8); |
| 272 data++; |
| 273 } |
| 274 |
| 275 PyBuffer_Release(&buf); |
| 276 |
| 277 return PyLong_FromLong((long)crc); |
| 278 } |
| 279 |
| 280 //----------------------------------------------------------------------------- |
| 281 // Compute a 24-bit crc over the input data. |
| 282 // Inputs: |
| 283 // data - string containing the data |
| 284 // crc - unsigned integer containing the initial crc |
| 285 // table - string containing the 24-bit table corresponding to the generator |
| 286 // polynomial. |
| 287 // Returns: |
| 288 // crc - unsigned integer containing the resulting crc |
| 289 |
| 290 static PyObject* |
| 291 _crc24(PyObject* self, PyObject* args) |
| 292 { |
| 293 PyObject *obj; |
| 294 Py_buffer buf; |
| 295 UINT32 crc; |
| 296 UINT8* data; |
| 297 Py_ssize_t dataLen; |
| 298 UINT32* table; |
| 299 Py_ssize_t tableLen; |
| 300 |
| 301 if (!PyArg_ParseTuple(args, INPUT32, &obj, &crc, |
| 302 &table, &tableLen)) |
| 303 { |
| 304 return NULL; |
| 305 } |
| 306 |
| 307 if (tableLen != 256*4) |
| 308 { |
| 309 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); |
| 310 return NULL; |
| 311 } |
| 312 |
| 313 GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); |
| 314 data = buf.buf; |
| 315 dataLen = buf.len; |
| 316 |
| 317 while (dataLen--) |
| 318 { |
| 319 crc = table[*data ^ BYTE2(crc)] ^ (crc << 8); |
| 320 data++; |
| 321 } |
| 322 |
| 323 PyBuffer_Release(&buf); |
| 324 |
| 325 return PyLong_FromLong((long)(crc & 0xFFFFFFU)); |
| 326 } |
| 327 |
| 328 //----------------------------------------------------------------------------- |
| 329 // Compute a 24-bit crc over the input data. The data stream is bit reversed |
| 330 // during the computation. |
| 331 // Inputs: |
| 332 // data - string containing the data |
| 333 // crc - unsigned integer containing the initial crc |
| 334 // table - string containing the 24-bit table corresponding to the generator |
| 335 // polynomial. |
| 336 // Returns: |
| 337 // crc - unsigned integer containing the resulting crc |
| 338 |
| 339 static PyObject* |
| 340 _crc24r(PyObject* self, PyObject* args) |
| 341 { |
| 342 PyObject *obj; |
| 343 Py_buffer buf; |
| 344 UINT32 crc; |
| 345 UINT8* data; |
| 346 Py_ssize_t dataLen; |
| 347 UINT32* table; |
| 348 Py_ssize_t tableLen; |
| 349 |
| 350 if (!PyArg_ParseTuple(args, INPUT32, &obj, &crc, |
| 351 &table, &tableLen)) |
| 352 { |
| 353 return NULL; |
| 354 } |
| 355 |
| 356 if (tableLen != 256*4) |
| 357 { |
| 358 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); |
| 359 return NULL; |
| 360 } |
| 361 |
| 362 GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); |
| 363 data = buf.buf; |
| 364 dataLen = buf.len; |
| 365 |
| 366 crc = crc & 0xFFFFFFU; |
| 367 while (dataLen--) |
| 368 { |
| 369 crc = table[*data ^ BYTE0(crc)] ^ (crc >> 8); |
| 370 data++; |
| 371 } |
| 372 |
| 373 PyBuffer_Release(&buf); |
| 374 |
| 375 return PyLong_FromLong((long)crc); |
| 376 } |
| 377 |
| 378 //----------------------------------------------------------------------------- |
| 379 // Compute a 32-bit crc over the input data. |
| 380 // Inputs: |
| 381 // data - string containing the data |
| 382 // crc - unsigned integer containing the initial crc |
| 383 // table - string containing the 32-bit table corresponding to the generator |
| 384 // polynomial. |
| 385 // Returns: |
| 386 // crc - unsigned integer containing the resulting crc |
| 387 |
| 388 static PyObject* |
| 389 _crc32(PyObject* self, PyObject* args) |
| 390 { |
| 391 PyObject *obj; |
| 392 Py_buffer buf; |
| 393 UINT32 crc; |
| 394 UINT8* data; |
| 395 Py_ssize_t dataLen; |
| 396 UINT32* table; |
| 397 Py_ssize_t tableLen; |
| 398 |
| 399 if (!PyArg_ParseTuple(args, INPUT32, &obj, &crc, |
| 400 &table, &tableLen)) |
| 401 { |
| 402 return NULL; |
| 403 } |
| 404 |
| 405 if (tableLen != 256*4) |
| 406 { |
| 407 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); |
| 408 return NULL; |
| 409 } |
| 410 |
| 411 GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); |
| 412 data = buf.buf; |
| 413 dataLen = buf.len; |
| 414 |
| 415 while (dataLen--) |
| 416 { |
| 417 crc = table[*data ^ BYTE3(crc)] ^ (crc << 8); |
| 418 data++; |
| 419 } |
| 420 |
| 421 PyBuffer_Release(&buf); |
| 422 |
| 423 return PyLong_FromUnsignedLong(crc); |
| 424 } |
| 425 |
| 426 //----------------------------------------------------------------------------- |
| 427 // Compute a 32-bit crc over the input data. The data stream is bit reversed |
| 428 // during the computation. |
| 429 // Inputs: |
| 430 // data - string containing the data |
| 431 // crc - unsigned integer containing the initial crc |
| 432 // table - string containing the 32-bit table corresponding to the generator |
| 433 // polynomial. |
| 434 // Returns: |
| 435 // crc - unsigned integer containing the resulting crc |
| 436 |
| 437 static PyObject* |
| 438 _crc32r(PyObject* self, PyObject* args) |
| 439 { |
| 440 PyObject *obj; |
| 441 Py_buffer buf; |
| 442 UINT32 crc; |
| 443 UINT8* data; |
| 444 Py_ssize_t dataLen; |
| 445 UINT32* table; |
| 446 Py_ssize_t tableLen; |
| 447 |
| 448 if (!PyArg_ParseTuple(args, INPUT32, &obj, &crc, |
| 449 &table, &tableLen)) |
| 450 { |
| 451 return NULL; |
| 452 } |
| 453 |
| 454 if (tableLen != 256*4) |
| 455 { |
| 456 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); |
| 457 return NULL; |
| 458 } |
| 459 |
| 460 GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); |
| 461 data = buf.buf; |
| 462 dataLen = buf.len; |
| 463 |
| 464 while (dataLen--) |
| 465 { |
| 466 crc = table[*data ^ BYTE0(crc)] ^ (crc >> 8); |
| 467 data++; |
| 468 } |
| 469 |
| 470 PyBuffer_Release(&buf); |
| 471 |
| 472 return PyLong_FromUnsignedLong(crc); |
| 473 } |
| 474 |
| 475 //----------------------------------------------------------------------------- |
| 476 // Compute a 64-bit crc over the input data. |
| 477 // Inputs: |
| 478 // data - string containing the data |
| 479 // crc - unsigned integer containing the initial crc |
| 480 // table - string containing the 64-bit table corresponding to the generator |
| 481 // polynomial. |
| 482 // Returns: |
| 483 // crc - unsigned integer containing the resulting crc |
| 484 |
| 485 static PyObject* |
| 486 _crc64(PyObject* self, PyObject* args) |
| 487 { |
| 488 PyObject *obj; |
| 489 Py_buffer buf; |
| 490 UINT64 crc; |
| 491 UINT8* data; |
| 492 Py_ssize_t dataLen; |
| 493 UINT64* table; |
| 494 Py_ssize_t tableLen; |
| 495 |
| 496 if (!PyArg_ParseTuple(args, INPUT64, &obj, &crc, |
| 497 &table, &tableLen)) |
| 498 { |
| 499 return NULL; |
| 500 } |
| 501 |
| 502 if (tableLen != 256*8) |
| 503 { |
| 504 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); |
| 505 return NULL; |
| 506 } |
| 507 |
| 508 GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); |
| 509 data = buf.buf; |
| 510 dataLen = buf.len; |
| 511 |
| 512 while (dataLen--) |
| 513 { |
| 514 crc = table[*data ^ BYTE7(crc)] ^ (crc << 8); |
| 515 data++; |
| 516 } |
| 517 |
| 518 PyBuffer_Release(&buf); |
| 519 |
| 520 return PyLong_FromUnsignedLongLong(crc); |
| 521 } |
| 522 |
| 523 //----------------------------------------------------------------------------- |
| 524 // Compute a 64-bit crc over the input data. The data stream is bit reversed |
| 525 // during the computation. |
| 526 // Inputs: |
| 527 // data - string containing the data |
| 528 // crc - unsigned integer containing the initial crc |
| 529 // table - string containing the 64-bit table corresponding to the generator |
| 530 // polynomial. |
| 531 // Returns: |
| 532 // crc - unsigned integer containing the resulting crc |
| 533 |
| 534 static PyObject* |
| 535 _crc64r(PyObject* self, PyObject* args) |
| 536 { |
| 537 PyObject *obj; |
| 538 Py_buffer buf; |
| 539 UINT64 crc; |
| 540 UINT8* data; |
| 541 Py_ssize_t dataLen; |
| 542 UINT64* table; |
| 543 Py_ssize_t tableLen; |
| 544 |
| 545 if (!PyArg_ParseTuple(args, INPUT64, &obj, &crc, |
| 546 &table, &tableLen)) |
| 547 { |
| 548 return NULL; |
| 549 } |
| 550 |
| 551 if (tableLen != 256*8) |
| 552 { |
| 553 PyErr_SetString(PyExc_ValueError, "invalid CRC table"); |
| 554 return NULL; |
| 555 } |
| 556 |
| 557 GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); |
| 558 data = buf.buf; |
| 559 dataLen = buf.len; |
| 560 |
| 561 while (dataLen--) |
| 562 { |
| 563 crc = table[*data ^ BYTE0(crc)] ^ (crc >> 8); |
| 564 data++; |
| 565 } |
| 566 |
| 567 PyBuffer_Release(&buf); |
| 568 |
| 569 return PyLong_FromUnsignedLongLong(crc); |
| 570 } |
| 571 |
| 572 //----------------------------------------------------------------------------- |
| 573 static PyMethodDef methodTable[] = { |
| 574 {"_crc8", _crc8, METH_VARARGS}, |
| 575 {"_crc8r", _crc8r, METH_VARARGS}, |
| 576 {"_crc16", _crc16, METH_VARARGS}, |
| 577 {"_crc16r", _crc16r, METH_VARARGS}, |
| 578 {"_crc24", _crc24, METH_VARARGS}, |
| 579 {"_crc24r", _crc24r, METH_VARARGS}, |
| 580 {"_crc32", _crc32, METH_VARARGS}, |
| 581 {"_crc32r", _crc32r, METH_VARARGS}, |
| 582 {"_crc64", _crc64, METH_VARARGS}, |
| 583 {"_crc64r", _crc64r, METH_VARARGS}, |
| 584 {NULL, NULL} |
| 585 }; |
| 586 |
| 587 //----------------------------------------------------------------------------- |
| 588 static struct PyModuleDef moduleDef = { |
| 589 PyModuleDef_HEAD_INIT, |
| 590 "_crcfunext", // name of module |
| 591 NULL, // module documentation, may be NULL |
| 592 -1, // size of per-interpreter state of the module, |
| 593 // or -1 if the module keeps state in global variables. |
| 594 methodTable |
| 595 }; |
| 596 |
| 597 //----------------------------------------------------------------------------- |
| 598 PyMODINIT_FUNC |
| 599 PyInit__crcfunext(void) |
| 600 { |
| 601 if ((sizeof(UINT8) != 1) || (sizeof(UINT16) != 2) || |
| 602 (sizeof(UINT32) != 4) || (sizeof(UINT64) != 8)) |
| 603 { |
| 604 Py_FatalError("crcfunext: One of the data types is invalid"); |
| 605 } |
| 606 |
| 607 return PyModule_Create(&moduleDef); |
| 608 } |
| 609 |
OLD | NEW |