/*
nrange.* - stores a set of numbers in a non-memory-hogging way (and speedy too?)
Copyright (C) 1999-2002 Matthew Mueller <donut AT dakotacom.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "nrange.h"
#include "log.h"
void c_nrange::insert(ulong n){
t_rlist::iterator i=rlist.lower_bound(n),j;
if (i!=rlist.end()){
if ((*i).second<=n)
return;//already in a range
if ((*i).second==n+1){
(*i).second=n;
// return;//1 below a range, don't return because we need to check for being 1 above another range
}else
i=rlist.end();//no good.
}
//changed=1;//if we've gotten here, something will change.
if (n>varmin){//don't wanna wrap around, since we are using unsigned
j=rlist.find(n-1);
if (j!=rlist.end()){
if (i!=rlist.end())
(*i).second=(*j).second;//1 above and 1 below two different ranges
else
rlist[n]=(*j).second;//only 1 above a range
rlist.erase(j);
return;
}
}
if (i==rlist.end())
rlist[n]=n;//need a new range
}
void c_nrange::insert(ulong l,ulong h){
if (rlist.empty()){
rlist[h]=l;
//changed=1;
return;
}
ulong l1=(l>varmin)?l-1:l;
ulong h1=(h<varmax)?h+1:h;
t_rlist::iterator j=rlist.lower_bound(l1);
if (j==rlist.end()){
rlist[h]=l;//changed=1;
return;
}
t_rlist::iterator i=rlist.lower_bound(h);
if (i==j){//if high and low matches find the same range
if (l<(*j).second){//if low is outside the range:
if ( (*j).second > h1 )
rlist[h]=l;//and high is outside too, make a new range
else
(*j).second=l;//else extend it
//changed=1;
}
return;
}
if ((*j).second<l)
l=(*j).second;
rlist.erase(j,i);//erase all the entries that will be encompassed by the new range
if ((i==rlist.end()) || ( (*i).second > h1 ) ){
rlist[h]=l;//if we are at the end, or below the one above us, make a new entry
}else
(*i).second=l;//else extend the one above us
//changed=1;
}
void c_nrange::remove(ulong l, ulong h){
const int debug=0;//hehe.
if (debug){printf("remove (%lu-%lu) nrange...",l,h);fflush(stdout);}
if (rlist.empty()){
if (debug)printf("empty\n");
return;
}
ulong ssize=0,rtot=0,rpart=0;
int tmp=0,doneflag=0;
if (debug)ssize=rlist.size();
t_rlist::iterator i=rlist.lower_bound(h),j;
if (i==rlist.end())
i=rlist.lower_bound(l);
// --i;
//while (i!=rlist.end()){
if (i==rlist.end())
doneflag=1;
else
j=i;
//while (j!=rlist.begin() && i!=rlist.end()){
while (!doneflag){
if (j==rlist.begin())
doneflag=1;
--i;
if (h >= (*j).first){
if (l <= (*j).first) {//remove range cuts off (some or all) of this range
if (l > (*j).second){
rlist[l-1]=(*j).second;//remove range cuts off only the top part
rpart++;
}else
rtot++;
rlist.erase(j);
//changed=1;
}else{
// if (debug)printf("a(%i)\n",ssize-rlist.size());
// return;//remove range is completely above this range, so we are done
tmp=2;break;
}
}else{
if (h >= (*j).second) {//remove range cuts off (some) of the lower of this range
if (l > (*j).second) {
tmp=1;
rlist[l-1]=(*j).second;//remove range cuts through the middle of a current range
}
(*j).second=h+1;
//changed=1;
rpart++;
if (tmp) break;//its completely within this range, so we are done.
}
// delete j;
}
j=i;
}
if (debug)printf("%i(%lu tot:%lu part:%lu (%lu->%lu))\n",tmp,ssize-(ulong)rlist.size(),rtot,rpart,ssize,(ulong)rlist.size());
}
void c_nrange::invert(const c_nrange &r){
if (r.empty()) {
insert(varmin,varmax);
return;
}
ulong n=varmin;
t_rlist::const_iterator i;
for (i=r.rlist.begin(); i!=r.rlist.end(); ++i) {
if (n!=i->second)
insert(n, i->second-1);
n=i->first+1;
}
if (n!=varmin)//if r contains varmax, then n=varmax+1=varmin, so don't try to add anything.
insert(n, varmax);
}
syntax highlighted by Code2HTML, v. 0.9.1