tree: rationalize data organization #1164

pull/1351/head
nick black 4 years ago committed by Nick Black
parent 85e3e1d79a
commit 6227b9c1ba

@ -1,5 +1,6 @@
#include "internal.h" #include "internal.h"
// these are never allocated themselves, but always as arrays of object
typedef struct nctree_int_item { typedef struct nctree_int_item {
void* curry; void* curry;
ncplane* n; ncplane* n;
@ -10,40 +11,50 @@ typedef struct nctree_int_item {
typedef struct nctree { typedef struct nctree {
ncplane* ncp; ncplane* ncp;
int (*cbfxn)(ncplane*, void*, int); int (*cbfxn)(ncplane*, void*, int);
nctree_int_item* items; nctree_int_item items;
unsigned itemcount;
// FIXME need to track item we're on, probably via array of uints + sentinel? // FIXME need to track item we're on, probably via array of uints + sentinel?
unsigned maxdepth;
unsigned activerow; unsigned activerow;
uint64_t bchannels; uint64_t bchannels;
} nctree; } nctree;
// recursively free an array of nctree_int_item; nctree_int_item structs are
// never individually free()d, just their innards
static void static void
free_tree_items(nctree_int_item* iarray){ free_tree_items(nctree_int_item* iarray){
for(unsigned c = 0 ; c < iarray->subcount ; ++c){ for(unsigned c = 0 ; c < iarray->subcount ; ++c){
free_tree_items(&iarray->subs[c]); free_tree_items(&iarray->subs[c]);
} }
ncplane_destroy(iarray->n);
free(iarray->subs); free(iarray->subs);
} }
static nctree_int_item* // allocates a |count|-sized array of nctree_int_items, and fills |fill| in,
dup_tree_items(const nctree_item* items, unsigned count){ // using |items|. updates |*maxdepth| when appropriate.
nctree_int_item* ret = malloc(sizeof(*ret) * count); static int
if(ret){ dup_tree_items(nctree_int_item* fill, const nctree_item* items, unsigned count, unsigned depth,
for(unsigned c = 0 ; c < count ; ++c){ unsigned* maxdepth){
nctree_int_item* nii = &ret[c]; fill->subcount = count;
fill->subs = malloc(sizeof(*fill->subs) * count);
if(fill->subs == NULL){
return -1;
}
for(unsigned c = 0 ; c < fill->subcount ; ++c){
nctree_int_item* nii = &fill->subs[c];
nii->curry = items[c].curry; nii->curry = items[c].curry;
nii->n = NULL; nii->n = NULL;
nii->subcount = items[c].subcount; if(dup_tree_items(nii, items[c].subs, items[c].subcount, depth + 1, maxdepth)){
if((nii->subs = dup_tree_items(items[c].subs, nii->subcount)) == NULL){
while(c--){ while(c--){
free_tree_items(&ret[c]); free_tree_items(&fill->subs[c]);
} }
free(ret); free(fill->subs);
return NULL; return -1;
} }
} }
if(depth > *maxdepth){
*maxdepth = depth;
} }
return ret; return 0;
} }
static nctree* static nctree*
@ -52,15 +63,15 @@ nctree_inner_create(ncplane* n, const struct nctree_options* opts){
if(ret){ if(ret){
ret->bchannels = opts->bchannels; ret->bchannels = opts->bchannels;
ret->cbfxn = opts->nctreecb; ret->cbfxn = opts->nctreecb;
ret->itemcount = opts->count; ret->maxdepth = 0;
ret->items = dup_tree_items(opts->items, ret->itemcount); if(dup_tree_items(&ret->items, opts->items, opts->count, 0, &ret->maxdepth)){
ret->activerow = 0;
ret->ncp = n;
if(ret->items == NULL){
logerror(ncplane_notcurses(n), "Couldn't duplicate tree items\n");
free(ret); free(ret);
return NULL; return NULL;
} }
ret->items.n = NULL;
ret->items.curry = NULL;
ret->activerow = 0;
ret->ncp = n;
} }
return ret; return ret;
} }
@ -84,10 +95,7 @@ nctree* nctree_create(ncplane* n, const struct nctree_options* opts){
void nctree_destroy(nctree* n){ void nctree_destroy(nctree* n){
if(n){ if(n){
for(unsigned c = 0 ; c < n->itemcount ; ++c){ free_tree_items(&n->items);
free_tree_items(&n->items[c]);
}
free(n->items);
free(n); free(n);
} }
} }

Loading…
Cancel
Save