ArraySTF

Array implementation which supports strings as indizes (st).  Once an object is assigned a memory location it is never changed (fixed location).  See also http://en.wikipedia.org/wiki/Radix_tree.

Summary
ArraySTFArray implementation which supports strings as indizes (st).
CopyrightThis program is free software.
Files
C-kern/api/ds/inmem/arraystf.hHeader file ArraySTF.
C-kern/ds/inmem/arraystf.cImplementation file ArraySTF impl.
Types
struct arraystf_tExport arraystf_t.
struct arraystf_iterator_tExport arraystf_iterator_t, iterator type to iterate of contained nodes.
Functions
test
unittest_ds_inmem_arraystfUnittest for arraystf_t.
arraystf_tTrie implementation to support arrays index with string keys.
lengthThe number of elements stored in this array.
toplevelsizeThe size of array root.
rootidxshiftNr of bits to shift right before root key is used to access root.
rootPoints to top level nodes.
lifetime
new_arraystfAllocates a new array object.
delete_arraystfFrees allocated memory.
foreach-support
iteratortype_arraystfDeclaration to associate arraystf_iterator_t with arraystf_t.
iteratedtype_arraystfFunction declaration to associate arraystf_node_t with arraystf_t.
query
length_arraystfReturns the number of elements stored in the array.
at_arraystfReturns node with same key as *keydata*[size].
change
insert_arraystfInserts new node with string key into array.
tryinsert_arraystfSame as insert_arraystf but no error log in case of EEXIST.
remove_arraystfRemoves node with key keydata.
tryremove_arraystfSame as remove_arraystf but no error log in case of ESRCH.
generic
arraystf_IMPLEMENTAdapts interface of arraystf_t to object type object_t.
arraystf_iterator_tIterates over elements contained in arraystf_t.
stackRemembers last position in tree.
arrayRemembers iterated container.
riIndex into arraystf_t.root.
lifetime
arraystf_iterator_FREEStatic initializer.
initfirst_arraystfiteratorInitializes an iterator for an arraystf_t.
free_arraystfiteratorFrees an iterator for an arraystf_t.
iterate
next_arraystfiteratorReturns next iterated node.
inline implementation
Macros
length_arraystfImplements arraystf_t.length_arraystf.
arraystf_IMPLEMENTImplements arraystf_t.arraystf_IMPLEMENT.

Copyright

This program is free software.  You can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

Author

© 2011 Jörg Seebohn

Files

C-kern/api/ds/inmem/arraystf.h

Header file ArraySTF.

C-kern/ds/inmem/arraystf.c

Implementation file ArraySTF impl.

Types

struct arraystf_t

typedef struct arraystf_t arraystf_t

Export arraystf_t.

struct arraystf_iterator_t

typedef struct arraystf_iterator_t arraystf_iterator_t

Export arraystf_iterator_t, iterator type to iterate of contained nodes.

Functions

test

unittest_ds_inmem_arraystf

int unittest_ds_inmem_arraystf(void)

Unittest for arraystf_t.

arraystf_t

struct arraystf_t

Trie implementation to support arrays index with string keys.  This type of array supports strings as indizes with arbitrary length.

Once an object is assigned a memory location the address is never changed (fixed location).  Every internal trie node contains a memory offset and a bit position (from highest to lowest).  If a key is searched for and an internal node is encountered the byte value at the memory offset in the key is taken and the value of the two bits are extracted.  The resuslting number (0..3) is taken as index into the child array of the internal node arraystf_mwaybranch_t.

From the root node to the leaf node only such offset/bit combinations are compared if there exist at least two stored keys which have different values at this position.  Therefore leaf nodes (user type <generic_object_t>) have always a depth of less than (key length in bits)/2 The mean depth is log2(number of stored keys)/2.

Special Encoding

Cause keys of different length make problems in a patricia trie implementation if a smaller key is a prefix of a longer one.

A C-string has a null byte at its end so no stored string can be a prefix of another longer one.  To allows keys of any binary content an encoding of is chosen so that every key has the same length.  The encoding is as follows (keylength: key->size; keycontent: key->addr[0 .. key->size-1])

  • Every key is of length SIZE_MAX (UINT32_MAX or UINT64_MAX)
  • The byte values at offset 0 .. key->size-1 are taken from key->addr
  • The byte values at offset key->size ..  SIZE_MAX-1 are always 0
  • The value at offset SIZE_MAX is key->size and has bitsof(size_t) bits instead of only 8
Summary
lengthThe number of elements stored in this array.
toplevelsizeThe size of array root.
rootidxshiftNr of bits to shift right before root key is used to access root.
rootPoints to top level nodes.
lifetime
new_arraystfAllocates a new array object.
delete_arraystfFrees allocated memory.
foreach-support
iteratortype_arraystfDeclaration to associate arraystf_iterator_t with arraystf_t.
iteratedtype_arraystfFunction declaration to associate arraystf_node_t with arraystf_t.
query
length_arraystfReturns the number of elements stored in the array.
at_arraystfReturns node with same key as *keydata*[size].
change
insert_arraystfInserts new node with string key into array.
tryinsert_arraystfSame as insert_arraystf but no error log in case of EEXIST.
remove_arraystfRemoves node with key keydata.
tryremove_arraystfSame as remove_arraystf but no error log in case of ESRCH.
generic
arraystf_IMPLEMENTAdapts interface of arraystf_t to object type object_t.

length

size_t length

The number of elements stored in this array.

toplevelsize

uint32_t toplevelsize:24

The size of array root.

rootidxshift

uint32_t rootidxshift:8

Nr of bits to shift right before root key is used to access root.

root

union arraystf_unode_t * root[/*toplevelsize*/]

Points to top level nodes.  The size of the root array is determined by toplevelsize.

lifetime

new_arraystf

int new_arraystf(/*out*/arraystf_t **array,
uint32_t toplevelsize)

Allocates a new array object.  Parameter toplevelsize determines the number of childs of root node.

delete_arraystf

int delete_arraystf(arraystf_t **array,
struct typeadapt_member_t *nodeadp)

Frees allocated memory.  If nodeadp is set to 0 no free function is called for contained nodes.

foreach-support

iteratortype_arraystf

typedef arraystf_iterator_t iteratortype_arraystf

Declaration to associate arraystf_iterator_t with arraystf_t.  The association is done with a typedef which looks like a function.

iteratedtype_arraystf

typedef struct arraystf_node_t * iteratedtype_arraystf

Function declaration to associate arraystf_node_t with arraystf_t.  The association is done with a typedef which looks like a function.

query

length_arraystf

size_t length_arraystf(arraystf_t *array)

Returns the number of elements stored in the array.

at_arraystf

struct arraystf_node_t * at_arraystf(const arraystf_t *array,
size_t size,
const uint8_t keydata[size])

Returns node with same key as *keydata*[size].  If no element exists with this key value 0 is returned.

change

insert_arraystf

int insert_arraystf(
   arraystf_t *array,  
   struct arraystf_node_t *node,  
   /*out*/struct arraystf_node_t **inserted_node/*0 = >copy not returned*/,
   struct typeadapt_member_t *nodeadp/*0 = >no copy is made*/
)

Inserts new node with string key into array.  If the provided key is already stored EEXIST is returned.  If you have set nodeadp to a value != 0 then a copy of node is made before it is inserted.  The copied node is returned in inserted_node.  If nodeadp is 0 and no copy is made inserted_node is set to node.

tryinsert_arraystf

int tryinsert_arraystf(
   arraystf_t *array,  
   struct arraystf_node_t *node,  
    /*out;  
   err*/struct arraystf_node_t **inserted_or_existing_node,  
   struct typeadapt_member_t *nodeadp/*0 = >no copy is made*/
)

Same as insert_arraystf but no error log in case of EEXIST.  If EEXIST is returned nothing was inserted but the existing node will be returned in inserted_or_existing_node nevertheless.

remove_arraystf

int remove_arraystf(arraystf_t *array,
size_t size,
const uint8_t keydata[size],
/*out*/struct arraystf_node_t **removed_node)

Removes node with key keydata.  If no node exists with this key ESRCH is returned.  In case of success the removed node is returned in removed_node.

tryremove_arraystf

int tryremove_arraystf(arraystf_t *array,
size_t size,
const uint8_t keydata[size],
/*out*/struct arraystf_node_t **removed_node)

Same as remove_arraystf but no error log in case of ESRCH.

generic

arraystf_IMPLEMENT

void arraystf_IMPLEMENT(IDNAME _fsuffix,
TYPENAME object_t,
IDNAME nodename) ;

Adapts interface of arraystf_t to object type object_t.  All generated functions are the same as for arraystf_t except the type arraystf_node_t is replaced with object_t.  The conversion from object_t to arraystf_node_t and vice versa is done before _arraystf functions are called and after return the out parameters are converted.

Parameter

_fsuffixIt is the suffix of the generated container interface functions which wraps all calls to arraystf_t.
object_tThe object which is stored in this container derived from generic arraystf_t.
nodenameThe member name (access path) in object_t corresponding to the member name of the embedded arraystf_node_t.  Or the same value as the first parameter used in <arraystf_node_EMBED> to embed the node.

arraystf_iterator_t

struct arraystf_iterator_t

Iterates over elements contained in arraystf_t.

Summary
stackRemembers last position in tree.
arrayRemembers iterated container.
riIndex into arraystf_t.root.
lifetime
arraystf_iterator_FREEStatic initializer.
initfirst_arraystfiteratorInitializes an iterator for an arraystf_t.
free_arraystfiteratorFrees an iterator for an arraystf_t.
iterate
next_arraystfiteratorReturns next iterated node.

stack

struct binarystack_t * stack

Remembers last position in tree.

array

arraystf_t * array

Remembers iterated container.

ri

unsigned ri

Index into arraystf_t.root.

lifetime

arraystf_iterator_FREE

#define arraystf_iterator_FREE { 0, 0, 0 }

Static initializer.

initfirst_arraystfiterator

int initfirst_arraystfiterator(/*out*/arraystf_iterator_t *iter,
arraystf_t *array)

Initializes an iterator for an arraystf_t.

free_arraystfiterator

int free_arraystfiterator(arraystf_iterator_t *iter)

Frees an iterator for an arraystf_t.

iterate

next_arraystfiterator

bool next_arraystfiterator(arraystf_iterator_t *iter,
/*out*/struct arraystf_node_t **node)

Returns next iterated node.  The first call after initfirst_arraystfiterator returns the first array element if it is not empty.

Returns

truenode contains a pointer to the next valid node in the list.
falseThere is no next node.  The last element was already returned or the array is empty.

Macros

length_arraystf

#define length_arraystf(array) ((array)->length)

Implements arraystf_t.length_arraystf.

arraystf_IMPLEMENT

#define arraystf_IMPLEMENT(
   _fsuffix,
   object_t,
   nodename
) typedef arraystf_iterator_t iteratortype##_fsuffix ; typedef object_t * iteratedtype##_fsuffix ; static inline int new##_fsuffix(/*out*/arraystf_t ** array, uint32_t toplevelsize) __attribute__ ((always_inline)) ; static inline int delete##_fsuffix(arraystf_t ** array, struct typeadapt_member_t * nodeadp) __attribute__ ((always_inline)) ; static inline size_t length##_fsuffix(arraystf_t * array) __attribute__ ((always_inline)) ; static inline object_t * at##_fsuffix(const arraystf_t * array, size_t size, const uint8_t keydata[size]) __attribute__ ((always_inline)) ; static inline int insert##_fsuffix(arraystf_t * array, object_t * node, /*out*/object_t ** inserted_node/*0=>copy not returned*/, struct typeadapt_member_t * nodeadp/*0=>no copy is made*/) __attribute__ ((always_inline)) ; static inline int tryinsert##_fsuffix(arraystf_t * array, object_t * node, /*out;err*/object_t ** inserted_or_existing_node, struct typeadapt_member_t * nodeadp/*0=>no copy is made*/) __attribute__ ((always_inline)) ; static inline int remove##_fsuffix(arraystf_t * array, size_t size, const uint8_t keydata[size], /*out*/object_t ** removed_node) __attribute__ ((always_inline)) ; static inline int tryremove##_fsuffix(arraystf_t * array, size_t size, const uint8_t keydata[size], /*out*/object_t ** removed_node) __attribute__ ((always_inline)) ; static inline int initfirst##_fsuffix##iterator(/*out*/arraystf_iterator_t * iter, arraystf_t * array) __attribute__ ((always_inline)) ; static inline int free##_fsuffix##iterator(arraystf_iterator_t * iter) __attribute__ ((always_inline)) ; static inline bool next##_fsuffix##iterator(arraystf_iterator_t * iter, /*out*/object_t ** node) __attribute__ ((always_inline)) ; static inline arraystf_node_t * asnode##_fsuffix(object_t * object) { static_assert(&((object_t*)0)->nodename == (void*)offsetof(object_t, nodename), "correct type") ; return (arraystf_node_t*) ((uintptr_t)object + offsetof(object_t, nodename)) ; } static inline object_t * asobject##_fsuffix(arraystf_node_t * node) { return (object_t *) ((uintptr_t)node - offsetof(object_t, nodename)) ; } static inline object_t * asobjectnull##_fsuffix(arraystf_node_t * node) { return node ? (object_t *) ((uintptr_t)node - offsetof(object_t, nodename)) : 0 ; } static inline int new##_fsuffix(/*out*/arraystf_t ** array, uint32_t toplevelsize) { return new_arraystf(array, toplevelsize) ; } static inline int delete##_fsuffix(arraystf_t ** array, struct typeadapt_member_t * nodeadp) { return delete_arraystf(array, nodeadp) ; } static inline size_t length##_fsuffix(arraystf_t * array) { return length_arraystf(array) ; } static inline object_t * at##_fsuffix(const arraystf_t * array, size_t size, const uint8_t keydata[size]) { arraystf_node_t * node = at_arraystf(array, size, keydata) ; return asobjectnull##_fsuffix(node) ; } static inline int insert##_fsuffix(arraystf_t * array, object_t * node, /*out*/object_t ** inserted_node/*0=>copy not returned*/, struct typeadapt_member_t * nodeadp/*0=>no copy is made*/) { int err = insert_arraystf(array, asnode##_fsuffix(node), (struct arraystf_node_t**)inserted_node, nodeadp) ; if (!err && inserted_node) *inserted_node = asobject##_fsuffix(*(struct arraystf_node_t**)inserted_node) ; return err ; } static inline int tryinsert##_fsuffix(arraystf_t * array, object_t * node, /*out;err*/object_t ** inserted_or_existing_node, struct typeadapt_member_t * nodeadp/*0=>no copy is made*/) { int err = tryinsert_arraystf(array, asnode##_fsuffix(node), (struct arraystf_node_t**)inserted_or_existing_node, nodeadp) ; *inserted_or_existing_node = asobjectnull##_fsuffix(*(struct arraystf_node_t**)inserted_or_existing_node) ; return err ; } static inline int remove##_fsuffix(arraystf_t * array, size_t size, const uint8_t keydata[size], /*out*/object_t ** removed_node) { int err = remove_arraystf(array, size, keydata, (struct arraystf_node_t**)removed_node) ; if (!err) *removed_node = asobject##_fsuffix(*(struct arraystf_node_t**)removed_node) ; return err ; } static inline int tryremove##_fsuffix(arraystf_t * array, size_t size, const uint8_t keydata[size], /*out*/object_t ** removed_node) { int err = tryremove_arraystf(array, size, keydata, (struct arraystf_node_t**)removed_node) ; if (!err) *removed_node = asobject##_fsuffix(*(struct arraystf_node_t**)removed_node) ; return err ; } static inline int initfirst##_fsuffix##iterator(/*out*/arraystf_iterator_t * iter, arraystf_t * array) { return initfirst_arraystfiterator(iter, array) ; } static inline int free##_fsuffix##iterator(arraystf_iterator_t * iter) { return free_arraystfiterator(iter) ; } static inline bool next##_fsuffix##iterator(arraystf_iterator_t * iter, /*out*/object_t ** node) { bool isNext = next_arraystfiterator(iter, (struct arraystf_node_t**)node) ; if (isNext) *node = asobject##_fsuffix(*(struct arraystf_node_t**)node) ; return isNext ; }

Implements arraystf_t.arraystf_IMPLEMENT.

Array implementation which supports strings as indizes (st).
Implements array which supports strings as index values.
typedef struct arraystf_t arraystf_t
Export arraystf_t.
struct arraystf_t
Trie implementation to support arrays index with string keys.
typedef struct arraystf_iterator_t arraystf_iterator_t
Export arraystf_iterator_t, iterator type to iterate of contained nodes.
struct arraystf_iterator_t
Iterates over elements contained in arraystf_t.
int unittest_ds_inmem_arraystf(void)
Unittest for arraystf_t.
size_t length
The number of elements stored in this array.
uint32_t toplevelsize:24
The size of array root.
union arraystf_unode_t * root[/*toplevelsize*/]
Points to top level nodes.
uint32_t rootidxshift:8
Nr of bits to shift right before root key is used to access root.
int new_arraystf(/*out*/arraystf_t **array,
uint32_t toplevelsize)
Allocates a new array object.
int delete_arraystf(arraystf_t **array,
struct typeadapt_member_t *nodeadp)
Frees allocated memory.
typedef arraystf_iterator_t iteratortype_arraystf
Declaration to associate arraystf_iterator_t with arraystf_t.
typedef struct arraystf_node_t * iteratedtype_arraystf
Function declaration to associate arraystf_node_t with arraystf_t.
size_t length_arraystf(arraystf_t *array)
Returns the number of elements stored in the array.
struct arraystf_node_t * at_arraystf(const arraystf_t *array,
size_t size,
const uint8_t keydata[size])
Returns node with same key as *keydata*[size].
int insert_arraystf(
   arraystf_t *array,  
   struct arraystf_node_t *node,  
   /*out*/struct arraystf_node_t **inserted_node/*0 = >copy not returned*/,
   struct typeadapt_member_t *nodeadp/*0 = >no copy is made*/
)
Inserts new node with string key into array.
int tryinsert_arraystf(
   arraystf_t *array,  
   struct arraystf_node_t *node,  
    /*out;  
   err*/struct arraystf_node_t **inserted_or_existing_node,  
   struct typeadapt_member_t *nodeadp/*0 = >no copy is made*/
)
Same as insert_arraystf but no error log in case of EEXIST.
int remove_arraystf(arraystf_t *array,
size_t size,
const uint8_t keydata[size],
/*out*/struct arraystf_node_t **removed_node)
Removes node with key keydata.
int tryremove_arraystf(arraystf_t *array,
size_t size,
const uint8_t keydata[size],
/*out*/struct arraystf_node_t **removed_node)
Same as remove_arraystf but no error log in case of ESRCH.
void arraystf_IMPLEMENT(IDNAME _fsuffix,
TYPENAME object_t,
IDNAME nodename) ;
Adapts interface of arraystf_t to object type object_t.
struct binarystack_t * stack
Remembers last position in tree.
arraystf_t * array
Remembers iterated container.
unsigned ri
Index into arraystf_t.root.
#define arraystf_iterator_FREE { 0, 0, 0 }
Static initializer.
int initfirst_arraystfiterator(/*out*/arraystf_iterator_t *iter,
arraystf_t *array)
Initializes an iterator for an arraystf_t.
int free_arraystfiterator(arraystf_iterator_t *iter)
Frees an iterator for an arraystf_t.
bool next_arraystfiterator(arraystf_iterator_t *iter,
/*out*/struct arraystf_node_t **node)
Returns next iterated node.
#define length_arraystf(array) ((array)->length)
Implements arraystf_t.length_arraystf.
#define arraystf_IMPLEMENT(
   _fsuffix,
   object_t,
   nodename
) typedef arraystf_iterator_t iteratortype##_fsuffix ; typedef object_t * iteratedtype##_fsuffix ; static inline int new##_fsuffix(/*out*/arraystf_t ** array, uint32_t toplevelsize) __attribute__ ((always_inline)) ; static inline int delete##_fsuffix(arraystf_t ** array, struct typeadapt_member_t * nodeadp) __attribute__ ((always_inline)) ; static inline size_t length##_fsuffix(arraystf_t * array) __attribute__ ((always_inline)) ; static inline object_t * at##_fsuffix(const arraystf_t * array, size_t size, const uint8_t keydata[size]) __attribute__ ((always_inline)) ; static inline int insert##_fsuffix(arraystf_t * array, object_t * node, /*out*/object_t ** inserted_node/*0=>copy not returned*/, struct typeadapt_member_t * nodeadp/*0=>no copy is made*/) __attribute__ ((always_inline)) ; static inline int tryinsert##_fsuffix(arraystf_t * array, object_t * node, /*out;err*/object_t ** inserted_or_existing_node, struct typeadapt_member_t * nodeadp/*0=>no copy is made*/) __attribute__ ((always_inline)) ; static inline int remove##_fsuffix(arraystf_t * array, size_t size, const uint8_t keydata[size], /*out*/object_t ** removed_node) __attribute__ ((always_inline)) ; static inline int tryremove##_fsuffix(arraystf_t * array, size_t size, const uint8_t keydata[size], /*out*/object_t ** removed_node) __attribute__ ((always_inline)) ; static inline int initfirst##_fsuffix##iterator(/*out*/arraystf_iterator_t * iter, arraystf_t * array) __attribute__ ((always_inline)) ; static inline int free##_fsuffix##iterator(arraystf_iterator_t * iter) __attribute__ ((always_inline)) ; static inline bool next##_fsuffix##iterator(arraystf_iterator_t * iter, /*out*/object_t ** node) __attribute__ ((always_inline)) ; static inline arraystf_node_t * asnode##_fsuffix(object_t * object) { static_assert(&((object_t*)0)->nodename == (void*)offsetof(object_t, nodename), "correct type") ; return (arraystf_node_t*) ((uintptr_t)object + offsetof(object_t, nodename)) ; } static inline object_t * asobject##_fsuffix(arraystf_node_t * node) { return (object_t *) ((uintptr_t)node - offsetof(object_t, nodename)) ; } static inline object_t * asobjectnull##_fsuffix(arraystf_node_t * node) { return node ? (object_t *) ((uintptr_t)node - offsetof(object_t, nodename)) : 0 ; } static inline int new##_fsuffix(/*out*/arraystf_t ** array, uint32_t toplevelsize) { return new_arraystf(array, toplevelsize) ; } static inline int delete##_fsuffix(arraystf_t ** array, struct typeadapt_member_t * nodeadp) { return delete_arraystf(array, nodeadp) ; } static inline size_t length##_fsuffix(arraystf_t * array) { return length_arraystf(array) ; } static inline object_t * at##_fsuffix(const arraystf_t * array, size_t size, const uint8_t keydata[size]) { arraystf_node_t * node = at_arraystf(array, size, keydata) ; return asobjectnull##_fsuffix(node) ; } static inline int insert##_fsuffix(arraystf_t * array, object_t * node, /*out*/object_t ** inserted_node/*0=>copy not returned*/, struct typeadapt_member_t * nodeadp/*0=>no copy is made*/) { int err = insert_arraystf(array, asnode##_fsuffix(node), (struct arraystf_node_t**)inserted_node, nodeadp) ; if (!err && inserted_node) *inserted_node = asobject##_fsuffix(*(struct arraystf_node_t**)inserted_node) ; return err ; } static inline int tryinsert##_fsuffix(arraystf_t * array, object_t * node, /*out;err*/object_t ** inserted_or_existing_node, struct typeadapt_member_t * nodeadp/*0=>no copy is made*/) { int err = tryinsert_arraystf(array, asnode##_fsuffix(node), (struct arraystf_node_t**)inserted_or_existing_node, nodeadp) ; *inserted_or_existing_node = asobjectnull##_fsuffix(*(struct arraystf_node_t**)inserted_or_existing_node) ; return err ; } static inline int remove##_fsuffix(arraystf_t * array, size_t size, const uint8_t keydata[size], /*out*/object_t ** removed_node) { int err = remove_arraystf(array, size, keydata, (struct arraystf_node_t**)removed_node) ; if (!err) *removed_node = asobject##_fsuffix(*(struct arraystf_node_t**)removed_node) ; return err ; } static inline int tryremove##_fsuffix(arraystf_t * array, size_t size, const uint8_t keydata[size], /*out*/object_t ** removed_node) { int err = tryremove_arraystf(array, size, keydata, (struct arraystf_node_t**)removed_node) ; if (!err) *removed_node = asobject##_fsuffix(*(struct arraystf_node_t**)removed_node) ; return err ; } static inline int initfirst##_fsuffix##iterator(/*out*/arraystf_iterator_t * iter, arraystf_t * array) { return initfirst_arraystfiterator(iter, array) ; } static inline int free##_fsuffix##iterator(arraystf_iterator_t * iter) { return free_arraystfiterator(iter) ; } static inline bool next##_fsuffix##iterator(arraystf_iterator_t * iter, /*out*/object_t ** node) { bool isNext = next_arraystfiterator(iter, (struct arraystf_node_t**)node) ; if (isNext) *node = asobject##_fsuffix(*(struct arraystf_node_t**)node) ; return isNext ; }
Implements arraystf_t.arraystf_IMPLEMENT.
struct arraystf_mwaybranch_t
Internal node to implement a multiway trie.
Close