1 9 package javolution.text; 10 11 import j2me.io.Serializable; 12 import j2me.lang.CharSequence; 13 import j2mex.realtime.MemoryArea; 14 15 import javolution.context.Realtime; 16 import javolution.context.RealtimeObject; 17 import javolution.lang.MathLib; 18 import javolution.lang.Reusable; 19 20 34 public class TextBuilder extends RealtimeObject implements Appendable , 35 CharSequence , Reusable, Serializable { 36 37 40 private static final Factory FACTORY = new Factory() { 41 public Object create() { 42 return new TextBuilder(); 43 } 44 }; 45 46 54 static final int D0 = 5; 55 56 static final int M0 = (1 << D0) - 1; 57 58 static final int C0 = 1 << D0; 60 private static final int D1 = D0 + 2; 61 62 private static final int R1 = D0; 63 64 private static final int M1 = (1 << D1) - 1; 65 66 private static final int C1 = 1 << (D0 + D1); 68 private static final int D2 = D1 + 2; 69 70 private static final int R2 = D0 + D1; 71 72 private static final int M2 = (1 << D2) - 1; 73 74 private static final int C2 = 1 << (D0 + D1 + D2); 76 private static final int D3 = D2 + 2; 77 78 private static final int R3 = D0 + D1 + D2; 79 80 private final char[] _chars0 = new char[1 << D0]; 82 private char[][] _chars1; 84 private char[][][] _chars2; 86 private char[][][][] _chars3; 88 91 private int _capacity = C0; 92 93 96 private int _length; 97 98 101 public TextBuilder() { 102 } 103 104 109 public TextBuilder(CharSequence csq) { 110 append(csq); 111 } 112 113 118 public TextBuilder(String str) { 119 append(str); 120 } 121 122 129 public TextBuilder(int capacity) { 130 while (capacity > _capacity) { 131 increaseCapacity(); 132 } 133 } 134 135 142 public static TextBuilder newInstance() { 143 TextBuilder textBuilder = (TextBuilder) FACTORY.object(); 144 textBuilder._length = 0; 145 return textBuilder; 146 } 147 148 153 public static void recycle(TextBuilder instance) { 154 FACTORY.recycle(instance); 155 } 156 157 162 public final int length() { 163 return _length; 164 } 165 166 173 public final char charAt(int i) { 174 if ((i < 0) || (i >= _length)) 175 throw new IndexOutOfBoundsException (); 176 return charsAt(i)[i & M0]; 177 } 178 179 final char[] charsAt(int i) { 181 return (i < C0) ? _chars0 : (i < C1) ? _chars1[(i >> R1)] 182 : (i < C2) ? _chars2[(i >> R2)][(i >> R1) & M1] 183 : _chars3[(i >> R3)][(i >> R2) & M2][(i >> R1) & M1]; 184 } 185 186 198 public final void getChars(int srcBegin, int srcEnd, char[] dst, 199 int dstBegin) { 200 if ((srcBegin < 0) || (dstBegin < 0) || (srcBegin > srcEnd) 201 || (srcEnd > this.length()) 202 || ((dstBegin + srcEnd - srcBegin) > dst.length)) 203 throw new IndexOutOfBoundsException (); 204 for (int i = srcBegin, j = dstBegin; i < srcEnd;) { 205 char[] chars0 = charsAt(i); int i0 = i & M0; 207 int length = MathLib.min(C0 - i0, srcEnd - i); 208 System.arraycopy(chars0, i0, dst, j, length); 209 i += length; 210 j += length; 211 } 212 } 213 214 222 public final void setCharAt(int index, char c) { 223 if ((index < 0) || (index >= _length)) 224 throw new IndexOutOfBoundsException ("index: " + index); 225 charsAt(index)[index & M0] = c; 226 } 227 228 236 public final void setLength(int newLength) { 237 if (newLength < 0) 238 throw new IndexOutOfBoundsException (); 239 if (newLength <= _length) { 240 _length = newLength; 241 } else { 242 for (int i = _length; i++ < newLength;) { 243 append('\u0000'); 244 } 245 } 246 } 247 248 258 public final CharSequence subSequence(int start, int end) { 259 if ((start < 0) || (end < 0) || (start > end) || (end > _length)) 260 throw new IndexOutOfBoundsException (); 261 return Text.valueOf(this, start, end); 262 } 263 264 270 public final Appendable append(char c) { if (_length >= C0) 272 return append2(c); 273 _chars0[_length++] = c; 274 return this; 275 } 276 277 private Appendable append2(char c) { 278 if (_length >= _capacity) 279 increaseCapacity(); 280 final int i = _length++; 281 if (i < C1) { 282 _chars1[(i >> R1)][i & M0] = c; 283 } else if (i < C2) { 284 _chars2[(i >> R2)][(i >> R1) & M1][i & M0] = c; 285 } else { 286 _chars3[(i >> R3)][(i >> R2) & M2][(i >> R1) & M1][i & M0] = c; 287 } 288 return this; 289 } 290 291 299 public final Appendable append(CharSequence csq) { 300 return (csq == null) ? append("null") : append(csq, 0, csq.length()); 301 } 302 303 315 public final Appendable append(CharSequence csq, int start, 316 int end) { 317 if (csq == null) 318 return append("null"); 319 if ((start < 0) || (end < 0) || (start > end) || (end > csq.length())) 320 throw new IndexOutOfBoundsException (); 321 for (int i = start; i < end;) { 322 append(csq.charAt(i++)); 323 } 324 return this; 325 } 326 327 335 public final TextBuilder append(Object obj) { 336 if (obj instanceof String ) { 337 return append((String ) obj); 338 } else if (obj instanceof CharSequence ) { 339 return (TextBuilder) append((CharSequence ) obj); 340 } else if (obj instanceof Realtime) { 341 return append(((Realtime) obj).toText()); 342 } else if (obj != null) { 343 return append(obj.toString()); 344 } else { 345 return append("null"); 346 } 347 } 348 349 357 public final TextBuilder append(String str) { 358 if (str == null) 359 return append("null"); 360 final int length = str.length(); 361 for (int i = 0; i < length;) { 362 append(str.charAt(i++)); 363 } 364 return this; 365 } 366 367 379 public final TextBuilder append(String str, int start, int end) { 380 if (str == null) 381 return append("null"); 382 if ((start < 0) || (end < 0) || (start > end) || (end > str.length())) 383 throw new IndexOutOfBoundsException (); 384 for (int i = start; i < end;) { 385 append(str.charAt(i++)); 386 } 387 return this; 388 } 389 390 398 public TextBuilder append(Text text) { 399 if (text == null) 400 return append("null"); 401 final int length = text.length(); 402 for (int i = 0; i < length;) { 403 append(text.charAt(i++)); 404 } 405 return this; 406 } 407 408 414 public final TextBuilder append(char chars[]) { 415 return append(chars, 0, chars.length); 416 } 417 418 428 public final TextBuilder append(char chars[], int offset, int length) { 429 if ((offset < 0) || (length < 0) || ((offset + length) > chars.length)) 430 throw new IndexOutOfBoundsException (); 431 final int end = offset + length; 432 for (int i = offset; i < end;) { 433 append(chars[i++]); 434 } 435 return this; 436 } 437 438 446 public final TextBuilder append(boolean b) { 447 return b ? append("true") : append("false"); 448 } 449 450 457 public final TextBuilder append(int i) { 458 if (i < 0) { 459 if (i == Integer.MIN_VALUE) return append("-2147483648"); i = -i; 462 append('-'); 463 } 464 if (i >= 100000) { 465 int high = i / 100000; 466 writeDigits(high, false); 467 i -= high * 100000; 468 writeDigits(i, true); 469 } else { 470 writeDigits(i, false); 471 } 472 return this; 473 } 474 475 483 public final TextBuilder append(int i, int radix) { 484 if (radix == 10) 485 return append(i); if (radix < 2 || radix > 36) 487 throw new IllegalArgumentException ("radix: " + radix); 488 if (i < 0) { 489 append('-'); 490 } else { 491 i = -i; 492 } 493 append2(i, radix); 494 return this; 495 } 496 497 private void append2(int i, int radix) { 498 if (i <= -radix) { 499 append2(i / radix, radix); 500 append(DIGIT_TO_CHAR[-(i % radix)]); 501 } else { 502 append(DIGIT_TO_CHAR[-i]); 503 } 504 } 505 506 513 public final TextBuilder append(long l) { 514 if (l < 0) { 515 if (l == Long.MIN_VALUE) return append("-9223372036854775808"); l = -l; 518 append('-'); 519 } 520 boolean writeZero = false; 521 if (l >= 1000000000000000L) { 522 int high = (int) (l / 1000000000000000L); 523 writeDigits(high, writeZero); 524 l -= high * 1000000000000000L; 525 writeZero = true; 526 } 527 if (writeZero || (l >= 10000000000L)) { 528 int high = (int) (l / 10000000000L); 529 writeDigits(high, writeZero); 530 l -= high * 10000000000L; 531 writeZero = true; 532 } 533 if (writeZero || (l >= 100000)) { 534 int high = (int) (l / 100000); 535 writeDigits(high, writeZero); 536 l -= high * 100000L; 537 writeZero = true; 538 } 539 writeDigits((int) l, writeZero); 540 return this; 541 } 542 543 551 public final TextBuilder append(long l, int radix) { 552 if (radix == 10) 553 return append(l); if (radix < 2 || radix > 36) 555 throw new IllegalArgumentException ("radix: " + radix); 556 if (l < 0) { 557 append('-'); 558 } else { 559 l = -l; 560 } 561 append2(l, radix); 562 return this; 563 } 564 565 private void append2(long l, int radix) { 566 if (l <= -radix) { 567 append2(l / radix, radix); 568 append(DIGIT_TO_CHAR[(int) -(l % radix)]); 569 } else { 570 append(DIGIT_TO_CHAR[(int) -l]); 571 } 572 } 573 574 586 587 601 602 691 692 final void appendFraction(long l, int digits, boolean showZero) { 693 append('.'); 694 int length = MathLib.digitLength(l); 695 if ((length == 0) && !showZero) { append('0'); 697 return; 698 } 699 for (int i = length; i < digits; i++) { 700 append('0'); 701 } 702 if (l != 0) { 703 append(l); 704 } 705 if (!showZero) { int trailingZeros = 0; 707 while (true) { 708 char c = charAt(_length - trailingZeros - 1); 709 if (c != '0') 710 break; 711 trailingZeros++; 712 } 713 this.setLength(_length - trailingZeros); 714 } 715 } 716 717 726 public final TextBuilder insert(int index, CharSequence csq) { 727 if ((index < 0) || (index > _length)) 728 throw new IndexOutOfBoundsException ("index: " + index); 729 final int shift = csq.length(); 730 _length += shift; 731 while (_length >= _capacity) { 732 increaseCapacity(); 733 } 734 for (int i = _length - shift; --i >= index;) { 735 this.setCharAt(i + shift, this.charAt(i)); 736 } 737 for (int i = csq.length(); --i >= 0;) { 738 this.setCharAt(index + i, csq.charAt(i)); 739 } 740 return this; 741 } 742 743 749 public final TextBuilder clear() { 750 _length = 0; 751 return this; 752 } 753 754 763 public final TextBuilder delete(int start, int end) { 764 if ((start < 0) || (end < 0) || (start > end) || (end > this.length())) 765 throw new IndexOutOfBoundsException (); 766 for (int i = end, j = start; i < _length;) { 767 this.setCharAt(j++, this.charAt(i++)); 768 } 769 _length -= end - start; 770 return this; 771 } 772 773 778 public final TextBuilder reverse() { 779 final int n = _length - 1; 780 for (int j = (n - 1) >> 1; j >= 0;) { 781 char c = charAt(j); 782 setCharAt(j, charAt(n - j)); 783 setCharAt(n - j--, c); 784 } 785 return this; 786 } 787 788 795 public final Text toText() { 796 return Text.valueOf(this, 0, _length); 797 } 798 799 804 public final String stringValue() { 805 char[] data = new char[_length]; 806 this.getChars(0, _length, data, 0); 807 return new String (data, 0, _length); 808 } 809 810 813 public final void reset() { 814 _length = 0; 815 } 816 817 822 public final int hashCode() { 823 int h = 0; 824 for (int i = 0; i < _length;) { 825 h = 31 * h + charAt(i++); 826 } 827 return h; 828 } 829 830 839 public final boolean equals(Object obj) { 840 if (this == obj) 841 return true; 842 if (!(obj instanceof TextBuilder)) 843 return false; 844 TextBuilder that = (TextBuilder) obj; 845 if (this._length != that._length) 846 return false; 847 for (int i = 0; i < _length;) { 848 if (this.charAt(i) != that.charAt(i++)) 849 return false; 850 } 851 return true; 852 } 853 854 860 final void appendTo(StringBuffer sb) { 861 sb.append(_chars0, 0, _length); 862 } 863 864 874 875 883 public final boolean contentEquals(CharSequence csq) { 884 if (csq.length() != _length) 885 return false; 886 char[] chars = charsAt(0); for (int i = 0; i < _length;) { 888 if (chars[i & M0] != csq.charAt(i++)) 889 return false; 890 if ((i & M0) == 0) { chars = charsAt(i); 892 } 893 } 894 return true; 895 } 896 897 905 public final boolean contentEquals(String csq) { 906 if (csq.length() != _length) 907 return false; 908 char[] chars = charsAt(0); for (int i = 0; i < _length;) { 910 if (chars[i & M0] != csq.charAt(i++)) 911 return false; 912 if ((i & M0) == 0) { chars = charsAt(i); 914 } 915 } 916 return true; 917 } 918 919 922 private void increaseCapacity() { 923 MemoryArea.getMemoryArea(this).executeInArea(new Runnable () { 924 public void run() { 925 final int c = _capacity; 926 _capacity += 1 << D0; 927 if (c < C1) { 928 if (_chars1 == null) { 929 _chars1 = new char[1 << D1][]; 930 } 931 _chars1[(c >> R1)] = new char[1 << D0]; 932 933 } else if (c < C2) { 934 if (_chars2 == null) { 935 _chars2 = new char[1 << D2][][]; 936 } 937 if (_chars2[(c >> R2)] == null) { 938 _chars2[(c >> R2)] = new char[1 << D1][]; 939 } 940 _chars2[(c >> R2)][(c >> R1) & M1] = new char[1 << D0]; 941 942 } else { 943 if (_chars3 == null) { 944 _chars3 = new char[1 << D3][][][]; 945 } 946 if (_chars3[(c >> R3)] == null) { 947 _chars3[(c >> R3)] = new char[1 << D2][][]; 948 } 949 if (_chars3[(c >> R3)][(c >> R2) & M2] == null) { 950 _chars3[(c >> R3)][(c >> R2) & M2] = new char[1 << D1][]; 951 } 952 _chars3[(c >> R3)][(c >> R2) & M2][(c >> R1) & M1] = new char[1 << D0]; 953 } 954 } 955 }); 956 } 957 958 966 private void writeDigits(int i, boolean writeZero) { 967 { 968 final int e = 10000; 969 if (i >= e) { 970 writeZero = true; 971 if (i >= e * 5) { 972 if (i >= e * 8) { 973 if (i >= e * 9) { 974 append('9'); 975 i -= e * 9; 976 } else { 977 append('8'); 978 i -= e * 8; 979 } 980 } else { if (i >= e * 7) { 982 append('7'); 983 i -= e * 7; 984 } else if (i >= e * 6) { 985 append('6'); 986 i -= e * 6; 987 } else { 988 append('5'); 989 i -= e * 5; 990 } 991 } 992 } else { if (i >= e * 3) { 994 if (i >= e * 4) { 995 append('4'); 996 i -= e * 4; 997 } else { 998 append('3'); 999 i -= e * 3; 1000 } 1001 } else { if (i >= e * 2) { 1003 append('2'); 1004 i -= e * 2; 1005 } else { 1006 append('1'); 1007 i -= e; 1008 } 1009 } 1010 } 1011 } else if (writeZero) { 1012 append('0'); 1013 } 1014 } 1015 { 1016 final int e = 1000; 1017 if (i >= e) { 1018 writeZero = true; 1019 if (i >= e * 5) { 1020 if (i >= e * 8) { 1021 if (i >= e * 9) { 1022 append('9'); 1023 i -= e * 9; 1024 } else { 1025 append('8'); 1026 i -= e * 8; 1027 } 1028 } else { if (i >= e * 7) { 1030 append('7'); 1031 i -= e * 7; 1032 } else if (i >= e * 6) { 1033 append('6'); 1034 i -= e * 6; 1035 } else { 1036 append('5'); 1037 i -= e * 5; 1038 } 1039 } 1040 } else { if (i >= e * 3) { 1042 if (i >= e * 4) { 1043 append('4'); 1044 i -= e * 4; 1045 } else { 1046 append('3'); 1047 i -= e * 3; 1048 } 1049 } else { if (i >= e * 2) { 1051 append('2'); 1052 i -= e * 2; 1053 } else { 1054 append('1'); 1055 i -= e; 1056 } 1057 } 1058 } 1059 } else if (writeZero) { 1060 append('0'); 1061 } 1062 } 1063 { 1064 final int e = 100; 1065 if (i >= e) { 1066 writeZero = true; 1067 if (i >= e * 5) { 1068 if (i >= e * 8) { 1069 if (i >= e * 9) { 1070 append('9'); 1071 i -= e * 9; 1072 } else { 1073 append('8'); 1074 i -= e * 8; 1075 } 1076 } else { if (i >= e * 7) { 1078 append('7'); 1079 i -= e * 7; 1080 } else if (i >= e * 6) { 1081 append('6'); 1082 i -= e * 6; 1083 } else { 1084 append('5'); 1085 i -= e * 5; 1086 } 1087 } 1088 } else { if (i >= e * 3) { 1090 if (i >= e * 4) { 1091 append('4'); 1092 i -= e * 4; 1093 } else { 1094 append('3'); 1095 i -= e * 3; 1096 } 1097 } else { if (i >= e * 2) { 1099 append('2'); 1100 i -= e * 2; 1101 } else { 1102 append('1'); 1103 i -= e; 1104 } 1105 } 1106 } 1107 } else if (writeZero) { 1108 append('0'); 1109 } 1110 } 1111 { 1112 final int e = 10; 1113 if (i >= e) { 1114 writeZero = true; 1115 if (i >= e * 5) { 1116 if (i >= e * 8) { 1117 if (i >= e * 9) { 1118 append('9'); 1119 i -= e * 9; 1120 } else { 1121 append('8'); 1122 i -= e * 8; 1123 } 1124 } else { if (i >= e * 7) { 1126 append('7'); 1127 i -= e * 7; 1128 } else if (i >= e * 6) { 1129 append('6'); 1130 i -= e * 6; 1131 } else { 1132 append('5'); 1133 i -= e * 5; 1134 } 1135 } 1136 } else { if (i >= e * 3) { 1138 if (i >= e * 4) { 1139 append('4'); 1140 i -= e * 4; 1141 } else { 1142 append('3'); 1143 i -= e * 3; 1144 } 1145 } else { if (i >= e * 2) { 1147 append('2'); 1148 i -= e * 2; 1149 } else { 1150 append('1'); 1151 i -= e; 1152 } 1153 } 1154 } 1155 } else if (writeZero) { 1156 append('0'); 1157 } 1158 } 1159 append(DIGIT_TO_CHAR[i]); 1160 } 1161 1162 1165 private final static char[] DIGIT_TO_CHAR = { '0', '1', '2', '3', '4', '5', 1166 '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 1167 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 1168 'w', 'x', 'y', 'z' }; 1169 1170} | Popular Tags |