Convert the HLL with sparse representation given as input in its dense * representation. Both representations are represented by SDS strings, and * the input representation is freed as a side effect. * * The function returns C_OK if the sparse representation was valid, * otherwise C_ERR is returned if the representation was corrupted. */
| 584 | * The function returns C_OK if the sparse representation was valid, |
| 585 | * otherwise C_ERR is returned if the representation was corrupted. */ |
| 586 | int hllSparseToDense(robj *o) { |
| 587 | sds sparse = szFromObj(o), dense; |
| 588 | struct hllhdr *hdr, *oldhdr = (struct hllhdr*)sparse; |
| 589 | int idx = 0, runlen, regval; |
| 590 | uint8_t *p = (uint8_t*)sparse, *end = p+sdslen(sparse); |
| 591 | |
| 592 | /* If the representation is already the right one return ASAP. */ |
| 593 | hdr = (struct hllhdr*) sparse; |
| 594 | if (hdr->encoding == HLL_DENSE) return C_OK; |
| 595 | |
| 596 | /* Create a string of the right size filled with zero bytes. |
| 597 | * Note that the cached cardinality is set to 0 as a side effect |
| 598 | * that is exactly the cardinality of an empty HLL. */ |
| 599 | dense = sdsnewlen(NULL,HLL_DENSE_SIZE); |
| 600 | hdr = (struct hllhdr*) dense; |
| 601 | *hdr = *oldhdr; /* This will copy the magic and cached cardinality. */ |
| 602 | hdr->encoding = HLL_DENSE; |
| 603 | |
| 604 | /* Now read the sparse representation and set non-zero registers |
| 605 | * accordingly. */ |
| 606 | p += HLL_HDR_SIZE; |
| 607 | while(p < end) { |
| 608 | if (HLL_SPARSE_IS_ZERO(p)) { |
| 609 | runlen = HLL_SPARSE_ZERO_LEN(p); |
| 610 | idx += runlen; |
| 611 | p++; |
| 612 | } else if (HLL_SPARSE_IS_XZERO(p)) { |
| 613 | runlen = HLL_SPARSE_XZERO_LEN(p); |
| 614 | idx += runlen; |
| 615 | p += 2; |
| 616 | } else { |
| 617 | runlen = HLL_SPARSE_VAL_LEN(p); |
| 618 | regval = HLL_SPARSE_VAL_VALUE(p); |
| 619 | if ((runlen + idx) > HLL_REGISTERS) break; /* Overflow. */ |
| 620 | while(runlen--) { |
| 621 | HLL_DENSE_SET_REGISTER(hdr->registers(),idx,regval); |
| 622 | idx++; |
| 623 | } |
| 624 | p++; |
| 625 | } |
| 626 | } |
| 627 | |
| 628 | /* If the sparse representation was valid, we expect to find idx |
| 629 | * set to HLL_REGISTERS. */ |
| 630 | if (idx != HLL_REGISTERS) { |
| 631 | sdsfree(dense); |
| 632 | return C_ERR; |
| 633 | } |
| 634 | |
| 635 | /* Free the old representation and set the new one. */ |
| 636 | sdsfree(szFromObj(o)); |
| 637 | o->m_ptr = dense; |
| 638 | return C_OK; |
| 639 | } |
| 640 | |
| 641 | /* Low level function to set the sparse HLL register at 'index' to the |
| 642 | * specified value if the current value is smaller than 'count'. |