A listpack is encoded into a single linear chunk of memory. It has a fixed
length header of six bytes (instead of ten bytes of ziplist, since we no
longer need a pointer to the start of the last element). The header is
followed by the listpack elements. In theory the data structure does not need
any terminator, however for certain concerns, a special entry marking the
end of the listpack is provided, in the form of a single byte with value
FF (255). The main advantages of the terminator are the ability to scan the
listpack without holding (and comparing at each iteration) the address of
the end of the listpack, and to recognize easily if a listpack is well
formed or truncated. These advantages are, in the idea of the writer, worth
the additional byte needed in the representation.
<tot-bytes> <num-elements> <element-1> ... <element-N> <listpack-end-byte>
The six byte header, composed of the tot-bytes and num-elements fields is
encoded in the following way:
tot-bytes
: 32 bit unsigned integer holding the total amount of bytes
representing the listpack. Including the header itself and the terminator.
This basically is the total size of the allocation needed to hold the listpack
and allows to jump at the end in order to scan the listpack in reverse order,
from the last to the first element, when needed.
num-elements
: 16 bit unsigned integer holding the total number of elements
the listpack holds. However if this field is set to 65535, which is the greatest
unsigned integer representable in 16 bit, it means that the number of listpack
elements is not known, so a LIST-LENGTH operation will require to fully scan
the listpack. This happens when, at some point, the listpack has a number of
elements equal or greater than 65535. The num-elements field will be set again
to a lower number the first time a LIST-LENGTH operation detects the elements
count returned in the representable range.
All integers in the listpack are stored in little endian format, if not
otherwise specified (certain special encodings are in big endian because
it is more natural to represent them in this way for the way the specification
maps to C code).
Return the number of elements inside the listpack. This function attempts
to use the cached value when within range, otherwise a full scan is
needed. As a side effect of calling this function, the listpack header
could be modified, because if the count is found to be already within
the 'numele' header field range, the new value is set.
Return the total number of bytes the listpack is composed of.
Decodes and returns the entry value of the element.
If the function is called against a badly encoded listpack, so that there
is no valid way to parse it, the function returns like if there was an
integer encoded with value 12345678900000000 + , this may
be an hint to understand that something is wrong. To crash in this case is
not sensible because of the different requirements of the application using
this lib.
Similarly, there is no error returned since the listpack normally can be
assumed to be valid, so that would be a very high API cost. However a function
in order to check the integrity of the listpack at load time is provided,
check is_valid().
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 first(), last(), index(), next(), prev() or
seek().
The element is inserted before, after, or replaces the element pointed
by 'p' depending on the 'where' argument, that can be BEFORE, AFTER
or REPLACE.
If 'ele' is set to NULL, the function removes the element pointed by 'p'
instead of inserting one.
Returns None on out of memory or when the listpack total length would exceed
the max allowed size of 2^32-1, otherwise the new pointer to the listpack
holding the new element is returned (and the old pointer passed is no longer
considered valid)
If 'newp' is not NULL, at the end of a successful call '*newp' will be set
to the address of the element just added, so that it will be possible to
continue an iteration with next() and prev().
For deletion operations ('ele' set to None) 'newp' is set to the next
element, on the right of the deleted one, or to NULL if the deleted element
was the last one.
Append the specified element 'ele' of length 'len' at the end of the
listpack. It is implemented in terms of insert(), so the return value is
the same as insert().
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 first(), last(), index(), next(), prev() or seek().
The element is inserted before, after, or replaces the element pointed
by 'p' depending on the 'where' argument, that can be BEFORE, AFTER
or REPLACE.
If 'ele' is set to NULL, the function removes the element pointed by 'p'
instead of inserting one.
Returns None on out of memory or when the listpack total length would exceed
the max allowed size of 2^32-1, otherwise the new pointer to the listpack
holding the new element is returned (and the old pointer passed is no longer
considered valid)
If 'newp' is not NULL, at the end of a successful call '*newp' will be set
to the address of the element just added, so that it will be possible to
continue an iteration with next() and prev().
Append the specified element 'ele' of length 'len' at the end of the
listpack. It is implemented in terms of insert(), so the return value is
the same as insert().
Returns true if it succeeded or false when out-of-memory or when the
listpack total length would exceed the max allowed size of 2^32-1
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 first(), last(), index(), next(), prev() or
seek().
The element is inserted before, after, or replaces the element pointed
by 'p' depending on the 'where' argument, that can be BEFORE, AFTER
or REPLACE.
If 'ele' is set to NULL, the function removes the element pointed by 'p'
instead of inserting one.
Returns None on out of memory or when the listpack total length would exceed
the max allowed size of 2^32-1, otherwise the new pointer to the listpack
holding the new element is returned (and the old pointer passed is no longer
considered valid)
If 'newp' is not NULL, at the end of a successful call '*newp' will be set
to the address of the element just added, so that it will be possible to
continue an iteration with next() and prev().
For deletion operations ('ele' set to None) 'newp' is set to the next
element, on the right of the deleted one, or to NULL if the deleted element
was the last one.
If None is returned then it failed because of out-of-memory or invalid
element pointer.
Append the specified element 'ele' of length 'len' at the end of the
listpack. It is implemented in terms of insert(), so the return value is
the same as insert().
Replace the specified element with the specified value
Remove the element pointed by 'p', and return the resulting listpack.
If 'newp' is not NULL, the next element pointer (to the right of the
deleted one) is returned by reference. If the deleted element was the
last one, '*newp' is set to None.
Return a pointer to the first element of the listpack, or None if the
listpack has no elements.
Return a pointer to the last element of the listpack, or None if the
listpack has no elements.
/* If 'after' points to an element of the listpack, calling next() will return
the pointer to the next element (the one on the right), or None if 'after'
already pointed to the last element of the listpack. */
If 'p' points to an element of the listpack, calling prev() will return
the pointer to the previous element (the one on the left), or None if 'before'
already pointed to the first element of the listpack.
Seek the specified element and returns the pointer to the seeked element.
Positive indexes specify the zero-based element to seek from the head to
the tail, negative indexes specify elements starting from the tail, where
-1 means the last element, -2 the penultimate and so forth. If the index
is out of range, NULL is returned.