1 38 package org.jruby; 39 40 import java.nio.ByteBuffer ; 41 import java.nio.charset.CharacterCodingException ; 42 import java.nio.charset.Charset ; 43 import java.nio.charset.CharsetDecoder ; 44 import java.nio.charset.CodingErrorAction ; 45 import java.util.ArrayList ; 46 import java.util.List ; 47 import java.util.Locale ; 48 import java.util.regex.Matcher ; 49 import java.util.regex.Pattern ; 50 51 import org.jruby.javasupport.JavaUtil; 52 import org.jruby.runtime.Arity; 53 import org.jruby.runtime.Block; 54 import org.jruby.runtime.CallType; 55 import org.jruby.runtime.ClassIndex; 56 import org.jruby.runtime.ThreadContext; 57 import org.jruby.runtime.builtin.IRubyObject; 58 import org.jruby.runtime.marshal.UnmarshalStream; 59 import org.jruby.util.ByteList; 60 import org.jruby.util.KCode; 61 import org.jruby.util.Pack; 62 import org.jruby.util.PrintfFormat; 63 64 68 public class RubyString extends RubyObject { 69 private static final String DEFAULT_RS = "\n"; 71 72 public static final byte OP_PLUS_SWITCHVALUE = 1; 73 public static final byte OP_LT_SWITCHVALUE = 2; 74 public static final byte AREF_SWITCHVALUE = 3; 75 public static final byte ASET_SWITCHVALUE = 4; 76 public static final byte NIL_P_SWITCHVALUE = 5; 77 public static final byte EQUALEQUAL_SWITCHVALUE = 6; 78 public static final byte OP_GE_SWITCHVALUE = 7; 79 public static final byte OP_LSHIFT_SWITCHVALUE = 8; 80 public static final byte EMPTY_P_SWITCHVALUE = 9; 81 82 private ByteList value; 83 private int hash; 84 private RubyFixnum r_hash; 85 private boolean validHash = false; 86 private String stringValue; 87 88 private RubyString(Ruby runtime, CharSequence value) { 90 this(runtime, runtime.getString(), value); 91 } 92 93 private RubyString(Ruby runtime, byte[] value) { 94 this(runtime, runtime.getString(), value); 95 } 96 97 private RubyString(Ruby runtime, ByteList value) { 98 this(runtime, runtime.getString(), value); 99 } 100 101 private RubyString(Ruby runtime, RubyClass rubyClass, CharSequence value) { 102 super(runtime, rubyClass); 103 104 assert value != null; 105 106 this.value = new ByteList(ByteList.plain(value),false); 107 } 108 109 private RubyString(Ruby runtime, RubyClass rubyClass, byte[] value) { 110 super(runtime, rubyClass); 111 112 assert value != null; 113 114 this.value = new ByteList(value); 115 } 116 117 private RubyString(Ruby runtime, RubyClass rubyClass, ByteList value) { 118 super(runtime, rubyClass); 119 120 assert value != null; 121 122 this.value = value; 123 } 124 125 public IRubyObject callMethod(ThreadContext context, RubyModule rubyclass, byte switchvalue, String name, 126 IRubyObject[] args, CallType callType, Block block) { 127 switch (switchvalue) { 128 case OP_PLUS_SWITCHVALUE: 129 Arity.singleArgument().checkArity(context.getRuntime(), args); 130 return op_plus(args[0]); 131 case OP_LT_SWITCHVALUE: 132 Arity.singleArgument().checkArity(context.getRuntime(), args); 133 return op_lt(args[0]); 134 case AREF_SWITCHVALUE: 135 Arity.optional().checkArity(context.getRuntime(), args); 136 return aref(args); 137 case ASET_SWITCHVALUE: 138 Arity.optional().checkArity(context.getRuntime(), args); 139 return aset(args); 140 case NIL_P_SWITCHVALUE: 141 Arity.noArguments().checkArity(context.getRuntime(), args); 142 return nil_p(); 143 case EQUALEQUAL_SWITCHVALUE: 144 Arity.singleArgument().checkArity(context.getRuntime(), args); 145 return eql(args[0]); 146 case OP_GE_SWITCHVALUE: 147 Arity.singleArgument().checkArity(context.getRuntime(), args); 148 return op_ge(args[0]); 149 case OP_LSHIFT_SWITCHVALUE: 150 Arity.singleArgument().checkArity(context.getRuntime(), args); 151 return concat(args[0]); 152 case EMPTY_P_SWITCHVALUE: 153 Arity.noArguments().checkArity(context.getRuntime(), args); 154 return empty(); 155 case 0: 156 default: 157 return super.callMethod(context, rubyclass, name, args, callType, block); 158 } 159 } 160 161 public int getNativeTypeIndex() { 162 return ClassIndex.STRING; 163 } 164 165 public Class getJavaClass() { 166 return String .class; 167 } 168 169 172 public String toString() { 173 if (stringValue == null) { 174 stringValue = new String (ByteList.plain(value.bytes),0,value.realSize); 175 } 176 return stringValue; 177 } 178 179 182 private void stringMutated() { 183 stringValue = null; 184 validHash = false; 185 taint(); 186 } 187 188 public static String bytesToString(byte[] bytes, int beg, int len) { 189 return new String (ByteList.plain(bytes), beg, len); 190 } 191 192 public static String byteListToString(ByteList bytes) { 193 return bytesToString(bytes.unsafeBytes(),0,bytes.length()); 194 } 195 196 public static String bytesToString(byte[] bytes) { 197 return bytesToString(bytes,0,bytes.length); 198 } 199 200 public static byte[] stringToBytes(String string) { 201 return ByteList.plain(string); 202 } 203 204 public static boolean isDigit(int c) { 205 return c >= '0' && c <= '9'; 206 } 207 208 public static boolean isUpper(int c) { 209 return c >= 'A' && c <= 'Z'; 210 } 211 212 public static boolean isLower(int c) { 213 return c >= 'a' && c <= 'z'; 214 } 215 216 public static boolean isLetter(int c) { 217 return isUpper(c) || isLower(c); 218 } 219 220 public static boolean isAlnum(int c) { 221 return isUpper(c) || isLower(c) || isDigit(c); 222 } 223 224 public static boolean isPrint(int c) { 225 return c >= 0x20 && c <= 0x7E; 226 } 227 228 public IRubyObject checkStringType() { 229 return this; 230 } 231 232 public IRubyObject to_s() { 233 return this; 234 } 235 236 237 public IRubyObject op_cmp(IRubyObject other) { 238 if (other instanceof RubyString) { 239 return getRuntime().newFixnum(cmp((RubyString)other)); 240 } 241 242 254 255 return getRuntime().getNil(); 256 } 257 258 public IRubyObject eql(IRubyObject other) { 259 Ruby runtime = getRuntime(); 260 if (other == this) { 261 return runtime.getTrue(); 262 } else if (!(other instanceof RubyString)) { 263 if(other.respondsTo("to_str")) { 264 return other.callMethod(runtime.getCurrentContext(), "==", this); 265 } 266 return runtime.getFalse(); 267 } 268 269 return runtime.newBoolean(value.equals(((RubyString) other).value)); 270 } 271 272 public IRubyObject op_plus(IRubyObject other) { 273 RubyString str = RubyString.stringValue(other); 274 275 ByteList newValue = new ByteList(value); 276 newValue.append(str.value); 277 return (RubyString) newString(getRuntime(), newValue).infectBy(str); 278 } 279 280 public IRubyObject op_mul(IRubyObject other) { 281 RubyInteger otherInteger = 282 (RubyInteger) other.convertType(RubyInteger.class, "Integer", "to_i"); 283 long len = otherInteger.getLongValue(); 284 285 if (len < 0) { 286 throw getRuntime().newArgumentError("negative argument"); 287 } 288 289 if (len > 0 && Integer.MAX_VALUE / len < value.length()) { 291 throw getRuntime().newArgumentError("argument too big"); 292 } 293 ByteList newBytes = new ByteList(value.length() * (int)len); 294 295 for (int i = 0; i < len; i++) { 296 newBytes.append(value); 297 } 298 299 RubyString newString = newString(getRuntime(), newBytes); 300 newString.setTaint(isTaint()); 301 return newString; 302 } 303 304 public IRubyObject format(IRubyObject arg) { 305 Object [] args; 307 IRubyObject[] rargs = null; 308 if (arg instanceof RubyArray) { 309 rargs = (IRubyObject[])((RubyArray)arg).getList().toArray(new IRubyObject[0]); 310 args = new Object [rargs.length]; 311 for(int i=0;i<rargs.length;i++) { 312 args[i] = JavaUtil.convertRubyToJava(rargs[i]); 313 } 314 } else { 315 args = new Object []{JavaUtil.convertRubyToJava(arg)}; 316 rargs = new IRubyObject[]{arg}; 317 } 318 return getRuntime().newString(new PrintfFormat(Locale.US, toString()).sprintf(args,rargs)); 319 } 320 321 public RubyFixnum hash() { 322 hashCode(); 323 return r_hash; 324 } 325 326 public int hashCode() { 327 if(!validHash) { 328 hash = value.hashCode(); 329 r_hash = getRuntime().newFixnum(hash); 330 validHash = true; 331 } 332 return hash; 333 } 334 335 public boolean equals(Object other) { 336 if (this == other) { 337 return true; 338 } 339 340 if (other instanceof RubyString) { 341 RubyString string = (RubyString)other; 342 343 if (string.value.equals(value)) { 344 return true; 345 } 346 } 347 348 return false; 349 } 350 351 private boolean sameAs(RubyString other) { 353 return value.equals(other.value); 354 } 355 356 359 public static RubyString objAsString(IRubyObject obj) { 360 if (obj instanceof RubyString) return (RubyString) obj; 361 362 IRubyObject str = obj.callMethod(obj.getRuntime().getCurrentContext(), "to_s"); 363 364 if (!(str instanceof RubyString)) return (RubyString) obj.anyToString(); 365 366 if (obj.isTaint()) str.setTaint(true); 367 368 return (RubyString) str; 369 } 370 371 374 public int cmp(RubyString other) { 375 return value.cmp(other.value); 376 } 377 378 381 public String asSymbol() { 382 return toString(); 383 } 384 385 386 392 public RubyString newString(CharSequence s) { 393 return new RubyString(getRuntime(), getType(), s); 394 } 395 396 402 public RubyString newString(ByteList s) { 403 return new RubyString(getRuntime(), getType(), s); 404 } 405 406 408 411 public static RubyString newString(Ruby runtime, CharSequence str) { 412 return new RubyString(runtime, str); 413 } 414 415 public static RubyString newString(Ruby runtime, byte[] bytes) { 416 return new RubyString(runtime, bytes); 417 } 418 419 public static RubyString newString(Ruby runtime, ByteList bytes) { 420 return new RubyString(runtime, bytes); 421 } 422 423 public static RubyString newString(Ruby runtime, byte[] bytes, int start, int length) { 424 byte[] bytes2 = new byte[length]; 425 System.arraycopy(bytes, start, bytes2, 0, length); 426 return new RubyString(runtime, bytes2); 427 } 428 429 public IRubyObject doClone(){ 430 return newString(getRuntime(), (ByteList)value.clone()); 431 } 432 433 public RubyString cat(byte[] str) { 434 value.append(str); 435 stringMutated(); 436 return this; 437 } 438 439 public RubyString cat(ByteList str) { 440 value.append(str); 441 stringMutated(); 442 return this; 443 } 444 445 public RubyString cat(byte ch) { 446 value.append(ch); 447 stringMutated(); 448 return this; 449 } 450 451 public IRubyObject to_str() { 452 if (getMetaClass().getRealClass() != getRuntime().getString()) { 453 return newString(getRuntime(), value.bytes()); 454 } 455 return this; 456 } 457 458 461 public RubyString replace(IRubyObject other) { 462 testFrozen("String"); 463 464 RubyString newValue = stringValue(other); 465 if (this == other || sameAs(newValue)) { 466 return this; 467 } 468 value.replace(newValue.value.bytes()); 469 stringMutated(); 470 return (RubyString) infectBy(newValue); 471 } 472 473 public RubyString reverse() { 474 return newString(getRuntime(), (ByteList)value.clone()).reverse_bang(); 475 } 476 477 public RubyString reverse_bang() { 478 for (int i = 0; i < (value.length() / 2); i++) { 479 byte b = (byte)value.get(i); 480 value.set(i, value.get(value.length() - i - 1)); 481 value.set(value.length() - i - 1, b); 482 } 483 stringMutated(); 484 return this; 485 } 486 487 490 public static RubyString newInstance(IRubyObject recv, IRubyObject[] args, Block block) { 491 RubyString newString = recv.getRuntime().newString(""); 492 newString.setMetaClass((RubyClass) recv); 493 newString.callInit(args, block); 494 return newString; 495 } 496 497 public IRubyObject initialize(IRubyObject[] args, Block unusedBlock) { 498 if (checkArgumentCount(args, 0, 1) == 1) { 499 replace(args[0]); 500 } 501 return this; 502 } 503 504 public IRubyObject casecmp(IRubyObject other) { 505 int compare = toString().compareToIgnoreCase(stringValue(other).toString()); 506 return RubyFixnum.newFixnum(getRuntime(), compare == 0 ? 0 : (compare < 0 ? -1 : 1)); 507 } 508 509 512 public IRubyObject match(IRubyObject other) { 513 if (other instanceof RubyRegexp) { 514 return ((RubyRegexp) other).match(this); 515 } else if (other instanceof RubyString) { 516 throw getRuntime().newTypeError("type mismatch: String given"); 517 } 518 return other.callMethod(getRuntime().getCurrentContext(), "=~", this); 519 } 520 521 524 public IRubyObject match2() { 525 return RubyRegexp.newRegexp(this, 0, null).match2(); 526 } 527 528 533 public IRubyObject match3(IRubyObject pattern) { 534 if (pattern instanceof RubyRegexp) { 535 return ((RubyRegexp)pattern).search2(toString()); 536 } else if (pattern instanceof RubyString) { 537 RubyRegexp regexp = RubyRegexp.newRegexp((RubyString) pattern, 0, null); 538 return regexp.search2(toString()); 539 } 540 541 return getRuntime().getNil(); 542 } 543 544 547 public IRubyObject capitalize() { 548 RubyString result = (RubyString) dup(); 549 result.capitalize_bang(); 550 return result; 551 } 552 553 556 public IRubyObject capitalize_bang() { 557 if (isEmpty()) { 558 return getRuntime().getNil(); 559 } 560 char capital = value.charAt(0); 561 boolean changed = false; 562 if (Character.isLetter(capital) && Character.isLowerCase(capital)) { 563 value.set(0, (byte)Character.toUpperCase(capital)); 564 changed = true; 565 } 566 567 for (int i = 1; i < value.length(); i++) { 568 capital = value.charAt(i); 569 if (Character.isLetter(capital) && Character.isUpperCase(capital)) { 570 value.set(i, (byte)Character.toLowerCase(capital)); 571 changed = true; 572 } 573 } 574 575 if (changed) { 576 stringMutated(); 577 return this; 578 } else { 579 return getRuntime().getNil(); 580 } 581 } 582 583 public IRubyObject op_ge(IRubyObject other) { 584 if (other instanceof RubyString) { 585 return getRuntime().newBoolean(cmp((RubyString) other) >= 0); 586 } 587 588 return RubyComparable.op_ge(this, other); 589 } 590 591 public IRubyObject op_gt(IRubyObject other) { 592 if (other instanceof RubyString) { 593 return getRuntime().newBoolean(cmp((RubyString) other) > 0); 594 } 595 596 return RubyComparable.op_gt(this, other); 597 } 598 599 public IRubyObject op_le(IRubyObject other) { 600 if (other instanceof RubyString) { 601 return getRuntime().newBoolean(cmp((RubyString) other) <= 0); 602 } 603 604 return RubyComparable.op_le(this, other); 605 } 606 607 public IRubyObject op_lt(IRubyObject other) { 608 if (other instanceof RubyString) { 609 return getRuntime().newBoolean(cmp((RubyString) other) < 0); 610 } 611 612 return RubyComparable.op_lt(this, other); 613 } 614 615 public IRubyObject op_eql(IRubyObject other) { 616 return equals(other) ? other.getRuntime().getTrue() : other.getRuntime().getFalse(); 617 } 618 619 622 public RubyString upcase() { 623 return newString(toString().toUpperCase()); 624 } 625 626 629 public IRubyObject upcase_bang() { 630 boolean changed = false; 631 for (int i = 0; i < value.length(); i++) { 632 char c = value.charAt(i); 633 if (!Character.isLetter(c) || Character.isUpperCase(c)) continue; 634 value.set(i, (byte)Character.toUpperCase(c)); 635 changed = true; 636 } 637 if (changed) { 638 stringMutated(); 639 return this; 640 } else { 641 return getRuntime().getNil(); 642 } 643 } 644 645 648 public RubyString downcase() { 649 return newString(toString().toLowerCase()); 650 } 651 652 655 public IRubyObject downcase_bang() { 656 boolean changed = false; 657 for (int i = 0; i < value.length(); i++) { 658 char c = value.charAt(i); 659 if (!Character.isLetter(c) || Character.isLowerCase(c)) continue; 660 value.set(i, (byte)Character.toLowerCase(c)); 661 changed = true; 662 } 663 if (changed) { 664 stringMutated(); 665 return this; 666 } else { 667 return getRuntime().getNil(); 668 } 669 } 670 671 674 public RubyString swapcase() { 675 RubyString newString = newString(getRuntime(), (ByteList)value.clone()); 676 IRubyObject swappedString = newString.swapcase_bang(); 677 678 return (RubyString) (swappedString.isNil() ? newString : swappedString); 679 } 680 681 684 public IRubyObject swapcase_bang() { 685 boolean changesMade = false; 686 687 for (int i = 0; i < value.length(); i++) { 688 char c = value.charAt(i); 689 690 if (!Character.isLetter(c)) { 691 continue; 692 } else if (Character.isLowerCase(c)) { 693 changesMade = true; 694 value.set(i, (byte)Character.toUpperCase(c)); 695 } else { 696 changesMade = true; 697 value.set(i, (byte)Character.toLowerCase(c)); 698 } 699 } 700 if (changesMade) { 701 stringMutated(); 702 return this; 703 } 704 return getRuntime().getNil(); 705 } 706 707 710 public RubyString dump() { 711 return inspect(true); 712 } 713 714 public IRubyObject insert(IRubyObject indexArg, IRubyObject stringArg) { 715 int index = (int) indexArg.convertToInteger().getLongValue(); 716 if (index < 0) { 717 index += value.length() + 1; 718 } 719 720 if (index < 0 || index > value.length()) { 721 throw getRuntime().newIndexError("index " + index + " out of range"); 722 } 723 724 ByteList insert = ((RubyString)stringArg.convertToString()).value; 725 value.unsafeReplace(index, 0, insert); 726 stringMutated(); 727 return this; 728 } 729 730 733 public IRubyObject inspect() { 734 return inspect(false); 735 } 736 737 private RubyString inspect(boolean dump) { 738 final int length = value.length(); 739 Ruby runtime = getRuntime(); 740 741 StringBuffer sb = new StringBuffer (length + 2 + length / 100); 742 743 sb.append('\"'); 744 745 for (int i = 0; i < length; i++) { 747 int c = value.get(i) & 0xFF; 748 if (isAlnum(c)) { 749 sb.append((char)c); 750 } else if (runtime.getKCode() == KCode.UTF8 && c == 0xEF) { 751 sb.append((char)c); 754 sb.append((char)(value.get(++i) & 0xFF)); 755 sb.append((char)(value.get(++i) & 0xFF)); 756 } else if (c == '\"' || c == '\\') { 757 sb.append('\\').append((char)c); 758 } else if (dump && c == '#') { 759 sb.append('\\').append((char)c); 760 } else if (isPrint(c)) { 761 sb.append((char)c); 762 } else if (c == '\n') { 763 sb.append('\\').append('n'); 764 } else if (c == '\r') { 765 sb.append('\\').append('r'); 766 } else if (c == '\t') { 767 sb.append('\\').append('t'); 768 } else if (c == '\f') { 769 sb.append('\\').append('f'); 770 } else if (c == '\u000B') { 771 sb.append('\\').append('v'); 772 } else if (c == '\u0007') { 773 sb.append('\\').append('a'); 774 } else if (c == '\u0008') { 775 sb.append('\\').append('b'); 777 } else if (c == '\u001B') { 778 sb.append('\\').append('e'); 779 } else { 780 sb.append(new PrintfFormat("\\%.3o").sprintf((char)c)); 781 } 782 } 783 784 sb.append('\"'); 785 return getRuntime().newString(sb.toString()); 786 } 787 788 791 public RubyFixnum length() { 792 return getRuntime().newFixnum(value.length()); 793 } 794 795 798 public RubyBoolean empty() { 799 return getRuntime().newBoolean(isEmpty()); 800 } 801 802 private boolean isEmpty() { 803 return value.length() == 0; 804 } 805 806 809 public RubyString append(IRubyObject other) { 810 infectBy(other); 811 return cat(stringValue(other).value); 812 } 813 814 817 public RubyString concat(IRubyObject other) { 818 if ((other instanceof RubyFixnum) && ((RubyFixnum) other).getLongValue() < 256) { 819 return cat((byte) ((RubyFixnum) other).getLongValue()); 820 } 821 return append(other); 822 } 823 824 827 public RubyString crypt(IRubyObject other) { 828 String salt = stringValue(other).getValue().toString(); 829 if(salt.length()<2) { 830 throw getRuntime().newArgumentError("salt too short(need >=2 bytes)"); 831 } 832 833 salt = salt.substring(0,2); 834 return getRuntime().newString(JavaCrypt.crypt(salt, this.toString())); 835 } 836 837 838 public static class JavaCrypt { 839 private static java.util.Random r_gen = new java.util.Random (); 840 841 private static final char theBaseSalts[] = { 842 'a','b','c','d','e','f','g','h','i','j','k','l','m', 843 'n','o','p','q','r','s','t','u','v','w','x','y','z', 844 'A','B','C','D','E','F','G','H','I','J','K','L','M', 845 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', 846 '0','1','2','3','4','5','6','7','8','9','/','.'}; 847 848 private static final int ITERATIONS = 16; 849 850 private static final int con_salt[] = { 851 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 852 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 853 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 854 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 855 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 856 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 857 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 858 0x0A, 0x0B, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 859 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 860 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 861 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 862 0x23, 0x24, 0x25, 0x20, 0x21, 0x22, 0x23, 0x24, 863 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 864 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 865 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 866 0x3D, 0x3E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 867 }; 868 869 private static final boolean shifts2[] = { 870 false, false, true, true, true, true, true, true, 871 false, true, true, true, true, true, true, false }; 872 873 private static final int skb[][] = { 874 { 875 876 0x00000000, 0x00000010, 0x20000000, 0x20000010, 877 0x00010000, 0x00010010, 0x20010000, 0x20010010, 878 0x00000800, 0x00000810, 0x20000800, 0x20000810, 879 0x00010800, 0x00010810, 0x20010800, 0x20010810, 880 0x00000020, 0x00000030, 0x20000020, 0x20000030, 881 0x00010020, 0x00010030, 0x20010020, 0x20010030, 882 0x00000820, 0x00000830, 0x20000820, 0x20000830, 883 0x00010820, 0x00010830, 0x20010820, 0x20010830, 884 0x00080000, 0x00080010, 0x20080000, 0x20080010, 885 0x00090000, 0x00090010, 0x20090000, 0x20090010, 886 0x00080800, 0x00080810, 0x20080800, 0x20080810, 887 0x00090800, 0x00090810, 0x20090800, 0x20090810, 888 0x00080020, 0x00080030, 0x20080020, 0x20080030, 889 0x00090020, 0x00090030, 0x20090020, 0x20090030, 890 0x00080820, 0x00080830, 0x20080820, 0x20080830, 891 0x00090820, 0x00090830, 0x20090820, 0x20090830, 892 },{ 893 894 0x00000000, 0x02000000, 0x00002000, 0x02002000, 895 0x00200000, 0x02200000, 0x00202000, 0x02202000, 896 0x00000004, 0x02000004, 0x00002004, 0x02002004, 897 0x00200004, 0x02200004, 0x00202004, 0x02202004, 898 0x00000400, 0x02000400, 0x00002400, 0x02002400, 899 0x00200400, 0x02200400, 0x00202400, 0x02202400, 900 0x00000404, 0x02000404, 0x00002404, 0x02002404, 901 0x00200404, 0x02200404, 0x00202404, 0x02202404, 902 0x10000000, 0x12000000, 0x10002000, 0x12002000, 903 0x10200000, 0x12200000, 0x10202000, 0x12202000, 904 0x10000004, 0x12000004, 0x10002004, 0x12002004, 905 0x10200004, 0x12200004, 0x10202004, 0x12202004, 906 0x10000400, 0x12000400, 0x10002400, 0x12002400, 907 0x10200400, 0x12200400, 0x10202400, 0x12202400, 908 0x10000404, 0x12000404, 0x10002404, 0x12002404, 909 0x10200404, 0x12200404, 0x10202404, 0x12202404, 910 },{ 911 912 0x00000000, 0x00000001, 0x00040000, 0x00040001, 913 0x01000000, 0x01000001, 0x01040000, 0x01040001, 914 0x00000002, 0x00000003, 0x00040002, 0x00040003, 915 0x01000002, 0x01000003, 0x01040002, 0x01040003, 916 0x00000200, 0x00000201, 0x00040200, 0x00040201, 917 0x01000200, 0x01000201, 0x01040200, 0x01040201, 918 0x00000202, 0x00000203, 0x00040202, 0x00040203, 919 0x01000202, 0x01000203, 0x01040202, 0x01040203, 920 0x08000000, 0x08000001, 0x08040000, 0x08040001, 921 0x09000000, 0x09000001, 0x09040000, 0x09040001, 922 0x08000002, 0x08000003, 0x08040002, 0x08040003, 923 0x09000002, 0x09000003, 0x09040002, 0x09040003, 924 0x08000200, 0x08000201, 0x08040200, 0x08040201, 925 0x09000200, 0x09000201, 0x09040200, 0x09040201, 926 0x08000202, 0x08000203, 0x08040202, 0x08040203, 927 0x09000202, 0x09000203, 0x09040202, 0x09040203, 928 },{ 929 930 0x00000000, 0x00100000, 0x00000100, 0x00100100, 931 0x00000008, 0x00100008, 0x00000108, 0x00100108, 932 0x00001000, 0x00101000, 0x00001100, 0x00101100, 933 0x00001008, 0x00101008, 0x00001108, 0x00101108, 934 0x04000000, 0x04100000, 0x04000100, 0x04100100, 935 0x04000008, 0x04100008, 0x04000108, 0x04100108, 936 0x04001000, 0x04101000, 0x04001100, 0x04101100, 937 0x04001008, 0x04101008, 0x04001108, 0x04101108, 938 0x00020000, 0x00120000, 0x00020100, 0x00120100, 939 0x00020008, 0x00120008, 0x00020108, 0x00120108, 940 0x00021000, 0x00121000, 0x00021100, 0x00121100, 941 0x00021008, 0x00121008, 0x00021108, 0x00121108, 942 0x04020000, 0x04120000, 0x04020100, 0x04120100, 943 0x04020008, 0x04120008, 0x04020108, 0x04120108, 944 0x04021000, 0x04121000, 0x04021100, 0x04121100, 945 0x04021008, 0x04121008, 0x04021108, 0x04121108, 946 },{ 947 948 0x00000000, 0x10000000, 0x00010000, 0x10010000, 949 0x00000004, 0x10000004, 0x00010004, 0x10010004, 950 0x20000000, 0x30000000, 0x20010000, 0x30010000, 951 0x20000004, 0x30000004, 0x20010004, 0x30010004, 952 0x00100000, 0x10100000, 0x00110000, 0x10110000, 953 0x00100004, 0x10100004, 0x00110004, 0x10110004, 954 0x20100000, 0x30100000, 0x20110000, 0x30110000, 955 0x20100004, 0x30100004, 0x20110004, 0x30110004, 956 0x00001000, 0x10001000, 0x00011000, 0x10011000, 957 0x00001004, 0x10001004, 0x00011004, 0x10011004, 958 0x20001000, 0x30001000, 0x20011000, 0x30011000, 959 0x20001004, 0x30001004, 0x20011004, 0x30011004, 960 0x00101000, 0x10101000, 0x00111000, 0x10111000, 961 0x00101004, 0x10101004, 0x00111004, 0x10111004, 962 0x20101000, 0x30101000, 0x20111000, 0x30111000, 963 0x20101004, 0x30101004, 0x20111004, 0x30111004, 964 },{ 965 966 0x00000000, 0x08000000, 0x00000008, 0x08000008, 967 0x00000400, 0x08000400, 0x00000408, 0x08000408, 968 0x00020000, 0x08020000, 0x00020008, 0x08020008, 969 0x00020400, 0x08020400, 0x00020408, 0x08020408, 970 0x00000001, 0x08000001, 0x00000009, 0x08000009, 971 0x00000401, 0x08000401, 0x00000409, 0x08000409, 972 0x00020001, 0x08020001, 0x00020009, 0x08020009, 973 0x00020401, 0x08020401, 0x00020409, 0x08020409, 974 0x02000000, 0x0A000000, 0x02000008, 0x0A000008, 975 0x02000400, 0x0A000400, 0x02000408, 0x0A000408, 976 0x02020000, 0x0A020000, 0x02020008, 0x0A020008, 977 0x02020400, 0x0A020400, 0x02020408, 0x0A020408, 978 0x02000001, 0x0A000001, 0x02000009, 0x0A000009, 979 0x02000401, 0x0A000401, 0x02000409, 0x0A000409, 980 0x02020001, 0x0A020001, 0x02020009, 0x0A020009, 981 0x02020401, 0x0A020401, 0x02020409, 0x0A020409, 982 },{ 983 984 0x00000000, 0x00000100, 0x00080000, 0x00080100, 985 0x01000000, 0x01000100, 0x01080000, 0x01080100, 986 0x00000010, 0x00000110, 0x00080010, 0x00080110, 987 0x01000010, 0x01000110, 0x01080010, 0x01080110, 988 0x00200000, 0x00200100, 0x00280000, 0x00280100, 989 0x01200000, 0x01200100, 0x01280000, 0x01280100, 990 0x00200010, 0x00200110, 0x00280010, 0x00280110, 991 0x01200010, 0x01200110, 0x01280010, 0x01280110, 992 0x00000200, 0x00000300, 0x00080200, 0x00080300, 993 0x01000200, 0x01000300, 0x01080200, 0x01080300, 994 0x00000210, 0x00000310, 0x00080210, 0x00080310, 995 0x01000210, 0x01000310, 0x01080210, 0x01080310, 996 0x00200200, 0x00200300, 0x00280200, 0x00280300, 997 0x01200200, 0x01200300, 0x01280200, 0x01280300, 998 0x00200210, 0x00200310, 0x00280210, 0x00280310, 999 0x01200210, 0x01200310, 0x01280210, 0x01280310, 1000 },{ 1001 1002 0x00000000, 0x04000000, 0x00040000, 0x04040000, 1003 0x00000002, 0x04000002, 0x00040002, 0x04040002, 1004 0x00002000, 0x04002000, 0x00042000, 0x04042000, 1005 0x00002002, 0x04002002, 0x00042002, 0x04042002, 1006 0x00000020, 0x04000020, 0x00040020, 0x04040020, 1007 0x00000022, 0x04000022, 0x00040022, 0x04040022, 1008 0x00002020, 0x04002020, 0x00042020, 0x04042020, 1009 0x00002022, 0x04002022, 0x00042022, 0x04042022, 1010 0x00000800, 0x04000800, 0x00040800, 0x04040800, 1011 0x00000802, 0x04000802, 0x00040802, 0x04040802, 1012 0x00002800, 0x04002800, 0x00042800, 0x04042800, 1013 0x00002802, 0x04002802, 0x00042802, 0x04042802, 1014 0x00000820, 0x04000820, 0x00040820, 0x04040820, 1015 0x00000822, 0x04000822, 0x00040822, 0x04040822, 1016 0x00002820, 0x04002820, 0x00042820, 0x04042820, 1017 0x00002822, 0x04002822, 0x00042822, 0x04042822, 1018 } 1019 }; 1020 1021 private static final int SPtrans[][] = { 1022 { 1023 1024 0x00820200, 0x00020000, 0x80800000, 0x80820200, 1025 0x00800000, 0x80020200, 0x80020000, 0x80800000, 1026 0x80020200, 0x00820200, 0x00820000, 0x80000200, 1027 0x80800200, 0x00800000, 0x00000000, 0x80020000, 1028 0x00020000, 0x80000000, 0x00800200, 0x00020200, 1029 0x80820200, 0x00820000, 0x80000200, 0x00800200, 1030 0x80000000, 0x00000200, 0x00020200, 0x80820000, 1031 0x00000200, 0x80800200, 0x80820000, 0x00000000, 1032 0x00000000, 0x80820200, 0x00800200, 0x80020000, 1033 0x00820200, 0x00020000, 0x80000200, 0x00800200, 1034 0x80820000, 0x00000200, 0x00020200, 0x80800000, 1035 0x80020200, 0x80000000, 0x80800000, 0x00820000, 1036 0x80820200, 0x00020200, 0x00820000, 0x80800200, 1037 0x00800000, 0x80000200, 0x80020000, 0x00000000, 1038 0x00020000, 0x00800000, 0x80800200, 0x00820200, 1039 0x80000000, 0x80820000, 0x00000200, 0x80020200, 1040 },{ 1041 1042 0x10042004, 0x00000000, 0x00042000, 0x10040000, 1043 0x10000004, 0x00002004, 0x10002000, 0x00042000, 1044 0x00002000, 0x10040004, 0x00000004, 0x10002000, 1045 0x00040004, 0x10042000, 0x10040000, 0x00000004, 1046 0x00040000, 0x10002004, 0x10040004, 0x00002000, 1047 0x00042004, 0x10000000, 0x00000000, 0x00040004, 1048 0x10002004, 0x00042004, 0x10042000, 0x10000004, 1049 0x10000000, 0x00040000, 0x00002004, 0x10042004, 1050 0x00040004, 0x10042000, 0x10002000, 0x00042004, 1051 0x10042004, 0x00040004, 0x10000004, 0x00000000, 1052 0x10000000, 0x00002004, 0x00040000, 0x10040004, 1053 0x00002000, 0x10000000, 0x00042004, 0x10002004, 1054 0x10042000, 0x00002000, 0x00000000, 0x10000004, 1055 0x00000004, 0x10042004, 0x00042000, 0x10040000, 1056 0x10040004, 0x00040000, 0x00002004, 0x10002000, 1057 0x10002004, 0x00000004, 0x10040000, 0x00042000, 1058 },{ 1059 1060 0x41000000, 0x01010040, 0x00000040, 0x41000040, 1061 0x40010000, 0x01000000, 0x41000040, 0x00010040, 1062 0x01000040, 0x00010000, 0x01010000, 0x40000000, 1063 0x41010040, 0x40000040, 0x40000000, 0x41010000, 1064 0x00000000, 0x40010000, 0x01010040, 0x00000040, 1065 0x40000040, 0x41010040, 0x00010000, 0x41000000, 1066 0x41010000, 0x01000040, 0x40010040, 0x01010000, 1067 0x00010040, 0x00000000, 0x01000000, 0x40010040, 1068 0x01010040, 0x00000040, 0x40000000, 0x00010000, 1069 0x40000040, 0x40010000, 0x01010000, 0x41000040, 1070 0x00000000, 0x01010040, 0x00010040, 0x41010000, 1071 0x40010000, 0x01000000, 0x41010040, 0x40000000, 1072 0x40010040, 0x41000000, 0x01000000, 0x41010040, 1073 0x00010000, 0x01000040, 0x41000040, 0x00010040, 1074 0x01000040, 0x00000000, 0x41010000, 0x40000040, 1075 0x41000000, 0x40010040, 0x00000040, 0x01010000, 1076 },{ 1077 1078 0x00100402, 0x04000400, 0x00000002, 0x04100402, 1079 0x00000000, 0x04100000, 0x04000402, 0x00100002, 1080 0x04100400, 0x04000002, 0x04000000, 0x00000402, 1081 0x04000002, 0x00100402, 0x00100000, 0x04000000, 1082 0x04100002, 0x00100400, 0x00000400, 0x00000002, 1083 0x00100400, 0x04000402, 0x04100000, 0x00000400, 1084 0x00000402, 0x00000000, 0x00100002, 0x04100400, 1085 0x04000400, 0x04100002, 0x04100402, 0x00100000, 1086 0x04100002, 0x00000402, 0x00100000, 0x04000002, 1087 0x00100400, 0x04000400, 0x00000002, 0x04100000, 1088 0x04000402, 0x00000000, 0x00000400, 0x00100002, 1089 0x00000000, 0x04100002, 0x04100400, 0x00000400, 1090 0x04000000, 0x04100402, 0x00100402, 0x00100000, 1091 0x04100402, 0x00000002, 0x04000400, 0x00100402, 1092 0x00100002, 0x00100400, 0x04100000, 0x04000402, 1093 0x00000402, 0x04000000, 0x04000002, 0x04100400, 1094 },{ 1095 1096 0x02000000, 0x00004000, 0x00000100, 0x02004108, 1097 0x02004008, 0x02000100, 0x00004108, 0x02004000, 1098 0x00004000, 0x00000008, 0x02000008, 0x00004100, 1099 0x02000108, 0x02004008, 0x02004100, 0x00000000, 1100 0x00004100, 0x02000000, 0x00004008, 0x00000108, 1101 0x02000100, 0x00004108, 0x00000000, 0x02000008, 1102 0x00000008, 0x02000108, 0x02004108, 0x00004008, 1103 0x02004000, 0x00000100, 0x00000108, 0x02004100, 1104 0x02004100, 0x02000108, 0x00004008, 0x02004000, 1105 0x00004000, 0x00000008, 0x02000008, 0x02000100, 1106 0x02000000, 0x00004100, 0x02004108, 0x00000000, 1107 0x00004108, 0x02000000, 0x00000100, 0x00004008, 1108 0x02000108, 0x00000100, 0x00000000, 0x02004108, 1109 0x02004008, 0x02004100, 0x00000108, 0x00004000, 1110 0x00004100, 0x02004008, 0x02000100, 0x00000108, 1111 0x00000008, 0x00004108, 0x02004000, 0x02000008, 1112 },{ 1113 1114 0x20000010, 0x00080010, 0x00000000, 0x20080800, 1115 0x00080010, 0x00000800, 0x20000810, 0x00080000, 1116 0x00000810, 0x20080810, 0x00080800, 0x20000000, 1117 0x20000800, 0x20000010, 0x20080000, 0x00080810, 1118 0x00080000, 0x20000810, 0x20080010, 0x00000000, 1119 0x00000800, 0x00000010, 0x20080800, 0x20080010, 1120 0x20080810, 0x20080000, 0x20000000, 0x00000810, 1121 0x00000010, 0x00080800, 0x00080810, 0x20000800, 1122 0x00000810, 0x20000000, 0x20000800, 0x00080810, 1123 0x20080800, 0x00080010, 0x00000000, 0x20000800, 1124 0x20000000, 0x00000800, 0x20080010, 0x00080000, 1125 0x00080010, 0x20080810, 0x00080800, 0x00000010, 1126 0x20080810, 0x00080800, 0x00080000, 0x20000810, 1127 0x20000010, 0x20080000, 0x00080810, 0x00000000, 1128 0x00000800, 0x20000010, 0x20000810, 0x20080800, 1129 0x20080000, 0x00000810, 0x00000010, 0x20080010, 1130 },{ 1131 1132 0x00001000, 0x00000080, 0x00400080, 0x00400001, 1133 0x00401081, 0x00001001, 0x00001080, 0x00000000, 1134 0x00400000, 0x00400081, 0x00000081, 0x00401000, 1135 0x00000001, 0x00401080, 0x00401000, 0x00000081, 1136 0x00400081, 0x00001000, 0x00001001, 0x00401081, 1137 0x00000000, 0x00400080, 0x00400001, 0x00001080, 1138 0x00401001, 0x00001081, 0x00401080, 0x00000001, 1139 0x00001081, 0x00401001, 0x00000080, 0x00400000, 1140 0x00001081, 0x00401000, 0x00401001, 0x00000081, 1141 0x00001000, 0x00000080, 0x00400000, 0x00401001, 1142 0x00400081, 0x00001081, 0x00001080, 0x00000000, 1143 0x00000080, 0x00400001, 0x00000001, 0x00400080, 1144 0x00000000, 0x00400081, 0x00400080, 0x00001080, 1145 0x00000081, 0x00001000, 0x00401081, 0x00400000, 1146 0x00401080, 0x00000001, 0x00001001, 0x00401081, 1147 0x00400001, 0x00401080, 0x00401000, 0x00001001, 1148 },{ 1149 1150 0x08200020, 0x08208000, 0x00008020, 0x00000000, 1151 0x08008000, 0x00200020, 0x08200000, 0x08208020, 1152 0x00000020, 0x08000000, 0x00208000, 0x00008020, 1153 0x00208020, 0x08008020, 0x08000020, 0x08200000, 1154 0x00008000, 0x00208020, 0x00200020, 0x08008000, 1155 0x08208020, 0x08000020, 0x00000000, 0x00208000, 1156 0x08000000, 0x00200000, 0x08008020, 0x08200020, 1157 0x00200000, 0x00008000, 0x08208000, 0x00000020, 1158 0x00200000, 0x00008000, 0x08000020, 0x08208020, 1159 0x00008020, 0x08000000, 0x00000000, 0x00208000, 1160 0x08200020, 0x08008020, 0x08008000, 0x00200020, 1161 0x08208000, 0x00000020, 0x00200020, 0x08008000, 1162 0x08208020, 0x00200000, 0x08200000, 0x08000020, 1163 0x00208000, 0x00008020, 0x08008020, 0x08200000, 1164 0x00000020, 0x08208000, 0x00208020, 0x00000000, 1165 0x08000000, 0x08200020, 0x00008000, 0x00208020 1166 } 1167 }; 1168 1169 private static final int cov_2char[] = { 1170 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 1171 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 1172 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 1173 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 1174 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 1175 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 1176 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 1177 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A 1178 }; 1179 1180 private static final int byteToUnsigned(byte b) { 1181 return b & 0xFF; 1182 } 1183 1184 private static int fourBytesToInt(byte b[], int offset) { 1185 int value; 1186 value = byteToUnsigned(b[offset++]); 1187 value |= (byteToUnsigned(b[offset++]) << 8); 1188 value |= (byteToUnsigned(b[offset++]) << 16); 1189 value |= (byteToUnsigned(b[offset++]) << 24); 1190 return(value); 1191 } 1192 1193 private static final void intToFourBytes(int iValue, byte b[], int offset) { 1194 b[offset++] = (byte)((iValue) & 0xff); 1195 b[offset++] = (byte)((iValue >>> 8 ) & 0xff); 1196 b[offset++] = (byte)((iValue >>> 16) & 0xff); 1197 b[offset++] = (byte)((iValue >>> 24) & 0xff); 1198 } 1199 1200 private static final void PERM_OP(int a, int b, int n, int m, int results[]) { 1201 int t; 1202 1203 t = ((a >>> n) ^ b) & m; 1204 a ^= t << n; 1205 b ^= t; 1206 1207 results[0] = a; 1208 results[1] = b; 1209 } 1210 1211 private static final int HPERM_OP(int a, int n, int m) { 1212 int t; 1213 1214 t = ((a << (16 - n)) ^ a) & m; 1215 a = a ^ t ^ (t >>> (16 - n)); 1216 1217 return(a); 1218 } 1219 1220 private static int [] des_set_key(byte key[]) { 1221 int schedule[] = new int[ITERATIONS * 2]; 1222 1223 int c = fourBytesToInt(key, 0); 1224 int d = fourBytesToInt(key, 4); 1225 1226 int results[] = new int[2]; 1227 1228 PERM_OP(d, c, 4, 0x0f0f0f0f, results); 1229 d = results[0]; c = results[1]; 1230 1231 c = HPERM_OP(c, -2, 0xcccc0000); 1232 d = HPERM_OP(d, -2, 0xcccc0000); 1233 1234 PERM_OP(d, c, 1, 0x55555555, results); 1235 d = results[0]; c = results[1]; 1236 1237 PERM_OP(c, d, 8, 0x00ff00ff, results); 1238 c = results[0]; d = results[1]; 1239 1240 PERM_OP(d, c, 1, 0x55555555, results); 1241 d = results[0]; c = results[1]; 1242 1243 d = (((d & 0x000000ff) << 16) | (d & 0x0000ff00) | 1244 ((d & 0x00ff0000) >>> 16) | ((c & 0xf0000000) >>> 4)); 1245 c &= 0x0fffffff; 1246 1247 int s, t; 1248 int j = 0; 1249 1250 for(int i = 0; i < ITERATIONS; i ++) { 1251 if(shifts2[i]) { 1252 c = (c >>> 2) | (c << 26); 1253 d = (d >>> 2) | (d << 26); 1254 } else { 1255 c = (c >>> 1) | (c << 27); 1256 d = (d >>> 1) | (d << 27); 1257 } 1258 1259 c &= 0x0fffffff; 1260 d &= 0x0fffffff; 1261 1262 s = skb[0][ (c ) & 0x3f ]| 1263 skb[1][((c >>> 6) & 0x03) | ((c >>> 7) & 0x3c)]| 1264 skb[2][((c >>> 13) & 0x0f) | ((c >>> 14) & 0x30)]| 1265 skb[3][((c >>> 20) & 0x01) | ((c >>> 21) & 0x06) | 1266 ((c >>> 22) & 0x38)]; 1267 1268 t = skb[4][ (d ) & 0x3f ]| 1269 skb[5][((d >>> 7) & 0x03) | ((d >>> 8) & 0x3c)]| 1270 skb[6][ (d >>>15) & 0x3f ]| 1271 skb[7][((d >>>21) & 0x0f) | ((d >>> 22) & 0x30)]; 1272 1273 schedule[j++] = ((t << 16) | (s & 0x0000ffff)) & 0xffffffff; 1274 s = ((s >>> 16) | (t & 0xffff0000)); 1275 1276 s = (s << 4) | (s >>> 28); 1277 schedule[j++] = s & 0xffffffff; 1278 } 1279 return(schedule); 1280 } 1281 1282 private static final int D_ENCRYPT(int L, int R, int S, int E0, int E1, int s[]) { 1283 int t, u, v; 1284 1285 v = R ^ (R >>> 16); 1286 u = v & E0; 1287 v = v & E1; 1288 u = (u ^ (u << 16)) ^ R ^ s[S]; 1289 t = (v ^ (v << 16)) ^ R ^ s[S + 1]; 1290 t = (t >>> 4) | (t << 28); 1291 1292 L ^= SPtrans[1][(t ) & 0x3f] | 1293 SPtrans[3][(t >>> 8) & 0x3f] | 1294 SPtrans[5][(t >>> 16) & 0x3f] | 1295 SPtrans[7][(t >>> 24) & 0x3f] | 1296 SPtrans[0][(u ) & 0x3f] | 1297 SPtrans[2][(u >>> 8) & 0x3f] | 1298 SPtrans[4][(u >>> 16) & 0x3f] | 1299 SPtrans[6][(u >>> 24) & 0x3f]; 1300 1301 return(L); 1302 } 1303 1304 private static final int [] body(int schedule[], int Eswap0, int Eswap1) { 1305 int left = 0; 1306 int right = 0; 1307 int t = 0; 1308 1309 for(int j = 0; j < 25; j ++) { 1310 for(int i = 0; i < ITERATIONS * 2; i += 4) { 1311 left = D_ENCRYPT(left, right, i, Eswap0, Eswap1, schedule); 1312 right = D_ENCRYPT(right, left, i + 2, Eswap0, Eswap1, schedule); 1313 } 1314 t = left; 1315 left = right; 1316 right = t; 1317 } 1318 1319 t = right; 1320 1321 right = (left >>> 1) | (left << 31); 1322 left = (t >>> 1) | (t << 31); 1323 1324 left &= 0xffffffff; 1325 right &= 0xffffffff; 1326 1327 int results[] = new int[2]; 1328 1329 PERM_OP(right, left, 1, 0x55555555, results); 1330 right = results[0]; left = results[1]; 1331 1332 PERM_OP(left, right, 8, 0x00ff00ff, results); 1333 left = results[0]; right = results[1]; 1334 1335 PERM_OP(right, left, 2, 0x33333333, results); 1336 right = results[0]; left = results[1]; 1337 1338 PERM_OP(left, right, 16, 0x0000ffff, results); 1339 left = results[0]; right = results[1]; 1340 1341 PERM_OP(right, left, 4, 0x0f0f0f0f, results); 1342 right = results[0]; left = results[1]; 1343 1344 int out[] = new int[2]; 1345 1346 out[0] = left; out[1] = right; 1347 1348 return(out); 1349 } 1350 1351 public static final String crypt(String salt, String original) { 1352 while(salt.length() < 2) 1353 salt += getSaltChar(); 1354 1355 StringBuffer buffer = new StringBuffer (" "); 1356 1357 char charZero = salt.charAt(0); 1358 char charOne = salt.charAt(1); 1359 1360 buffer.setCharAt(0, charZero); 1361 buffer.setCharAt(1, charOne); 1362 1363 int Eswap0 = con_salt[(int)charZero]; 1364 int Eswap1 = con_salt[(int)charOne] << 4; 1365 1366 byte key[] = new byte[8]; 1367 1368 for(int i = 0; i < key.length; i ++) { 1369 key[i] = (byte)0; 1370 } 1371 1372 for(int i = 0; i < key.length && i < original.length(); i ++) { 1373 int iChar = (int)original.charAt(i); 1374 1375 key[i] = (byte)(iChar << 1); 1376 } 1377 1378 int schedule[] = des_set_key(key); 1379 int out[] = body(schedule, Eswap0, Eswap1); 1380 1381 byte b[] = new byte[9]; 1382 1383 intToFourBytes(out[0], b, 0); 1384 intToFourBytes(out[1], b, 4); 1385 b[8] = 0; 1386 1387 for(int i = 2, y = 0, u = 0x80; i < 13; i ++) { 1388 for(int j = 0, c = 0; j < 6; j ++) { 1389 c <<= 1; 1390 1391 if(((int)b[y] & u) != 0) 1392 c |= 1; 1393 1394 u >>>= 1; 1395 1396 if(u == 0) { 1397 y++; 1398 u = 0x80; 1399 } 1400 buffer.setCharAt(i, (char)cov_2char[c]); 1401 } 1402 } 1403 return(buffer.toString()); 1404 } 1405 1406 private static String getSaltChar() { 1407 return JavaCrypt.getSaltChar(1); 1408 } 1409 1410 private static String getSaltChar(int amount) { 1411 StringBuffer sb = new StringBuffer (); 1412 for(int i=amount;i>0;i--) { 1413 sb.append(theBaseSalts[(Math.abs(r_gen.nextInt())%64)]); 1414 } 1415 return sb.toString(); 1416 } 1417 1418 public static boolean check(String theClear,String theCrypt) { 1419 String theTest = JavaCrypt.crypt(theCrypt.substring(0,2),theClear); 1420 return theTest.equals(theCrypt); 1421 } 1422 1423 public static String crypt(String theClear) { 1424 return JavaCrypt.crypt(getSaltChar(2),theClear); 1425 } 1426 } 1427 1428 1429 public static RubyString stringValue(IRubyObject object) { 1430 return (RubyString) (object instanceof RubyString ? object : 1431 object.convertType(RubyString.class, "String", "to_str")); 1432 } 1433 1434 1437 public IRubyObject sub(IRubyObject[] args, Block block) { 1438 return sub(args, false, block); 1439 } 1440 1441 1444 public IRubyObject sub_bang(IRubyObject[] args, Block block) { 1445 return sub(args, true, block); 1446 } 1447 1448 private IRubyObject sub(IRubyObject[] args, boolean bang, Block block) { 1449 IRubyObject repl = getRuntime().getNil(); 1450 boolean iter = false; 1451 ThreadContext tc = getRuntime().getCurrentContext(); 1452 1453 if (args.length == 1 && block.isGiven()) { 1454 iter = true; 1455 } else if (args.length == 2) { 1456 repl = args[1]; 1457 } else { 1458 throw getRuntime().newArgumentError("wrong number of arguments"); 1459 } 1460 RubyRegexp pat = RubyRegexp.regexpValue(args[0]); 1461 1462 String intern = toString(); 1463 boolean utf8 = pat.getCode() == KCode.UTF8; 1464 1465 if(utf8) { 1466 try { 1467 intern = new String (ByteList.plain(intern),"UTF8"); 1468 } catch(Exception e) { 1469 } 1470 } 1471 1472 if (pat.search(intern, 0) >= 0) { 1473 RubyMatchData match = (RubyMatchData) tc.getBackref(); 1474 RubyString newStr = match.pre_match(); 1475 newStr.append(iter ? tc.yield(match.group(0), block) : pat.regsub(repl, match)); 1476 newStr.append(match.post_match()); 1477 newStr.setTaint(isTaint() || repl.isTaint()); 1478 if(utf8) { 1479 try { 1480 newStr.setValue(new String (ByteList.plain(newStr.toString().getBytes("UTF8")))); 1481 } catch(Exception e) { 1482 } 1483 } 1484 if (bang) { 1485 value = newStr.value; 1486 stringMutated(); 1487 return this; 1488 } 1489 1490 return newStr; 1491 } 1492 1493 return bang ? getRuntime().getNil() : this; 1494 } 1495 1496 1499 public IRubyObject gsub(IRubyObject[] args, Block block) { 1500 return gsub(args, false, block); 1501 } 1502 1503 1506 public IRubyObject gsub_bang(IRubyObject[] args, Block block) { 1507 return gsub(args, true, block); 1508 } 1509 1510 private IRubyObject gsub(IRubyObject[] args, boolean bang, Block block) { 1511 IRubyObject repl = getRuntime().getNil(); 1513 RubyMatchData match; 1514 boolean iter = false; 1515 if (args.length == 1 && block.isGiven()) { 1516 iter = true; 1517 } else if (args.length == 2) { 1518 repl = args[1]; 1519 } else { 1520 throw getRuntime().newArgumentError("wrong number of arguments"); 1521 } 1522 boolean taint = repl.isTaint(); 1523 RubyRegexp pat = RubyRegexp.regexpValue(args[0]); 1524 1525 String str = toString(); 1526 int beg = pat.search(str, 0); 1527 if (beg < 0) { 1528 return bang ? getRuntime().getNil() : dup(); 1529 } 1530 ByteList sbuf = new ByteList(this.value.length()); 1531 IRubyObject newStr; 1532 int offset = 0; 1533 1534 ThreadContext tc = getRuntime().getCurrentContext(); 1537 1538 if(iter) { 1539 while (beg >= 0) { 1540 match = (RubyMatchData) tc.getBackref(); 1541 sbuf.append(this.value,offset,beg-offset); 1542 newStr = tc.yield(match.group(0), block); 1543 taint |= newStr.isTaint(); 1544 sbuf.append(newStr.objAsString().getByteList()); 1545 offset = match.matchEndPosition(); 1546 beg = pat.search(str, offset == beg ? beg + 1 : offset); 1547 } 1548 } else { 1549 RubyString r = stringValue(repl); 1550 while (beg >= 0) { 1551 match = (RubyMatchData) tc.getBackref(); 1552 sbuf.append(this.value,offset,beg-offset); 1553 pat.regsub(r, match, sbuf); 1554 offset = match.matchEndPosition(); 1555 beg = pat.search(str, offset == beg ? beg + 1 : offset); 1556 } 1557 } 1558 1559 sbuf.append(this.value,offset,this.value.length()-offset); 1560 1561 if (bang) { 1562 setTaint(isTaint() || taint); 1563 setValue(sbuf); 1564 return this; 1565 } 1566 RubyString result = newString(sbuf); 1567 result.setTaint(isTaint() || taint); 1568 return result; 1569 } 1570 1571 1574 public IRubyObject index(IRubyObject[] args) { 1575 return index(args, false); 1576 } 1577 1578 1581 public IRubyObject rindex(IRubyObject[] args) { 1582 return index(args, true); 1583 } 1584 1585 1588 private IRubyObject index(IRubyObject[] args, boolean reverse) { 1589 int pos = 0; 1591 if (reverse) { 1592 pos = value.length(); 1593 } 1594 if (checkArgumentCount(args, 1, 2) == 2) { 1595 pos = RubyNumeric.fix2int(args[1]); 1596 } 1597 if (pos < 0) { 1598 pos += value.length(); 1599 if (pos < 0) { 1600 return getRuntime().getNil(); 1601 } 1602 } 1603 if (args[0] instanceof RubyRegexp) { 1604 int doNotLookPastIfReverse = pos; 1605 1606 pos = ((RubyRegexp) args[0]).search(toString(), reverse ? 0 : pos); 1610 1611 int dummy = pos; 1612 while (reverse && dummy > -1 && dummy <= doNotLookPastIfReverse) { 1613 pos = dummy; 1614 dummy = ((RubyRegexp) args[0]).search(toString(), pos + 1); 1615 } 1616 } else if (args[0] instanceof RubyString) { 1617 String sub = ((RubyString) args[0]).toString(); 1618 StringBuffer sb = new StringBuffer (toString()); 1619 pos = reverse ? sb.lastIndexOf(sub, pos) : sb.indexOf(sub, pos); 1620 } else if (args[0] instanceof RubyFixnum) { 1621 char c = (char) ((RubyFixnum) args[0]).getLongValue(); 1622 pos = reverse ? toString().lastIndexOf(c, pos) : toString().indexOf(c, pos); 1623 } else { 1624 throw getRuntime().newArgumentError("wrong type of argument"); 1625 } 1626 1627 return pos == -1 ? getRuntime().getNil() : getRuntime().newFixnum(pos); 1628 } 1629 1630 1631 public IRubyObject substr(int beg, int len) { 1632 int length = value.length(); 1633 if (len < 0 || beg > length) { 1634 return getRuntime().getNil(); 1635 } 1636 if (beg < 0) { 1637 beg += length; 1638 if (beg < 0) { 1639 return getRuntime().getNil(); 1640 } 1641 } 1642 int end = Math.min(length, beg + len); 1643 ByteList newValue = new ByteList(value, beg, end - beg); 1644 return newString(getRuntime(), newValue).infectBy(this); 1645 } 1646 1647 1648 public IRubyObject replace(int beg, int len, RubyString replaceWith) { 1649 if (beg + len >= value.length()) { 1650 len = value.length() - beg; 1651 } 1652 1653 value.unsafeReplace(beg,len,replaceWith.value); 1654 stringMutated(); 1655 return infectBy(replaceWith); 1656 } 1657 1658 1661 public IRubyObject aref(IRubyObject[] args) { 1662 if (checkArgumentCount(args, 1, 2) == 2) { 1663 if (args[0] instanceof RubyRegexp) { 1664 IRubyObject match = RubyRegexp.regexpValue(args[0]).match(toString(), 0); 1665 long idx = args[1].convertToInteger().getLongValue(); 1666 getRuntime().getCurrentContext().setBackref(match); 1667 return RubyRegexp.nth_match((int) idx, match); 1668 } 1669 return substr(RubyNumeric.fix2int(args[0]), RubyNumeric.fix2int(args[1])); 1670 } 1671 1672 if (args[0] instanceof RubyRegexp) { 1673 return RubyRegexp.regexpValue(args[0]).search(toString(), 0) >= 0 ? 1674 RubyRegexp.last_match(getRuntime().getCurrentContext().getBackref()) : 1675 getRuntime().getNil(); 1676 } else if (args[0] instanceof RubyString) { 1677 return toString().indexOf(stringValue(args[0]).toString()) != -1 ? 1678 args[0] : getRuntime().getNil(); 1679 } else if (args[0] instanceof RubyRange) { 1680 long[] begLen = ((RubyRange) args[0]).getBeginLength(value.length(), true, false); 1681 return begLen == null ? getRuntime().getNil() : 1682 substr((int) begLen[0], (int) begLen[1]); 1683 } 1684 int idx = (int) args[0].convertToInteger().getLongValue(); 1685 if (idx < 0) { 1686 idx += value.length(); 1687 } 1688 if (idx < 0 || idx >= value.length()) { 1689 return getRuntime().getNil(); 1690 } else { 1691 RubyFixnum result = getRuntime().newFixnum(value.get(idx) & 0xFF); 1692 return result; 1693 } 1694 } 1695 1696 1700 private void subpatSet(RubyRegexp regexp, int nth, IRubyObject repl) { 1701 int found = regexp.search(this.toString(), 0); 1702 if (found == -1) { 1703 throw getRuntime().newIndexError("regexp not matched"); 1704 } 1705 1706 RubyMatchData match = (RubyMatchData) getRuntime().getCurrentContext() 1707 .getBackref(); 1708 1709 if (nth >= match.getSize()) { 1710 throw getRuntime().newIndexError("index " + nth + " out of regexp"); 1711 } 1712 if (nth < 0) { 1713 if (-nth >= match.getSize()) { 1714 throw getRuntime().newIndexError("index " + nth + " out of regexp"); 1715 } 1716 nth += match.getSize(); 1717 } 1718 1719 IRubyObject group = match.group(nth); 1720 if (getRuntime().getNil().equals(group)) { 1721 throw getRuntime().newIndexError( 1722 "regexp group " + nth + " not matched"); 1723 } 1724 1725 int beg = (int) match.begin(nth); 1726 int len = (int) (match.end(nth) - beg); 1727 1728 replace(beg, len, stringValue(repl)); 1729 1730 } 1731 1732 1735 public IRubyObject aset(IRubyObject[] args) { 1736 testFrozen("class"); 1737 int strLen = value.length(); 1738 if (checkArgumentCount(args, 2, 3) == 3) { 1739 if (args[0] instanceof RubyFixnum) { 1740 RubyString repl = stringValue(args[2]); 1741 int beg = RubyNumeric.fix2int(args[0]); 1742 int len = RubyNumeric.fix2int(args[1]); 1743 if (len < 0) { 1744 throw getRuntime().newIndexError("negative length"); 1745 } 1746 if (beg < 0) { 1747 beg += strLen; 1748 } 1749 if (beg < 0 || (beg > 0 && beg >= strLen)) { 1750 throw getRuntime().newIndexError( 1751 "string index out of bounds"); 1752 } 1753 if (beg + len > strLen) { 1754 len = strLen - beg; 1755 } 1756 replace(beg, len, repl); 1757 return repl; 1758 } 1759 if (args[0] instanceof RubyRegexp) { 1760 RubyString repl = stringValue(args[2]); 1761 int nth = RubyNumeric.fix2int(args[1]); 1762 subpatSet((RubyRegexp) args[0], nth, repl); 1763 return repl; 1764 } 1765 } 1766 if (args[0] instanceof RubyFixnum) { int idx = RubyNumeric.fix2int(args[0]); if (idx < 0) { 1769 idx += value.length(); 1770 } 1771 if (idx < 0 || idx >= value.length()) { 1772 throw getRuntime().newIndexError("string index out of bounds"); 1773 } 1774 if (args[1] instanceof RubyFixnum) { 1775 value.set(idx, (byte) RubyNumeric.fix2int(args[1])); 1776 stringMutated(); 1777 } else { 1778 replace(idx, 1, stringValue(args[1])); 1779 } 1780 return args[1]; 1781 } 1782 if (args[0] instanceof RubyRegexp) { 1783 sub_bang(args, null); 1784 return args[1]; 1785 } 1786 if (args[0] instanceof RubyString) { 1787 RubyString orig = stringValue(args[0]); 1788 int beg = toString().indexOf(orig.toString()); 1789 if (beg != -1) { 1790 replace(beg, orig.value.length(), stringValue(args[1])); 1791 } 1792 return args[1]; 1793 } 1794 if (args[0] instanceof RubyRange) { 1795 long[] idxs = ((RubyRange) args[0]).getBeginLength(value.length(), true, true); 1796 replace((int) idxs[0], (int) idxs[1], stringValue(args[1])); 1797 return args[1]; 1798 } 1799 throw getRuntime().newTypeError("wrong argument type"); 1800 } 1801 1802 1805 public IRubyObject slice_bang(IRubyObject[] args) { 1806 int argc = checkArgumentCount(args, 1, 2); 1807 IRubyObject[] newArgs = new IRubyObject[argc + 1]; 1808 newArgs[0] = args[0]; 1809 if (argc > 1) { 1810 newArgs[1] = args[1]; 1811 } 1812 newArgs[argc] = newString(""); 1813 IRubyObject result = aref(args); 1814 if (result.isNil()) { 1815 return result; 1816 } 1817 aset(newArgs); 1818 return result; 1819 } 1820 1821 public IRubyObject succ() { 1822 return ((RubyString) dup()).succ_bang(); 1823 } 1824 1825 public IRubyObject succ_bang() { 1826 if (value.length() == 0) { 1827 return this; 1828 } 1829 1830 boolean alnumSeen = false; 1831 int pos = -1; 1832 int c = 0; 1833 int n = 0; 1834 for (int i = value.length() - 1; i >= 0; i--) { 1835 c = value.get(i) & 0xFF; 1836 if (isAlnum(c)) { 1837 alnumSeen = true; 1838 if ((isDigit(c) && c < '9') || (isLower(c) && c < 'z') || (isUpper(c) && c < 'Z')) { 1839 value.set(i, (byte)(c + 1)); 1840 pos = -1; 1841 break; 1842 } 1843 pos = i; 1844 n = isDigit(c) ? '0' : (isLower(c) ? 'a' : 'A'); 1845 value.set(i, (byte)n); 1846 } 1847 } 1848 if (!alnumSeen) { 1849 for (int i = value.length() - 1; i >= 0; i--) { 1850 c = value.get(i); 1851 if (c < 0xff) { 1852 value.set(i, (byte)(c + 1)); 1853 pos = -1; 1854 break; 1855 } 1856 pos = i; 1857 n = '\u0001'; 1858 value.set(i, 0); 1859 } 1860 } 1861 if (pos > -1) { 1862 value.prepend((byte)(isDigit(c) ? '1' : (isLower(c) ? 'a' : 'A'))); 1867 } 1868 stringMutated(); 1869 return this; 1870 } 1871 1872 1875 public IRubyObject upto(IRubyObject str, Block block) { 1876 return upto(str, false, block); 1877 } 1878 1879 1880 public IRubyObject upto(IRubyObject str, boolean excl, Block block) { 1881 RubyString beg = this; 1883 RubyString end = stringValue(str); 1884 1885 int n = beg.cmp(end); 1886 if (n > 0 || (excl && n == 0)) { 1887 return beg; 1888 } 1889 1890 RubyString afterEnd = stringValue(end.succ()); 1891 RubyString current = beg; 1892 1893 ThreadContext context = getRuntime().getCurrentContext(); 1894 while (!current.equals(afterEnd)) { 1895 context.yield(current, block); 1896 if (!excl && current.equals(end)) { 1897 break; 1898 } 1899 1900 current = (RubyString) current.succ(); 1901 if (excl && current.equals(end)) { 1902 break; 1903 } 1904 if (current.length().getLongValue() > end.length().getLongValue()) { 1905 break; 1906 } 1907 } 1908 1909 return beg; 1910 1911 } 1912 1913 1914 1917 public RubyBoolean include(IRubyObject obj) { 1918 if (obj instanceof RubyFixnum) { 1919 int c = RubyNumeric.fix2int(obj); 1920 for (int i = 0; i < value.length(); i++) { 1921 if (value.get(i) == (byte)c) { 1922 return getRuntime().getTrue(); 1923 } 1924 } 1925 return getRuntime().getFalse(); 1926 } 1927 String str = stringValue(obj).toString(); 1928 return getRuntime().newBoolean(new StringBuffer (toString()).indexOf(str) != -1); 1929 } 1930 1931 1934 public IRubyObject to_i(IRubyObject[] args) { 1935 long base = checkArgumentCount(args, 0, 1) == 0 ? 10 : ((RubyInteger) args[0].convertType(RubyInteger.class, 1936 "Integer", "to_i")).getLongValue(); 1937 return RubyNumeric.str2inum(getRuntime(), this, (int) base); 1938 } 1939 1940 1943 public IRubyObject oct() { 1944 if (isEmpty()) { 1945 return getRuntime().newFixnum(0); 1946 } 1947 1948 int base = 8; 1949 String str = toString().trim(); 1950 int pos = (str.charAt(0) == '-' || str.charAt(0) == '+') ? 1 : 0; 1951 if (str.indexOf("0x") == pos || str.indexOf("0X") == pos) { 1952 base = 16; 1953 } else if (str.indexOf("0b") == pos || str.indexOf("0B") == pos) { 1954 base = 2; 1955 } 1956 return RubyNumeric.str2inum(getRuntime(), this, base); 1957 } 1958 1959 1962 public IRubyObject hex() { 1963 return RubyNumeric.str2inum(getRuntime(), this, 16); 1964 } 1965 1966 1969 public IRubyObject to_f() { 1970 return RubyNumeric.str2fnum(getRuntime(), this); 1971 } 1972 1973 1976 public RubyArray split(IRubyObject[] args) { 1977 RubyRegexp pattern; 1978 boolean isWhitespace = false; 1979 1980 if (args.length == 0) { 1982 isWhitespace = true; 1983 pattern = RubyRegexp.newRegexp(getRuntime(), "\\s+", 0, null); 1984 } else if (args[0] instanceof RubyRegexp) { 1985 pattern = RubyRegexp.regexpValue(args[0]); 1989 } else { 1990 String stringPattern = RubyString.stringValue(args[0]).toString(); 1991 1992 if (stringPattern.equals(" ")) { 1993 isWhitespace = true; 1994 pattern = RubyRegexp.newRegexp(getRuntime(), "\\s+", 0, null); 1995 } else { 1996 pattern = RubyRegexp.newRegexp(getRuntime(), RubyRegexp.escapeSpecialChars(stringPattern), 0, null); 1997 } 1998 } 1999 2000 int limit = getLimit(args); 2001 String [] result = null; 2002 String splitee = toString(); 2004 boolean unicodeSuccess = false; 2005 if (getRuntime().getKCode() == KCode.UTF8) { 2006 CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder(); 2009 decoder.onMalformedInput(CodingErrorAction.REPORT); 2010 decoder.onUnmappableCharacter(CodingErrorAction.REPORT); 2011 2012 try { 2013 splitee = decoder.decode(ByteBuffer.wrap(value.bytes())).toString(); 2014 unicodeSuccess = true; 2015 } catch (CharacterCodingException cce) { 2016 } 2018 } 2019 2020 2021 if (limit == 1) { 2022 result = new String [] {splitee}; 2023 } else { 2024 List list = new ArrayList (); 2025 int numberOfHits = 0; 2026 int stringLength = splitee.length(); 2027 2028 Pattern pat = pattern.getPattern(); 2029 Matcher matt = pat.matcher(splitee); 2030 2031 int startOfCurrentHit = 0; 2032 int endOfCurrentHit = 0; 2033 String group = null; 2034 2035 2037 if (matt.find()) { 2038 2040 endOfCurrentHit = matt.start(); 2042 2043 if (endOfCurrentHit != 0 || !isWhitespace) { 2045 2047 numberOfHits++; 2048 2049 if (matt.end() != 0) { 2051 2052 list.add(splitee.substring(startOfCurrentHit, endOfCurrentHit)); 2054 2055 for (int groupIndex = 1; groupIndex <= matt.groupCount(); groupIndex++) { 2057 group = matt.group(groupIndex); 2058 list.add(group); 2059 } 2060 } 2061 } 2062 2063 startOfCurrentHit = matt.end(); 2065 2066 if (numberOfHits + 1 != limit) { 2068 while (matt.find()) { 2070 endOfCurrentHit = matt.start(); 2072 numberOfHits++; 2073 2074 list.add(splitee.substring(startOfCurrentHit, endOfCurrentHit)); 2076 2077 for (int groupIndex = 1; groupIndex <= matt.groupCount(); groupIndex++) { 2079 group = matt.group(groupIndex); 2080 list.add(group); 2081 } 2082 2083 startOfCurrentHit = matt.end(); 2085 } 2086 } 2087 } 2088 2089 if (numberOfHits == 0) { 2090 list.add(splitee); 2092 } else if (startOfCurrentHit <= stringLength) { 2093 list.add(splitee.substring(startOfCurrentHit, stringLength)); 2095 } 2096 2097 if (limit == 0 && list.size() > 0) { 2099 for (int size = list.size() - 1; 2100 size >= 0 && ((String ) list.get(size)).length() == 0; size--) { 2101 list.remove(size); 2102 } 2103 } 2104 2105 result = (String [])list.toArray(new String [list.size()]); 2106 } 2107 2108 RubyArray resultArray = getRuntime().newArray(result.length); 2110 2111 for (int i = 0; i < result.length; i++) { 2112 RubyString string = getRuntime().newString(result[i]); 2113 2114 if (unicodeSuccess && getRuntime().getKCode() == KCode.UTF8) { 2117 string.setUnicodeValue(result[i]); 2118 } 2119 2120 resultArray.append(string); 2121 } 2122 2123 return resultArray; 2124 } 2125 2126 private static int getLimit(IRubyObject[] args) { 2127 if (args.length == 2) { 2128 return RubyNumeric.fix2int(args[1]); 2129 } 2130 return 0; 2131 } 2132 2133 2136 public IRubyObject scan(IRubyObject arg, Block block) { 2137 RubyRegexp pattern = RubyRegexp.regexpValue(arg); 2138 int start = 0; 2139 ThreadContext tc = getRuntime().getCurrentContext(); 2140 2141 String toString = toString(); 2145 2146 if (!block.isGiven()) { 2147 RubyArray ary = getRuntime().newArray(); 2148 while (pattern.search(toString, start) != -1) { 2149 RubyMatchData md = (RubyMatchData) tc.getBackref(); 2150 ary.append(md.getSize() == 1 ? md.group(0) : md.subseq(1, md.getSize())); 2151 2152 if (md.matchEndPosition() == md.matchStartPosition()) { 2153 start++; 2154 } else { 2155 start = md.matchEndPosition(); 2156 } 2157 } 2158 return ary; 2159 } 2160 2161 while (pattern.search(toString, start) != -1) { 2162 RubyMatchData md = (RubyMatchData) tc.getBackref(); 2163 tc.yield(md.getSize() == 1 ? md.group(0) : md.subseq(1, md.getSize()), block); 2164 2165 if (md.matchEndPosition() == md.matchStartPosition()) { 2166 start++; 2167 } else { 2168 start = md.matchEndPosition(); 2169 } 2170 } 2171 return this; 2172 } 2173 2174 private IRubyObject justify(IRubyObject [] args, boolean leftJustify) { 2175 checkArgumentCount(args, 1, 2); 2176 int length = RubyNumeric.fix2int(args[0]); 2177 if (length <= value.length()) { 2178 return dup(); 2179 } 2180 2181 String paddingArg; 2182 2183 if (args.length == 2) { 2184 paddingArg = args[1].convertToString().toString(); 2185 if (paddingArg.length() == 0) { 2186 throw getRuntime().newArgumentError("zero width padding"); 2187 } 2188 } else { 2189 paddingArg = " "; 2190 } 2191 2192 StringBuffer sbuf = new StringBuffer (length); 2193 String thisStr = toString(); 2194 2195 if (leftJustify) { 2196 sbuf.append(thisStr); 2197 } 2198 2199 int whole = (length - thisStr.length()) / paddingArg.length(); 2201 for (int w = 0; w < whole; w++ ) { 2202 sbuf.append(paddingArg); 2203 } 2204 2205 int fractionalLength = (length - thisStr.length()) % paddingArg.length(); 2207 if (fractionalLength > 0) { 2208 sbuf.append(paddingArg.substring(0, fractionalLength)); 2209 } 2210 2211 if (!leftJustify) { 2212 sbuf.append(thisStr); 2213 } 2214 2215 RubyString ret = newString(sbuf.toString()); 2216 2217 if (args.length == 2) { 2218 ret.infectBy(args[1]); 2219 } 2220 2221 return ret; 2222 } 2223 2224 2227 public IRubyObject ljust(IRubyObject [] args) { 2228 return justify(args, true); 2229 } 2230 2231 2234 public IRubyObject rjust(IRubyObject [] args) { 2235 return justify(args, false); 2236 } 2237 2238 public IRubyObject center(IRubyObject[] args) { 2239 checkArgumentCount(args, 1, 2); 2240 int len = RubyNumeric.fix2int(args[0]); 2241 String pad = args.length == 2 ? args[1].convertToString().toString() : " "; 2242 int strLen = value.length(); 2243 int padLen = pad.length(); 2244 2245 if (padLen == 0) { 2246 throw getRuntime().newArgumentError("zero width padding"); 2247 } 2248 if (len <= strLen) { 2249 return dup(); 2250 } 2251 StringBuffer sbuf = new StringBuffer (len); 2252 int lead = (len - strLen) / 2; 2253 for (int i = 0; i < lead; i++) { 2254 sbuf.append(pad.charAt(i % padLen)); 2255 } 2256 sbuf.append(getValue()); 2257 int remaining = len - (lead + strLen); 2258 for (int i = 0; i < remaining; i++) { 2259 sbuf.append(pad.charAt(i % padLen)); 2260 } 2261 return newString(sbuf.toString()); 2262 } 2263 2264 public IRubyObject chop() { 2265 RubyString newString = (RubyString) dup(); 2266 2267 newString.chop_bang(); 2268 2269 return newString; 2270 } 2271 2272 public IRubyObject chop_bang() { 2273 int end = value.length() - 1; 2274 2275 if (end < 0) { 2276 return getRuntime().getNil(); 2277 } 2278 2279 if ((value.get(end) & 0xFF) == '\n') { 2280 if (end > 0 && (value.get(end-1) & 0xFF) == '\r') { 2281 end--; 2282 } 2283 } 2284 2285 value.length(end); 2286 stringMutated(); 2287 return this; 2288 } 2289 2290 public RubyString chomp(IRubyObject[] args) { 2291 RubyString result = (RubyString) dup(); 2292 2293 result.chomp_bang(args); 2294 2295 return result; 2296 } 2297 2298 2309 public IRubyObject chomp_bang(IRubyObject[] args) { 2310 if (isEmpty()) { 2311 return getRuntime().getNil(); 2312 } 2313 2314 String separator = (args.length == 0) ? 2316 getRuntime().getGlobalVariables().get("$/").asSymbol() : args[0].asSymbol(); 2317 2318 if (separator.equals(DEFAULT_RS)) { 2319 int end = value.length() - 1; 2320 int removeCount = 0; 2321 2322 if (end < 0) { 2323 return getRuntime().getNil(); 2324 } 2325 2326 if ((value.get(end) & 0xFF) == '\n') { 2327 removeCount++; 2328 if (end > 0 && (value.get(end-1) & 0xFF) == '\r') { 2329 removeCount++; 2330 } 2331 } else if ((value.get(end) & 0xFF) == '\r') { 2332 removeCount++; 2333 } 2334 2335 if (removeCount == 0) { 2336 return getRuntime().getNil(); 2337 } 2338 2339 value.length(end - removeCount + 1); 2340 stringMutated(); 2341 return this; 2342 } 2343 2344 if (separator.length() == 0) { 2345 int end = value.length() - 1; 2346 int removeCount = 0; 2347 while(end - removeCount >= 0 && (value.get(end - removeCount) & 0xFF) == '\n') { 2348 removeCount++; 2349 if (end - removeCount >= 0 && (value.get(end - removeCount) & 0xFF) == '\r') { 2350 removeCount++; 2351 } 2352 } 2353 if (removeCount == 0) { 2354 return getRuntime().getNil(); 2355 } 2356 2357 value.length(end - removeCount + 1); 2358 stringMutated(); 2359 return this; 2360 } 2361 2362 if (toString().endsWith(separator)) { 2364 value.length(value.length() - separator.length()); 2365 stringMutated(); 2366 return this; 2367 } 2368 return getRuntime().getNil(); 2369 } 2370 2371 public IRubyObject lstrip() { 2372 return newString(getRuntime(), lstripInternal()); 2373 } 2374 2375 public ByteList lstripInternal() { 2376 int length = value.length(); 2377 int i = 0; 2378 2379 for (; i < length; i++) { 2380 if (!Character.isWhitespace(value.charAt(i))) { 2381 break; 2382 } 2383 } 2384 2385 return new ByteList(value, i, value.length() - i); 2386 } 2387 2388 public IRubyObject lstrip_bang() { 2389 ByteList newBytes = lstripInternal(); 2390 if (value.equals(newBytes)) { 2391 return getRuntime().getNil(); 2392 } 2393 value = newBytes; 2394 stringMutated(); 2395 2396 return this; 2397 } 2398 2399 public IRubyObject rstrip() { 2400 return newString(getRuntime(), rstripInternal()); 2401 } 2402 2403 public ByteList rstripInternal() { 2404 int i = value.length() - 1; 2405 2406 for (; i >= 0; i--) { 2407 if (!Character.isWhitespace(value.charAt(i))) { 2408 break; 2409 } 2410 } 2411 2412 return new ByteList(value, 0, i + 1); 2413 } 2414 2415 public IRubyObject rstrip_bang() { 2416 ByteList newBytes = rstripInternal(); 2417 if (value.equals(newBytes)) { 2418 return getRuntime().getNil(); 2419 } 2420 value = newBytes; 2421 stringMutated(); 2422 2423 return this; 2424 } 2425 2426 2429 public IRubyObject strip() { 2430 if (isEmpty()) { 2431 return dup(); 2432 } 2433 ByteList bytes = stripInternal(); 2434 if (bytes == null) { 2435 return newString(getRuntime(), (ByteList)value.clone()); 2436 } 2437 2438 return newString(getRuntime(), bytes); 2439 } 2440 2441 2444 public IRubyObject strip_bang() { 2445 if (isEmpty()) { 2446 return getRuntime().getNil(); 2447 } 2448 ByteList bytes = stripInternal(); 2449 if (bytes == null) { 2450 return getRuntime().getNil(); 2451 } 2452 value = bytes; 2453 stringMutated(); 2454 return this; 2455 } 2456 2457 public ByteList stripInternal() { 2458 int head = 0; 2459 while (head < value.length() && Character.isWhitespace(value.charAt(head))) head++; 2460 int tail = value.length() - 1; 2461 while (tail > head && Character.isWhitespace(value.charAt(tail))) tail--; 2462 2463 if (head == 0 && tail == value.length() - 1) { 2464 return null; 2465 } 2466 2467 if (head <= tail) { 2468 return new ByteList(value, head, tail - head + 1); 2469 } 2470 2471 if (head > tail) { 2472 return new ByteList(); 2473 } 2474 2475 return null; 2476 } 2477 2478 private static String expandTemplate(String spec, boolean invertOK) { 2479 int len = spec.length(); 2480 if (len <= 1) { 2481 return spec; 2482 } 2483 StringBuffer sbuf = new StringBuffer (); 2484 int pos = (invertOK && spec.charAt(0) == '^') ? 1 : 0; 2485 while (pos < len) { 2486 char c1 = spec.charAt(pos), c2; 2487 if (pos + 2 < len && spec.charAt(pos + 1) == '-') { 2488 if ((c2 = spec.charAt(pos + 2)) > c1) { 2489 for (int i = c1; i <= c2; i++) { 2490 sbuf.append((char) i); 2491 } 2492 } 2493 pos += 3; 2494 continue; 2495 } 2496 sbuf.append(c1); 2497 pos++; 2498 } 2499 return sbuf.toString(); 2500 } 2501 2502 private String setupTable(String [] specs) { 2503 int[] table = new int[256]; 2504 int numSets = 0; 2505 for (int i = 0; i < specs.length; i++) { 2506 String template = expandTemplate(specs[i], true); 2507 boolean invert = specs[i].length() > 1 && specs[i].charAt(0) == '^'; 2508 for (int j = 0; j < 256; j++) { 2509 if (template.indexOf(j) != -1) { 2510 table[j] += invert ? -1 : 1; 2511 } 2512 } 2513 numSets += invert ? 0 : 1; 2514 } 2515 StringBuffer sbuf = new StringBuffer (); 2516 for (int k = 0; k < 256; k++) { 2517 if (table[k] == numSets) { 2518 sbuf.append((char) k); 2519 } 2520 } 2521 return sbuf.toString(); 2522 } 2523 2524 2527 public IRubyObject count(IRubyObject[] args) { 2528 int argc = checkArgumentCount(args, 1, -1); 2529 String [] specs = new String [argc]; 2530 for (int i = 0; i < argc; i++) { 2531 specs[i] = stringValue(args[i]).toString(); 2532 } 2533 String table = setupTable(specs); 2534 2535 int count = 0; 2536 for (int j = 0; j < value.length(); j++) { 2537 if (table.indexOf(value.get(j) & 0xFF) != -1) { 2538 count++; 2539 } 2540 } 2541 return getRuntime().newFixnum(count); 2542 } 2543 2544 private ByteList getDelete(IRubyObject[] args) { 2545 int argc = checkArgumentCount(args, 1, -1); 2546 String [] specs = new String [argc]; 2547 for (int i = 0; i < argc; i++) { 2548 specs[i] = stringValue(args[i]).toString(); 2549 } 2550 String table = setupTable(specs); 2551 2552 int strLen = value.length(); 2553 StringBuffer sbuf = new StringBuffer (strLen); 2554 int c; 2555 for (int j = 0; j < strLen; j++) { 2556 c = value.get(j) & 0xFF; 2557 if (table.indexOf(c) == -1) { 2558 sbuf.append((char)c); 2559 } 2560 } 2561 return new ByteList(stringToBytes(sbuf.toString())); 2562 } 2563 2564 2567 public IRubyObject delete(IRubyObject[] args) { 2568 return newString(getRuntime(), getDelete(args)).infectBy(this); 2569 } 2570 2571 2574 public IRubyObject delete_bang(IRubyObject[] args) { 2575 ByteList newStr = getDelete(args); 2576 if (value.equals(newStr)) { 2577 return getRuntime().getNil(); 2578 } 2579 value = newStr; 2580 stringMutated(); 2581 return this; 2582 } 2583 2584 private ByteList getSqueeze(IRubyObject[] args) { 2585 int argc = args.length; 2586 String [] specs = null; 2587 if (argc > 0) { 2588 specs = new String [argc]; 2589 for (int i = 0; i < argc; i++) { 2590 specs[i] = stringValue(args[i]).toString(); 2591 } 2592 } 2593 String table = specs == null ? null : setupTable(specs); 2594 2595 int strLen = value.length(); 2596 if (strLen <= 1) { 2597 return value; 2598 } 2599 StringBuffer sbuf = new StringBuffer (strLen); 2600 int c1 = value.get(0) & 0xFF; 2601 sbuf.append((char)c1); 2602 int c2; 2603 for (int j = 1; j < strLen; j++) { 2604 c2 = value.get(j) & 0xFF; 2605 if (c2 == c1 && (table == null || table.indexOf(c2) != -1)) { 2606 continue; 2607 } 2608 sbuf.append((char)c2); 2609 c1 = c2; 2610 } 2611 return new ByteList(stringToBytes(sbuf.toString())); 2612 } 2613 2614 2617 public IRubyObject squeeze(IRubyObject[] args) { 2618 return newString(getRuntime(), getSqueeze(args)).infectBy(this); 2619 } 2620 2621 2624 public IRubyObject squeeze_bang(IRubyObject[] args) { 2625 ByteList newStr = getSqueeze(args); 2626 if (value.equals(newStr)) { 2627 return getRuntime().getNil(); 2628 } 2629 value = newStr; 2630 stringMutated(); 2631 return this; 2632 } 2633 2634 private ByteList tr(IRubyObject search, IRubyObject replace, boolean squeeze) { 2635 String srchSpec = search.convertToString().toString(); 2636 String srch = expandTemplate(srchSpec, true); 2637 if (srchSpec.startsWith("^")) { 2638 StringBuffer sbuf = new StringBuffer (256); 2639 for (int i = 0; i < 256; i++) { 2640 char c = (char) i; 2641 if (srch.indexOf(c) == -1) { 2642 sbuf.append(c); 2643 } 2644 } 2645 srch = sbuf.toString(); 2646 } 2647 String repl = expandTemplate(replace.convertToString().toString(), false); 2648 2649 int strLen = value.length(); 2650 if (strLen == 0 || srch.length() == 0) { 2651 return value; 2652 } 2653 int repLen = repl.length(); 2654 StringBuffer sbuf = new StringBuffer (strLen); 2655 int last = -1; 2656 for (int i = 0; i < strLen; i++) { 2657 int cs = value.get(i) & 0xFF; 2658 int pos = srch.indexOf(cs); 2659 if (pos == -1) { 2660 sbuf.append((char)cs); 2661 last = -1; 2662 } else if (repLen > 0) { 2663 char cr = repl.charAt(Math.min(pos, repLen - 1)); 2664 if (squeeze && cr == last) { 2665 continue; 2666 } 2667 sbuf.append((char)cr); 2668 last = cr; 2669 } 2670 } 2671 return new ByteList(stringToBytes(sbuf.toString())); 2672 } 2673 2674 2677 public IRubyObject tr(IRubyObject search, IRubyObject replace) { 2678 return newString(getRuntime(), tr(search, replace, false)).infectBy(this); 2679 } 2680 2681 2684 public IRubyObject tr_bang(IRubyObject search, IRubyObject replace) { 2685 ByteList newStr = tr(search, replace, false); 2686 if (value.equals(newStr)) { 2687 return getRuntime().getNil(); 2688 } 2689 value = newStr; 2690 stringMutated(); 2691 return this; 2692 } 2693 2694 2697 public IRubyObject tr_s(IRubyObject search, IRubyObject replace) { 2698 return newString(getRuntime(), tr(search, replace, true)).infectBy(this); 2699 } 2700 2701 2704 public IRubyObject tr_s_bang(IRubyObject search, IRubyObject replace) { 2705 ByteList newStr = tr(search, replace, true); 2706 if (value.equals(newStr)) { 2707 return getRuntime().getNil(); 2708 } 2709 value = newStr; 2710 stringMutated(); 2711 return this; 2712 } 2713 2714 2717 public IRubyObject each_line(IRubyObject[] args, Block block) { 2718 int strLen = value.length(); 2719 if (strLen == 0) { 2720 return this; 2721 } 2722 String sep; 2723 if (checkArgumentCount(args, 0, 1) == 1) { 2724 sep = RubyRegexp.escapeSpecialChars(stringValue(args[0]).toString()); 2725 } else { 2726 sep = RubyRegexp.escapeSpecialChars(getRuntime().getGlobalVariables().get("$/").asSymbol()); 2727 } 2728 if (sep == null) { 2729 sep = "(?:\\n|\\r\\n?)"; 2730 } else if (sep.length() == 0) { 2731 sep = "(?:\\n|\\r\\n?){2,}"; 2732 } 2733 RubyRegexp pat = RubyRegexp.newRegexp(getRuntime(), ".*?" + sep, RubyRegexp.RE_OPTION_MULTILINE, null); 2734 int start = 0; 2735 ThreadContext tc = getRuntime().getCurrentContext(); 2736 2737 String toString = toString(); 2741 2742 while (pat.search(toString, start) != -1) { 2743 RubyMatchData md = (RubyMatchData) tc.getBackref(); 2744 tc.yield(md.group(0), block); 2745 start = md.matchEndPosition(); 2746 } 2747 if (start < strLen) { 2748 tc.yield(substr(start, strLen - start), block); 2749 } 2750 return this; 2751 } 2752 2753 2756 public RubyString each_byte(Block block) { 2757 int lLength = value.length(); 2758 ThreadContext context = getRuntime().getCurrentContext(); 2759 for (int i = 0; i < lLength; i++) { 2760 context.yield(getRuntime().newFixnum(value.get(i) & 0xFF), block); 2761 } 2762 return this; 2763 } 2764 2765 2768 public RubySymbol intern() { 2769 String s = toString(); 2770 if (s.equals("")) { 2771 throw getRuntime().newArgumentError("interning empty string"); 2772 } 2773 if (s.indexOf('\0') >= 0) { 2774 throw getRuntime().newArgumentError("symbol string may not contain '\\0'"); 2775 } 2776 return RubySymbol.newSymbol(getRuntime(), toString()); 2777 } 2778 2779 public RubySymbol to_sym() { 2780 return intern(); 2781 } 2782 2783 public RubyInteger sum(IRubyObject[] args) { 2784 long bitSize = 16; 2785 if (args.length > 0) { 2786 bitSize = ((RubyInteger) args[0].convertType(RubyInteger.class, 2787 "Integer", "to_i")).getLongValue(); 2788 } 2789 2790 long result = 0; 2791 for (int i = 0; i < value.length(); i++) { 2792 result += value.get(i) & 0xFF; 2793 } 2794 return getRuntime().newFixnum(bitSize == 0 ? result : result % (long) Math.pow(2, bitSize)); 2795 } 2796 2797 public static RubyString unmarshalFrom(UnmarshalStream input) throws java.io.IOException { 2798 RubyString result = newString(input.getRuntime(), input.unmarshalString()); 2799 input.registerLinkTarget(result); 2800 return result; 2801 } 2802 2803 2806 public RubyArray unpack(IRubyObject obj) { 2807 return Pack.unpack(getRuntime(), this.value, stringValue(obj).value); 2808 } 2809 2810 2815 public void setValue(CharSequence value) { 2816 this.value.replace(ByteList.plain(value)); 2817 stringMutated(); 2818 } 2819 2820 public void setValue(ByteList value) { 2821 this.value = value; 2822 stringMutated(); 2823 } 2824 2825 public CharSequence getValue() { 2826 return toString(); 2827 } 2828 2829 public String getUnicodeValue() { 2830 try { 2831 return new String (value.bytes,0,value.realSize, "UTF8"); 2832 } catch (Exception e) { 2833 throw new RuntimeException ("Something's seriously broken with encodings", e); 2834 } 2835 } 2836 2837 public void setUnicodeValue(String newValue) { 2838 try { 2839 value.replace(newValue.getBytes("UTF8")); 2840 stringMutated(); 2841 } catch (Exception e) { 2842 throw new RuntimeException ("Something's seriously broken with encodings", e); 2843 } 2844 } 2845 2846 public byte[] getBytes() { 2847 return value.bytes(); 2848 } 2849 2850 public ByteList getByteList() { 2851 return value; 2852 } 2853} 2854 | Popular Tags |