/* list.c */
#include "common.h"
#include "list.h"
#define list_SORTED (1 << 0)
int list_append( list * l, const list_ITY p ) {
l->flags &= ~list_SORTED;
return buffer_append( l, &p, sizeof( p ) );
}
int list_build( list * l, const list_ITY v, size_t sz ) {
int err;
if ( err = list_init( l, sz ), ERR_None != err ) {
return err;
}
for ( ; v; v = list_NEXT( v ) ) {
if ( err = list_append( l, v ), ERR_None != err ) {
return err;
}
}
return ERR_None;
}
static int list_compare( const void *a, const void *b ) {
return list_CMP( a, b );
}
void list_sort( list * l ) {
if ( ( l->flags & list_SORTED ) == 0 ) {
qsort( l->buf, list_used( l ), list_ISZ, list_compare );
l->flags |= list_SORTED;
}
}
long list_true_diff( list * a, list * b, const void *p,
list_callback added, list_callback removed ) {
list_ITY *a_ar;
list_ITY *b_ar;
long a_p, b_p, diff;
size_t a_sz, b_sz;
list_sort( a );
list_sort( b );
a_ar = list_ar( a );
a_sz = list_used( a );
a_p = 0;
b_ar = list_ar( b );
b_sz = list_used( b );
b_p = 0;
diff = 0;
while ( a_p < a_sz || b_p < b_sz ) {
while ( a_p < a_sz &&
( b_p == b_sz ||
list_CMP( &b_ar[b_p], &a_ar[a_p] ) > 0 ) ) {
if ( removed ) {
removed( a_ar[a_p], p );
}
a_p++;
diff++;
}
while ( b_p < b_sz &&
( a_p == a_sz ||
list_CMP( &a_ar[a_p], &b_ar[b_p] ) > 0 ) ) {
if ( added ) {
added( b_ar[b_p], p );
}
b_p++;
diff++;
}
while ( a_p < a_sz && b_p < b_sz &&
list_CMP( &a_ar[a_p], &b_ar[b_p] ) == 0 ) {
a_p++;
b_p++;
}
}
return diff;
}