int bdb_idl_insert( ID *ids, ID id ) { unsigned x; #if IDL_DEBUG > 1 Debug( LDAP_DEBUG_ANY, "insert: %04lx at %d\n", (long) id, x, 0 ); idl_dump( ids ); #elif IDL_DEBUG > 0 idl_check( ids ); #endif if (BDB_IDL_IS_RANGE( ids )) { /* if already in range, treat as a dup */ if (id >= BDB_IDL_RANGE_FIRST(ids) && id <= BDB_IDL_RANGE_LAST(ids)) return -1; if (id < BDB_IDL_RANGE_FIRST(ids)) ids[1] = id; else if (id > BDB_IDL_RANGE_LAST(ids)) ids[2] = id; return 0; } x = bdb_idl_search( ids, id ); assert( x > 0 ); if( x < 1 ) { /* internal error */ return -2; } if ( x <= ids[0] && ids[x] == id ) { /* duplicate */ return -1; } if ( ++ids[0] >= BDB_IDL_DB_MAX ) { if( id < ids[1] ) { ids[1] = id; ids[2] = ids[ids[0]-1]; } else if ( ids[ids[0]-1] < id ) { ids[2] = id; } else { ids[2] = ids[ids[0]-1]; } ids[0] = NOID; } else { /* insert id */ AC_MEMCPY( &ids[x+1], &ids[x], (ids[0]-x) * sizeof(ID) ); ids[x] = id; } #if IDL_DEBUG > 1 idl_dump( ids ); #elif IDL_DEBUG > 0 idl_check( ids ); #endif return 0; }
/* Add one ID to an unsorted list. We ensure that the first element is the * minimum and the last element is the maximum, for fast range compaction. * this means IDLs up to length 3 are always sorted... */ int bdb_idl_append_one( ID *ids, ID id ) { if (BDB_IDL_IS_RANGE( ids )) { /* if already in range, treat as a dup */ if (id >= BDB_IDL_RANGE_FIRST(ids) && id <= BDB_IDL_RANGE_LAST(ids)) return -1; if (id < BDB_IDL_RANGE_FIRST(ids)) ids[1] = id; else if (id > BDB_IDL_RANGE_LAST(ids)) ids[2] = id; return 0; } if ( ids[0] ) { ID tmp; if (id < ids[1]) { tmp = ids[1]; ids[1] = id; id = tmp; } if ( ids[0] > 1 && id < ids[ids[0]] ) { tmp = ids[ids[0]]; ids[ids[0]] = id; id = tmp; } } ids[0]++; if ( ids[0] >= BDB_IDL_UM_MAX ) { ids[0] = NOID; ids[2] = id; } else { ids[ids[0]] = id; } return 0; }
static void idl_check( ID *ids ) { if( BDB_IDL_IS_RANGE( ids ) ) { assert( BDB_IDL_RANGE_FIRST(ids) <= BDB_IDL_RANGE_LAST(ids) ); } else { ID i; for( i=1; i < ids[0]; i++ ) { assert( ids[i+1] > ids[i] ); } } }
static void idl_dump( ID *ids ) { if( BDB_IDL_IS_RANGE( ids ) ) { #ifdef NEW_LOGGING LDAP_LOG( INDEX, INFO, "IDL: range (%ld - %ld)\n", (long) BDB_IDL_RANGE_FIRST( ids ), (long) BDB_IDL_RANGE_LAST( ids ), 0 ); #else Debug( LDAP_DEBUG_ANY, "IDL: range ( %ld - %ld )\n", (long) BDB_IDL_RANGE_FIRST( ids ), (long) BDB_IDL_RANGE_LAST( ids ) ); #endif } else { ID i; #ifdef NEW_LOGGING LDAP_LOG( INDEX, INFO, "IDL: size %ld", (long) ids[0], 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "IDL: size %ld", (long) ids[0], 0, 0 ); #endif for( i=1; i<=ids[0]; i++ ) { if( i % 16 == 1 ) { Debug( LDAP_DEBUG_ANY, "\n", 0, 0, 0 ); } #ifdef NEW_LOGGING LDAP_LOG( INDEX, INFO, "%02lx",(long)ids[i], 0, 0 ); #else Debug( LDAP_DEBUG_ANY, " %02lx", (long) ids[i], 0, 0 ); #endif } Debug( LDAP_DEBUG_ANY, "\n", 0, 0, 0 ); } idl_check( ids ); }
static void idl_dump( ID *ids ) { if( BDB_IDL_IS_RANGE( ids ) ) { Debug( LDAP_DEBUG_ANY, "IDL: range ( %ld - %ld )\n", (long) BDB_IDL_RANGE_FIRST( ids ), (long) BDB_IDL_RANGE_LAST( ids ) ); } else { ID i; Debug( LDAP_DEBUG_ANY, "IDL: size %ld", (long) ids[0], 0, 0 ); for( i=1; i<=ids[0]; i++ ) { if( i % 16 == 1 ) { Debug( LDAP_DEBUG_ANY, "\n", 0, 0, 0 ); } Debug( LDAP_DEBUG_ANY, " %02lx", (long) ids[i], 0, 0 ); } Debug( LDAP_DEBUG_ANY, "\n", 0, 0, 0 ); } idl_check( ids ); }
/* * idl_intersection - return a = a intersection b */ int bdb_idl_intersection( ID *a, ID *b ) { ID ida, idb; ID idmax, idmin; ID cursora = 0, cursorb = 0, cursorc; int swap = 0; if ( BDB_IDL_IS_ZERO( a ) || BDB_IDL_IS_ZERO( b ) ) { a[0] = 0; return 0; } idmin = IDL_MAX( BDB_IDL_FIRST(a), BDB_IDL_FIRST(b) ); idmax = IDL_MIN( BDB_IDL_LAST(a), BDB_IDL_LAST(b) ); if ( idmin > idmax ) { a[0] = 0; return 0; } else if ( idmin == idmax ) { a[0] = 1; a[1] = idmin; return 0; } if ( BDB_IDL_IS_RANGE( a ) ) { if ( BDB_IDL_IS_RANGE(b) ) { /* If both are ranges, just shrink the boundaries */ a[1] = idmin; a[2] = idmax; return 0; } else { /* Else swap so that b is the range, a is a list */ ID *tmp = a; a = b; b = tmp; swap = 1; } } /* If a range completely covers the list, the result is * just the list. If idmin to idmax is contiguous, just * turn it into a range. */ if ( BDB_IDL_IS_RANGE( b ) && BDB_IDL_RANGE_FIRST( b ) <= BDB_IDL_RANGE_FIRST( a ) && BDB_IDL_RANGE_LAST( b ) >= BDB_IDL_RANGE_LAST( a ) ) { if (idmax - idmin + 1 == a[0]) { a[0] = NOID; a[1] = idmin; a[2] = idmax; } goto done; } /* Fine, do the intersection one element at a time. * First advance to idmin in both IDLs. */ cursora = cursorb = idmin; ida = bdb_idl_first( a, &cursora ); idb = bdb_idl_first( b, &cursorb ); cursorc = 0; while( ida <= idmax || idb <= idmax ) { if( ida == idb ) { a[++cursorc] = ida; ida = bdb_idl_next( a, &cursora ); idb = bdb_idl_next( b, &cursorb ); } else if ( ida < idb ) { ida = bdb_idl_next( a, &cursora ); } else { idb = bdb_idl_next( b, &cursorb ); } } a[0] = cursorc; done: if (swap) BDB_IDL_CPY( b, a ); return 0; }