+ /// Moves whole case from current mapping to the NewMapping object.
+ void detachCase(self& NewMapping, SuccessorClass *Succ) {
+ for (CaseItemIt i = Items.begin(); i != Items.end();)
+ if (i->second == Succ) {
+ NewMapping.add(i->first, i->second);
+ Items.erase(i++);
+ } else
+ ++i;
+ }
+
+ /// Removes all clusters for given successor.
+ void removeCase(SuccessorClass *Succ) {
+ for (CaseItemIt i = Items.begin(); i != Items.end();)
+ if (i->second == Succ) {
+ Items.erase(i++);
+ } else
+ ++i;
+ }
+
+ /// Find successor that satisfies given value.
+ SuccessorClass *findSuccessor(const IntTy& Val) {
+ for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) {
+ if (i->first.isInRange(Val))
+ return i->second;
+ }
+ return 0;
+ }
+
+ /// Calculates the difference between this mapping and RHS.
+ /// THIS without RHS is placed into LExclude,
+ /// RHS without THIS is placed into RExclude,
+ /// THIS intersect RHS is placed into Intersection.
+ void diff(self *LExclude, self *Intersection, self *RExclude,
+ const self& RHS) {
+
+ if (SingleNumbersOnly && RHS.SingleNumbersOnly) {
+ diff_single_numbers(LExclude, Intersection, RExclude, RHS);
+ return;
+ }
+
+ DiffStateMachine Machine(LExclude, Intersection, RExclude);
+
+ CaseItemConstIt L = Items.begin(), R = RHS.Items.begin();
+ CaseItemConstIt el = Items.end(), er = RHS.Items.end();
+ while (L != el && R != er) {
+ const Cluster &LCluster = *L;
+ const RangeEx &LRange = LCluster.first;
+ const Cluster &RCluster = *R;
+ const RangeEx &RRange = RCluster.first;
+
+ if (LRange.getHigh() < RRange.getLow()) {
+ Machine.onLOpen(LRange.getLow(), LCluster.second);
+ Machine.onLClose(LRange.getHigh());
+ ++L;
+ continue;
+ }
+
+ if (LRange.getLow() > RRange.getHigh()) {
+ Machine.onROpen(RRange.getLow(), RCluster.second);
+ Machine.onRClose(RRange.getHigh());
+ ++R;
+ continue;
+ }
+
+ if (LRange.isSingleNumber() && RRange.isSingleNumber()) {
+ Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second);
+ Machine.onLRClose(LRange.getLow());
+ ++L;
+ ++R;
+ continue;
+ }
+
+ if (LRange.isSingleNumber()) {
+ Machine.onLOpen(LRange.getLow(), LCluster.second);
+ Machine.onLClose(LRange.getLow());
+ ++L;
+ while(L != Items.end() && L->first.getHigh() < RRange.getHigh()) {
+ Machine.onLOpen(LRange.getLow(), LCluster.second);
+ Machine.onLClose(LRange.getLow());
+ ++L;
+ }
+ continue;
+ } else if (RRange.isSingleNumber()) {
+ Machine.onROpen(R->first.getLow(), R->second);
+ Machine.onRClose(R->first.getHigh());
+ ++R;
+ while(R != RHS.Items.end() && R->first.getHigh() < LRange.getHigh()) {
+ Machine.onROpen(R->first.getLow(), R->second);
+ Machine.onRClose(R->first.getHigh());
+ ++R;
+ }
+ continue;
+ } else
+ if (LRange.getLow() < RRange.getLow()) {
+ // May be opened in previous iteration.
+ if (!Machine.isLOpened())
+ Machine.onLOpen(LRange.getLow(), LCluster.second);
+ Machine.onROpen(RRange.getLow(), RCluster.second);
+ }
+ else if (RRange.getLow() < LRange.getLow()) {
+ if (!Machine.isROpened())
+ Machine.onROpen(RRange.getLow(), RCluster.second);
+ Machine.onLOpen(LRange.getLow(), LCluster.second);
+ }
+ else
+ Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second);
+
+ if (LRange.getHigh() < RRange.getHigh()) {
+ Machine.onLClose(LRange.getHigh());
+ ++L;
+ while(L != Items.end() && L->first.getHigh() < RRange.getHigh()) {
+ Machine.onLOpen(L->first.getLow(), L->second);
+ Machine.onLClose(L->first.getHigh());
+ ++L;
+ }
+ }
+ else if (RRange.getHigh() < LRange.getHigh()) {
+ Machine.onRClose(RRange.getHigh());
+ ++R;
+ while(R != RHS.Items.end() && R->first.getHigh() < LRange.getHigh()) {
+ Machine.onROpen(R->first.getLow(), R->second);
+ Machine.onRClose(R->first.getHigh());
+ ++R;
+ }
+ }
+ else {
+ Machine.onLRClose(LRange.getHigh());
+ ++L;
+ ++R;
+ }
+ }
+
+ if (L != Items.end()) {
+ if (Machine.isLOpened()) {
+ Machine.onLClose(L->first.getHigh());
+ ++L;
+ }
+ if (LExclude)
+ while (L != Items.end()) {
+ LExclude->add(L->first, L->second);
+ ++L;
+ }
+ } else if (R != RHS.Items.end()) {
+ if (Machine.isROpened()) {
+ Machine.onRClose(R->first.getHigh());
+ ++R;
+ }
+ if (RExclude)
+ while (R != RHS.Items.end()) {
+ RExclude->add(R->first, R->second);
+ ++R;
+ }
+ }
+ }
+