/* nrange.* - stores a set of numbers in a non-memory-hogging way (and speedy too?) Copyright (C) 1999-2002 Matthew Mueller 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 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 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); }