KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > RubyStringIO


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2006 Ola Bini <ola@ologix.com>
15  * Copyright (C) 2006 Ryan Bell <ryan.l.bell@gmail.com>
16  *
17  * Alternatively, the contents of this file may be used under the terms of
18  * either of the GNU General Public License Version 2 or later (the "GPL"),
19  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20  * in which case the provisions of the GPL or the LGPL are applicable instead
21  * of those above. If you wish to allow use of your version of this file only
22  * under the terms of either the GPL or the LGPL, and not to allow others to
23  * use your version of this file under the terms of the CPL, indicate your
24  * decision by deleting the provisions above and replace them with the notice
25  * and other provisions required by the GPL or the LGPL. If you do not delete
26  * the provisions above, a recipient may use your version of this file under
27  * the terms of any one of the CPL, the GPL or the LGPL.
28  ***** END LICENSE BLOCK *****/

29 package org.jruby;
30
31 import java.util.ArrayList JavaDoc;
32 import java.util.List JavaDoc;
33
34 import org.jruby.runtime.Block;
35 import org.jruby.runtime.CallbackFactory;
36 import org.jruby.runtime.ObjectAllocator;
37 import org.jruby.runtime.ThreadContext;
38 import org.jruby.runtime.builtin.IRubyObject;
39
40 import org.jruby.util.IOHandler;
41 import org.jruby.util.ByteList;
42
43 public class RubyStringIO extends RubyObject {
44     private static ObjectAllocator STRINGIO_ALLOCATOR = new ObjectAllocator() {
45         public IRubyObject allocate(Ruby runtime, RubyClass klass) {
46             return new RubyStringIO(runtime, klass);
47         }
48     };
49     
50     public static RubyClass createStringIOClass(final Ruby runtime) {
51         final RubyClass stringIOClass = runtime.defineClass("StringIO", runtime.getObject(), STRINGIO_ALLOCATOR);
52         
53         final CallbackFactory callbackFactory = runtime.callbackFactory(RubyStringIO.class);
54         
55         stringIOClass.getMetaClass().defineMethod("open", callbackFactory.getOptSingletonMethod("open"));
56         stringIOClass.defineMethod("initialize", callbackFactory.getOptMethod("initialize"));
57         stringIOClass.defineFastMethod("<<", callbackFactory.getFastMethod("append",RubyKernel.IRUBY_OBJECT));
58         stringIOClass.defineFastMethod("binmode", callbackFactory.getFastMethod("binmode"));
59         stringIOClass.defineFastMethod("close", callbackFactory.getFastMethod("close"));
60         stringIOClass.defineFastMethod("closed?", callbackFactory.getFastMethod("closed_p"));
61         stringIOClass.defineFastMethod("close_read", callbackFactory.getFastMethod("close_read"));
62         stringIOClass.defineFastMethod("closed_read?", callbackFactory.getFastMethod("closed_read_p"));
63         stringIOClass.defineFastMethod("close_write", callbackFactory.getFastMethod("close_write"));
64         stringIOClass.defineFastMethod("closed_write?", callbackFactory.getFastMethod("closed_write_p"));
65         stringIOClass.defineMethod("each", callbackFactory.getOptMethod("each"));
66         stringIOClass.defineMethod("each_byte", callbackFactory.getMethod("each_byte"));
67         stringIOClass.defineMethod("each_line", callbackFactory.getMethod("each_line"));
68         stringIOClass.defineFastMethod("eof", callbackFactory.getFastMethod("eof"));
69         stringIOClass.defineFastMethod("eof?", callbackFactory.getFastMethod("eof_p"));
70         stringIOClass.defineFastMethod("fcntl", callbackFactory.getFastMethod("fcntl"));
71         stringIOClass.defineFastMethod("fileno", callbackFactory.getFastMethod("fileno"));
72         stringIOClass.defineFastMethod("flush", callbackFactory.getFastMethod("flush"));
73         stringIOClass.defineFastMethod("fsync", callbackFactory.getFastMethod("fsync"));
74         stringIOClass.defineFastMethod("getc", callbackFactory.getFastMethod("getc"));
75         stringIOClass.defineFastMethod("gets", callbackFactory.getFastOptMethod("gets"));
76         stringIOClass.defineFastMethod("isatty", callbackFactory.getFastMethod("isatty"));
77         // FIXME: this should probably be an alias?
78
stringIOClass.defineFastMethod("tty?", callbackFactory.getFastMethod("tty_p"));
79         stringIOClass.defineFastMethod("length", callbackFactory.getFastMethod("length"));
80         stringIOClass.defineFastMethod("lineno", callbackFactory.getFastMethod("lineno"));
81         stringIOClass.defineFastMethod("lineno=", callbackFactory.getFastMethod("set_lineno", RubyFixnum.class));
82         stringIOClass.defineFastMethod("path", callbackFactory.getFastMethod("path"));
83         stringIOClass.defineFastMethod("pid", callbackFactory.getFastMethod("pid"));
84         stringIOClass.defineFastMethod("pos", callbackFactory.getFastMethod("pos"));
85         // FIXME: this should probably be an alias?
86
stringIOClass.defineFastMethod("tell", callbackFactory.getFastMethod("tell"));
87         stringIOClass.defineFastMethod("pos=", callbackFactory.getFastMethod("set_pos", RubyFixnum.class));
88         stringIOClass.defineFastMethod("print", callbackFactory.getFastOptMethod("print"));
89         stringIOClass.defineFastMethod("printf", callbackFactory.getFastOptMethod("printf"));
90         stringIOClass.defineFastMethod("putc", callbackFactory.getFastMethod("putc", RubyKernel.IRUBY_OBJECT));
91         stringIOClass.defineFastMethod("puts", callbackFactory.getFastOptMethod("puts"));
92         stringIOClass.defineFastMethod("read", callbackFactory.getFastOptMethod("read"));
93         stringIOClass.defineFastMethod("readchar", callbackFactory.getFastMethod("readchar"));
94         stringIOClass.defineFastMethod("readline", callbackFactory.getFastOptMethod("readline"));
95         stringIOClass.defineFastMethod("readlines", callbackFactory.getFastOptMethod("readlines"));
96         stringIOClass.defineFastMethod("reopen", callbackFactory.getFastMethod("reopen", RubyKernel.IRUBY_OBJECT));
97         stringIOClass.defineFastMethod("rewind", callbackFactory.getFastMethod("rewind"));
98         stringIOClass.defineFastMethod("seek", callbackFactory.getFastOptMethod("seek"));
99         stringIOClass.defineFastMethod("size", callbackFactory.getFastMethod("size"));
100         stringIOClass.defineFastMethod("string", callbackFactory.getFastMethod("string"));
101         stringIOClass.defineFastMethod("string=", callbackFactory.getFastMethod("set_string",RubyString.class));
102         stringIOClass.defineFastMethod("sync", callbackFactory.getFastMethod("sync"));
103         stringIOClass.defineFastMethod("sync=", callbackFactory.getFastMethod("set_sync", RubyKernel.IRUBY_OBJECT));
104         stringIOClass.defineFastMethod("syswrite", callbackFactory.getFastMethod("syswrite", RubyKernel.IRUBY_OBJECT));
105         stringIOClass.defineFastMethod("truncate", callbackFactory.getFastMethod("truncate", RubyFixnum.class));
106         stringIOClass.defineFastMethod("ungetc", callbackFactory.getFastMethod("ungetc", RubyFixnum.class));
107         stringIOClass.defineFastMethod("write", callbackFactory.getFastMethod("write", RubyKernel.IRUBY_OBJECT));
108
109         return stringIOClass;
110     }
111
112     public static IRubyObject open(IRubyObject recv, IRubyObject[] args, Block block) {
113         RubyString str = recv.getRuntime().newString("");
114         IRubyObject mode = recv.getRuntime().getNil();
115         if (args.length > 0) {
116             str = args[0].convertToString();
117             if (args.length > 1) {
118                 mode = args[1];
119             }
120         }
121         RubyStringIO strio = (RubyStringIO)((RubyClass)recv).newInstance(new IRubyObject[]{str,mode}, Block.NULL_BLOCK);
122         IRubyObject val = strio;
123         ThreadContext tc = recv.getRuntime().getCurrentContext();
124         
125         if (block.isGiven()) {
126             try {
127                 val = tc.yield(strio, block);
128             } finally {
129                 strio.close();
130             }
131         }
132         return val;
133     }
134
135     protected RubyStringIO(Ruby runtime, RubyClass klass) {
136         super(runtime, klass);
137     }
138
139     private long pos = 0L;
140     private int lineno = 0;
141     private boolean eof = false;
142     private ByteList internal;
143     private boolean closedRead = false;
144     private boolean closedWrite = false;
145
146     public IRubyObject initialize(IRubyObject[] args, Block block) {
147         if (checkArgumentCount(args, 0, 2) > 0) {
148             // Share bytelist since stringio is acting on this passed-in string.
149
internal = args[0].convertToString().getByteList();
150         } else {
151             internal = new ByteList();
152         }
153         return this;
154     }
155
156     public IRubyObject append(IRubyObject obj) {
157         ByteList val = ((RubyString)obj.callMethod(obj.getRuntime().getCurrentContext(),"to_s")).getByteList();
158         int left = internal.length()-(int)pos;
159         internal.replace((int)pos,Math.min(val.length(),left),val);
160         pos += val.length();
161         return this;
162     }
163
164     public IRubyObject binmode() {
165         return getRuntime().getTrue();
166     }
167     
168     public IRubyObject close() {
169         closedRead = true;
170         closedWrite = true;
171         return getRuntime().getNil();
172     }
173
174     public IRubyObject closed_p() {
175         return (closedRead && closedWrite) ? getRuntime().getTrue() : getRuntime().getFalse();
176     }
177
178     public IRubyObject close_read() {
179         closedRead = true;
180         return getRuntime().getNil();
181     }
182
183     public IRubyObject closed_read_p() {
184         return closedRead ? getRuntime().getTrue() : getRuntime().getFalse();
185     }
186
187     public IRubyObject close_write() {
188         closedWrite = true;
189         return getRuntime().getNil();
190     }
191
192     public IRubyObject closed_write_p() {
193         return closedWrite ? getRuntime().getTrue() : getRuntime().getFalse();
194     }
195
196    public IRubyObject each(IRubyObject[] args, Block block) {
197        IRubyObject line = gets(args);
198        ThreadContext context = getRuntime().getCurrentContext();
199        while (!line.isNil()) {
200            context.yield(line, block);
201            line = gets(args);
202        }
203        return this;
204    }
205
206     public IRubyObject each_byte(Block block) {
207         RubyString.newString(getRuntime(),new ByteList(internal, (int)pos, internal.length())).each_byte(block);
208         return this;
209     }
210
211     public IRubyObject each_line(Block block) {
212         return each(new RubyObject[0], block);
213     }
214
215     public IRubyObject eof() {
216         return (pos >= internal.length() || eof) ? getRuntime().getTrue() : getRuntime().getFalse();
217     }
218
219     public IRubyObject eof_p() {
220         return (pos >= internal.length() || eof) ? getRuntime().getTrue() : getRuntime().getFalse();
221     }
222
223     public IRubyObject fcntl() {
224         throw getRuntime().newNotImplementedError("fcntl not implemented");
225     }
226
227     public IRubyObject fileno() {
228         return getRuntime().getNil();
229     }
230
231     public IRubyObject flush() {
232         return this;
233     }
234
235     public IRubyObject fsync() {
236         return RubyFixnum.zero(getRuntime());
237     }
238
239     public IRubyObject getc() {
240         return getRuntime().newFixnum( internal.get((int)pos++) & 0xFF);
241     }
242
243     public IRubyObject internalGets(IRubyObject[] args) {
244         if (pos < internal.length() && !eof) {
245             String JavaDoc sep = ((RubyString)getRuntime().getGlobalVariables().get("$/")).getValue().toString();
246             if (args.length>0) {
247                 if (args[0].isNil()) {
248                     ByteList buf = new ByteList(internal, (int)pos, internal.length()-(int)pos);
249                     pos+=buf.length();
250                     return RubyString.newString(getRuntime(),buf);
251                 }
252                 sep = args[0].toString();
253             }
254             String JavaDoc ss = RubyString.byteListToString(internal);
255             int ix = ss.indexOf(sep,(int)pos);
256             String JavaDoc add = sep;
257             if (-1 == ix) {
258                 ix = internal.length();
259                 add = "";
260             }
261             ByteList line = new ByteList(internal, (int)pos, ix-(int)pos);
262             line.append(RubyString.stringToBytes(add));
263             pos = ix + add.length();
264             lineno++;
265             return RubyString.newString(getRuntime(),line);
266         }
267         return getRuntime().getNil();
268     }
269
270     public IRubyObject gets(IRubyObject[] args) {
271         IRubyObject result = internalGets(args);
272         if (!result.isNil()) {
273             getRuntime().getCurrentContext().setLastline(result);
274         }
275         return result;
276     }
277
278     public IRubyObject isatty() {
279         return getRuntime().getNil();
280     }
281
282     public IRubyObject tty_p() {
283         return getRuntime().getNil();
284     }
285
286     public IRubyObject length() {
287         return getRuntime().newFixnum(internal.length());
288     }
289
290     public IRubyObject lineno() {
291         return getRuntime().newFixnum(lineno);
292     }
293
294     public IRubyObject set_lineno(RubyFixnum val) {
295         lineno = (int)val.getLongValue();
296         return getRuntime().getNil();
297     }
298
299     public IRubyObject path() {
300         return getRuntime().getNil();
301     }
302
303     public IRubyObject pid() {
304         return getRuntime().getNil();
305     }
306
307     public IRubyObject pos() {
308         return getRuntime().newFixnum(pos);
309     }
310
311     public IRubyObject tell() {
312         return getRuntime().newFixnum(pos);
313     }
314
315     public IRubyObject set_pos(RubyFixnum val) {
316         pos = (int)val.getLongValue();
317         return getRuntime().getNil();
318     }
319
320     public IRubyObject print(IRubyObject[] args) {
321         if (args.length != 0) {
322             for (int i=0,j=args.length;i<j;i++) {
323                 append(args[i]);
324             }
325         }
326         IRubyObject sep = getRuntime().getGlobalVariables().get("$\\");
327         if (!sep.isNil()) {
328             append(sep);
329         }
330         return getRuntime().getNil();
331     }
332     
333     public IRubyObject printf(IRubyObject[] args) {
334         append(RubyKernel.sprintf(this,args));
335         return getRuntime().getNil();
336     }
337
338     public IRubyObject putc(IRubyObject obj) {
339         append(obj);
340         return obj;
341     }
342
343     private static final ByteList NEWLINE_BL = new ByteList(new byte[]{10},false);
344
345     public IRubyObject puts(IRubyObject[] obj) {
346         if (obj.length == 0) {
347             append(RubyString.newString(getRuntime(),NEWLINE_BL));
348         }
349         
350         for (int i=0,j=obj.length;i<j;i++) {
351             append(obj[i]);
352             internal.unsafeReplace((int)(pos++),0,NEWLINE_BL);
353         }
354         return getRuntime().getNil();
355     }
356
357     public IRubyObject read(IRubyObject[] args) {
358         ByteList buf = null;
359         if (!(pos >= internal.length() || eof)) {
360             if (args.length > 0 && !args[0].isNil()) {
361                 int len = RubyNumeric.fix2int(args[0]);
362                 int end = ((int)pos) + len;
363                 if (end > internal.length()) {
364                     buf = new ByteList(internal,(int)pos,internal.length()-(int)pos);
365                 } else {
366                     buf = new ByteList(internal,(int)pos,len);
367                 }
368             } else {
369                 buf = new ByteList(internal,(int)pos,internal.length()-(int)pos);
370             }
371             pos+= buf.length();
372         }
373         IRubyObject ret = null;
374         if (buf == null) {
375             if (args.length > 0) {
376                 return getRuntime().getNil();
377             }
378             return getRuntime().newString("");
379         } else {
380             if (args.length>1) {
381                 ret = args[1].convertToString();
382                                 ((RubyString)ret).setValue(buf);
383             } else {
384                 ret = RubyString.newString(getRuntime(),buf);
385             }
386         }
387
388         return ret;
389     }
390
391     public IRubyObject readchar() {
392         return getc();
393     }
394
395     public IRubyObject readline(IRubyObject[] args) {
396         return gets(args);
397     }
398     
399     public IRubyObject readlines(IRubyObject[] arg) {
400         List JavaDoc lns = new ArrayList JavaDoc();
401         while (!(pos >= internal.length() || eof)) {
402             lns.add(gets(arg));
403         }
404         return getRuntime().newArray(lns);
405     }
406     
407     public IRubyObject reopen(IRubyObject str) {
408         if (str instanceof RubyStringIO) {
409             pos = ((RubyStringIO)str).pos;
410             lineno = ((RubyStringIO)str).lineno;
411             eof = ((RubyStringIO)str).eof;
412             closedRead = ((RubyStringIO)str).closedRead;
413             closedWrite = ((RubyStringIO)str).closedWrite;
414             internal = new ByteList(((RubyStringIO)str).internal);
415         } else {
416             pos = 0L;
417             lineno = 0;
418             eof = false;
419             closedRead = false;
420             closedWrite = false;
421             internal = new ByteList();
422             internal.append(str.convertToString().getByteList());
423         }
424         return this;
425     }
426
427     public IRubyObject rewind() {
428         this.pos = 0L;
429         this.lineno = 0;
430         return RubyFixnum.zero(getRuntime());
431     }
432
433     public IRubyObject seek(IRubyObject[] args) {
434         long amount = ((RubyNumeric)args[0]).getLongValue();
435         int whence = IOHandler.SEEK_SET;
436         if (args.length > 1) {
437             whence = (int)(((RubyNumeric)args[1]).getLongValue());
438         }
439         if (whence == IOHandler.SEEK_CUR) {
440             pos += amount;
441         } else if (whence == IOHandler.SEEK_END) {
442             pos = internal.length() + amount;
443         } else {
444             pos = amount;
445         }
446         return RubyFixnum.zero(getRuntime());
447     }
448
449     public IRubyObject size() {
450         return getRuntime().newFixnum(internal.length());
451     }
452
453     public IRubyObject string() {
454         return RubyString.newString(getRuntime(),internal);
455     }
456
457     public IRubyObject set_string(RubyString arg) {
458         return reopen(arg);
459     }
460
461     public IRubyObject sync() {
462         return getRuntime().getTrue();
463     }
464
465     public IRubyObject set_sync(IRubyObject args) {
466         return args;
467     }
468
469     public IRubyObject syswrite(IRubyObject args) {
470         return write(args);
471     }
472
473     public IRubyObject truncate(RubyFixnum args) {
474         int len = (int) args.getLongValue();
475         internal.length(len);
476         return RubyFixnum.zero(getRuntime());
477     }
478
479     public IRubyObject ungetc(RubyFixnum args) {
480         internal.insert((int)pos,(int)args.getLongValue());
481         return getRuntime().getNil();
482     }
483
484     public IRubyObject write(IRubyObject args) {
485         String JavaDoc obj = args.toString();
486         append(args);
487         return getRuntime().newFixnum(obj.length());
488     }
489 }
490
Popular Tags