/* -------------------- */ /* nested_loops.c */ #include "nested_loops.h" void NestedLoop_list_free_none(void*) { /* Do nothing */ } void NestedLoops_array_to_list( struct NestedLoop_List* list, void* array, int array_size, int elem_size ) { (*list).length = array_size; (*list).free = &free; NestedLoops_to_ptr_array( &((*list).ptr), array, array_size, elem_size ); } void NestedLoops_to_ptr_array( void** ptr_array_ptr, void* array, int array_size, int elem_size ) { int src; void* dst; int i; ptr_array_ptr = (void**)calloc(ptr_array_size, sizeof(void*)); src = (int)array; dst = *ptr_array_ptr; for (i=array_size; i--; ) { *dst = (void*)src; dst++; src += elem_size; } } void NestedLoops_free_list(struct NestedLoop_List* list) { if ((*list).ptr != NULL) { (*list).free(list); (*list).length = 0; (*list).ptr = NULL; (*list).free = &NestedLoop_no_free; (*list).free_pad = NULL; } } void NestedLoops_get_iter( struct NestedLoop_Iter* iter, int num_loops, struct NestedLoop_Arg* loops, ) { (*iter).num_loops = num_loops; (*iter).loops = loops; (*iter).indexes = (int*)calloc(num_loops, sizeof(int)); (*iter).vals = (struct NestedLoop_List*)calloc(num_loops, sizeof(struct NestedLoop_List)) (*iter).list.length = 0; (*iter).list.ptr = (void**)calloc(num_loops, sizeof(void*)); (*iter).list.free = &free; { int i = (*iter).num_loops; struct NestedLoop_Arg* loop = (*iter).loops; struct NestedLoop_List* loop_vals = (*iter).vals; while (i--) { if ((*loop).ptr_type == NestedLoop_PT_ARRAY) { (*loop_vals).length = (*loop).ptr.array.length; (*loop_vals).ptr = (*loop).ptr.array.ptr; (*loop_vals).free = &NestedLoop_no_free; (*loop_vals).free_pad = NULL; } else /* if ((*loop).ptr_type == NestedLoop_PT_FUNC) */ { (*loop_vals).length = 0; (*loop_vals).ptr = NULL; (*loop_vals).free = &NestedLoop_no_free; (*loop_vals).free_pad = NULL; } loop++; loop_vals++; } } } BOOL NestedLoops_fetch( struct NestedLoop_Iter* iter ) { int last_loop_idx = (*iter).num_loops - 1; int last_list_idx = (*iter).list.length - 1; /* Save on return! */ int* indexes = (*iter).indexes; if (last_list_idx < last_loop_idx) { struct NestedLoopArg* loops = (*iter).loops; indexes[++last_list_idx] = -1; if (loops[last_list_idx].ptr_type == NestedLoop_PT_FUNC) { struct NestedLoop_Arg* loop = &{loops[last_list_idx]); struct NestedLoop_List* loop_vals = &(vals [last_list_idx]); NestedLoops_free_list(loop_vals); (*(*arg).ptr.func.ptr)(loop_vals, (*arg).ptr.func.pad); } } /* If the last loop is done, */ /* increment the index of the previous loop. */ /* Exit if every loop is at its last index. */ for (;;) { struct NestedLoop_List* loop_vals = &(vals[last_list_idx]); ++indexes[last_list_idx]; if (indexes[last_list_idx] >= (*loop_vals).length) { break; } --last_list_idx; if (last_list_idx < 0) { (*iter).list.length = last_list_idx + 1; return FALSE; } } /* Populate the list. */ (*iter).list.ptr[last_list_idx] = vals[last_list_idx].ptr[indexes[last_list_idx]]; (*iter).list.length = last_list_idx + 1; return TRUE; } void NestedLoops_done( struct NestedLoop_Iter* iter ) { NestedLoops_free_list((*iter).list); { int i = (*iter).num_loops; struct NestedLoop_List* loop_vals = (*iter).vals; while (i--) { NestedLoops_free_list(loop_vals++); } } free((*iter).indexes); (*iter).indexes = NULL; }