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 }