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