001 // Copyright (c) 2001 Hursh Jain (http://www.mollypages.org)
002 // The Molly framework is freely distributable under the terms of an
003 // MIT-style license. For details, see the molly pages web site at:
004 // http://www.mollypages.org/. Use, modify, have fun !
005
006 package fc.util;
007
008 import java.util.*;
009
010
011 /** A set of char ranges. **/
012 public class CharRangeSet
013 {
014 CharRange seedRange;
015 List union;
016 List intersect;
017
018 /**
019 Constructs a new CharRangeSet with the initial set containing
020 only the specified charrange
021
022 @param cs the initial charrange
023 **/
024 public CharRangeSet(CharRange cs)
025 {
026 Argcheck.notnull(cs);
027 seedRange = cs;
028 //do _not_ lazy instantiate, otherwise have to put in
029 //null checks in other places
030 union = new ArrayList();
031 intersect = new ArrayList();
032 }
033
034 /**
035 Adds this specified range as a union to the existing set of
036 ranges (for purposes of {@link inRange(char)} method).
037 Overlapping ranges are ok.
038
039 @param cs a charrange to unite with
040 @throws IllegalArgumentException
041 if the specified range was null
042 **/
043 public void union(CharRange r)
044 {
045 Argcheck.notnull(r);
046 union.add(r);
047 }
048
049 /**
050 Adds the specified range as an intersection to the existing
051 ranges (for purposes of {@link inRange(char)} method).
052 Overlapping ranges are ok.
053
054 @param r the range to add
055 **/
056 public void intersection(CharRange r)
057 {
058 Argcheck.notnull(r);
059 intersect.add(r);
060 }
061
062 /**
063 Consider a set of ranges <tt>A</tt>, <tt>B</tt> added as a union
064 (logical <tt>or</tt>) and ranges <tt>C</tt> and <tt>D</tt> added as an
065 intersection (logical <tt>and</tt>). A character <tt>c</tt> is in range if
066 it exists in:
067
068 <blockquote> <tt>
069
070 (A.inRange(c) || B.inRange(c) || ...) && C.inRange(c) && D.inRange(c)
071 && ...
072
073 </tt></blockquote>
074
075 This can be generalized to an arbitrary number of sub ranges. If
076 intersection or union ranges don't exist, then they are not
077 considered in the above expression. Note, the interaction may be
078 subtle if any of the ranges (<tt>A, B, C...</tt>etc) are
079 individually negated because in that case the inRange method for
080 that negated range would return true if the specified character
081 was <b>not</b> in that range.
082
083 @return <tt>true</tt> if the passed in character is allowed by this
084 set of ranges.
085
086 **/
087 public boolean inRange(char c)
088 {
089 boolean result = seedRange.inRange(c);
090 for (int i = 0, n = union.size(); i < n; i++) {
091 CharRange item = (CharRange) union.get(i);
092 result = result || item.inRange(c);
093 }
094 for (int i = 0, n = intersect.size(); i < n; i++) {
095 CharRange item = (CharRange) intersect.get(i);
096 result = result && item.inRange(c);
097 }
098 return result;
099 }
100
101 public String toString() {
102 StringBuffer buf = new StringBuffer(128);
103 buf.append("CharRangeSet:[");
104
105 if (intersect.size() > 0)
106 buf.append("(");
107
108 buf.append(seedRange);
109
110 int len = union.size();
111 if (len > 0)
112 {
113 buf.append(" || " );
114 for (int i = 0; i < len; i++) {
115 buf.append(union.get(i).toString());
116 if (i < (len-1))
117 buf.append(" || ");
118 }
119 }
120
121 len = intersect.size();
122 if (len > 0)
123 {
124 buf.append(") && " );
125 for (int i = 0; i < len; i++) {
126 buf.append(intersect.get(i).toString());
127 if (i < (len-1))
128 buf.append(" && ");
129 }
130 }
131
132 buf.append("]");
133 return buf.toString();
134 }
135
136
137 public static void main(String[] args)
138 {
139 CharRange r = new CharRange('b', 'd');
140 CharRange r2 = new CharRange('x', 'y');
141 CharRangeSet crs = new CharRangeSet(r);
142 crs.union(r2);
143 System.out.println("constructed: " + crs);
144
145 //normal
146 test(crs);
147
148 crs.intersection(new CharRange('a', 'x'));
149 System.out.println("added intersection, now: ");
150 System.out.println(crs);
151 test(crs);
152
153 crs.union(new CharRange('a', 'z'));
154 crs.intersection(new CharRange('s', 't'));
155 System.out.println("added union, intersection, now: ");
156 System.out.println(crs);
157
158 test(crs);
159 }
160
161 private static void test(CharRangeSet r)
162 {
163 System.out.println("'b' in range:" + r.inRange('b'));
164 System.out.println("'z' in range:" + r.inRange('z'));
165 System.out.println("'s' in range:" + r.inRange('s'));
166 System.out.println("'m' in range:" + r.inRange('m'));
167 }
168 }