1 34 package org.jruby; 35 36 import java.io.EOFException ; 37 import java.io.FileNotFoundException ; 38 import java.io.IOException ; 39 import java.io.InputStream ; 40 import java.io.OutputStream ; 41 import java.lang.ref.WeakReference ; 42 import java.nio.channels.Channel ; 43 import org.jruby.runtime.Block; 44 import org.jruby.runtime.ThreadContext; 45 import org.jruby.runtime.builtin.IRubyObject; 46 import org.jruby.util.ByteList; 47 import org.jruby.util.IOHandler; 48 import org.jruby.util.IOHandlerJavaIO; 49 import org.jruby.util.IOHandlerNio; 50 import org.jruby.util.IOHandlerNull; 51 import org.jruby.util.IOHandlerProcess; 52 import org.jruby.util.IOHandlerSeekable; 53 import org.jruby.util.IOHandlerUnseekable; 54 import org.jruby.util.IOModes; 55 56 60 public class RubyIO extends RubyObject { 61 public static final int STDIN = 0; 62 public static final int STDOUT = 1; 63 public static final int STDERR = 2; 64 65 protected IOHandler handler = null; 66 protected IOModes modes = null; 67 protected int lineNumber = 0; 68 69 protected boolean isOpen = true; 77 private boolean atEOF = false; 78 79 135 136 141 public void registerIOHandler(IOHandler newHandler) { 142 getRuntime().getIoHandlers().put(new Integer (newHandler.getFileno()), new WeakReference (newHandler)); 143 } 144 145 public void unregisterIOHandler(int aFileno) { 146 getRuntime().getIoHandlers().remove(new Integer (aFileno)); 147 } 148 149 public IOHandler getIOHandlerByFileno(int aFileno) { 150 return (IOHandler) ((WeakReference ) getRuntime().getIoHandlers().get(new Integer (aFileno))).get(); 151 } 152 153 protected static int fileno = 2; 155 156 public static int getNewFileno() { 157 fileno++; 158 159 return fileno; 160 } 161 162 public RubyIO(Ruby runtime, RubyClass type) { 165 super(runtime, type); 166 } 167 168 public RubyIO(Ruby runtime, OutputStream outputStream) { 169 super(runtime, runtime.getClass("IO")); 170 171 if (outputStream == null) { 173 throw runtime.newIOError("Opening invalid stream"); 174 } 175 176 try { 177 handler = new IOHandlerUnseekable(runtime, null, outputStream); 178 } catch (IOException e) { 179 throw runtime.newIOError(e.getMessage()); 180 } 181 modes = handler.getModes(); 182 183 registerIOHandler(handler); 184 } 185 186 public RubyIO(Ruby runtime, InputStream inputStream) { 187 super(runtime, runtime.getClass("IO")); 188 189 if (inputStream == null) { 190 throw runtime.newIOError("Opening invalid stream"); 191 } 192 193 try { 194 handler = new IOHandlerUnseekable(runtime, inputStream, null); 195 } catch (IOException e) { 196 throw runtime.newIOError(e.getMessage()); 197 } 198 199 modes = handler.getModes(); 200 201 registerIOHandler(handler); 202 } 203 204 public RubyIO(Ruby runtime, Channel channel) { 205 super(runtime, runtime.getClass("IO")); 206 207 if (channel == null) { 209 throw runtime.newIOError("Opening invalid stream"); 210 } 211 212 try { 213 handler = new IOHandlerNio(runtime, channel); 214 } catch (IOException e) { 215 throw runtime.newIOError(e.getMessage()); 216 } 217 modes = handler.getModes(); 218 219 registerIOHandler(handler); 220 } 221 222 public RubyIO(Ruby runtime, Process process) { 223 super(runtime, runtime.getClass("IO")); 224 225 modes = new IOModes(runtime, "w+"); 226 227 try { 228 handler = new IOHandlerProcess(runtime, process, modes); 229 } catch (IOException e) { 230 throw runtime.newIOError(e.getMessage()); 231 } 232 modes = handler.getModes(); 233 234 registerIOHandler(handler); 235 } 236 237 public RubyIO(Ruby runtime, int descriptor) { 238 super(runtime, runtime.getClass("IO")); 239 240 try { 241 handler = new IOHandlerUnseekable(runtime, descriptor); 242 } catch (IOException e) { 243 throw runtime.newIOError(e.getMessage()); 244 } 245 modes = handler.getModes(); 246 247 registerIOHandler(handler); 248 } 249 250 254 public static IRubyObject fdOpen(Ruby runtime, int descriptor) { 255 return new RubyIO(runtime, descriptor); 256 } 257 258 261 protected void checkWriteable() { 262 if (!isOpen() || !modes.isWriteable()) { 263 throw getRuntime().newIOError("not opened for writing"); 264 } 265 } 266 267 276 protected void checkReadable() { 277 if (!isOpen() || !modes.isReadable()) { 278 throw getRuntime().newIOError("not opened for reading"); 279 } 280 } 281 282 public boolean isOpen() { 283 return isOpen; 284 } 285 286 public OutputStream getOutStream() { 287 if(handler instanceof IOHandlerJavaIO) { 288 return ((IOHandlerJavaIO) handler).getOutputStream(); 289 } else { 290 return null; 291 } 292 } 293 294 public InputStream getInStream() { 295 if (handler instanceof IOHandlerJavaIO) { 296 return ((IOHandlerJavaIO) handler).getInputStream(); 297 } else { 298 return null; 299 } 300 } 301 302 public Channel getChannel() { 303 if (handler instanceof IOHandlerNio) { 304 return ((IOHandlerNio) handler).getChannel(); 305 } else { 306 return null; 307 } 308 } 309 310 public IRubyObject reopen(IRubyObject[] args) { 311 if (args.length < 1) { 312 throw getRuntime().newArgumentError("wrong number of arguments"); 313 } 314 315 if (args[0].isKindOf(getRuntime().getClass("IO"))) { 316 RubyIO ios = (RubyIO) args[0]; 317 318 int keepFileno = handler.getFileno(); 319 320 if (handler.isOpen()) { 322 try { 323 handler.close(); 324 } catch (IOHandler.BadDescriptorException e) { 325 throw getRuntime().newErrnoEBADFError(); 326 } catch (EOFException e) { 327 return getRuntime().getNil(); 328 } catch (IOException e) { 329 throw getRuntime().newIOError(e.getMessage()); 330 } 331 } 332 333 try { 342 handler = ios.handler.cloneIOHandler(); 343 } catch (IOHandler.InvalidValueException e) { 344 throw getRuntime().newErrnoEINVALError(); 345 } catch (IOHandler.PipeException e) { 346 throw getRuntime().newErrnoESPIPEError(); 347 } catch (FileNotFoundException e) { 348 throw getRuntime().newErrnoENOENTError(); 349 } catch (IOException e) { 350 throw getRuntime().newIOError(e.getMessage()); 351 } 352 handler.setFileno(keepFileno); 353 354 registerIOHandler(handler); 356 } else if (args[0].isKindOf(getRuntime().getString())) { 357 String path = ((RubyString) args[0]).toString(); 358 IOModes newModes = null; 359 360 if (args.length > 1) { 361 if (!args[1].isKindOf(getRuntime().getString())) { 362 throw getRuntime().newTypeError(args[1], getRuntime().getString()); 363 } 364 365 newModes = new IOModes(getRuntime(), ((RubyString) args[1]).toString()); 366 } 367 368 try { 369 if (handler != null) { 370 close(); 371 } 372 373 if (newModes != null) { 374 modes = newModes; 375 } 376 if ("/dev/null".equals(path)) { 377 handler = new IOHandlerNull(getRuntime(), modes); 378 } else { 379 handler = new IOHandlerSeekable(getRuntime(), path, modes); 380 } 381 382 registerIOHandler(handler); 383 } catch (IOHandler.InvalidValueException e) { 384 throw getRuntime().newErrnoEINVALError(); 385 } catch (IOException e) { 386 throw getRuntime().newIOError(e.toString()); 387 } 388 } 389 390 isOpen = true; 392 return this; 393 } 394 397 public IRubyObject internalGets(IRubyObject[] args) { 400 checkReadable(); 401 402 IRubyObject sepVal = getRuntime().getGlobalVariables().get("$/"); 403 404 if (args.length > 0) { 405 sepVal = args[0]; 406 } 407 408 409 ByteList separator = sepVal.isNil() ? null : ((RubyString) sepVal).getByteList(); 410 411 if (separator != null && separator.realSize == 0) { 412 separator = IOHandler.PARAGRAPH_DELIMETER; 413 } 414 415 try { 416 ByteList newLine = handler.gets(separator); 417 418 if (newLine != null) { 419 lineNumber++; 420 getRuntime().getGlobalVariables().set("$.", getRuntime().newFixnum(lineNumber)); 421 RubyString result = RubyString.newString(getRuntime(), newLine); 422 result.taint(); 423 424 return result; 425 } 426 427 return getRuntime().getNil(); 428 } catch (IOHandler.BadDescriptorException e) { 429 throw getRuntime().newErrnoEBADFError(); 430 } catch (IOException e) { 431 throw getRuntime().newIOError(e.getMessage()); 432 } 433 } 434 435 437 public IRubyObject initialize(IRubyObject[] args, Block unusedBlock) { 438 int count = checkArgumentCount(args, 1, 2); 439 int newFileno = RubyNumeric.fix2int(args[0]); 440 String mode = null; 441 442 if (count > 1) { 443 mode = args[1].convertToString().toString(); 444 } 445 446 IOHandler existingIOHandler = getIOHandlerByFileno(newFileno); 450 451 if (existingIOHandler == null) { 452 if (mode == null) { 453 mode = "r"; 454 } 455 456 try { 457 handler = new IOHandlerUnseekable(getRuntime(), newFileno, mode); 458 } catch (IOException e) { 459 throw getRuntime().newIOError(e.getMessage()); 460 } 461 modes = new IOModes(getRuntime(), mode); 462 463 registerIOHandler(handler); 464 } else { 465 handler = existingIOHandler; 468 469 modes = mode == null ? handler.getModes() : 471 new IOModes(getRuntime(), mode); 472 473 try { 475 handler.reset(modes); 476 } catch (IOHandler.InvalidValueException e) { 477 throw getRuntime().newErrnoEINVALError(); 478 } catch (IOException e) { 479 throw getRuntime().newIOError(e.getMessage()); 480 } 481 } 482 483 return this; 484 } 485 486 public IRubyObject binmode() { 488 return this; 489 } 490 491 public IRubyObject syswrite(IRubyObject obj) { 492 try { 493 if (obj instanceof RubyString) { 494 return getRuntime().newFixnum(handler.syswrite(((RubyString)obj).getByteList())); 495 } else { 496 return getRuntime().newFixnum( 498 handler.syswrite( 499 ((RubyString)obj.callMethod( 500 obj.getRuntime().getCurrentContext(), "to_s")).getByteList())); 501 } 502 } catch (IOHandler.BadDescriptorException e) { 503 throw getRuntime().newErrnoEBADFError(); 504 } catch (IOException e) { 505 throw getRuntime().newSystemCallError(e.getMessage()); 506 } 507 } 508 509 512 public IRubyObject write(IRubyObject obj) { 513 checkWriteable(); 514 515 try { 516 if (obj instanceof RubyString) { 517 return getRuntime().newFixnum(handler.write(((RubyString)obj).getByteList())); 518 } else { 519 return getRuntime().newFixnum( 521 handler.write( 522 ((RubyString)obj.callMethod( 523 obj.getRuntime().getCurrentContext(), "to_s")).getByteList())); 524 } 525 } catch (IOHandler.BadDescriptorException e) { 526 return RubyFixnum.zero(getRuntime()); 527 } catch (IOException e) { 528 return RubyFixnum.zero(getRuntime()); 529 } 530 } 531 532 535 public IRubyObject addString(IRubyObject anObject) { 536 IRubyObject strObject = anObject.callMethod(getRuntime().getCurrentContext(), "to_s"); 538 539 write(strObject); 540 541 return this; 542 } 543 544 public RubyFixnum fileno() { 545 return getRuntime().newFixnum(handler.getFileno()); 546 } 547 548 552 public RubyFixnum lineno() { 553 return getRuntime().newFixnum(lineNumber); 554 } 555 556 560 public RubyFixnum lineno_set(IRubyObject newLineNumber) { 561 lineNumber = RubyNumeric.fix2int(newLineNumber); 562 563 return (RubyFixnum) newLineNumber; 564 } 565 566 570 public RubyBoolean sync() { 571 return getRuntime().newBoolean(handler.isSync()); 572 } 573 574 582 public IRubyObject pid() { 583 int pid = handler.pid(); 584 585 if (pid == -1) { 586 return getRuntime().getNil(); 587 } 588 589 return getRuntime().newFixnum(pid); 590 } 591 592 public RubyFixnum pos() { 593 try { 594 return getRuntime().newFixnum(handler.pos()); 595 } catch (IOHandler.PipeException e) { 596 throw getRuntime().newErrnoESPIPEError(); 597 } catch (IOException e) { 598 throw getRuntime().newIOError(e.getMessage()); 599 } 600 } 601 602 public RubyFixnum pos_set(IRubyObject newPosition) { 603 long offset = RubyNumeric.fix2long(newPosition); 604 605 if (offset < 0) { 606 throw getRuntime().newSystemCallError("Negative seek offset"); 607 } 608 609 try { 610 handler.seek(offset, IOHandler.SEEK_SET); 611 } catch (IOHandler.InvalidValueException e) { 612 throw getRuntime().newErrnoEINVALError(); 613 } catch (IOHandler.PipeException e) { 614 throw getRuntime().newErrnoESPIPEError(); 615 } catch (IOException e) { 616 throw getRuntime().newIOError(e.getMessage()); 617 } 618 619 return (RubyFixnum) newPosition; 620 } 621 622 625 public IRubyObject print(IRubyObject[] args) { 626 if (args.length == 0) { 627 args = new IRubyObject[] { getRuntime().getCurrentContext().getLastline() }; 628 } 629 630 IRubyObject fs = getRuntime().getGlobalVariables().get("$,"); 631 IRubyObject rs = getRuntime().getGlobalVariables().get("$\\"); 632 ThreadContext context = getRuntime().getCurrentContext(); 633 634 for (int i = 0; i < args.length; i++) { 635 if (i > 0 && !fs.isNil()) { 636 callMethod(context, "write", fs); 637 } 638 if (args[i].isNil()) { 639 callMethod(context, "write", getRuntime().newString("nil")); 640 } else { 641 callMethod(context, "write", args[i]); 642 } 643 } 644 if (!rs.isNil()) { 645 callMethod(context, "write", rs); 646 } 647 648 return getRuntime().getNil(); 649 } 650 651 public IRubyObject printf(IRubyObject[] args) { 652 checkArgumentCount(args, 1, -1); 653 callMethod(getRuntime().getCurrentContext(), "write", RubyKernel.sprintf(this, args)); 654 return getRuntime().getNil(); 655 } 656 657 public IRubyObject putc(IRubyObject object) { 658 int c; 659 660 if (object.isKindOf(getRuntime().getString())) { 661 String value = ((RubyString) object).toString(); 662 663 if (value.length() > 0) { 664 c = value.charAt(0); 665 } else { 666 throw getRuntime().newTypeError( 667 "Cannot convert String to Integer"); 668 } 669 } else if (object.isKindOf(getRuntime().getFixnum())){ 670 c = RubyNumeric.fix2int(object); 671 } else { c = RubyNumeric.fix2int(object.callMethod(getRuntime().getCurrentContext(), "to_i")); 673 } 674 675 try { 676 handler.putc(c); 677 } catch (IOHandler.BadDescriptorException e) { 678 return RubyFixnum.zero(getRuntime()); 679 } catch (IOException e) { 680 return RubyFixnum.zero(getRuntime()); 681 } 682 683 return getRuntime().newFixnum(c); 684 } 685 686 public RubyFixnum seek(IRubyObject[] args) { 689 if (args.length == 0) { 690 throw getRuntime().newArgumentError("wrong number of arguments"); 691 } 692 693 long offset = RubyNumeric.fix2long(args[0]); 694 int type = IOHandler.SEEK_SET; 695 696 if (args.length > 1) { 697 type = RubyNumeric.fix2int(args[1].convertToInteger()); 698 } 699 700 try { 701 handler.seek(offset, type); 702 } catch (IOHandler.InvalidValueException e) { 703 throw getRuntime().newErrnoEINVALError(); 704 } catch (IOHandler.PipeException e) { 705 throw getRuntime().newErrnoESPIPEError(); 706 } catch (IOException e) { 707 throw getRuntime().newIOError(e.getMessage()); 708 } 709 710 return RubyFixnum.zero(getRuntime()); 711 } 712 713 public RubyFixnum rewind() { 714 try { 715 handler.rewind(); 716 } catch (IOHandler.InvalidValueException e) { 717 throw getRuntime().newErrnoEINVALError(); 718 } catch (IOHandler.PipeException e) { 719 throw getRuntime().newErrnoESPIPEError(); 720 } catch (IOException e) { 721 throw getRuntime().newIOError(e.getMessage()); 722 } 723 724 lineNumber = 0; 726 727 return RubyFixnum.zero(getRuntime()); 728 } 729 730 public RubyFixnum fsync() { 731 checkWriteable(); 732 733 try { 734 handler.sync(); 735 } catch (IOException e) { 736 throw getRuntime().newIOError(e.getMessage()); 737 } catch (IOHandler.BadDescriptorException e) { 738 throw getRuntime().newErrnoEBADFError(); 739 } 740 741 return RubyFixnum.zero(getRuntime()); 742 } 743 744 748 public IRubyObject sync_set(IRubyObject newSync) { 749 handler.setIsSync(newSync.isTrue()); 750 751 return this; 752 } 753 754 public RubyBoolean eof() { 755 try { 756 boolean isEOF = handler.isEOF(); 757 return isEOF ? getRuntime().getTrue() : getRuntime().getFalse(); 758 } catch (IOHandler.BadDescriptorException e) { 759 throw getRuntime().newErrnoEBADFError(); 760 } catch (IOException e) { 761 throw getRuntime().newIOError(e.getMessage()); 762 } 763 } 764 765 public RubyBoolean tty() { 766 int fileno = handler.getFileno(); 768 if (fileno == STDOUT || fileno == STDIN || fileno == STDERR) { 769 return getRuntime().getTrue(); 770 } else { 771 return getRuntime().getFalse(); 772 } 773 } 774 775 public IRubyObject initialize_copy(IRubyObject original){ 776 if (this == original) return this; 777 778 RubyIO originalIO = (RubyIO) original; 779 780 793 handler = originalIO.handler; 794 modes = (IOModes) originalIO.modes.clone(); 795 796 return this; 797 } 798 799 803 public RubyBoolean closed() { 804 return isOpen() ? getRuntime().getFalse() : 805 getRuntime().getTrue(); 806 } 807 808 814 public IRubyObject close() { 815 isOpen = false; 816 817 try { 818 handler.close(); 819 } catch (IOHandler.BadDescriptorException e) { 820 throw getRuntime().newErrnoEBADFError(); 821 } catch (IOException e) { 822 throw getRuntime().newIOError(e.getMessage()); 823 } 824 825 unregisterIOHandler(handler.getFileno()); 826 827 return this; 828 } 829 830 834 public RubyIO flush() { 835 try { 836 handler.flush(); 837 } catch (IOHandler.BadDescriptorException e) { 838 throw getRuntime().newErrnoEBADFError(); 839 } catch (IOException e) { 840 throw getRuntime().newIOError(e.getMessage()); 841 } 842 843 return this; 844 } 845 846 849 public IRubyObject gets(IRubyObject[] args) { 850 IRubyObject result = internalGets(args); 851 852 if (!result.isNil()) { 853 getRuntime().getCurrentContext().setLastline(result); 854 } 855 856 return result; 857 } 858 859 public boolean getBlocking() { 860 if (!(handler instanceof IOHandlerNio)) { 861 return true; 862 } 863 864 return ((IOHandlerNio) handler).getBlocking(); 865 } 866 867 public IRubyObject fcntl(IRubyObject cmd, IRubyObject arg) throws IOException { 868 long realCmd = cmd.convertToInteger().getLongValue(); 869 870 if (!(arg instanceof RubyNumeric)) { 873 return getRuntime().newFixnum(0); 874 } 875 876 long realArg = ((RubyNumeric)arg).getLongValue(); 877 878 if (realCmd == 1L) { boolean block = true; 881 882 if((realArg & IOModes.NONBLOCK) == IOModes.NONBLOCK) { 883 block = false; 884 } 885 886 if(!(handler instanceof IOHandlerNio)) { 887 throw getRuntime().newNotImplementedError("FCNTL only works with Nio based handlers"); 889 } 890 891 try { 892 ((IOHandlerNio) handler).setBlocking(block); 893 } catch (IOException e) { 894 throw getRuntime().newIOError(e.getMessage()); 895 } 896 } 897 898 return getRuntime().newFixnum(0); 899 } 900 901 public IRubyObject puts(IRubyObject[] args) { 902 checkArgumentCount(args, 0, -1); 903 904 ThreadContext context = getRuntime().getCurrentContext(); 905 906 if (args.length == 0) { 907 callMethod(context, "write", getRuntime().newString("\n")); 908 return getRuntime().getNil(); 909 } 910 911 for (int i = 0; i < args.length; i++) { 912 String line = null; 913 if (args[i].isNil()) { 914 line = "nil"; 915 } else if (args[i] instanceof RubyArray) { 916 puts(((RubyArray) args[i]).toJavaArray()); 917 continue; 918 } else { 919 line = args[i].toString(); 920 } 921 callMethod(getRuntime().getCurrentContext(), "write", getRuntime().newString(line+ 922 (line.endsWith("\n") ? "" : "\n"))); 923 } 924 return getRuntime().getNil(); 925 } 926 927 930 public IRubyObject readline(IRubyObject[] args) { 931 IRubyObject line = gets(args); 932 933 if (line.isNil()) { 934 throw getRuntime().newEOFError(); 935 } 936 937 return line; 938 } 939 940 943 public IRubyObject getc() { 944 checkReadable(); 945 946 try { 947 int c = handler.getc(); 948 949 return c == -1 ? getRuntime().getNil() : getRuntime().newFixnum(c); 950 } catch (IOHandler.BadDescriptorException e) { 951 throw getRuntime().newErrnoEBADFError(); 952 } catch (EOFException e) { 953 return getRuntime().getNil(); 954 } catch (IOException e) { 955 throw getRuntime().newIOError(e.getMessage()); 956 } 957 } 958 959 964 public IRubyObject ungetc(IRubyObject number) { 965 handler.ungetc(RubyNumeric.fix2int(number)); 966 967 return getRuntime().getNil(); 968 } 969 970 public IRubyObject readpartial(IRubyObject[] args) { 971 if(!(handler instanceof IOHandlerNio)) { 972 throw getRuntime().newNotImplementedError("readpartial only works with Nio based handlers"); 974 } 975 try { 976 ByteList buf = ((IOHandlerNio)handler).readpartial(RubyNumeric.fix2int(args[0])); 977 IRubyObject strbuf = RubyString.newString(getRuntime(), buf == null ? new ByteList(ByteList.NULL_ARRAY) : buf); 978 if(args.length > 1) { 979 args[1].callMethod(getRuntime().getCurrentContext(),"<<", strbuf); 980 return args[1]; 981 } 982 983 return strbuf; 984 } catch (IOHandler.BadDescriptorException e) { 985 throw getRuntime().newErrnoEBADFError(); 986 } catch (EOFException e) { 987 return getRuntime().getNil(); 988 } catch (IOException e) { 989 throw getRuntime().newIOError(e.getMessage()); 990 } 991 } 992 993 public IRubyObject sysread(IRubyObject number) { 994 try { 995 ByteList buf = handler.sysread(RubyNumeric.fix2int(number)); 996 997 return RubyString.newString(getRuntime(), buf); 998 } catch (IOHandler.BadDescriptorException e) { 999 throw getRuntime().newErrnoEBADFError(); 1000 } catch (EOFException e) { 1001 throw getRuntime().newEOFError(); 1002 } catch (IOException e) { 1003 if ("File not open".equals(e.getMessage())) { 1007 throw getRuntime().newIOError(e.getMessage()); 1008 } 1009 throw getRuntime().newSystemCallError(e.getMessage()); 1010 } 1011 } 1012 1013 public IRubyObject read(IRubyObject[] args) { 1014 1015 int argCount = checkArgumentCount(args, 0, 2); 1016 RubyString callerBuffer = null; 1017 boolean readEntireStream = (argCount == 0 || args[0].isNil()); 1018 1019 try { 1020 if (atEOF && handler.isEOF()) { 1024 throw new EOFException (); 1025 } 1026 1027 if (argCount == 2) { 1028 if (!(args[1] instanceof RubyString)) { 1031 getRuntime().newTypeError(args[1], getRuntime().getString()); 1032 } 1033 callerBuffer = (RubyString) args[1]; 1034 } 1035 1036 ByteList buf = readEntireStream ? handler.getsEntireStream() : handler.read(RubyNumeric 1037 .fix2int(args[0])); 1038 1039 if (buf == null) { 1040 throw new EOFException (); 1041 } 1042 1043 atEOF = false; 1047 if (callerBuffer != null) { 1048 callerBuffer.setValue(buf); 1049 return callerBuffer; 1050 } 1051 1052 return RubyString.newString(getRuntime(), buf); 1053 1054 } catch (IOHandler.BadDescriptorException e) { 1055 throw getRuntime().newErrnoEBADFError(); 1056 } catch (EOFException e) { 1057 atEOF = true; 1061 if (callerBuffer != null) { 1062 callerBuffer.setValue(""); 1063 return readEntireStream ? callerBuffer : getRuntime().getNil(); 1064 } 1065 1066 return readEntireStream ? getRuntime().newString("") : getRuntime().getNil(); 1067 } catch (IOException e) { 1068 throw getRuntime().newIOError(e.getMessage()); 1069 } finally { 1070 if (readEntireStream) { 1072 atEOF = true; 1073 } 1074 } 1075 } 1076 1077 1080 public IRubyObject readchar() { 1081 checkReadable(); 1082 1083 try { 1084 int c = handler.getc(); 1085 1086 if (c == -1) { 1087 throw getRuntime().newEOFError(); 1088 } 1089 1090 return getRuntime().newFixnum(c); 1091 } catch (IOHandler.BadDescriptorException e) { 1092 throw getRuntime().newErrnoEBADFError(); 1093 } catch (EOFException e) { 1094 throw getRuntime().newEOFError(); 1095 } catch (IOException e) { 1096 throw getRuntime().newIOError(e.getMessage()); 1097 } 1098 } 1099 1100 1103 public IRubyObject each_byte(Block block) { 1104 try { 1105 ThreadContext context = getRuntime().getCurrentContext(); 1106 for (int c = handler.getc(); c != -1; c = handler.getc()) { 1107 assert c < 256; 1108 context.yield(getRuntime().newFixnum(c), block); 1109 } 1110 1111 return getRuntime().getNil(); 1112 } catch (IOHandler.BadDescriptorException e) { 1113 throw getRuntime().newErrnoEBADFError(); 1114 } catch (EOFException e) { 1115 return getRuntime().getNil(); 1116 } catch (IOException e) { 1117 throw getRuntime().newIOError(e.getMessage()); 1118 } 1119 } 1120 1121 1124 public RubyIO each_line(IRubyObject[] args, Block block) { 1125 ThreadContext context = getRuntime().getCurrentContext(); 1126 for (IRubyObject line = internalGets(args); !line.isNil(); 1127 line = internalGets(args)) { 1128 context.yield(line, block); 1129 } 1130 1131 return this; 1132 } 1133 1134 1135 public RubyArray readlines(IRubyObject[] args) { 1136 IRubyObject[] separatorArgument; 1137 if (args.length > 0) { 1138 if (!args[0].isKindOf(getRuntime().getNilClass()) && 1139 !args[0].isKindOf(getRuntime().getString())) { 1140 throw getRuntime().newTypeError(args[0], 1141 getRuntime().getString()); 1142 } 1143 separatorArgument = new IRubyObject[] { args[0] }; 1144 } else { 1145 separatorArgument = IRubyObject.NULL_ARRAY; 1146 } 1147 1148 RubyArray result = getRuntime().newArray(); 1149 IRubyObject line; 1150 while (! (line = internalGets(separatorArgument)).isNil()) { 1151 result.append(line); 1152 } 1153 return result; 1154 } 1155 1156 public RubyIO to_io() { 1157 return this; 1158 } 1159 1160 public String toString() { 1161 return "RubyIO(" + modes + ", " + fileno + ")"; 1162 } 1163} 1164 | Popular Tags |