#include "Remembrance.h" /** Allocates and returns a remembrance struct initialised to hold two elements in the vector, the first of which is set to zero. The vector is pre-allocated to be able to hold four elements. Caller should set the second element to the appropiate dimension. */ struct remembrance* remembrance_init() { struct remembrance *ret = malloc( sizeof( struct remembrance ) ); if( ret == NULL ) fprintf(stderr, "remembrance_init(): Error during initialisation!\n"); else { ret->size = 0; ret->alloc = 2; ret->vector = malloc( ret->alloc*sizeof( struct remembrance_item ) ); ret->empty.size = 0; ret->empty.alloc = 1; ret->empty.vector = malloc( ret->empty.alloc*sizeof( struct remembrance_item ) ); ret->free_id = 1; } return ret; } /** Used for sorting remembrance vectors on index */ int remembrance_item_compare( const void *one, const void *two ) { const unsigned long a = ((struct remembrance_item*)one)->index; const unsigned long b = ((struct remembrance_item*)two)->index; if( a>b ) return 1; if( a<b ) return -1; return 0; } /** Will free a remembrance struct. */ int remembrance_destroy( struct remembrance * m ) { if( m == NULL ) { fprintf( stderr, "remembrance_destroy(): Null pointer supplied!\n" ); return FALSE; } if( m->vector == NULL || m->empty.vector == NULL ) { fprintf( stderr, "remembrance_destroy(): Invalid remembrance structure!\n" ); return FALSE; } free( m->vector ); free( m->empty.vector ); free( m ); return TRUE; } struct remembrance_item * remembrance_get( struct remembrance * const m ) { if( m == NULL ) { fprintf( stderr, "remembrance_get(): Null pointer supplied!\n" ); return NULL; } if( m->vector == NULL ) { fprintf( stderr, "remembrance_get(): Invalid remembrance struct!\n" ); return NULL; } if( !remembrance_relateHierarchy( m ) ) { fprintf( stderr, "remembrance_get(): Unable to get relative hierarchy!\n" ); return NULL; } return m->vector; } unsigned long remembrance_getFreeID( struct remembrance * const m ) { return m->free_id++; } /* This function invalidates the data in the empty cuts struct! (m->empty) */ int remembrance_relateHierarchy(struct remembrance * m) { long i; const long int size = m->size; struct remembrance_item * const vector = m->vector; /* extend and abuse empty cuts vector for index translation */ /* worst case memory usage: O(p), where p is the number of parts requested; this is due to the number of IDs given out by remembrance is of O(p) */ const long int tr_size = remembrance_getFreeID( m ); unsigned long *translate; m->empty.vector = realloc( m->empty.vector, tr_size * sizeof( unsigned long ) ); translate = ((unsigned long*)(m->empty.vector)); if( translate == NULL ) { fprintf(stderr, "remembrance_relateHierarchy(): Realloc failed!\n"); return FALSE; } for (i = 0; i < tr_size; i++ ) translate[ i ] = ULONG_MAX; for (i = 0; i < size; i++) { if( vector[i].id == ULONG_MAX ) continue; translate[ vector[ i ].id ] = i; } for (i = 0; i < tr_size; i++ ) if( translate[ i ] == ULONG_MAX ) { fprintf( stderr, "remembrance_relateHierarchy(): ID %ld unset!\n", i ); return FALSE; } for (i = 0; i < size; i++) { vector[ i ].parent = ( vector[i].parent == ULONG_MAX ? ULONG_MAX : translate[ vector[ i ].parent ] ); } return TRUE; } int remembrance_write(struct remembrance * m, FILE *File) { long i; /* if (File == NULL || m == NULL) { fprintf(stderr, "remembrance_write(): Null arguments!\n"); return FALSE; } */ const struct remembrance_item * const vector = m->vector; const long int size = m->size; for (i = 0; i < size-1; i++) { /* Write only indices and relative hierarchy; not the internal IDs */ fprintf(File, "%lu\t%lu\n", vector[i].index + 1, (vector[i].parent == ULONG_MAX ? 0 : vector[i].parent + 1) ); } fprintf(File, "%lu\n", vector[size-1].index+1); return TRUE; }