1 
2 /* Web Polygraph       http://www.web-polygraph.org/
3  * Copyright 2003-2011 The Measurement Factory
4  * Licensed under the Apache License, Version 2.0 */
5 
6 #include "base/polygraph.h"
7 
8 #include <ctype.h>
9 #include <iomanip>
10 #include "xstd/h/iostream.h"
11 
12 #include "xstd/gadgets.h"
13 #include "base/StringRangeBlocks.h"
14 
15 
16 /* StringRangeBlock */
17 
diffCount(const StringRangeBlock & b) const18 int StringRangeBlock::diffCount(const StringRangeBlock &b) const {
19 	if (theType == sbtPoint) {
20 		if (b.type() == sbtPoint)
21 			return ((const StringRangePoint*)this)->
22 				countDiffs((const StringRangePoint&)b);
23 		else
24 			return 2; // "big" difference
25 	}
26 
27 	if (theType == sbtInterval) {
28 		if (b.type() == sbtInterval)
29 			return ((const StringRangeInterval*)this)->
30 				countDiffs((const StringRangeInterval&)b);
31 		else
32 			return 2; // "big" difference
33 	}
34 
35 	Assert(false);
36 	return 2;
37 }
38 
merge(StringRangeBlock & b)39 void StringRangeBlock::merge(StringRangeBlock &b) {
40 	if (type() == sbtPoint && b.type() == sbtPoint) {
41 		((StringRangePoint*)this)->
42 			mergeWith((const StringRangePoint&)b);
43 	} else
44 	if (type() == sbtInterval && b.type() == sbtInterval) {
45 		((StringRangeInterval*)this)->
46 			mergeWith((const StringRangeInterval&)b);
47 	} else {
48 		Assert(false);
49 	}
50 }
51 
52 
53 /* StringRangePoint */
54 
StringRangePoint(const String & aPoint)55 StringRangePoint::StringRangePoint(const String &aPoint):
56 	StringRangeBlock(sbtPoint), thePoint(aPoint) {
57 }
58 
clone() const59 StringRangeBlock *StringRangePoint::clone() const {
60 	return new StringRangePoint(thePoint);
61 }
62 
count() const63 int StringRangePoint::count() const {
64 	return 1;
65 }
66 
findTail(const Area & a,int & tailPos,int & idx) const67 bool StringRangePoint::findTail(const Area &a, int &tailPos, int &idx) const {
68 	int myPos = thePoint.len() -1;
69 	int aPos = a.size() - 1;
70 	bool found = false;
71 	while (myPos >= 0 && aPos >= 0 && thePoint[myPos] == a.data()[aPos]) {
72 		found = true;
73 		tailPos = aPos;
74 		--myPos;
75 		--aPos;
76 	}
77 
78 	if (found)
79 		idx = 0;
80 
81 	return found;
82 }
83 
countDiffs(const StringRangePoint & b) const84 int StringRangePoint::countDiffs(const StringRangePoint &b) const {
85 	return thePoint == b.thePoint ? 0 : 2;
86 }
87 
mergeWith(const StringRangePoint & b)88 void StringRangePoint::mergeWith(const StringRangePoint &b) {
89 	Assert(countDiffs(b) == 0);
90 }
91 
atLast() const92 bool StringRangePoint::atLast() const {
93 	return true;
94 }
95 
pos() const96 int StringRangePoint::pos() const {
97 	return 0;
98 }
99 
start()100 void StringRangePoint::start() {
101 }
102 
next()103 void StringRangePoint::next() {
104 	Assert(false);
105 }
106 
pos(int aPos)107 void StringRangePoint::pos(int aPos) {
108 	Assert(aPos == 0);
109 }
110 
print(ostream & os) const111 void StringRangePoint::print(ostream &os) const {
112 	os << thePoint;
113 }
114 
printCur(ostream & os) const115 void StringRangePoint::printCur(ostream &os) const {
116 	print(os);
117 }
118 
119 
120 /* StringRangeInterval */
121 
StringRangeInterval(int aStart,int aStop,bool beIsolated,int aBase)122 StringRangeInterval::StringRangeInterval(int aStart, int aStop, bool beIsolated, int aBase):
123 	StringRangeBlock(sbtInterval), theStart(aStart), theStop(aStop),
124 	theBase(aBase), thePos(aStart), isIsolated(beIsolated) {
125 	Should(theBase == 10 || theBase == 16);
126 }
127 
clone() const128 StringRangeBlock *StringRangeInterval::clone() const {
129 	return new StringRangeInterval(theStart, theStop, isIsolated, theBase);
130 }
131 
count() const132 int StringRangeInterval::count() const {
133 	return theStop - theStart;
134 }
135 
findTail(const Area & a,int & tailPos,int & idx) const136 bool StringRangeInterval::findTail(const Area &a, int &tailPos, int &idx) const {
137 	// does the area end with a number?
138 	int aPos = a.size() - 1;
139 	int foundPos = -1;
140 	while (aPos >= 0 && isdigit(a.data()[aPos])) {
141 		foundPos = aPos;
142 		--aPos;
143 	}
144 
145 	if (foundPos >= 0) {
146 		// does the number belong to our range?
147 		int num = -1;
148 		if (isInt(a.data() + foundPos, num) && theStart <= num && num < theStop) {
149 			tailPos = foundPos;
150 			idx = num - theStart;
151 			return true;
152 		}
153 	}
154 
155 	return false;
156 }
157 
countDiffs(const StringRangeInterval & b) const158 int StringRangeInterval::countDiffs(const StringRangeInterval &b) const {
159 	// different bases cannot merge
160 	if (theBase != b.theBase)
161 		return 2;
162 
163 	// exact match
164 	if (theStart == b.theStart && theStop == b.theStop)
165 		return 0;
166 
167 	// can only merge without changing the number of members
168 	// if one range follows the other
169 	if (theStop == b.theStart || b.theStop == theStart)
170 		return 1;
171 
172 	// "big" difference
173 	return 2;
174 }
175 
mergeWith(const StringRangeInterval & b)176 void StringRangeInterval::mergeWith(const StringRangeInterval &b) {
177 	Should(theBase == b.theBase);
178 	theStart = Min(theStart, b.theStart);
179 	theStop = Max(theStop, b.theStop);
180 	// isIsolated does not change?
181 }
182 
atLast() const183 bool StringRangeInterval::atLast() const {
184 	return thePos == theStop-1;
185 }
186 
pos() const187 int StringRangeInterval::pos() const {
188 	return thePos - theStart;
189 }
190 
start()191 void StringRangeInterval::start() {
192 	thePos = theStart;
193 }
194 
next()195 void StringRangeInterval::next() {
196 	thePos++;
197 }
198 
pos(int aPos)199 void StringRangeInterval::pos(int aPos) {
200 	thePos = theStart + aPos; // local coordinates
201 	Assert(theStart <= thePos && thePos < theStop);
202 }
203 
print(ostream & os) const204 void StringRangeInterval::print(ostream &os) const {
205 	const ios_fmtflags savedFlags = os.flags();
206 	os << setbase(theBase);
207 
208 	if (!isIsolated)
209 		os << '[';
210 	os << theStart;
211 	if (theStart != theStop-1)
212 		os << '-' << (theStop-1);
213 	if (!isIsolated)
214 		os << ']';
215 
216 	os.flags(savedFlags);
217 }
218 
printCur(ostream & os) const219 void StringRangeInterval::printCur(ostream &os) const {
220 	const ios_fmtflags savedFlags = os.flags();
221 	os << setbase(theBase) << thePos;
222 	os.flags(savedFlags);
223 }
224