|
11 | 11 | #define MAX_SHORT_LEN 127 |
12 | 12 | #define LONG_STR_TAG 1 |
13 | 13 |
|
14 | | -#define MIN_SHORT_INT (-10) |
| 14 | +#define MIN_SHORT_INT -10 |
15 | 15 | #define MAX_SHORT_INT 117 |
16 | 16 | #define MEDIUM_INT_TAG 1 |
17 | 17 | #define LONG_INT_TAG 3 |
@@ -391,14 +391,21 @@ read_int_internal(PyObject *data) { |
391 | 391 | if (_check_buffer(data) == 2) |
392 | 392 | return CPY_INT_TAG; |
393 | 393 |
|
394 | | - if (_check_read((BufferObject *)data, sizeof(CPyTagged)) == 2) |
395 | | - return CPY_INT_TAG; |
396 | 394 | char *buf = ((BufferObject *)data)->buf; |
| 395 | + if (_check_read((BufferObject *)data, 1) == 2) |
| 396 | + return CPY_INT_TAG; |
397 | 397 |
|
398 | | - CPyTagged ret = *(CPyTagged *)(buf + ((BufferObject *)data)->pos); |
399 | | - ((BufferObject *)data)->pos += sizeof(CPyTagged); |
400 | | - if ((ret & CPY_INT_TAG) == 0) |
| 398 | + uint8_t first = *(uint8_t *)(buf + ((BufferObject *)data)->pos); |
| 399 | + ((BufferObject *)data)->pos += 1; |
| 400 | + if ((first & MEDIUM_INT_TAG) == 0) { |
| 401 | + return ((Py_ssize_t)(first >> 1) + MIN_SHORT_INT) << 1; |
| 402 | + } |
| 403 | + if (first == MEDIUM_INT_TAG) { |
| 404 | + CPyTagged ret = *(CPyTagged *)(buf + ((BufferObject *)data)->pos); |
| 405 | + ((BufferObject *)data)->pos += sizeof(CPyTagged); |
401 | 406 | return ret; |
| 407 | + } |
| 408 | + // first == LONG_INT_TAG |
402 | 409 | // People who have literal ints not fitting in size_t should be punished :-) |
403 | 410 | PyObject *str_ret = read_str_internal(data); |
404 | 411 | if (str_ret == NULL) |
@@ -426,17 +433,34 @@ write_int_internal(PyObject *data, CPyTagged value) { |
426 | 433 | if (_check_buffer(data) == 2) |
427 | 434 | return 2; |
428 | 435 |
|
429 | | - if (_check_size((BufferObject *)data, sizeof(CPyTagged)) == 2) |
430 | | - return 2; |
431 | | - char *buf = ((BufferObject *)data)->buf; |
| 436 | + char *buf; |
432 | 437 | if ((value & CPY_INT_TAG) == 0) { |
433 | | - *(CPyTagged *)(buf + ((BufferObject *)data)->pos) = value; |
| 438 | + Py_ssize_t real_value = CPyTagged_ShortAsSsize_t(value); |
| 439 | + if (real_value >= MIN_SHORT_INT && real_value <= MAX_SHORT_INT) { |
| 440 | + // Most common case: int that is small in absolute value. |
| 441 | + if (_check_size((BufferObject *)data, 1) == 2) |
| 442 | + return 2; |
| 443 | + buf = ((BufferObject *)data)->buf; |
| 444 | + *(uint8_t *)(buf + ((BufferObject *)data)->pos) = (uint8_t)(real_value - MIN_SHORT_INT) << 1; |
| 445 | + ((BufferObject *)data)->pos += 1; |
| 446 | + ((BufferObject *)data)->end += 1; |
| 447 | + } else { |
| 448 | + if (_check_size((BufferObject *)data, sizeof(CPyTagged) + 1) == 2) |
| 449 | + return 2; |
| 450 | + buf = ((BufferObject *)data)->buf; |
| 451 | + *(uint8_t *)(buf + ((BufferObject *)data)->pos) = MEDIUM_INT_TAG; |
| 452 | + ((BufferObject *)data)->pos += 1; |
| 453 | + *(CPyTagged *)(buf + ((BufferObject *)data)->pos) = value; |
| 454 | + ((BufferObject *)data)->pos += sizeof(CPyTagged); |
| 455 | + ((BufferObject *)data)->end += sizeof(CPyTagged) + 1; |
| 456 | + } |
434 | 457 | } else { |
435 | | - *(CPyTagged *)(buf + ((BufferObject *)data)->pos) = CPY_INT_TAG; |
436 | | - } |
437 | | - ((BufferObject *)data)->pos += sizeof(CPyTagged); |
438 | | - ((BufferObject *)data)->end += sizeof(CPyTagged); |
439 | | - if ((value & CPY_INT_TAG) != 0) { |
| 458 | + if (_check_size((BufferObject *)data, 1) == 2) |
| 459 | + return 2; |
| 460 | + buf = ((BufferObject *)data)->buf; |
| 461 | + *(uint8_t *)(buf + ((BufferObject *)data)->pos) = LONG_INT_TAG; |
| 462 | + ((BufferObject *)data)->pos += 1; |
| 463 | + ((BufferObject *)data)->end += 1; |
440 | 464 | PyObject *str_value = PyObject_Str(CPyTagged_LongAsObject(value)); |
441 | 465 | if (str_value == NULL) |
442 | 466 | return 2; |
|
0 commit comments