• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *******************************************************************************
3  * Copyright (C) 2002-2012, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7 package org.unicode.cldr.util;
8 
9 import java.util.ArrayList;
10 import java.util.Arrays;
11 import java.util.HashSet;
12 import java.util.Random;
13 import java.util.Set;
14 
15 import com.ibm.icu.text.UTF16;
16 import com.ibm.icu.text.UnicodeSet;
17 
18 abstract public class Pick {
19     private static boolean DEBUG = false;
20 
21     // for using to get strings
22 
23     static class Target {
24         private Pick pick;
25         private Random random;
26         private Quoter quoter;
27 
make(Pick pick, Random random, Quoter quoter)28         public static Target make(Pick pick, Random random, Quoter quoter) {
29             Target result = new Target();
30             result.pick = pick;
31             result.random = random;
32             result.quoter = quoter;
33             return result;
34         }
35 
next()36         public String next() {
37             quoter.clear();
38             pick.addTo(this);
39             return get();
40         }
41 
get()42         public String get() {
43             return quoter.toString();
44         }
45 
copyState(Target other)46         private void copyState(Target other) {
47             random = other.random;
48         }
49 
clear()50         private void clear() {
51             quoter.clear();
52         }
53 
54         /*private int length() {
55             return quoter.length();
56         }*/
append(int codepoint)57         private Target append(int codepoint) {
58             quoter.append(codepoint);
59             return this;
60         }
61 
append(String s)62         private Target append(String s) {
63             quoter.append(s);
64             return this;
65         }
66 
67         // must return value between 0 (inc) and 1 (exc)
nextDouble()68         private double nextDouble() {
69             return random.nextDouble();
70         }
71     }
72 
73     // for Building
74 
replace(String toReplace, Pick replacement)75     public Pick replace(String toReplace, Pick replacement) {
76         Replacer visitor = new Replacer(toReplace, replacement);
77         return visit(visitor);
78     }
79 
name(String nameStr)80     public Pick name(String nameStr) {
81         name = nameStr;
82         return this;
83     }
84 
makeSequence()85     static public Pick.Sequence makeSequence() {
86         return new Sequence();
87     }
88 
makeAlternation()89     static public Pick.Alternation makeAlternation() {
90         return new Alternation();
91     }
92     /*
93     static public Pick.Sequence and(Object item) {
94         return new Sequence().and2(item);
95     }
96     static public Pick.Sequence and(Object[] items) {
97         return new Sequence().and2(items);
98     }
99     static public Pick.Alternation or(int itemWeight, Object item) {
100         return new Alternation().or2(itemWeight, item);
101     }
102     static public Pick.Alternation or(Object[] items) {
103         return new Alternation().or2(1, items);
104     }
105     static public Pick.Alternation or(int itemWeight, Object[] items) {
106         return new Alternation().or2(itemWeight, items);
107     }
108     static public Pick.Alternation or(int[] itemWeights, Object[] items) {
109         return new Alternation().or2(itemWeights, items);
110     }
111 
112     static public Pick maybe(int percent, Object item) {
113         return new Repeat(0, 1, new int[]{100-percent, percent}, item);
114         //return Pick.or(1.0-percent, NOTHING).or2(percent, item);
115     }
116     static public Pick repeat(int minCount, int maxCount, int itemWeights, Object item) {
117         return new Repeat(minCount, maxCount, itemWeights, item);
118     }
119 
120     static public Pick codePoint(String source) {
121         return new CodePoint(new UnicodeSet(source));
122     }
123     */
124 
repeat(int minCount, int maxCount, int[] itemWeights, Pick item)125     static public Pick repeat(int minCount, int maxCount, int[] itemWeights, Pick item) {
126         return new Repeat(minCount, maxCount, itemWeights, item);
127     }
128 
codePoint(UnicodeSet source)129     static public Pick codePoint(UnicodeSet source) {
130         return new CodePoint(source);
131     }
132 
string(String source)133     static public Pick string(String source) {
134         return new Literal(source);
135     }
136     /*
137     static public Pick unquoted(String source) {
138         return new Literal(source);
139     }
140     static public Pick string(int minLength, int maxLength, Pick item) {
141         return new Morph(item, minLength, maxLength);
142     }
143     */
144 
getInternal(int depth, Set alreadySeen)145     public abstract String getInternal(int depth, Set alreadySeen);
146     // Internals
147 
148     protected String name;
149 
addTo(Target target)150     protected abstract void addTo(Target target);
151 
match(String input, Position p)152     public abstract boolean match(String input, Position p);
153 
154     public static class Sequence extends ListPick {
and2(Pick item)155         public Sequence and2(Pick item) {
156             addInternal(new Pick[] { item }); // we don't care about perf
157             return this; // for chaining
158         }
159 
and2(Pick[] itemArray)160         public Sequence and2(Pick[] itemArray) {
161             addInternal(itemArray);
162             return this; // for chaining
163         }
164 
addTo(Target target)165         protected void addTo(Target target) {
166             for (int i = 0; i < items.length; ++i) {
167                 items[i].addTo(target);
168             }
169         }
170 
getInternal(int depth, Set alreadySeen)171         public String getInternal(int depth, Set alreadySeen) {
172             String result = checkName(name, alreadySeen);
173             if (result.startsWith("$")) return result;
174             result = indent(depth) + result + "SEQ(";
175             for (int i = 0; i < items.length; ++i) {
176                 if (i != 0) result += ", ";
177                 result += items[i].getInternal(depth + 1, alreadySeen);
178             }
179             result += ")";
180             return result;
181         }
182 
183         // keep private
Sequence()184         private Sequence() {
185         }
186 
match(String input, Position p)187         public boolean match(String input, Position p) {
188             int originalIndex = p.index;
189             for (int i = 0; i < items.length; ++i) {
190                 if (!items[i].match(input, p)) {
191                     p.index = originalIndex;
192                     return false;
193                 }
194             }
195             return true;
196         }
197     }
198 
checkName(String nameStr, Set alreadySeen)199     String checkName(String nameStr, Set alreadySeen) {
200         if (nameStr == null) return "";
201         if (alreadySeen.contains(nameStr)) return nameStr;
202         alreadySeen.add(nameStr);
203         return "{" + nameStr + "=}";
204     }
205 
206     public static class Alternation extends ListPick {
207         private WeightedIndex weightedIndex = new WeightedIndex(0);
208 
or2(Pick[] newItems)209         public Alternation or2(Pick[] newItems) {
210             return or2(1, newItems);
211         }
212 
or2(int itemWeight, Pick item)213         public Alternation or2(int itemWeight, Pick item) {
214             return or2(itemWeight, new Pick[] { item }); // we don't care about perf
215         }
216 
or2(int itemWeight, Pick[] newItems)217         public Alternation or2(int itemWeight, Pick[] newItems) {
218             int[] itemWeights = new int[newItems.length];
219             Arrays.fill(itemWeights, itemWeight);
220             return or2(itemWeights, newItems); // we don't care about perf
221         }
222 
or2(int[] itemWeights, Pick[] newItems)223         public Alternation or2(int[] itemWeights, Pick[] newItems) {
224             if (newItems.length != itemWeights.length) {
225                 throw new ArrayIndexOutOfBoundsException(
226                     "or lengths must be equal: " + newItems.length + " != " + itemWeights.length);
227             }
228             // int lastLen = this.items.length;
229             addInternal(newItems);
230             weightedIndex.add(itemWeights);
231             return this; // for chaining
232         }
233 
addTo(Target target)234         protected void addTo(Target target) {
235             items[weightedIndex.toIndex(target.nextDouble())].addTo(target);
236         }
237 
getInternal(int depth, Set alreadySeen)238         public String getInternal(int depth, Set alreadySeen) {
239             String result = checkName(name, alreadySeen);
240             if (result.startsWith("$")) return result;
241             result = indent(depth) + result + "OR(";
242             for (int i = 0; i < items.length; ++i) {
243                 if (i != 0) result += ", ";
244                 result += items[i].getInternal(depth + 1, alreadySeen) + "/" + weightedIndex.weights[i];
245             }
246             return result + ")";
247         }
248 
249         // keep private
Alternation()250         private Alternation() {
251         }
252 
253         // take first matching option
match(String input, Position p)254         public boolean match(String input, Position p) {
255             for (int i = 0; i < weightedIndex.weights.length; ++i) {
256                 if (p.isFailure(this, i)) continue;
257                 if (items[i].match(input, p)) return true;
258                 p.setFailure(this, i);
259             }
260             return false;
261         }
262     }
263 
indent(int depth)264     private static String indent(int depth) {
265         String result = "\r\n";
266         for (int i = 0; i < depth; ++i) {
267             result += " ";
268         }
269         return result;
270     }
271 
272     private static class Repeat extends ItemPick {
273         WeightedIndex weightedIndex;
274         int minCount = 0;
275 
Repeat(int minCount, int maxCount, int[] itemWeights, Pick item)276         private Repeat(int minCount, int maxCount, int[] itemWeights, Pick item) {
277             super(item);
278             weightedIndex = new WeightedIndex(minCount).add(maxCount - minCount + 1, itemWeights);
279         }
280 
281         /*private Repeat(int minCount, int maxCount, int itemWeight, Pick item) {
282             super(item);
283             weightedIndex = new WeightedIndex(minCount).add(maxCount-minCount+1, itemWeight);
284         }*/
285         /*
286         private Repeat(int minCount, int maxCount, Object item) {
287             this.item = convert(item);
288             weightedIndex = new WeightedIndex(minCount).add(maxCount-minCount+1, 1);
289         }
290         */
addTo(Target target)291         protected void addTo(Target target) {
292             //int count ;
293             for (int i = weightedIndex.toIndex(target.nextDouble()); i > 0; --i) {
294                 item.addTo(target);
295             }
296         }
297 
getInternal(int depth, Set alreadySeen)298         public String getInternal(int depth, Set alreadySeen) {
299             String result = checkName(name, alreadySeen);
300             if (result.startsWith("$")) return result;
301             result = indent(depth) + result + "REPEAT(" + weightedIndex
302                 + "; " + item.getInternal(depth + 1, alreadySeen)
303                 + ")";
304             return result;
305         }
306 
307         // match longest, e.g. up to just before a failure
match(String input, Position p)308         public boolean match(String input, Position p) {
309             //int bestMatch = p.index;
310             int count = 0;
311             for (int i = 0; i < weightedIndex.weights.length; ++i) {
312                 if (p.isFailure(this, i)) break;
313                 if (!item.match(input, p)) {
314                     p.setFailure(this, i);
315                     break;
316                 }
317                 //bestMatch = p.index;
318                 count++;
319             }
320             if (count >= minCount) {
321                 return true;
322             }
323             // TODO fix failure
324             return false;
325         }
326     }
327 
328     private static class CodePoint extends FinalPick {
329         private UnicodeSet source;
330 
CodePoint(UnicodeSet source)331         private CodePoint(UnicodeSet source) {
332             this.source = source;
333         }
334 
addTo(Target target)335         protected void addTo(Target target) {
336             target.append(source.charAt(pick(target.random, 0, source.size() - 1)));
337         }
338 
match(String s, Position p)339         public boolean match(String s, Position p) {
340             int cp = UTF16.charAt(s, p.index);
341             if (source.contains(cp)) {
342                 p.index += UTF16.getCharCount(cp);
343                 return true;
344             }
345             p.setMax("codePoint");
346             return false;
347         }
348 
getInternal(int depth, Set alreadySeen)349         public String getInternal(int depth, Set alreadySeen) {
350             String result = checkName(name, alreadySeen);
351             if (result.startsWith("$")) return result;
352             return source.toString();
353         }
354     }
355 
356     static class Morph extends ItemPick {
Morph(Pick item)357         Morph(Pick item) {
358             super(item);
359         }
360 
361         private String lastValue = null;
362         private Target addBuffer = Target.make(this, null, new Quoter.RuleQuoter());
363         private StringBuffer mergeBuffer = new StringBuffer();
364 
365         private static final int COPY_NEW = 0, COPY_BOTH = 1, COPY_LAST = 3, SKIP = 4,
366             LEAST_SKIP = 4;
367         // give weights to the above. make sure we delete about the same as we insert
368         private static final WeightedIndex choice = new WeightedIndex(0)
369             .add(new int[] { 10, 10, 100, 10 });
370 
addTo(Target target)371         protected void addTo(Target target) {
372             // get contents into separate buffer
373             addBuffer.copyState(target);
374             addBuffer.clear();
375             item.addTo(addBuffer);
376             String newValue = addBuffer.get();
377             if (DEBUG) System.out.println("Old: " + lastValue + ", New:" + newValue);
378 
379             // if not first one, merge with old
380             if (lastValue != null) {
381                 mergeBuffer.setLength(0);
382                 int lastIndex = 0;
383                 int newIndex = 0;
384                 // the new length is a random value between old and new.
385                 int newLenLimit = (int) pick(target.random, lastValue.length(), newValue.length());
386 
387                 while (mergeBuffer.length() < newLenLimit
388                     && newIndex < newValue.length()
389                     && lastIndex < lastValue.length()) {
390                     int c = choice.toIndex(target.nextDouble());
391                     if (c == COPY_NEW || c == COPY_BOTH || c == SKIP) {
392                         newIndex = getChar(newValue, newIndex, mergeBuffer, c < LEAST_SKIP);
393                         if (mergeBuffer.length() >= newLenLimit) break;
394                     }
395                     if (c == COPY_LAST || c == COPY_BOTH || c == SKIP) {
396                         lastIndex = getChar(lastValue, lastIndex, mergeBuffer, c < LEAST_SKIP);
397                     }
398                 }
399                 newValue = mergeBuffer.toString();
400             }
401             lastValue = newValue;
402             target.append(newValue);
403             if (DEBUG) System.out.println("Result: " + newValue);
404         }
405 
getInternal(int depth, Set alreadySeen)406         public String getInternal(int depth, Set alreadySeen) {
407             String result = checkName(name, alreadySeen);
408             if (result.startsWith("$")) return result;
409             return indent(depth) + result + "MORPH("
410                 + item.getInternal(depth + 1, alreadySeen)
411                 + ")";
412         }
413 
414         /* (non-Javadoc)
415          * @see Pick#match(java.lang.String, Pick.Position)
416          */
match(String input, Position p)417         public boolean match(String input, Position p) {
418             // TODO Auto-generated method stub
419             return false;
420         }
421     }
422 
423     /* Add character if we can
424      */
getChar(String newValue, int newIndex, StringBuffer mergeBuffer, boolean copy)425     static int getChar(String newValue, int newIndex, StringBuffer mergeBuffer, boolean copy) {
426         if (newIndex >= newValue.length()) return newIndex;
427         int cp = UTF16.charAt(newValue, newIndex);
428         if (copy) UTF16.append(mergeBuffer, cp);
429         return newIndex + UTF16.getCharCount(cp);
430     }
431 
432     /*
433             // quoted add
434             appendQuoted(target, addBuffer.toString(), quoteBuffer);
435             // fix buffers
436             StringBuffer swapTemp = addBuffer;
437             addBuffer = source;
438             source = swapTemp;
439         }
440     }
441     */
442 
443     static class Quote extends ItemPick {
Quote(Pick item)444         Quote(Pick item) {
445             super(item);
446         }
447 
addTo(Target target)448         protected void addTo(Target target) {
449             target.quoter.setQuoting(true);
450             item.addTo(target);
451             target.quoter.setQuoting(false);
452         }
453 
match(String s, Position p)454         public boolean match(String s, Position p) {
455             return false;
456         }
457 
getInternal(int depth, Set alreadySeen)458         public String getInternal(int depth, Set alreadySeen) {
459             String result = checkName(name, alreadySeen);
460             if (result.startsWith("$")) return result;
461             return indent(depth) + result + "QUOTE(" + item.getInternal(depth + 1, alreadySeen)
462                 + ")";
463         }
464     }
465 
466     private static class Literal extends FinalPick {
toString()467         public String toString() {
468             return name;
469         }
470 
Literal(String source)471         private Literal(String source) {
472             this.name = source;
473         }
474 
addTo(Target target)475         protected void addTo(Target target) {
476             target.append(name);
477         }
478 
match(String input, Position p)479         public boolean match(String input, Position p) {
480             int len = name.length();
481             if (input.regionMatches(p.index, name, 0, len)) {
482                 p.index += len;
483                 return true;
484             }
485             p.setMax("literal");
486             return false;
487         }
488 
getInternal(int depth, Set alreadySeen)489         public String getInternal(int depth, Set alreadySeen) {
490             return "'" + name + "'";
491         }
492     }
493 
494     public static class Position {
495         public ArrayList failures = new ArrayList();
496         public int index;
497         public int maxInt;
498         public String maxType;
499 
setMax(String type)500         public void setMax(String type) {
501             if (index >= maxInt) {
502                 maxType = type;
503             }
504         }
505 
toString()506         public String toString() {
507             return "index; " + index
508                 + ", maxInt:" + maxInt
509                 + ", maxType: " + maxType;
510         }
511         /*private static final Object BAD = new Object();
512         private static final Object GOOD = new Object();*/
513 
isFailure(Pick pick, int item)514         public boolean isFailure(Pick pick, int item) {
515             ArrayList val = (ArrayList) failures.get(index);
516             if (val == null) return false;
517             Set set = (Set) val.get(item);
518             if (set == null) return false;
519             return !set.contains(pick);
520         }
521 
setFailure(Pick pick, int item)522         public void setFailure(Pick pick, int item) {
523             ArrayList val = (ArrayList) failures.get(index);
524             if (val == null) {
525                 val = new ArrayList();
526                 failures.set(index, val);
527             }
528             Set set = (Set) val.get(item);
529             if (set == null) {
530                 set = new HashSet();
531                 val.set(item, set);
532             }
533             set.add(pick);
534         }
535     }
536 
537     /*
538     public static final Pick NOTHING = new Nothing();
539 
540 
541     private static class Nothing extends FinalPick {
542         protected void addTo(Target target) {}
543         protected boolean match(String input, Position p) {
544             return true;
545         }
546         public String getInternal(int depth, Set alreadySeen) {
547             return indent(depth) + "\u00F8";
548         }
549     }
550     */
551 
552     // intermediates
553 
554     abstract static class Visitor {
555         Set already = new HashSet();
556 
557         // Note: each visitor should return the Pick that will replace a (or a itself)
handle(Pick a)558         abstract Pick handle(Pick a);
559 
alreadyEntered(Pick item)560         boolean alreadyEntered(Pick item) {
561             boolean result = already.contains(item);
562             already.add(item);
563             return result;
564         }
565 
reset()566         void reset() {
567             already.clear();
568         }
569     }
570 
visit(Visitor visitor)571     protected abstract Pick visit(Visitor visitor);
572 
573     static class Replacer extends Visitor {
574         String toReplace;
575         Pick replacement;
576 
Replacer(String toReplace, Pick replacement)577         Replacer(String toReplace, Pick replacement) {
578             this.toReplace = toReplace;
579             this.replacement = replacement;
580         }
581 
handle(Pick a)582         public Pick handle(Pick a) {
583             if (toReplace.equals(a.name)) {
584                 a = replacement;
585             }
586             return a;
587         }
588     }
589 
590     abstract private static class FinalPick extends Pick {
visit(Visitor visitor)591         public Pick visit(Visitor visitor) {
592             return visitor.handle(this);
593         }
594     }
595 
596     private abstract static class ItemPick extends Pick {
597         protected Pick item;
598 
ItemPick(Pick item)599         ItemPick(Pick item) {
600             this.item = item;
601         }
602 
visit(Visitor visitor)603         public Pick visit(Visitor visitor) {
604             Pick result = visitor.handle(this);
605             if (visitor.alreadyEntered(this)) return result;
606             if (item != null) item = item.visit(visitor);
607             return result;
608         }
609     }
610 
611     private abstract static class ListPick extends Pick {
612         protected Pick[] items = new Pick[0];
613 
simplify()614         Pick simplify() {
615             if (items.length > 1) return this;
616             if (items.length == 1) return items[0];
617             return null;
618         }
619 
size()620         int size() {
621             return items.length;
622         }
623 
getLast()624         Pick getLast() {
625             return items[items.length - 1];
626         }
627 
setLast(Pick newOne)628         void setLast(Pick newOne) {
629             items[items.length - 1] = newOne;
630         }
631 
addInternal(Pick[] objs)632         protected void addInternal(Pick[] objs) {
633             int lastLen = items.length;
634             items = realloc(items, items.length + objs.length);
635             for (int i = 0; i < objs.length; ++i) {
636                 items[lastLen + i] = objs[i];
637             }
638         }
639 
visit(Visitor visitor)640         public Pick visit(Visitor visitor) {
641             Pick result = visitor.handle(this);
642             if (visitor.alreadyEntered(this)) return result;
643             for (int i = 0; i < items.length; ++i) {
644                 items[i] = items[i].visit(visitor);
645             }
646             return result;
647         }
648     }
649 
650     /**
651      * Simple class to distribute a number between 0 (inclusive) and 1 (exclusive) among
652      * a number of indices, where each index is weighted.
653      * Item weights may be zero, but cannot be negative.
654      * @author Davis
655      */
656     // As in other case, we use an array for runtime speed; don't care about buildspeed.
657     public static class WeightedIndex {
658         private int[] weights = new int[0];
659         private int minCount = 0;
660         private double total;
661 
WeightedIndex(int minCount)662         public WeightedIndex(int minCount) {
663             this.minCount = minCount;
664         }
665 
add(int count, int itemWeights)666         public WeightedIndex add(int count, int itemWeights) {
667             if (count > 0) {
668                 int[] newWeights = new int[count];
669                 if (itemWeights < 1) itemWeights = 1;
670                 Arrays.fill(newWeights, 0, count, itemWeights);
671                 add(1, newWeights);
672             }
673             return this; // for chaining
674         }
675 
add(int[] newWeights)676         public WeightedIndex add(int[] newWeights) {
677             return add(newWeights.length, newWeights);
678         }
679 
add(int maxCount, int[] newWeights)680         public WeightedIndex add(int maxCount, int[] newWeights) {
681             if (newWeights == null) newWeights = new int[] { 1 };
682             int oldLen = weights.length;
683             if (maxCount < newWeights.length) maxCount = newWeights.length;
684             weights = (int[]) realloc(weights, weights.length + maxCount);
685             System.arraycopy(newWeights, 0, weights, oldLen, newWeights.length);
686             int lastWeight = weights[oldLen + newWeights.length - 1];
687             for (int i = oldLen + newWeights.length; i < maxCount; ++i) {
688                 weights[i] = lastWeight;
689             }
690             total = 0;
691             for (int i = 0; i < weights.length; ++i) {
692                 if (weights[i] < 0) {
693                     throw new RuntimeException("only positive weights: " + i);
694                 }
695                 total += weights[i];
696             }
697             return this; // for chaining
698         }
699 
700         // TODO, make this more efficient
toIndex(double zeroToOne)701         public int toIndex(double zeroToOne) {
702             double weight = zeroToOne * total;
703             int i;
704             for (i = 0; i < weights.length; ++i) {
705                 weight -= weights[i];
706                 if (weight <= 0) break;
707             }
708             return i + minCount;
709         }
710 
toString()711         public String toString() {
712             String result = "";
713             for (int i = 0; i < minCount; ++i) {
714                 if (result.length() != 0) result += ",";
715                 result += "0";
716             }
717             for (int i = 0; i < weights.length; ++i) {
718                 if (result.length() != 0) result += ",";
719                 result += weights[i];
720             }
721             return result;
722         }
723     }
724     /*
725     private static Pick convert(Object obj) {
726         if (obj instanceof Pick) return (Pick)obj;
727         return new Literal(obj.toString(), false);
728     }
729     */
730     // Useful statics
731 
pick(Random random, int start, int end)732     static public int pick(Random random, int start, int end) {
733         return start + (int) (random.nextDouble() * (end + 1 - start));
734     }
735 
pick(Random random, double start, double end)736     static public double pick(Random random, double start, double end) {
737         return start + (random.nextDouble() * (end + 1 - start));
738     }
739 
pick(Random random, double percent)740     static public boolean pick(Random random, double percent) {
741         return random.nextDouble() <= percent;
742     }
743 
pick(Random random, UnicodeSet s)744     static public int pick(Random random, UnicodeSet s) {
745         return s.charAt(pick(random, 0, s.size() - 1));
746     }
747 
pick(Random random, String[] source)748     static public String pick(Random random, String[] source) {
749         return source[pick(random, 0, source.length - 1)];
750     }
751 
752     // these utilities really ought to be in Java
753 
realloc(double[] source, int newSize)754     public static double[] realloc(double[] source, int newSize) {
755         double[] temp = new double[newSize];
756         if (newSize > source.length) newSize = source.length;
757         if (newSize != 0) System.arraycopy(source, 0, temp, 0, newSize);
758         return temp;
759     }
760 
realloc(int[] source, int newSize)761     public static int[] realloc(int[] source, int newSize) {
762         int[] temp = new int[newSize];
763         if (newSize > source.length) newSize = source.length;
764         if (newSize != 0) System.arraycopy(source, 0, temp, 0, newSize);
765         return temp;
766     }
767 
realloc(Pick[] source, int newSize)768     public static Pick[] realloc(Pick[] source, int newSize) {
769         Pick[] temp = new Pick[newSize];
770         if (newSize > source.length) newSize = source.length;
771         if (newSize != 0) System.arraycopy(source, 0, temp, 0, newSize);
772         return temp;
773     }
774 
775     // test utilities
776     /*private static void append(StringBuffer target, String toAdd, StringBuffer quoteBuffer) {
777         Utility.appendToRule(target, (int)-1, true, false, quoteBuffer); // close previous quote
778         if (DEBUG) System.out.println("\"" + toAdd + "\"");
779         target.append(toAdd);
780     }
781 
782     private static void appendQuoted(StringBuffer target, String toAdd, StringBuffer quoteBuffer) {
783         if (DEBUG) System.out.println("\"" + toAdd + "\"");
784         Utility.appendToRule(target, toAdd, false, false, quoteBuffer);
785     }*/
786 
787     /*
788     public static abstract class MatchHandler {
789         public abstract void handleString(String source, int start, int limit);
790         public abstract void handleSequence(String source, int start, int limit);
791         public abstract void handleAlternation(String source, int start, int limit);
792 
793     }
794     */
795     /*
796     // redistributes random value
797     // values are still between 0 and 1, but with a different distribution
798     public interface Spread {
799         public double spread(double value);
800     }
801 
802     // give the weight for the high end.
803     // values are linearly scaled according to the weight.
804     static public class SimpleSpread implements Spread {
805         static final Spread FLAT = new SimpleSpread(1.0);
806         boolean flat = false;
807         double aa, bb, cc;
808         public SimpleSpread(double maxWeight) {
809             if (maxWeight > 0.999 && maxWeight < 1.001) {
810                 flat = true;
811             } else {
812                 double q = (maxWeight - 1.0);
813                 aa = -1/q;
814                 bb = 1/(q*q);
815                 cc = (2.0+q)/q;
816            }
817         }
818         public double spread(double value) {
819             if (flat) return value;
820             value = aa + Math.sqrt(bb + cc*value);
821             if (value < 0.0) return 0.0;    // catch math gorp
822             if (value >= 1.0) return 1.0;
823             return value;
824         }
825     }
826     static public int pick(Spread spread, Random random, int start, int end) {
827         return start + (int)(spread.spread(random.nextDouble()) * (end + 1 - start));
828     }
829 
830     */
831 
832 }