/* */ package com.ibm.icu.util;
/* */
/* */ import java.util.ArrayList;
/* */ import java.util.HashMap;
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public abstract class StringTrieBuilder
/* */ {
/* */ public static enum Option
/* */ {
/* 36 */ FAST,
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 48 */ SMALL;
/* */
/* */
/* */
/* */ private Option() {}
/* */ }
/* */
/* */
/* */
/* */ /**
/* */ * @deprecated
/* */ */
/* */ protected void addImpl(CharSequence s, int value)
/* */ {
/* 62 */ if (this.state != State.ADDING)
/* */ {
/* 64 */ throw new IllegalStateException("Cannot add (string, value) pairs after build().");
/* */ }
/* 66 */ if (s.length() > 65535)
/* */ {
/* 68 */ throw new IndexOutOfBoundsException("The maximum string length is 0xffff.");
/* */ }
/* 70 */ if (this.root == null) {
/* 71 */ this.root = createSuffixNode(s, 0, value);
/* */ } else {
/* 73 */ this.root = this.root.add(this, s, 0, value);
/* */ }
/* */ }
/* */
/* */ /**
/* */ * @deprecated
/* */ */
/* */ protected final void buildImpl(Option buildOption)
/* */ {
/* 82 */ switch (this.state) {
/* */ case ADDING:
/* 84 */ if (this.root == null) {
/* 85 */ throw new IndexOutOfBoundsException("No (string, value) pairs were added.");
/* */ }
/* 87 */ if (buildOption == Option.FAST) {
/* 88 */ this.state = State.BUILDING_FAST;
/* */
/* */
/* */
/* */
/* */ }
/* */ else
/* */ {
/* */
/* */
/* */
/* 99 */ this.state = State.BUILDING_SMALL;
/* */ }
/* 101 */ break;
/* */
/* */ case BUILDING_FAST:
/* */ case BUILDING_SMALL:
/* 105 */ throw new IllegalStateException("Builder failed and must be clear()ed.");
/* */ case BUILT:
/* 107 */ return;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* 115 */ this.root = this.root.register(this);
/* 116 */ this.root.markRightEdgesFirst(-1);
/* 117 */ this.root.write(this);
/* 118 */ this.state = State.BUILT;
/* */ }
/* */
/* */ /**
/* */ * @deprecated
/* */ */
/* */ protected void clearImpl()
/* */ {
/* 126 */ this.strings.setLength(0);
/* 127 */ this.nodes.clear();
/* 128 */ this.root = null;
/* 129 */ this.state = State.ADDING;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private final Node registerNode(Node newNode)
/* */ {
/* 140 */ if (this.state == State.BUILDING_FAST) {
/* 141 */ return newNode;
/* */ }
/* */
/* 144 */ Node oldNode = (Node)this.nodes.get(newNode);
/* 145 */ if (oldNode != null) {
/* 146 */ return oldNode;
/* */ }
/* */
/* */
/* 150 */ oldNode = (Node)this.nodes.put(newNode, newNode);
/* 151 */ assert (oldNode == null);
/* 152 */ return newNode;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private final ValueNode registerFinalValue(int value)
/* */ {
/* 165 */ this.lookupFinalValueNode.setFinalValue(value);
/* 166 */ Node oldNode = (Node)this.nodes.get(this.lookupFinalValueNode);
/* 167 */ if (oldNode != null) {
/* 168 */ return (ValueNode)oldNode;
/* */ }
/* 170 */ ValueNode newNode = new ValueNode(value);
/* */
/* */
/* 173 */ oldNode = (Node)this.nodes.put(newNode, newNode);
/* 174 */ assert (oldNode == null);
/* 175 */ return newNode;
/* */ }
/* */
/* */ private static abstract class Node { protected int offset;
/* */
/* 180 */ public Node() { this.offset = 0; }
/* */
/* */
/* */ public abstract int hashCode();
/* */
/* */
/* */ public boolean equals(Object other)
/* */ {
/* 188 */ return (this == other) || (getClass() == other.getClass());
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */ public Node add(StringTrieBuilder builder, CharSequence s, int start, int sValue)
/* */ {
/* 197 */ return this;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public Node register(StringTrieBuilder builder)
/* */ {
/* 207 */ return this;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public int markRightEdgesFirst(int edgeNumber)
/* */ {
/* 236 */ if (this.offset == 0) {
/* 237 */ this.offset = edgeNumber;
/* */ }
/* 239 */ return edgeNumber;
/* */ }
/* */
/* */
/* */
/* */
/* */ public abstract void write(StringTrieBuilder paramStringTrieBuilder);
/* */
/* */
/* */
/* */ public final void writeUnlessInsideRightEdge(int firstRight, int lastRight, StringTrieBuilder builder)
/* */ {
/* 251 */ if ((this.offset < 0) && ((this.offset < lastRight) || (firstRight < this.offset)))
/* 252 */ write(builder);
/* */ }
/* */
/* 255 */ public final int getOffset() { return this.offset; }
/* */ }
/* */
/* */ private static class ValueNode extends StringTrieBuilder.Node {
/* */ protected boolean hasValue;
/* */ protected int value;
/* */
/* */ public ValueNode() {}
/* */
/* */ public ValueNode(int v) {
/* 265 */ this.hasValue = true;
/* 266 */ this.value = v;
/* */ }
/* */
/* 269 */ public final void setValue(int v) { assert (!this.hasValue);
/* 270 */ this.hasValue = true;
/* 271 */ this.value = v;
/* */ }
/* */
/* 274 */ private void setFinalValue(int v) { this.hasValue = true;
/* 275 */ this.value = v;
/* */ }
/* */
/* */ public int hashCode() {
/* 279 */ int hash = 1118481;
/* 280 */ if (this.hasValue) {
/* 281 */ hash = hash * 37 + this.value;
/* */ }
/* 283 */ return hash;
/* */ }
/* */
/* */ public boolean equals(Object other) {
/* 287 */ if (this == other) {
/* 288 */ return true;
/* */ }
/* 290 */ if (!super.equals(other)) {
/* 291 */ return false;
/* */ }
/* 293 */ ValueNode o = (ValueNode)other;
/* 294 */ return (this.hasValue == o.hasValue) && ((!this.hasValue) || (this.value == o.value));
/* */ }
/* */
/* */ public StringTrieBuilder.Node add(StringTrieBuilder builder, CharSequence s, int start, int sValue) {
/* 298 */ if (start == s.length()) {
/* 299 */ throw new IllegalArgumentException("Duplicate string.");
/* */ }
/* */
/* 302 */ ValueNode node = builder.createSuffixNode(s, start, sValue);
/* 303 */ node.setValue(this.value);
/* 304 */ return node;
/* */ }
/* */
/* */ public void write(StringTrieBuilder builder) {
/* 308 */ this.offset = builder.writeValueAndFinal(this.value, true);
/* */ }
/* */ }
/* */
/* */ private static final class IntermediateValueNode extends StringTrieBuilder.ValueNode
/* */ {
/* */ private StringTrieBuilder.Node next;
/* */
/* */ public IntermediateValueNode(int v, StringTrieBuilder.Node nextNode) {
/* 317 */ this.next = nextNode;
/* 318 */ setValue(v);
/* */ }
/* */
/* */ public int hashCode() {
/* 322 */ return (82767594 + this.value) * 37 + this.next.hashCode();
/* */ }
/* */
/* */ public boolean equals(Object other) {
/* 326 */ if (this == other) {
/* 327 */ return true;
/* */ }
/* 329 */ if (!super.equals(other)) {
/* 330 */ return false;
/* */ }
/* 332 */ IntermediateValueNode o = (IntermediateValueNode)other;
/* 333 */ return this.next == o.next;
/* */ }
/* */
/* */ public int markRightEdgesFirst(int edgeNumber) {
/* 337 */ if (this.offset == 0) {
/* 338 */ this.offset = (edgeNumber = this.next.markRightEdgesFirst(edgeNumber));
/* */ }
/* 340 */ return edgeNumber;
/* */ }
/* */
/* */ public void write(StringTrieBuilder builder) {
/* 344 */ this.next.write(builder);
/* 345 */ this.offset = builder.writeValueAndFinal(this.value, false); } }
/* */
/* */ private static final class LinearMatchNode extends StringTrieBuilder.ValueNode { private CharSequence strings;
/* */ private int stringOffset;
/* */ private int length;
/* */ private StringTrieBuilder.Node next;
/* */ private int hash;
/* */
/* 353 */ public LinearMatchNode(CharSequence builderStrings, int sOffset, int len, StringTrieBuilder.Node nextNode) { this.strings = builderStrings;
/* 354 */ this.stringOffset = sOffset;
/* 355 */ this.length = len;
/* 356 */ this.next = nextNode;
/* */ }
/* */
/* 359 */ public int hashCode() { return this.hash; }
/* */
/* */ public boolean equals(Object other) {
/* 362 */ if (this == other) {
/* 363 */ return true;
/* */ }
/* 365 */ if (!super.equals(other)) {
/* 366 */ return false;
/* */ }
/* 368 */ LinearMatchNode o = (LinearMatchNode)other;
/* 369 */ if ((this.length != o.length) || (this.next != o.next)) {
/* 370 */ return false;
/* */ }
/* 372 */ int i = this.stringOffset;int j = o.stringOffset; for (int limit = this.stringOffset + this.length; i < limit; j++) {
/* 373 */ if (this.strings.charAt(i) != this.strings.charAt(j)) {
/* 374 */ return false;
/* */ }
/* 372 */ i++;
/* */ }
/* */
/* */
/* */
/* 377 */ return true;
/* */ }
/* */
/* */ public StringTrieBuilder.Node add(StringTrieBuilder builder, CharSequence s, int start, int sValue) {
/* 381 */ if (start == s.length()) {
/* 382 */ if (this.hasValue) {
/* 383 */ throw new IllegalArgumentException("Duplicate string.");
/* */ }
/* 385 */ setValue(sValue);
/* 386 */ return this;
/* */ }
/* */
/* 389 */ int limit = this.stringOffset + this.length;
/* 390 */ for (int i = this.stringOffset; i < limit; start++) {
/* 391 */ if (start == s.length())
/* */ {
/* 393 */ int prefixLength = i - this.stringOffset;
/* 394 */ LinearMatchNode suffixNode = new LinearMatchNode(this.strings, i, this.length - prefixLength, this.next);
/* 395 */ suffixNode.setValue(sValue);
/* 396 */ this.length = prefixLength;
/* 397 */ this.next = suffixNode;
/* 398 */ return this;
/* */ }
/* 400 */ char thisChar = this.strings.charAt(i);
/* 401 */ char newChar = s.charAt(start);
/* 402 */ if (thisChar != newChar)
/* */ {
/* 404 */ StringTrieBuilder.DynamicBranchNode branchNode = new StringTrieBuilder.DynamicBranchNode();
/* */ StringTrieBuilder.Node result;
/* */ StringTrieBuilder.Node thisSuffixNode;
/* 407 */ StringTrieBuilder.Node result; if (i == this.stringOffset)
/* */ {
/* 409 */ if (this.hasValue)
/* */ {
/* 411 */ branchNode.setValue(this.value);
/* 412 */ this.value = 0;
/* 413 */ this.hasValue = false;
/* */ }
/* 415 */ this.stringOffset += 1;
/* 416 */ this.length -= 1;
/* 417 */ StringTrieBuilder.Node thisSuffixNode = this.length > 0 ? this : this.next;
/* */
/* 419 */ result = branchNode; } else { StringTrieBuilder.Node result;
/* 420 */ if (i == limit - 1)
/* */ {
/* 422 */ this.length -= 1;
/* 423 */ StringTrieBuilder.Node thisSuffixNode = this.next;
/* 424 */ this.next = branchNode;
/* 425 */ result = this;
/* */ }
/* */ else {
/* 428 */ int prefixLength = i - this.stringOffset;
/* 429 */ i++;
/* 430 */ thisSuffixNode = new LinearMatchNode(this.strings, i, this.length - (prefixLength + 1), this.next);
/* */
/* 432 */ this.length = prefixLength;
/* 433 */ this.next = branchNode;
/* 434 */ result = this;
/* */ } }
/* 436 */ StringTrieBuilder.ValueNode newSuffixNode = builder.createSuffixNode(s, start + 1, sValue);
/* 437 */ branchNode.add(thisChar, thisSuffixNode);
/* 438 */ branchNode.add(newChar, newSuffixNode);
/* 439 */ return result;
/* */ }
/* 390 */ i++;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 443 */ this.next = this.next.add(builder, s, start, sValue);
/* 444 */ return this;
/* */ }
/* */
/* */ public StringTrieBuilder.Node register(StringTrieBuilder builder) {
/* 448 */ this.next = this.next.register(builder);
/* */
/* 450 */ int maxLinearMatchLength = builder.getMaxLinearMatchLength();
/* 451 */ while (this.length > maxLinearMatchLength) {
/* 452 */ int nextOffset = this.stringOffset + this.length - maxLinearMatchLength;
/* 453 */ this.length -= maxLinearMatchLength;
/* 454 */ LinearMatchNode suffixNode = new LinearMatchNode(this.strings, nextOffset, maxLinearMatchLength, this.next);
/* */
/* 456 */ suffixNode.setHashCode();
/* 457 */ this.next = builder.registerNode(suffixNode); }
/* */ StringTrieBuilder.Node result;
/* */ StringTrieBuilder.Node result;
/* 460 */ if ((this.hasValue) && (!builder.matchNodesCanHaveValues())) {
/* 461 */ int intermediateValue = this.value;
/* 462 */ this.value = 0;
/* 463 */ this.hasValue = false;
/* 464 */ setHashCode();
/* 465 */ result = new StringTrieBuilder.IntermediateValueNode(intermediateValue, builder.registerNode(this));
/* */ } else {
/* 467 */ setHashCode();
/* 468 */ result = this;
/* */ }
/* 470 */ return builder.registerNode(result);
/* */ }
/* */
/* */ public int markRightEdgesFirst(int edgeNumber) {
/* 474 */ if (this.offset == 0) {
/* 475 */ this.offset = (edgeNumber = this.next.markRightEdgesFirst(edgeNumber));
/* */ }
/* 477 */ return edgeNumber;
/* */ }
/* */
/* */ public void write(StringTrieBuilder builder) {
/* 481 */ this.next.write(builder);
/* 482 */ builder.write(this.stringOffset, this.length);
/* 483 */ this.offset = builder.writeValueAndType(this.hasValue, this.value, builder.getMinLinearMatch() + this.length - 1);
/* */ }
/* */
/* */ private void setHashCode()
/* */ {
/* 488 */ this.hash = ((124151391 + this.length) * 37 + this.next.hashCode());
/* 489 */ if (this.hasValue) {
/* 490 */ this.hash = (this.hash * 37 + this.value);
/* */ }
/* 492 */ int i = this.stringOffset; for (int limit = this.stringOffset + this.length; i < limit; i++) {
/* 493 */ this.hash = (this.hash * 37 + this.strings.charAt(i));
/* */ }
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private static final class DynamicBranchNode
/* */ extends StringTrieBuilder.ValueNode
/* */ {
/* */ public void add(char c, StringTrieBuilder.Node node)
/* */ {
/* 508 */ int i = find(c);
/* 509 */ this.chars.insert(i, c);
/* 510 */ this.equal.add(i, node);
/* */ }
/* */
/* */ public StringTrieBuilder.Node add(StringTrieBuilder builder, CharSequence s, int start, int sValue) {
/* 514 */ if (start == s.length()) {
/* 515 */ if (this.hasValue) {
/* 516 */ throw new IllegalArgumentException("Duplicate string.");
/* */ }
/* 518 */ setValue(sValue);
/* 519 */ return this;
/* */ }
/* */
/* 522 */ char c = s.charAt(start++);
/* 523 */ int i = find(c);
/* 524 */ if ((i < this.chars.length()) && (c == this.chars.charAt(i))) {
/* 525 */ this.equal.set(i, ((StringTrieBuilder.Node)this.equal.get(i)).add(builder, s, start, sValue));
/* */ } else {
/* 527 */ this.chars.insert(i, c);
/* 528 */ this.equal.add(i, builder.createSuffixNode(s, start, sValue));
/* */ }
/* 530 */ return this;
/* */ }
/* */
/* */ public StringTrieBuilder.Node register(StringTrieBuilder builder) {
/* 534 */ StringTrieBuilder.Node subNode = register(builder, 0, this.chars.length());
/* 535 */ StringTrieBuilder.BranchHeadNode head = new StringTrieBuilder.BranchHeadNode(this.chars.length(), subNode);
/* 536 */ StringTrieBuilder.Node result = head;
/* 537 */ if (this.hasValue) {
/* 538 */ if (builder.matchNodesCanHaveValues()) {
/* 539 */ head.setValue(this.value);
/* */ } else {
/* 541 */ result = new StringTrieBuilder.IntermediateValueNode(this.value, builder.registerNode(head));
/* */ }
/* */ }
/* 544 */ return builder.registerNode(result);
/* */ }
/* */
/* 547 */ private StringTrieBuilder.Node register(StringTrieBuilder builder, int start, int limit) { int length = limit - start;
/* 548 */ if (length > builder.getMaxBranchLinearSubNodeLength())
/* */ {
/* 550 */ int middle = start + length / 2;
/* 551 */ return builder.registerNode(new StringTrieBuilder.SplitBranchNode(this.chars.charAt(middle), register(builder, start, middle), register(builder, middle, limit)));
/* */ }
/* */
/* */
/* */
/* */
/* 557 */ StringTrieBuilder.ListBranchNode listNode = new StringTrieBuilder.ListBranchNode(length);
/* */ do {
/* 559 */ char c = this.chars.charAt(start);
/* 560 */ StringTrieBuilder.Node node = (StringTrieBuilder.Node)this.equal.get(start);
/* 561 */ if (node.getClass() == StringTrieBuilder.ValueNode.class)
/* */ {
/* 563 */ listNode.add(c, ((StringTrieBuilder.ValueNode)node).value);
/* */ } else {
/* 565 */ listNode.add(c, node.register(builder));
/* */ }
/* 567 */ start++; } while (start < limit);
/* 568 */ return builder.registerNode(listNode);
/* */ }
/* */
/* */ private int find(char c) {
/* 572 */ int start = 0;
/* 573 */ int limit = this.chars.length();
/* 574 */ while (start < limit) {
/* 575 */ int i = (start + limit) / 2;
/* 576 */ char middleChar = this.chars.charAt(i);
/* 577 */ if (c < middleChar) {
/* 578 */ limit = i;
/* 579 */ } else { if (c == middleChar) {
/* 580 */ return i;
/* */ }
/* 582 */ start = i + 1;
/* */ }
/* */ }
/* 585 */ return start;
/* */ }
/* */
/* 588 */ private StringBuilder chars = new StringBuilder();
/* 589 */ private ArrayList<StringTrieBuilder.Node> equal = new ArrayList();
/* */ }
/* */
/* */ private static abstract class BranchNode extends StringTrieBuilder.Node { protected int hash;
/* */ protected int firstEdgeNumber;
/* */
/* 595 */ public int hashCode() { return this.hash; }
/* */ }
/* */
/* */ private static final class ListBranchNode extends StringTrieBuilder.BranchNode { private StringTrieBuilder.Node[] equal;
/* */ private int length;
/* */ private int[] values;
/* */ private char[] units;
/* */
/* 603 */ public ListBranchNode(int capacity) { this.hash = (165535188 + capacity);
/* 604 */ this.equal = new StringTrieBuilder.Node[capacity];
/* 605 */ this.values = new int[capacity];
/* 606 */ this.units = new char[capacity];
/* */ }
/* */
/* */ public boolean equals(Object other) {
/* 610 */ if (this == other) {
/* 611 */ return true;
/* */ }
/* 613 */ if (!super.equals(other)) {
/* 614 */ return false;
/* */ }
/* 616 */ ListBranchNode o = (ListBranchNode)other;
/* 617 */ for (int i = 0; i < this.length; i++) {
/* 618 */ if ((this.units[i] != o.units[i]) || (this.values[i] != o.values[i]) || (this.equal[i] != o.equal[i])) {
/* 619 */ return false;
/* */ }
/* */ }
/* 622 */ return true;
/* */ }
/* */
/* */ public int markRightEdgesFirst(int edgeNumber) {
/* 626 */ if (this.offset == 0) {
/* 627 */ this.firstEdgeNumber = edgeNumber;
/* 628 */ int step = 0;
/* 629 */ int i = this.length;
/* */ do {
/* 631 */ StringTrieBuilder.Node edge = this.equal[(--i)];
/* 632 */ if (edge != null) {
/* 633 */ edgeNumber = edge.markRightEdgesFirst(edgeNumber - step);
/* */ }
/* */
/* 636 */ step = 1;
/* 637 */ } while (i > 0);
/* 638 */ this.offset = edgeNumber;
/* */ }
/* 640 */ return edgeNumber;
/* */ }
/* */
/* */
/* */
/* */
/* */ public void write(StringTrieBuilder builder)
/* */ {
/* 648 */ int unitNumber = this.length - 1;
/* 649 */ StringTrieBuilder.Node rightEdge = this.equal[unitNumber];
/* 650 */ int rightEdgeNumber = rightEdge == null ? this.firstEdgeNumber : rightEdge.getOffset();
/* */ do {
/* 652 */ unitNumber--;
/* 653 */ if (this.equal[unitNumber] != null) {
/* 654 */ this.equal[unitNumber].writeUnlessInsideRightEdge(this.firstEdgeNumber, rightEdgeNumber, builder);
/* */ }
/* 656 */ } while (unitNumber > 0);
/* */
/* */
/* 659 */ unitNumber = this.length - 1;
/* 660 */ if (rightEdge == null) {
/* 661 */ builder.writeValueAndFinal(this.values[unitNumber], true);
/* */ } else {
/* 663 */ rightEdge.write(builder);
/* */ }
/* 665 */ this.offset = builder.write(this.units[unitNumber]);
/* */ for (;;) {
/* 667 */ unitNumber--; if (unitNumber < 0) break;
/* */ boolean isFinal;
/* */ int value;
/* 670 */ boolean isFinal; if (this.equal[unitNumber] == null)
/* */ {
/* 672 */ int value = this.values[unitNumber];
/* 673 */ isFinal = true;
/* */ }
/* */ else {
/* 676 */ assert (this.equal[unitNumber].getOffset() > 0);
/* 677 */ value = this.offset - this.equal[unitNumber].getOffset();
/* 678 */ isFinal = false;
/* */ }
/* 680 */ builder.writeValueAndFinal(value, isFinal);
/* 681 */ this.offset = builder.write(this.units[unitNumber]);
/* */ }
/* */ }
/* */
/* */ public void add(int c, int value) {
/* 686 */ this.units[this.length] = ((char)c);
/* 687 */ this.equal[this.length] = null;
/* 688 */ this.values[this.length] = value;
/* 689 */ this.length += 1;
/* 690 */ this.hash = ((this.hash * 37 + c) * 37 + value);
/* */ }
/* */
/* */ public void add(int c, StringTrieBuilder.Node node) {
/* 694 */ this.units[this.length] = ((char)c);
/* 695 */ this.equal[this.length] = node;
/* 696 */ this.values[this.length] = 0;
/* 697 */ this.length += 1;
/* 698 */ this.hash = ((this.hash * 37 + c) * 37 + node.hashCode());
/* */ }
/* */ }
/* */
/* */
/* */ private static final class SplitBranchNode
/* */ extends StringTrieBuilder.BranchNode
/* */ {
/* */ private char unit;
/* */
/* */ private StringTrieBuilder.Node lessThan;
/* */ private StringTrieBuilder.Node greaterOrEqual;
/* */
/* */ public SplitBranchNode(char middleUnit, StringTrieBuilder.Node lessThanNode, StringTrieBuilder.Node greaterOrEqualNode)
/* */ {
/* 713 */ this.hash = (((206918985 + middleUnit) * 37 + lessThanNode.hashCode()) * 37 + greaterOrEqualNode.hashCode());
/* */
/* 715 */ this.unit = middleUnit;
/* 716 */ this.lessThan = lessThanNode;
/* 717 */ this.greaterOrEqual = greaterOrEqualNode;
/* */ }
/* */
/* */ public boolean equals(Object other) {
/* 721 */ if (this == other) {
/* 722 */ return true;
/* */ }
/* 724 */ if (!super.equals(other)) {
/* 725 */ return false;
/* */ }
/* 727 */ SplitBranchNode o = (SplitBranchNode)other;
/* 728 */ return (this.unit == o.unit) && (this.lessThan == o.lessThan) && (this.greaterOrEqual == o.greaterOrEqual);
/* */ }
/* */
/* */ public int markRightEdgesFirst(int edgeNumber) {
/* 732 */ if (this.offset == 0) {
/* 733 */ this.firstEdgeNumber = edgeNumber;
/* 734 */ edgeNumber = this.greaterOrEqual.markRightEdgesFirst(edgeNumber);
/* 735 */ this.offset = (edgeNumber = this.lessThan.markRightEdgesFirst(edgeNumber - 1));
/* */ }
/* 737 */ return edgeNumber;
/* */ }
/* */
/* */ public void write(StringTrieBuilder builder)
/* */ {
/* 742 */ this.lessThan.writeUnlessInsideRightEdge(this.firstEdgeNumber, this.greaterOrEqual.getOffset(), builder);
/* */
/* 744 */ this.greaterOrEqual.write(builder);
/* */
/* 746 */ assert (this.lessThan.getOffset() > 0);
/* 747 */ builder.writeDeltaTo(this.lessThan.getOffset());
/* 748 */ this.offset = builder.write(this.unit);
/* */ }
/* */ }
/* */
/* */ private static final class BranchHeadNode extends StringTrieBuilder.ValueNode
/* */ {
/* */ private int length;
/* */ private StringTrieBuilder.Node next;
/* */
/* */ public BranchHeadNode(int len, StringTrieBuilder.Node subNode)
/* */ {
/* 759 */ this.length = len;
/* 760 */ this.next = subNode;
/* */ }
/* */
/* */ public int hashCode() {
/* 764 */ return (248302782 + this.length) * 37 + this.next.hashCode();
/* */ }
/* */
/* */ public boolean equals(Object other) {
/* 768 */ if (this == other) {
/* 769 */ return true;
/* */ }
/* 771 */ if (!super.equals(other)) {
/* 772 */ return false;
/* */ }
/* 774 */ BranchHeadNode o = (BranchHeadNode)other;
/* 775 */ return (this.length == o.length) && (this.next == o.next);
/* */ }
/* */
/* */ public int markRightEdgesFirst(int edgeNumber) {
/* 779 */ if (this.offset == 0) {
/* 780 */ this.offset = (edgeNumber = this.next.markRightEdgesFirst(edgeNumber));
/* */ }
/* 782 */ return edgeNumber;
/* */ }
/* */
/* */ public void write(StringTrieBuilder builder) {
/* 786 */ this.next.write(builder);
/* 787 */ if (this.length <= builder.getMinLinearMatch()) {
/* 788 */ this.offset = builder.writeValueAndType(this.hasValue, this.value, this.length - 1);
/* */ } else {
/* 790 */ builder.write(this.length - 1);
/* 791 */ this.offset = builder.writeValueAndType(this.hasValue, this.value, 0);
/* */ }
/* */ }
/* */ }
/* */
/* */
/* */
/* */ private ValueNode createSuffixNode(CharSequence s, int start, int sValue)
/* */ {
/* 800 */ ValueNode node = registerFinalValue(sValue);
/* 801 */ if (start < s.length()) {
/* 802 */ int offset = this.strings.length();
/* 803 */ this.strings.append(s, start, s.length());
/* 804 */ node = new LinearMatchNode(this.strings, offset, s.length() - start, node);
/* */ }
/* 806 */ return node;
/* */ }
/* */
/* */
/* */ /**
/* */ * @deprecated
/* */ */
/* */ protected abstract boolean matchNodesCanHaveValues();
/* */
/* */
/* */ /**
/* */ * @deprecated
/* */ */
/* */ protected abstract int getMaxBranchLinearSubNodeLength();
/* */
/* */ /**
/* */ * @deprecated
/* */ */
/* */ protected abstract int getMinLinearMatch();
/* */
/* */ /**
/* */ * @deprecated
/* */ */
/* */ protected abstract int getMaxLinearMatchLength();
/* */
/* */ /**
/* */ * @deprecated
/* */ */
/* */ protected abstract int write(int paramInt);
/* */
/* */ /**
/* */ * @deprecated
/* */ */
/* */ protected abstract int write(int paramInt1, int paramInt2);
/* */
/* */ /**
/* */ * @deprecated
/* */ */
/* */ protected abstract int writeValueAndFinal(int paramInt, boolean paramBoolean);
/* */
/* */ /**
/* */ * @deprecated
/* */ */
/* */ protected abstract int writeValueAndType(boolean paramBoolean, int paramInt1, int paramInt2);
/* */
/* */ /**
/* */ * @deprecated
/* */ */
/* */ protected abstract int writeDeltaTo(int paramInt);
/* */
/* */ private static enum State
/* */ {
/* 858 */ ADDING, BUILDING_FAST, BUILDING_SMALL, BUILT;
/* */ private State() {} }
/* 860 */ private State state = State.ADDING;
/* */
/* */
/* */
/* */ /**
/* */ * @deprecated
/* */ */
/* 867 */ protected StringBuilder strings = new StringBuilder();
/* */
/* */ private Node root;
/* */
/* 871 */ private HashMap<Node, Node> nodes = new HashMap();
/* 872 */ private ValueNode lookupFinalValueNode = new ValueNode();
/* */ }
/* Location: C:\Users\Ethan\Desktop\FontZip\FontTool\sfnttool.jar!\com\ibm\icu\util\StringTrieBuilder.class
* Java compiler version: 5 (49.0)
* JD-Core Version: 0.7.1
*/