| parrotcode: List aka array routines | |
| Contents | C | 

src/list.c - List aka array routines

List is roughly based on concepts of IntList (thanks to Steve), so I don't repeat them here.
Especially the same invariants hold, except an empty list is really empty, meaning, push does first check for space.
The main differences are:
- List can hold items of different size, it's suitable for ints and PMCs ..., calculations are still done in terms of items. The item_size is specified at list creation time with the "type" argument.
If you later store different item types in the list, as stated initially, you'll get probably not what you want - so don't do this.
- List does auto grow. The caller may implement a different behaviour if she likes.
- Error checking for out of bounds access is minimal, caller knows better, what should be done.
- List structure itself is different from List_chunk, implying:
list->prev but list->end- list chunks don't have ->start and ->end fields.
Instead the list has ->start,
which is start of first chunk,
and ->cap,
the total usable capacity in the list.
- number of items in chunks are not fixed, but there is a mode using same sized chunks

enum_grow_fixedMAX_ITEMS size,
chosen,
when the first access to the array is indexed and beyond MIN_ITEMS and below 10 * MAX_ITEMSMAX_ITEMS a sparse chunk will be created.    new P0, 'Array'
    set P0, 100000  # sets fixed sized, no sparse
enum_grow_growingMIN_ITEMS to MAX_ITEMS, this will be selected for pushing data on an empty array.enum_grow_mixedget_chunk below for details.
To save memory, List can handle sparse arrays. This code snippet:
new P0, 'IntList' set P0[1000000], 42
generates 3 List_chunks, one at the beginning of the array, a big sparse chunk and a chunk for the actual data.
Setting values inside sparse chunks changes them to real chunks. For poping/shifting inside sparse chunks, s. return value below.

fixed_itemsgrow_itemsno_power_2sparsechunk->items holds the items of this sparse hole.
A List can hold various datatypes. See src/datatypes.h for the enumeration of types.
Not all are yet implemented in list_set/list_item, see the switch().
Arbitrary length data:
Construct initializer with:
In list_assign the values are copied into the array, list_get returns a pointer as for all other data types.
See src/list_2.t and list_new_init().

List get functions return a (void*) pointer to the location of the stored data. The caller has to extract the value from this pointer.
For non existent data beyond the dimensions of the array a NULL pointer is returned.
For non existing data inside sparse holes, a pointer (void*)-1 is returned.
The caller can decide to assume these data as undef or 0 or whatever is appropriate.

See t/src/{int, }list.c and t/pmc/{int, }list.t.
Also all array usage depends on list.

static List_chunk *allocate_chunkstatic void list_dumpstatic void rebuild_chunk_ptrsstatic void rebuild_sparsestatic void rebuild_otherstatic void rebuild_fix_endsrebuild_chunk_list().static UINTVAL rebuild_chunk_liststatic List_chunk *alloc_next_sizestatic List_chunk *add_chunkUINTVAL ldstatic List_chunk *get_chunkidx, also update the idx to point into the chunk.rebuild_chunk_list does provide.    if all_chunks_are_MAX_ITEMS
         chunk = chunk_list[ idx / MAX_ITEMS ]
         idx =   idx % MAX_ITEMS
         done.
    chunk = first
    repeat
         if (index < chunk->items)
             done.
     if (index >= items_in_chunk_block)
         index -= items_in_chunk_block
         chunk += chunks_in_chunk_block
         continue
     calc chunk and index in this block
     done.
rebuild_chunk_list tries to reduce the complexity, but may fail, if you e.g. do a prime sieve by actually list_deleting the none prime numbers.chunk_blocks are there. They come from:MAX_ITEMS sized, when this would improve performance.static void split_chunkidxMAX_ITEMS near idx and if there is still sparse space after the real chunk, this also n*MAX_ITEMS sized, so that consecutive writing would make MAX_ITEMS sized real chunks.static void list_setitem of type type in chunk at idx.static void *list_itemtype in the chunk at idx.static void list_append
List *list_newtype.void list_pmc_newList *list_new_initlist_new_init() uses these initializers:    0 ... size (set initial size of list)
    1 ... array dimensions (multiarray)
    2 ... type (overriding type parameter)
    3 ... item_size for enum_type_sized
    4 ... items_per_chunk
void list_pmc_new_initList *list_clonevoid list_markvoid list_visitpinfo is the visit info, (see include/parrot/pmc_freeze.h>).INTVAL list_lengthvoid list_set_lengthlen.void list_insertn_items at idx.void list_deleten_items at idx.void list_pushitem of type type on to the end of the list.void list_unshiftitem of type type on to the start of the list.void *list_poptype from the end of the list.void *list_shifttype from the start of the list.void list_assignitem of type type to index idx.void *list_gettype at index idx.void list_splicecount items starting at offset with the items in value.count is 0 then the items in value will be inserted after offset.
|  |   |