MCPcopy Create free account
hub / github.com/Snapchat/KeyDB / lpInsert

Function lpInsert

src/listpack.c:655–794  ·  view source on GitHub ↗

Insert, delete or replace the specified element 'ele' of length 'len' at * the specified position 'p', with 'p' being a listpack element pointer * obtained with lpFirst(), lpLast(), lpNext(), lpPrev() or lpSeek(). * * The element is inserted before, after, or replaces the element pointed * by 'p' depending on the 'where' argument, that can be LP_BEFORE, LP_AFTER * or LP_REPLACE. * * If 'el

Source from the content-addressed store, hash-verified

653 * element, on the right of the deleted one, or to NULL if the deleted element
654 * was the last one. */
655unsigned char *lpInsert(unsigned char *lp, unsigned char *ele, uint32_t size, unsigned char *p, int where, unsigned char **newp) {
656 unsigned char intenc[LP_MAX_INT_ENCODING_LEN];
657 unsigned char backlen[LP_MAX_BACKLEN_SIZE];
658
659 uint64_t enclen; /* The length of the encoded element. */
660
661 /* An element pointer set to NULL means deletion, which is conceptually
662 * replacing the element with a zero-length element. So whatever we
663 * get passed as 'where', set it to LP_REPLACE. */
664 if (ele == NULL) where = LP_REPLACE;
665
666 /* If we need to insert after the current element, we just jump to the
667 * next element (that could be the EOF one) and handle the case of
668 * inserting before. So the function will actually deal with just two
669 * cases: LP_BEFORE and LP_REPLACE. */
670 if (where == LP_AFTER) {
671 p = lpSkip(p);
672 where = LP_BEFORE;
673 ASSERT_INTEGRITY(lp, p);
674 }
675
676 /* Store the offset of the element 'p', so that we can obtain its
677 * address again after a reallocation. */
678 unsigned long poff = p-lp;
679
680 /* Calling lpEncodeGetType() results into the encoded version of the
681 * element to be stored into 'intenc' in case it is representable as
682 * an integer: in that case, the function returns LP_ENCODING_INT.
683 * Otherwise if LP_ENCODING_STR is returned, we'll have to call
684 * lpEncodeString() to actually write the encoded string on place later.
685 *
686 * Whatever the returned encoding is, 'enclen' is populated with the
687 * length of the encoded element. */
688 int enctype;
689 if (ele) {
690 enctype = lpEncodeGetType(ele,size,intenc,&enclen);
691 } else {
692 enctype = -1;
693 enclen = 0;
694 }
695
696 /* We need to also encode the backward-parsable length of the element
697 * and append it to the end: this allows to traverse the listpack from
698 * the end to the start. */
699 unsigned long backlen_size = ele ? lpEncodeBacklen(backlen,enclen) : 0;
700 uint64_t old_listpack_bytes = lpGetTotalBytes(lp);
701 uint32_t replaced_len = 0;
702 if (where == LP_REPLACE) {
703 replaced_len = lpCurrentEncodedSizeUnsafe(p);
704 replaced_len += lpEncodeBacklen(NULL,replaced_len);
705 ASSERT_INTEGRITY_LEN(lp, p, replaced_len);
706 }
707
708 uint64_t new_listpack_bytes = old_listpack_bytes + enclen + backlen_size
709 - replaced_len;
710 if (new_listpack_bytes > UINT32_MAX) return NULL;
711
712 /* We now need to reallocate in order to make space or shrink the

Callers 3

lpAppendFunction · 0.85
lpDeleteFunction · 0.85
lpReplaceIntegerFunction · 0.85

Calls 5

lpSkipFunction · 0.85
lpEncodeGetTypeFunction · 0.85
lpEncodeBacklenFunction · 0.85
lpEncodeStringFunction · 0.85

Tested by

no test coverage detected